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

« back to all changes in this revision

Viewing changes to synti/synth.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: synth.cpp,v 1.8 2002/02/27 08:48:09 muse Exp $
 
4
//    $Id: synth.cpp,v 1.1.1.1 2003/10/29 10:06:00 wschweer Exp $
5
5
//  (C) Copyright 2000 Werner Schweer (ws@seh.de)
6
6
//=========================================================
7
7
 
8
8
#include <qdir.h>
9
9
#include <dlfcn.h>
 
10
#include <qpopupmenu.h>
 
11
 
10
12
#include "app.h"
11
13
#include "synth.h"
12
14
#include "xml.h"
15
17
#include "mess.h"
16
18
#include "ladspa.h"
17
19
#include "song.h"
18
 
#include "audiothread.h"
 
20
#include "audio.h"
19
21
#include "event.h"
 
22
#include "mpevent.h"
20
23
#include "midithread.h"
21
24
#include <sys/mman.h>
22
25
 
30
33
Synth** synthis;              // static array of available synthis
31
34
SynthIList synthiInstances;  // this list is owned by seq thread
32
35
 
 
36
extern void connectNodes(AudioNode*, AudioNode*);
 
37
 
33
38
//---------------------------------------------------------
34
39
//   SynthI
35
40
//---------------------------------------------------------
37
42
SynthI::SynthI(Synth* s)
38
43
   : synthesizer(s)
39
44
      {
40
 
      _mdev    = 0;
41
 
      _mess    = (Mess*)synthesizer->instantiate();
 
45
      _mdev       = 0;
 
46
      _mess       = (Mess*)synthesizer->instantiate();
42
47
      _mess->euid = euid;
43
48
      _mess->ruid = ruid;
 
49
      if (! realTimeScheduling)
 
50
              _mess->realTimePriority = 0;
44
51
      synthesizer->activate(_mess);
45
 
      _name    = _mess->name();
 
52
      setIName(QString(_mess->name()));
46
53
      _gui     = false;
47
54
      _readFd  = -1;
48
55
      _writeFd = -1;
49
56
      setVolume(1.0);
50
57
      setPan(0.0);
51
 
      setRoute(song->master());
52
 
      AudioNode::setChannels(s->channels());
 
58
      AudioNode::setPorts(s->channels());
 
59
      connectOut(&audioOutput);       // default: connect to master
53
60
      printf("create Synth instance <%s> channels %d %d\n",
54
 
         _name.latin1(), s->channels(), channels());
 
61
         iname().latin1(), s->channels(), ports());
55
62
      }
56
63
 
57
64
SynthI::~SynthI()
68
75
 
69
76
void SynthI::sysexReceived(const unsigned char* p, int n)
70
77
      {
71
 
// printf("FROM GUI: sysex %p\n", _mdev);
72
78
      if (!_mdev)
73
79
            return;
74
 
      MidiEvent* event = new MidiEvent(_mdev->port()|0x100, 0, 0,
75
 
         MidiEvent::Sysex, n, p);
76
 
      midiThread->eventReceived(event);
77
 
      _mdev->putEvent(event);     // echo to softSynth
78
 
      delete event;
 
80
      MidiPlayEvent event(_mdev->port()|0x100, p, n);
 
81
      midiThread->eventReceived(&event);
 
82
      _mdev->putEvent(&event);     // echo to softSynth
79
83
      }
80
84
 
81
85
//---------------------------------------------------------
86
90
 
87
91
void SynthI::eventReceived(int a, int b, int c)
88
92
      {
89
 
//      printf("FROM GUI mdev %p\n", _mdev);
90
93
      if (_mdev == 0)
91
94
            return;
92
 
      midiThread->eventReceived(_mdev->port()|0x100, a, b, c);
 
95
      midiThread->eventReceived(_mdev->port()|0x80, a, b, c);
93
96
      switch(a & 0xf0) {
94
97
            case 0xb0:
95
98
                  {
96
 
                  MidiEvent event(0, 0, 0, MidiEvent::Ctrl7,
97
 
                    b, c, 0, 0);
 
99
                  MidiPlayEvent event(0, 0, 0xb0, b, c);
98
100
                  _mdev->putEvent(&event);   // echo to softSynth
99
101
                  }
100
102
                  break;
106
108
 
107
109
//---------------------------------------------------------
108
110
//   showGui
109
 
//    execution context: midiThread
 
111
//    execution context: midithread
110
112
//---------------------------------------------------------
111
113
 
112
114
void SynthI::showGui(bool f)
156
158
                        return;
157
159
                        }
158
160
                  }
 
161
 
159
162
            int rfiledes[2];
160
163
            int wfiledes[2];
161
164
            int rv = pipe(rfiledes);
168
171
                  printf("pipe failed\n");
169
172
                  return;
170
173
                  }
171
 
 
172
174
            _guiPid = fork();
173
175
            if (_guiPid == 0) {       // Child side
174
176
                  dup2(rfiledes[1], 1);    // connect stdout to pipe
177
179
                  dup2(wfiledes[0], 0);    // connect stdin to pipe
178
180
                  close(wfiledes[0]);
179
181
                  close(wfiledes[1]);
180
 
                  const char* const new_argv[3] = {
 
182
 
 
183
                  for (int i = 3; i < 50; ++i)
 
184
                        close(i);
 
185
                  const char* const new_argv[4] = {
181
186
                        classname,
182
187
                        instname,
 
188
                        museProject.latin1(),
183
189
                        0
184
190
                        };
 
191
 
185
192
                  // Restore the signals
186
193
                  sigaction (SIGINT, &intr, 0);
187
194
                  sigaction (SIGQUIT, &quit, 0);
194
201
                  //    c) gui does not run uid root
195
202
 
196
203
                  struct sched_param sp;
197
 
                  sp.sched_priority = 0;
 
204
                  memset(&sp, 0, sizeof(sp));
 
205
                  // sp.sched_priority = 0;
198
206
                    sched_setscheduler(0, SCHED_OTHER, &sp);
199
207
                  munlockall();
200
208
                  setuid(getuid());
206
214
                  ;
207
215
            _readFd  = rfiledes[0];
208
216
            _writeFd = wfiledes[1];
 
217
 
209
218
            if ((sigaction (SIGINT, &intr, 0)
210
219
               | sigaction (SIGQUIT, &quit, 0)
211
220
               | sigprocmask (SIG_SETMASK, &omask, 0)) != 0) {
230
239
 
231
240
//---------------------------------------------------------
232
241
//   getData
 
242
//    - connect LADSPA ports
 
243
//    - run LADSPA ports
233
244
//---------------------------------------------------------
234
245
 
235
 
void SynthI::getData(float* buffer, int /*idx*/)
 
246
bool SynthI::getData(int ports, unsigned long nframes, float** buffer)
236
247
      {
237
 
      for (int i = 0; i < channels(); ++i) {
238
 
            synthesizer->connect((LADSPA_Handle*)_mess, i,
239
 
               buffer + segmentSize * i);
240
 
            }
241
 
      synthesizer->run((LADSPA_Handle*)_mess, segmentSize);
 
248
      for (int i = 0; i < ports; ++i)
 
249
            synthesizer->connect((LADSPA_Handle*)_mess, i, buffer[i]);
 
250
      synthesizer->run((LADSPA_Handle*)_mess, nframes);
 
251
      return true;
242
252
      }
243
253
 
244
254
//---------------------------------------------------------
248
258
 
249
259
static bool addSynthi(QFileInfo* fi, int idx)
250
260
      {
251
 
      void* handle = dlopen(fi->filePath().data(), RTLD_NOW);
252
 
//      void* handle = dlopen(fi->filePath().data(), RTLD_LAZY);
 
261
      void* handle = dlopen(fi->filePath().ascii(), RTLD_NOW);
253
262
      if (handle == 0) {
254
263
            fprintf(stderr, "addSynthi: dlopen(%s) failed: %s\n",
255
 
               fi->filePath().data(), dlerror());
 
264
               fi->filePath().ascii(), dlerror());
256
265
            return false;
257
266
            }
258
267
      LADSPA_Descriptor_Function ladspa = (LADSPA_Descriptor_Function)dlsym(handle, "ladspa_descriptor");
264
273
                     "Unable to find ladspa_descriptor() function in plugin "
265
274
                     "library file \"%s\": %s.\n"
266
275
                     "Are you sure this is a LADSPA plugin file?\n",
267
 
                     fi->filePath().data(), txt);
 
276
                     fi->filePath().ascii(), txt);
268
277
                  return false;
269
278
                  }
270
279
            }
295
304
      LADSPA_Properties properties = descr->Properties;
296
305
      if (LADSPA_IS_INPLACE_BROKEN(properties)) {
297
306
              fprintf(stderr,
298
 
               "Plugin \"%s\" is not capable of in-place processing and "
 
307
               "Synti \"%s\" is not capable of in-place processing and "
299
308
               "therefore cannot be used by this program.\n",
300
309
               descr->Name);
301
310
            return false;
302
311
            }
303
 
      printf("found soft synth <%s> <%s>\n", descr->Label, descr->Name);
 
312
      if (debugMsg)
 
313
            printf("found soft synth <%s> <%s>\n", descr->Label, descr->Name);
304
314
      synthis[idx] = new Synth(fi, ladspa, descr);
305
315
      return true;
306
316
      }
316
326
 
317
327
      if (!alsaFound)
318
328
            return;
319
 
      QDir pluginDir(s, "*.so", QDir::Files);
320
 
printf("searching for software synthesizer in <%s>\n", s.latin1());
 
329
      QDir pluginDir(s, QString("*.so"), QDir::Files);
 
330
      if (debugMsg)
 
331
            printf("searching for software synthesizer in <%s>\n", s.latin1());
321
332
      if (pluginDir.exists()) {
322
333
            const QFileInfoList* list = pluginDir.entryInfoList();
323
334
            nsynthis = list->count();
324
 
printf("%d soft synth found\n", nsynthis);
 
335
            if (debugMsg)
 
336
                  printf("%d soft synth found\n", nsynthis);
325
337
            synthis  = new (Synth*)[nsynthis];
326
338
            QFileInfoListIterator it(*list);
327
339
            QFileInfo* fi;
437
449
                              continue;
438
450
                        }
439
451
 
440
 
                  int a = ev.dataA();
441
 
                  int b = ev.dataB();
442
452
                  unsigned char* p = ev.data();
443
453
                  xml.nput(level++, "<event type=\"%d\"", type);
444
454
                  if (p) {
452
462
                              }
453
463
                        xml.nput("\n");
454
464
                        xml.tag(level, "/event");
455
 
                        delete p;
 
465
                        delete[] p;
456
466
                        ev.setData(0);
457
467
                        }
458
468
                  else {
459
 
                        xml.put(" a=\"%d\" b=\"%d\"/>", a, b);
 
469
                        xml.put(" a=\"%d\" b=\"%d\"/>", ev.dataA(), ev.dataB());
460
470
                        }
461
471
                  --level;
462
472
                  }
531
541
                              if (synth == 0)
532
542
                                    return;
533
543
                              // synth is not yet connected:
534
 
                              audioThread->msgAddSynthI(synth);
 
544
                              audio->msgAddSynthI(synth);
535
545
                              midiThread->msgAddSynthI(synth);
 
546
                              midiThread->msgShowInstrumentGui(synth, guiVisible);
 
547
                              sleep(2);  // TODO: wait for GUI
536
548
                              if (port != -1) {
537
549
                                    EventList* el = synth->midiState();
 
550
                                    MPEventList mpl;
 
551
                                    int tick = 0;
 
552
                                    // we must use a tick to get the right
 
553
                                    // event sorting order
538
554
                                    for (iEvent i = el->begin(); i != el->end(); ++i) {
539
555
                                          MidiEvent* ev = (MidiEvent*)(i->second);
540
 
                                          ev->setPort(port);
541
 
                                          ev->setChannel(0);
542
 
                                          midiThread->playMidiEvent(ev);
543
 
                                          }
 
556
                                          mpl.add(tick, ev, port, 0);
 
557
                                          // might add more than one raw event
 
558
                                          tick += 16;
 
559
                                          }
 
560
                                    for (iMPEvent i = mpl.begin(); i != mpl.end(); ++i) {
 
561
                                          midiThread->playMidiEvent(&(i->second));
 
562
                                          synth->writeToGui(&(i->second));
 
563
                                          }
 
564
                                    mpl.clear();
544
565
                                    }
545
 
                              midiThread->msgShowInstrumentGui(synth, guiVisible);
546
566
                              return;
547
567
                              }
548
568
                  default:
572
592
      while (mp) {
573
593
            int id = ((mp->hbank & 0xff) << 16)
574
594
                      + ((mp->lbank & 0xff) << 8) + mp->prog;
575
 
            menu->insertItem(mp->name, id);
 
595
            menu->insertItem(QString(mp->name), id);
576
596
            mp = _mess->getNextPatch(ch, mp);
577
597
            }
578
598
      }
601
621
      for (ii = synthiInstances.begin(); ii != synthiInstances.end();) {
602
622
            iSynthI ni = ii;
603
623
            ++ni;
604
 
            audioThread->msgRemoveSynthI(*ii);
 
624
            audio->msgRemoveSynthI(*ii);
 
625
            delete *ii;
605
626
            ii = ni;
606
627
            }
607
 
      update();
608
628
      }
609
629
 
610
630
//---------------------------------------------------------
611
631
//   writeToGui
612
632
//---------------------------------------------------------
613
633
 
614
 
void SynthI::writeToGui(const MidiEvent* ev)
 
634
void SynthI::writeToGui(const MidiPlayEvent* e)
615
635
      {
616
636
      if (!_gui)
617
637
            return;
618
 
      switch (ev->type()) {
619
 
            case MidiEvent::Sysex:
620
 
                  {
621
 
                  int n = ev->dataLen();
622
 
                  char data[n + 2];
623
 
                  data[0]   = 0xf0;
624
 
                  data[n+1] = 0xf7;
625
 
                  memcpy(data+1, ev->data(), n);
626
 
                  int nn = write(_writeFd, data, n+2);
627
 
                  if (nn != n+2)
628
 
                        perror("write to gui failed");
629
 
                  }
630
 
                  break;
631
 
            case MidiEvent::Ctrl7:
632
 
                  {
633
 
                  char data[3];
634
 
                  data[0] = 0xb0 + ev->channel();
635
 
                  data[1] = ev->dataA();
636
 
                  data[2] = ev->dataB();
 
638
 
 
639
      int chn = e->channel();
 
640
      int a   = e->dataA();
 
641
      int b   = e->dataB();
 
642
      int typ = e->type();
 
643
 
 
644
      char data[3];
 
645
      data[0] = typ + chn;
 
646
      data[1] = a;
 
647
      data[2] = b;
 
648
 
 
649
      switch(typ) {
 
650
            case 0x90:
 
651
            case 0x80:
 
652
            case 0xb0:
 
653
            case 0xa0:
 
654
            case 0xe0:
 
655
                  {
637
656
                  int nn = write(_writeFd, data, 3);
638
657
                  if (nn != 3)
639
658
                        perror("write to gui failed");
640
659
                  }
641
660
                  break;
 
661
            case 0xc0:
 
662
            case 0xd0:
 
663
                  {
 
664
                  int nn = write(_writeFd, data, 2);
 
665
                  if (nn != 3)
 
666
                        perror("write to gui failed");
 
667
                  }
 
668
                  break;
 
669
            case 0xf0:
 
670
                  {
 
671
                  unsigned char c = 0xf0;
 
672
                  write(_writeFd, &c, 1);
 
673
                  write(_writeFd, e->data(), e->len());
 
674
                  c = 0xf7;
 
675
                  write(_writeFd, &c, 1);
 
676
                  }
 
677
                  break;
642
678
            default:
 
679
                  printf("Synti: GUI write: illegal event type %d\n", typ);
643
680
                  break;
644
681
            }
645
682
      }