~ubuntu-branches/ubuntu/oneiric/muse/oneiric

« back to all changes in this revision

Viewing changes to seq.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: seq.cpp,v 1.4 2002/02/27 15:53:45 muse Exp $
 
5
//
 
6
//  (C) Copyright 1999/2000 Werner Schweer (ws@seh.de)
 
7
//=========================================================
 
8
 
 
9
#include <stdio.h>
 
10
#include <errno.h>
 
11
 
 
12
#include <sys/time.h>
 
13
#include <sys/ioctl.h>
 
14
#include <sys/types.h>
 
15
#include <sys/time.h>
 
16
#include <sys/mman.h>
 
17
#include <assert.h>
 
18
 
 
19
#include <qtimer.h>
 
20
 
 
21
#include "seq.h"
 
22
#include <qstring.h>
 
23
#include <fcntl.h>
 
24
#include "xml.h"
 
25
#include "song.h"
 
26
#include "midi.h"
 
27
#include "device.h"
 
28
#include "globals.h"
 
29
#include "plugins/plugin.h"
 
30
#include "midictrl.h"
 
31
#include "midiport.h"
 
32
#include "audioport.h"
 
33
#include "driver/mididev.h"
 
34
#include "driver/audiodev.h"
 
35
#include "event.h"
 
36
#include "minstrument.h"
 
37
#include "audiomix.h"
 
38
#include "sf/sndfile.h"
 
39
#include "driver/alsamidi.h"
 
40
#include "synth.h"
 
41
#include "audiothread.h"
 
42
#include "audioprefetch.h"
 
43
#include "midithread.h"
 
44
 
 
45
//---------------------------------------------------------
 
46
//   Sequencer
 
47
//---------------------------------------------------------
 
48
 
 
49
Sequencer::Sequencer()
 
50
      {
 
51
      if (realTimePriority < sched_get_priority_min(SCHED_RR))
 
52
            realTimePriority = sched_get_priority_min(SCHED_RR);
 
53
      else if (realTimePriority > sched_get_priority_max(SCHED_RR))
 
54
            realTimePriority = sched_get_priority_max(SCHED_RR);
 
55
 
 
56
      midiThread = new MidiThread(realTimeScheduling,
 
57
         realTimePriority, lockMemory);
 
58
      audioThread = new AudioThread(realTimeScheduling,
 
59
         realTimePriority/3, lockMemory);
 
60
      audioPrefetch = new AudioPrefetch(realTimeScheduling,
 
61
         realTimePriority/4, lockMemory);
 
62
      }
 
63
 
 
64
//---------------------------------------------------------
 
65
//   start
 
66
//---------------------------------------------------------
 
67
 
 
68
void Sequencer::startThread()
 
69
      {
 
70
      if (!noAudio) {
 
71
            audioThread->start();
 
72
            audioPrefetch->start();
 
73
            }
 
74
      midiThread->start();
 
75
      }
 
76
 
 
77
//---------------------------------------------------------
 
78
//   stop
 
79
//---------------------------------------------------------
 
80
 
 
81
void Sequencer::stopThread()
 
82
      {
 
83
      midiThread->stop();
 
84
      if (!noAudio) {
 
85
            audioPrefetch->stop();
 
86
            audioThread->stop();
 
87
            }
 
88
      }
 
89
 
 
90
//---------------------------------------------------------
 
91
//   Sequencer
 
92
//---------------------------------------------------------
 
93
 
 
94
Sequencer::~Sequencer()
 
95
      {
 
96
      delete audioPrefetch;
 
97
      delete audioThread;
 
98
      delete midiThread;
 
99
      }
 
100
 
 
101
//---------------------------------------------------------
 
102
//   writeConfiguration
 
103
//---------------------------------------------------------
 
104
 
 
105
void Sequencer::writeConfiguration(int level, Xml& xml)
 
106
      {
 
107
      xml.tag(level++, "sequencer");
 
108
 
 
109
      xml.tag(level++, "metronom");
 
110
      xml.intTag(level, "premeasures", preMeasures);
 
111
      xml.intTag(level, "measurepitch", measureClickNote);
 
112
      xml.intTag(level, "measurevelo", measureClickVelo);
 
113
      xml.intTag(level, "beatpitch", beatClickNote);
 
114
      xml.intTag(level, "beatvelo", beatClickVelo);
 
115
      xml.intTag(level, "channel", clickChan);
 
116
      xml.intTag(level, "port", clickPort);
 
117
 
 
118
      xml.intTag(level, "precountEnable", precountEnableFlag);
 
119
      xml.intTag(level, "fromMastertrack", precountFromMastertrackFlag);
 
120
      xml.intTag(level, "signatureZ", precountSigZ);
 
121
      xml.intTag(level, "signatureN", precountSigN);
 
122
      xml.intTag(level, "prerecord", precountPrerecord);
 
123
      xml.intTag(level, "preroll", precountPreroll);
 
124
      xml.intTag(level, "midiClickEnable", midiClickFlag);
 
125
      xml.intTag(level, "audioClickEnable", audioClickFlag);
 
126
      xml.tag(level--, "/metronom");
 
127
 
 
128
      xml.intTag(level, "rcEnable",   rcEnable);
 
129
      xml.intTag(level, "rcStop",     rcStopNote);
 
130
      xml.intTag(level, "rcRecord",   rcRecordNote);
 
131
      xml.intTag(level, "rcGotoLeft", rcGotoLeftMarkNote);
 
132
      xml.intTag(level, "rcPlay",     rcPlayNote);
 
133
 
 
134
      SndFile* master = audioThread->masterMix();
 
135
      if (master) {
 
136
            SndFile* master = audioThread->masterMix();
 
137
            xml.tag(level++, "mixdown");
 
138
            xml.intTag(level, "record",     audioThread->mixdownRecord());
 
139
            xml.strTag(level, "path",       master->path().latin1());
 
140
            xml.intTag(level, "channels",   master->channels());
 
141
            xml.intTag(level, "format",     master->format());
 
142
            xml.intTag(level, "samplebits", master->sampleBits());
 
143
            xml.etag(level--, "mixdown");
 
144
            }
 
145
 
 
146
      for (int i = 0; i < MIDI_PORTS; ++i) {
 
147
            MidiPort* mport = &midiPorts[i];
 
148
            MidiDevice* dev = mport->device();
 
149
            if (dev) {
 
150
                  xml.tag(level++, "midiport idx=\"%d\"", i);
 
151
                  xml.strTag(level, "instrument", mport->instrument()->iname());
 
152
                  xml.strTag(level, "name",   dev->name());
 
153
                  xml.intTag(level, "record", dev->rwFlags() & 0x2 ? 1 : 0);
 
154
                  xml.etag(level--, "midiport");
 
155
                  }
 
156
            }
 
157
      AudioPort* port  = &audioPort;
 
158
      AudioDevice* dev = port->device();
 
159
      if (dev) {
 
160
            xml.tag(level++, "audioport idx=\"%d\"", 0);
 
161
            xml.strTag(level, "name",   dev->name().latin1());
 
162
            xml.intTag(level, "record", port->rwFlags() & 0x2 ? 1 : 0);
 
163
            xml.intTag(level, "play",   port->rwFlags() & 0x1);
 
164
            QString s;
 
165
            port->writeConfiguration(level, xml);
 
166
            xml.tag(level--, "/audioport");
 
167
            }
 
168
 
 
169
      for (int i = 0; i < AUDIO_GROUPS; ++i) {
 
170
            xml.tag(level++, "audiogroup idx=\"%d\"", i);
 
171
            song->group(i)->writeConfiguration(level, xml);
 
172
            xml.tag(level--, "/audiogroup");
 
173
            }
 
174
 
 
175
      xml.tag(level++, "audiomaster");
 
176
      song->master()->writeConfiguration(level, xml);
 
177
      xml.tag(level--, "/audiomaster");
 
178
 
 
179
      xml.tag(level, "/sequencer");
 
180
      }
 
181
 
 
182
//---------------------------------------------------------
 
183
//   loadConfigMetronom
 
184
//---------------------------------------------------------
 
185
 
 
186
void Sequencer::loadConfigMetronom(Xml& xml)
 
187
      {
 
188
      for (;;) {
 
189
            Xml::Token token = xml.parse();
 
190
            if (token == Xml::Error || token == Xml::End)
 
191
                  break;
 
192
            QString tag = xml.s1();
 
193
            switch (token) {
 
194
                  case Xml::TagStart:
 
195
                        if (tag == "premeasures")
 
196
                              preMeasures = xml.parseInt();
 
197
                        else if (tag == "measurepitch")
 
198
                              measureClickNote = xml.parseInt();
 
199
                        else if (tag == "measurevelo")
 
200
                              measureClickVelo = xml.parseInt();
 
201
                        else if (tag == "beatpitch")
 
202
                              beatClickNote = xml.parseInt();
 
203
                        else if (tag == "beatvelo")
 
204
                              beatClickVelo = xml.parseInt();
 
205
                        else if (tag == "channel")
 
206
                              clickChan = xml.parseInt();
 
207
                        else if (tag == "port")
 
208
                              clickPort = xml.parseInt();
 
209
                        else if (tag == "precountEnable")
 
210
                              precountEnableFlag = xml.parseInt();
 
211
                        else if (tag == "fromMastertrack")
 
212
                              precountFromMastertrackFlag = xml.parseInt();
 
213
                        else if (tag == "signatureZ")
 
214
                              precountSigZ = xml.parseInt();
 
215
                        else if (tag == "signatureN")
 
216
                              precountSigN = xml.parseInt();
 
217
                        else if (tag == "prerecord")
 
218
                              precountPrerecord = xml.parseInt();
 
219
                        else if (tag == "preroll")
 
220
                              precountPreroll = xml.parseInt();
 
221
                        else if (tag == "midiClickEnable")
 
222
                              midiClickFlag = xml.parseInt();
 
223
                        else if (tag == "audioClickEnable")
 
224
                              audioClickFlag = xml.parseInt();
 
225
                        else
 
226
                              xml.unknown("Metronome");
 
227
                        break;
 
228
                  case Xml::TagEnd:
 
229
                        if (tag == "metronom")
 
230
                              return;
 
231
                  default:
 
232
                        break;
 
233
                  }
 
234
            }
 
235
      }
 
236
 
 
237
//---------------------------------------------------------
 
238
//   readConfiguration
 
239
//---------------------------------------------------------
 
240
 
 
241
void Sequencer::readConfiguration(Xml& xml)
 
242
      {
 
243
      for (;;) {
 
244
            Xml::Token token = xml.parse();
 
245
            if (token == Xml::Error || token == Xml::End)
 
246
                  break;
 
247
            const QString& tag = xml.s1();
 
248
            switch (token) {
 
249
                  case Xml::TagStart:
 
250
                        if (tag == "metronom")
 
251
                              loadConfigMetronom(xml);
 
252
                        else if (tag == "midiport")
 
253
                              readConfigMidiPort(xml);
 
254
                        else if (tag == "audioport")
 
255
                              readConfigAudioPort(xml);
 
256
                        else if (tag == "audiogroup")
 
257
                              readConfigAudioGroup(xml);
 
258
                        else if (tag == "audiomaster")
 
259
                              readConfigAudioMaster(xml);
 
260
                        else if (tag == "rcStop")
 
261
                              rcStopNote = xml.parseInt();
 
262
                        else if (tag == "rcEnable")
 
263
                              rcEnable = xml.parseInt();
 
264
                        else if (tag == "rcRecord")
 
265
                              rcRecordNote = xml.parseInt();
 
266
                        else if (tag == "rcGotoLeft")
 
267
                              rcGotoLeftMarkNote = xml.parseInt();
 
268
                        else if (tag == "rcPlay")
 
269
                              rcPlayNote = xml.parseInt();
 
270
                        else if (tag == "mixdown")
 
271
                              readMixdown(xml);
 
272
                        else
 
273
                              xml.unknown("Seq");
 
274
                        break;
 
275
                  case Xml::TagEnd:
 
276
                        if (tag == "sequencer") {
 
277
                              return;
 
278
                              }
 
279
                  default:
 
280
                        break;
 
281
                  }
 
282
            }
 
283
      }
 
284
 
 
285
//---------------------------------------------------------
 
286
//   readMixdown
 
287
//---------------------------------------------------------
 
288
 
 
289
void Sequencer::readMixdown(Xml& xml)
 
290
      {
 
291
      QString path;
 
292
      int channels   = 2;
 
293
      int format     = SF_FORMAT_WAV | SF_FORMAT_PCM;
 
294
      int samplebits = 16;
 
295
 
 
296
      for (;;) {
 
297
            Xml::Token token = xml.parse();
 
298
            if (token == Xml::Error || token == Xml::End)
 
299
                  break;
 
300
            const QString& tag = xml.s1();
 
301
            switch (token) {
 
302
                  case Xml::TagStart:
 
303
                        if (tag == "path")
 
304
                              path = xml.parse1();
 
305
                        else if (tag == "channels")
 
306
                              channels = xml.parseInt();
 
307
                        else if (tag == "format")
 
308
                              format = xml.parseInt();
 
309
                        else if (tag == "samplebits")
 
310
                              samplebits = xml.parseInt();
 
311
                        else if (tag == "record") {
 
312
                              bool record = xml.parseInt();
 
313
                              if (record)
 
314
                                    audioThread->msgOpenMixdownRecord();
 
315
                              }
 
316
                        else
 
317
                              xml.unknown("mixdown");
 
318
                        break;
 
319
                  case Xml::TagEnd:
 
320
                        if (tag == "mixdown") {
 
321
                              SndFile* sf = new SndFile(path);
 
322
                              sf->setFormat(format, channels, sampleRate, samplebits);
 
323
                              audioThread->msgSetMixdownFile(sf);
 
324
                              return;
 
325
                              }
 
326
                  default:
 
327
                        break;
 
328
                  }
 
329
            }
 
330
      }
 
331
 
 
332
//---------------------------------------------------------
 
333
//   readConfigMidiPort
 
334
//---------------------------------------------------------
 
335
 
 
336
void Sequencer::readConfigMidiPort(Xml& xml)
 
337
      {
 
338
      int idx = 0;
 
339
      QString device;
 
340
      QString instrument;
 
341
      bool recFlag = false;
 
342
      bool thruFlag = false;
 
343
 
 
344
      for (;;) {
 
345
            Xml::Token token = xml.parse();
 
346
            if (token == Xml::Error || token == Xml::End)
 
347
                  break;
 
348
            QString tag = xml.s1();
 
349
            switch (token) {
 
350
                  case Xml::TagStart:
 
351
                        if (tag == "name")
 
352
                              device = xml.parse1();
 
353
                        else if (tag == "record")
 
354
                              recFlag = xml.parseInt();
 
355
                        else if (tag == "instrument")
 
356
                              instrument = xml.parse1();
 
357
                        else if (tag == "midithru")
 
358
                              thruFlag = xml.parseInt(); // obsolete
 
359
                        else
 
360
                              xml.unknown("MidiDevice");
 
361
                        break;
 
362
                  case Xml::Attribut:
 
363
                        if (tag == "idx") {
 
364
                              idx = xml.s2().toInt();
 
365
                              }
 
366
                        break;
 
367
                  case Xml::TagEnd:
 
368
                        if (tag == "midiport") {
 
369
                              if (idx > MIDI_PORTS) {
 
370
                                    fprintf(stderr, "bad midi port %d (>%d)\n",
 
371
                                       idx, MIDI_PORTS);
 
372
                                    idx = 0;
 
373
                                    }
 
374
                              MidiDevice* dev = midiDevices.find(device);
 
375
                              MidiPort* mp = &midiPorts[idx];
 
376
                              if (dev) {
 
377
                                    mp->setrwFlags(recFlag ? 3 : 1);
 
378
                                    midiThread->setMidiDevice(mp, dev);
 
379
                                    }
 
380
                              midiPorts[idx].setInstrument(
 
381
                                 registerMidiInstrument(instrument)
 
382
                                 );
 
383
                              return;
 
384
                              }
 
385
                  default:
 
386
                        break;
 
387
                  }
 
388
            }
 
389
      }
 
390
 
 
391
//---------------------------------------------------------
 
392
//   readConfigAudioPort
 
393
//---------------------------------------------------------
 
394
 
 
395
void Sequencer::readConfigAudioPort(Xml& xml)
 
396
      {
 
397
      int idx;
 
398
      QString device;
 
399
      AudioDevice* dev;
 
400
      AudioPort* port = 0;
 
401
      int rwFlags = 0;
 
402
 
 
403
      for (;;) {
 
404
            Xml::Token token = xml.parse();
 
405
            if (token == Xml::Error || token == Xml::End)
 
406
                  break;
 
407
            QString tag = xml.s1();
 
408
            switch (token) {
 
409
                  case Xml::TagStart:
 
410
                        if (tag == "name")
 
411
                              device = xml.parse1();
 
412
                        else if (tag == "record")
 
413
                              rwFlags |= xml.parseInt() ? 2 : 0;
 
414
                        else if (tag == "play")
 
415
                              rwFlags |= xml.parseInt() ? 1 : 0;
 
416
                        else if (tag == "audionode")
 
417
                              port->readConfiguration(xml);
 
418
                        else
 
419
                              xml.unknown("AudioDevice");
 
420
                        break;
 
421
                  case Xml::Attribut:
 
422
                        if (tag == "idx") {
 
423
                              idx = xml.s2().toInt();
 
424
                              idx = 0;
 
425
                              port = &audioPort;
 
426
                              }
 
427
                        break;
 
428
                  case Xml::TagEnd:
 
429
                        if (tag == "audioport") {
 
430
                              if (!device.isEmpty()) {
 
431
                                    dev = audioDevices.find(device);
 
432
                                    if (dev) {
 
433
                                          port->setrwFlags(rwFlags);
 
434
                                          audioThread->msgSetAudioDevice(port, dev);
 
435
                                          }
 
436
                                    audioThread->msgAddRoute(port, port->route());
 
437
                                    }
 
438
                              return;
 
439
                              }
 
440
                  default:
 
441
                        break;
 
442
                  }
 
443
            }
 
444
      }
 
445
 
 
446
//---------------------------------------------------------
 
447
//   readConfigAudioGroup
 
448
//---------------------------------------------------------
 
449
 
 
450
void Sequencer::readConfigAudioGroup(Xml& xml)
 
451
      {
 
452
      AudioMixer* mixer = 0;
 
453
      for (;;) {
 
454
            Xml::Token token = xml.parse();
 
455
            if (token == Xml::Error || token == Xml::End)
 
456
                  break;
 
457
            QString tag = xml.s1();
 
458
            switch (token) {
 
459
                  case Xml::TagStart:
 
460
                        if (tag == "audionode")
 
461
                              mixer->readConfiguration(xml);
 
462
                        else
 
463
                              xml.unknown("AudioGroup");
 
464
                        break;
 
465
                  case Xml::Attribut:
 
466
                        if (tag == "idx") {
 
467
                              int idx = xml.s2().toInt();
 
468
                              if (idx > AUDIO_GROUPS) {
 
469
                                    fprintf(stderr, "bad audio group %d (>%d)\n",
 
470
                                       idx, AUDIO_GROUPS);
 
471
                                    idx = 0;
 
472
                                    }
 
473
                              mixer = song->group(idx);
 
474
                              }
 
475
                        break;
 
476
                  case Xml::TagEnd:
 
477
                        if (tag == "audiogroup") {
 
478
                              audioThread->msgAddRoute(mixer, mixer->route());
 
479
                              return;
 
480
                              }
 
481
                  default:
 
482
                        break;
 
483
                  }
 
484
            }
 
485
      }
 
486
 
 
487
//---------------------------------------------------------
 
488
//   readConfigAudioMaster
 
489
//---------------------------------------------------------
 
490
 
 
491
void Sequencer::readConfigAudioMaster(Xml& xml)
 
492
      {
 
493
      AudioMixer* mixer = song->master();
 
494
      for (;;) {
 
495
            Xml::Token token = xml.parse();
 
496
            if (token == Xml::Error || token == Xml::End)
 
497
                  break;
 
498
            QString tag = xml.s1();
 
499
            switch (token) {
 
500
                  case Xml::TagStart:
 
501
                        if (tag == "audionode")
 
502
                              mixer->readConfiguration(xml);
 
503
                        else
 
504
                              xml.unknown("AudioMaster");
 
505
                        break;
 
506
                  case Xml::TagEnd:
 
507
                        if (tag == "audiomaster") {
 
508
//                              song->msgAddRoute(*mixer, mixer->route());
 
509
//                              mixer.setRoute(audioPort); // override settings
 
510
                              return;
 
511
                              }
 
512
                  default:
 
513
                        break;
 
514
                  }
 
515
            }
 
516
      }
 
517