Browse Source

add read/write handles for ALSA midi so MIDI plugin can control,

and change MIDI gui device range to 0 - 127
master
aj_genius 21 years ago
parent
commit
c4c867f05c
3 changed files with 114 additions and 66 deletions
  1. +99
    -60
      SpiralSound/Midi.C
  2. +11
    -2
      SpiralSound/Midi.h
  3. +4
    -4
      SpiralSound/Plugins/MidiPlugin/MidiPluginGUI.C

+ 99
- 60
SpiralSound/Midi.C View File

@@ -70,7 +70,7 @@ m_ClockCount (0)
AppleOpen(); AppleOpen();
#endif #endif
#ifdef USE_ALSA_MIDI #ifdef USE_ALSA_MIDI
seq_handle=AlsaOpen(t);
AlsaOpen();
#endif #endif
#ifdef USE_OSS_MIDI #ifdef USE_OSS_MIDI
if (!OssOpen()) return; if (!OssOpen()) return;
@@ -122,30 +122,7 @@ MidiEvent MidiDevice::GetEvent(int Device)


void MidiDevice::SendEvent (int Device, const MidiEvent &Event) { void MidiDevice::SendEvent (int Device, const MidiEvent &Event) {
#ifdef USE_ALSA_MIDI #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 #else
if (Device<0 || Device>15) if (Device<0 || Device>15)
{ {
@@ -367,17 +344,28 @@ void MidiDevice::OssAddEvent(unsigned char* midi)
// code taken and modified from jack_miniFMsynth // code taken and modified from jack_miniFMsynth


void MidiDevice::AlsaClose () { 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 () { 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; int seq_nfds, l1;
struct pollfd *pfds; 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]; 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 (;;) { for (;;) {
if (poll (pfds, seq_nfds, 1000) > 0) { if (poll (pfds, seq_nfds, 1000) > 0) {
for (l1 = 0; l1 < seq_nfds; l1++) { for (l1 = 0; l1 < seq_nfds; l1++) {
@@ -388,7 +376,7 @@ void MidiDevice::AlsaCollectEvents () {
MidiEvent::type MessageType=MidiEvent::NONE; MidiEvent::type MessageType=MidiEvent::NONE;
int Volume=0, Note=0, EventDevice=0; int Volume=0, Note=0, EventDevice=0;
do { 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)) { if ((ev->type == SND_SEQ_EVENT_NOTEON) && (ev->data.note.velocity == 0)) {
ev->type = SND_SEQ_EVENT_NOTEOFF; ev->type = SND_SEQ_EVENT_NOTEOFF;
} }
@@ -419,7 +407,7 @@ void MidiDevice::AlsaCollectEvents () {
m_EventVec[EventDevice].push (MidiEvent (MessageType, Note, Volume)); m_EventVec[EventDevice].push (MidiEvent (MessageType, Note, Volume));
pthread_mutex_unlock (m_Mutex); pthread_mutex_unlock (m_Mutex);
snd_seq_free_event (ev); 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; 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 #endif


+ 11
- 2
SpiralSound/Midi.h View File

@@ -98,9 +98,18 @@ private:
#ifdef USE_ALSA_MIDI #ifdef USE_ALSA_MIDI
static void *MidiReaderCallback (void *o) { ((MidiDevice*)o)->AlsaCollectEvents(); return NULL; } static void *MidiReaderCallback (void *o) { ((MidiDevice*)o)->AlsaCollectEvents(); return NULL; }
void AlsaCollectEvents(); void AlsaCollectEvents();
void AlsaSendEvent(int Device, const MidiEvent &Event);

void AlsaClose (); 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 #endif
#ifdef USE_OSS_MIDI #ifdef USE_OSS_MIDI
static void *MidiReaderCallback (void *o) { ((MidiDevice*)o)->OssCollectEvents(); return NULL; } static void *MidiReaderCallback (void *o) { ((MidiDevice*)o)->OssCollectEvents(); return NULL; }


+ 4
- 4
SpiralSound/Plugins/MidiPlugin/MidiPluginGUI.C View File

@@ -80,7 +80,7 @@ SpiralPluginGUI(w,h,o,ch)
m_DeviceNum->box (FL_PLASTIC_UP_BOX); m_DeviceNum->box (FL_PLASTIC_UP_BOX);
m_DeviceNum->color (Info->GUI_COLOUR); m_DeviceNum->color (Info->GUI_COLOUR);
m_DeviceNum->step(1); m_DeviceNum->step(1);
m_DeviceNum->value(1);
m_DeviceNum->value(0);
m_DeviceNum->callback((Fl_Callback*)cb_DeviceNum, NULL); m_DeviceNum->callback((Fl_Callback*)cb_DeviceNum, NULL);


m_NoteCut = new Fl_Button (0, 52, 80, 20, "Note Cut"); m_NoteCut = new Fl_Button (0, 52, 80, 20, "Note Cut");
@@ -123,10 +123,10 @@ void MidiPluginGUI::UpdateValues(SpiralPlugin *o)
//// Callbacks //// //// Callbacks ////
inline void MidiPluginGUI::cb_DeviceNum_i(Fl_Counter* o, void* v) 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) void MidiPluginGUI::cb_DeviceNum(Fl_Counter* o, void* v)
{ ((MidiPluginGUI*)(o->parent()))->cb_DeviceNum_i(o,v);} { ((MidiPluginGUI*)(o->parent()))->cb_DeviceNum_i(o,v);}


Loading…
Cancel
Save