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

« back to all changes in this revision

Viewing changes to midithread.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: midithread.cpp,v 1.6 2002/02/27 15:53:45 muse Exp $
 
4
//  $Id: midithread.cpp,v 1.6 2003/12/30 20:12:50 spamatica Exp $
5
5
//
6
 
//  (C) Copyright 2001 Werner Schweer (ws@seh.de)
 
6
//  (C) Copyright 2002 Werner Schweer (ws@seh.de)
7
7
//=========================================================
8
8
 
9
9
#include <config.h>
14
14
#include <sys/ioctl.h>
15
15
#include <errno.h>
16
16
#include <sys/time.h>
 
17
#include <cmath>
17
18
 
18
19
#include <linux/version.h>
19
20
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
34
35
#include "midictrl.h"
35
36
#include "event.h"
36
37
#include "tempo.h"
37
 
#include "midithreadp.h"
 
38
#include "audiodev.h"
38
39
#include "app.h"
39
40
#include "utils.h"
 
41
#include "drummap.h"
 
42
#include "jackaudio.h"
 
43
#include "audio.h"
 
44
#include "wave.h"
 
45
#include "sync.h"
40
46
 
41
47
static const unsigned char mmcStopMsg[] =         { 0x7f, 0x7f, 0x06, 0x01 };
42
48
static const unsigned char mmcDeferredPlayMsg[] = { 0x7f, 0x7f, 0x06, 0x03 };
43
49
 
44
50
static int TICK_SLICE;
 
51
MidiThread* midiThread;
 
52
 
 
53
//---------------------------------------------------------
 
54
//   SEvent
 
55
//---------------------------------------------------------
 
56
 
 
57
struct SEvent {
 
58
      MidiPlayEvent* ev;
 
59
      bool operator<(SEvent&);
 
60
      SEvent(MidiPlayEvent* me) { ev = me; }
 
61
      };
 
62
 
 
63
//---------------------------------------------------------
 
64
//   SEventList
 
65
//---------------------------------------------------------
 
66
 
 
67
class SEventList : public std::list<SEvent > {
 
68
      public:
 
69
      SEventList() {}
 
70
      };
 
71
 
 
72
typedef std::list<SEvent>::iterator iSEvent;
 
73
 
 
74
bool SEvent::operator<(SEvent& e)
 
75
      {
 
76
      if (ev->port() != e.ev->port())
 
77
            return ev->port() < e.ev->port();
 
78
 
 
79
      // play note off events first to prevent overlapping
 
80
      // notes
 
81
 
 
82
      if (ev->channel() == e.ev->channel())
 
83
            return ev->type() == MidiEvent::NoteOff;
 
84
 
 
85
      int map[16] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10, 11, 12, 13, 14, 15 };
 
86
      return map[ev->channel()] < map[e.ev->channel()];
 
87
      }
 
88
 
 
89
static SEventList sevents;
45
90
 
46
91
//---------------------------------------------------------
47
92
//   recTimeStamp
49
94
 
50
95
int MidiThread::recTimeStamp() const
51
96
      {
52
 
      return tempomap.time2tick(curTime() - data->startTime)
53
 
         + data->recStartTick;
 
97
      return _midiTick;
54
98
      }
55
99
 
56
100
//---------------------------------------------------------
57
101
//   heartBeat
 
102
//    (GUI context)
58
103
//---------------------------------------------------------
59
104
 
60
105
void MidiThread::heartBeat()
61
106
      {
62
 
      song->beat(data->playTickPos);
63
 
      if (data->controlChanged) {
 
107
      song->beat(playTickPos);
 
108
// printf("heart beat %d %d\n", _midiTick, playTickPos);
 
109
      if (controlChanged) {
64
110
            muse->ctrlChanged();
65
 
            data->controlChanged = false;
 
111
            controlChanged = false;
 
112
            }
 
113
      while (noteFifoSize) {
 
114
            int pv = recNoteFifo[noteFifoRindex];
 
115
            noteFifoRindex = (noteFifoRindex + 1) % REC_NOTE_FIFO_SIZE;
 
116
            emit midiNote((pv >> 8) & 0xff, pv & 0xff);
 
117
            --noteFifoSize;
66
118
            }
67
119
      }
68
120
 
70
122
//   MidiThread
71
123
//---------------------------------------------------------
72
124
 
73
 
MidiThread::MidiThread(bool rt=true, int prio=50, bool ml = true)
74
 
   : QObject(0, "midiThread"), Thread(rt, prio, ml)
 
125
MidiThread::MidiThread(int prio, const char* name)
 
126
   : QObject(0, name), Thread(prio, name)
75
127
      {
76
 
      data               = new MidiThreadPrivate;
77
 
      data->tempoSN      = -1;
78
 
      data->timerFd      = -1;
79
 
      data->state        = IDLE;
80
 
      data->midiTick     = 0;
81
 
      data->rtcTick      = 0;
82
 
      data->midiSync     = division/24;
83
 
      data->playTickPos  = 0;
84
 
      data->rtcTick      = 0;
85
 
      data->controlChanged = false;
86
 
      data->playEvents   = new EventList;
87
 
      data->stuckNotes   = new EventList;
88
 
      data->realRtcTicks = rtcTicks;
89
 
      TICK_SLICE         = division/10;
90
 
      data->endSlice     = 0;
91
 
 
92
 
      heartBeatTimer    = new QTimer(this, "timer");
 
128
      tempoSN        = -1;
 
129
      timerFd        = -1;
 
130
      state          = IDLE;
 
131
      controlChanged = false;
 
132
      noteFifoSize   = 0;
 
133
      noteFifoWindex = 0;
 
134
      noteFifoRindex = 0;
 
135
      realRtcTicks   = rtcTicks;
 
136
      TICK_SLICE     = division/10;
 
137
      endSlice       = 0;
 
138
 
 
139
      startRecord.setType(Pos::TICKS);
 
140
      endRecord.setType(Pos::TICKS);
 
141
 
 
142
      heartBeatTimer = new QTimer(this, "timer");
93
143
      connect(heartBeatTimer, SIGNAL(timeout()), this, SLOT(heartBeat()));
94
144
 
95
145
      //---------------------------------------------------
101
151
            perror("creating pipe1");
102
152
            exit(-1);
103
153
            }
104
 
      data->sigFd = filedes[1];
 
154
      sigFd = filedes[1];
105
155
      QSocketNotifier* ss = new QSocketNotifier(filedes[0], QSocketNotifier::Read);
106
156
      connect(ss, SIGNAL(activated(int)), this, SLOT(seqSignal(int)));
107
157
      }
112
162
 
113
163
MidiThread::~MidiThread()
114
164
      {
115
 
      if (data->timerFd) {
116
 
            ioctl(data->timerFd, RTC_PIE_OFF, 0);
117
 
            close(data->timerFd);
 
165
      if (timerFd != -1) {
 
166
            ioctl(timerFd, RTC_PIE_OFF, 0);
 
167
            close(timerFd);
118
168
            }
119
 
      delete data->stuckNotes;
120
 
      delete data->playEvents;
121
 
      delete data;
122
169
      }
123
170
 
124
171
//---------------------------------------------------------
127
174
 
128
175
bool MidiThread::isPlaying() const
129
176
      {
130
 
      return data->state == PLAY;
131
 
      }
132
 
 
133
 
//---------------------------------------------------------
134
 
//   curTickPos
135
 
//    current play position in midi ticks;
136
 
//    provided for gui "heartBeat()"
137
 
//---------------------------------------------------------
138
 
 
139
 
int MidiThread::curTickPos() const
140
 
      {
141
 
      return data->playTickPos;
142
 
      }
143
 
 
144
 
//---------------------------------------------------------
145
 
//   SEvent
146
 
//---------------------------------------------------------
147
 
 
148
 
struct SEvent {
149
 
      MidiEvent* ev;
150
 
      bool operator<(SEvent&);
151
 
      SEvent(MidiEvent* me) { ev = me; }
152
 
      };
153
 
 
154
 
//---------------------------------------------------------
155
 
//   SEventList
156
 
//---------------------------------------------------------
157
 
 
158
 
class SEventList : public std::list<SEvent> {
159
 
   public:
160
 
      SEventList() {}
161
 
      };
162
 
typedef std::list<SEvent>::iterator iSEvent;
163
 
 
164
 
bool SEvent::operator<(SEvent& e)
165
 
      {
166
 
      if (ev->port() != e.ev->port())
167
 
            return ev->port() < e.ev->port();
168
 
 
169
 
 
170
 
      // play note off events first to prevent overlapping
171
 
      // notes
172
 
 
173
 
      if (ev->channel() == e.ev->channel())
174
 
            return ev->type() == MidiEvent::NoteOff;
175
 
 
176
 
      int map[16] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10, 11, 12, 13, 14, 15 };
177
 
      return map[ev->channel()] < map[e.ev->channel()];
 
177
      return state == PLAY;
178
178
      }
179
179
 
180
180
//---------------------------------------------------------
185
185
void MidiThread::recordStop()
186
186
      {
187
187
      TrackList* tl = song->tracks();
188
 
      int lastTick = tempomap.time2tick(curTime() - data->startTime);
189
 
// printf("record STOP, starttick %d - enddtick %d\n",
190
 
//  data->recStartTick, lastTick);
 
188
      int firstTick = startRecord.posTick();
 
189
      int lastTick  = endRecord.posTick();
 
190
      bool updateMixer = false;
 
191
 
191
192
      for (iTrack it = tl->begin(); it != tl->end(); ++it) {
192
 
            if ((*it)->type() != Track::MIDI && (*it)->type() != Track::DRUM)
 
193
            Track::TrackType type = (*it)->type();
 
194
            if (type == Track::WAVE) {
 
195
                  WaveTrack* track = (WaveTrack*)(*it);
 
196
                  if (!track->recordFlag())
 
197
                        continue;
 
198
                  song->cmdAddRecordedWave(track,
 
199
                     startRecord.posSample(),
 
200
                     endRecord.posSample());
 
201
                  track->setRecFile(0);
 
202
                  song->setRecordFlag(track, false);
 
203
                  updateMixer = true;
193
204
                  continue;
 
205
                  }
194
206
            MidiTrack* mt = (MidiTrack*)*it;
195
207
            EventList* el = mt->events();
196
208
 
201
213
            for (iEvent i = el->begin(); i != el->end(); ++i) {
202
214
                  MidiEvent* ev  = (MidiEvent*)i->second;
203
215
                  if (ev->isNote()) {
 
216
                        if (ev->velo() == 0) {
 
217
                              // this is a note off event without a note on
 
218
                              // set note on to begin of recording:
 
219
                              // velocity info is lost (set to default 80)
 
220
 
 
221
                              ev->setPosTick(firstTick);
 
222
                              ev->setVelo(80);
 
223
                              int len = i->first - firstTick;
 
224
                              if (len <= 0)
 
225
                                    len = 1;
 
226
                              ev->setLenTick(i->first - firstTick);
 
227
                              continue;
 
228
                              }
 
229
 
204
230
                        iEvent k = i;
205
231
                        for (++k; k != el->end(); ++k) {
206
232
                              if (ev->isNoteOff((MidiEvent*)k->second)) {
207
233
                                    int t = k->first - i->first;
208
234
                                    if (t == 0) {
209
235
                                          t = 1;
210
 
                                          printf("len == 0!\n");
 
236
                                          printf("note len == 0! (set to 1)\n");
211
237
                                          }
212
238
                                    ev->setLenTick(t);
213
239
                                    ev->setVeloOff(((MidiEvent*)i->second)->veloOff());
216
242
                                    }
217
243
                              }
218
244
                        if (k == el->end()) {
219
 
                              int len = lastTick - k->first;
 
245
                              // note off event is missing; set note end
 
246
                              // to end of recording
 
247
 
 
248
                              int len = lastTick - i->first;
220
249
                              if (len < 1)
221
250
                                    len = 1;
222
251
                              ev->setLenTick(len);
228
257
            //    assign events to parts
229
258
            //-------------------------------------------------------------
230
259
 
231
 
            song->cmdAddRecordedEvents(mt, el, data->recStartTick);
 
260
            song->cmdAddRecordedEvents(mt, el, firstTick);
232
261
            el->clear();
233
262
            }
 
263
      if (audioOutput.recordFlag()) {
 
264
            SndFile* sf = audioOutput.recFile();
 
265
            if (sf)
 
266
                  delete sf;              // close
 
267
            audioOutput.setRecFile(0);
 
268
            audioOutput.setRecordFlag1(false);
 
269
            audio->msgSetRecord(&audioOutput, false);
 
270
            }
234
271
      song->setRecord(false);
 
272
      song->update(SC_RECFLAG);
235
273
      }
236
274
 
237
275
//---------------------------------------------------------
244
282
      {
245
283
      char buffer[16];
246
284
 
247
 
      int n = ::read(fd, buffer, 1);
248
 
      if (n != 1) {
249
 
            printf("MidiThread: seqSignal: READ PIPE returns %d\n", n);
 
285
      int n = ::read(fd, buffer, 16);
 
286
      if (n < 0) {
 
287
            printf("MidiThread: seqSignal: READ PIPE failed: %s\n",
 
288
               strerror(errno));
250
289
            return;
251
290
            }
252
 
      switch(buffer[0]) {
253
 
            case '0':         // STOP
254
 
                  if (song->record())
255
 
                        recordStop();
256
 
                  song->setPlay(false);
257
 
                  break;
258
 
            case '2':   // record
259
 
                  song->setRecord(true);
260
 
            case '1':
261
 
                  song->setPlay(true);
262
 
                  break;
263
 
            case 'P':   // alsa ports changed
264
 
                  song->rescanAlsaPorts();
265
 
                  break;
266
 
            case 'I':   // event received
267
 
                  emit midiNote(data->curPitch, data->curVelo);
268
 
                  break;
269
 
            case 'G':
270
 
                  song->setPos(0, data->playTickPos, true, true, true);
271
 
                  break;
272
 
            default:
273
 
                  printf("Seq Signal <%c>\n", buffer[0]);
274
 
                  break;
 
291
      for (int i = 0; i < n; ++i) {
 
292
            switch(buffer[i]) {
 
293
                  case '0':         // STOP
 
294
                        if (song->record())
 
295
                              recordStop();
 
296
                        song->setStopPlay(false);
 
297
                        break;
 
298
                  case '1':
 
299
                        song->setStopPlay(true);
 
300
                        break;
 
301
                  case '2':   // record
 
302
                        song->setRecord(true);
 
303
                  case 'P':   // alsa ports changed
 
304
                        song->rescanAlsaPorts();
 
305
                        break;
 
306
//                case 'I':   // event received
 
307
//                      emit midiNote(curPitch, curVelo);
 
308
//                      break;
 
309
                  case 'G':
 
310
                        song->setPos(0, playTickPos, true, true, true);
 
311
                        break;
 
312
                  default:
 
313
                        printf("unknown Seq Signal <%c>\n", buffer[i]);
 
314
                        break;
 
315
                  }
275
316
            }
276
317
      }
277
318
 
293
334
void MidiThread::midiTick(void* p, void*)
294
335
      {
295
336
      MidiThread* at = (MidiThread*)p;
296
 
      at->data->processTimerTick();
 
337
      at->processTimerTick();
297
338
      }
298
339
 
299
340
//---------------------------------------------------------
350
391
 
351
392
void MidiThread::start()
352
393
      {
 
394
      tempoSN      = -1;
 
395
      timerFd      = -1;
 
396
      state        = IDLE;
 
397
      controlChanged = false;
 
398
 
 
399
      realRtcTicks = rtcTicks;
 
400
      TICK_SLICE         = division/10;
 
401
      endSlice     = 0;
 
402
      //---------------------------------------------
 
403
 
353
404
      setHeartBeat();
354
405
 
355
406
      //---------------------------------------------------
356
407
      // initialize timer
357
408
      //---------------------------------------------------
358
409
 
359
 
#ifndef RTCAP
360
410
      doSetuid();
361
 
#endif
362
 
      data->timerFd = ::open("/dev/rtc", O_RDWR);
363
 
#ifndef RTCAP
364
 
      undoSetuid();
365
 
#endif
366
 
      if (data->timerFd == -1)
 
411
      timerFd = ::open("/dev/rtc", O_RDWR);
 
412
      if (timerFd == -1) {
367
413
            perror("cannot open rtc clock /dev/rtc");
 
414
            if (!debugMode)
 
415
                  exit(-1);
 
416
            }
368
417
      if (setRtcTicks()) {
369
 
#ifndef RTCAP
370
 
      doSetuid();
371
 
#endif
372
 
            if (ioctl(data->timerFd, RTC_PIE_ON, 0) == -1)
373
 
                  perror("RTC_PIE_ON failed");
374
 
#ifndef RTCAP
 
418
            if (ioctl(timerFd, RTC_PIE_ON, 0) == -1) {
 
419
                  perror("MidiThread: start: RTC_PIE_ON failed");
 
420
                  if (!debugMode)
 
421
                        exit(-1);
 
422
                  }
 
423
            }
375
424
      undoSetuid();
376
 
#endif
377
 
            }
378
 
 
 
425
      Thread::start();
 
426
      }
 
427
 
 
428
//---------------------------------------------------------
 
429
//   threadStart
 
430
//---------------------------------------------------------
 
431
 
 
432
void MidiThread::threadStart(void*)
 
433
      {
 
434
      _midiTick     = 0;
 
435
      rtcTick      = 0;
 
436
      midiClock    = 0;
 
437
      playTickPos  = 0;
379
438
      updatePollFd();
380
 
      Thread::start();
 
439
      }
 
440
 
 
441
//---------------------------------------------------------
 
442
//   threadStop
 
443
//---------------------------------------------------------
 
444
 
 
445
void MidiThread::threadStop()
 
446
      {
 
447
      if (timerFd != -1) {
 
448
            ioctl(timerFd, RTC_PIE_OFF, 0);
 
449
            ::close(timerFd);
 
450
            timerFd = -1;
 
451
            }
381
452
      }
382
453
 
383
454
//---------------------------------------------------------
386
457
 
387
458
void MidiThread::updatePollFd()
388
459
      {
 
460
      if (!isRunning())
 
461
            return;
 
462
 
389
463
      clearPollFd();
390
 
      if (data->timerFd)
391
 
            addPollFd(data->timerFd, POLLIN, midiTick, this, 0);
392
 
// printf("update poll %d\n", toThreadFdr);
 
464
 
 
465
      if (timerFd != -1) {
 
466
            addPollFd(timerFd, POLLIN, midiTick, this, 0);
 
467
            }
 
468
      else {
 
469
            fprintf(stderr, "updatePollFd: no timer fd\n");
 
470
            if (!debugMode)
 
471
                  exit(-1);
 
472
            }
 
473
 
393
474
      addPollFd(toThreadFdr, POLLIN, ::readMsg, this, 0);
394
475
 
395
476
      //---------------------------------------------------
397
478
      //---------------------------------------------------
398
479
 
399
480
      for (int i = 0; i < MIDI_PORTS; ++i) {
400
 
            MidiPort* mp = &midiPorts[i];
 
481
            MidiPort* mp    = &midiPorts[i];
401
482
            MidiDevice* dev = mp->device();
402
483
            if (dev) {
403
 
                  if ((mp->rwFlags()&0x2) || (extSyncFlag.value() && (extSyncPort==i))) {
 
484
                  if ((mp->rwFlags()&0x2) || (extSyncFlag.value()
 
485
                     && (rxSyncPort == i || rxSyncPort == -1))) {
404
486
                        int fd = dev->selectRfd();
405
487
                        if (fd != -1)
406
488
                              addPollFd(fd, POLLIN, ::midiRead, this, dev);
412
494
                        }
413
495
                  }
414
496
            }
415
 
#ifdef ALSA
416
497
      // special handling for alsa midi:
417
498
      // (one fd for all devices)
418
499
      //    this allows for processing of some alsa events
421
502
      if (fd != -1) {
422
503
            addPollFd(fd, POLLIN, ::alsaMidiRead, this, 0);
423
504
            }
424
 
#endif
425
505
 
426
506
      //---------------------------------------------------
427
507
      //   connect Synthi instances (GUI)
441
521
 
442
522
bool MidiThread::setRtcTicks()
443
523
      {
444
 
      if (data->timerFd == -1) {
 
524
      if (timerFd == -1) {
 
525
            if (!debugMode) {
 
526
                  fprintf(stderr, "setRtcTicks: not rtc timer avail.");
 
527
                  exit(-1);
 
528
                  }
445
529
            setPollWait(10);  // 10 msec
446
 
            data->realRtcTicks = 100;
 
530
            realRtcTicks = 100;
447
531
            return false;
448
532
            }
449
 
#ifndef RTCAP
450
 
      doSetuid();
451
 
#endif
452
 
      int rc = ioctl(data->timerFd, RTC_IRQP_SET, rtcTicks);
453
 
#ifndef RTCAP
454
 
      undoSetuid();
455
 
#endif
456
 
 
 
533
      int rc = ioctl(timerFd, RTC_IRQP_SET, rtcTicks);
457
534
      if (rc == -1) {
458
535
            fprintf(stderr, "cannot set tick on /dev/rtc: %s\n",
459
536
               strerror(errno));
460
537
            fprintf(stderr, "precise timer not available\n");
461
 
            close(data->timerFd);
462
 
            data->timerFd = -1;
 
538
            close(timerFd);
 
539
            if (!debugMode)
 
540
                  exit(-1);
 
541
            timerFd = -1;
463
542
            setPollWait(10);  // 10 msec
464
 
            data->realRtcTicks = 100;
 
543
            realRtcTicks = 100;
465
544
            return false;
466
545
            }
467
 
      data->realRtcTicks = rtcTicks;
 
546
      realRtcTicks = rtcTicks;
468
547
      return true;
469
548
      }
470
549
 
482
561
                        midiPorts[i].instrument()->reset(i, song->mtype());
483
562
                  break;
484
563
            case SEQM_INIT_DEVICES:
485
 
                  data->initDevices();
 
564
                  initDevices();
486
565
                  break;
487
566
            case SEQM_MIDI_LOCAL_OFF:
488
567
                  sendLocalOff();
489
568
                  break;
 
569
            case SEQM_PANIC:
 
570
                  panic();
 
571
                  break;
490
572
            case SEQM_MIDI_CTRL:
491
573
                  midiPorts[msg->port].setCtrl(msg->channel, msg->ctrl, msg->a);
492
574
                  break;
499
581
                  updatePollFd();
500
582
                  break;
501
583
            case SEQM_PLAY_MIDI_EVENT:
502
 
                  data->playEvent((MidiEvent*)(msg->p1));
 
584
                  {
 
585
                  MidiPlayEvent* ev = (MidiPlayEvent*)(msg->p1);
 
586
                  midiPorts[ev->port()].putEvent(ev);
 
587
                  }
503
588
                  break;
504
589
            case SEQM_SET_RTC_TICKS:
 
590
                  doSetuid();
505
591
                  setRtcTicks();
 
592
                  undoSetuid();
506
593
                  break;
507
594
            case SEQM_SEEK:
508
 
                  if (data->state == PLAY)
509
 
                        data->seek(msg->a);
 
595
                  if (state == PLAY)
 
596
                        seek(msg->a);
510
597
                  break;
511
598
            case SEQM_SCAN_ALSA_MIDI_PORTS:
512
599
                  alsaScanMidiPorts();
513
600
                  break;
514
601
            case SEQM_PLAY:
515
 
                  if (data->state == IDLE && msg->a)
516
 
                        data->startPlay();
517
 
                  else if ((data->state == PLAY || data->state == PRECOUNT)
518
 
                     && !msg->a)
519
 
                        data->stopPlay();
 
602
                  if (state == IDLE && msg->a)
 
603
                        startPlay(song->cpos());
 
604
                  else if ((state == PLAY || state == PRECOUNT) && !msg->a)
 
605
                        stopPlay();
520
606
                  break;
521
607
            case MIDI_ADD_SYNTHI:
522
608
                  updatePollFd();
523
609
                  break;
524
610
            case MIDI_SHOW_INSTR_GUI:
525
 
                  ((MidiInstrument*)(msg->p1))->showGui(msg->a);
 
611
//                  ((MidiInstrument*)(msg->p1))->showGui(msg->a);
526
612
                  updatePollFd();
527
613
                  break;
528
614
            default:
529
 
                  song->processMsg(msg);
530
 
                  break;
531
 
            }
532
 
      }
533
 
 
534
 
//---------------------------------------------------------
535
 
//   playEvent
536
 
//---------------------------------------------------------
537
 
 
538
 
void MidiThreadPrivate::playEvent(MidiEvent* event)
539
 
      {
540
 
      MidiTrack* t   = event->trk();
541
 
      MidiPort* port = &midiPorts[event->port()];
542
 
      switch (event->type()) {
543
 
            case MidiEvent::Note:
544
 
                  {
545
 
                  int len   = event->lenTick();
546
 
                  int pitch = event->pitch();
547
 
                  int velo  = event->velo();
548
 
                  if (t) {
549
 
                        if (song->mute(t))
550
 
                              return;
551
 
                        pitch += t->transposition;
552
 
                        if (pitch > 127)
553
 
                              pitch = 127;
554
 
                        if (pitch < 0)
555
 
                              pitch = 0;
556
 
 
557
 
                        velo += t->velocity;
558
 
                        velo = (velo * t->compression) / 100;
559
 
                        if (velo > 127)
560
 
                              velo = 127;
561
 
                        if (velo < 1)           // no off event
562
 
                              velo = 1;
563
 
 
564
 
                        len = (len *  t->len) / 100;
565
 
                        t->addActivity(velo);
566
 
                        }
567
 
                  if (len <= 0)     // don�t allow zero length
568
 
                        len = 1;
569
 
                  MidiEvent* noteOff = new MidiEvent(*event);
570
 
                  noteOff->setType(MidiEvent::NoteOff);
571
 
                  noteOff->setPosTick(event->posTick() + len);
572
 
                  noteOff->setPitch(pitch);
573
 
                  stuckNotes->add(noteOff, noteOff->posTick());
574
 
                  if (len != event->lenTick() || pitch != event->pitch()
575
 
                     | velo != event->velo()) {
576
 
                        //CHECK
577
 
                        MidiEvent* ev = new MidiEvent(*event);
578
 
                        ev->setLenTick(len);
579
 
                        ev->setPitch(pitch);
580
 
                        ev->setVelo(velo);
581
 
                        port->putEvent(ev);
582
 
                        return;
583
 
                        }
584
 
                  }
585
 
                  break;
586
 
 
587
 
            case MidiEvent::Ctrl7:
588
 
            case MidiEvent::Ctrl14:
589
 
                  if (song->mute(t))
590
 
                        return;
591
 
                  controlChanged = true;
592
 
                  break;
593
 
            case MidiEvent::NoteOff:
594
 
                  if (t == 0)
595
 
                        break;
596
 
                  t->addActivity(-(event->velo()));
597
 
                  break;
598
 
            default:
599
 
                  if (t && song->mute(t))
600
 
                        return;
601
 
                  break;
602
 
            }
603
 
      port->putEvent(event);
604
 
      if (port->instrument()->hasGui())
605
 
            port->instrument()->writeToGui(event);
 
615
                  song->processMidiMsg(msg);
 
616
                  break;
 
617
            }
606
618
      }
607
619
 
608
620
//---------------------------------------------------------
609
621
//   stop
610
622
//---------------------------------------------------------
611
623
 
612
 
void MidiThreadPrivate::stopPlay()
 
624
void MidiThread::stopPlay()
613
625
      {
 
626
      endRecord.setPosTick(playTickPos);
 
627
      audio->msgPlay(false);
 
628
 
614
629
      //---------------------------------------------------
615
630
      //    end all notes
616
631
      //---------------------------------------------------
617
632
 
618
 
      for (iEvent i = stuckNotes->begin(); i != stuckNotes->end(); ++i)
619
 
            playEvent((MidiEvent*)(i->second));
620
 
      stuckNotes->clear();
 
633
      // printf("stopPlay: stuck notes %d\n", stuckNotes.size());
 
634
 
 
635
//      midiOutputTrace = true;
 
636
      for (iMPEvent i = stuckNotes.begin(); i != stuckNotes.end(); ++i)
 
637
            playEvent(&i->second);
 
638
      stuckNotes.clear();
 
639
//      midiOutputTrace = false;
621
640
 
622
641
      //---------------------------------------------------
623
642
      //    reset sustain
630
649
                  }
631
650
            }
632
651
 
633
 
      audioThread->stopPlay();
634
 
 
635
652
      //---------------------------------------------------
636
653
      //    clear track activity display
637
654
      //---------------------------------------------------
638
655
 
639
656
      TrackList* tl = song->tracks();
640
657
      for (iTrack i = tl->begin(); i != tl->end(); ++i) {
641
 
            SoundSource* ss = dynamic_cast<SoundSource*>(*i);
642
 
            ss->resetMeter();
643
 
            ss->setCurActivity(1);
 
658
            SNode* ss = (*i)->node();
 
659
            // ss->resetMeter();
 
660
            ss->setActivity(0);
644
661
            }
645
662
 
646
 
      MidiDevice* syncDev = midiPorts[extSyncPort].device();
647
 
 
648
 
      if (genMTCSync) {       // MTC
 
663
      if (genMMC) {
649
664
            unsigned char mmcPos[] = {
650
665
                  0x7f, 0x7f, 0x06, 0x44, 0x06, 0x01,
651
666
                  0, 0, 0, 0, 0
656
671
            mmcPos[8] = mtc.s();
657
672
            mmcPos[9] = mtc.f();
658
673
            mmcPos[10] = mtc.sf();
659
 
            MidiEvent ev0(0, 0, 0, MidiEvent::Sysex, sizeof(mmcStopMsg), mmcStopMsg);
660
 
            midiPorts[extSyncPort].putEvent(&ev0);
661
 
            MidiEvent ev1(0, 0, 0, MidiEvent::Sysex, sizeof(mmcPos), mmcPos);
662
 
            midiPorts[extSyncPort].putEvent(&ev1);
 
674
            midiPorts[txSyncPort].sysex(mmcStopMsg, sizeof(mmcStopMsg));
 
675
            midiPorts[txSyncPort].sysex(mmcPos, sizeof(mmcPos));
663
676
            }
664
 
      if (genMCSync) {        // Midi Clock
 
677
 
 
678
      MidiDevice* syncDev = midiPorts[txSyncPort].device();
 
679
      if (genMCSync && syncDev) {         // Midi Clock
665
680
            // send STOP and
666
681
            // "set song position pointer"
667
 
            if (syncDev) {
668
 
                  syncDev->putStop();
669
 
                  int beat = playTickPos * 4 / division;
670
 
                  syncDev->putSongpos(beat);
671
 
                  }
 
682
            syncDev->putStop();
 
683
            int beat = playTickPos * 4 / division;
 
684
            syncDev->putSongpos(beat);
672
685
            }
673
686
      state = IDLE;
674
687
      write(sigFd, "0", 1);   // STOP
680
693
 
681
694
void MidiThread::defaultTick()
682
695
      {
683
 
      data->processTimerTick();
 
696
      processTimerTick();
684
697
      }
685
698
 
686
699
//---------------------------------------------------------
689
702
 
690
703
void MidiThread::midiPortsChanged()
691
704
      {
692
 
      write(data->sigFd, "P", 1);
 
705
      write(sigFd, "P", 1);
693
706
      }
694
707
 
695
708
//---------------------------------------------------------
705
718
      }
706
719
 
707
720
//---------------------------------------------------------
 
721
//   panic
 
722
//---------------------------------------------------------
 
723
 
 
724
void MidiThread::panic()
 
725
      {
 
726
      MidiPlayEvent ev;
 
727
      ev.setType(0xb0);
 
728
      for (int i = 0; i < MIDI_PORTS; ++i) {
 
729
            MidiPort* port = &midiPorts[i];
 
730
            if (port == 0)
 
731
                  continue;
 
732
            ev.setPort(i);
 
733
            for (int chan = 0; chan < MIDI_CHANNELS; ++chan) {
 
734
                  ev.setChannel(chan);
 
735
                  ev.setA(120);          // all sound off
 
736
                  ev.setB(0);
 
737
                  port->putEvent(&ev);
 
738
 
 
739
                  ev.setA(121);          // reset all controller
 
740
                  ev.setB(0);
 
741
                  port->putEvent(&ev);
 
742
                  }
 
743
            }
 
744
      }
 
745
 
 
746
//---------------------------------------------------------
708
747
//   initDevices
709
748
//---------------------------------------------------------
710
749
 
711
 
void MidiThreadPrivate::initDevices()
 
750
void MidiThread::initDevices()
712
751
      {
713
 
// printf("init Devices\n");
714
752
      //
715
753
      // mark all used devices in song as active
716
754
      //
720
758
 
721
759
      TrackList* tracks = song->tracks();
722
760
      for (iTrack it = tracks->begin(); it != tracks->end(); ++it) {
723
 
            MidiTrack* track = dynamic_cast<MidiTrack*>(*it);
724
 
            if (track == 0)
 
761
            Track* t = *it;
 
762
            if (t->type() != Track::MIDI && t->type() != Track::DRUM)
725
763
                  continue;
 
764
            MidiTrack* track = (MidiTrack*)t;
726
765
            activeDevices[track->outPort()] = true;
727
766
            }
728
767
 
 
768
 
 
769
      //
 
770
      // test for explicit instrument initialization
 
771
      //
 
772
 
 
773
      for (int i = 0; i < MIDI_PORTS; ++i) {
 
774
            if (!activeDevices[i])
 
775
                  continue;
 
776
            MidiPort* port = &midiPorts[i];
 
777
            MidiInstrument* instr = port->instrument();
 
778
            if (instr) {
 
779
                  EventList* events = instr->midiInit();
 
780
                  if (events->empty())
 
781
                        continue;
 
782
                  MPEventList el;
 
783
                  for (iEvent ie = events->begin(); ie != events->end(); ++ie)
 
784
                        el.add(0, (MidiEvent*)(ie->second), i, 0);
 
785
                  el.play();
 
786
                  activeDevices[i] = false;  // no standard initialization
 
787
                  }
 
788
            }
729
789
      //
730
790
      // damit Midi-Devices, die mehrere Ports besitzen, wie z.B.
731
791
      // das Korg NS5R, nicht mehrmals zwischen GM und XG/GS hin und
733
793
      // initialisiert, und dann erst XG/GS
734
794
      //
735
795
      for (int i = 0; i < MIDI_PORTS; ++i) {
736
 
            if (activeDevices[i] == false)
 
796
            if (!activeDevices[i])
737
797
                  continue;
738
798
            MidiPort* port = &midiPorts[i];
739
799
            switch(song->mtype()) {
743
803
                  case MT_GM:
744
804
                  case MT_XG:
745
805
                        port->gmOn();
746
 
                        usleep(200000);   // wait 200ms
 
806
                        // usleep(200000);   // wait 200ms
747
807
                        break;
748
808
                  }
749
809
            }
750
810
      for (int i = 0; i < MIDI_PORTS; ++i) {
751
 
            if (activeDevices[i] == false)
 
811
            if (!activeDevices[i])
752
812
                  continue;
753
813
            MidiPort* port = &midiPorts[i];
754
814
            switch(song->mtype()) {
758
818
                        break;
759
819
                  case MT_GS:
760
820
                        port->gsOn();
761
 
                        usleep(50000);    // wait 50 ms
 
821
                        // usleep(50000);    // wait 50 ms
762
822
                        break;
763
823
                  case MT_XG:
764
824
                        port->xgOn();
765
 
                        usleep(50000);    // wait 50 ms
 
825
                        // usleep(50000);    // wait 50 ms
766
826
                        break;
767
827
                  }
768
828
            }
769
829
 
770
830
      for (int i = 0; i < MIDI_PORTS; ++i) {
771
 
            if (activeDevices[i] == false)
 
831
            if (!activeDevices[i])
772
832
                  continue;
773
833
            MidiPort* port = &midiPorts[i];
774
834
            //
815
875
//   startPlay
816
876
//---------------------------------------------------------
817
877
 
818
 
void MidiThreadPrivate::startPlay()
 
878
void MidiThread::startPlay(int st)
819
879
      {
820
880
      //
821
881
      // reset runstate of midi devices for more
823
883
      //
824
884
      for (int i = 0; i < MIDI_PORTS; ++i)
825
885
            midiPorts[i].resetRunstate();
826
 
      if (song->cpos() == 0 && !song->record())
 
886
      if (st == 0 && !song->record())
827
887
            initDevices();
828
 
      audioThread->play(song->cpos());
829
888
 
830
 
      seek(song->cpos());
831
 
      if (genMTCSync) {
832
 
            MidiEvent ev(0, 0, 0, MidiEvent::Sysex,
833
 
              sizeof(mmcDeferredPlayMsg), mmcDeferredPlayMsg);
834
 
            midiPorts[extSyncPort].putEvent(&ev);
835
 
            }
 
889
      seek(st);
 
890
      if (genMMC)
 
891
            midiPorts[txSyncPort].sysex(mmcDeferredPlayMsg, sizeof(mmcDeferredPlayMsg));
836
892
      if (genMCSync) {
837
893
            if (playTickPos)
838
 
                  midiPorts[extSyncPort].putContinue();
 
894
                  midiPorts[txSyncPort].putContinue();
839
895
            else
840
 
                  midiPorts[extSyncPort].putStart();
 
896
                  midiPorts[txSyncPort].putStart();
841
897
            }
842
898
      if (precountEnableFlag
843
899
         && song->click()
854
910
            clickno       = z * preMeasures;
855
911
            clicksMeasure = z;
856
912
            ticksBeat     = (division * 4)/n;
857
 
            midiClick     = midiTick;         // start now
 
913
            midiClick     = _midiTick;         // start now
858
914
            }
859
915
      else {
860
916
            int bar, beat, tick;
862
918
            if (tick)
863
919
                  beat += 1;
864
920
            midiClick = sigmap.bar2tick(bar, beat, 0);
865
 
// printf("tick %d(%d)  %d %d %d = %d\n",
866
 
//   midiTick, song->cpos(), bar, beat, tick, midiClick);
867
921
            }
868
 
      // start real play on next midi sync
869
 
      // current state is START_PLAY
 
922
      // start real play on next midiClock
 
923
      // current state is START_PLAY (set in seek)
870
924
      }
871
925
 
872
926
//---------------------------------------------------------
873
927
//   seek
874
928
//---------------------------------------------------------
875
929
 
876
 
void MidiThreadPrivate::seek(int pos)
 
930
void MidiThread::seek(int pos)
877
931
      {
 
932
      state       = START_PLAY;
878
933
      playTickPos = pos;
 
934
      midiClick   = pos;      // first click on loop start
879
935
 
880
936
      //---------------------------------------------------
881
937
      //    end all notes
882
938
      //---------------------------------------------------
883
939
 
884
 
      for (iEvent i = stuckNotes->begin(); i != stuckNotes->end(); ++i)
885
 
            playEvent((MidiEvent*)(i->second));
886
 
      stuckNotes->clear();
 
940
      for (iMPEvent i = stuckNotes.begin(); i != stuckNotes.end(); ++i)
 
941
            playEvent(&i->second);
 
942
      stuckNotes.clear();
887
943
 
888
 
      MidiDevice* syncDev = midiPorts[extSyncPort].device();
 
944
      MidiDevice* syncDev = midiPorts[txSyncPort].device();
889
945
      if (genMCSync && syncDev) {
890
946
            int beat = (playTickPos * 4) / division;
891
947
            syncDev->putStop();           // ??
892
948
            syncDev->putSongpos(beat);
893
949
            syncDev->putContinue();       // ??
894
950
            }
895
 
      audioThread->seek(playTickPos);
 
951
      audio->msgSeek(playTickPos);
896
952
      loopPassed = true;   // for record loop mode
897
 
      playEvents->clear();
898
 
      state = START_PLAY;
899
 
      }
900
 
 
901
 
//---------------------------------------------------------
902
 
//   processMidiTick
903
 
//---------------------------------------------------------
904
 
 
905
 
void MidiThreadPrivate::processMidiTick()
 
953
      playEvents.clear();
 
954
      }
 
955
 
 
956
//---------------------------------------------------------
 
957
//   playEvent
 
958
//---------------------------------------------------------
 
959
 
 
960
void MidiThread::playEvent(const MidiPlayEvent* event)
 
961
      {
 
962
      MidiPort* port = &midiPorts[event->port()];
 
963
      port->putEvent(event);
 
964
      if (port->instrument()->hasGui())
 
965
            port->instrument()->writeToGui(event);
 
966
      }
 
967
 
 
968
//---------------------------------------------------------
 
969
//   nextEvents
 
970
//    collects all events between stick - etick
 
971
//---------------------------------------------------------
 
972
 
 
973
void MidiThread::nextEvents(int stick, int etick)
 
974
      {
 
975
      for (iTrack t = song->tracks()->begin(); t != song->tracks()->end(); ++t) {
 
976
            if ((*t)->type() != Track::MIDI && (*t)->type() != Track::DRUM)
 
977
                  continue;
 
978
            MidiTrack* track = (MidiTrack*)(*t);
 
979
            if (track->node()->isMute())
 
980
                  continue;
 
981
            PartList* pl = track->parts();
 
982
            for (iPart p = pl->begin(); p != pl->end(); ++p) {
 
983
                  MidiPart* part    = (MidiPart*)(p->second);
 
984
                  // dont play muted parts
 
985
                  if (part->mute())
 
986
                        continue;
 
987
                  EventList* events = part->events();
 
988
 
 
989
                  int partTick = part->posTick();
 
990
                  int delay    = track->delay;
 
991
                  iEvent ie    = events->lower_bound(stick - delay - partTick);
 
992
                  iEvent iend  = events->lower_bound(etick - delay - partTick);
 
993
 
 
994
                  for (; ie != iend; ++ie) {
 
995
                        MidiEvent* ev = (MidiEvent*)ie->second;
 
996
                        //
 
997
                        //  don�t play any meta events
 
998
                        //
 
999
                        if (ev->type() == MidiEvent::Meta)
 
1000
                              continue;
 
1001
                        if (track->type() == Track::DRUM) {
 
1002
                              int instr = ev->pitch();
 
1003
                              if (ev->isNote() && drumMap[instr].mute) //Ignore muted drums
 
1004
                                    continue;
 
1005
                              }
 
1006
                        int tick    = ev->posTick() + delay + part->posTick();
 
1007
                        int port    = track->outPort();
 
1008
                        int channel =  track->outChannel();
 
1009
                        switch (ev->type()) {
 
1010
                              case MidiEvent::Note:
 
1011
                              case MidiEvent::NoteOff:
 
1012
                                    {
 
1013
                                    int len   = ev->lenTick();
 
1014
                                    int pitch = ev->pitch();
 
1015
                                    if (track->type() == Track::DRUM)  { //Map drum-notes to the drum-map values
 
1016
                                          int instr = ev->pitch();
 
1017
                                          pitch = drumMap[instr].anote;
 
1018
                                          port = drumMap[instr].port;
 
1019
                                          channel = drumMap[instr].channel;
 
1020
                                          }
 
1021
                                    else
 
1022
                                          pitch+= (track->transposition + song->globalPitchShift()); //Transpose non-drum notes
 
1023
 
 
1024
 
 
1025
                                    int velo  = ev->velo();
 
1026
                                    if (pitch > 127)
 
1027
                                          pitch = 127;
 
1028
                                    if (pitch < 0)
 
1029
                                          pitch = 0;
 
1030
                                    velo += track->velocity;
 
1031
                                    velo = (velo * track->compression) / 100;
 
1032
                                    if (velo > 127)
 
1033
                                          velo = 127;
 
1034
                                    if (velo < 1)           // no off event
 
1035
                                          velo = 1;
 
1036
                                    len = (len *  track->len) / 100;
 
1037
                                    if (len <= 0)     // don�t allow zero length
 
1038
                                          len = 1;
 
1039
                                    int veloOff = ev->veloOff();
 
1040
 
 
1041
                                    if (ev->type() == MidiEvent::Note)
 
1042
                                          playEvents.add(tick,
 
1043
                                             port, channel, 0x90, pitch, velo);
 
1044
                                    else
 
1045
                                          playEvents.add(tick,
 
1046
                                             port, channel, 0x80, pitch, veloOff);
 
1047
                                    if (ev->type() == MidiEvent::Note) {
 
1048
                                          stuckNotes.add(tick + len,
 
1049
                                             port, channel,
 
1050
                                             veloOff ? 0x80 : 0x90, pitch, veloOff);
 
1051
                                          track->addActivity(velo);
 
1052
                                          }
 
1053
                                    }
 
1054
                                    break;
 
1055
 
 
1056
                              case MidiEvent::Ctrl7:
 
1057
                              case MidiEvent::Ctrl14:
 
1058
                                    controlChanged = true;
 
1059
                              default:
 
1060
                                    playEvents.add(tick, ev, port, channel);
 
1061
                                    break;
 
1062
                              } //end switch
 
1063
                        }//end for
 
1064
                  }
 
1065
            }
 
1066
      }
 
1067
 
 
1068
//---------------------------------------------------------
 
1069
//   processMidiClock
 
1070
//---------------------------------------------------------
 
1071
 
 
1072
void MidiThread::processMidiClock()
906
1073
      {
907
1074
      if (genMCSync)
908
 
            midiPorts[extSyncPort].clock();
 
1075
            midiPorts[txSyncPort].clock();
909
1076
      if (state == START_PLAY) {
910
1077
            // start play on sync
911
1078
            state         = PLAY;
912
 
            midiTickStart = playTickPos;
913
 
            midiTick      = playTickPos;
914
 
            midiSync      = playTickPos;
915
 
            rtcTickStart  = rtcTick;
916
 
            endSlice      = playTickPos;
917
 
            recTick       = playTickPos;
918
 
            lastTickPos   = playTickPos;
919
 
            startTime     = curTime();
920
 
            recStartTick  = playTickPos;
921
 
            write(sigFd, "1", 1);   // PLAY
 
1079
            _midiTick      = playTickPos;
 
1080
            midiClock     = playTickPos;
 
1081
 
 
1082
            int bar, beat, tick;
 
1083
            sigmap.tickValues(_midiTick, &bar, &beat, &tick);
 
1084
            midiClick      = sigmap.bar2tick(bar, beat+1, 0);
 
1085
 
 
1086
            double cpos    = tempomap.tick2time(playTickPos);
 
1087
            samplePosStart = samplePos - lrint(cpos * sampleRate);
 
1088
            rtcTickStart   = rtcTick - lrint(cpos * realRtcTicks);
 
1089
 
 
1090
            endSlice       = playTickPos;
 
1091
            recTick        = playTickPos;
 
1092
            lastTickPos    = playTickPos;
 
1093
 
 
1094
            tempoSN = tempomap.tempoSN();
 
1095
 
 
1096
            startRecord.setPosTick(playTickPos);
 
1097
            audio->msgPlay(true);
922
1098
            }
 
1099
      midiClock += division/24;
923
1100
      }
924
1101
 
925
1102
//---------------------------------------------------------
926
1103
//   processTimerTick
 
1104
//    fast hardware timer tick interrupt at
 
1105
//    rtcTicks rate
927
1106
//---------------------------------------------------------
928
1107
 
929
 
void MidiThreadPrivate::processTimerTick()
 
1108
void MidiThread::processTimerTick()
930
1109
      {
 
1110
      extern int watchMidi;
 
1111
      ++watchMidi;      // make watchdog happy
 
1112
 
 
1113
      //---------------------------------------------------
 
1114
      //    if tempomap changed, fix
 
1115
      //    samplePosStart and rtcTickStart
 
1116
      //---------------------------------------------------
 
1117
 
 
1118
      if (tempoSN != tempomap.tempoSN()) {
 
1119
            double cpos    = tempomap.tick2time(_midiTick);
 
1120
            samplePosStart = samplePos - lrint(cpos * sampleRate);
 
1121
            rtcTickStart   = rtcTick - lrint(cpos * realRtcTicks);
 
1122
            tempoSN        = tempomap.tempoSN();
 
1123
            }
 
1124
 
 
1125
      //---------------------------------------------------
 
1126
      //    read elapsed rtc timer ticks
 
1127
      //---------------------------------------------------
 
1128
 
931
1129
      int nn = 1;
932
1130
      if (timerFd != -1) {
933
1131
            unsigned long nn;
934
1132
            if (read(timerFd, &nn, sizeof(unsigned long)) != sizeof(unsigned long)) {
935
 
                  perror("illegal timer return");
 
1133
                  perror("rtc timer read error");
936
1134
                  exit(-1);
937
1135
                  }
938
1136
            nn >>= 8;
939
 
            // rtcTicks  (ticks per second);
940
 
            }
941
 
      if (tempoSN != tempomap.tempoSN()) {
942
 
            midiTickStart = midiTick;
943
 
            rtcTickStart  = rtcTick;
944
 
            tempoSN       = tempomap.tempoSN();
945
1137
            }
946
1138
      rtcTick += nn;
947
 
      midiTick = tempomap.time2tick(1.0/realRtcTicks
948
 
                  * (rtcTick - rtcTickStart)) + midiTickStart;
949
 
 
950
 
      if (!extSyncFlag.value() && midiTick >= midiSync) {
951
 
            processMidiTick();
952
 
            midiSync += division/24;
953
 
            }
 
1139
 
 
1140
      //---------------------------------------------------
 
1141
      // compute current midiTick value
 
1142
      //---------------------------------------------------
 
1143
 
 
1144
      if (audioTimebase) {
 
1145
            samplePos = audio->curPlayPos();
 
1146
            _midiTick  = tempomap.time2tick(
 
1147
               double(samplePos - samplePosStart) / double(sampleRate));
 
1148
            }
 
1149
      else {
 
1150
            _midiTick = tempomap.time2tick(
 
1151
               double(rtcTick - rtcTickStart) / double(realRtcTicks)
 
1152
               );
 
1153
            }
 
1154
 
 
1155
      if (!extSyncFlag.value() && _midiTick >= midiClock)
 
1156
            processMidiClock();
954
1157
 
955
1158
      if (genMTCSync) {
956
1159
            // printf("Midi Time Code Sync generation not impl.\n");
957
1160
            }
958
1161
 
959
1162
      if (state == PLAY) {
960
 
            playTickPos = midiTick;
961
 
            if (song->loop() && !extSyncFlag.value()
962
 
               && (playTickPos >= song->rpos())) {
 
1163
            playTickPos = _midiTick;
 
1164
            // start loop division/24-1 ticks earlier
 
1165
            if (song->loop() && !extSyncFlag.value() && (playTickPos >= song->rpos()-division/24+1)) {
963
1166
                  seek(song->lpos());
964
 
                  // loop on next midiSync
 
1167
                  // loop on next midiClock
965
1168
                  return;
966
1169
                  }
967
1170
            if (playTickPos >= endSlice) {
968
1171
                  int next = endSlice + TICK_SLICE;
969
 
                  song->nextEvents(endSlice, next, playEvents);
 
1172
                  nextEvents(endSlice, next);
970
1173
                  endSlice = next;
971
1174
                  }
972
 
            if (playTickPos >= song->len() && !song->record() && !song->loop()) {
 
1175
            if (playTickPos >= song->len() && (!song->record() || song->bounceTrack)
 
1176
               && !song->loop()) {
973
1177
                  stopPlay();
974
1178
                  }
975
1179
            }
976
1180
      if ((state == PRECOUNT || (song->click() && (state == PLAY)))
977
 
         && (midiTick >= midiClick)) {
978
 
            MidiEvent* ev = new MidiEvent(clickPort, clickChan,
979
 
               midiTick, MidiEvent::Note,
980
 
               beatClickNote, beatClickVelo, 0, 4);
 
1181
         && (_midiTick >= midiClick)) {
 
1182
            int bar, beat, tick;
981
1183
            bool isMeasure = false;
982
 
            int bar, beat, tick;
983
1184
            switch (state) {
984
1185
                  case PRECOUNT:
985
 
                        if ((clickno % clicksMeasure) == 0)
986
 
                              isMeasure = true;
987
 
                        if (clickno) {
 
1186
                        isMeasure = (clickno % clicksMeasure) == 0;
 
1187
                        midiClick += ticksBeat;
 
1188
                        if (clickno)
988
1189
                              --clickno;
989
 
                              midiClick += ticksBeat;
990
 
                              break;
991
 
                              }
992
 
                        sigmap.tickValues(playTickPos, &bar, &beat, &tick);
993
 
                        if (beat == 0 && tick == 0)
994
 
                              isMeasure = true;
995
 
                        midiClick = sigmap.bar2tick(bar, beat+1, 0);
996
 
                        state = START_PLAY;
 
1190
                        else
 
1191
                              state = START_PLAY;
997
1192
                        break;
 
1193
 
998
1194
                  case PLAY:
999
 
                        sigmap.tickValues(midiTick, &bar, &beat, &tick);
1000
 
//tick==0?*/            if (beat == 0 && tick == 0)
1001
 
                              isMeasure = true;
 
1195
                        sigmap.tickValues(_midiTick, &bar, &beat, &tick);
1002
1196
                        midiClick = sigmap.bar2tick(bar, beat+1, 0);
 
1197
                        isMeasure = beat == 0;
1003
1198
                        break;
1004
1199
                  default:
1005
1200
                        break;
1006
1201
                  }
 
1202
 
1007
1203
            if (isMeasure) {
1008
 
                  ev->setPitch(measureClickNote);
1009
 
                  ev->setVelo(measureClickVelo);
1010
 
                  }
1011
 
            playEvents->add(ev);
 
1204
                  playEvents.add(_midiTick, clickPort, clickChan, 0x90,
 
1205
                    measureClickNote, measureClickVelo);
 
1206
                  stuckNotes.add(_midiTick+10, clickPort, clickChan, 0x90,
 
1207
                    measureClickNote, 0);
 
1208
                  }
 
1209
            else {
 
1210
                  playEvents.add(_midiTick, clickPort, clickChan, 0x90,
 
1211
                    beatClickNote, beatClickVelo);
 
1212
                  stuckNotes.add(_midiTick+10, clickPort, clickChan, 0x90,
 
1213
                    beatClickNote, 0);
 
1214
                  }
1012
1215
            }
 
1216
      //
 
1217
      //  play all event upto/including _midiTick
 
1218
      //
1013
1219
      SEventList sevents;
1014
 
// printf("midiTick %d\n", midiTick);
1015
 
      EventRange range1 = stuckNotes->equal_range(midiTick);
1016
 
//      for (iEvent k = range1.first; k != range1.second; ++k)
1017
 
      for (iEvent k = stuckNotes->begin(); k != range1.second; ++k)
1018
 
            sevents.push_back(SEvent((MidiEvent*)(k->second)));
1019
 
      EventRange range2 = playEvents->equal_range(midiTick);
1020
 
//      for (iEvent k = range2.first; k != range2.second; ++k)
1021
 
      for (iEvent k = playEvents->begin(); k != range2.second; ++k)
1022
 
            sevents.push_back(SEvent((MidiEvent*)(k->second)));
 
1220
      sevents.clear();
 
1221
 
 
1222
      //   collect stuck notes
 
1223
      MPEventRange range1 = stuckNotes.equal_range(_midiTick);
 
1224
      for (iMPEvent k = stuckNotes.begin(); k != range1.second; ++k)
 
1225
            sevents.push_back(SEvent(&k->second));
 
1226
 
 
1227
      //   collect play notes
 
1228
      MPEventRange range2 = playEvents.equal_range(_midiTick);
 
1229
      for (iMPEvent k = playEvents.begin(); k != range2.second; ++k)
 
1230
            sevents.push_back(SEvent(&k->second));
 
1231
 
1023
1232
      if (!sevents.empty()) {
1024
1233
            sevents.sort();
1025
1234
            for (iSEvent sk = sevents.begin(); sk != sevents.end(); ++sk)
1026
1235
                  playEvent(sk->ev);
1027
 
            EventRange range1 = stuckNotes->equal_range(midiTick);
1028
 
//            stuckNotes->erase(range1.first, range1.second);
1029
 
//            playEvents->erase(range2.first, range2.second);
1030
 
            stuckNotes->erase(stuckNotes->begin(), range1.second);
1031
 
            playEvents->erase(playEvents->begin(), range2.second);
 
1236
            //
 
1237
            // why recompute range1?
 
1238
            MPEventRange range1 = stuckNotes.equal_range(_midiTick);
 
1239
            stuckNotes.erase(stuckNotes.begin(), range1.second);
 
1240
            playEvents.erase(playEvents.begin(), range2.second);
1032
1241
            }
1033
1242
      }
1034
1243