Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/MD_package/MDPlayer_MacOSX.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 181 - (show annotations) (download) (as text)
Sat Feb 29 15:29:29 2020 UTC (4 years, 2 months ago) by toshinagata1964
File MIME type: text/x-csrc
File size: 88895 byte(s)
Keyswitch will be sent while prerolling
1 /*
2 * MDPlayer_MacOSX.c
3 *
4 * Created by Toshi Nagata on Sun Jul 01 2001.
5
6 Copyright (c) 2000-2016 Toshi Nagata. All rights reserved.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation version 2 of the License.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 */
17
18 #include "MDHeaders.h"
19 #include "MDPlayer_MacOSX.h"
20 #include "MDAudio.h"
21
22 /* Define macros such as 'AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER'; these are used in AUGraph.h etc. */
23 /* AUGraph.h (and maybe other headers) must really include this header; maybe I need to file a bug. */
24 #include <AvailabilityMacros.h>
25
26 //#define USE_TIME_MANAGER 1
27
28 #if !USE_TIME_MANAGER
29 #include <pthread.h>
30 #else
31 #include <CoreServices/CoreServices.h> /* for Time Manager (Classic MacOS-like -> obsolete in Mac OS 10.4) */
32 #endif
33
34 #include <CoreMIDI/CoreMIDI.h> /* for MIDI input/output */
35 #include <CoreAudio/CoreAudio.h> /* for AudioConvertNanosToHostTime() */
36 /*#include <unistd.h> *//* for usleep() */
37
38 #pragma mark ====== Definitions ======
39
40 #if USE_TIME_MANAGER
41 typedef struct MyTMTask {
42 TMTask tmTask;
43 MDPlayer *player;
44 } MyTMTask;
45 #endif
46
47 #define kInvalidUniqueID 0
48
49 typedef struct MDMIDIDeviceRecord {
50 MIDIEndpointRef eref; /* CoreMIDI endpoint */
51 MIDISysexSendRequest sysexRequest; /* Sysex send request */
52 MIDIPacketList packetList; /* MIDI packet list */
53 } MDMIDIDeviceRecord;
54
55 typedef struct MDPatchNameRecord {
56 UInt32 instno; /* 0xMMLLPP, MM: bank MSB, LL: bank LSB, PP: program number */
57 char *name;
58 } MDPatchNameRecord;
59
60 typedef struct MDDeviceIDRecord {
61 char * name;
62
63 /* OS-specific fields for identification of devices */
64 /* Only one of uniqueID or streamIndex is valid */
65 int streamIndex; /* MDAudioIOStream index (= bus index of Audio setup) */
66 int uniqueID; /* CoreMIDI device */
67 MDMIDIDeviceRecord *midiRec; /* CoreMIDI device record (malloc'ed) */
68
69 /* Patch names */
70 int npatches;
71 MDPatchNameRecord *patches;
72
73 } MDDeviceIDRecord;
74
75 typedef struct MDDeviceInfo {
76 char initialized; /* non-zero if already initialized */
77 int32_t destNum; /* The number of destinations */
78 MDDeviceIDRecord *dest; /* The names of destinations */
79 int32_t sourceNum; /* The number of sources */
80 MDDeviceIDRecord *source; /* The names of sources */
81 } MDDeviceInfo;
82
83 static MDDeviceInfo sDeviceInfo = { 0, 0, NULL, 0, NULL };
84
85 /* Information for MIDI output */
86 typedef struct MDDestinationInfo {
87 int32_t refCount;
88 int32_t dev; /* Index to sDeviceInfo.dest[] */
89
90 /* CoreMIDI (Mac OS X) specfic fields */
91 int32_t bytesToSend;
92 int numEvents;
93 // MIDIEndpointRef eref; /* MIDI device */
94 // MusicDeviceComponent comp; /* MusicDevice */
95 // int streamIndex; /* Index of MDAudioIOStreamInfo (same as MDDeviceIDRecord.streamIndex) */
96 MIDIPacketList packetList;
97 MIDIPacket * packetPtr;
98 MDTimeType timeOfLastEvent;
99 MIDISysexSendRequest sysexRequest;
100 unsigned char sysexTransmitting; /* non-zero if sysexRequest is being processed */
101
102 MDTrackMerger * merger;
103 MDEvent * currentEp;
104 MDTrack * currentTrack;
105 MDTickType currentTick;
106 MDTrack * noteOff; /* Keep the 'internal' note off */
107 MDPointer * noteOffPtr;
108 MDTickType noteOffTick;
109
110 } MDDestinationInfo;
111
112 #define MIDIObjectNull ((MIDIObjectRef)0)
113
114 /* CoreMIDI (Mac OS X) specific static variables */
115 static MIDIClientRef sMIDIClientRef = MIDIObjectNull;
116 static MIDIPortRef sMIDIInputPortRef = MIDIObjectNull;
117 static MIDIPortRef sMIDIOutputPortRef = MIDIObjectNull;
118
119 /* Forward declaration of the MIDI read callback */
120 static void MyMIDIReadProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon);
121
122 #define kMDRecordingBufferSize 32768
123 /*#define kMDRecordingBufferSize 99 *//* Small buffer for debugging */
124
125 typedef struct MDRecordingBuffer {
126 struct MDRecordingBuffer *next;
127 int32_t size;
128 unsigned char data[4];
129 } MDRecordingBuffer;
130
131 typedef struct MDRecordingEventHeader {
132 MDTimeType timeStamp;
133 int32_t size;
134 } MDRecordingEventHeader;
135
136 struct MDPlayer {
137 int32_t refCount;
138 MDSequence * sequence;
139 MDCalibrator * calib; /* for tick <-> time conversion */
140 MDTimeType time; /* the last time when interrupt fired */
141 MDTimeType startTime; /* In microseconds */
142 MDTickType lastTick; /* tick of the last event already sent */
143 MDPlayerStatus status;
144 unsigned char shouldTerminate; /* Flag to request the playing thread to terminate */
145
146 /* Destination list */
147 int32_t destNum; /* The number of destinations used in this player */
148 MDDestinationInfo **destInfo; /* Information for MIDI output */
149
150 /* Metronome status */
151 MDTickType nextMetronomeBar; /* Tick to ring the metronome bell (top of bar) */
152 MDTickType nextMetronomeBeat; /* Tick to ring the metronome click (each beat) */
153 int metronomeBar; /* Bar length */
154 int metronomeBeat; /* Beat length */
155 MDTickType nextTimeSignature; /* Next time signature change for metronome */
156
157 /* Count-off metronome */
158 MDTimeType countOffDuration; /* Time (in microseconds) for count-off */
159 MDTimeType countOffEndTime; /* End time for count-off */
160 MDTimeType countOffBar; /* Bar duration for count-off; if zero, then only beat tap will be sent out */
161 MDTimeType countOffBeat; /* Beat duration for count-off */
162 MDTimeType countOffFirstRing; /* First time for count-off metronome note */
163 MDTimeType countOffNextRing; /* Last time for count-off metronome note */
164
165 /* Recording info */
166 unsigned char isRecording;
167 MDTickType recordingStopTick;
168
169 MDAudio * audio;
170
171 /* Recording buffer */
172 MDRecordingBuffer *topBuffer;
173 int32_t topPos;
174 int32_t topSize;
175 MDRecordingBuffer *bottomBuffer;
176 int32_t bottomPos;
177 int32_t bottomSize;
178 MDRecordingBuffer *topFreeBuffer;
179 MDRecordingBuffer *bottomFreeBuffer;
180
181 /* Temporary storage for converting recorded data to MDEvent */
182 unsigned char * tempStorage;
183 int32_t tempStorageSize;
184 int32_t tempStorageLength;
185 int32_t tempStorageIndex;
186 unsigned char runningStatusByte;
187
188 /* CoreMIDI (Mac OS X) specific fields */
189 #if !USE_TIME_MANAGER
190 pthread_t playThread;
191
192 #else
193 MyTMTask myTMTask;
194 #endif
195 };
196
197 static MDPlayer *sRecordingPlayer = NULL; /* the MDPlayer that receives the incoming MIDI messages */
198
199 /* TODO: Don't use MIDI device directly. Use MDDestinationInfo instead. */
200 //static int32_t sMIDIThruDevice = -1;
201 //static MIDIEndpointRef sMIDIThruDeviceRef = MIDIObjectNull;
202
203 //static MDDestinationInfo *sMIDIThruDestination = NULL;
204 static int32_t sMIDIThruDevice = -1;
205 static int sMIDIThruChannel = 0; /* 0..15; if 16, then incoming channel number is kept */
206 static int sMIDIThruTranspose = 0;
207
208 /* Minimum interval of interrupts */
209 #define kMDPlayerMinimumInterval 50000 /* 50 msec */
210 #define kMDPlayerMaximumInterval 100000 /* 100 msec */
211
212 /* Prefetch interval */
213 #define kMDPlayerPrefetchInterval 100000 /* 100 msec */
214
215 MetronomeInfoRecord gMetronomeInfo;
216
217 #pragma mark ====== Utility function ======
218
219 int
220 my_usleep(uint32_t useconds)
221 {
222 struct timespec req_time, rem_time;
223 req_time.tv_sec = useconds / 1000000;
224 req_time.tv_nsec = (useconds % 1000000) * 1000;
225 return nanosleep(&req_time, &rem_time);
226 }
227
228 #pragma mark ====== Device Management ======
229
230 static void
231 MDPlayerDumpNames(MIDIObjectRef ref)
232 {
233 CFStringRef name;
234 char buf[256];
235 MIDIObjectGetStringProperty(ref, kMIDIPropertyManufacturer, &name);
236 CFStringGetCString(name, buf, 255, CFStringGetSystemEncoding());
237 fprintf(stderr, "Manufacturer = %s\n", buf);
238 CFRelease(name);
239 MIDIObjectGetStringProperty(ref, kMIDIPropertyModel, &name);
240 CFStringGetCString(name, buf, 255, CFStringGetSystemEncoding());
241 fprintf(stderr, "Model = %s\n", buf);
242 CFRelease(name);
243 MIDIObjectGetStringProperty(ref, kMIDIPropertyName, &name);
244 CFStringGetCString(name, buf, 255, CFStringGetSystemEncoding());
245 fprintf(stderr, "Name = %s\n", buf);
246 CFRelease(name);
247 }
248
249 static void
250 MDPlayerReloadDeviceInformationSub(MDDeviceIDRecord **src_dst_p, int32_t *src_dst_Num_p, int is_dst)
251 {
252 MIDIEndpointRef eref, eref1;
253 MIDIDeviceRef dref;
254 MIDIEntityRef entref;
255 CFStringRef name, devname, name1;
256 int32_t n, dev, ent, en, num;
257 char buf[256], *p;
258 SInt32 uniqueID;
259 int i;
260
261 /* Look up all src/dst, compare the unique ID, and update the name */
262 num = (int)(is_dst ? MIDIGetNumberOfDestinations() : MIDIGetNumberOfSources());
263 for (n = 0; n < num; n++) {
264 eref = (is_dst ? MIDIGetDestination(n) : MIDIGetSource(n));
265 MIDIObjectGetStringProperty(eref, kMIDIPropertyName, &name);
266 if (MIDIObjectGetIntegerProperty(eref, kMIDIPropertyUniqueID, &uniqueID) != noErr)
267 uniqueID = 0;
268 /* Search the device/entity/endpoint tree */
269 for (dev = (int)MIDIGetNumberOfDevices() - 1; dev >= 0; dev--) {
270 dref = MIDIGetDevice(dev);
271 for (ent = (int)MIDIDeviceGetNumberOfEntities(dref) - 1; ent >= 0; ent--) {
272 entref = MIDIDeviceGetEntity(dref, ent);
273 en = (int)(is_dst ? MIDIEntityGetNumberOfDestinations(entref) : MIDIEntityGetNumberOfSources(entref)) - 1;
274 for ( ; en >= 0; en--) {
275 eref1 = (is_dst ? MIDIEntityGetDestination(entref, en) : MIDIEntityGetSource(entref, en));
276 if (eref1 == eref)
277 goto found1;
278 }
279 }
280 }
281 found1:
282 if (dev >= 0) {
283 MIDIObjectType objType;
284 MIDIObjectRef oref;
285 SInt32 uid;
286 if (MIDIObjectGetIntegerProperty(eref, kMIDIPropertyConnectionUniqueID, &uid) == noErr
287 && uid != 0
288 && MIDIObjectFindByUniqueID(uid, &oref, &objType) == noErr) {
289 MDPlayerDumpNames(oref);
290 MIDIObjectGetStringProperty(oref, kMIDIPropertyName, &name);
291 } else {
292 MIDIObjectGetStringProperty(dref, kMIDIPropertyName, &devname);
293 name1 = name;
294 name = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@-%@"), devname, name);
295 CFRelease(name1);
296 CFRelease(devname);
297 }
298 }
299 if (!CFStringGetCString(name, buf, 255, kCFStringEncodingUTF8))
300 sprintf(buf, "(Device %d)", n);
301 buf[255] = 0;
302 /* Look up in the existing table whether this device is already there (by uniqueID) */
303 for (i = 0; i < *src_dst_Num_p; i++) {
304 if ((*src_dst_p)[i].uniqueID == uniqueID)
305 break;
306 }
307 if (i >= 0 && i < *src_dst_Num_p) {
308 /* If found, then update the name and eref */
309 p = (*src_dst_p)[i].name;
310 if (p == NULL || strcmp(p, buf) != 0) {
311 if (p != NULL)
312 free(p);
313 p = (char *)malloc(strlen(buf) + 1);
314 strcpy(p, buf);
315 (*src_dst_p)[i].name = p;
316 }
317 } else {
318 /* Look up by device name, and create a new entry if not found */
319 i = (is_dst ? MDPlayerAddDestinationName(buf) : MDPlayerAddSourceName(buf));
320 }
321 /* And update the uniqueID */
322 if (i >= 0 && i < *src_dst_Num_p) {
323 MDDeviceIDRecord *dp = *src_dst_p + i;
324 if (dp->midiRec == NULL) {
325 dp->midiRec = (MDMIDIDeviceRecord *)calloc(sizeof(MDMIDIDeviceRecord), 1);
326 if (dp->midiRec == NULL)
327 return;
328 /* Raise sysex completion flag (to enable sysex sending) */
329 dp->midiRec->sysexRequest.complete = 1;
330 }
331 dp->uniqueID = uniqueID;
332 dp->streamIndex = -1;
333 dp->midiRec->eref = eref;
334 }
335 }
336
337 /* Handle MusicDevice */
338 if (is_dst) {
339 MDAudioIOStreamInfo *ip;
340 int j;
341 for (i = 0; i < kMDAudioNumberOfInputStreams; i++) {
342 ip = MDAudioGetIOStreamInfoAtIndex(i);
343 if (ip->midiControllerName == NULL)
344 continue;
345 for (j = 0; j < *src_dst_Num_p; j++) {
346 p = (*src_dst_p)[j].name;
347 if (p == NULL || strcmp(p, ip->midiControllerName) == 0)
348 break;
349 }
350 if (j >= *src_dst_Num_p) {
351 j = MDPlayerAddDestinationName(ip->midiControllerName);
352 }
353 if (j >= 0 && j < *src_dst_Num_p) {
354 /* Update the device info */
355 (*src_dst_p)[j].uniqueID = kInvalidUniqueID;
356 (*src_dst_p)[j].midiRec = NULL;
357 (*src_dst_p)[j].streamIndex = i;
358 MDPlayerUpdatePatchNames(j);
359 }
360 }
361 }
362 }
363
364 static void
365 sCoreMIDINotifyProc(const MIDINotification *message, void *refCon)
366 {
367 if (message->messageID == kMIDIMsgSetupChanged) {
368 // MDPlayerReloadDeviceInformation();
369 MDPlayerNotificationCallback();
370 }
371 }
372
373 /* --------------------------------------
374 ��� MDPlayerInitCoreMIDI
375 -------------------------------------- */
376 void
377 MDPlayerInitCoreMIDI(void)
378 {
379 if (sDeviceInfo.initialized)
380 return;
381
382 if (sMIDIClientRef == MIDIObjectNull)
383 MIDIClientCreate(CFSTR("Alchemusica"), sCoreMIDINotifyProc, NULL, &sMIDIClientRef);
384 if (sMIDIOutputPortRef == MIDIObjectNull)
385 MIDIOutputPortCreate(sMIDIClientRef, CFSTR("Output port"), &sMIDIOutputPortRef);
386 if (sMIDIInputPortRef == MIDIObjectNull)
387 MIDIInputPortCreate(sMIDIClientRef, CFSTR("Input port"), MyMIDIReadProc, NULL, &sMIDIInputPortRef);
388 sDeviceInfo.initialized = 1;
389 }
390
391 /* --------------------------------------
392 ��� MDPlayerReloadDeviceInformation
393 -------------------------------------- */
394 void
395 MDPlayerReloadDeviceInformation(void)
396 {
397 int n;
398
399 if (!sDeviceInfo.initialized)
400 MDPlayerInitCoreMIDI();
401
402 /* Disconnect the previous MIDI sources from the input port */
403 for (n = 0; n < sDeviceInfo.sourceNum; n++) {
404 if (sDeviceInfo.source[n].uniqueID != kInvalidUniqueID) {
405 MIDIPortDisconnectSource(sMIDIInputPortRef, sDeviceInfo.source[n].midiRec->eref);
406 }
407 }
408
409 /* Update the device information */
410 /* The device index to the same device [i.e. the device with the same uniqueID] remains the same. */
411 MDPlayerReloadDeviceInformationSub(&(sDeviceInfo.dest), &(sDeviceInfo.destNum), 1);
412 MDPlayerReloadDeviceInformationSub(&(sDeviceInfo.source), &(sDeviceInfo.sourceNum), 0);
413
414 /* Connect the updated MIDI sources to the input port */
415 for (n = 0; n < sDeviceInfo.sourceNum; n++) {
416 if (sDeviceInfo.source[n].uniqueID != kInvalidUniqueID) {
417 MIDIPortConnectSource(sMIDIInputPortRef, sDeviceInfo.source[n].midiRec->eref, (void *)(intptr_t)n);
418 }
419 }
420 }
421
422 /* --------------------------------------
423 ��� MDPlayerGetNumberOfDestinations
424 -------------------------------------- */
425 int32_t
426 MDPlayerGetNumberOfDestinations(void)
427 {
428 /* if (!sDeviceInfo.initialized)
429 MDPlayerReloadDeviceInformation(); */
430 return sDeviceInfo.destNum;
431 }
432
433 /* --------------------------------------
434 ��� MDPlayerGetDestinationName
435 -------------------------------------- */
436 MDStatus
437 MDPlayerGetDestinationName(int32_t dev, char *name, int32_t sizeof_name)
438 {
439 /* if (!sDeviceInfo.initialized)
440 MDPlayerReloadDeviceInformation(); */
441 if (dev >= 0 && dev < sDeviceInfo.destNum) {
442 strncpy(name, sDeviceInfo.dest[dev].name, sizeof_name - 1);
443 name[sizeof_name - 1] = 0;
444 return kMDNoError;
445 } else {
446 name[0] = 0;
447 return kMDErrorBadDeviceNumber;
448 }
449 }
450
451 /* --------------------------------------
452 ��� MDPlayerGetDestinationNumberFromName
453 -------------------------------------- */
454 int32_t
455 MDPlayerGetDestinationNumberFromName(const char *name)
456 {
457 int32_t dev;
458 /* if (!sDeviceInfo.initialized)
459 MDPlayerReloadDeviceInformation(); */
460 for (dev = 0; dev < sDeviceInfo.destNum; dev++) {
461 if (strcmp(name, sDeviceInfo.dest[dev].name) == 0)
462 return dev;
463 }
464 return -1;
465 }
466
467 /* --------------------------------------
468 ��� MDPlayerGetNumberOfSources
469 -------------------------------------- */
470 int32_t
471 MDPlayerGetNumberOfSources(void)
472 {
473 /* if (!sDeviceInfo.initialized)
474 MDPlayerReloadDeviceInformation(); */
475 return sDeviceInfo.sourceNum;
476 }
477
478 /* --------------------------------------
479 ��� MDPlayerGetSourceName
480 -------------------------------------- */
481 MDStatus
482 MDPlayerGetSourceName(int32_t dev, char *name, int32_t sizeof_name)
483 {
484 /* if (!sDeviceInfo.initialized)
485 MDPlayerReloadDeviceInformation(); */
486 if (dev >= 0 && dev < sDeviceInfo.sourceNum) {
487 strncpy(name, sDeviceInfo.source[dev].name, sizeof_name - 1);
488 name[sizeof_name - 1] = 0;
489 return kMDNoError;
490 } else {
491 name[0] = 0;
492 return kMDErrorBadDeviceNumber;
493 }
494 }
495
496 /* --------------------------------------
497 ��� MDPlayerGetSourceNumberFromName
498 -------------------------------------- */
499 int32_t
500 MDPlayerGetSourceNumberFromName(const char *name)
501 {
502 int32_t dev;
503 /* if (!sDeviceInfo.initialized)
504 MDPlayerReloadDeviceInformation(); */
505 for (dev = 0; dev < sDeviceInfo.sourceNum; dev++) {
506 if (strcmp(name, sDeviceInfo.source[dev].name) == 0)
507 return dev;
508 }
509 return -1;
510 }
511
512 /* --------------------------------------
513 ��� MDPlayerAddDestinationName
514 -------------------------------------- */
515 int32_t
516 MDPlayerAddDestinationName(const char *name)
517 {
518 int32_t dev;
519 /* if (!sDeviceInfo.initialized)
520 MDPlayerReloadDeviceInformation(); */
521 dev = MDPlayerGetDestinationNumberFromName(name);
522 if (dev < 0) {
523 /* Expand the array */
524 MDDeviceIDRecord *idp;
525 dev = sDeviceInfo.destNum;
526 if (sDeviceInfo.dest != NULL)
527 idp = (MDDeviceIDRecord *)realloc(sDeviceInfo.dest, sizeof(MDDeviceIDRecord) * (dev + 1));
528 else
529 idp = (MDDeviceIDRecord *)malloc(sizeof(MDDeviceIDRecord) * (dev + 1));
530 memset(&idp[dev], 0, sizeof(MDDeviceIDRecord));
531 idp[dev].name = (char *)malloc(strlen(name) + 1);
532 strcpy(idp[dev].name, name);
533 sDeviceInfo.dest = idp;
534 sDeviceInfo.destNum = dev + 1;
535 }
536 return dev;
537 }
538
539 /* --------------------------------------
540 ��� MDPlayerAddSourceName
541 -------------------------------------- */
542 int32_t
543 MDPlayerAddSourceName(const char *name)
544 {
545 int32_t dev;
546 dev = MDPlayerGetSourceNumberFromName(name);
547 if (dev < 0) {
548 /* Expand the array */
549 MDDeviceIDRecord *idp;
550 dev = sDeviceInfo.sourceNum;
551 if (sDeviceInfo.source != NULL)
552 idp = (MDDeviceIDRecord *)realloc(sDeviceInfo.source, sizeof(MDDeviceIDRecord) * (dev + 1));
553 else
554 idp = (MDDeviceIDRecord *)malloc(sizeof(MDDeviceIDRecord) * (dev + 1));
555 memset(&idp[dev], 0, sizeof(MDDeviceIDRecord));
556 idp[dev].name = (char *)malloc(strlen(name) + 1);
557 strcpy(idp[dev].name, name);
558 sDeviceInfo.source = idp;
559 sDeviceInfo.sourceNum = dev + 1;
560 }
561 return dev;
562 }
563
564 /* --------------------------------------
565 ��� MDPlayerUpdatePatchNames
566 -------------------------------------- */
567 /* Update the patch name info for the given device. */
568 int
569 MDPlayerUpdatePatchNames(int32_t dev)
570 {
571 MDDeviceIDRecord *rp;
572 int i;
573 if (dev < 0 || dev >= sDeviceInfo.destNum)
574 return -1; /* Invalid device */
575 rp = &(sDeviceInfo.dest[dev]);
576 if (rp->uniqueID != kInvalidUniqueID) {
577 /* TODO: Implement patch list for external MIDI device */
578 return -1;
579 } else if (rp->streamIndex >= 0) {
580 /* MusicDevice */
581 OSStatus err;
582 UInt32 count, instno;
583 UInt32 datasize;
584 MDAudioIOStreamInfo *mp = MDAudioGetIOStreamInfoAtIndex(rp->streamIndex);
585 if (mp == NULL)
586 return -1;
587 datasize = sizeof(UInt32);
588 err = AudioUnitGetProperty(mp->unit, kMusicDeviceProperty_InstrumentCount, kAudioUnitScope_Global, 0, &count, &datasize);
589 if (err != noErr)
590 return -1;
591 if (rp->npatches > 0) {
592 /* Free previous info */
593 for (i = 0; i < rp->npatches; i++) {
594 free(rp->patches[i].name);
595 }
596 free(rp->patches);
597 rp->patches = NULL;
598 rp->npatches = 0;
599 }
600 if (count > 0) {
601 rp->patches = (MDPatchNameRecord *)calloc(sizeof(MDPatchNameRecord), count);
602 rp->npatches = 0;
603 for (i = 0; i < count; i++) {
604 char name[256];
605 datasize = sizeof(instno);
606 err = AudioUnitGetProperty(mp->unit, kMusicDeviceProperty_InstrumentNumber, kAudioUnitScope_Global, i, &instno, &datasize);
607 if (err != noErr)
608 continue;
609 datasize = sizeof(name);
610 err = AudioUnitGetProperty(mp->unit, kMusicDeviceProperty_InstrumentName, kAudioUnitScope_Global, instno, name, &datasize);
611 if (err != noErr)
612 continue;
613 rp->patches[rp->npatches].instno = instno;
614 rp->patches[rp->npatches].name = strdup(name);
615 rp->npatches++;
616 }
617 }
618 return rp->npatches;
619 }
620 return -1;
621 }
622
623 /* --------------------------------------
624 ��� MDPlayerGetNumberOfPatchNames
625 -------------------------------------- */
626 /* Returns the number of available patch names. */
627 int
628 MDPlayerGetNumberOfPatchNames(int32_t dev)
629 {
630 if (dev >= 0 && dev < sDeviceInfo.destNum) {
631 return sDeviceInfo.dest[dev].npatches;
632 } else return 0;
633 }
634
635 /* --------------------------------------
636 ��� MDPlayerGetPatchName
637 -------------------------------------- */
638 /* Returns the patch name if available. If bank is -1, then progno is the index that
639 scans all registered patch information. If bank is 0xMMLL (MM and LL are the bank
640 select MSB and LSB), then the progno is the program number (0-127).
641 Returns the patch number (0xMMLLPP) if the patch name is available, -1 otherwise */
642 int
643 MDPlayerGetPatchName(int32_t dev, int bank, int progno, char *name, int32_t sizeof_name)
644 {
645 int idx = -1;
646 if (dev >= 0 && dev < sDeviceInfo.destNum) {
647 if (bank == -1) {
648 if (progno >= 0 && progno < sDeviceInfo.dest[dev].npatches)
649 idx = progno;
650 } else if (progno >= 0 && progno < 128) {
651 /* Look for the given bank and program */
652 UInt32 instno = (bank << 8) + progno;
653 for (idx = sDeviceInfo.dest[dev].npatches - 1; idx >= 0; idx--) {
654 MDPatchNameRecord *pr = &(sDeviceInfo.dest[dev].patches[idx]);
655 if (pr->instno == instno)
656 break;
657 }
658 }
659 }
660 if (idx >= 0) {
661 strncpy(name, sDeviceInfo.dest[dev].patches[idx].name, sizeof_name - 1);
662 name[sizeof_name - 1] = 0;
663 return sDeviceInfo.dest[dev].patches[idx].instno;
664 } else return -1;
665 }
666
667 /* --------------------------------------
668 ��� MDPlayerInitDestinationInfo
669 -------------------------------------- */
670 static void
671 MDPlayerInitDestinationInfo(MDDestinationInfo *info, int32_t dev)
672 {
673 info->dev = dev;
674 info->bytesToSend = 0;
675 info->sysexTransmitting = 0;
676 info->packetPtr = MIDIPacketListInit(&info->packetList);
677 }
678
679 /* --------------------------------------
680 ��� MDPlayerNewDestinationInfo
681 -------------------------------------- */
682 static MDDestinationInfo *
683 MDPlayerNewDestinationInfo(int32_t dev)
684 {
685 MDDestinationInfo *info;
686 info = (MDDestinationInfo *)malloc(sizeof(MDDestinationInfo));
687 if (info == NULL)
688 return NULL;
689 memset(info, 0, sizeof(MDDestinationInfo));
690 info->refCount = 1;
691 MDPlayerInitDestinationInfo(info, dev);
692 return info;
693 }
694
695 /* --------------------------------------
696 ��� MDPlayerReleaseDestinationInfo
697 -------------------------------------- */
698 static void
699 MDPlayerReleaseDestinationInfo(MDDestinationInfo *info)
700 {
701 if (info != NULL) {
702 info->refCount--;
703 if (info->refCount == 0) {
704 if (info->merger != NULL)
705 MDTrackMergerRelease(info->merger);
706 if (info->noteOffPtr != NULL)
707 MDPointerRelease(info->noteOffPtr);
708 if (info->noteOff != NULL)
709 MDTrackRelease(info->noteOff);
710 free(info);
711 }
712 }
713 }
714
715 #pragma mark ====== Internal MIDI Functions ======
716
717 #if DEBUG
718 static FILE *sMIDIInputDump;
719 #endif
720
721 static void
722 MDPlayerReleaseRecordingBuffer(MDPlayer *inPlayer)
723 {
724 MDRecordingBuffer *buf1, *buf2;
725 if (inPlayer == NULL)
726 return;
727 buf1 = inPlayer->bottomBuffer;
728 while (buf1 != NULL) {
729 buf2 = buf1->next;
730 free(buf1);
731 buf1 = buf2;
732 }
733 buf1 = inPlayer->bottomFreeBuffer;
734 while (buf1 != NULL) {
735 buf2 = buf1->next;
736 free(buf1);
737 buf1 = buf2;
738 }
739 inPlayer->topBuffer = inPlayer->bottomBuffer = NULL;
740 inPlayer->topFreeBuffer = inPlayer->bottomFreeBuffer = NULL;
741 inPlayer->topPos = inPlayer->bottomPos = inPlayer->topSize = inPlayer->bottomSize = 0;
742 }
743
744 static MDRecordingBuffer *
745 AllocateOneRecordingBuffer(void)
746 {
747 MDRecordingBuffer *buf;
748 buf = (MDRecordingBuffer *)malloc(sizeof(MDRecordingBuffer) - 4 + kMDRecordingBufferSize);
749 if (buf != NULL) {
750 memset(buf, 0, sizeof(MDRecordingBuffer) - 4 + kMDRecordingBufferSize);
751 buf->size = kMDRecordingBufferSize;
752 }
753 return buf;
754 }
755
756 static MDRecordingBuffer *
757 MDPlayerAllocateRecordingBuffer(MDPlayer *inPlayer)
758 {
759 MDRecordingBuffer *buf;
760 if (inPlayer == NULL)
761 return NULL;
762 if (inPlayer->topBuffer == NULL) {
763 /* First invocation: allocate one buffer for immediate use, and
764 two buffers for later use */
765 buf = AllocateOneRecordingBuffer();
766 if (buf == NULL)
767 return NULL;
768 inPlayer->topBuffer = inPlayer->bottomBuffer = buf;
769 inPlayer->topPos = inPlayer->bottomPos = inPlayer->topSize = inPlayer->bottomSize = 0;
770 buf = AllocateOneRecordingBuffer();
771 if (buf == NULL)
772 return NULL;
773 inPlayer->topFreeBuffer = buf;
774 buf = AllocateOneRecordingBuffer();
775 if (buf == NULL)
776 return NULL;
777 inPlayer->bottomFreeBuffer = buf;
778 buf->next = inPlayer->topFreeBuffer;
779 } else {
780 if (inPlayer->topBuffer->next != NULL)
781 return inPlayer->topBuffer->next; /* No need to allocate */
782 if (inPlayer->bottomFreeBuffer != NULL && inPlayer->bottomFreeBuffer->next != NULL) {
783 buf = inPlayer->bottomFreeBuffer;
784 inPlayer->bottomFreeBuffer = buf->next;
785 memset(buf->data, 0, kMDRecordingBufferSize);
786 #if DEBUG
787 if (gMDVerbose >= 2) {
788 MDRecordingBuffer *b;
789 fprintf(stderr, "%d %s[%d]: freeBuffer ", 2, __FILE__, __LINE__);
790 for (b = inPlayer->bottomFreeBuffer; b != NULL; b = b->next)
791 fprintf(stderr, "%p -> ", b);
792 fprintf(stderr, "(NULL)\n");
793 }
794 #endif
795 } else {
796 buf = AllocateOneRecordingBuffer();
797 if (buf == NULL)
798 return NULL;
799 }
800 buf->next = NULL;
801 inPlayer->topBuffer->next = buf;
802 inPlayer->topBuffer = buf;
803 }
804 return inPlayer->topBuffer;
805 }
806
807 int
808 MDPlayerPutRecordingData(MDPlayer *inPlayer, MDTimeType timeStamp, int32_t size, const unsigned char *buf)
809 {
810 unsigned char *op;
811 MDRecordingEventHeader header;
812 MDRecordingBuffer *topBuffer;
813 int32_t topPos;
814 int32_t nsize, n;
815
816 if (inPlayer == NULL)
817 return -1;
818 if (inPlayer->topBuffer == NULL) {
819 if (MDPlayerAllocateRecordingBuffer(inPlayer) == NULL)
820 return -3; /* Out of memory */
821 }
822 topBuffer = inPlayer->topBuffer;
823 topPos = inPlayer->topPos;
824 op = topBuffer->data + topPos;
825 header.timeStamp = timeStamp;
826 header.size = size;
827 nsize = sizeof(header);
828 n = topBuffer->size - topPos;
829 if (n < nsize) {
830 memcpy(op, (unsigned char *)(&header), n);
831 nsize -= n;
832 if (MDPlayerAllocateRecordingBuffer(inPlayer) == NULL)
833 return -3; /* Out of memory */
834 topBuffer = topBuffer->next;
835 topPos = 0;
836 op = topBuffer->data;
837 }
838 if (nsize > 0) {
839 memcpy(op, (unsigned char *)(&header) + sizeof(header) - nsize, nsize);
840 topPos += nsize;
841 op += nsize;
842 }
843 nsize = size;
844 while (nsize > 0) {
845 n = topBuffer->size - topPos;
846 if (n <= 0) {
847 if (MDPlayerAllocateRecordingBuffer(inPlayer) == NULL)
848 return -3; /* Out of memory */
849 topBuffer = topBuffer->next;
850 topPos = 0;
851 n = topBuffer->size;
852 }
853 if (n > nsize)
854 n = nsize;
855 memcpy(topBuffer->data + topPos, buf, n);
856 buf += n;
857 nsize -= n;
858 topPos += n;
859 }
860 inPlayer->topBuffer = topBuffer;
861 inPlayer->topPos = topPos;
862 inPlayer->topSize += header.size + sizeof(header);
863 return 0;
864 }
865
866 int
867 MDPlayerGetRecordingData(MDPlayer *inPlayer, MDTimeType *outTimeStamp, int32_t *outSize, unsigned char **outBuf, int32_t *outBufSize)
868 {
869 /* **outBuf and *outBufSize must contain valid values on calling, with a malloc'ed
870 pointer in **outBuf and its size in *outBufSize. On return, both may be changed
871 via realloc() when the buffer size is not sufficient */
872 unsigned char *ip, *op;
873 MDRecordingEventHeader header;
874 MDRecordingBuffer *bottomBuffer;
875 int32_t bottomPos;
876 int32_t size, n;
877 if (inPlayer == NULL || inPlayer->bottomBuffer == NULL || inPlayer->bottomSize >= inPlayer->topSize)
878 return -1;
879 bottomBuffer = inPlayer->bottomBuffer;
880 bottomPos = inPlayer->bottomPos;
881 ip = bottomBuffer->data + bottomPos;
882 size = sizeof(header);
883 if (inPlayer->topSize - inPlayer->bottomSize <= size)
884 return -2; /* Internal inconsistency */
885 n = bottomBuffer->size - bottomPos;
886 if (n < size) {
887 memcpy((unsigned char *)(&header), ip, n);
888 size -= n;
889 bottomBuffer = bottomBuffer->next;
890 bottomPos = 0;
891 ip = bottomBuffer->data;
892 }
893 if (size > 0) {
894 memcpy((unsigned char *)(&header) + sizeof(header) - size, ip, size);
895 bottomPos += size;
896 ip += size;
897 }
898 size = header.size;
899 if (inPlayer->topSize - inPlayer->bottomSize < size + sizeof(header))
900 return -2; /* Internal inconsistency */
901 if (*outBuf == NULL) {
902 n = (size + 4) / 4 * 4;
903 *outBuf = (unsigned char *)malloc(n);
904 if (*outBuf == NULL)
905 return -3; /* Out of memory */
906 *outBufSize = n;
907 } else if (*outBufSize <= size) {
908 n = (size + 4) / 4 * 4;
909 op = (unsigned char *)realloc(*outBuf, n);
910 if (op == NULL)
911 return -3; /* Out of memory */
912 *outBuf = op;
913 *outBufSize = n;
914 }
915 op = *outBuf;
916 while (size > 0) {
917 n = bottomBuffer->size - bottomPos;
918 if (n <= 0) {
919 bottomBuffer = bottomBuffer->next;
920 bottomPos = 0;
921 n = bottomBuffer->size;
922 }
923 if (n > size)
924 n = size;
925 memcpy(op, bottomBuffer->data + bottomPos, n);
926 op += n;
927 size -= n;
928 bottomPos += n;
929 }
930 if (bottomBuffer->size <= bottomPos) {
931 bottomBuffer = bottomBuffer->next;
932 bottomPos = 0;
933 }
934 if (inPlayer->bottomBuffer != bottomBuffer && inPlayer->topFreeBuffer != NULL) {
935 /* Put to the free block list for reuse */
936 MDRecordingBuffer *buf;
937 buf = inPlayer->bottomBuffer;
938 while (buf->next != NULL && buf->next != bottomBuffer)
939 buf = buf->next;
940 buf->next = NULL;
941 inPlayer->topFreeBuffer->next = inPlayer->bottomBuffer;
942 inPlayer->topFreeBuffer = buf;
943 #if DEBUG
944 if (gMDVerbose >= 2) {
945 fprintf(stderr, "%d %s[%d]: freeBuffer ", 2, __FILE__, __LINE__);
946 for (buf = inPlayer->bottomFreeBuffer; buf != NULL; buf = buf->next)
947 fprintf(stderr, "%p -> ", buf);
948 fprintf(stderr, "(NULL)\n");
949 }
950 #endif
951 }
952 inPlayer->bottomBuffer = bottomBuffer;
953 inPlayer->bottomPos = bottomPos;
954 inPlayer->bottomSize += header.size + sizeof(header);
955 *outTimeStamp = header.timeStamp;
956 *outSize = header.size;
957 #if DEBUG
958 {
959 if (sMIDIInputDump != NULL) {
960 int i;
961 fprintf(sMIDIInputDump, "-%qd ", (int64_t)*outTimeStamp);
962 for (i = 0; i < header.size; i++) {
963 fprintf(sMIDIInputDump, "%02x%c", (*outBuf)[i], (i == header.size - 1 ? '\n' : ' '));
964 }
965 }
966 }
967 #endif
968 return 0;
969 }
970
971 #if 0
972 static void
973 MySysexCompletionProc(MIDISysexSendRequest *request)
974 {
975 request->bytesToSend = 0;
976 *((unsigned char *)(request->completionRefCon)) = 0;
977 }
978 #endif
979
980 static int
981 ScheduleMIDIEventToDevice(int32_t dev, UInt64 timeStamp, int length, unsigned char *data)
982 {
983 OSStatus sts;
984 if (dev < 0 || dev >= sDeviceInfo.destNum)
985 return 0; /* No output */
986 MDDeviceIDRecord *rp = &(sDeviceInfo.dest[dev]);
987 if (rp->midiRec != NULL) {
988 /* Real MIDI device */
989 MDMIDIDeviceRecord *mrec = rp->midiRec;
990 MIDIPacket *packet;
991 packet = MIDIPacketListInit(&mrec->packetList);
992 packet = MIDIPacketListAdd(&mrec->packetList, sizeof(mrec->packetList), packet, timeStamp, length, data);
993 if (packet != NULL) {
994 /* Send packet */
995 sts = MIDISend(sMIDIOutputPortRef, mrec->eref, &mrec->packetList);
996 } else sts = 1;
997 if (sts != 0 && data[0] == 0xf0 && mrec->sysexRequest.complete != 0) {
998 /* Try to send sysex */
999 mrec->sysexRequest.destination = mrec->eref;
1000 mrec->sysexRequest.data = data;
1001 mrec->sysexRequest.bytesToSend = length;
1002 mrec->sysexRequest.complete = 0;
1003 mrec->sysexRequest.completionProc = NULL;
1004 mrec->sysexRequest.completionRefCon = NULL;
1005 sts = MIDISendSysex(&mrec->sysexRequest);
1006 }
1007 return (sts == 0 ? length : -1);
1008 } else if (rp->streamIndex >= 0) {
1009 MDAudioIOStreamInfo *ip = MDAudioGetIOStreamInfoAtIndex(rp->streamIndex);
1010 // printf("%lld %d %02x %02x...\n", ConvertHostTimeToMDTimeType(timeStamp), length, data[0], data[1]);
1011 sts = MDAudioScheduleMIDIToStream(ip, timeStamp, length, data, 0);
1012 if (sts != 0 && data[0] == 0xf0) {
1013 /* Try to send sysex */
1014 sts = MDAudioScheduleMIDIToStream(ip, timeStamp, length, data, 1);
1015 }
1016 return (sts == 0 ? length : -1);
1017 } else return 0; /* No output */
1018 }
1019
1020 static int
1021 ScheduleMDEventToDevice(int32_t dev, UInt64 timeStamp, MDEvent *ep, int channel)
1022 {
1023 unsigned char buf[4];
1024 unsigned char *p;
1025 int32_t len;
1026 if (MDIsSysexEvent(ep)) {
1027 p = MDGetMessagePtr(ep, &len);
1028 } else if (MDIsChannelEvent(ep)) {
1029 memset(buf, 0, 4);
1030 len = MDEventToMIDIMessage(ep, buf);
1031 buf[0] |= channel;
1032 p = buf;
1033 } else return 0; /* No output */
1034 return ScheduleMIDIEventToDevice(dev, timeStamp, len, p);
1035 }
1036
1037 static void
1038 MyMIDIReadProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon)
1039 {
1040 MDTimeType now, myTimeStamp;
1041 MIDIPacket *packet;
1042 unsigned char recordingFlag;
1043 int i, j, n;
1044
1045 // dprintf(0, "MyMIDIReadProc invoked\n");
1046 if (sRecordingPlayer == NULL || sRecordingPlayer->isRecording == 0)
1047 recordingFlag = 0;
1048 else {
1049 recordingFlag = 1;
1050 now = GetHostTimeInMDTimeType() - sRecordingPlayer->startTime;
1051 }
1052 packet = (MIDIPacket *)pktlist->packet;
1053 for (i = 0; i < pktlist->numPackets; i++, packet = MIDIPacketNext(packet)) {
1054 if (sMIDIThruTranspose != 0) {
1055 /* Transpose */
1056 for (j = 0; j < packet->length; j++) {
1057 if (packet->data[j] >= 0x80 && packet->data[j] <= 0x9f) {
1058 n = packet->data[j + 1] + sMIDIThruTranspose;
1059 if (n >= 0 && n < 128)
1060 packet->data[j + 1] = n;
1061 }
1062 }
1063 }
1064 if (recordingFlag) {
1065 if (packet->timeStamp != 0) {
1066 myTimeStamp = ConvertHostTimeToMDTimeType(packet->timeStamp) - sRecordingPlayer->startTime;
1067 } else myTimeStamp = now;
1068 n = MDPlayerPutRecordingData(sRecordingPlayer, myTimeStamp, (int32_t)(packet->length), (unsigned char *)(packet->data));
1069 }
1070 /* Echo back */
1071 if (sMIDIThruDevice >= 0) {
1072 if (sMIDIThruChannel >= 0 && sMIDIThruChannel < 16) {
1073 /* Rechannelize status bytes */
1074 for (j = 0; j < packet->length; j++) {
1075 if (packet->data[j] >= 0x80 && packet->data[j] < 0xf0)
1076 packet->data[j] = (packet->data[j] & 0xf0) | sMIDIThruChannel;
1077 }
1078 }
1079 ScheduleMIDIEventToDevice(sMIDIThruDevice, packet->timeStamp, packet->length, packet->data);
1080 }
1081 }
1082 }
1083
1084 static void
1085 RegisterEventInNoteOffTrack(MDDestinationInfo *info, const MDEvent *ep)
1086 {
1087 MDEvent *ep0;
1088 MDPointerJumpToTick(info->noteOffPtr, MDGetTick(ep) + 1);
1089 MDPointerInsertAnEvent(info->noteOffPtr, ep);
1090 MDPointerSetPosition(info->noteOffPtr, 0);
1091 if ((ep0 = MDPointerCurrent(info->noteOffPtr)) != NULL)
1092 info->noteOffTick = MDGetTick(ep0);
1093 else info->noteOffTick = kMDMaxTick;
1094 }
1095
1096 static void
1097 PrepareMetronomeForTick(MDPlayer *inPlayer, MDTickType inTick)
1098 {
1099 MDEvent *ep;
1100 int32_t timebase = MDSequenceGetTimebase(inPlayer->sequence);
1101 MDTickType t, t0;
1102 int32_t beat, bar;
1103 MDCalibratorJumpToTick(inPlayer->calib, inTick);
1104 ep = MDCalibratorGetEvent(inPlayer->calib, NULL, kMDEventTimeSignature, -1);
1105 MDEventCalculateMetronomeBarAndBeat(ep, timebase, &bar, &beat);
1106 inPlayer->metronomeBeat = beat;
1107 inPlayer->metronomeBar = bar;
1108 t = (ep == NULL ? 0 : MDGetTick(ep));
1109 /* if (ep == NULL) {
1110 t = 0;
1111 inPlayer->metronomeBeat = timebase;
1112 inPlayer->metronomeBar = timebase * 4;
1113 } else {
1114 const unsigned char *p = MDGetMetaDataPtr(ep);
1115 t = MDGetTick(ep);
1116 inPlayer->metronomeBeat = timebase * p[2] / 24;
1117 inPlayer->metronomeBar = timebase * p[0] * 4 / (1 << p[1]);
1118 if (inPlayer->metronomeBar < timebase / 64)
1119 inPlayer->metronomeBar = timebase;
1120 if (inPlayer->metronomeBeat < timebase / 64)
1121 inPlayer->metronomeBeat = inPlayer->metronomeBar;
1122 } */
1123 inPlayer->nextMetronomeBar = t + (inTick - t + inPlayer->metronomeBar - 1) / inPlayer->metronomeBar * inPlayer->metronomeBar;
1124 t0 = inPlayer->nextMetronomeBar;
1125 if (t0 > inTick)
1126 t0 -= inPlayer->metronomeBar;
1127 inPlayer->nextMetronomeBeat = t0 + (inTick - t0 + inPlayer->metronomeBeat - 1) / inPlayer->metronomeBeat * inPlayer->metronomeBeat;
1128 if (inPlayer->nextMetronomeBeat > inPlayer->nextMetronomeBar)
1129 inPlayer->nextMetronomeBeat = inPlayer->nextMetronomeBar;
1130 ep = MDCalibratorGetNextEvent(inPlayer->calib, NULL, kMDEventTimeSignature, -1);
1131 if (ep == NULL)
1132 inPlayer->nextTimeSignature = kMDMaxTick;
1133 else inPlayer->nextTimeSignature = MDGetTick(ep);
1134 }
1135
1136 /* Send MIDI events before prefetch_tick to their destinations */
1137 /* foreach destination {
1138 while true {
1139 get_one_event # metronome, internal note-off, or MIDI event
1140 if beyond stop_tick {
1141 set next_tick
1142 break
1143 }
1144 if beyond prefetch_tick {
1145 # stop_tick should be handled by the caller as prefetch_tick
1146 set next_tick
1147 break # to next destination
1148 } else if cannot schedule {
1149 set next_tick
1150 break # to next destination
1151 }
1152 }
1153 }
1154 */
1155
1156 enum {
1157 kNoScheduleType = 0,
1158 kMetronomeScheduleType,
1159 kNoteOffScheduleType,
1160 kTrackScheduleType,
1161 kMutedScheduleType
1162 };
1163
1164 static int32_t
1165 SendMIDIEventsBeforeTick(MDPlayer *inPlayer, MDTickType now_tick, MDTickType prefetch_tick, MDTickType *outNextTick)
1166 {
1167 int n, bytesToSend = 0;
1168 MDTickType sequenceDuration = MDSequenceGetDuration(inPlayer->sequence);
1169 MDTickType nextTick = kMDMaxTick;
1170
1171 for (n = 0; n < inPlayer->destNum; n++) {
1172 MDDestinationInfo *info;
1173 MDTickType currentTick;
1174 info = inPlayer->destInfo[n];
1175 while (1) {
1176 unsigned char scheduleType = kTrackScheduleType;
1177 MDEvent *ep, metEvent, offEvent;
1178 unsigned char channel, isBell;
1179
1180 currentTick = info->currentTick;
1181 if (info->currentEp == NULL) {
1182 /* No event */
1183 currentTick = kMDMaxTick;
1184 scheduleType = kNoScheduleType;
1185 } else {
1186 MDTrackAttribute attr;
1187 attr = MDTrackGetAttribute(info->currentTrack);
1188 if (attr & (kMDTrackAttributeMute | kMDTrackAttributeMuteBySolo))
1189 scheduleType = kMutedScheduleType;
1190 }
1191
1192 /* Registered note-off? */
1193 if (info->noteOffTick <= currentTick) {
1194 scheduleType = kNoteOffScheduleType;
1195 currentTick = info->noteOffTick;
1196 }
1197
1198 /* Metronome device? */
1199 if (gMetronomeInfo.dev == info->dev) {
1200 if (gMetronomeInfo.enableWhenPlay || (gMetronomeInfo.enableWhenRecord && inPlayer->isRecording)) {
1201 MDTickType metroTick;
1202 if (inPlayer->nextMetronomeBeat < 0) {
1203 PrepareMetronomeForTick(inPlayer, now_tick);
1204 }
1205 metroTick = inPlayer->nextMetronomeBeat;
1206 if (!inPlayer->isRecording && metroTick >= sequenceDuration) {
1207 /* Metronome will not ring after sequence duration
1208 unless MIDI recording is on */
1209 metroTick = kMDMaxTick;
1210 }
1211 if (metroTick <= currentTick) {
1212 /* Metronome event is earlier */
1213 scheduleType = kMetronomeScheduleType;
1214 currentTick = metroTick;
1215 isBell = (metroTick == inPlayer->nextMetronomeBar);
1216 }
1217 }
1218 }
1219
1220 /* Out of range? */
1221 if (currentTick >= prefetch_tick)
1222 break;
1223
1224 /* Prepare MIDI event */
1225 if (scheduleType == kMetronomeScheduleType) {
1226 MDTickType metDuration;
1227 MDEventInit(&metEvent);
1228 MDSetKind(&metEvent, kMDEventNote);
1229 MDSetCode(&metEvent, (isBell ? gMetronomeInfo.note1 : gMetronomeInfo.note2));
1230 MDSetNoteOnVelocity(&metEvent, (isBell ? gMetronomeInfo.vel1 : gMetronomeInfo.vel2));
1231 MDSetNoteOffVelocity(&metEvent, 0);
1232 MDSetTick(&metEvent, currentTick);
1233 MDSetChannel(&metEvent, gMetronomeInfo.channel & 15);
1234 metDuration = MDCalibratorTimeToTick(inPlayer->calib, MDCalibratorTickToTime(inPlayer->calib, currentTick) + gMetronomeInfo.duration) - currentTick;
1235 MDSetDuration(&metEvent, metDuration);
1236 ep = &metEvent;
1237 channel = gMetronomeInfo.channel & 15;
1238 // printf("Metronome %ld %c\n", currentTick, (isBell ? '*' : ' '));
1239 } else if (scheduleType == kNoteOffScheduleType) {
1240 ep = MDPointerCurrent(info->noteOffPtr);
1241 channel = MDGetChannel(ep);
1242 } else if (scheduleType == kTrackScheduleType) {
1243 ep = info->currentEp;
1244 channel = MDTrackGetTrackChannel(info->currentTrack);
1245 if (MDIsMetaEvent(ep)) {
1246 ep = NULL;
1247 }
1248 } else ep = NULL;
1249
1250 if (ep != NULL) {
1251 int len;
1252 MDTimeType scheduleTime = MDCalibratorTickToTime(inPlayer->calib, currentTick);
1253 UInt64 timeStamp = ConvertMDTimeTypeToHostTime(scheduleTime + inPlayer->startTime);
1254 /* Schedule the MIDI event to the device */
1255 len = ScheduleMDEventToDevice(info->dev, timeStamp, ep, channel);
1256 if (len < 0) {
1257 /* Unsuccessful: break loop and continue to the next destination */
1258 break;
1259 }
1260 bytesToSend += len;
1261 if (scheduleType == kMetronomeScheduleType) {
1262 /* Proceed to the next metronome event */
1263 if (inPlayer->nextMetronomeBar == inPlayer->nextMetronomeBeat)
1264 inPlayer->nextMetronomeBar += inPlayer->metronomeBar;
1265 inPlayer->nextMetronomeBeat += inPlayer->metronomeBeat;
1266 if (inPlayer->nextMetronomeBeat > inPlayer->nextMetronomeBar)
1267 inPlayer->nextMetronomeBeat = inPlayer->nextMetronomeBar;
1268 if (inPlayer->nextMetronomeBar >= inPlayer->nextTimeSignature) {
1269 PrepareMetronomeForTick(inPlayer, inPlayer->nextMetronomeBeat);
1270 }
1271 } else if (scheduleType == kNoteOffScheduleType) {
1272 /* Unregister this internal-note-off */
1273 MDPointerDeleteAnEvent(info->noteOffPtr, NULL);
1274 MDPointerSetPosition(info->noteOffPtr, 0);
1275 if ((ep = MDPointerCurrent(info->noteOffPtr)) != NULL)
1276 info->noteOffTick = MDGetTick(ep);
1277 else info->noteOffTick = kMDMaxTick;
1278 } else if (MDGetKind(ep) == kMDEventNote) {
1279 /* Register an internal-note-off */
1280 MDSetKind(&offEvent, kMDEventInternalNoteOff);
1281 MDSetCode(&offEvent, MDGetCode(ep));
1282 MDSetChannel(&offEvent, channel);
1283 MDSetNoteOffVelocity(&offEvent, MDGetNoteOffVelocity(ep));
1284 MDSetTick(&offEvent, MDGetTick(ep) + MDGetDuration(ep));
1285 RegisterEventInNoteOffTrack(info, &offEvent);
1286 }
1287 }
1288 if (scheduleType == kTrackScheduleType || scheduleType == kMutedScheduleType) {
1289 /* Proceed to next event */
1290 info->currentEp = MDTrackMergerForward(info->merger, &(info->currentTrack));
1291 if (info->currentEp != NULL)
1292 info->currentTick = MDGetTick(info->currentEp);
1293 else info->currentTick = kMDMaxTick;
1294 }
1295 }
1296 /* At this point, currentTick is 'the tick of the next event'
1297 (if no more event are present, then kMDMaxTick) */
1298 if (currentTick < nextTick)
1299 nextTick = currentTick;
1300 }
1301 if (nextTick == kMDMaxTick) {
1302 if (prefetch_tick < sequenceDuration) {
1303 /* If no more event is present but sequence duration is not reached */
1304 nextTick = sequenceDuration;
1305 } else if (inPlayer->isRecording) {
1306 /* If no more event is present but is recording MIDI, then continue playing */
1307 nextTick = prefetch_tick + 1;
1308 }
1309 }
1310 *outNextTick = nextTick;
1311 return bytesToSend;
1312 }
1313
1314 static int32_t
1315 MyTimerFunc(MDPlayer *player)
1316 {
1317 MDTimeType now_time, last_time;
1318 MDTimeType time_to_wait;
1319 MDTickType now_tick, prefetch_tick, tick;
1320 MDSequence *sequence;
1321 int32_t n;
1322
1323 if (player == NULL)
1324 return -1;
1325
1326 sequence = player->sequence;
1327
1328 now_time = GetHostTimeInMDTimeType() - player->startTime;
1329 if (now_time < player->countOffEndTime) {
1330 /* During count-off */
1331 MDTimeType time1, time2;
1332 if (player->countOffNextRing < player->countOffEndTime && player->countOffNextRing < now_time + kMDPlayerPrefetchInterval) {
1333 /* Ring the metronome */
1334 int isBell = 0;
1335 if (player->countOffBar > 0 && (player->countOffNextRing - player->countOffFirstRing) % player->countOffBar == 0)
1336 isBell = 1;
1337 MDPlayerRingMetronomeClick(player, player->countOffNextRing, isBell);
1338 /* Next metronome */
1339 time1 = player->countOffNextRing + player->countOffBeat;
1340 if (player->countOffBar > 0) {
1341 time2 = ((player->countOffNextRing - player->countOffFirstRing) / player->countOffBar + 1) * player->countOffBar + player->countOffFirstRing;
1342 if (time2 < time1)
1343 time1 = time2;
1344 }
1345 player->countOffNextRing = time1;
1346 }
1347 time1 = player->countOffNextRing - now_time;
1348 time2 = player->countOffEndTime - now_time;
1349 time_to_wait = (time1 < time2 ? time1 : time2);
1350 if (time_to_wait < kMDPlayerMinimumInterval)
1351 time_to_wait = kMDPlayerMinimumInterval;
1352 return (int32_t)time_to_wait;
1353 }
1354 player->time = now_time;
1355 now_tick = MDCalibratorTimeToTick(player->calib, now_time);
1356 prefetch_tick = MDCalibratorTimeToTick(player->calib, now_time + kMDPlayerPrefetchInterval);
1357 last_time = 0;
1358
1359 if (MDSequenceTryLock(sequence) == 0) {
1360 /* if (now_tick >= player->recordingStopTick) {
1361 if (player->isRecording)
1362 MDPlayerStopRecording(player);
1363 if (MDAudioIsRecording())
1364 MDAudioStopRecording();
1365 player->recordingStopTick = kMDMaxTick;
1366 } */
1367 n = SendMIDIEventsBeforeTick(player, now_tick, prefetch_tick, &tick);
1368 // printf("now_tick = %ld tick = %ld\n", now_tick, tick);
1369 if (tick >= kMDMaxTick) {
1370 player->status = kMDPlayer_exhausted;
1371 time_to_wait = -1;
1372 } else {
1373 time_to_wait = now_time - MDCalibratorTickToTime(player->calib, tick);
1374 if (time_to_wait > kMDPlayerPrefetchInterval)
1375 time_to_wait = kMDPlayerPrefetchInterval;
1376 else if (time_to_wait < kMDPlayerMinimumInterval)
1377 time_to_wait = kMDPlayerMinimumInterval;
1378 }
1379 MDSequenceUnlock(sequence);
1380 } else {
1381 n = 0;
1382 time_to_wait = kMDPlayerPrefetchInterval;
1383 }
1384 return (int32_t)time_to_wait;
1385
1386 #if 0
1387 player->time = now_time;
1388 if (tick >= kMDMaxTick && !player->isRecording && !MDAudioIsRecording()) {
1389 player->status = kMDPlayer_exhausted;
1390 // player->time = MDCalibratorTickToTime(player->calib, MDSequenceGetDuration(MDMergerGetSequence(player->merger)));
1391 if (tick >= kMDMaxTick)
1392 tick = MDSequenceGetDuration(sequence);
1393 player->time = MDCalibratorTickToTime(player->calib, tick);
1394 return -1;
1395 } else {
1396 if (now_tick >= player->recordingStopTick) {
1397 if (player->isRecording)
1398 MDPlayerStopRecording(player);
1399 if (MDAudioIsRecording())
1400 MDAudioStopRecording();
1401 player->recordingStopTick = kMDMaxTick;
1402 }
1403 if (tick >= kMDMaxTick && player->nextMetronomeBeat < tick)
1404 tick = player->nextMetronomeBeat;
1405 next_time = MDCalibratorTickToTime(player->calib, tick + 1);
1406 next_time -= (now_time + kMDPlayerPrefetchInterval);
1407 if (next_time < kMDPlayerMinimumInterval)
1408 next_time = kMDPlayerMinimumInterval;
1409 if (next_time < last_time - now_time)
1410 next_time = last_time - now_time;
1411 return (int32_t)next_time;
1412 }
1413 #endif
1414 }
1415
1416 #if !USE_TIME_MANAGER
1417 void *
1418 MyThreadFunc(void *param)
1419 {
1420 MDPlayer *player = (MDPlayer *)param;
1421 int32_t time_to_wait;
1422 while ((player->status == kMDPlayer_playing || (player->status == kMDPlayer_exhausted && player->isRecording)) && player->shouldTerminate == 0) {
1423 time_to_wait = MyTimerFunc(player);
1424 if (time_to_wait < 0)
1425 break;
1426 while (time_to_wait > 0 && player->shouldTerminate == 0) {
1427 /* Check every 100ms whether the player should terminate */
1428 int32_t n = (time_to_wait > kMDPlayerMaximumInterval * 2 ? kMDPlayerMaximumInterval : time_to_wait);
1429 my_usleep(n);
1430 time_to_wait -= n;
1431 }
1432 }
1433 return NULL;
1434 }
1435
1436 #else
1437 static void
1438 MyTimerCallback(TMTaskPtr tmTaskPtr)
1439 {
1440 int32_t time_to_wait;
1441 time_to_wait = MyTimerFunc(((MyTMTask *)tmTaskPtr)->player);
1442 if (time_to_wait > 0)
1443 PrimeTimeTask((QElemPtr)tmTaskPtr, -time_to_wait);
1444 }
1445 #endif
1446
1447 static void
1448 StopSoundInAllTracks(MDPlayer *inPlayer)
1449 {
1450 int n, num;
1451 MDDestinationInfo *info;
1452 MDDeviceIDRecord *rec;
1453 MDAudioIOStreamInfo *ip;
1454 unsigned char buf[6];
1455
1456 if (inPlayer == NULL)
1457 return;
1458
1459 /* Dispose the already scheduled MIDI events */
1460 for (n = inPlayer->destNum - 1; n >= 0; n--) {
1461 if (inPlayer->destInfo[n] != NULL) {
1462 rec = &sDeviceInfo.dest[inPlayer->destInfo[n]->dev];
1463 if (rec->midiRec != NULL) {
1464 MIDIFlushOutput(rec->midiRec->eref);
1465 } else if (rec->streamIndex >= 0) {
1466 ip = MDAudioGetIOStreamInfoAtIndex(rec->streamIndex);
1467 ip->requestFlush = 1;
1468 }
1469 }
1470 }
1471
1472 /* Wait until all requestFlush are processed */
1473 while (1) {
1474 for (n = inPlayer->destNum - 1; n >= 0; n--) {
1475 if (inPlayer->destInfo[n] != NULL) {
1476 rec = &sDeviceInfo.dest[inPlayer->destInfo[n]->dev];
1477 if (rec->midiRec == NULL && rec->streamIndex >= 0) {
1478 ip = MDAudioGetIOStreamInfoAtIndex(rec->streamIndex);
1479 if (ip->requestFlush)
1480 break;
1481 }
1482 }
1483 }
1484 if (n < 0)
1485 break;
1486 my_usleep(10000);
1487 }
1488
1489 /* Dispose the pending note-offs */
1490 for (n = inPlayer->destNum - 1; n >= 0; n--) {
1491 MDTrack *track;
1492 info = inPlayer->destInfo[n];
1493 if (info == NULL)
1494 continue;
1495 if (info->noteOff != NULL) {
1496 MDTrackClear(info->noteOff);
1497 info->noteOffTick = kMDMaxTick;
1498 }
1499
1500 /* Send AllNoteOff (Bn 7B 00), AllSoundOff (Bn 78 00), ResetAllControllers
1501 (Bn 79 00) to all tracks */
1502 for (num = 0; (track = MDTrackMergerGetTrack(info->merger, num)) != NULL; num++) {
1503 int channel = MDTrackGetTrackChannel(track);
1504 buf[0] = 0xB0 + channel;
1505 buf[1] = 0x7B;
1506 buf[2] = 0;
1507 ScheduleMIDIEventToDevice(info->dev, 0, 3, buf);
1508 buf[0] = 0xB0 + channel;
1509 buf[1] = 0x78;
1510 buf[2] = 0;
1511 ScheduleMIDIEventToDevice(info->dev, 0, 3, buf);
1512 buf[0] = 0xB0 + channel;
1513 buf[1] = 0x79;
1514 buf[2] = 0;
1515 ScheduleMIDIEventToDevice(info->dev, 0, 3, buf);
1516 }
1517 }
1518 }
1519
1520 int
1521 MDPlayerSendRawMIDI(MDPlayer *inPlayer, const unsigned char *p, int size, int destDevice, MDTimeType scheduledTime)
1522 {
1523 MDDeviceIDRecord *rp;
1524 UInt64 timeStamp;
1525
1526 if (destDevice < 0 || destDevice >= sDeviceInfo.destNum)
1527 return -1;
1528 rp = &(sDeviceInfo.dest[destDevice]);
1529 if (inPlayer != NULL && scheduledTime + inPlayer->startTime >= 0)
1530 timeStamp = ConvertMDTimeTypeToHostTime(scheduledTime + inPlayer->startTime);
1531 else if (scheduledTime >= 0)
1532 timeStamp = ConvertMDTimeTypeToHostTime(scheduledTime);
1533 else timeStamp = 0;
1534 return ScheduleMIDIEventToDevice(destDevice, timeStamp, size, (unsigned char *)p);
1535 }
1536
1537 void
1538 MDPlayerRingMetronomeClick(MDPlayer *inPlayer, MDTimeType atTime, int isPrincipal)
1539 {
1540 unsigned char buf[4];
1541 buf[0] = 0x90 + (gMetronomeInfo.channel & 15);
1542 buf[1] = (isPrincipal ? gMetronomeInfo.note1 : gMetronomeInfo.note2);
1543 buf[2] = (isPrincipal ? gMetronomeInfo.vel1 : gMetronomeInfo.vel2);
1544 if (atTime == 0) {
1545 atTime = GetHostTimeInMDTimeType();
1546 if (inPlayer != NULL)
1547 atTime -= inPlayer->startTime;
1548 }
1549 MDPlayerSendRawMIDI(inPlayer, buf, 3, gMetronomeInfo.dev, atTime);
1550 buf[2] = 0;
1551 MDPlayerSendRawMIDI(inPlayer, buf, 3, gMetronomeInfo.dev, atTime + gMetronomeInfo.duration);
1552 }
1553
1554 #pragma mark ====== MDPlayer Functions ======
1555
1556 /* --------------------------------------
1557 ��� MDPlayerNew
1558 -------------------------------------- */
1559 MDPlayer *
1560 MDPlayerNew(MDSequence *inSequence)
1561 {
1562 MDPlayer *player = (MDPlayer *)malloc(sizeof(MDPlayer));
1563 if (player != NULL) {
1564 memset(player, 0, sizeof(MDPlayer));
1565 player->refCount = 1;
1566 player->sequence = inSequence;
1567 MDSequenceRetain(inSequence);
1568 player->calib = MDCalibratorNew(inSequence, NULL, kMDEventTempo, -1);
1569 if (player->calib == NULL)
1570 goto error;
1571 MDCalibratorAppend(player->calib, NULL, kMDEventTimeSignature, -1);
1572
1573 player->status = kMDPlayer_idle;
1574 player->time = 0;
1575 player->startTime = 0;
1576 player->recordingStopTick = kMDMaxTick;
1577
1578 player->destInfo = NULL;
1579 player->destNum = 0;
1580 /* player->destIndex = NULL;
1581 player->destChannel = NULL;
1582 player->trackAttr = NULL; */
1583
1584 if (MDPlayerAllocateRecordingBuffer(player) == NULL)
1585 goto error;
1586
1587 player->tempStorage = (unsigned char *)malloc(256);
1588 if (player->tempStorage == NULL)
1589 goto error;
1590 player->tempStorageSize = 256;
1591
1592 }
1593 return player;
1594
1595 error:
1596 MDPlayerReleaseRecordingBuffer(player);
1597 if (player->tempStorage != NULL)
1598 free(player->tempStorage);
1599 if (player->calib != NULL)
1600 MDCalibratorRelease(player->calib);
1601 if (player->sequence != NULL)
1602 MDSequenceRelease(player->sequence);
1603 free(player);
1604 return NULL;
1605 }
1606
1607 /* --------------------------------------
1608 ��� MDPlayerRetain
1609 -------------------------------------- */
1610 void
1611 MDPlayerRetain(MDPlayer *inPlayer)
1612 {
1613 if (inPlayer != NULL)
1614 inPlayer->refCount++;
1615 }
1616
1617 /* --------------------------------------
1618 ��� MDPlayerRelease
1619 -------------------------------------- */
1620 void
1621 MDPlayerRelease(MDPlayer *inPlayer)
1622 {
1623 int32_t num;
1624 if (inPlayer != NULL) {
1625 if (--inPlayer->refCount == 0) {
1626 if (inPlayer->status == kMDPlayer_playing || inPlayer->status == kMDPlayer_exhausted)
1627 MDPlayerStop(inPlayer);
1628 if (inPlayer->destInfo != NULL) {
1629 for (num = 0; num < inPlayer->destNum; num++)
1630 MDPlayerReleaseDestinationInfo(inPlayer->destInfo[num]);
1631 free(inPlayer->destInfo);
1632 }
1633 if (inPlayer->tempStorage != NULL)
1634 free(inPlayer->tempStorage);
1635 /* if (inPlayer->trackAttr != NULL)
1636 free(inPlayer->trackAttr);
1637 if (inPlayer->destChannel != NULL)
1638 free(inPlayer->destChannel);
1639 if (inPlayer->destIndex != NULL)
1640 free(inPlayer->destIndex); */
1641 if (inPlayer->calib != NULL)
1642 MDCalibratorRelease(inPlayer->calib);
1643 if (inPlayer->sequence != NULL)
1644 MDSequenceRelease(inPlayer->sequence);
1645 MDPlayerReleaseRecordingBuffer(inPlayer);
1646 free(inPlayer);
1647 }
1648 }
1649 }
1650
1651 /* --------------------------------------
1652 ��� MDPlayerSetSequence
1653 -------------------------------------- */
1654 MDStatus
1655 MDPlayerSetSequence(MDPlayer *inPlayer, MDSequence *inSequence)
1656 {
1657 if (inPlayer != NULL) {
1658 MDCalibrator *calib;
1659 if (inPlayer->status == kMDPlayer_playing || inPlayer->status == kMDPlayer_exhausted)
1660 MDPlayerStop(inPlayer);
1661 calib = MDCalibratorNew(inSequence, NULL, kMDEventTempo, -1);
1662 if (calib == NULL)
1663 return kMDErrorOutOfMemory;
1664 MDCalibratorRelease(inPlayer->calib);
1665 inPlayer->calib = calib;
1666 MDSequenceRelease(inPlayer->sequence);
1667 inPlayer->sequence = inSequence;
1668 MDSequenceRetain(inSequence);
1669 inPlayer->time = 0;
1670 inPlayer->startTime = 0;
1671 }
1672 return kMDNoError;
1673 }
1674
1675 /* --------------------------------------
1676 ��� MDPlayerGetAudioPlayer
1677 -------------------------------------- */
1678 MDAudio *
1679 MDPlayerGetAudioPlayer(MDPlayer *inPlayer)
1680 {
1681 if (inPlayer == NULL)
1682 return NULL;
1683 else return inPlayer->audio;
1684 }
1685
1686 /* --------------------------------------
1687 ��� MDPlayerRefreshTrackDestinations
1688 -------------------------------------- */
1689 MDStatus
1690 MDPlayerRefreshTrackDestinations(MDPlayer *inPlayer)
1691 {
1692 MDSequence *sequence;
1693 int32_t n, num, i, dev;
1694 int32_t *temp;
1695
1696 /* TODO: we need to rewrite all here! */
1697 if (inPlayer == NULL || (sequence = inPlayer->sequence) == NULL)
1698 return kMDNoError;
1699
1700 num = MDSequenceGetNumberOfTracks(sequence);
1701 // inPlayer->trackNum = num;
1702 // inPlayer->destIndex = (int32_t *)re_malloc(inPlayer->destIndex, num * sizeof(int32_t));
1703 // if (inPlayer->destIndex == NULL)
1704 // return kMDErrorOutOfMemory;
1705 // inPlayer->destChannel = (unsigned char *)re_malloc(inPlayer->destChannel, num * sizeof(unsigned char));
1706 // if (inPlayer->destChannel == NULL)
1707 // return kMDErrorOutOfMemory;
1708 // inPlayer->trackAttr = (MDTrackAttribute *)re_malloc(inPlayer->trackAttr, num * sizeof(MDTrackAttribute));
1709 // if (inPlayer->trackAttr == NULL)
1710 // return kMDErrorOutOfMemory;
1711
1712 temp = (int32_t *)malloc((num + 1) * sizeof(int32_t));
1713 if (temp == NULL)
1714 return kMDErrorOutOfMemory;
1715
1716 // for (i = 0; i < inPlayer->destNum; i++)
1717 // temp[i] = inPlayer->destInfo[i]->dev;
1718 // origDestNum = inPlayer->destNum;
1719
1720 MDSequenceLock(sequence);
1721
1722 /* Dispose previous destInfo[] */
1723 if (inPlayer->destInfo != NULL) {
1724 for (i = 0; i < inPlayer->destNum; i++)
1725 MDPlayerReleaseDestinationInfo(inPlayer->destInfo[i]);
1726 free(inPlayer->destInfo);
1727 }
1728
1729 /* Allocate destInfo */
1730 inPlayer->destInfo = (MDDestinationInfo **)malloc((num + 1) * sizeof(MDDestinationInfo *));
1731 if (inPlayer->destInfo == NULL)
1732 return kMDErrorOutOfMemory;
1733 memset(inPlayer->destInfo, 0, num * sizeof(MDDestinationInfo *));
1734 inPlayer->destNum = 0;
1735
1736 /* Initialize MDDestinationInfo for necessary destinations */
1737 /* (each track and metronome) */
1738 for (n = 0; n <= num; n++) {
1739 MDTrack *track;
1740 MDDestinationInfo *info;
1741 char name1[256];
1742 if (n == num) {
1743 dev = gMetronomeInfo.dev;
1744 } else {
1745 track = MDSequenceGetTrack(sequence, n);
1746 if (track == NULL)
1747 continue;
1748 MDTrackGetDeviceName(track, name1, sizeof name1);
1749 dev = MDPlayerGetDestinationNumberFromName(name1);
1750 }
1751 if (dev >= 0) {
1752 for (i = 0; i < inPlayer->destNum; i++) {
1753 if (inPlayer->destInfo[i]->dev == dev)
1754 break;
1755 }
1756 if (i == inPlayer->destNum) {
1757 /* New device */
1758 inPlayer->destInfo[i] = MDPlayerNewDestinationInfo(dev);
1759 inPlayer->destNum++;
1760 }
1761 /* Add this track to the destination info */
1762 info = inPlayer->destInfo[i];
1763 if (info->merger == NULL) {
1764 info->merger = MDTrackMergerNew();
1765 if (info->merger == NULL)
1766 return kMDErrorOutOfMemory;
1767 }
1768 if (n < num && MDTrackMergerAddTrack(info->merger, track) < 0)
1769 return kMDErrorOutOfMemory;
1770 info->noteOff = MDTrackNew();
1771 info->noteOffPtr = MDPointerNew(info->noteOff);
1772 info->noteOffTick = kMDMaxTick;
1773 }
1774 }
1775 MDPlayerJumpToTick(inPlayer, 0);
1776
1777 MDSequenceUnlock(sequence);
1778
1779 return kMDNoError;
1780
1781 #if 0
1782 /* Update destIndex[] and destChannel[] */
1783 for (n = 0; n < num; n++) {
1784 MDTrack *track;
1785 char name1[256];
1786 track = MDSequenceGetTrack(sequence, n);
1787 i = -1;
1788 if (track != NULL) {
1789 /* Look up the device name */
1790 MDTrackGetDeviceName(track, name1, sizeof name1);
1791 dev = MDPlayerGetDestinationNumberFromName(name1);
1792 /* dev = MDTrackGetDevice(track); */
1793 /* Is it already used? */
1794 if (dev >= 0) {
1795 for (i = 0; i < inPlayer->destNum; i++) {
1796 if (temp[i] == dev)
1797 break;
1798 }
1799 if (i == inPlayer->destNum) {
1800 /* new device */
1801 temp[i] = dev;
1802 inPlayer->destNum++;
1803 }
1804 }
1805 }
1806 inPlayer->destIndex[n] = i;
1807 inPlayer->destChannel[n] = MDTrackGetTrackChannel(track);
1808 inPlayer->trackAttr[n] = MDTrackGetAttribute(track);
1809 dprintf(2, "%s%d%s", (n==0?"trackAttr={":""), inPlayer->trackAttr[n], (n==num-1?"}\n":","));
1810 }
1811 /* Register device for metronome output */
1812 if (gMetronomeInfo.enableWhenPlay || gMetronomeInfo.enableWhenRecord) {
1813 for (i = 0; i < inPlayer->destNum; i++) {
1814 if (temp[i] == gMetronomeInfo.dev)
1815 break;
1816 }
1817 if (i == inPlayer->destNum) {
1818 temp[i] = gMetronomeInfo.dev;
1819 inPlayer->destNum++;
1820 }
1821 }
1822 #endif
1823 }
1824
1825 /* --------------------------------------
1826 ��� MDPlayerJumpToTick
1827 -------------------------------------- */
1828 MDStatus
1829 MDPlayerJumpToTick(MDPlayer *inPlayer, MDTickType inTick)
1830 {
1831 int i;
1832 MDCalibratorJumpToTick(inPlayer->calib, inTick);
1833 for (i = 0; i < inPlayer->destNum; i++) {
1834 MDDestinationInfo *info = inPlayer->destInfo[i];
1835 info->currentEp = MDTrackMergerJumpToTick(info->merger, inTick, &info->currentTrack);
1836 if (info->currentEp != NULL)
1837 info->currentTick = MDGetTick(info->currentEp);
1838 else info->currentTick = kMDMaxTick;
1839 MDTrackClear(info->noteOff);
1840 MDPointerSetPosition(info->noteOffPtr, 0);
1841 info->noteOffTick = kMDMaxTick;
1842 }
1843 inPlayer->lastTick = inTick;
1844 inPlayer->time = MDCalibratorTickToTime(inPlayer->calib, inTick);
1845 inPlayer->status = kMDPlayer_ready;
1846 return kMDNoError;
1847 }
1848
1849 /* --------------------------------------
1850 ��� MDPlayerPreroll
1851 -------------------------------------- */
1852 MDStatus
1853 MDPlayerPreroll(MDPlayer *inPlayer, MDTickType inTick, int backtrack)
1854 {
1855 /* int32_t i, num, dev, *temp; */
1856 /* MDSequence *sequence; */
1857 MDStatus sts;
1858 if (inPlayer != NULL && inPlayer->sequence != NULL) {
1859 sts = MDPlayerRefreshTrackDestinations(inPlayer);
1860 MDPlayerJumpToTick(inPlayer, inTick);
1861 if (sts != kMDNoError)
1862 return sts;
1863 /* Backtrack earlier events */
1864 if (inTick > 0 && backtrack) {
1865 static int32_t sEventType[] = {
1866 kMDEventSysex, kMDEventSysexCont, kMDEventKeyPres,
1867 kMDEventProgram,
1868 ((0 << 16) + kMDEventControl), ((6 << 16) + kMDEventControl),
1869 ((32 << 16) + kMDEventControl), ((100 << 16) + kMDEventControl),
1870 ((101 << 16) + kMDEventControl), ((98 << 16) + kMDEventControl),
1871 ((99 << 16) + kMDEventControl),
1872 -1 };
1873 static int32_t sEventLastOnly[] = {
1874 kMDEventPitchBend, kMDEventChanPres,
1875 ((0xffff << 16) | kMDEventControl),
1876 -1 };
1877 MDPlayerBacktrackEvents(inPlayer, inTick, sEventType, sEventLastOnly);
1878 }
1879
1880 /* Prepare metronome */
1881 PrepareMetronomeForTick(inPlayer, inTick);
1882 inPlayer->status = kMDPlayer_suspended;
1883 }
1884 return kMDNoError;
1885 }
1886
1887
1888 /* --------------------------------------
1889 ��� MDPlayerStart
1890 -------------------------------------- */
1891 MDStatus
1892 MDPlayerStart(MDPlayer *inPlayer)
1893 {
1894 int status;
1895 /* MDSequence *sequence; */
1896
1897 if (inPlayer == NULL || inPlayer->sequence == NULL)
1898 return kMDNoError;
1899 if (inPlayer->status == kMDPlayer_playing)
1900 return kMDNoError;
1901
1902 if (inPlayer->status != kMDPlayer_suspended)
1903 MDPlayerPreroll(inPlayer, MDCalibratorTimeToTick(inPlayer->calib, inPlayer->time), 0);
1904
1905 if (MDSequenceCreateMutex(inPlayer->sequence))
1906 return kMDErrorOnSequenceMutex;
1907
1908 inPlayer->startTime = GetHostTimeInMDTimeType() - inPlayer->time;
1909 inPlayer->countOffEndTime = inPlayer->time;
1910 if (inPlayer->isRecording && inPlayer->countOffDuration > 0) {
1911 inPlayer->countOffFirstRing = inPlayer->time - inPlayer->countOffDuration;
1912 inPlayer->countOffNextRing = inPlayer->countOffFirstRing;
1913 inPlayer->startTime += inPlayer->countOffDuration;
1914 }
1915 inPlayer->status = kMDPlayer_playing;
1916 inPlayer->shouldTerminate = 0;
1917
1918 #if !USE_TIME_MANAGER
1919 status = pthread_create(&inPlayer->playThread, NULL, MyThreadFunc, inPlayer);
1920 if (status != 0)
1921 return kMDErrorCannotStartPlaying;
1922 #else
1923 {
1924 OSStatus err;
1925 inPlayer->myTMTask.tmTask.tmAddr = NewTimerUPP(MyTimerCallback);
1926 inPlayer->myTMTask.tmTask.tmCount = 0;
1927 inPlayer->myTMTask.tmTask.tmWakeUp = 0;
1928 inPlayer->myTMTask.tmTask.tmReserved = 0;
1929 inPlayer->myTMTask.player = inPlayer;
1930
1931 err = InstallXTimeTask((QElemPtr)&(inPlayer->myTMTask));
1932 err = PrimeTimeTask((QElemPtr)&(inPlayer->myTMTask), -100);
1933 }
1934 #endif
1935
1936 return kMDNoError;
1937 }
1938
1939 /* --------------------------------------
1940 ��� MDPlayerStop
1941 -------------------------------------- */
1942 MDStatus
1943 MDPlayerStop(MDPlayer *inPlayer)
1944 {
1945 if (inPlayer == NULL || inPlayer->sequence == NULL)
1946 return kMDNoError;
1947
1948 if (inPlayer->status == kMDPlayer_suspended) {
1949 inPlayer->recordingStopTick = kMDMaxTick;
1950 inPlayer->status = kMDPlayer_ready;
1951 return kMDNoError;
1952 }
1953 if (inPlayer->status != kMDPlayer_playing && inPlayer->status != kMDPlayer_exhausted)
1954 return kMDNoError;
1955
1956 /* Stop MIDI recording */
1957 MDPlayerStopRecording(inPlayer);
1958
1959 /* Stop Audio Processing */
1960 /* MDAudioStop(inPlayer->audio); */
1961
1962 /* for (i = MIDIGetNumberOfSources() - 1; i >= 0; i--) {
1963 MIDIPortDisconnectSource(sMIDIInputPortRef, MIDIGetSource(i));
1964 } */
1965
1966 #if !USE_TIME_MANAGER
1967 inPlayer->shouldTerminate = 1;
1968 pthread_join(inPlayer->playThread, NULL); /* Wait for the playing thread to terminate */
1969 #else
1970 {
1971 OSStatus err = RemoveTimeTask((QElemPtr)&(inPlayer->myTMTask));
1972 DisposeTimerUPP(inPlayer->myTMTask.tmTask.tmAddr);
1973 inPlayer->myTMTask.player = NULL;
1974 }
1975 #endif
1976
1977 MDSequenceDisposeMutex(inPlayer->sequence);
1978
1979 /* Send AllNoteOff (Bn 7B 00) and AllSoundOff (Bn 78 00) */
1980 /* {
1981 static unsigned char sAllNoteAndSoundOff[] = {0xB0, 0x7B, 0x00, 0xB0, 0x78, 0x00};
1982 MDTimeType lastTime = MDCalibratorTickToTime(inPlayer->calib, inPlayer->lastTick);
1983 SendMIDIEventsToAllTracks(inPlayer, lastTime, 6, sAllNoteAndSoundOff);
1984 } */
1985 StopSoundInAllTracks(inPlayer);
1986
1987 inPlayer->status = kMDPlayer_ready;
1988
1989 inPlayer->recordingStopTick = kMDMaxTick;
1990
1991 return kMDNoError;
1992 }
1993
1994 /* --------------------------------------
1995 ��� MDPlayerStartRecording
1996 -------------------------------------- */
1997 MDStatus
1998 MDPlayerStartRecording(MDPlayer *inPlayer)
1999 {
2000 MDStatus sts = kMDNoError;
2001 if (inPlayer != NULL) {
2002 /* Start recording */
2003 if (sRecordingPlayer != NULL)
2004 return kMDErrorAlreadyRecording;
2005 MDPlayerReleaseRecordingBuffer(inPlayer);
2006 if (MDPlayerAllocateRecordingBuffer(inPlayer) == NULL)
2007 return kMDErrorOutOfMemory;
2008 sRecordingPlayer = inPlayer;
2009 inPlayer->isRecording = 1;
2010 sts = MDPlayerStart(inPlayer);
2011 if (inPlayer->status != kMDPlayer_playing && inPlayer->status != kMDPlayer_exhausted) {
2012 sRecordingPlayer = NULL;
2013 inPlayer->isRecording = 0;
2014 }
2015 }
2016
2017 #if DEBUG
2018 {
2019 char buf[1024];
2020 snprintf(buf, sizeof buf, "%s/Alchemusica_MIDIin_dump", getenv("HOME"));
2021 sMIDIInputDump = fopen(buf, "w");
2022 }
2023 #endif
2024
2025 return sts;
2026 }
2027
2028 /* --------------------------------------
2029 ��� MDPlayerStopRecording
2030 -------------------------------------- */
2031 MDStatus
2032 MDPlayerStopRecording(MDPlayer *inPlayer)
2033 {
2034 if (inPlayer != NULL && inPlayer->isRecording) {
2035 if (sRecordingPlayer == inPlayer)
2036 sRecordingPlayer = NULL;
2037 inPlayer->isRecording = 0;
2038 }
2039 #if DEBUG
2040 {
2041 if (sMIDIInputDump != NULL)
2042 fclose(sMIDIInputDump);
2043 sMIDIInputDump = NULL;
2044 }
2045 #endif
2046 return kMDNoError;
2047 }
2048
2049 /* --------------------------------------
2050 ��� MDPlayerSuspend
2051 -------------------------------------- */
2052 MDStatus
2053 MDPlayerSuspend(MDPlayer *inPlayer)
2054 {
2055 MDStatus sts;
2056 if (inPlayer != NULL) {
2057 sts = MDPlayerStop(inPlayer);
2058 inPlayer->status = kMDPlayer_suspended;
2059 return sts;
2060 } else return kMDNoError;
2061 }
2062
2063 /* --------------------------------------
2064 ��� MDPlayerSetRecordingStopTick
2065 -------------------------------------- */
2066 MDStatus
2067 MDPlayerSetRecordingStopTick(MDPlayer *inPlayer, MDTickType inTick)
2068 {
2069 /* Note: recording stop tick will be reset every time MDPlayerStop() is called */
2070 if (inPlayer != NULL)
2071 inPlayer->recordingStopTick = inTick;
2072 return kMDNoError;
2073 }
2074
2075 /* --------------------------------------
2076 ��� MDPlayerGetStatus
2077 -------------------------------------- */
2078 MDPlayerStatus
2079 MDPlayerGetStatus(MDPlayer *inPlayer)
2080 {
2081 if (inPlayer != NULL)
2082 return inPlayer->status;
2083 else return -1;
2084 }
2085
2086 /* --------------------------------------
2087 ��� MDPlayerIsRecording
2088 -------------------------------------- */
2089 int
2090 MDPlayerIsRecording(MDPlayer *inPlayer)
2091 {
2092 return inPlayer->isRecording;
2093 }
2094
2095 /* --------------------------------------
2096 ��� MDPlayerRecordingPlayer
2097 -------------------------------------- */
2098 MDPlayer *
2099 MDPlayerRecordingPlayer(void)
2100 {
2101 return sRecordingPlayer;
2102 }
2103
2104 /* --------------------------------------
2105 ��� MDPlayerGetTime
2106 -------------------------------------- */
2107 MDTimeType
2108 MDPlayerGetTime(MDPlayer *inPlayer)
2109 {
2110 if (inPlayer != NULL) {
2111 if (inPlayer->status == kMDPlayer_playing || inPlayer->status == kMDPlayer_exhausted) {
2112 MDTimeType now_time = GetHostTimeInMDTimeType() - inPlayer->startTime;
2113 if (now_time < inPlayer->countOffEndTime)
2114 return inPlayer->countOffEndTime;
2115 else return now_time;
2116 } else {
2117 return inPlayer->time;
2118 }
2119 }
2120 return 0;
2121 }
2122
2123 /* --------------------------------------
2124 ��� MDPlayerGetTick
2125 -------------------------------------- */
2126 MDTickType
2127 MDPlayerGetTick(MDPlayer *inPlayer)
2128 {
2129 if (inPlayer != NULL) {
2130 if (inPlayer->status == kMDPlayer_playing || inPlayer->isRecording) {
2131 return MDCalibratorTimeToTick(inPlayer->calib, GetHostTimeInMDTimeType() - inPlayer->startTime);
2132 } else {
2133 return MDCalibratorTimeToTick(inPlayer->calib, inPlayer->time);
2134 }
2135 }
2136 return 0;
2137 }
2138
2139 /* --------------------------------------
2140 ��� MDPlayerSetMIDIThruDeviceAndChannel
2141 -------------------------------------- */
2142 void
2143 MDPlayerSetMIDIThruDeviceAndChannel(int32_t dev, int ch)
2144 {
2145 sMIDIThruDevice = dev;
2146 sMIDIThruChannel = ch;
2147 }
2148
2149 /* --------------------------------------
2150 ��� MDPlayerSetMIDIThruTranspose
2151 -------------------------------------- */
2152 void
2153 MDPlayerSetMIDIThruTranspose(int transpose)
2154 {
2155 sMIDIThruTranspose = transpose;
2156 }
2157
2158 /* --------------------------------------
2159 ��� MDPlayerSetCountOffSettings
2160 -------------------------------------- */
2161 void
2162 MDPlayerSetCountOffSettings(MDPlayer *inPlayer, MDTimeType duration, MDTimeType bar, MDTimeType beat)
2163 {
2164 if (inPlayer != NULL) {
2165 inPlayer->countOffDuration = duration;
2166 inPlayer->countOffBar = bar;
2167 inPlayer->countOffBeat = beat;
2168 }
2169 }
2170
2171 /* --------------------------------------
2172 ��� MDPlayerBuildKeyswitchRecord
2173 -------------------------------------- */
2174 static char *
2175 sMDPlayerBuildKeyswitchRecord(MDPlayer *inPlayer)
2176 {
2177 /* Returns an array of chars, whose [t*128+n] element (where t is
2178 a track number and n is a note number) contains '1' when
2179 the note number for the track works as a keyswitch.
2180 The keyswitch info is stored as a Meta text in the form
2181 '%%keyswitch: note1,note2,...' at tick 0. */
2182 MDSequence *seq = inPlayer->sequence;
2183 int32_t num = MDSequenceGetNumberOfTracks(seq);
2184 char *record = (char *)calloc(1, num * 128);
2185 int32_t i;
2186 for (i = 1; i < num; i++) {
2187 MDTrack *track = MDSequenceGetTrack(seq, i);
2188 MDPointer *pt = MDPointerNew(track);
2189 MDEvent *ep;
2190 while ((ep = MDPointerForward(pt)) != NULL) {
2191 if (MDGetTick(ep) > 0)
2192 break;
2193 if (MDGetKind(ep) == kMDEventMetaText && MDGetCode(ep) == kMDMetaText) {
2194 const char *mes = (const char *)MDGetMessageConstPtr(ep, NULL);
2195 if (strncmp(mes, "%%keyswitch:", 12) == 0) {
2196 int note;
2197 mes += 12;
2198 while ((note = MDEventNoteNameToNoteNumber(mes)) >= 0 && note < 128) {
2199 record[i * 128 + note] = 1;
2200 mes = strchr(mes, ',');
2201 if (mes == NULL)
2202 break;
2203 mes++;
2204 }
2205 }
2206 }
2207 }
2208 }
2209 return record;
2210 }
2211
2212 /* --------------------------------------
2213 ��� MDPlayerBacktrackEvents
2214 -------------------------------------- */
2215 MDStatus
2216 MDPlayerBacktrackEvents(MDPlayer *inPlayer, MDTickType inTick, const int32_t *inEventType, const int32_t *inEventTypeLastOnly)
2217 {
2218 /* The int32_t values in inEventType[] and inEventTypeLastOnly[] are in the following format:
2219 lower 16 bits = MDEventKind, upper 16 bits = the 'code' field in MDEvent record.
2220 The value -1 is used for termination. */
2221
2222 MDEvent *ep;
2223 MDEvent **lastOnlyEvents;
2224 MDDestinationInfo *info;
2225 int i, channel, num, lastOnlyCount, processedDest;
2226 static const int32_t sDefaultEventType = { -1 };
2227 char *ks_record;
2228
2229 if (inEventType == NULL)
2230 inEventType = &sDefaultEventType;
2231 if (inEventTypeLastOnly == NULL)
2232 inEventTypeLastOnly = &sDefaultEventType;
2233
2234 /* Count the 'last only' types */
2235 for (i = 0; inEventTypeLastOnly[i] != -1; i++);
2236 lastOnlyCount = i;
2237 if (lastOnlyCount > 0)
2238 lastOnlyEvents = (MDEvent **)calloc(sizeof(MDEvent *), lastOnlyCount * inPlayer->destNum * 16);
2239 else lastOnlyEvents = NULL;
2240
2241 /* Rewind to the top of the sequence */
2242 MDPlayerJumpToTick(inPlayer, 0);
2243
2244 /* Use note-off track for keeping 'last only' events */
2245 for (num = 0; num < inPlayer->destNum; num++) {
2246 info = inPlayer->destInfo[num];
2247 MDPointerSetPosition(info->noteOffPtr, 0);
2248 MDTrackClear(info->noteOff);
2249 }
2250
2251 /* Build keyswitch record */
2252 ks_record = sMDPlayerBuildKeyswitchRecord(inPlayer);
2253
2254 do {
2255 processedDest = 0;
2256 for (num = 0; num < inPlayer->destNum; num++) {
2257 int kind, code;
2258 int32_t n;
2259 info = inPlayer->destInfo[num];
2260 if (info->currentTick < inTick) {
2261 processedDest++;
2262 ep = info->currentEp;
2263 /* Is this event to be sent? */
2264 for (i = 0; (n = inEventType[i]) != -1; i++) {
2265 kind = (n & 0xffff);
2266 code = ((n >> 16) & 0xffff);
2267 if (MDGetKind(ep) == kind && (!MDHasCode(ep) || code == 0xffff || MDGetCode(ep) == code))
2268 break;
2269 }
2270 if (n != -1) {
2271 /* Schedule this event */
2272 channel = (MDTrackGetTrackChannel(info->currentTrack) & 15);
2273 if (ScheduleMDEventToDevice(info->dev, 0, ep, channel) < 0)
2274 continue;
2275 } else {
2276 if (MDGetKind(ep) == kMDEventNote) {
2277 /* Is this a keyswitch? */
2278 n = MDSequenceFindTrack(inPlayer->sequence, info->currentTrack);
2279 if (n >= 1 && ks_record[n * 128 + MDGetCode(ep)] == 1)
2280 i = 0;
2281 else i = lastOnlyCount;
2282 } else {
2283 /* Is this 'last only' event? */
2284 for (i = 0; i < lastOnlyCount; i++) {
2285 n = inEventTypeLastOnly[i];
2286 kind = (n & 0xffff);
2287 code = ((n >> 16) & 0xffff);
2288 if (MDGetKind(ep) == kind && (!MDHasCode(ep) || code == 0xffff || MDGetCode(ep) == code))
2289 break;
2290 }
2291 }
2292 if (i < lastOnlyCount) {
2293 /* Store this event; if the same type of event is already
2294 present, then overwrite it */
2295 MDEvent ev, *ep1;
2296 MDEventClear(&ev);
2297 MDEventCopy(&ev, ep, 1);
2298 channel = (MDTrackGetTrackChannel(info->currentTrack) & 15);
2299 MDSetChannel(&ev, channel);
2300 MDSetTick(&ev, 0);
2301 MDPointerSetPosition(info->noteOffPtr, -1);
2302 kind = MDGetKind(ep);
2303 code = (MDHasCode(ep) ? MDGetCode(ep) : 0);
2304 while ((ep1 = MDPointerForward(info->noteOffPtr)) != NULL) {
2305 if (MDGetChannel(ep1) == channel
2306 && MDGetKind(ep1) == kind
2307 && (kind == kMDEventNote || !MDHasCode(ep1) || MDGetCode(ep1) == code))
2308 break;
2309 }
2310 if (ep1 != NULL) {
2311 /* Replace ep1 with ev */
2312 MDPointerReplaceAnEvent(info->noteOffPtr, &ev, NULL);
2313 } else {
2314 /* Add ev */
2315 MDPointerInsertAnEvent(info->noteOffPtr, &ev);
2316 }
2317 }
2318 }
2319 info->currentEp = MDTrackMergerForward(info->merger, &(info->currentTrack));
2320 info->currentTick = (info->currentEp != NULL ? MDGetTick(info->currentEp) : kMDMaxTick);
2321 }
2322 }
2323 } while (processedDest > 0);
2324 /* Send the 'last only' events */
2325 for (num = 0; num < inPlayer->destNum; num++) {
2326 MDEvent *ep2;
2327 info = inPlayer->destInfo[num];
2328 MDPointerSetPosition(info->noteOffPtr, -1);
2329 while ((ep2 = MDPointerForward(info->noteOffPtr)) != NULL) {
2330 ScheduleMDEventToDevice(info->dev, 0, ep2, 0);
2331 if (MDGetKind(ep2) == kMDEventNote) {
2332 MDSetKind(ep2, kMDEventInternalNoteOff);
2333 ScheduleMDEventToDevice(info->dev, 0, ep2, 0);
2334 MDSetKind(ep2, kMDEventNote);
2335 }
2336 }
2337 MDPointerSetPosition(info->noteOffPtr, 0);
2338 MDTrackClear(info->noteOff);
2339 info->noteOffTick = kMDMaxTick;
2340 }
2341 inPlayer->lastTick = inTick;
2342 inPlayer->time = MDCalibratorTickToTime(inPlayer->calib, inTick);
2343 return 0;
2344 #if 0
2345 /* eventWithDestList[]: record the event to be sent */
2346 maxIndex = 256;
2347 eventWithDestList = (EventWithDest *)malloc(maxIndex * sizeof(EventWithDest));
2348 if (eventWithDestList == NULL) {
2349 MDMergerRelease(merger);
2350 return kMDErrorOutOfMemory;
2351 }
2352 index = 0;
2353
2354 while ((ep = MDMergerBackward(merger)) != NULL) {
2355 unsigned short kind, code;
2356 track = MDMergerGetCurrentTrack(merger);
2357 dest = inPlayer->destIndex[track];
2358 if (dest < 0 || inPlayer->destInfo[dest] == NULL)
2359 continue; /* No output */
2360 for (num = 0; (n = inEventType[num]) != -1; num++) {
2361 kind = (n & 0xffff);
2362 code = ((n >> 16) & 0xffff);
2363 if (MDGetKind(ep) == kind && (!MDHasCode(ep) || code == 0xffff || MDGetCode(ep) == code))
2364 break;
2365 }
2366 if (n == -1) {
2367 for (num = 0; (n = inEventTypeLastOnly[num]) != -1; num++) {
2368 kind = (n & 0xffff);
2369 code = ((n >> 16) & 0xffff);
2370 if (MDGetKind(ep) == kind && (!MDHasCode(ep) || code == 0xffff || MDGetCode(ep) == code)) {
2371 /* Search eventWithDestList[] if this type of event is already registered */
2372 for (n = 0; n < index; n++) {
2373 MDEvent *ep2;
2374 if (eventWithDestList[n].dest != dest)
2375 continue;
2376 ep2 = eventWithDestList[n].ep;
2377 if (MDGetChannel(ep2) != MDGetChannel(ep) || MDGetKind(ep2) != MDGetKind(ep))
2378 continue;
2379 if (MDHasCode(ep) && MDGetCode(ep2) != MDGetCode(ep))
2380 continue;
2381 break; /* Found (which means this event must be skipped) */
2382 }
2383 if (n < index)
2384 ep = NULL;
2385 break;
2386 }
2387 }
2388 if (n == -1)
2389 ep = NULL;
2390 }
2391 /* If ep != NULL, then this event should be sent */
2392 if (ep != NULL) {
2393 if (index >= maxIndex) {
2394 /* eventWithDestList[] should be expanded */
2395 void *p;
2396 maxIndex += 256;
2397 p = realloc(eventWithDestList, maxIndex * sizeof(EventWithDest));
2398 if (p == NULL) {
2399 free(eventWithDestList);
2400 MDMergerRelease(merger);
2401 return kMDErrorOutOfMemory;
2402 }
2403 eventWithDestList = (EventWithDest *)p;
2404 }
2405 eventWithDestList[index].ep = ep;
2406 eventWithDestList[index].dest = dest;
2407 index++;
2408 }
2409 }
2410
2411 /* Send the events */
2412 for (num = index - 1; num >= 0; num--) {
2413 ep = eventWithDestList[num].ep;
2414 dest = eventWithDestList[num].dest;
2415 info = inPlayer->destInfo[dest];
2416 if (MDIsSysexEvent(ep)) {
2417 /* Prepare a MIDISysexSendRequest */
2418 MIDISysexSendRequest *rp = &info->sysexRequest;
2419 rp->destination = info->eref;
2420 rp->data = (Byte *)MDGetMessageConstPtr(ep, &n);
2421 rp->bytesToSend = n;
2422 rp->complete = 0;
2423 rp->completionProc = MySysexCompletionProc;
2424 rp->completionRefCon = info;
2425 MIDISendSysex(&info->sysexRequest);
2426 my_usleep(40000);
2427 while (rp->complete == 0)
2428 my_usleep(1000);
2429 } else {
2430 unsigned char buf[4];
2431 memset(buf, 0, 4);
2432 n = MDEventToMIDIMessage(ep, buf);
2433 buf[0] |= inPlayer->destChannel[track];
2434 info->packetPtr = MIDIPacketListInit(&info->packetList);
2435 info->packetPtr = MIDIPacketListAdd(&info->packetList, sizeof(info->packetList), info->packetPtr,
2436 0, n, buf);
2437 MIDISend(sMIDIOutputPortRef, info->eref, &info->packetList);
2438 my_usleep(n * 400);
2439 }
2440 }
2441 free(eventWithDestList);
2442 MDMergerRelease(merger);
2443 return kMDNoError;
2444 #endif
2445 }
2446
2447 static int
2448 sMDPlayerGetOneByte(void *ptr)
2449 {
2450 MDPlayer *player = (MDPlayer *)ptr;
2451 if (player->tempStorageIndex >= player->tempStorageLength)
2452 return -1;
2453 else return player->tempStorage[player->tempStorageIndex++];
2454 }
2455
2456 /* --------------------------------------
2457 ��� MDPlayerGetRecordedEvents
2458 -------------------------------------- */
2459 /* *outEvent must be either NULL or a memory block allocated by malloc, and *outEventBufSiz
2460 must be the number of MDEvents that (*outEvent)[] can store. Both *outEvent and
2461 *outEventBufSiz can be changed by realloc.
2462 Returns the number of events. */
2463 int
2464 MDPlayerGetRecordedEvents(MDPlayer *inPlayer, MDEvent **outEvent, int *outEventBufSiz)
2465 {
2466 int result;
2467 MDTimeType timeStamp;
2468 MDTickType tick;
2469 int eventCount = 0, n;
2470 while (eventCount == 0) {
2471 result = MDPlayerGetRecordingData(inPlayer, &timeStamp, &(inPlayer->tempStorageLength), &(inPlayer->tempStorage), &(inPlayer->tempStorageSize));
2472 dprintf(2, "get record data result %d, timeStamp %g, length %ld, data %p\n", result, (double)timeStamp, inPlayer->tempStorageLength, inPlayer->tempStorage);
2473 if (result == -1)
2474 return 0;
2475 else if (result < 0)
2476 return result;
2477 if (outEvent == NULL)
2478 break; /* Just skip this block */
2479 inPlayer->tempStorageIndex = 0;
2480 while ((n = sMDPlayerGetOneByte(inPlayer)) >= 0) {
2481 MDEvent tempEvent;
2482 MDEventInit(&tempEvent);
2483 if (n == 0xf0) {
2484 /* System Exclusive */
2485 int32_t len = 1; /* Include the first 0xf0 byte */
2486 while ((n = sMDPlayerGetOneByte(inPlayer)) >= 0 && n != 0xf7)
2487 len++;
2488 if (n == 0xf7)
2489 len++;
2490 else inPlayer->tempStorageIndex--; /* unget the last byte */
2491 MDSetKind(&tempEvent, kMDEventSysex);
2492 if (MDSetMessageLength(&tempEvent, len) < len) {
2493 MDEventInit(&tempEvent);
2494 return kMDErrorOutOfMemory;
2495 }
2496 /* Do we need to add extra 0xf7 if it is absent...? */
2497 MDSetMessage(&tempEvent, inPlayer->tempStorage + inPlayer->tempStorageIndex - len);
2498 } else if (n >= 0 && n < 0xf0) {
2499 /* MIDI Event */
2500 MDStatus sts;
2501 sts = MDEventFromMIDIMessage(&tempEvent, n, inPlayer->runningStatusByte, sMDPlayerGetOneByte, inPlayer, &(inPlayer->runningStatusByte));
2502 if (sts != kMDNoError) {
2503 MDEventInit(&tempEvent);
2504 return sts;
2505 }
2506 } else {
2507 /* realtime events: skipped */
2508 continue;
2509 /* MDEventInit(outEvent);
2510 return kMDErrorNoEvents; */
2511 }
2512 tick = MDCalibratorTimeToTick(inPlayer->calib, timeStamp);
2513 if (tick < inPlayer->recordingStopTick) {
2514 MDSetTick(&tempEvent, tick);
2515 if (*outEvent == NULL || eventCount >= *outEventBufSiz) {
2516 /* (Re)allocate the event buffer */
2517 int allocSize = *outEventBufSiz + 8;
2518 MDEvent *ep = (MDEvent *)calloc(sizeof(MDEvent), allocSize);
2519 if (*outEvent != NULL && *outEventBufSiz > 0)
2520 MDEventMove(ep, *outEvent, *outEventBufSiz);
2521 *outEventBufSiz = allocSize;
2522 if (*outEvent != NULL)
2523 free(*outEvent);
2524 *outEvent = ep;
2525 }
2526 MDEventMove(*outEvent + eventCount, &tempEvent, 1);
2527 eventCount++;
2528 } else {
2529 /* If the tick exceeds recordingStopTick, then do not collect it */
2530 /* This does not happen so often, because recording should be stopped
2531 by PlayingViewController after a while */
2532 MDEventClear(&tempEvent);
2533 }
2534 }
2535 }
2536 return eventCount;
2537 }
2538
2539 /* --------------------------------------
2540 ��� MDPlayerClearRecordedEvents
2541 -------------------------------------- */
2542 void
2543 MDPlayerClearRecordedEvents(MDPlayer *inPlayer)
2544 {
2545 MDPlayerReleaseRecordingBuffer(inPlayer);
2546 MDPlayerAllocateRecordingBuffer(inPlayer);
2547 }
2548

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26