diff --git a/SpiralSound/Midi.C b/SpiralSound/Midi.C index 9af2a24..dbd9674 100644 --- a/SpiralSound/Midi.C +++ b/SpiralSound/Midi.C @@ -70,7 +70,7 @@ m_ClockCount (0) AppleOpen(); #endif #ifdef USE_ALSA_MIDI - seq_handle=AlsaOpen(t); + AlsaOpen(); #endif #ifdef USE_OSS_MIDI if (!OssOpen()) return; @@ -122,30 +122,7 @@ MidiEvent MidiDevice::GetEvent(int Device) void MidiDevice::SendEvent (int Device, const MidiEvent &Event) { #ifdef USE_ALSA_MIDI - snd_seq_event_t ev; - snd_seq_ev_clear (&ev); - snd_seq_ev_set_direct (&ev); - snd_seq_ev_set_subs (&ev); - snd_seq_ev_set_source (&ev, 0); - - switch (Event.GetType()) - { - case MidiEvent::ON: - ev.type = SND_SEQ_EVENT_NOTEON; - break; - case MidiEvent::OFF: - ev.type = SND_SEQ_EVENT_NOTEOFF; - break; - default: - break; - } - - ev.data.note.velocity = (char)Event.GetVolume()*127; - ev.data.control.channel = Device; - ev.data.note.note=Event.GetNote(); - - int ret=snd_seq_event_output(seq_handle, &ev); - snd_seq_drain_output(seq_handle); + AlsaSendEvent (Device, Event); #else if (Device<0 || Device>15) { @@ -367,17 +344,28 @@ void MidiDevice::OssAddEvent(unsigned char* midi) // code taken and modified from jack_miniFMsynth void MidiDevice::AlsaClose () { - snd_seq_close (seq_handle); + + //Alsa requires two handles - one for read and one for write, + //so we make sure too close both here + + snd_seq_close (seq_rhandle); + snd_seq_close (seq_whandle); } void MidiDevice::AlsaCollectEvents () { + //As Alsa only supports a read or write, we use the read handle here to poll our input + //for MIDI events + int seq_nfds, l1; struct pollfd *pfds; - seq_nfds = snd_seq_poll_descriptors_count(seq_handle, POLLIN); - // Andy Preston - // pfds = (struct pollfd *)alloca (sizeof(struct pollfd) * seq_nfds); + + //get descriptors count to find out how many events are + //waiting to be processed + seq_nfds = snd_seq_poll_descriptors_count(seq_rhandle, POLLIN); + + //poll the descriptors to be proccessed and loop through them pfds = new struct pollfd[seq_nfds]; - snd_seq_poll_descriptors(seq_handle, pfds, seq_nfds, POLLIN); + snd_seq_poll_descriptors(seq_rhandle, pfds, seq_nfds, POLLIN); for (;;) { if (poll (pfds, seq_nfds, 1000) > 0) { for (l1 = 0; l1 < seq_nfds; l1++) { @@ -388,7 +376,7 @@ void MidiDevice::AlsaCollectEvents () { MidiEvent::type MessageType=MidiEvent::NONE; int Volume=0, Note=0, EventDevice=0; do { - snd_seq_event_input (seq_handle, &ev); + snd_seq_event_input (seq_rhandle, &ev); if ((ev->type == SND_SEQ_EVENT_NOTEON) && (ev->data.note.velocity == 0)) { ev->type = SND_SEQ_EVENT_NOTEOFF; } @@ -419,7 +407,7 @@ void MidiDevice::AlsaCollectEvents () { m_EventVec[EventDevice].push (MidiEvent (MessageType, Note, Volume)); pthread_mutex_unlock (m_Mutex); snd_seq_free_event (ev); - } while (snd_seq_event_input_pending(seq_handle, 0) > 0); + } while (snd_seq_event_input_pending(seq_rhandle, 0) > 0); } } } @@ -427,40 +415,91 @@ void MidiDevice::AlsaCollectEvents () { delete [] pfds; } -snd_seq_t *MidiDevice::AlsaOpen(Type t) +void MidiDevice::AlsaSendEvent (int Device, const MidiEvent &Event) { + //As Alsa only supports a read or write, we use the write handle here to send + //our MIDI events + + snd_seq_event_t ev; + + snd_seq_ev_clear (&ev); + snd_seq_ev_set_direct (&ev); + snd_seq_ev_set_subs (&ev); + snd_seq_ev_set_source (&ev, 0); + + switch (Event.GetType()) + { + case MidiEvent::ON: + ev.type = SND_SEQ_EVENT_NOTEON; + break; + case MidiEvent::OFF: + ev.type = SND_SEQ_EVENT_NOTEOFF; + break; +/* case MidiEvent::PARAMETER: + ev.type = SND_SEQ_EVENT_CONTROLLER; + ev.data.control.param = Event.GetNote(); + ev.data.control.value = + break; + case MidiEvent::PITCHBEND: + ev.type = SND_SEQ_EVENT_PITCHBEND; + ev.data.control.param = Event.GetNote(); + ev.data.control.value = + break;*/ + default: + break; + } + + ev.data.note.velocity = (char)Event.GetVolume()*127; + ev.data.control.channel = Device; + ev.data.note.note=Event.GetNote(); + + snd_seq_event_output(seq_whandle, &ev); + snd_seq_drain_output(seq_whandle); +} + +void MidiDevice::AlsaOpen() { - snd_seq_t *seq_handle; - int client_id, port_id; + int client_id, port_id; + + //Alsa apears to require two handles, one for read and one for write + //so we try to open one first for input and then one for output + + //open input handle + if (snd_seq_open(&seq_rhandle, "default", SND_SEQ_OPEN_INPUT, 0) < 0) + { + fprintf(stderr, "Error opening ALSA input sequencer.\n"); + exit(1); + } + + //setup our input name as seen by other apps, and get corresponding client id + snd_seq_set_client_name(seq_rhandle, m_AppName.c_str()); + client_id = snd_seq_client_id(seq_rhandle); - if (t==WRITE) + //try and create our actual input port capable of being written to by MIDI outputs + if ((port_id = snd_seq_create_simple_port(seq_rhandle, m_AppName.c_str(), + SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, + SND_SEQ_PORT_TYPE_APPLICATION) < 0)) { - if (snd_seq_open(&seq_handle, "default", SND_SEQ_OPEN_OUTPUT, 0) < 0) { - fprintf(stderr, "Error opening ALSA sequencer.\n"); - exit(1); - } - snd_seq_set_client_name(seq_handle, m_AppName.c_str()); - client_id = snd_seq_client_id(seq_handle); - if ((port_id = snd_seq_create_simple_port(seq_handle, m_AppName.c_str(), - SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, - SND_SEQ_PORT_TYPE_APPLICATION) < 0)) { - fprintf(stderr, "Error creating sequencer port.\n"); - } + fprintf(stderr, "Error creating input sequencer port.\n"); } - else + + //open output handle + if (snd_seq_open(&seq_whandle, "default", SND_SEQ_OPEN_OUTPUT, 0) < 0) + { + fprintf(stderr, "Error opening ALSA ouput sequencer.\n"); + exit(1); + } + + //setup our output name as seen by other apps, and get corresponding client id + snd_seq_set_client_name(seq_whandle, m_AppName.c_str()); + client_id = snd_seq_client_id(seq_whandle); + + //try and create our actual output port capable of being read from by MIDI inputs + if ((port_id = snd_seq_create_simple_port(seq_whandle, m_AppName.c_str(), + SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, + SND_SEQ_PORT_TYPE_APPLICATION) < 0)) { - if (snd_seq_open(&seq_handle, "default", SND_SEQ_OPEN_INPUT, 0) < 0) { - fprintf(stderr, "Error opening ALSA sequencer.\n"); - exit(1); - } - snd_seq_set_client_name(seq_handle, m_AppName.c_str()); - client_id = snd_seq_client_id(seq_handle); - if ((port_id = snd_seq_create_simple_port(seq_handle, m_AppName.c_str(), - SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, - SND_SEQ_PORT_TYPE_APPLICATION) < 0)) { - fprintf(stderr, "Error creating sequencer port.\n"); - } + fprintf(stderr, "Error creating output sequencer port.\n"); } - return(seq_handle); } #endif diff --git a/SpiralSound/Midi.h b/SpiralSound/Midi.h index d3ed2e9..89b652a 100644 --- a/SpiralSound/Midi.h +++ b/SpiralSound/Midi.h @@ -98,9 +98,18 @@ private: #ifdef USE_ALSA_MIDI static void *MidiReaderCallback (void *o) { ((MidiDevice*)o)->AlsaCollectEvents(); return NULL; } void AlsaCollectEvents(); + void AlsaSendEvent(int Device, const MidiEvent &Event); + void AlsaClose (); - snd_seq_t *seq_handle; - snd_seq_t *AlsaOpen(Type t); + + //snd_seq_t *seq_handle; + + //I appears that ALsa does not support both a read and write handle + //so we must have two handle one for each mode + snd_seq_t *seq_rhandle; + snd_seq_t *seq_whandle; + + void AlsaOpen(); #endif #ifdef USE_OSS_MIDI static void *MidiReaderCallback (void *o) { ((MidiDevice*)o)->OssCollectEvents(); return NULL; } diff --git a/SpiralSound/Plugins/MidiPlugin/MidiPluginGUI.C b/SpiralSound/Plugins/MidiPlugin/MidiPluginGUI.C index 2f78eed..4ea7c7b 100644 --- a/SpiralSound/Plugins/MidiPlugin/MidiPluginGUI.C +++ b/SpiralSound/Plugins/MidiPlugin/MidiPluginGUI.C @@ -80,7 +80,7 @@ SpiralPluginGUI(w,h,o,ch) m_DeviceNum->box (FL_PLASTIC_UP_BOX); m_DeviceNum->color (Info->GUI_COLOUR); m_DeviceNum->step(1); - m_DeviceNum->value(1); + m_DeviceNum->value(0); m_DeviceNum->callback((Fl_Callback*)cb_DeviceNum, NULL); m_NoteCut = new Fl_Button (0, 52, 80, 20, "Note Cut"); @@ -123,10 +123,10 @@ void MidiPluginGUI::UpdateValues(SpiralPlugin *o) //// Callbacks //// inline void MidiPluginGUI::cb_DeviceNum_i(Fl_Counter* o, void* v) { - if (o->value()<1) o->value(1); - if (o->value()>128) o->value(128); + if (o->value()<0) o->value(0); + if (o->value()>127) o->value(127); - m_GUICH->Set("DeviceNum",(int)o->value()-1); + m_GUICH->Set("DeviceNum",(int)o->value()); } void MidiPluginGUI::cb_DeviceNum(Fl_Counter* o, void* v) { ((MidiPluginGUI*)(o->parent()))->cb_DeviceNum_i(o,v);}