~ubuntu-branches/ubuntu/breezy/muse/breezy

« back to all changes in this revision

Viewing changes to driver/mess.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Kobras
  • Date: 2004-02-07 15:18:22 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040207151822-es27xxkzbcxkebjm
Tags: 0.6.3-1
* New upstream version.
* Added patches:
  + [10_alsa_init_fix] New, from upstream CVS.
    Initialize direction variable when setting Alsa parameters.
  + [10_canvas_translation_fix] New, from upstream CVS.
    Do not translate tooltips twice in canvas popup.
  + [10_checkbox_fix] New, from upstream CVS.
    Use proper set/test methods on metronome checkboxes.
  + [10_html_doc_cleanup] New.
    Fix links and HTML errors in documentation.
  + [20_allow_system_timer] New.
    The new upstream version fails by default if the real-time clock
    could not be accessed (usually the case when not running suid-root).
    This patch reverts the old behaviour of falling back to the more
    inaccurate system timer.
* Updated patches:
  + [11_PIC_fixes_fixup] Rediffed.
* Removed patches:
  + [20_no_atomic_asm] Merged upstream.
* debian/compat: Splice out debhelper compatibility level from rules file.
* debian/control: Build-depend on latest jack release by default.
  Closes: #228788
* debian/control: Bump standards version.
* debian/control: Use auto-generated debconf dependency via misc:Depends.
* debian/control: Minor tweaks to the long description.
* debian/control: Tighten fluidsynth build dependency to sane version.
* debian/muse.doc-base: New. Register HTML documentation with doc-base.
* debian/templates: Tiny rewording, and typo fix.
* debian/templates, debian/po/*: Switch to po-debconf for translations.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
//=========================================================
2
2
//  MusE
3
3
//  Linux Music Editor
4
 
//    $Id: mess.cpp,v 1.6 2002/02/27 08:48:09 muse Exp $
 
4
//    $Id: mess.cpp,v 1.1.1.1 2003/10/29 10:06:11 wschweer Exp $
5
5
//  (C) Copyright 2001 Werner Schweer (ws@seh.de)
6
6
//=========================================================
7
7
 
14
14
#include <sys/time.h>
15
15
#include <errno.h>
16
16
#include <unistd.h>
 
17
#include <cmath>
17
18
 
18
19
#include "ladspa.h"
19
20
 
20
 
extern void __init();
21
 
 
 
21
extern void initMess();
 
22
 
 
23
#ifdef RTCAP
 
24
//---------------------------------------------------------
 
25
//   getCapabilities
 
26
//---------------------------------------------------------
 
27
 
 
28
void getCapabilities()
 
29
      {
 
30
#ifdef __linux__
 
31
      const char* napp = getenv("GIVERTCAP");
 
32
      system(napp ? napp : "givertcap");
 
33
#endif // __linux__
 
34
      }
 
35
#endif
22
36
 
23
37
//---------------------------------------------------------
24
38
//   doSetuid
25
39
//    Restore the effective UID to its original value.
26
40
//---------------------------------------------------------
27
41
 
 
42
#ifdef _POSIX_SAVED_IDS
 
43
static void doSetuid(uid_t euid, uid_t)
 
44
#else
28
45
static void doSetuid(uid_t euid, uid_t ruid)
 
46
#endif
29
47
      {
 
48
#ifdef RTCAP
 
49
      extern void getCapabilities();
 
50
      getCapabilities();
 
51
#else
30
52
      int status;
31
53
 
32
54
#ifdef _POSIX_SAVED_IDS
35
57
      status = setreuid (ruid, euid);
36
58
#endif
37
59
      if (status < 0) {
38
 
            fprintf(stderr, "Couldn't set uid.\n");
 
60
            perror("doSetuid: Couldn't set uid.\n");
39
61
            }
 
62
#endif
40
63
      }
41
64
 
42
65
//---------------------------------------------------------
46
69
 
47
70
static void undoSetuid(uid_t euid, uid_t ruid)
48
71
      {
 
72
#ifndef RTCAP
49
73
      int status;
50
74
 
51
75
#ifdef _POSIX_SAVED_IDS
54
78
      status = setreuid (euid, ruid);
55
79
#endif
56
80
      if (status < 0) {
57
 
            fprintf (stderr, "Couldn't set uid.\n");
 
81
            fprintf(stderr, "undoSetuid: Couldn't set uid (eff:%d,real:%d): %s\n",
 
82
               euid, ruid, strerror(errno));
58
83
            exit (status);
59
84
            }
 
85
#endif
60
86
      }
61
87
 
62
88
//---------------------------------------------------------
66
92
static double curTime()
67
93
      {
68
94
      struct timeval t;
69
 
      struct timezone tz;
70
 
      gettimeofday(&t, &tz);
 
95
      gettimeofday(&t, 0);
71
96
      return (double)((double)t.tv_sec + (t.tv_usec / 1000000.0));
72
97
      }
73
98
 
82
107
      pthread_exit(0);
83
108
      }
84
109
 
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
110
//---------------------------------------------------------
100
111
//   midiRun
101
112
//---------------------------------------------------------
102
113
 
103
114
void Mess::midiRun()
104
115
      {
105
 
#ifdef RTCAP
106
 
      extern void getCapabilities();
107
 
      getCapabilities();
108
 
#else
109
 
      doSetuid(euid, ruid);
110
 
#endif
111
 
      struct sched_param sp;
 
116
#define BIG_ENOUGH_STACK (1024*1024*1)
 
117
      char buf[BIG_ENOUGH_STACK];
 
118
      for (int i = 0; i < BIG_ENOUGH_STACK; i++)
 
119
            buf[i] = i;
 
120
#undef BIG_ENOUGH_STACK
 
121
 
112
122
      pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
113
123
      pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
114
124
 
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
 
125
      int policy;
 
126
      if ((policy = sched_getscheduler (0)) < 0) {
 
127
            printf("Cannot get current client scheduler: %s\n", strerror(errno));
 
128
            }
 
129
 
 
130
      printf("Mess: MidiThread set to %s priority 60\n",
 
131
         policy == SCHED_FIFO ? "SCHED_FIFO" : "SCHED_OTHER");
 
132
 
 
133
      pthread_mutex_lock(&messLock);
 
134
      pthread_cond_signal(&messReady);
 
135
      pthread_mutex_unlock(&messLock);
129
136
 
130
137
      MEvent* ev;
131
138
      for (;;) {
132
139
            int n = poll(pfd, npfd, -1);  // wait infinite for event
133
 
            if (n <= 0)
 
140
            if (n < 0) {
 
141
                  perror("MusE Mess: poll failed");
 
142
                  break;
 
143
                  }
 
144
            if (n == 0) {
 
145
                  fprintf(stderr, "MusE: Mess: poll return zero\n");
 
146
                  sleep(1);
134
147
                  continue;
 
148
                  }
135
149
            for(;;) {
136
150
                  snd_seq_event_t* event;
137
151
                  int rv = snd_seq_event_input(alsaSeq, &event);
145
159
                  if (event->type == SND_SEQ_EVENT_PORT_START)
146
160
                        continue;
147
161
 
148
 
                  unsigned pos = int ((curTime() - frame) * _sampleRate);
 
162
                  unsigned pos = lrint((curTime() - frame) * _sampleRate);
149
163
 
150
164
                  ev = 0;
151
165
                  switch(event->type) {
152
166
//                        case SND_SEQ_EVENT_PORT_START:
153
167
                        case SND_SEQ_EVENT_PORT_EXIT:
 
168
                        case SND_SEQ_EVENT_PORT_SUBSCRIBED:
154
169
                              break;
155
170
 
156
171
                        case SND_SEQ_EVENT_NOTEON:
157
172
                        case SND_SEQ_EVENT_KEYPRESS:
158
173
                        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);
 
174
                              ev = allocMEvent();
 
175
                              ev->setSamplePos(pos);
 
176
                              ev->setType(event->type);
 
177
                              ev->setChan(event->data.note.channel);
 
178
                              ev->setDataA(event->data.note.note);
 
179
                              ev->setDataB(event->data.note.velocity);
163
180
                              break;
164
181
 
165
182
                        case SND_SEQ_EVENT_CONTROL14:
168
185
                        case SND_SEQ_EVENT_CONTROLLER:
169
186
                        case SND_SEQ_EVENT_PGMCHANGE:
170
187
                        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);
 
188
                              ev = allocMEvent();
 
189
                              ev->setSamplePos(pos);
 
190
                              ev->setType(event->type);
 
191
                              ev->setChan(event->data.control.channel);
 
192
                              ev->setDataA(event->data.control.param);
 
193
                              ev->setDataB(event->data.control.value);
175
194
                              break;
176
195
 
177
196
 
178
197
                        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);
 
198
                              ev = allocMEvent();
 
199
                              ev->setSamplePos(pos);
 
200
                              ev->setType(event->type);
 
201
                              ev->setChan(event->data.control.channel);
 
202
                              ev->setDataA((event->data.control.value >> 7) & 0x7f);
 
203
                              ev->setDataB(event->data.control.value & 0x7f);
183
204
                              break;
184
205
 
185
206
                        case SND_SEQ_EVENT_SYSEX:
187
208
                              int len = event->data.ext.len;
188
209
                              unsigned char* data = new unsigned char[len];
189
210
                              memcpy(data, event->data.ext.ptr, len);
190
 
                              ev = new MEvent(pos, event->type, 0, 0, 0, data, len);
 
211
                              ev = allocMEvent();
 
212
                              ev->setSamplePos(pos);
 
213
                              ev->setType(event->type);
 
214
                              ev->setData(data);
 
215
                              ev->setDataLen(len);
191
216
                              }
192
217
                              break;
193
218
 
219
244
Mess::Mess(const char* cn, int chn)
220
245
   : _className(strdup(cn))
221
246
      {
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;
 
247
      realTimePriority = 60;
 
248
      head             = 0;
 
249
      chunks           = 0;
 
250
      _channels        = chn;
 
251
      outputPorts      = new float*[_channels];
 
252
      _name            = 0;
 
253
      alsaSeq          = 0;
 
254
      pfd              = 0;
 
255
      npfd             = 0;
 
256
      startFrame       = 0.0;
 
257
      _sampleRate      = 44100;          // default
230
258
      pthread_mutex_init(&lock, 0);
 
259
      pthread_mutex_init(&messLock, 0);
 
260
      pthread_cond_init(&messReady, 0);
231
261
      }
232
262
 
233
263
//---------------------------------------------------------
234
264
//   Mess
235
265
//---------------------------------------------------------
236
266
 
237
 
#if (SND_LIB_MAJOR==0) && (SND_LIB_MINOR==9)
238
267
Mess::~Mess()
239
268
      {
 
269
      pthread_cancel(midiThread);
 
270
      pthread_join(midiThread, 0);
 
271
      pthread_mutex_destroy(&lock);
 
272
      pthread_mutex_destroy(&messLock);
 
273
 
 
274
      Chunk* n = chunks;
 
275
      while (n) {
 
276
            Chunk* p = n;
 
277
            n = n->next;
 
278
            delete p;
 
279
            }
 
280
 
240
281
      delete[] outputPorts;
241
282
      if (_name)
242
283
            delete _name;
243
284
      if (_className)
244
285
            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);
 
286
      if (!alsaSeq) {
 
287
            printf("~Mess(): no seq!\n");
 
288
            return;
 
289
            }
 
290
      int error = snd_seq_delete_port(alsaSeq, _alsaPort.port);
 
291
      if (error) {
 
292
            fprintf(stderr, "ALSA: cannot delete port: %s\n",
 
293
               snd_strerror(error));
 
294
            }
 
295
      // why does this not remove client from client table?:
 
296
      error = snd_seq_close(alsaSeq);
 
297
      if (error) {
 
298
            fprintf(stderr, "ALSA: cannot close seq: %s\n",
 
299
               snd_strerror(error));
 
300
            }
 
301
      }
 
302
 
 
303
//---------------------------------------------------------
 
304
//   grow
 
305
//---------------------------------------------------------
 
306
 
 
307
void Mess::grow()
 
308
      {
 
309
      Chunk* n = new Chunk;
 
310
      n->next  = chunks;
 
311
      chunks   = n;
 
312
 
 
313
      char* start = n->mem;
 
314
      char* last  = &start[(nelem-1)*sizeof(MEvent)];
 
315
 
 
316
      for (char* p = start; p < last; p += sizeof(MEvent)) {
 
317
            reinterpret_cast<Verweis*>(p)->next
 
318
              = reinterpret_cast<Verweis*>(p + sizeof(MEvent));
 
319
            }
 
320
      reinterpret_cast<Verweis*>(last)->next = 0;
 
321
      head = reinterpret_cast<Verweis*>(start);
298
322
      }
299
323
 
300
324
//---------------------------------------------------------
301
325
//   registerAlsa
302
326
//---------------------------------------------------------
303
327
 
304
 
#if (SND_LIB_MAJOR==0) && (SND_LIB_MINOR==9)
305
328
void Mess::registerAlsa()
306
329
      {
307
330
      //-----------------------------------------
312
335
      if (alsaSeq == 0) {
313
336
            int error = snd_seq_open(&alsaSeq, "hw", SND_SEQ_OPEN_DUPLEX|SND_SEQ_NONBLOCK, 0);
314
337
            if (error < 0) {
315
 
                  fprintf(stderr, "Could not open ALSA sequencer: %s\n",
 
338
                  fprintf(stderr, "Mess: Could not open ALSA sequencer: %s\n",
316
339
                     snd_strerror(error));
317
340
                  alsaSeq = 0;
318
341
                  return;
330
353
 
331
354
      //-----------------------------------------
332
355
      //  find an unused alsa port name
 
356
      //  find muse port
333
357
      //-----------------------------------------
334
358
 
 
359
      bool museFound = false;
335
360
      char buffer[256];
336
361
      for (int i = 1;; ++i) {
337
362
            bool found = false;
338
363
            sprintf(buffer, "%s-%d", _className, i);
339
364
 
340
365
            snd_seq_client_info_t* cinfo;
341
 
#ifdef snd_seq_client_info_alloca
342
366
            snd_seq_client_info_alloca(&cinfo);
343
367
            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
368
            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
369
                  snd_seq_port_info_t *pinfo;
355
 
#ifdef snd_seq_port_info_alloca
356
370
                  snd_seq_port_info_alloca(&pinfo);
357
371
                  snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
358
372
                  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
373
                  while (snd_seq_query_next_port(alsaSeq, pinfo) >= 0) {
366
374
                        const char* portname;
367
 
#ifdef snd_seq_port_info_alloca
368
375
                        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
 
376
                        if (strcmp(portname, buffer) == 0) {
 
377
                              found = true;
 
378
                              break;
 
379
                              }
 
380
                        if (strcmp(portname, "MusE Port 0") == 0) {
 
381
                              museFound = true;
 
382
                              snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
 
383
                              _musePort.port   = snd_seq_port_info_get_port(pinfo);
 
384
                              _musePort.client = snd_seq_client_info_get_client(cinfo);
 
385
                              }
 
386
                        }
 
387
                  if (found)
 
388
                        break;
 
389
                  }
 
390
            if (!found)
 
391
                  break;
 
392
            }
 
393
      if (!museFound) {
 
394
            printf("Mess: muse port not found!\n");
 
395
            return;
 
396
            }
 
397
      _name = strdup(buffer);
 
398
 
 
399
      //-----------------------------------------
 
400
      //    create port to alsa sequencer
 
401
      //-----------------------------------------
 
402
 
 
403
      int port  = snd_seq_create_simple_port(alsaSeq, _name,
 
404
         SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE,
 
405
         SND_SEQ_PORT_TYPE_APPLICATION);
 
406
      if (port < 0) {
 
407
            perror("create port");
 
408
            return;
 
409
            }
 
410
      _alsaPort.port   = port;
 
411
      _alsaPort.client = snd_seq_client_id(alsaSeq);
 
412
 
 
413
      //----------------------------------------------
 
414
      // create the midi thread
 
415
      // with SCHED_FIFO and priority 60
 
416
 
 
417
      pthread_attr_t* attributes = 0;
 
418
      doSetuid(euid, ruid);
 
419
      if (realTimePriority) {
 
420
            struct sched_param rt_param;
 
421
            memset(&rt_param, 0, sizeof(rt_param));
 
422
            rt_param.sched_priority = 60;
 
423
 
 
424
            attributes = new pthread_attr_t;
 
425
            pthread_attr_init(attributes);
 
426
 
 
427
            if (pthread_attr_setschedpolicy(attributes, SCHED_FIFO)) {
 
428
                  printf("Mess: cannot set FIFO scheduling class for RT thread\n");
 
429
                  }
 
430
            if (pthread_attr_setschedparam(attributes, &rt_param)) {
 
431
                  printf("Mess: Cannot set scheduling priority for RT thread (%s)\n", strerror(errno));
 
432
                  }
 
433
            if (pthread_attr_setscope(attributes, PTHREAD_SCOPE_SYSTEM)) {
 
434
                  printf("Mess: Cannot set scheduling scope for RT thread\n");
 
435
                  }
 
436
            }
 
437
      pthread_mutex_lock(&messLock);
 
438
 
 
439
      int err = pthread_create(&midiThread, attributes, midi_run, this);
 
440
 
 
441
      if (err) {
 
442
            printf("Mess: Couldn't create midi thread: %s\n",
 
443
               strerror(errno));
 
444
      } else
 
445
              pthread_cond_wait(&messReady, &messLock);
 
446
      pthread_mutex_unlock(&messLock);
 
447
 
 
448
      if (attributes) {
 
449
            pthread_attr_destroy(attributes);
 
450
            delete attributes;
 
451
            }
 
452
      undoSetuid(euid, ruid);
 
453
      }
576
454
 
577
455
//---------------------------------------------------------
578
456
//   getPatchName
610
488
      pp += n;
611
489
      *pp = 0xf7;
612
490
 
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
491
      int error = snd_seq_event_output_direct(alsaSeq, &event);
622
492
      if (error < 0)
623
 
            fprintf(stderr, "sysex: midi write error: %s\n", snd_strerror(error));
624
 
#endif
625
 
      delete buf;
 
493
            fprintf(stderr, "sysex: src:%d:%d-dst:%d:%d midi write error (n=%d): %s\n",
 
494
                _alsaPort.port, _alsaPort.client, _musePort.port, _musePort.client,
 
495
                n, snd_strerror(error));
 
496
      delete[] buf;
626
497
      }
627
498
 
628
499
//---------------------------------------------------------
635
506
      startFrame = curTime();
636
507
      pthread_mutex_unlock(&lock);
637
508
 
638
 
      int offset = 0;
639
509
      for (int channel = 0; channel < _channels; ++channel)
640
510
            memset(outputPorts[channel], 0, len * sizeof(float));
641
511
 
 
512
      int offset = 0;
 
513
 
642
514
      //---------------------------------------------------
643
515
      //  process all midi events for this buffer
644
516
      //---------------------------------------------------
655
527
                  }
656
528
            MEvent* e = events.front();
657
529
            int samplePos = e->samplePos();
 
530
            if (samplePos < 0)                  // ???
 
531
                  samplePos = 0;
658
532
            if (samplePos >= len) {
 
533
                  samplePos %= len;
659
534
                  for (iMEvent i = events.begin(); i != events.end(); ++i) {
660
535
                        (*i)->adjustSamplePos(len);
661
536
                        }
671
546
 
672
547
            int samplesToSynthesize = samplePos - offset;
673
548
 
 
549
// printf("write %d %d  %d\n", samplesToSynthesize, offset, samplePos);
674
550
            write(samplesToSynthesize, outputPorts, offset);
675
551
            offset += samplesToSynthesize;
676
552
            processEvent(e);
677
 
            delete e;
 
553
            freeMEvent(e);
678
554
            }
679
555
 
680
556
      //---------------------------------------------------
682
558
      //---------------------------------------------------
683
559
 
684
560
      int samplesToSynthesize = len - offset;
685
 
      write(samplesToSynthesize, outputPorts, offset);
 
561
      if (samplesToSynthesize > 0) {
 
562
// printf("write %d %d\n", samplesToSynthesize, offset);
 
563
            write(samplesToSynthesize, outputPorts, offset);
 
564
            }
686
565
      }
687
566
 
688
567
//---------------------------------------------------------
833
712
 
834
713
static void activate(LADSPA_Handle instance)
835
714
      {
836
 
      ((Mess *)instance)->init();
837
715
      ((Mess *)instance)->registerAlsa();
838
716
      }
839
717
 
902
780
 
903
781
const LADSPA_Descriptor* ladspa_descriptor(unsigned long i)
904
782
      {
905
 
      __init();         // create ladspa descritpor
 
783
      initMess();         // create ladspa descriptor
906
784
      return (i == 0) ? &descriptor : 0;
907
785
      }
908
786
 
921
799
      descriptor.Maker     = maker;
922
800
      descriptor.Copyright = copyright;
923
801
      descriptor.PortCount = ports;
924
 
      xinstantiate          = inst;
 
802
      xinstantiate         = inst;
925
803
      }
926
804