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

« back to all changes in this revision

Viewing changes to sync.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
//=========================================================
 
2
//  MusE
 
3
//  Linux Music Editor
 
4
//  $Id: sync.cpp,v 1.1.1.1 2003/10/29 10:05:10 wschweer Exp $
 
5
//
 
6
//  (C) Copyright 2003 Werner Schweer (ws@seh.de)
 
7
//=========================================================
 
8
 
 
9
#include <cmath>
 
10
#include "midithread.h"
 
11
#include "sync.h"
 
12
#include "song.h"
 
13
#include "utils.h"
 
14
#include "midiport.h"
 
15
#include "mididev.h"
 
16
#include "globals.h"
 
17
 
 
18
int rxSyncPort = -1;         // receive from all ports
 
19
int txSyncPort = 1;
 
20
int rxDeviceId = 0x7f;       // �any� device
 
21
int txDeviceId = 0x7f;       // �any� device
 
22
 
 
23
bool debugSync = false;
 
24
int mtcType     = 1;
 
25
MTC mtcOffset;
 
26
BValue extSyncFlag(0, "extSync");       // false - MASTER, true - SLAVE
 
27
bool genMTCSync = false;      // output MTC Sync
 
28
bool genMCSync  = false;      // output MidiClock Sync
 
29
bool genMMC     = false;      // output Midi Machine Control
 
30
bool acceptMTC  = false;
 
31
bool acceptMC   = true;
 
32
bool acceptMMC  = true;
 
33
 
 
34
static MTC mtcCurTime;
 
35
static int mtcState;    // 0-7 next expected quarter message
 
36
static bool mtcValid;
 
37
static int mtcLost;
 
38
static bool mtcSync;    // receive complete mtc frame?
 
39
 
 
40
static bool mcStart = false;
 
41
static int mcStartTick;
 
42
 
 
43
//---------------------------------------------------------
 
44
//  mmcInput
 
45
//    Midi Machine Control Input received
 
46
//---------------------------------------------------------
 
47
 
 
48
void MidiThread::mmcInput(const unsigned char* p, int n)
 
49
      {
 
50
      if (debugSync)
 
51
            printf("mmcInput: n:%d %02x %02x %02x %02x\n",
 
52
               n, p[2], p[3], p[4], p[5]);
 
53
      if (!(extSyncFlag.value() && acceptMMC))
 
54
            return;
 
55
 
 
56
      switch(p[3]) {
 
57
            case 1:
 
58
                  if (debugSync)
 
59
                        printf("  MMC: STOP\n");
 
60
                  if ((state == PLAY || state == PRECOUNT))
 
61
                        stopPlay();
 
62
                  break;
 
63
            case 2:
 
64
                  if (debugSync)
 
65
                        printf("  MMC: PLAY\n");
 
66
            case 3:
 
67
                  if (debugSync)
 
68
                        printf("  MMC: DEFERRED PLAY\n");
 
69
                  mtcState = 0;
 
70
                  mtcValid = false;
 
71
                  mtcLost  = 0;
 
72
                  mtcSync  = false;
 
73
                  startPlay(song->cpos());
 
74
                  break;
 
75
 
 
76
            case 4:
 
77
                  printf("MMC: FF not implemented\n");
 
78
                  break;
 
79
            case 5:
 
80
                  printf("MMC: REWIND not implemented\n");
 
81
                  break;
 
82
            case 6:
 
83
                  printf("MMC: REC STROBE not implemented\n");
 
84
                  break;
 
85
            case 7:
 
86
                  printf("MMC: REC EXIT not implemented\n");
 
87
                  break;
 
88
            case 0xd:
 
89
                  printf("MMC: RESET not implemented\n");
 
90
                  break;
 
91
            case 0x44:
 
92
                  if (p[5] == 0) {
 
93
                        printf("MMC: LOCATE IF not implemented\n");
 
94
                        break;
 
95
                        }
 
96
                  else if (p[5] == 1) {
 
97
                        MTC mtc(p[6] & 0x1f, p[7], p[8], p[9], p[10]);
 
98
                        int mmcPos = tempomap.time2tick(mtc.time());
 
99
 
 
100
                        seek(mmcPos);
 
101
                        if (debugSync) {
 
102
                              printf("MMC: %f %d seek ",
 
103
                                 mtc.time(), mmcPos);
 
104
                              mtc.print();
 
105
                              printf("\n");
 
106
                              }
 
107
                        write(sigFd, "G", 1);
 
108
                        break;
 
109
                        }
 
110
                  // fall through
 
111
            default:
 
112
                  printf("MMC %x %x, unknown\n", p[3], p[4]); break;
 
113
            }
 
114
      }
 
115
 
 
116
//---------------------------------------------------------
 
117
//   mtcInputQuarter
 
118
//    process Quarter Frame Message
 
119
//---------------------------------------------------------
 
120
 
 
121
void MidiThread::mtcInputQuarter(int, unsigned char c)
 
122
      {
 
123
      static int hour, min, sec, frame;
 
124
 
 
125
      if (!extSyncFlag.value())
 
126
            return;
 
127
 
 
128
      int valL = c & 0xf;
 
129
      int valH = valL << 4;
 
130
 
 
131
      int _state = (c & 0x70) >> 4;
 
132
      if (mtcState != _state)
 
133
            mtcLost += _state - mtcState;
 
134
      mtcState = _state + 1;
 
135
 
 
136
      switch(_state) {
 
137
            case 7:
 
138
                  hour  = (hour  & 0x0f) | valH;
 
139
                  break;
 
140
            case 6:
 
141
                  hour  = (hour  & 0xf0) | valL;
 
142
                  break;
 
143
            case 5:
 
144
                  min   = (min   & 0x0f) | valH;
 
145
                  break;
 
146
            case 4:
 
147
                  min   = (min   & 0xf0) | valL;
 
148
                  break;
 
149
            case 3:
 
150
                  sec   = (sec   & 0x0f) | valH;
 
151
                  break;
 
152
            case 2:
 
153
                  sec   = (sec   & 0xf0) | valL;
 
154
                  break;
 
155
            case 1:
 
156
                  frame = (frame & 0x0f) | valH;
 
157
                  break;
 
158
            case 0:  frame = (frame & 0xf0) | valL;
 
159
                  break;
 
160
            }
 
161
      frame &= 0x1f;    // 0-29
 
162
      sec   &= 0x3f;    // 0-59
 
163
      min   &= 0x3f;    // 0-59
 
164
      hour  &= 0x1f;
 
165
 
 
166
      if (mtcState == 8) {
 
167
            mtcValid = (mtcLost == 0);
 
168
            mtcState = 0;
 
169
            mtcLost  = 0;
 
170
            if (mtcValid) {
 
171
                  mtcCurTime.set(hour, min, sec, frame);
 
172
                  mtcSyncMsg(mtcCurTime, !mtcSync);
 
173
                  mtcSync = true;
 
174
                  }
 
175
            }
 
176
      else if (mtcValid && (mtcLost == 0)) {
 
177
            mtcCurTime.incQuarter();
 
178
            mtcSyncMsg(mtcCurTime, false);
 
179
            }
 
180
      }
 
181
 
 
182
//---------------------------------------------------------
 
183
//   mtcInputFull
 
184
//    process Frame Message
 
185
//---------------------------------------------------------
 
186
 
 
187
void MidiThread::mtcInputFull(const unsigned char* p, int n)
 
188
      {
 
189
      if (debugSync)
 
190
            printf("mtcInputFull\n");
 
191
      if (!extSyncFlag.value())
 
192
            return;
 
193
 
 
194
      if (p[3] != 1) {
 
195
            if (p[3] != 2) {   // silently ignore user bits
 
196
                  printf("unknown mtc msg subtype 0x%02x\n", p[3]);
 
197
                  dump(p, n);
 
198
                  }
 
199
            return;
 
200
            }
 
201
      int hour  = p[4];
 
202
      int min   = p[5];
 
203
      int sec   = p[6];
 
204
      int frame = p[7];
 
205
 
 
206
      frame &= 0x1f;    // 0-29
 
207
      sec   &= 0x3f;    // 0-59
 
208
      min   &= 0x3f;    // 0-59
 
209
//      int type = (hour >> 5) & 3;
 
210
      hour &= 0x1f;
 
211
 
 
212
      mtcCurTime.set(hour, min, sec, frame);
 
213
      mtcState = 0;
 
214
      mtcValid = true;
 
215
      mtcLost  = 0;
 
216
      }
 
217
 
 
218
//---------------------------------------------------------
 
219
//   nonRealtimeSystemSysex
 
220
//---------------------------------------------------------
 
221
 
 
222
void MidiThread::nonRealtimeSystemSysex(const unsigned char* p, int n)
 
223
      {
 
224
//      int chan = p[2];
 
225
      switch(p[3]) {
 
226
            case 4:
 
227
                  printf("NRT Setup\n");
 
228
                  break;
 
229
            default:
 
230
                  printf("unknown NRT Msg 0x%02x\n", p[3]);
 
231
                  dump(p, n);
 
232
                  break;
 
233
           }
 
234
      }
 
235
 
 
236
//---------------------------------------------------------
 
237
//   setSongPosition
 
238
//    MidiBeat is a 14 Bit value. Each MidiBeat spans
 
239
//    6 MIDI Clocks. Inother words, each MIDI Beat is a
 
240
//    16th note (since there are 24 MIDI Clocks in a
 
241
//    quarter note).
 
242
//---------------------------------------------------------
 
243
 
 
244
void MidiThread::setSongPosition(int port, int midiBeat)
 
245
      {
 
246
      if (midiInputTrace)
 
247
            printf("set song position port:%d %d\n", port, midiBeat);
 
248
      if (!extSyncFlag.value())
 
249
            return;
 
250
      playTickPos = midiClick = (division * midiBeat) / 4;
 
251
      if (debugSync)
 
252
            printf("setSongPosition %d\n", playTickPos);
 
253
      write(sigFd, "G", 1);
 
254
      }
 
255
 
 
256
//---------------------------------------------------------
 
257
//   realtimeSystemInput
 
258
//    real time message received
 
259
//---------------------------------------------------------
 
260
 
 
261
void MidiThread::realtimeSystemInput(int port, int c)
 
262
      {
 
263
      if (midiInputTrace)
 
264
            printf("realtimeSystemInput port:%d 0x%x\n", port+1, c);
 
265
 
 
266
      if (midiInputTrace && (rxSyncPort != port) && rxSyncPort != -1) {
 
267
            if (debugSync)
 
268
                  printf("rxSyncPort configured as %d; received sync from port %d\n",
 
269
                     rxSyncPort, port);
 
270
            return;
 
271
            }
 
272
      if (!extSyncFlag.value())
 
273
            return;
 
274
      switch(c) {
 
275
            case 0xf8:  // midi clock (24 ticks / quarter note)
 
276
                  {
 
277
                  double mclock0 = curTime();
 
278
                  processMidiClock();
 
279
                  if (state == PLAY) {
 
280
                        recTick  += division / 24;
 
281
                        int diff  = recTick - _midiTick;
 
282
                        int tempo = tempomap.tempo(0);
 
283
                        tempo    -= diff*5;
 
284
                        tempomap.setTempo(0, tempo);
 
285
                        _midiTick = recTick;  // brutal
 
286
                        break;
 
287
                        }
 
288
                  double tdiff0   = mclock0 - mclock1;
 
289
                  double tdiff1   = mclock1 - mclock2;
 
290
                  if (mclock1 == 0.0)
 
291
                        midiPorts[port].device()->discardInput();
 
292
                  if ((mclock2 != 0.0) && (tdiff0 > 0.0)) {
 
293
                        int tempo0 = int(24000000.0 * tdiff0 + .5);
 
294
                        int tempo1 = int(24000000.0 * tdiff1 + .5);
 
295
                        int tempo = tempomap.tempo(0);
 
296
 
 
297
                        int diff0 = tempo0 - tempo;
 
298
                        int diff1 = tempo1 - tempo0;
 
299
                        if (diff0) {
 
300
                              int newTempo = tempo + diff0/8 + diff1/16;
 
301
                              tempomap.setTempo(0, newTempo);
 
302
                              }
 
303
                        }
 
304
                  mclock2 = mclock1;
 
305
                  mclock1 = mclock0;
 
306
                  }
 
307
                  break;
 
308
            case 0xf9:  // midi tick  (every 10 msec)
 
309
                  if (mcStart) {
 
310
                        song->setPos(0, mcStartTick);
 
311
                        mcStart = false;
 
312
                        return;
 
313
                        }
 
314
                  break;
 
315
            case 0xfa:  // start
 
316
                  if (debugSync)
 
317
                        printf("   start\n");
 
318
                  if (state == IDLE) {
 
319
                        seek(0);
 
320
                        startPlay(song->cpos());
 
321
                        }
 
322
                  break;
 
323
            case 0xfb:  // continue
 
324
                  if (debugSync)
 
325
                        printf("   continue\n");
 
326
                  if (state == IDLE) {
 
327
                        startPlay(song->cpos());
 
328
                        }
 
329
                  break;
 
330
            case 0xfc:  // stop
 
331
                  if (debugSync)
 
332
                        printf("   stop\n");
 
333
                  if (state == PLAY)
 
334
                        stopPlay();
 
335
                  break;
 
336
            case 0xfd:  // unknown
 
337
            case 0xfe:  // active sensing
 
338
            case 0xff:  // system reset
 
339
                  break;
 
340
            }
 
341
      }
 
342
 
 
343
//---------------------------------------------------------
 
344
//   mtcSyncMsg
 
345
//    process received mtc Sync
 
346
//    seekFlag - first complete mtc frame received after
 
347
//                start
 
348
//---------------------------------------------------------
 
349
 
 
350
void MidiThread::mtcSyncMsg(const MTC& mtc, bool seekFlag)
 
351
      {
 
352
      double time = mtc.time();
 
353
      if (debugSync)
 
354
            printf("mtcSyncMsg: time %f\n", time);
 
355
 
 
356
      if (seekFlag && state == START_PLAY) {
 
357
//            int tick = tempomap.time2tick(time);
 
358
            state = PLAY;
 
359
            write(sigFd, "1", 1);  // say PLAY to gui
 
360
            return;
 
361
            }
 
362
      // double curT = curTime();
 
363
 
 
364
      if (tempoSN != tempomap.tempoSN()) {
 
365
            double cpos    = tempomap.tick2time(_midiTick, 0);
 
366
            samplePosStart = samplePos - lrint(cpos * sampleRate);
 
367
            rtcTickStart   = rtcTick - lrint(cpos * realRtcTicks);
 
368
            tempoSN        = tempomap.tempoSN();
 
369
            }
 
370
 
 
371
      //
 
372
      // diff is the time in sec MusE is out of sync
 
373
      //
 
374
      double diff = time - (double(samplePosStart)/double(sampleRate));
 
375
      if (debugSync)
 
376
            printf("   state %d diff %f\n", mtcState, diff);
 
377
      }
 
378
 
 
379