Browse Source

alsa midi support

master
nebogeo 22 years ago
parent
commit
79ca7be009
8 changed files with 162 additions and 101 deletions
  1. +135
    -88
      SpiralSound/Midi.C
  2. +16
    -10
      SpiralSound/Midi.h
  3. +1
    -1
      SpiralSound/PluginManager.C
  4. +1
    -0
      SpiralSound/Plugins/LADSPAPlugin/LADSPAInfo.C
  5. +1
    -1
      SpiralSound/Plugins/MidiPlugin/Makefile.in
  6. +5
    -0
      SpiralSound/Plugins/MidiPlugin/MidiPlugin.C
  7. +1
    -0
      SpiralSound/SpiralInfo.C
  8. +2
    -1
      main.cpp

+ 135
- 88
SpiralSound/Midi.C View File

@@ -17,7 +17,6 @@
*/

#include "Midi.h"
#include "NoteTable.h"
#include "unistd.h"
#include "sys/types.h"
#include "signal.h"
@@ -44,31 +43,27 @@ static int NKEYS = 30;
MidiDevice *MidiDevice::m_Singleton;
string MidiDevice::m_DeviceName;
string MidiDevice::m_AppName;

#if __APPLE__
#define read AppleRead
#endif

MidiDevice::MidiDevice() :
void MidiDevice::Init(const string &name, Type t)
{
if (!m_Singleton)
{
m_AppName=name;
m_Singleton=new MidiDevice(t);
}
}
MidiDevice::MidiDevice(Type t) :
m_Poly(1),
m_Clock(1.0f),
m_ClockCount(0)
{
#ifdef ALSA_MIDI
seq_handle=AlsaOpen();
#else
Open();
#endif

#ifdef KEYBOARD_SUPPORT
m_Oct=4;
m_CurrentVoice=0;
for (int n=0; n<256; n++)
{
m_KeyVoice[n]=' ';
}
#endif
Open(t);
}

MidiDevice::~MidiDevice()
@@ -97,10 +92,13 @@ void MidiDevice::Close()
}


void MidiDevice::Open()
void MidiDevice::Open(Type t)
{
#if __APPLE__
AppleOpen();
#else
#ifdef ALSA_MIDI
seq_handle=AlsaOpen(t);
#else
//if (!SpiralInfo::WANTMIDI) return;
@@ -119,11 +117,16 @@ void MidiDevice::Open()
}
cerr<<"Opened midi device ["<<m_DeviceName<<"]"<<endl;
#endif
#endif // !__APPLE__
m_Mutex = new pthread_mutex_t;
pthread_mutex_init(m_Mutex, NULL);
int ret=pthread_create(&m_MidiReader,NULL,(void*(*)(void*))MidiDevice::MidiReaderCallback,(void*)this);
#ifdef ALSA_MIDI
pthread_create(&m_MidiReader,NULL,(void*(*)(void*))MidiDevice::AlsaMidiReaderCallback,(void*)this);
#else
pthread_create(&m_MidiReader,NULL,(void*(*)(void*))MidiDevice::MidiReaderCallback,(void*)this);
#endif
}


@@ -137,18 +140,6 @@ MidiEvent MidiDevice::GetEvent(int Device)
return MidiEvent(MidiEvent::NONE,0,0);
}

#ifdef ALSA_MIDI
AlsaCallback();
if (m_EventVec[Device].size()==0)
{
return MidiEvent(MidiEvent::NONE,0,0);
}
MidiEvent event(m_EventVec[Device].front());
m_EventVec[Device].pop();
#else

pthread_mutex_lock(m_Mutex);
if (m_EventVec[Device].size()==0)
{
@@ -159,13 +150,32 @@ MidiEvent MidiDevice::GetEvent(int Device)
MidiEvent event(m_EventVec[Device].front());
m_EventVec[Device].pop();
pthread_mutex_unlock(m_Mutex);
#endif
return event;
}

void MidiDevice::SendEvent(int Device,const MidiEvent &Event)
{
#ifndef ALSA_MIDI
#ifdef 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;
case MidiEvent::OFF : ev.type = SND_SEQ_EVENT_NOTEOFF;
}
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);
#else
if (Device<0 || Device>15)
{
cerr<<"SendEvent: Invalid Midi device "<<Device<<endl;
@@ -358,67 +368,104 @@ void MidiDevice::AddEvent(unsigned char* midi)
#ifdef ALSA_MIDI
// code taken and modified from jack_miniFMsynth

int MidiDevice::AlsaCallback()
void MidiDevice::AlsaCollectEvents()
{
snd_seq_event_t *ev;
int l1;
MidiEvent::type MessageType=MidiEvent::NONE;
int Volume=0,Note=0,EventDevice=0;

do {
snd_seq_event_input(seq_handle, &ev);
if ((ev->type == SND_SEQ_EVENT_NOTEON) && (ev->data.note.velocity == 0))
{
ev->type = SND_SEQ_EVENT_NOTEOFF;
int seq_nfds, l1;
struct pollfd *pfds;
seq_nfds = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
pfds = (struct pollfd *)alloca(sizeof(struct pollfd) * seq_nfds);
snd_seq_poll_descriptors(seq_handle, pfds, seq_nfds, POLLIN);
for(;;)
{
cerr<<"poll"<<endl;
if (poll (pfds, seq_nfds, 1000) > 0)
{
for (l1 = 0; l1 < seq_nfds; l1++)
{
if (pfds[l1].revents > 0)
{
snd_seq_event_t *ev;
int l1;
MidiEvent::type MessageType=MidiEvent::NONE;
int Volume=0,Note=0,EventDevice=0;
cerr<<"found an event!"<<endl;
do
{
snd_seq_event_input(seq_handle, &ev);

if ((ev->type == SND_SEQ_EVENT_NOTEON) && (ev->data.note.velocity == 0))
{
ev->type = SND_SEQ_EVENT_NOTEOFF;
}

switch (ev->type) {
case SND_SEQ_EVENT_PITCHBEND:
MessageType=MidiEvent::CHANNELPRESSURE;
Volume = (char)((ev->data.control.value / 8192.0)*256);
break;
case SND_SEQ_EVENT_CONTROLLER:
MessageType=MidiEvent::PARAMETER;
Note = ev->data.control.param;
Volume = ev->data.control.value;
break;
case SND_SEQ_EVENT_NOTEON:
MessageType=MidiEvent::ON;
EventDevice = ev->data.control.channel;
Note = ev->data.note.note;
Volume = ev->data.note.velocity;
break;
case SND_SEQ_EVENT_NOTEOFF:
MessageType=MidiEvent::ON;
EventDevice = ev->data.control.channel;
Note = ev->data.note.note;
break;
}
pthread_mutex_lock(m_Mutex);
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);
}
}
}
switch (ev->type) {
case SND_SEQ_EVENT_PITCHBEND:
MessageType=MidiEvent::CHANNELPRESSURE;
Volume = (char)((ev->data.control.value / 8192.0)*256);
break;
case SND_SEQ_EVENT_CONTROLLER:
MessageType=MidiEvent::PARAMETER;
Note = ev->data.control.param;
Volume = ev->data.control.value;
break;
case SND_SEQ_EVENT_NOTEON:
MessageType=MidiEvent::ON;
EventDevice = ev->data.control.channel;
Note = ev->data.note.note;
Volume = ev->data.note.velocity;
break;
case SND_SEQ_EVENT_NOTEOFF:
MessageType=MidiEvent::ON;
EventDevice = ev->data.control.channel;
Note = ev->data.note.note;
break;
}
m_EventVec[EventDevice].push(MidiEvent(MessageType,Note,Volume));
snd_seq_free_event(ev);
} while (snd_seq_event_input_pending(seq_handle, 0) > 0);
return (0);
}
}

snd_seq_t *MidiDevice::AlsaOpen()
snd_seq_t *MidiDevice::AlsaOpen(Type t)
{
snd_seq_t *seq_handle;
int client_id, port_id;
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, "spiralmodular");
client_id = snd_seq_client_id(seq_handle);
if ((port_id = snd_seq_create_simple_port(seq_handle, "spiralmodular",
SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
SND_SEQ_PORT_TYPE_APPLICATION) < 0)) {
fprintf(stderr, "Error creating sequencer port.\n");
}
if (t==WRITE)
{
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");
}
}
else
{
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");
}
}
return(seq_handle);
}



+ 16
- 10
SpiralSound/Midi.h View File

@@ -30,7 +30,7 @@

using namespace std;

//#define ALSA_MIDI
#define ALSA_MIDI

#ifdef ALSA_MIDI
#include <alsa/asoundlib.h>
@@ -63,28 +63,31 @@ class MidiDevice
public:
~MidiDevice();

enum Type{READ,WRITE};

static void Init(const string &name, Type t);
static void SetDeviceName(string s) { m_DeviceName=s; }
static MidiDevice *Get() { if(!m_Singleton) m_Singleton=new MidiDevice; return m_Singleton; }
static MidiDevice *Get() { return m_Singleton; }
static void PackUpAndGoHome() { if(m_Singleton) delete m_Singleton; m_Singleton=NULL; }

static void *MidiReaderCallback(void *o) { ((MidiDevice*)o)->CollectEvents(); return NULL; }

MidiEvent GetEvent(int Device);
void SendEvent(int Device,const MidiEvent &Event);

void SetPoly(int s) { m_Poly=s; }

float GetClock() { return m_Clock; }
private:
MidiDevice();
MidiDevice(Type t);

void Open();
void Open(Type t);
void Close();
void CollectEvents();
void AddEvent(unsigned char* midi);

void ReadByte(unsigned char *c);
static void *MidiReaderCallback(void *o) { ((MidiDevice*)o)->CollectEvents(); return NULL; }

int m_MidiFd;
int m_MidiWrFd;
@@ -98,12 +101,15 @@ private:
static MidiDevice *m_Singleton;

pthread_t m_MidiReader;
pthread_mutex_t* m_Mutex;
pthread_mutex_t* m_Mutex;
static string m_AppName;
#ifdef ALSA_MIDI
int AlsaCallback();
static void *AlsaMidiReaderCallback(void *o) { ((MidiDevice*)o)->AlsaCollectEvents(); return NULL; }
void AlsaCollectEvents();
snd_seq_t *seq_handle;
snd_seq_t *AlsaOpen();
snd_seq_t *AlsaOpen(Type t);
#endif

#if __APPLE__


+ 1
- 1
SpiralSound/PluginManager.C View File

@@ -44,7 +44,7 @@ PluginID PluginManager::LoadPlugin(const char *PluginName)
if (NewPlugin->Handle==NULL)
{
SpiralInfo::Alert("Error loading plugin: \n"+string(dlerror()));
SpiralInfo::Alert("Error loading ["+string(PluginName)+"]: \n"+string(dlerror()));
return PluginError;
}


+ 1
- 0
SpiralSound/Plugins/LADSPAPlugin/LADSPAInfo.C View File

@@ -27,6 +27,7 @@
#include <iostream>
#include <sstream>
#include <algorithm>
#include <stdio.h>

#include <cstdlib>
#include <sys/types.h>


+ 1
- 1
SpiralSound/Plugins/MidiPlugin/Makefile.in View File

@@ -11,7 +11,7 @@ CXXFLAGS= @CXXFLAGS@
INCPATH = -I/usr/X11R6/include
LINK = g++ -shared
LFLAGS =
LIBS = -L/usr/X11R6/lib @FLTK_LIBS@ -lGL -lXext -lX11 -ldl -pthread
LIBS = -L/usr/X11R6/lib @FLTK_LIBS@ -lGL -lXext -lX11 -ldl -pthread -lasound
MOC = moc
UIC =



+ 5
- 0
SpiralSound/Plugins/MidiPlugin/MidiPlugin.C View File

@@ -62,6 +62,11 @@ m_CurrentNote(0)
{
m_Version=2;
if (m_RefCount==0)
{
MidiDevice::Init("SpiralModular",MidiDevice::READ);
}
m_RefCount++;

m_PluginInfo.Name="Midi";


+ 1
- 0
SpiralSound/SpiralInfo.C View File

@@ -139,6 +139,7 @@ void SpiralInfo::StreamInPrefs (istream &s) {
if (st!="end") PLUGINVEC.push_back (st);
}
}
#if __APPLE__
// ignore custom paths, plugins are encapsulated in the app anyway
// this prevents the program to fail if the user move the application icon


+ 2
- 1
main.cpp View File

@@ -174,9 +174,10 @@ int main(int argc, char **argv)
Fl::visual(FL_DOUBLE|FL_RGB);
synth=new SynthModular;
// setup the synth
Fl_Window* win = synth->CreateWindow();
synth->LoadPlugins(cmd_pluginPath);
win->xclass("");
if (GUI) win->show(1, argv); // prevents stuff happening before the plugins have loaded


Loading…
Cancel
Save