1
//=========================================================
4
// $Id: mess.cpp,v 1.6 2002/02/27 08:48:09 muse Exp $
5
// (C) Copyright 2001 Werner Schweer (ws@seh.de)
6
//=========================================================
23
//---------------------------------------------------------
25
// Restore the effective UID to its original value.
26
//---------------------------------------------------------
28
static void doSetuid(uid_t euid, uid_t ruid)
32
#ifdef _POSIX_SAVED_IDS
33
status = seteuid (euid);
35
status = setreuid (ruid, euid);
38
fprintf(stderr, "Couldn't set uid.\n");
42
//---------------------------------------------------------
44
// Set the effective UID to the real UID.
45
//---------------------------------------------------------
47
static void undoSetuid(uid_t euid, uid_t ruid)
51
#ifdef _POSIX_SAVED_IDS
52
status = seteuid (ruid);
54
status = setreuid (euid, ruid);
57
fprintf (stderr, "Couldn't set uid.\n");
62
//---------------------------------------------------------
64
//---------------------------------------------------------
66
static double curTime()
70
gettimeofday(&t, &tz);
71
return (double)((double)t.tv_sec + (t.tv_usec / 1000000.0));
74
//---------------------------------------------------------
76
//---------------------------------------------------------
78
static void* midi_run(void* d)
86
//---------------------------------------------------------
88
//---------------------------------------------------------
90
void getCapabilities()
93
const char* napp = getenv("GIVERTCAP");
94
system(napp ? napp : "givertcap");
99
//---------------------------------------------------------
101
//---------------------------------------------------------
106
extern void getCapabilities();
109
doSetuid(euid, ruid);
111
struct sched_param sp;
112
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
113
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
115
sp.sched_priority = 20;
116
if (sched_setscheduler(0, SCHED_RR, &sp) == 0) {
117
fprintf(stderr, "mess: %s: running as realtime process now (priority %d)\n",
121
fprintf(stderr, "mess: %s: Can't get realtime priority: %s\n",
122
_name, strerror(errno));
124
if (mlockall(MCL_FUTURE))
125
perror("mess: Cannot lock memory");
127
undoSetuid(euid, ruid);
132
int n = poll(pfd, npfd, -1); // wait infinite for event
136
snd_seq_event_t* event;
137
int rv = snd_seq_event_input(alsaSeq, &event);
141
pthread_mutex_lock(&lock);
142
double frame = startFrame;
143
pthread_mutex_unlock(&lock);
145
if (event->type == SND_SEQ_EVENT_PORT_START)
148
unsigned pos = int ((curTime() - frame) * _sampleRate);
151
switch(event->type) {
152
// case SND_SEQ_EVENT_PORT_START:
153
case SND_SEQ_EVENT_PORT_EXIT:
156
case SND_SEQ_EVENT_NOTEON:
157
case SND_SEQ_EVENT_KEYPRESS:
158
case SND_SEQ_EVENT_NOTEOFF:
159
ev = new MEvent(pos, event->type,
160
event->data.note.channel,
161
event->data.note.note,
162
event->data.note.velocity);
165
case SND_SEQ_EVENT_CONTROL14:
166
case SND_SEQ_EVENT_NONREGPARAM:
167
case SND_SEQ_EVENT_REGPARAM:
168
case SND_SEQ_EVENT_CONTROLLER:
169
case SND_SEQ_EVENT_PGMCHANGE:
170
case SND_SEQ_EVENT_CHANPRESS:
171
ev = new MEvent(pos, event->type,
172
event->data.control.channel,
173
event->data.control.param,
174
event->data.control.value);
178
case SND_SEQ_EVENT_PITCHBEND:
179
ev = new MEvent(pos, event->type,
180
event->data.control.channel,
181
(event->data.control.value >> 7) & 0x7f,
182
event->data.control.value & 0x7f);
185
case SND_SEQ_EVENT_SYSEX:
187
int len = event->data.ext.len;
188
unsigned char* data = new unsigned char[len];
189
memcpy(data, event->data.ext.ptr, len);
190
ev = new MEvent(pos, event->type, 0, 0, 0, data, len);
195
printf("mess: ALSA Seq input: type %d not handled\n", event->type);
198
snd_seq_free_event(event);
202
// allow for initialize events
206
pthread_mutex_lock(&lock);
207
events.push_back(ev);
208
pthread_mutex_unlock(&lock);
215
//---------------------------------------------------------
217
//---------------------------------------------------------
219
Mess::Mess(const char* cn, int chn)
220
: _className(strdup(cn))
223
outputPorts = new float*[_channels];
230
pthread_mutex_init(&lock, 0);
233
//---------------------------------------------------------
235
//---------------------------------------------------------
237
#if (SND_LIB_MAJOR==0) && (SND_LIB_MINOR==9)
240
delete[] outputPorts;
246
#ifdef snd_seq_port_info_alloca
247
int error = snd_seq_delete_port(alsaSeq, _alsaPort.port);
249
snd_seq_port_info_t *pinfo;
250
pinfo = (snd_seq_port_info_t*)alloca(sizeof(*pinfo));
251
memset(pinfo, 0, sizeof(*pinfo));
252
pinfo->client = _alsaPort.client;
253
pinfo->port = _alsaPort.port;
254
int error = snd_seq_delete_port(alsaSeq, pinfo);
257
fprintf(stderr, "ALSA: cannot delete port: %s\n",
258
snd_strerror(error));
264
//---------------------------------------------------------
266
//---------------------------------------------------------
268
#if (SND_LIB_MAJOR==0) && (SND_LIB_MINOR==5)
277
snd_seq_port_info_t* pinfo = new snd_seq_port_info_t;
278
memset(pinfo, 0, sizeof(*pinfo));
279
pinfo->client = _alsaPort.client;
280
pinfo->port = _alsaPort.port;
281
int error = snd_seq_delete_port(alsaSeq, pinfo);
283
fprintf(stderr, "ALSA: cannot delete port: %s\n",
284
snd_strerror(error));
291
//---------------------------------------------------------
293
//---------------------------------------------------------
295
void Mess::setName(const char* s)
300
//---------------------------------------------------------
302
//---------------------------------------------------------
304
#if (SND_LIB_MAJOR==0) && (SND_LIB_MINOR==9)
305
void Mess::registerAlsa()
307
//-----------------------------------------
308
// connect to ALSA and get poll
310
//-----------------------------------------
313
int error = snd_seq_open(&alsaSeq, "hw", SND_SEQ_OPEN_DUPLEX|SND_SEQ_NONBLOCK, 0);
315
fprintf(stderr, "Could not open ALSA sequencer: %s\n",
316
snd_strerror(error));
322
snd_seq_set_client_name(alsaSeq, _className);
323
npfd = snd_seq_poll_descriptors_count(alsaSeq, POLLIN);
324
pfd = new pollfd[npfd];
325
snd_seq_poll_descriptors(alsaSeq, pfd, npfd, POLLIN);
326
for (int i = 0; i < npfd; ++i) {
327
pfd[i].events = POLLIN;
331
//-----------------------------------------
332
// find an unused alsa port name
333
//-----------------------------------------
336
for (int i = 1;; ++i) {
338
sprintf(buffer, "%s-%d", _className, i);
340
snd_seq_client_info_t* cinfo;
341
#ifdef snd_seq_client_info_alloca
342
snd_seq_client_info_alloca(&cinfo);
343
snd_seq_client_info_set_client(cinfo, -1);
345
cinfo = (snd_seq_client_info_t*)alloca(sizeof(*cinfo));
346
memset(cinfo, 0, sizeof(*cinfo));
349
while (snd_seq_query_next_client(alsaSeq, cinfo) >= 0) {
350
#ifdef SND_SEQ_GROUP_SYSTEM
351
if (strcmp(cinfo->group, SND_SEQ_GROUP_SYSTEM) == 0)
354
snd_seq_port_info_t *pinfo;
355
#ifdef snd_seq_port_info_alloca
356
snd_seq_port_info_alloca(&pinfo);
357
snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
358
snd_seq_port_info_set_port(pinfo, -1);
360
pinfo = (snd_seq_port_info_t*)alloca(sizeof(*pinfo));
361
memset(pinfo, 0, sizeof(*pinfo));
362
pinfo->client = cinfo->client;
365
while (snd_seq_query_next_port(alsaSeq, pinfo) >= 0) {
366
const char* portname;
367
#ifdef snd_seq_port_info_alloca
368
portname = snd_seq_port_info_get_name(pinfo);
370
portname = pinfo->name;
372
// printf("compare port <%s> <%s>\n", portname, buffer);
373
if (strcmp(portname, buffer) == 0) {
384
_name = strdup(buffer);
388
snd_seq_client_info_t* cinfo;
389
#ifdef snd_seq_client_info_alloca
390
snd_seq_client_info_alloca(&cinfo);
391
snd_seq_client_info_set_client(cinfo, -1);
393
cinfo = (snd_seq_client_info_t*)alloca(sizeof(*cinfo));
394
memset(cinfo, 0, sizeof(*cinfo));
397
while (snd_seq_query_next_client(alsaSeq, cinfo) >= 0) {
399
snd_seq_port_info_t *pinfo;
400
#ifdef snd_seq_port_info_alloca
401
snd_seq_port_info_alloca(&pinfo);
402
snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
403
snd_seq_port_info_set_port(pinfo, -1);
405
pinfo = (snd_seq_port_info_t*)alloca(sizeof(*pinfo));
406
memset(pinfo, 0, sizeof(*pinfo));
407
pinfo->client = cinfo->client;
410
while (snd_seq_query_next_port(alsaSeq, pinfo) >= 0) {
411
const char* portname;
412
#ifdef snd_seq_port_info_alloca
413
portname = snd_seq_port_info_get_name(pinfo);
415
portname = pinfo->name;
417
if (strcmp(portname, "MusE Port 0") == 0) {
419
snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
421
_musePort.port = snd_seq_port_info_get_port(pinfo);
422
_musePort.client = snd_seq_client_info_get_client(cinfo);
430
printf("muse port not found!\n");
433
//-----------------------------------------
434
// create port to alsa sequencer
435
//-----------------------------------------
437
int port = snd_seq_create_simple_port(alsaSeq, _name,
438
SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE,
439
SND_SEQ_PORT_TYPE_APPLICATION);
440
// printf("create new alsa port <%s>\n", _name);
442
perror("create port");
445
_alsaPort.port = port;
446
_alsaPort.client = snd_seq_client_id(alsaSeq);
448
// create the midi thread
449
int err = pthread_create(&midiThread, 0, midi_run, this);
451
printf("Mess: Couldn't create midi thread: %s\n",
457
#if (SND_LIB_MAJOR==0) && (SND_LIB_MINOR==5)
458
//---------------------------------------------------------
461
//---------------------------------------------------------
463
void Mess::registerAlsa()
465
//-----------------------------------------
466
// connect to ALSA and get poll
468
//-----------------------------------------
470
int error = snd_seq_open(&alsaSeq, SND_SEQ_OPEN|SND_SEQ_NONBLOCK);
472
fprintf(stderr, "Could not open ALSA sequencer: %s\n",
473
snd_strerror(error));
478
int alsaSeqFd = snd_seq_file_descriptor(alsaSeq);
482
pfd->events = POLLIN;
485
//-----------------------------------------
486
// find an unused alsa port name
487
//-----------------------------------------
489
snd_seq_system_info_t sysinfo;
490
int error = snd_seq_system_info(alsaSeq, &sysinfo);
492
fprintf(stderr, "Cound not get ALSA sequencer info: %s\n",
493
snd_strerror(error));
499
for (int i = 1;; ++i) {
501
sprintf(buffer, "%s-%d", _className, i);
502
for (int client = 0; client < sysinfo.clients; ++client) {
503
snd_seq_client_info_t cinfo;
504
if (snd_seq_get_any_client_info(alsaSeq, client, &cinfo) < 0)
507
for (int port = 0; port < sysinfo.ports; port++) {
508
snd_seq_port_info_t pinfo;
510
if (snd_seq_get_any_port_info(alsaSeq, client, port, &pinfo) < 0)
512
const char* portname = pinfo.name;
513
if (strcmp(portname, buffer) == 0) {
524
_name = strdup(buffer);
528
for (int client = 0; client < sysinfo.clients; ++client) {
530
snd_seq_client_info_t cinfo;
531
if (snd_seq_get_any_client_info(alsaSeq, client, &cinfo) < 0)
533
for (int port = 0; port < sysinfo.ports; port++) {
534
snd_seq_port_info_t pinfo;
536
if (snd_seq_get_any_port_info(alsaSeq, client, port, &pinfo) < 0)
538
const char* portname = pinfo.name;
539
if (strcmp(portname, "MusE Port 0") == 0) {
541
_musePort.port = pinfo.port;
542
_musePort.client = cinfo.client;
550
printf("muse port not found!\n");
553
//-----------------------------------------
554
// create port to alsa sequencer
555
//-----------------------------------------
557
int port = snd_seq_create_simple_port(alsaSeq, _name,
558
SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE,
559
SND_SEQ_PORT_TYPE_APPLICATION);
560
// printf("create new alsa port <%s>\n", _name);
562
perror("create port");
565
_alsaPort.port = port;
566
_alsaPort.client = snd_seq_client_id(alsaSeq);
568
// create the midi thread
569
int err = pthread_create(&midiThread, 0, midi_run, this);
571
printf("Mess: Couldn't create midi thread: %s\n",
577
//---------------------------------------------------------
579
//---------------------------------------------------------
581
const char* Mess::getPatchName(int /*channel*/, int /*hbank*/, int /*lbank*/,
582
int /*prog*/, MType /*type*/)
587
//---------------------------------------------------------
589
//---------------------------------------------------------
591
void Mess::sendSysex(const unsigned char* p, int n)
593
snd_seq_event_t event;
594
int len = n + sizeof(event) + 2;
595
char* buf = new char[len];
596
memset(&event, 0, sizeof(event));
597
event.type = SND_SEQ_EVENT_SYSEX;
598
event.flags = SND_SEQ_EVENT_LENGTH_VARIABLE;
599
event.data.ext.len = n + 2;
600
event.data.ext.ptr = (void*)(buf + sizeof(event));
602
event.queue = SND_SEQ_QUEUE_DIRECT;
603
event.dest = _musePort;
604
event.source = _alsaPort;
606
memcpy(buf, &event, sizeof(event));
607
char* pp = buf + sizeof(event);
613
#if (SND_LIB_MAJOR==0) && (SND_LIB_MINOR==5)
614
int alsaSeqFd = snd_seq_file_descriptor(alsaSeq);
615
int error = write(alsaSeqFd, buf, len);
617
fprintf(stderr, "sysex: midi write error: %s\n", snd_strerror(error));
620
#if (SND_LIB_MAJOR==0) && (SND_LIB_MINOR==9)
621
int error = snd_seq_event_output_direct(alsaSeq, &event);
623
fprintf(stderr, "sysex: midi write error: %s\n", snd_strerror(error));
628
//---------------------------------------------------------
630
//---------------------------------------------------------
632
void Mess::processreplace(int len)
634
pthread_mutex_lock(&lock);
635
startFrame = curTime();
636
pthread_mutex_unlock(&lock);
639
for (int channel = 0; channel < _channels; ++channel)
640
memset(outputPorts[channel], 0, len * sizeof(float));
642
//---------------------------------------------------
643
// process all midi events for this buffer
644
//---------------------------------------------------
647
//---------------------------------------------
648
// get next midi event
649
//---------------------------------------------
650
pthread_mutex_lock(&lock);
652
if (events.empty()) {
653
pthread_mutex_unlock(&lock);
656
MEvent* e = events.front();
657
int samplePos = e->samplePos();
658
if (samplePos >= len) {
659
for (iMEvent i = events.begin(); i != events.end(); ++i) {
660
(*i)->adjustSamplePos(len);
662
pthread_mutex_unlock(&lock);
665
events.erase(events.begin());
666
pthread_mutex_unlock(&lock);
668
//---------------------------------------------
669
// generate samples up to this midi event
670
//---------------------------------------------
672
int samplesToSynthesize = samplePos - offset;
674
write(samplesToSynthesize, outputPorts, offset);
675
offset += samplesToSynthesize;
680
//---------------------------------------------------
682
//---------------------------------------------------
684
int samplesToSynthesize = len - offset;
685
write(samplesToSynthesize, outputPorts, offset);
688
//---------------------------------------------------------
690
//---------------------------------------------------------
692
MessMono::MessMono(const char* name, int channels)
693
: Mess(name, channels)
697
MessMono::~MessMono()
701
//---------------------------------------------------------
703
//---------------------------------------------------------
705
void MessMono::midiNoteOn(int channel, int pitch, int velo)
708
midiNoteOff(channel, pitch);
711
pitchStack.push_back(PitchVelo(channel, pitch, velo));
712
noteon(channel, pitch, velo);
715
//---------------------------------------------------------
717
//---------------------------------------------------------
719
void MessMono::midiNoteOff(int channel, int pitch)
721
if (pitchStack.empty())
723
if (pitchStack.back().pitch == pitch) {
724
pitchStack.pop_back();
725
if (pitchStack.empty()) {
726
noteoff(channel, pitch);
729
PitchVelo pv = pitchStack.back();
730
noteon(pv.channel, pv.pitch, pv.velo); // change pitch
733
for (std::list<PitchVelo>::iterator i = pitchStack.begin();
734
i != pitchStack.end(); ++i) {
735
if ((*i).pitch == pitch) {
742
noteoff(channel, pitch);
745
//---------------------------------------------------------
747
// process received midi event
748
//---------------------------------------------------------
750
void MessMono::processEvent(MEvent* ev)
753
case SND_SEQ_EVENT_NOTEON:
754
case SND_SEQ_EVENT_KEYPRESS:
755
midiNoteOn(ev->chan(), ev->dataA(), ev->dataB());
758
case SND_SEQ_EVENT_NOTEOFF:
759
midiNoteOff(ev->chan(), ev->dataA());
762
case SND_SEQ_EVENT_CONTROL14:
763
case SND_SEQ_EVENT_NONREGPARAM:
764
case SND_SEQ_EVENT_REGPARAM:
765
case SND_SEQ_EVENT_CONTROLLER:
766
switch(ev->dataA()) {
767
case 0x62: ctrlLo = ev->dataB(); break;
768
case 0x63: ctrlHi = ev->dataB(); break;
769
case 0x06: dataHi = ev->dataB(); break;
770
case 0x026: dataLo = ev->dataB(); break;
772
if(ev->dataA() == 0x06)
773
setController(ev->chan(), ctrlLo+ctrlHi*128, dataLo+dataHi*128);
776
case SND_SEQ_EVENT_SYSEX:
777
sysex(ev->data(), ev->dataLen());
779
case SND_SEQ_EVENT_CHANPRESS:
780
case SND_SEQ_EVENT_PITCHBEND:
781
case SND_SEQ_EVENT_PGMCHANGE:
784
printf("MessMono: event type %d not processed\n", ev->type());
789
//=========================================================
791
//=========================================================
793
static Mess* (*xinstantiate)(const char* name);
795
//---------------------------------------------------------
797
// construct a new synthesizer instance
798
//---------------------------------------------------------
800
static LADSPA_Handle instantiate(const LADSPA_Descriptor* descr, unsigned long sr)
802
Mess* synth = xinstantiate(descr->Label);
803
synth->setSampleRate(sr);
811
//---------------------------------------------------------
813
//---------------------------------------------------------
815
static void run(LADSPA_Handle instance, unsigned long sampleCount)
817
((Mess *)instance)->processreplace(sampleCount);
820
//---------------------------------------------------------
822
// Connect a port to a data location.
823
//---------------------------------------------------------
825
static void connect(LADSPA_Handle Instance, unsigned long port, float* data)
827
((Mess *)Instance)->setPort(port, data);
830
//---------------------------------------------------------
832
//---------------------------------------------------------
834
static void activate(LADSPA_Handle instance)
836
((Mess *)instance)->init();
837
((Mess *)instance)->registerAlsa();
840
//---------------------------------------------------------
842
//---------------------------------------------------------
844
static void cleanup(LADSPA_Handle instance)
846
delete (Mess *)instance;
849
//---------------------------------------------------------
851
//---------------------------------------------------------
853
static const char* portNames[] = {
858
//---------------------------------------------------------
860
//---------------------------------------------------------
862
static LADSPA_PortDescriptor portDescriptors[] = {
863
LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
864
LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
867
//---------------------------------------------------------
869
//---------------------------------------------------------
871
static LADSPA_PortRangeHint portRangeHints[] = {
876
static LADSPA_Descriptor descriptor = {
879
LADSPA_PROPERTY_HARD_RT_CAPABLE,
898
//---------------------------------------------------------
900
// Return a descriptor of the requested plugin type.
901
//---------------------------------------------------------
903
const LADSPA_Descriptor* ladspa_descriptor(unsigned long i)
905
__init(); // create ladspa descritpor
906
return (i == 0) ? &descriptor : 0;
909
//---------------------------------------------------------
911
// ports - 1-Mono 2-Stereo
912
//---------------------------------------------------------
914
void Mess::initMess(unsigned long id, const char* label, const char* maker,
915
const char* name, const char* copyright, unsigned long ports,
916
Mess* (inst)(const char*))
918
descriptor.UniqueID = id;
919
descriptor.Label = label;
920
descriptor.Name = name;
921
descriptor.Maker = maker;
922
descriptor.Copyright = copyright;
923
descriptor.PortCount = ports;