~ubuntu-branches/ubuntu/karmic/muse/karmic-proposed

« back to all changes in this revision

Viewing changes to driver/mess.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Kobras
  • Date: 2002-04-23 17:28:23 UTC
  • Revision ID: james.westby@ubuntu.com-20020423172823-w8yplzr81a759xa3
Tags: upstream-0.5.2
ImportĀ upstreamĀ versionĀ 0.5.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//=========================================================
 
2
//  MusE
 
3
//  Linux Music Editor
 
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
//=========================================================
 
7
 
 
8
#include "mess.h"
 
9
#include <stdio.h>
 
10
#include <string.h>
 
11
#include <poll.h>
 
12
#include <sys/mman.h>
 
13
#include <pthread.h>
 
14
#include <sys/time.h>
 
15
#include <errno.h>
 
16
#include <unistd.h>
 
17
 
 
18
#include "ladspa.h"
 
19
 
 
20
extern void __init();
 
21
 
 
22
 
 
23
//---------------------------------------------------------
 
24
//   doSetuid
 
25
//    Restore the effective UID to its original value.
 
26
//---------------------------------------------------------
 
27
 
 
28
static void doSetuid(uid_t euid, uid_t ruid)
 
29
      {
 
30
      int status;
 
31
 
 
32
#ifdef _POSIX_SAVED_IDS
 
33
      status = seteuid (euid);
 
34
#else
 
35
      status = setreuid (ruid, euid);
 
36
#endif
 
37
      if (status < 0) {
 
38
            fprintf(stderr, "Couldn't set uid.\n");
 
39
            }
 
40
      }
 
41
 
 
42
//---------------------------------------------------------
 
43
//   undoSetuid
 
44
//    Set the effective UID to the real UID.
 
45
//---------------------------------------------------------
 
46
 
 
47
static void undoSetuid(uid_t euid, uid_t ruid)
 
48
      {
 
49
      int status;
 
50
 
 
51
#ifdef _POSIX_SAVED_IDS
 
52
      status = seteuid (ruid);
 
53
#else
 
54
      status = setreuid (euid, ruid);
 
55
#endif
 
56
      if (status < 0) {
 
57
            fprintf (stderr, "Couldn't set uid.\n");
 
58
            exit (status);
 
59
            }
 
60
      }
 
61
 
 
62
//---------------------------------------------------------
 
63
//   curTime
 
64
//---------------------------------------------------------
 
65
 
 
66
static double curTime()
 
67
      {
 
68
      struct timeval t;
 
69
      struct timezone tz;
 
70
      gettimeofday(&t, &tz);
 
71
      return (double)((double)t.tv_sec + (t.tv_usec / 1000000.0));
 
72
      }
 
73
 
 
74
//---------------------------------------------------------
 
75
//   midi_run
 
76
//---------------------------------------------------------
 
77
 
 
78
static void* midi_run(void* d)
 
79
      {
 
80
      Mess* s = (Mess*) d;
 
81
      s->midiRun();
 
82
      pthread_exit(0);
 
83
      }
 
84
 
 
85
#ifdef RTCAP
 
86
//---------------------------------------------------------
 
87
//   getCapabilities
 
88
//---------------------------------------------------------
 
89
 
 
90
void getCapabilities()
 
91
      {
 
92
#ifdef __linux__
 
93
      const char* napp = getenv("GIVERTCAP");
 
94
      system(napp ? napp : "givertcap");
 
95
#endif // __linux__
 
96
      }
 
97
#endif
 
98
 
 
99
//---------------------------------------------------------
 
100
//   midiRun
 
101
//---------------------------------------------------------
 
102
 
 
103
void Mess::midiRun()
 
104
      {
 
105
#ifdef RTCAP
 
106
      extern void getCapabilities();
 
107
      getCapabilities();
 
108
#else
 
109
      doSetuid(euid, ruid);
 
110
#endif
 
111
      struct sched_param sp;
 
112
      pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
 
113
      pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
 
114
 
 
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",
 
118
               _name, 20);
 
119
            }
 
120
        else {
 
121
            fprintf(stderr, "mess: %s: Can't get realtime priority: %s\n",
 
122
               _name, strerror(errno));
 
123
            }
 
124
      if (mlockall(MCL_FUTURE))
 
125
            perror("mess: Cannot lock memory");
 
126
#ifndef RTCAP
 
127
      undoSetuid(euid, ruid);
 
128
#endif
 
129
 
 
130
      MEvent* ev;
 
131
      for (;;) {
 
132
            int n = poll(pfd, npfd, -1);  // wait infinite for event
 
133
            if (n <= 0)
 
134
                  continue;
 
135
            for(;;) {
 
136
                  snd_seq_event_t* event;
 
137
                  int rv = snd_seq_event_input(alsaSeq, &event);
 
138
                  if (rv < 0)
 
139
                        break;
 
140
 
 
141
                  pthread_mutex_lock(&lock);
 
142
                  double frame = startFrame;
 
143
                  pthread_mutex_unlock(&lock);
 
144
 
 
145
                  if (event->type == SND_SEQ_EVENT_PORT_START)
 
146
                        continue;
 
147
 
 
148
                  unsigned pos = int ((curTime() - frame) * _sampleRate);
 
149
 
 
150
                  ev = 0;
 
151
                  switch(event->type) {
 
152
//                        case SND_SEQ_EVENT_PORT_START:
 
153
                        case SND_SEQ_EVENT_PORT_EXIT:
 
154
                              break;
 
155
 
 
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);
 
163
                              break;
 
164
 
 
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);
 
175
                              break;
 
176
 
 
177
 
 
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);
 
183
                              break;
 
184
 
 
185
                        case SND_SEQ_EVENT_SYSEX:
 
186
                              {
 
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);
 
191
                              }
 
192
                              break;
 
193
 
 
194
                        default:
 
195
                              printf("mess: ALSA Seq input: type %d not handled\n", event->type);
 
196
                              break;
 
197
                        }
 
198
                  snd_seq_free_event(event);
 
199
                  if (ev) {
 
200
                        if (frame == 0.0) {
 
201
                              // audio not running
 
202
                              // allow for initialize events
 
203
                              processEvent(ev);
 
204
                              }
 
205
                        else {
 
206
                              pthread_mutex_lock(&lock);
 
207
                              events.push_back(ev);
 
208
                              pthread_mutex_unlock(&lock);
 
209
                              }
 
210
                        }
 
211
                  }
 
212
            }
 
213
      }
 
214
 
 
215
//---------------------------------------------------------
 
216
//   Mess
 
217
//---------------------------------------------------------
 
218
 
 
219
Mess::Mess(const char* cn, int chn)
 
220
   : _className(strdup(cn))
 
221
      {
 
222
      _channels   = chn;
 
223
      outputPorts = new float*[_channels];
 
224
      _name       = 0;
 
225
      alsaSeq     = 0;
 
226
      pfd         = 0;
 
227
      npfd        = 0;
 
228
      startFrame  = 0.0;
 
229
      _sampleRate = 44100;
 
230
      pthread_mutex_init(&lock, 0);
 
231
      }
 
232
 
 
233
//---------------------------------------------------------
 
234
//   Mess
 
235
//---------------------------------------------------------
 
236
 
 
237
#if (SND_LIB_MAJOR==0) && (SND_LIB_MINOR==9)
 
238
Mess::~Mess()
 
239
      {
 
240
      delete[] outputPorts;
 
241
      if (_name)
 
242
            delete _name;
 
243
      if (_className)
 
244
            delete _className;
 
245
      if (alsaSeq) {
 
246
#ifdef snd_seq_port_info_alloca
 
247
            int error = snd_seq_delete_port(alsaSeq, _alsaPort.port);
 
248
#else
 
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);
 
255
#endif
 
256
            if (error < 0) {
 
257
                  fprintf(stderr, "ALSA: cannot delete port: %s\n",
 
258
                     snd_strerror(error));
 
259
                  }
 
260
            }
 
261
      }
 
262
#endif
 
263
 
 
264
//---------------------------------------------------------
 
265
//   Mess
 
266
//---------------------------------------------------------
 
267
 
 
268
#if (SND_LIB_MAJOR==0) && (SND_LIB_MINOR==5)
 
269
Mess::~Mess()
 
270
      {
 
271
      delete outputPorts;
 
272
      if (_name)
 
273
            delete _name;
 
274
      if (_className)
 
275
            delete _className;
 
276
      if (alsaSeq) {
 
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);
 
282
            if (error < 0) {
 
283
                  fprintf(stderr, "ALSA: cannot delete port: %s\n",
 
284
                     snd_strerror(error));
 
285
                  }
 
286
            delete pinfo;
 
287
            }
 
288
      }
 
289
#endif
 
290
 
 
291
//---------------------------------------------------------
 
292
//   setName
 
293
//---------------------------------------------------------
 
294
 
 
295
void Mess::setName(const char* s)
 
296
      {
 
297
      _name = strdup(s);
 
298
      }
 
299
 
 
300
//---------------------------------------------------------
 
301
//   registerAlsa
 
302
//---------------------------------------------------------
 
303
 
 
304
#if (SND_LIB_MAJOR==0) && (SND_LIB_MINOR==9)
 
305
void Mess::registerAlsa()
 
306
      {
 
307
      //-----------------------------------------
 
308
      //  connect to ALSA and get poll
 
309
      //  descriptors
 
310
      //-----------------------------------------
 
311
 
 
312
      if (alsaSeq == 0) {
 
313
            int error = snd_seq_open(&alsaSeq, "hw", SND_SEQ_OPEN_DUPLEX|SND_SEQ_NONBLOCK, 0);
 
314
            if (error < 0) {
 
315
                  fprintf(stderr, "Could not open ALSA sequencer: %s\n",
 
316
                     snd_strerror(error));
 
317
                  alsaSeq = 0;
 
318
                  return;
 
319
                  }
 
320
            }
 
321
 
 
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;
 
328
            pfd[i].revents = 0;
 
329
            }
 
330
 
 
331
      //-----------------------------------------
 
332
      //  find an unused alsa port name
 
333
      //-----------------------------------------
 
334
 
 
335
      char buffer[256];
 
336
      for (int i = 1;; ++i) {
 
337
            bool found = false;
 
338
            sprintf(buffer, "%s-%d", _className, i);
 
339
 
 
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);
 
344
#else
 
345
            cinfo = (snd_seq_client_info_t*)alloca(sizeof(*cinfo));
 
346
            memset(cinfo, 0, sizeof(*cinfo));
 
347
            cinfo->client = -1;
 
348
#endif
 
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)
 
352
                        continue;
 
353
#endif
 
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);
 
359
#else
 
360
                  pinfo = (snd_seq_port_info_t*)alloca(sizeof(*pinfo));
 
361
                  memset(pinfo, 0, sizeof(*pinfo));
 
362
                  pinfo->client = cinfo->client;
 
363
                  pinfo->port = -1;
 
364
#endif
 
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);
 
369
#else
 
370
                        portname = pinfo->name;
 
371
#endif
 
372
// printf("compare port <%s> <%s>\n", portname, buffer);
 
373
                        if (strcmp(portname, buffer) == 0) {
 
374
                              found = true;
 
375
                              break;
 
376
                              }
 
377
                        }
 
378
                  if (found)
 
379
                        break;
 
380
                  }
 
381
            if (!found)
 
382
                  break;
 
383
            }
 
384
      _name = strdup(buffer);
 
385
 
 
386
      // search muse port
 
387
      bool found = false;
 
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);
 
392
#else
 
393
      cinfo = (snd_seq_client_info_t*)alloca(sizeof(*cinfo));
 
394
      memset(cinfo, 0, sizeof(*cinfo));
 
395
      cinfo->client = -1;
 
396
#endif
 
397
      while (snd_seq_query_next_client(alsaSeq, cinfo) >= 0) {
 
398
            found = false;
 
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);
 
404
#else
 
405
            pinfo = (snd_seq_port_info_t*)alloca(sizeof(*pinfo));
 
406
            memset(pinfo, 0, sizeof(*pinfo));
 
407
            pinfo->client = cinfo->client;
 
408
            pinfo->port = -1;
 
409
#endif
 
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);
 
414
#else
 
415
                  portname = pinfo->name;
 
416
#endif
 
417
                  if (strcmp(portname, "MusE Port 0") == 0) {
 
418
                        found = true;
 
419
                  snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
 
420
 
 
421
                        _musePort.port   = snd_seq_port_info_get_port(pinfo);
 
422
                        _musePort.client = snd_seq_client_info_get_client(cinfo);
 
423
                        break;
 
424
                        }
 
425
                  }
 
426
            if (found)
 
427
                  break;
 
428
            }
 
429
      if (!found) {
 
430
            printf("muse port not found!\n");
 
431
            }
 
432
 
 
433
      //-----------------------------------------
 
434
      //    create port to alsa sequencer
 
435
      //-----------------------------------------
 
436
 
 
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);
 
441
      if (port < 0) {
 
442
            perror("create port");
 
443
            return;
 
444
            }
 
445
      _alsaPort.port   = port;
 
446
      _alsaPort.client = snd_seq_client_id(alsaSeq);
 
447
 
 
448
      // create the midi thread
 
449
      int err = pthread_create(&midiThread, 0, midi_run, this);
 
450
      if (err) {
 
451
            printf("Mess: Couldn't create midi thread: %s\n",
 
452
               strerror(errno));
 
453
            }
 
454
      }
 
455
#endif
 
456
 
 
457
#if (SND_LIB_MAJOR==0) && (SND_LIB_MINOR==5)
 
458
//---------------------------------------------------------
 
459
//   registerAlsa
 
460
//    ALSA 5 version
 
461
//---------------------------------------------------------
 
462
 
 
463
void Mess::registerAlsa()
 
464
      {
 
465
      //-----------------------------------------
 
466
      //  connect to ALSA and get poll
 
467
      //  descriptors
 
468
      //-----------------------------------------
 
469
      if (alsaSeq == 0) {
 
470
            int error = snd_seq_open(&alsaSeq, SND_SEQ_OPEN|SND_SEQ_NONBLOCK);
 
471
            if (error < 0) {
 
472
                  fprintf(stderr, "Could not open ALSA sequencer: %s\n",
 
473
                     snd_strerror(error));
 
474
                  alsaSeq = 0;
 
475
                  return;
 
476
                  }
 
477
            }
 
478
      int alsaSeqFd = snd_seq_file_descriptor(alsaSeq);
 
479
      npfd         = 1;
 
480
      pfd          = new pollfd;
 
481
      pfd->fd      = alsaSeqFd;
 
482
      pfd->events  = POLLIN;
 
483
      pfd->revents = 0;
 
484
 
 
485
      //-----------------------------------------
 
486
      //  find an unused alsa port name
 
487
      //-----------------------------------------
 
488
 
 
489
      snd_seq_system_info_t sysinfo;
 
490
      int error = snd_seq_system_info(alsaSeq, &sysinfo);
 
491
      if (error < 0) {
 
492
            fprintf(stderr, "Cound not get ALSA sequencer info: %s\n",
 
493
               snd_strerror(error));
 
494
            return;
 
495
            }
 
496
 
 
497
      char buffer[256];
 
498
      buffer[0] = 0;
 
499
      for (int i = 1;; ++i) {
 
500
            bool found = false;
 
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)
 
505
                        continue;
 
506
 
 
507
                  for (int port = 0; port < sysinfo.ports; port++) {
 
508
                        snd_seq_port_info_t pinfo;
 
509
 
 
510
                        if (snd_seq_get_any_port_info(alsaSeq, client, port, &pinfo) < 0)
 
511
                              continue;
 
512
                        const char* portname = pinfo.name;
 
513
                        if (strcmp(portname, buffer) == 0) {
 
514
                              found = true;
 
515
                              break;
 
516
                              }
 
517
                        }
 
518
                  if (found)
 
519
                        break;
 
520
                  }
 
521
            if (!found)
 
522
                  break;
 
523
            }
 
524
      _name = strdup(buffer);
 
525
 
 
526
      // search muse port
 
527
      bool found;
 
528
      for (int client = 0; client < sysinfo.clients; ++client) {
 
529
            found = false;
 
530
            snd_seq_client_info_t cinfo;
 
531
            if (snd_seq_get_any_client_info(alsaSeq, client, &cinfo) < 0)
 
532
                  continue;
 
533
            for (int port = 0; port < sysinfo.ports; port++) {
 
534
                  snd_seq_port_info_t pinfo;
 
535
 
 
536
                  if (snd_seq_get_any_port_info(alsaSeq, client, port, &pinfo) < 0)
 
537
                        continue;
 
538
                  const char* portname = pinfo.name;
 
539
                  if (strcmp(portname, "MusE Port 0") == 0) {
 
540
                        found = true;
 
541
                        _musePort.port   = pinfo.port;
 
542
                        _musePort.client = cinfo.client;
 
543
                        break;
 
544
                        }
 
545
                  }
 
546
            if (found)
 
547
                  break;
 
548
            }
 
549
      if (!found) {
 
550
            printf("muse port not found!\n");
 
551
            }
 
552
 
 
553
      //-----------------------------------------
 
554
      //    create port to alsa sequencer
 
555
      //-----------------------------------------
 
556
 
 
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);
 
561
      if (port < 0) {
 
562
            perror("create port");
 
563
            return;
 
564
            }
 
565
      _alsaPort.port   = port;
 
566
      _alsaPort.client = snd_seq_client_id(alsaSeq);
 
567
 
 
568
      // create the midi thread
 
569
      int err = pthread_create(&midiThread, 0, midi_run, this);
 
570
      if (err) {
 
571
            printf("Mess: Couldn't create midi thread: %s\n",
 
572
               strerror(errno));
 
573
            }
 
574
      }
 
575
#endif
 
576
 
 
577
//---------------------------------------------------------
 
578
//   getPatchName
 
579
//---------------------------------------------------------
 
580
 
 
581
const char* Mess::getPatchName(int /*channel*/, int /*hbank*/, int /*lbank*/,
 
582
   int /*prog*/, MType /*type*/)
 
583
      {
 
584
      return "???";
 
585
      }
 
586
 
 
587
//---------------------------------------------------------
 
588
//    sysex
 
589
//---------------------------------------------------------
 
590
 
 
591
void Mess::sendSysex(const unsigned char* p, int n)
 
592
      {
 
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));
 
601
      event.tag           = 0;
 
602
      event.queue         = SND_SEQ_QUEUE_DIRECT;
 
603
      event.dest          = _musePort;
 
604
      event.source        = _alsaPort;
 
605
 
 
606
      memcpy(buf, &event, sizeof(event));
 
607
      char* pp = buf + sizeof(event);
 
608
      *pp++ = 0xf0;
 
609
      memcpy(pp, p, n);
 
610
      pp += n;
 
611
      *pp = 0xf7;
 
612
 
 
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);
 
616
      if (error != len)
 
617
            fprintf(stderr, "sysex: midi write error: %s\n", snd_strerror(error));
 
618
#endif
 
619
 
 
620
#if (SND_LIB_MAJOR==0) && (SND_LIB_MINOR==9)
 
621
      int error = snd_seq_event_output_direct(alsaSeq, &event);
 
622
      if (error < 0)
 
623
            fprintf(stderr, "sysex: midi write error: %s\n", snd_strerror(error));
 
624
#endif
 
625
      delete buf;
 
626
      }
 
627
 
 
628
//---------------------------------------------------------
 
629
//   processreplace
 
630
//---------------------------------------------------------
 
631
 
 
632
void Mess::processreplace(int len)
 
633
      {
 
634
      pthread_mutex_lock(&lock);
 
635
      startFrame = curTime();
 
636
      pthread_mutex_unlock(&lock);
 
637
 
 
638
      int offset = 0;
 
639
      for (int channel = 0; channel < _channels; ++channel)
 
640
            memset(outputPorts[channel], 0, len * sizeof(float));
 
641
 
 
642
      //---------------------------------------------------
 
643
      //  process all midi events for this buffer
 
644
      //---------------------------------------------------
 
645
 
 
646
      for (;;) {
 
647
            //---------------------------------------------
 
648
            //  get next midi event
 
649
            //---------------------------------------------
 
650
            pthread_mutex_lock(&lock);
 
651
 
 
652
            if (events.empty()) {
 
653
                  pthread_mutex_unlock(&lock);
 
654
                  break;
 
655
                  }
 
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);
 
661
                        }
 
662
                  pthread_mutex_unlock(&lock);
 
663
                  break;
 
664
                  }
 
665
            events.erase(events.begin());
 
666
            pthread_mutex_unlock(&lock);
 
667
 
 
668
            //---------------------------------------------
 
669
            //  generate samples up to this midi event
 
670
            //---------------------------------------------
 
671
 
 
672
            int samplesToSynthesize = samplePos - offset;
 
673
 
 
674
            write(samplesToSynthesize, outputPorts, offset);
 
675
            offset += samplesToSynthesize;
 
676
            processEvent(e);
 
677
            delete e;
 
678
            }
 
679
 
 
680
      //---------------------------------------------------
 
681
      //  any samples left?
 
682
      //---------------------------------------------------
 
683
 
 
684
      int samplesToSynthesize = len - offset;
 
685
      write(samplesToSynthesize, outputPorts, offset);
 
686
      }
 
687
 
 
688
//---------------------------------------------------------
 
689
//   MessMono
 
690
//---------------------------------------------------------
 
691
 
 
692
MessMono::MessMono(const char* name, int channels)
 
693
   : Mess(name, channels)
 
694
      {
 
695
      }
 
696
 
 
697
MessMono::~MessMono()
 
698
      {
 
699
      }
 
700
 
 
701
//---------------------------------------------------------
 
702
//   midiNoteOn
 
703
//---------------------------------------------------------
 
704
 
 
705
void MessMono::midiNoteOn(int channel, int pitch, int velo)
 
706
      {
 
707
      if (velo == 0) {
 
708
            midiNoteOff(channel, pitch);
 
709
            return;
 
710
            }
 
711
      pitchStack.push_back(PitchVelo(channel, pitch, velo));
 
712
      noteon(channel, pitch, velo);
 
713
      }
 
714
 
 
715
//---------------------------------------------------------
 
716
//   midiNoteOff
 
717
//---------------------------------------------------------
 
718
 
 
719
void MessMono::midiNoteOff(int channel, int pitch)
 
720
      {
 
721
      if (pitchStack.empty())
 
722
            return;
 
723
      if (pitchStack.back().pitch == pitch) {
 
724
            pitchStack.pop_back();
 
725
            if (pitchStack.empty()) {
 
726
                  noteoff(channel, pitch);
 
727
                  return;
 
728
                  }
 
729
            PitchVelo pv = pitchStack.back();
 
730
            noteon(pv.channel, pv.pitch, pv.velo);  // change pitch
 
731
            return;
 
732
            }
 
733
      for (std::list<PitchVelo>::iterator i = pitchStack.begin();
 
734
         i != pitchStack.end(); ++i) {
 
735
            if ((*i).pitch == pitch) {
 
736
                  pitchStack.erase(i);
 
737
                  return;
 
738
                  }
 
739
            }
 
740
      // no noteon found
 
741
      // emergency stop:
 
742
      noteoff(channel, pitch);
 
743
      }
 
744
 
 
745
//---------------------------------------------------------
 
746
//   processEvents
 
747
//    process received midi event
 
748
//---------------------------------------------------------
 
749
 
 
750
void MessMono::processEvent(MEvent* ev)
 
751
      {
 
752
      switch(ev->type()) {
 
753
            case SND_SEQ_EVENT_NOTEON:
 
754
            case SND_SEQ_EVENT_KEYPRESS:
 
755
                  midiNoteOn(ev->chan(), ev->dataA(), ev->dataB());
 
756
                  break;
 
757
 
 
758
            case SND_SEQ_EVENT_NOTEOFF:
 
759
                  midiNoteOff(ev->chan(), ev->dataA());
 
760
                  break;
 
761
 
 
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;
 
771
                        }
 
772
                        if(ev->dataA() == 0x06)
 
773
                                setController(ev->chan(), ctrlLo+ctrlHi*128, dataLo+dataHi*128);
 
774
                        break;
 
775
 
 
776
                case SND_SEQ_EVENT_SYSEX:
 
777
                        sysex(ev->data(), ev->dataLen());
 
778
                        break;
 
779
            case SND_SEQ_EVENT_CHANPRESS:
 
780
            case SND_SEQ_EVENT_PITCHBEND:
 
781
            case SND_SEQ_EVENT_PGMCHANGE:
 
782
                  break;
 
783
            default:
 
784
                  printf("MessMono: event type %d not processed\n", ev->type());
 
785
                  break;
 
786
            }
 
787
      }
 
788
 
 
789
//=========================================================
 
790
//    LADSPA
 
791
//=========================================================
 
792
 
 
793
static Mess* (*xinstantiate)(const char* name);
 
794
 
 
795
//---------------------------------------------------------
 
796
//   instantiate
 
797
//    construct a new synthesizer instance
 
798
//---------------------------------------------------------
 
799
 
 
800
static LADSPA_Handle instantiate(const LADSPA_Descriptor* descr, unsigned long sr)
 
801
      {
 
802
      Mess* synth = xinstantiate(descr->Label);
 
803
      synth->setSampleRate(sr);
 
804
      if (synth->init()) {
 
805
            delete synth;
 
806
            synth = 0;
 
807
            }
 
808
      return synth;
 
809
      }
 
810
 
 
811
//---------------------------------------------------------
 
812
//   run
 
813
//---------------------------------------------------------
 
814
 
 
815
static void run(LADSPA_Handle instance, unsigned long sampleCount)
 
816
      {
 
817
      ((Mess *)instance)->processreplace(sampleCount);
 
818
      }
 
819
 
 
820
//---------------------------------------------------------
 
821
//   connectPort
 
822
//    Connect a port to a data location.
 
823
//---------------------------------------------------------
 
824
 
 
825
static void connect(LADSPA_Handle Instance, unsigned long port, float* data)
 
826
      {
 
827
      ((Mess *)Instance)->setPort(port, data);
 
828
      }
 
829
 
 
830
//---------------------------------------------------------
 
831
//   activate
 
832
//---------------------------------------------------------
 
833
 
 
834
static void activate(LADSPA_Handle instance)
 
835
      {
 
836
      ((Mess *)instance)->init();
 
837
      ((Mess *)instance)->registerAlsa();
 
838
      }
 
839
 
 
840
//---------------------------------------------------------
 
841
//   cleanup
 
842
//---------------------------------------------------------
 
843
 
 
844
static void cleanup(LADSPA_Handle instance)
 
845
      {
 
846
      delete (Mess *)instance;
 
847
      }
 
848
 
 
849
//---------------------------------------------------------
 
850
//   portNames
 
851
//---------------------------------------------------------
 
852
 
 
853
static const char* portNames[] = {
 
854
      "Output",
 
855
      "Output",
 
856
      };
 
857
 
 
858
//---------------------------------------------------------
 
859
//   portDescriptors
 
860
//---------------------------------------------------------
 
861
 
 
862
static LADSPA_PortDescriptor portDescriptors[] = {
 
863
      LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
 
864
      LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
 
865
      };
 
866
 
 
867
//---------------------------------------------------------
 
868
//   portRangeHints
 
869
//---------------------------------------------------------
 
870
 
 
871
static LADSPA_PortRangeHint portRangeHints[] = {
 
872
      { 0, 0.0, 0.0 },
 
873
      { 0, 0.0, 0.0 },
 
874
      };
 
875
 
 
876
static LADSPA_Descriptor descriptor = {
 
877
      1223,
 
878
      "label",
 
879
      LADSPA_PROPERTY_HARD_RT_CAPABLE,
 
880
      "name",
 
881
      "maker",
 
882
      "copyright",
 
883
      1,
 
884
      portDescriptors,
 
885
      portNames,
 
886
      portRangeHints,
 
887
      0,                // impl. data
 
888
      instantiate,
 
889
      connect,
 
890
      activate,
 
891
      run,
 
892
      0,
 
893
      0,
 
894
      0,
 
895
      cleanup
 
896
      };
 
897
 
 
898
//---------------------------------------------------------
 
899
//   ladspa_descriptor
 
900
//    Return a descriptor of the requested plugin type.
 
901
//---------------------------------------------------------
 
902
 
 
903
const LADSPA_Descriptor* ladspa_descriptor(unsigned long i)
 
904
      {
 
905
      __init();         // create ladspa descritpor
 
906
      return (i == 0) ? &descriptor : 0;
 
907
      }
 
908
 
 
909
//---------------------------------------------------------
 
910
//   initMess
 
911
//    ports  -  1-Mono  2-Stereo
 
912
//---------------------------------------------------------
 
913
 
 
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*))
 
917
      {
 
918
      descriptor.UniqueID  = id;
 
919
      descriptor.Label     = label;
 
920
      descriptor.Name      = name;
 
921
      descriptor.Maker     = maker;
 
922
      descriptor.Copyright = copyright;
 
923
      descriptor.PortCount = ports;
 
924
      xinstantiate          = inst;
 
925
      }
 
926