Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/MD_package/MDTrack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 188 - (show annotations) (download) (as text)
Thu Mar 12 15:23:39 2020 UTC (4 years ago) by toshinagata1964
File MIME type: text/x-csrc
File size: 87341 byte(s)
Copy & paste had serious problems. Hopefully fixed.
1 /*
2 * MDTrack.c
3 *
4 * Created by Toshi Nagata on Sun Jun 17 2001.
5
6 Copyright (c) 2000-2017 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
20 #include <stdio.h> /* for sprintf() and standard I/O in MDTrackDump() */
21 #include <stdlib.h> /* for malloc(), realloc(), and free() */
22 #include <string.h> /* for memset() and strdup() */
23 #include <limits.h> /* for LONG_MAX */
24 #include <ctype.h> /* for isalpha() etc. */
25
26 #ifdef __MWERKS__
27 #pragma mark ====== Private definitions ======
28 #endif
29
30 #define kMDBlockSize 64 /* This number of MDEvent's are allocated per MDBlock */
31
32 typedef struct MDBlock MDBlock;
33 static MDBlock *sFreeBlocks = NULL; /* The pool of free MDBlock's */
34
35 struct MDBlock {
36 MDBlock * next; /* the next MDBlock in the linked list */
37 MDBlock * last; /* the last MDBlock in the linked list */
38 int32_t size; /* the number of allocated MDEvent's */
39 int32_t num; /* the number of actually containing MDEvent's */
40 MDEvent * events; /* the array of MDEvent's */
41 MDTickType largestTick; /* the max value of (MDGetTick(&events[i]) + MDHasDuration(&events[i]) ? MDGetDuration(&event[i]) : 0); may be kMDNegativeTick after modification, in which case it should be recached */
42 };
43
44 struct MDTrack {
45 int32_t refCount; /* the reference count */
46 int32_t num; /* the number of events */
47 int32_t numBlocks; /* the number of blocks */
48 char * name; /* the track name */
49 char * devname; /* the device name */
50 char ** extraInfo; /* Extra info: {key1, value1, ..., NULL} */
51 /* malloc'ed as multiples of 16*sizeof(char *) */
52 MDTrackAttribute attribute; /* the track attribute (Rec/Solo/Mute) */
53 MDBlock * first; /* the first MDBlock */
54 MDBlock * last; /* the last MDBlock */
55 MDTickType duration; /* the track duration in ticks */
56 int32_t nch[18]; /* the number of channel events (16: sysex, 17: non-MIDI) */
57 int32_t dev; /* the device number */
58 short channel; /* the MIDI channel for this track */
59 /* (meaningful only if the parent MDSequence is single-channel mode) */
60 MDPointer * pointer; /* the first MDPointer related to this track
61 (MDPointer's are combined as a linked list) */
62 /* This is a 'mutable' member, i.e. it may be modified internally
63 even when a 'const MDTrack *' is passed. This behavior is
64 acceptable, because this member is strictly internal. */
65 };
66
67 struct MDPointer {
68 int32_t refCount; /* the reference count */
69 MDTrack * parent; /* The parent sequence. */
70 MDBlock * block; /* The current block. */
71 int32_t position; /* The current position. Can be -1, which means
72 "before the beginning". */
73 int32_t index; /* The current index in the current block. */
74 MDPointer * next;
75 char removed; /* True if the 'current' event has been removed. */
76 char allocated; /* True if allocated by malloc() */
77 char autoAdjust; /* True if autoadjust is done after insert/delete (default is false) */
78 };
79
80 struct MDTrackMerger {
81 int32_t refCount; /* the reference count */
82 MDPointer ** pointers; /* array of MDPointers */
83 int npointers; /* number of MDPointers in pointers[] */
84 int idx; /* the index of the 'current' track */
85 };
86
87 #ifdef __MWERKS__
88 #pragma mark -
89 #pragma mark ====== MDTrack functions ======
90 #endif
91
92 #ifdef __MWERKS__
93 #pragma mark ====== Block manipulation (private functions) ======
94 #endif
95
96 /* --------------------------------------
97 ��� MDTrackAllocateBlock
98 -------------------------------------- */
99 static MDBlock *
100 MDTrackAllocateBlock(MDTrack *inTrack, MDBlock *inBlock, int32_t inSize)
101 {
102 MDBlock *aBlock;
103
104 if (sFreeBlocks != NULL) {
105 /* MDBlock pool ������������������������size ��� events ��������������� */
106 aBlock = sFreeBlocks;
107 sFreeBlocks = sFreeBlocks->next;
108 } else {
109 /* ������������������������������������������������ MDBlockRecord ��� buffer ������������������������������ */
110 aBlock = (MDBlock *)malloc(sizeof(*aBlock) + inSize * sizeof(aBlock->events[0]));
111 if (aBlock == NULL)
112 /* out of memory */
113 return NULL;
114 aBlock->size = inSize;
115 aBlock->events = (MDEvent *)(aBlock + 1);
116 }
117
118 aBlock->last = inBlock;
119 if (inBlock == NULL) {
120 /* top of list */
121 aBlock->next = inTrack->first;
122 inTrack->first = aBlock;
123 } else {
124 aBlock->next = inBlock->next;
125 inBlock->next = aBlock;
126 }
127 if (aBlock->next == NULL) {
128 /* bottom of list */
129 inTrack->last = aBlock;
130 } else {
131 aBlock->next->last = aBlock;
132 }
133
134 aBlock->num = 0;
135 aBlock->largestTick = kMDNegativeTick;
136
137 memset(aBlock->events, 0, aBlock->size * sizeof(aBlock->events[0]));
138
139 inTrack->numBlocks++;
140
141 return aBlock;
142 }
143
144 /* --------------------------------------
145 ��� MDTrackDeallocateBlock
146 -------------------------------------- */
147 static void
148 MDTrackDeallocateBlock(MDTrack *inTrack, MDBlock *inBlock)
149 {
150 if (inBlock->last == NULL) {
151 inTrack->first = inBlock->next;
152 } else {
153 inBlock->last->next = inBlock->next;
154 }
155 if (inBlock->next == NULL) {
156 inTrack->last = inBlock->last;
157 } else {
158 inBlock->next->last = inBlock->last;
159 }
160
161 /* MDBlock pool ��������� */
162 inBlock->next = sFreeBlocks;
163 sFreeBlocks = inBlock;
164
165 inTrack->numBlocks--;
166 }
167
168 /* --------------------------------------
169 ��� MDTrackClearBlock
170 -------------------------------------- */
171 static void
172 MDTrackClearBlock(MDTrack *inTrack, MDBlock *inBlock)
173 {
174 int32_t i;
175
176 for (i = 0; i < inBlock->num; i++) {
177 /* ���������������������������������������������������������������������������������������������
178 ��������������������������������������������������������� */
179 MDEventClear(&(inBlock->events[i]));
180 }
181 inBlock->num = 0;
182 MDTrackDeallocateBlock(inTrack, inBlock);
183 }
184
185 /* --------------------------------------
186 ��� MDTrackUpdateLargestTickForBlock
187 -------------------------------------- */
188 static void
189 MDTrackUpdateLargestTickForBlock(MDTrack *inTrack, MDBlock *inBlock)
190 {
191 MDTickType tick, largestTick;
192 int i;
193 MDEvent *ep;
194 if (inBlock->largestTick < 0) {
195 /* Recalc the largest tick and cache it */
196 largestTick = kMDNegativeTick;
197 for (i = 0; i < inBlock->num; i++) {
198 ep = &inBlock->events[i];
199 tick = MDGetTick(ep);
200 if (MDHasDuration(ep))
201 tick += MDGetDuration(ep);
202 if (tick > largestTick)
203 largestTick = tick;
204 }
205 inBlock->largestTick = largestTick;
206 }
207 }
208
209 #if 0
210 #pragma mark ====== Manipulation of extraInfo ======
211 #endif
212
213 /* --------------------------------------
214 ��� MDTrackCountExtraInfo
215 -------------------------------------- */
216 int32_t
217 MDTrackCountExtraInfo(const MDTrack *inTrack)
218 {
219 int i;
220 if (inTrack == NULL || inTrack->extraInfo == NULL)
221 return 0;
222 i = 0;
223 while (inTrack->extraInfo[i] != NULL)
224 i += 2;
225 return i / 2;
226 }
227
228 int32_t
229 MDTrackGetExtraInfo(const MDTrack *inTrack, const char *key, const char **outValue)
230 {
231 int i, n;
232 if (inTrack == NULL)
233 return -1;
234 n = MDTrackCountExtraInfo(inTrack);
235 for (i = 0; i < n; i++) {
236 if (strcmp(inTrack->extraInfo[i * 2], key) == 0) {
237 if (outValue != NULL)
238 *outValue = inTrack->extraInfo[i * 2 + 1];
239 return i;
240 }
241 }
242 return -1;
243 }
244
245 int32_t
246 MDTrackSetExtraInfo(MDTrack *inTrack, const char *key, const char *value)
247 {
248 int n;
249 if (inTrack == NULL)
250 return -1;
251 n = MDTrackGetExtraInfo(inTrack, key, NULL);
252 if (n >= 0) {
253 /* Found */
254 free(inTrack->extraInfo[n * 2 + 1]);
255 if (value != NULL) {
256 /* Replace the value */
257 inTrack->extraInfo[n * 2 + 1] = strdup(value);
258 } else {
259 /* Remove the key and value */
260 int m = MDTrackCountExtraInfo(inTrack);
261 memmove(inTrack->extraInfo + (n * 2), inTrack->extraInfo + (n * 2 + 2), sizeof(char *) * (2 * (m - n) + 1));
262 }
263 return n;
264 } else {
265 /* Create a new entry */
266 int m = MDTrackCountExtraInfo(inTrack);
267 if (value == NULL)
268 return -1; /* Do nothing */
269 if (m == 0 || m % 8 == 7) {
270 char **p = (char **)realloc(inTrack->extraInfo, ((m + 9) / 8) * sizeof(char *) * 16);
271 if (p == NULL)
272 return -1; /* Cannot allocate */
273 inTrack->extraInfo = p;
274 p[m * 2] = strdup(key);
275 p[m * 2 + 1] = strdup(value);
276 p[m * 2 + 2] = NULL;
277 }
278 return m;
279 }
280 }
281
282 const char *MDTrackGetExtraInfoAtIndex(const MDTrack *inTrack, int32_t index, const char **outKey)
283 {
284 int n = MDTrackCountExtraInfo(inTrack);
285 if (index < 0 || index >= n)
286 return NULL;
287 if (outKey != NULL)
288 *outKey = inTrack->extraInfo[index * 2];
289 return inTrack->extraInfo[index * 2 + 1];
290 }
291
292 #ifdef __MWERKS__
293 #pragma mark ====== Basic Insert/Delete (private functions) ======
294 #endif
295
296 /* --------------------------------------
297 ��� MDTrackInsertBlanks
298 -------------------------------------- */
299 static int32_t
300 MDTrackInsertBlanks(MDTrack *inTrack, MDPointer *inPointer, int32_t count)
301 {
302 MDBlock *block1, *block2;
303 int32_t index, room, num2, tail;
304 MDPointer *ptr;
305
306 if (count <= 0)
307 return count;
308
309 block1 = inPointer->block;
310 index = inPointer->index;
311
312 if (inTrack->num == 0 || block1 == NULL) {
313 room = tail = 0;
314 } else {
315 /* room: the number of available space */
316 room = block1->size - block1->num;
317 /* tail: the number of events that needs to be moved (i.e. after index in block1) */
318 tail = block1->num - index;
319 }
320 if (room >= count) {
321 /* The current block have enough room for the required blanks */
322 MDEventMove(block1->events + index + count, block1->events + index, tail);
323 block1->num += count;
324 block1->largestTick = kMDNegativeTick;
325 } else {
326 /* Allocate new blocks until there are enough room */
327 block2 = block1;
328 while (room < count) {
329 block2 = MDTrackAllocateBlock(inTrack, block2, kMDBlockSize);
330 if (block2 == NULL) {
331 /* Out of memory: clean up the allocated blocks */
332 if (block1 != NULL) {
333 while (block1->next != NULL && block1->next->num == 0)
334 MDTrackDeallocateBlock(inTrack, block1->next);
335 }
336 return 0;
337 }
338 room += block2->size;
339 }
340 /* block2: the last allocated block */
341 /* num2: the number of events (possibly including blanks) in block2 */
342 num2 = block2->size - (room - count);
343 /* Move the events after index in block1 if necessary */
344 if (tail > 0) {
345 if (tail <= num2) {
346 MDEventMove(block2->events + num2 - tail, block1->events + index, tail);
347 } else {
348 /* block1->events[index..num-num2-1] ====> block2->last->events[size-(tail-num2)..size-1]
349 block1->events[num-num2..num-1] ====> block2->events[0..num2-1] */
350 MDEventMove(block2->events, block1->events + (block1->num - num2), num2);
351 MDEventMove(block2->last->events + block2->last->size - (tail - num2), block1->events + index, tail - num2);
352 }
353 }
354 /* Invalidate the largestTick field */
355 if (block1 != NULL)
356 block1->largestTick = kMDNegativeTick;
357 /* update the num fields of modified blocks */
358 block2->num = num2; /* the last allocated block */
359 /* other blocks */
360 if (block1 == NULL)
361 block1 = inTrack->first;
362 while (block1 != block2) {
363 block1->num = block1->size;
364 block1 = block1->next;
365 }
366 }
367 inTrack->num += count;
368
369 if (inPointer->block == NULL) {
370 inPointer->block = inTrack->first;
371 inPointer->position = inPointer->index = 0;
372 } else if (inPointer->index == inPointer->block->size) {
373 /* The pointer was at the end of track, and the last block in the track
374 had maximum number of events. In this case, a new block must have been
375 allocated, so we move on to the next block and point to the first
376 event in that block. */
377 inPointer->block = inPointer->block->next;
378 inPointer->index = 0;
379 }
380
381 /* Update pointers */
382 /* (1) 0..inPointer->position-1 : no change
383 (2) inPointer->position : position not changed, block/index updated as in inPointer
384 (3) inPointer->position+1..inPointer->position+tail : position += count, block/index updated
385 (4) inPointer->position+tail+1.. : position += count, block/index not changed */
386 num2 = inPointer->position;
387 for (ptr = inTrack->pointer; ptr != NULL; ptr = ptr->next) {
388 if (ptr == inPointer || !ptr->autoAdjust)
389 continue;
390 index = ptr->position;
391 if (index > num2 + tail)
392 ptr->position += count; /* case 4 */
393 else if (index > num2) {
394 /* case 3 */
395 ptr->position = inPointer->position;
396 ptr->block = inPointer->block;
397 ptr->index = inPointer->index;
398 MDPointerSetRelativePosition(ptr, index - num2 + count);
399 } else if (index == num2) {
400 /* case 2 */
401 ptr->position = inPointer->position;
402 ptr->block = inPointer->block;
403 ptr->index = inPointer->index;
404 }
405 }
406
407 /* For debug */
408 for (ptr = inTrack->pointer; ptr != NULL; ptr = ptr->next) {
409 if (ptr == inPointer || ptr->autoAdjust)
410 MDPointerCheck(inPointer);
411 }
412 /* --------- */
413
414 return count;
415 }
416
417 /* --------------------------------------
418 ��� MDTrackDeleteEvents
419 -------------------------------------- */
420 static int32_t
421 MDTrackDeleteEvents(MDTrack *inTrack, MDPointer *inPointer, int32_t count)
422 {
423 MDBlock *block, *block2;
424 int32_t index, remain, i, n, tail;
425 MDPointer *ptr;
426
427 if (inTrack == NULL || inPointer == NULL || inPointer->parent != inTrack)
428 return 0;
429 if (count <= 0)
430 return count;
431
432 block = inPointer->block;
433 index = inPointer->index;
434 remain = count;
435 tail = 0;
436 while (remain > 0 && block != NULL) {
437 block->largestTick = kMDNegativeTick;
438 if (index + remain > block->num)
439 n = block->num - index;
440 else
441 n = remain;
442 for (i = 0; i < n; i++)
443 MDEventClear(block->events + index + i);
444 if (index + n < block->num) {
445 /* tail: the number of surviving events in the last modified block
446 (used later to modify pointers) */
447 tail = block->num - (index + n);
448 MDEventMove(block->events + index, block->events + index + n, tail);
449 }
450 block->num -= n;
451 remain -= n;
452 index = 0;
453 block = block->next;
454 }
455
456 /* Purge the empty blocks */
457 if (block == NULL)
458 block = inTrack->last;
459 while (block != NULL) {
460 int endFlag = 0;
461 if (block->num != 0) {
462 if (block == inPointer->block)
463 break;
464 block = block->last;
465 continue;
466 }
467 if (block == inPointer->block) {
468 /* inPointer is updated to point the next surviving event */
469 if (block->next != NULL) {
470 inPointer->block = block->next;
471 inPointer->index = 0;
472 } else {
473 inPointer->block = block->last;
474 if (block->last == NULL)
475 inPointer->index = 0;
476 else inPointer->index = block->last->num;
477 }
478 endFlag = 1;
479 }
480 block2 = block->last;
481 MDTrackDeallocateBlock(inTrack, block);
482 block = block2;
483 if (endFlag)
484 break;
485 }
486
487 inPointer->removed = 1;
488 inTrack->num -= count;
489
490 /* An ad-hoc sanity check */
491 if (inPointer->block != NULL && inPointer->block->num == inPointer->index && inPointer->block->next != NULL) {
492 inPointer->block = inPointer->block->next;
493 inPointer->index = 0;
494 }
495
496 /* Update pointers */
497 /* (1) 0..inPointer->position-1 : no change
498 (2) inPointer->position : position not changed, block/index updated as in inPointer
499 (3) inPointer->position+1..inPointer->position+count : position/block/index are made same as in inPointer
500 (4) inPointer->position+count+1..inPointer->position+count+tail : position -= count, block/index updated
501 (5) inPointer->position+count+tail+1 : position -= count, block/index not changed */
502 n = inPointer->position;
503 for (ptr = inTrack->pointer; ptr != NULL; ptr = ptr->next) {
504 if (inPointer == ptr || !ptr->autoAdjust)
505 continue;
506 index = ptr->position;
507 if (index > n + count + tail) /* case 5 */
508 ptr->position -= count;
509 else if (index >= n) {
510 ptr->position = inPointer->position;
511 ptr->block = inPointer->block;
512 ptr->index = inPointer->index;
513 if (index > n + count) {
514 /* case 4 */
515 MDPointerSetRelativePosition(ptr, index - (n + count));
516 } else ptr->removed = 1; /* case 3 and 2 */
517 } else { /* case 1 */ }
518 }
519
520 /* Another sanity check */
521 if (inPointer->parent->num == 0 && inPointer->position >= 0) {
522 inPointer->position = -1;
523 inPointer->index = -1;
524 inPointer->block = NULL;
525 }
526
527 /* For debug */
528 for (ptr = inTrack->pointer; ptr != NULL; ptr = ptr->next) {
529 if (ptr == inPointer || ptr->autoAdjust)
530 MDPointerCheck(inPointer);
531 }
532 /* --------- */
533
534 return count;
535 }
536
537 #ifdef __MWERKS__
538 #pragma mark ====== New/Retain/Release ======
539 #endif
540
541 /* --------------------------------------
542 ��� MDTrackNew
543 -------------------------------------- */
544 MDTrack *
545 MDTrackNew(void)
546 {
547 MDTrack *newTrack = (MDTrack *)malloc(sizeof(*newTrack));
548 if (newTrack == NULL)
549 return NULL; /* out of memory */
550 memset(newTrack, 0, sizeof(*newTrack));
551 newTrack->refCount = 1;
552 newTrack->dev = -1;
553 return newTrack;
554 }
555
556 /* --------------------------------------
557 ��� MDTrackRetain
558 -------------------------------------- */
559 void
560 MDTrackRetain(MDTrack *inTrack)
561 {
562 inTrack->refCount++;
563 }
564
565 /* --------------------------------------
566 ��� MDTrackRelease
567 -------------------------------------- */
568 void
569 MDTrackRelease(MDTrack *inTrack)
570 {
571 if (--inTrack->refCount == 0) {
572 if (inTrack->num != 0)
573 MDTrackClear(inTrack);
574
575 /* Remove the MDPointer's from the linked list */
576 while (inTrack->pointer != NULL)
577 MDPointerSetTrack(inTrack->pointer, NULL);
578
579 /* Release random fields */
580 if (inTrack->name != NULL)
581 free(inTrack->name);
582 if (inTrack->devname != NULL)
583 free(inTrack->devname);
584 if (inTrack->extraInfo != NULL) {
585 int i;
586 for (i = 0; inTrack->extraInfo[i] != NULL; i++)
587 free(inTrack->extraInfo[i]);
588 free(inTrack->extraInfo);
589 }
590 free(inTrack);
591 }
592 }
593
594 /* --------------------------------------
595 ��� MDTrackClear
596 -------------------------------------- */
597 void
598 MDTrackClear(MDTrack *inTrack)
599 {
600 MDPointer *pointer;
601
602 while (inTrack->first != NULL) {
603 MDTrackClearBlock(inTrack, inTrack->first);
604 }
605 inTrack->num = 0;
606
607 /* Reset the MDPointers */
608 for (pointer = inTrack->pointer; pointer != NULL; pointer = pointer->next) {
609 MDPointerSetPosition(pointer, -1);
610 }
611 }
612
613 /* --------------------------------------
614 ��� MDTrackNewFromTrack
615 -------------------------------------- */
616 MDTrack *
617 MDTrackNewFromTrack(const MDTrack *inTrack)
618 {
619 MDPointer *src, *dest;
620 MDEvent *eventSrc, *eventDest;
621 int32_t count, noteCount;
622 MDTrack *newTrack;
623 const char *key, *value;
624 int i;
625
626 /* Allocate a new track */
627 newTrack = MDTrackNew();
628 if (newTrack == NULL)
629 return NULL;
630
631 /* Set up pointers */
632 dest = MDPointerNew(newTrack);
633 src = MDPointerNew((MDTrack *)inTrack);
634 if (src == NULL || dest == NULL)
635 return NULL;
636 MDPointerSetPosition(dest, 0);
637
638 /* Prepare the blank space */
639 count = MDTrackGetNumberOfEvents(inTrack);
640 if (MDTrackInsertBlanks(newTrack, dest, count) < count) {
641 MDTrackRelease(newTrack);
642 return NULL;
643 }
644
645 /* Copy the events */
646 noteCount = 0;
647 while ((eventDest = MDPointerForward(dest)) != NULL && (eventSrc = MDPointerForward(src)) != NULL) {
648 MDEventCopy(eventDest, eventSrc, 1);
649 }
650 MDPointerRelease(dest);
651 MDPointerRelease(src);
652
653 /* Copy random fields */
654 for (i = 0; i < 18; i++)
655 newTrack->nch[i] = inTrack->nch[i];
656 newTrack->dev = inTrack->dev;
657 newTrack->channel = inTrack->channel;
658 newTrack->duration = inTrack->duration;
659 if (inTrack->name != NULL)
660 newTrack->name = strdup(inTrack->name);
661 if (inTrack->devname != NULL)
662 newTrack->devname = strdup(inTrack->devname);
663 for (i = 0; (value = MDTrackGetExtraInfoAtIndex(inTrack, i, &key)) != NULL; i++) {
664 MDTrackSetExtraInfo(newTrack, key, value);
665 }
666
667 return newTrack;
668 }
669
670 /* Exchange the contents of two MDTracks. The tracks should not have any
671 "parents" such as MDSequence. Otherwise, the results are undefined. */
672 void
673 MDTrackExchange(MDTrack *inTrack1, MDTrack *inTrack2)
674 {
675 MDTrack tempTrack;
676 MDPointer *pointer;
677
678 /* Exchange the contents of the MDTrack struct */
679 tempTrack = *inTrack1;
680 *inTrack1 = *inTrack2;
681 *inTrack2 = tempTrack;
682
683 /* Update the MDPointers */
684 for (pointer = inTrack1->pointer; pointer != NULL; pointer = pointer->next)
685 pointer->parent = inTrack2;
686 for (pointer = inTrack2->pointer; pointer != NULL; pointer = pointer->next)
687 pointer->parent = inTrack1;
688 }
689
690 #ifdef __MWERKS__
691 #pragma mark ====== Accessor functions ======
692 #endif
693
694 /* --------------------------------------
695 ��� MDTrackGetNumberOfEvents
696 -------------------------------------- */
697 int32_t
698 MDTrackGetNumberOfEvents(const MDTrack *inTrack)
699 {
700 return inTrack->num;
701 }
702
703 /* --------------------------------------
704 ��� MDTrackGetNumberOfChannelEvents
705 -------------------------------------- */
706 int32_t
707 MDTrackGetNumberOfChannelEvents(const MDTrack *inTrack, short channel)
708 {
709 int32_t n;
710 if (channel >= 0 && channel < 16)
711 return inTrack->nch[channel];
712 else {
713 n = 0;
714 for (channel = 0; channel < 16; channel++)
715 n += inTrack->nch[channel];
716 return n;
717 }
718 }
719
720 /* --------------------------------------
721 ��� MDTrackGetNumberOfSysexEvents
722 -------------------------------------- */
723 int32_t
724 MDTrackGetNumberOfSysexEvents(const MDTrack *inTrack)
725 {
726 return inTrack->nch[16];
727 }
728
729 /* --------------------------------------
730 ��� MDTrackGetNumberOfNonMIDIEvents
731 -------------------------------------- */
732 int32_t
733 MDTrackGetNumberOfNonMIDIEvents(const MDTrack *inTrack)
734 {
735 return inTrack->nch[17];
736 }
737
738 /* --------------------------------------
739 ��� MDTrackGetDuration
740 -------------------------------------- */
741 MDTickType
742 MDTrackGetDuration(const MDTrack *inTrack)
743 {
744 return inTrack->duration;
745 }
746
747 /* --------------------------------------
748 ��� MDTrackSetDuration
749 -------------------------------------- */
750 void
751 MDTrackSetDuration(MDTrack *inTrack, MDTickType inDuration)
752 {
753 inTrack->duration = inDuration;
754 }
755
756 #ifdef __MWERKS__
757 #pragma mark ====== Insert/Delete ======
758 #endif
759
760 /* --------------------------------------
761 ��� MDTrackAppendEvents
762 -------------------------------------- */
763 int32_t
764 MDTrackAppendEvents(MDTrack *inTrack, const MDEvent *inEvent, int32_t count)
765 {
766 MDBlock *block;
767 int32_t index, i, n, nn;
768 if (inTrack == NULL)
769 return 0;
770
771 /* Get the position of the last event */
772 block = inTrack->last;
773 if (block == NULL) {
774 block = MDTrackAllocateBlock(inTrack, NULL, kMDBlockSize);
775 if (block == NULL)
776 return 0;
777 index = 0;
778 } else index = block->num;
779
780 n = 0;
781 while (n < count) {
782 if (index >= block->size) {
783 block = MDTrackAllocateBlock(inTrack, block, kMDBlockSize);
784 if (block == NULL)
785 return n;
786 index = 0;
787 }
788 if (count > block->size - index)
789 nn = block->size - index;
790 else nn = count;
791 MDEventCopy(block->events + index, inEvent, nn);
792 for (i = 0; i < nn; i++) {
793 short ch = MDGetChannel(inEvent + i);
794 if (ch >= 0 && ch < 18)
795 inTrack->nch[ch]++;
796 }
797 block->num += nn;
798 block->largestTick = kMDNegativeTick;
799 index += nn;
800 inEvent += nn;
801 n += nn;
802 }
803 inTrack->num += n;
804 return n;
805 }
806
807 /* --------------------------------------
808 ��� MDTrackMerge
809 -------------------------------------- */
810 MDStatus
811 MDTrackMerge(MDTrack *inTrack1, const MDTrack *inTrack2, IntGroup **ioSet)
812 {
813 MDPointer *src1; /* The source position in inTrack1 */
814 MDPointer *src2; /* The source position in inTrack2 */
815 MDPointer *dest; /* The destination position */
816 MDEvent *eventSrc1, *eventSrc2, *eventDest;
817 int32_t noteCount; /* The number of note-on's that have partners */
818 int32_t destPosition;
819 int32_t i;
820 MDTickType tick1, duration1, duration2;
821 IntGroup *pset = NULL;
822 MDStatus result = kMDNoError;
823 MDBlock *block;
824
825 if (inTrack1 == NULL || inTrack2 == NULL || inTrack2->num == 0)
826 return kMDErrorNoEvents;
827
828 src1 = MDPointerNew(inTrack1);
829 dest = MDPointerNew(inTrack1);
830 if (src1 == NULL || dest == NULL)
831 return kMDErrorOutOfMemory;
832
833 src2 = MDPointerNew((MDTrack *)inTrack2);
834 if (src2 == NULL)
835 return kMDErrorOutOfMemory;
836 MDPointerSetPosition(src2, inTrack2->num - 1);
837
838 if (ioSet != NULL) {
839 pset = IntGroupNew();
840 if (pset == NULL)
841 return kMDErrorOutOfMemory;
842 }
843 eventSrc2 = MDPointerCurrent(src2);
844 tick1 = MDGetTick(eventSrc2);
845
846 /* Prepare the blank space at tick = tick1 + 1 in inTrack1 */
847 MDPointerJumpToTick(dest, tick1 + 1);
848 if (inTrack1->num == 0)
849 i = 0;
850 else
851 i = MDPointerGetPosition(dest);
852 if (MDTrackInsertBlanks(inTrack1, dest, inTrack2->num) < inTrack2->num)
853 return kMDErrorOutOfMemory;
854 MDPointerSetPosition(dest, i - 1 + inTrack2->num);
855 MDPointerSetPosition(src1, i - 1);
856
857 /* i = inTrack1->num;
858 MDPointerSetPosition(dest, i);
859 if (MDTrackInsertBlanks(inTrack1, dest, inTrack2->num) < inTrack2->num)
860 return kMDErrorOutOfMemory;
861 MDPointerSetPosition(dest, inTrack1->num - 1);
862 MDPointerSetPosition(src1, i - 1); */
863
864 eventDest = MDPointerCurrent(dest);
865 eventSrc1 = MDPointerCurrent(src1);
866 noteCount = 0;
867 destPosition = MDPointerGetPosition(dest);
868
869 while (eventSrc2 != NULL) {
870 /* transfer the 'larger' event to dest */
871 unsigned char prefer_2_over_1 = 0;
872 /* MDTickType t1, t2; *//* for debug */
873 /* t1 = (eventSrc1 != NULL ? MDGetTick(eventSrc1) : kMDNegativeTick);
874 t2 = MDGetTick(eventSrc2); */
875 if (eventSrc1 != NULL) {
876 if (MDIsTickEqual(eventSrc1, eventSrc2)) {
877 if (ioSet != NULL && *ioSet != NULL) {
878 /* Consult *ioSet whether we should select eventSrc2 or not */
879 if (IntGroupLookup(*ioSet, MDPointerGetPosition(dest), NULL))
880 prefer_2_over_1 = 1;
881 }
882 } else if (MDIsTickGreater(eventSrc2, eventSrc1)) {
883 prefer_2_over_1 = 1;
884 }
885 } else prefer_2_over_1 = 1;
886 if (prefer_2_over_1) {
887 MDEventCopy(eventDest, eventSrc2, 1);
888 /* fprintf(stderr, "MDTrackMerge: MDEventCopy %ld from %ld (t1=%ld, t2=%ld)\n", MDPointerGetPosition(dest), MDPointerGetPosition(src2), t1, t2); */
889 eventSrc2 = MDPointerBackward(src2);
890 if (pset != NULL) {
891 if (IntGroupAdd(pset, destPosition, 1) != kMDNoError) {
892 result = kMDErrorOutOfMemory;
893 IntGroupRelease(pset);
894 pset = NULL;
895 }
896 }
897 } else {
898 MDEventMove(eventDest, eventSrc1, 1);
899 /* fprintf(stderr, "MDTrackMerge: MDEventMove %ld from %ld (t1=%ld, t2=%ld)\n", MDPointerGetPosition(dest), MDPointerGetPosition(src1), t1, t2); */
900 eventSrc1 = MDPointerBackward(src1);
901 }
902 eventDest = MDPointerBackward(dest);
903 destPosition--;
904 }
905
906 for (i = 0; i < 18; i++) {
907 inTrack1->nch[i] += inTrack2->nch[i];
908 }
909
910 for (block = inTrack1->first; block != NULL; block = block->next)
911 block->largestTick = kMDNegativeTick;
912
913 MDPointerRelease(src2);
914 MDPointerRelease(src1);
915 MDPointerRelease(dest);
916
917 duration1 = inTrack1->duration;
918 duration2 = inTrack2->duration;
919 if (duration2 > duration1)
920 inTrack1->duration = duration2;
921
922 if (ioSet != NULL)
923 *ioSet = pset;
924 else if (pset != NULL)
925 IntGroupRelease(pset);
926
927 /* MDTrackCheck(inTrack1);
928 MDTrackCheck(inTrack2); */
929
930 return result;
931 }
932
933 /* --------------------------------------
934 ��� MDTrackUnmerge
935 -------------------------------------- */
936 static MDStatus
937 sMDTrackUnmergeSub(MDTrack *inTrack, MDTrack **outTrack, const IntGroup *inSet, int deleteFlag)
938 {
939 MDPointer *src;
940 MDPointer *dest;
941 MDEvent *eventSrc, *eventDest;
942 int32_t ptCount; /* The number of points in inSet */
943 int32_t noteCount; /* The number of note-on's that have partners */
944 int32_t destPosition;
945 int32_t index, start, length;
946 int i;
947 MDTickType duration;
948 MDTrack *newTrack;
949 MDBlock *block;
950
951 if (inTrack == NULL || inSet == NULL || (ptCount = IntGroupGetCount(inSet)) == 0)
952 return kMDErrorNoEvents;
953
954 /* Allocate a destination track */
955 newTrack = MDTrackNew();
956 if (newTrack == NULL)
957 return kMDErrorOutOfMemory;
958
959 src = MDPointerNew(inTrack);
960 dest = MDPointerNew(newTrack);
961 if (src == NULL || dest == NULL)
962 return kMDErrorOutOfMemory;
963
964 /* Prepare the blank space */
965 MDPointerSetPosition(dest, 0);
966 if (MDTrackInsertBlanks(newTrack, dest, ptCount) < ptCount)
967 return kMDErrorOutOfMemory;
968 MDPointerSetPosition(dest, 0);
969 destPosition = 0;
970 eventDest = MDPointerCurrent(dest);
971 duration = 0;
972 noteCount = 0;
973
974 /* Copy the events */
975 for (index = 0; index < IntGroupGetIntervalCount(inSet); index++) {
976 start = IntGroupGetStartPoint(inSet, index);
977 length = IntGroupGetInterval(inSet, index);
978 MDPointerSetPosition(src, start);
979 eventSrc = MDPointerCurrent(src);
980 while (eventDest != NULL && eventSrc != NULL && --length >= 0) {
981 MDEventCopy(eventDest, eventSrc, 1);
982 /* Count the event kind */
983 if (MDIsChannelEvent(eventDest))
984 newTrack->nch[MDGetChannel(eventDest)]++;
985 else if (MDIsSysexEvent(eventDest))
986 newTrack->nch[16]++;
987 else
988 newTrack->nch[17]++;
989
990 /* Estimated duration */
991 if (MDGetKind(eventDest) == kMDEventNote)
992 duration = MDGetTick(eventDest) + MDGetDuration(eventDest) + 1;
993 else
994 duration = MDGetTick(eventDest) + 1;
995
996 eventSrc = MDPointerForward(src);
997 eventDest = MDPointerForward(dest);
998 destPosition++;
999 }
1000 if (eventDest == NULL)
1001 break;
1002 }
1003
1004 /* Check if specified number of events have been copied */
1005 if (destPosition < ptCount) {
1006 MDTrackDeleteEvents(newTrack, dest, ptCount - destPosition);
1007 ptCount = destPosition;
1008 }
1009
1010 if (deleteFlag) {
1011 /* Delete the events from the source track */
1012 for (index = IntGroupGetIntervalCount(inSet) - 1; index >= 0; index--) {
1013 start = IntGroupGetStartPoint(inSet, index);
1014 length = IntGroupGetInterval(inSet, index);
1015 if (start < inTrack->num) {
1016 MDPointerSetPosition(src, start);
1017 if (start + length > inTrack->num)
1018 length = inTrack->num - start;
1019 if (length > 0)
1020 MDTrackDeleteEvents(inTrack, src, length);
1021 }
1022 }
1023
1024 for (i = 0; i < 18; i++) {
1025 inTrack->nch[i] -= newTrack->nch[i];
1026 }
1027 for (block = inTrack->first; block != NULL; block = block->next)
1028 block->largestTick = kMDNegativeTick;
1029 }
1030
1031 MDPointerRelease(src);
1032 MDPointerRelease(dest);
1033
1034 newTrack->duration = duration;
1035
1036 /* MDTrackCheck(inTrack);
1037 MDTrackCheck(newTrack); */
1038
1039 if (outTrack != NULL)
1040 *outTrack = newTrack;
1041 else if (newTrack != NULL)
1042 MDTrackRelease(newTrack);
1043
1044 return kMDNoError;
1045 }
1046
1047 MDStatus
1048 MDTrackUnmerge(MDTrack *inTrack, MDTrack **outTrack, const IntGroup *inSet)
1049 {
1050 return sMDTrackUnmergeSub(inTrack, outTrack, inSet, 1);
1051 }
1052
1053 MDStatus
1054 MDTrackExtract(MDTrack *inTrack, MDTrack **outTrack, const IntGroup *inSet)
1055 {
1056 return sMDTrackUnmergeSub(inTrack, outTrack, inSet, 0);
1057 }
1058
1059 /* --------------------------------------
1060 ��� MDTrackSplitByMIDIChannel
1061 -------------------------------------- */
1062 int
1063 MDTrackSplitByMIDIChannel(MDTrack *inTrack, MDTrack **outTracks)
1064 {
1065 int32_t count[16];
1066 int i, n, nn;
1067 MDPointer *pt;
1068 MDEvent *ep;
1069 IntGroup *pset;
1070 pt = MDPointerNew(inTrack);
1071 if (pt == NULL)
1072 return 0;
1073 for (i = 0; i < 16; i++) {
1074 count[i] = 0;
1075 outTracks[i] = NULL;
1076 }
1077 while ((ep = MDPointerForward(pt)) != NULL) {
1078 if (MDIsChannelEvent(ep))
1079 count[MDGetChannel(ep)]++;
1080 }
1081 for (i = n = 0; i < 16; i++) {
1082 if (count[i] > 0) {
1083 n++;
1084 nn = i;
1085 }
1086 }
1087 if (n == 0) {
1088 /* No channel events */
1089 outTracks[0] = inTrack;
1090 return 1;
1091 }
1092 if (n == 1) {
1093 /* No need to split */
1094 outTracks[nn] = inTrack;
1095 return 1;
1096 }
1097 nn = n;
1098 pset = IntGroupNew();
1099 if (pset == NULL) {
1100 MDPointerRelease(pt);
1101 return 0;
1102 }
1103
1104 /* Split by channel */
1105 for (i = 15; i >= 0; i--) {
1106 if (count[i] == 0)
1107 continue;
1108 if (--n == 0) {
1109 /* The last one */
1110 outTracks[i] = inTrack;
1111 break;
1112 }
1113 IntGroupClear(pset);
1114 MDPointerSetPosition(pt, -1);
1115 while ((ep = MDPointerForward(pt)) != NULL) {
1116 if (MDIsChannelEvent(ep) && MDGetChannel(ep) == i)
1117 IntGroupAdd(pset, MDPointerGetPosition(pt), 1);
1118 }
1119 if (MDTrackUnmerge(inTrack, &(outTracks[i]), pset) != kMDNoError) {
1120 MDPointerRelease(pt);
1121 IntGroupRelease(pset);
1122 return 0;
1123 }
1124 }
1125 MDPointerRelease(pt);
1126 IntGroupRelease(pset);
1127 return nn;
1128 }
1129
1130 /* --------------------------------------
1131 ��� MDTrackMatchNoteOff
1132 -------------------------------------- */
1133 MDStatus
1134 MDTrackMatchNoteOff(MDTrack *inTrack, const MDEvent *noteOffEvent, MDPointer *lastPendingNoteOn)
1135 {
1136 MDEvent *ep;
1137 MDStatus result = kMDErrorOrphanedNoteOff;
1138 int32_t lastPendingPos;
1139 unsigned char code = MDGetCode(noteOffEvent);
1140 int channel = MDGetChannel(noteOffEvent);
1141 MDTickType tick = MDGetTick(noteOffEvent);
1142 if (lastPendingNoteOn == NULL) {
1143 lastPendingNoteOn = MDPointerNew(inTrack);
1144 } else {
1145 MDPointerRetain(lastPendingNoteOn);
1146 MDPointerBackward(lastPendingNoteOn);
1147 }
1148 lastPendingPos = -1;
1149 #if 1
1150 while ((ep = MDPointerForward(lastPendingNoteOn)) != NULL) {
1151 if (MDGetKind(ep) == kMDEventInternalNoteOn) {
1152 if (MDGetCode(ep) == code && MDGetChannel(ep) == channel && (MDGetDuration(ep) == 0 || MDGetDuration(ep) == tick - MDGetTick(ep))) {
1153 /* Found */
1154 MDTickType duration = tick - MDGetTick(ep);
1155 MDSetKind(ep, kMDEventNote);
1156 if (duration <= 0)
1157 duration = 1; /* Avoid zero-duration event */
1158 MDSetDuration(ep, duration);
1159 MDSetNoteOffVelocity(ep, MDGetNoteOffVelocity(noteOffEvent));
1160 /* Reset the 'largestTick' field directly */
1161 lastPendingNoteOn->block->largestTick = kMDNegativeTick;
1162 result = kMDNoError;
1163 if (lastPendingPos == -1)
1164 lastPendingPos = MDPointerGetPosition(lastPendingNoteOn) + 1;
1165 break;
1166 }
1167 }
1168 if (lastPendingPos == -1)
1169 lastPendingPos = MDPointerGetPosition(lastPendingNoteOn);
1170 }
1171 if (lastPendingNoteOn->refCount > 1) {
1172 if (lastPendingPos < 0)
1173 MDPointerJumpToLast(lastPendingNoteOn);
1174 else
1175 MDPointerSetPosition(lastPendingNoteOn, lastPendingPos);
1176 }
1177 MDPointerRelease(lastPendingNoteOn);
1178 return result;
1179 #else
1180 /* Do not use MDPointer, but use internal block info directly (for efficiency) */
1181 for (bp = inTrack->last; bp != NULL; bp = bp->last) {
1182 MDEvent *ep;
1183 for (index = bp->num - 1, ep = &(bp->events[index]); index >= 0; index--, ep--) {
1184 if (MDGetKind(ep) == kMDEventInternalNoteOn && MDGetCode(ep) == code && MDGetChannel(ep) == channel) {
1185 MDTickType duration = MDGetDuration(ep);
1186 if (duration == 0 || duration == tick - MDGetTick(ep)) {
1187 /* Found */
1188 MDSetKind(ep, kMDEventNote);
1189 MDSetDuration(ep, tick - MDGetTick(ep));
1190 MDSetNoteOffVelocity(ep, MDGetNoteOffVelocity(noteOffEvent));
1191 bp->largestTick = kMDNegativeTick;
1192 MDPointerRelease(lastPendingNoteOn);
1193 return kMDNoError;
1194 }
1195 }
1196 }
1197 }
1198 return kMDErrorOrphanedNoteOff;
1199 #endif
1200 }
1201
1202 /* --------------------------------------
1203 ��� MDTrackMatchNoteOffInTrack
1204 -------------------------------------- */
1205 MDStatus
1206 MDTrackMatchNoteOffInTrack(MDTrack *inTrack, MDTrack *noteOffTrack)
1207 {
1208 /* Pair note-on with the corresponding note-off */
1209 MDPointer *noteon, *noteoff;
1210 MDEvent *eref1, *eref2;
1211 MDBlock *block;
1212 MDTickType largestTick = kMDNegativeTick;
1213
1214 noteon = MDPointerNew(inTrack);
1215 noteoff = MDPointerNew(noteOffTrack);
1216 if (noteon == NULL || noteoff == NULL)
1217 return kMDErrorOutOfMemory;
1218 while ((eref1 = MDPointerForward(noteon)) != NULL) {
1219 if (MDGetKind(eref1) == kMDEventInternalNoteOn) {
1220 MDPointerJumpToTick(noteoff, MDGetTick(eref1));
1221 MDPointerBackward(noteoff);
1222 while ((eref2 = MDPointerForward(noteoff)) != NULL) {
1223 if (MDGetKind(eref2) == kMDEventInternalNoteOff
1224 && MDGetCode(eref1) == MDGetCode(eref2)
1225 && MDGetChannel(eref1) == MDGetChannel(eref2)) {
1226 MDTickType tick2 = MDGetTick(eref2);
1227 MDSetDuration(eref1, tick2 - MDGetTick(eref1));
1228 MDSetNoteOffVelocity(eref1, MDGetNoteOffVelocity(eref2));
1229 MDSetKind(eref2, kMDEventNull);
1230 MDSetKind(eref1, kMDEventNote);
1231 dprintf(2, "Paired note-event: tick %ld code %d vel %d/%d duration %ld\n", MDGetTick(eref1), MDGetCode(eref1), MDGetNoteOnVelocity(eref1), MDGetNoteOffVelocity(eref1), MDGetDuration(eref1));
1232 if (tick2 > largestTick)
1233 largestTick = tick2;
1234 break;
1235 }
1236 }
1237 }
1238 }
1239 MDPointerRelease(noteon);
1240 MDPointerRelease(noteoff);
1241 for (block = inTrack->first; block != NULL; block = block->next)
1242 block->largestTick = kMDNegativeTick;
1243 if (largestTick > MDTrackGetDuration(inTrack))
1244 MDTrackSetDuration(inTrack, largestTick);
1245 return kMDNoError;
1246 }
1247
1248 static int
1249 sMDTrackEventComparator(const void *a, const void *b)
1250 {
1251 MDTickType ticka, tickb;
1252 ticka = MDGetTick((const MDEvent *)a);
1253 tickb = MDGetTick((const MDEvent *)b);
1254 if (ticka < tickb)
1255 return -1;
1256 else if (ticka > tickb)
1257 return 1;
1258 else return 0;
1259 }
1260
1261 /* --------------------------------------
1262 ��� MDTrackChangeTick
1263 -------------------------------------- */
1264 MDStatus
1265 MDTrackChangeTick(MDTrack *inTrack, MDTickType *newTick)
1266 {
1267 MDBlock *block;
1268 /* int index, i; */
1269 int32_t n, count;
1270 MDTickType largestTick;
1271 /* MDTickType oldTick, tick; */
1272 MDEvent *tempEvents;
1273
1274 #if 1
1275 /* Move all events to a temporary array of MDEvent */
1276 count = MDTrackGetNumberOfEvents(inTrack);
1277 tempEvents = (MDEvent *)malloc(sizeof(MDEvent) * count);
1278 if (tempEvents == NULL)
1279 return kMDErrorOutOfMemory;
1280 n = 0;
1281 for (block = inTrack->first; block != NULL; block = block->next) {
1282 MDEventMove(tempEvents + n, block->events, block->num);
1283 n += block->num;
1284 }
1285
1286 /* Modify tick */
1287 for (n = 0; n < count; n++)
1288 MDSetTick(&tempEvents[n], newTick[n]);
1289
1290 /* Sort event index by the new tick */
1291 qsort(tempEvents, count, sizeof(MDEvent), sMDTrackEventComparator);
1292
1293 /* Move the events back */
1294 n = 0;
1295 for (block = inTrack->first; block != NULL; block = block->next) {
1296 MDEventMove(block->events, tempEvents + n, block->num);
1297 block->largestTick = kMDNegativeTick;
1298 n += block->num;
1299 }
1300 free(tempEvents);
1301
1302 #else
1303 /* Pass 1: Check the new tick order first */
1304 oldTick = kMDNegativeTick;
1305 index = 0;
1306 for (block = inTrack->first; block != NULL; block = block->next) {
1307 for (i = 0; i < block->num; i++) {
1308 if (newTick[index] >= 0)
1309 tick = newTick[index];
1310 else
1311 tick = MDGetTick(&block->events[i]);
1312 if (oldTick > tick)
1313 return kMDErrorTickDisorder;
1314 oldTick = tick;
1315 index++;
1316 }
1317 }
1318
1319 /* Pass 2: Change the tick */
1320 index = 0;
1321 for (block = inTrack->first; block != NULL; block = block->next) {
1322 for (i = 0; i < block->num; i++) {
1323 if (newTick[index] >= 0)
1324 MDSetTick(&block->events[i], newTick[index]);
1325 index++;
1326 }
1327 block->largestTick = kMDNegativeTick;
1328 }
1329 #endif
1330
1331 largestTick = MDTrackGetLargestTick(inTrack);
1332 if (largestTick >= inTrack->duration)
1333 inTrack->duration = largestTick + 1;
1334 return kMDNoError;
1335 }
1336
1337 /* --------------------------------------
1338 ��� MDTrackOffsetTick
1339 -------------------------------------- */
1340 MDStatus
1341 MDTrackOffsetTick(MDTrack *inTrack, MDTickType offset)
1342 {
1343 MDBlock *block;
1344 int i;
1345 MDTickType tick;
1346
1347 for (block = inTrack->first; block != NULL; block = block->next) {
1348 if (block->largestTick >= 0)
1349 block->largestTick += offset;
1350 for (i = 0; i < block->num; i++) {
1351 MDEvent *ep = &block->events[i];
1352 tick = MDGetTick(ep) + offset;
1353 if (tick < 0) {
1354 tick = 0;
1355 block->largestTick = kMDNegativeTick;
1356 }
1357 MDSetTick(ep, tick);
1358 }
1359 }
1360
1361 inTrack->duration += offset;
1362 tick = MDTrackGetLargestTick(inTrack);
1363 if (tick >= inTrack->duration)
1364 inTrack->duration = tick + 1;
1365 return kMDNoError;
1366 }
1367
1368 #ifdef __MWERKS__
1369 #pragma mark ====== Duration search ======
1370 #endif
1371
1372 /* --------------------------------------
1373 ��� MDTrackGetLargestTick
1374 -------------------------------------- */
1375 MDTickType
1376 MDTrackGetLargestTick(MDTrack *inTrack)
1377 {
1378 MDTickType globalLargestTick;
1379 MDBlock *block;
1380 globalLargestTick = kMDNegativeTick;
1381 for (block = inTrack->first; block != NULL; block = block->next) {
1382 MDTrackUpdateLargestTickForBlock(inTrack, block);
1383 if (block->largestTick > globalLargestTick)
1384 globalLargestTick = block->largestTick;
1385 }
1386 return globalLargestTick;
1387 }
1388
1389 /* --------------------------------------
1390 ��� MDTrackSearchEventsWithDurationCrossingTick
1391 -------------------------------------- */
1392 IntGroup *
1393 MDTrackSearchEventsWithDurationCrossingTick(MDTrack *inTrack, MDTickType inTick)
1394 {
1395 IntGroup *pset;
1396 int32_t position, i;
1397 MDTickType tick, largestTick;
1398 MDBlock *block;
1399 MDEvent *ep;
1400 pset = IntGroupNew();
1401 if (pset == NULL)
1402 return NULL;
1403 position = 0;
1404 for (block = inTrack->first; block != NULL; block = block->next) {
1405 if (block->largestTick < 0 || block->largestTick >= inTick) {
1406 largestTick = kMDNegativeTick;
1407 for (i = 0; i < block->num; i++) {
1408 ep = &block->events[i];
1409 tick = MDGetTick(ep);
1410 if (tick >= inTick)
1411 goto exit;
1412 if (MDHasDuration(ep)) {
1413 tick += MDGetDuration(ep);
1414 if (tick >= inTick) {
1415 if (IntGroupAdd(pset, position + i, 1) != kMDNoError) {
1416 IntGroupRelease(pset);
1417 return NULL;
1418 }
1419 }
1420 }
1421 if (tick > largestTick)
1422 largestTick = tick;
1423 }
1424 block->largestTick = largestTick;
1425 }
1426 position += block->num;
1427 }
1428 exit:
1429 return pset;
1430 }
1431
1432 /* --------------------------------------
1433 ��� MDTrackSearchEventsWithSelector
1434 -------------------------------------- */
1435 IntGroup *
1436 MDTrackSearchEventsWithSelector(MDTrack *inTrack, MDEventSelector inSelector, void *inUserData)
1437 {
1438 IntGroup *pset;
1439 MDPointer *pt;
1440 MDEvent *ep;
1441 pset = IntGroupNew();
1442 pt = MDPointerNew(inTrack);
1443 if (pset == NULL || pt == NULL)
1444 return NULL;
1445 while ((ep = MDPointerForwardWithSelector(pt, inSelector, inUserData)) != NULL) {
1446 if (IntGroupAdd(pset, MDPointerGetPosition(pt), 1) != kMDNoError) {
1447 MDPointerRelease(pt);
1448 IntGroupRelease(pset);
1449 return NULL;
1450 }
1451 }
1452 MDPointerRelease(pt);
1453 return pset;
1454 }
1455
1456 #ifdef __MWERKS__
1457 #pragma mark ====== Track/device/channel manipulations ======
1458 #endif
1459
1460 /* --------------------------------------
1461 ��� MDTrackRemapChannel
1462 -------------------------------------- */
1463 void
1464 MDTrackRemapChannel(MDTrack *inTrack, const unsigned char *newch)
1465 {
1466 int32_t nnch[16];
1467 int32_t n;
1468 MDBlock *block;
1469 static unsigned char allzero[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1470 if (inTrack == NULL)
1471 return;
1472 if (newch == NULL)
1473 newch = allzero;
1474 for (n = 0; n < 16; n++)
1475 nnch[n] = 0;
1476 for (block = inTrack->first; block != NULL; block = block->next) {
1477 MDEvent *ep = block->events;
1478 for (n = 0; n < block->num; n++, ep++) {
1479 if (MDIsChannelEvent(ep)) {
1480 unsigned char ch;
1481 ch = (newch[MDGetChannel(ep) & 15]) & 15;
1482 MDSetChannel(ep, ch);
1483 nnch[ch]++;
1484 }
1485 }
1486 }
1487 for (n = 0; n < 16; n++)
1488 inTrack->nch[n] = nnch[n];
1489 }
1490
1491 /* --------------------------------------
1492 ��� MDTrackSetDevice
1493 -------------------------------------- */
1494 void
1495 MDTrackSetDevice(MDTrack *inTrack, int32_t dev)
1496 {
1497 if (inTrack != NULL)
1498 inTrack->dev = dev;
1499 }
1500
1501 /* --------------------------------------
1502 ��� MDTrackGetDevice
1503 -------------------------------------- */
1504 int32_t
1505 MDTrackGetDevice(const MDTrack *inTrack)
1506 {
1507 if (inTrack != NULL)
1508 return inTrack->dev;
1509 else return -1;
1510 }
1511
1512 /* --------------------------------------
1513 ��� MDTrackSetTrackChannel
1514 -------------------------------------- */
1515 void
1516 MDTrackSetTrackChannel(MDTrack *inTrack, short ch)
1517 {
1518 if (inTrack != NULL)
1519 inTrack->channel = ch;
1520 }
1521
1522 /* --------------------------------------
1523 ��� MDTrackGetTrackChannel
1524 -------------------------------------- */
1525 short
1526 MDTrackGetTrackChannel(const MDTrack *inTrack)
1527 {
1528 if (inTrack != NULL)
1529 return inTrack->channel;
1530 else return -1;
1531 }
1532
1533 /* --------------------------------------
1534 ��� MDTrackSetName
1535 -------------------------------------- */
1536 MDStatus
1537 MDTrackSetName(MDTrack *inTrack, const char *inName)
1538 {
1539 char *p;
1540 if (inName == NULL)
1541 p = NULL;
1542 else {
1543 p = (char *)malloc(strlen(inName) + 1);
1544 if (p == NULL)
1545 return kMDErrorOutOfMemory;
1546 strcpy(p, inName);
1547 }
1548 if (inTrack->name != NULL)
1549 free(inTrack->name);
1550 inTrack->name = p;
1551 return kMDNoError;
1552 }
1553
1554 /* --------------------------------------
1555 ��� MDTrackGetName
1556 -------------------------------------- */
1557 void
1558 MDTrackGetName(const MDTrack *inTrack, char *outName, int32_t length)
1559 {
1560 if (inTrack->name == NULL) {
1561 outName[0] = 0;
1562 } else {
1563 strncpy(outName, inTrack->name, length - 1);
1564 outName[length - 1] = 0;
1565 }
1566 }
1567
1568 /* --------------------------------------
1569 ��� MDTrackSetDeviceName
1570 -------------------------------------- */
1571 MDStatus
1572 MDTrackSetDeviceName(MDTrack *inTrack, const char *inName)
1573 {
1574 char *p;
1575 if (inName == NULL)
1576 p = NULL;
1577 else {
1578 p = (char *)malloc(strlen(inName) + 1);
1579 if (p == NULL)
1580 return kMDErrorOutOfMemory;
1581 strcpy(p, inName);
1582 }
1583 if (inTrack->devname != NULL)
1584 free(inTrack->devname);
1585 inTrack->devname = p;
1586 return kMDNoError;
1587 }
1588
1589 /* --------------------------------------
1590 ��� MDTrackGetDeviceName
1591 -------------------------------------- */
1592 void
1593 MDTrackGetDeviceName(const MDTrack *inTrack, char *outName, int32_t length)
1594 {
1595 if (inTrack->devname == NULL) {
1596 outName[0] = 0;
1597 } else {
1598 strncpy(outName, inTrack->devname, length - 1);
1599 outName[length - 1] = 0;
1600 }
1601 }
1602
1603 /* --------------------------------------
1604 ��� MDTrackGuessName
1605 -------------------------------------- */
1606 void
1607 MDTrackGuessName(MDTrack *inTrack, char *outName, int32_t length)
1608 {
1609 MDPointer *ptr;
1610 MDEvent *eref, *stopref;
1611 int32_t len;
1612
1613 ptr = MDPointerNew(inTrack);
1614
1615 /* Pass 1: find the track name meta event */
1616 while ((eref = MDPointerForward(ptr)) != NULL) {
1617 if (MDIsTextMetaEvent(eref) && MDGetCode(eref) == kMDMetaSequenceName)
1618 break;
1619 if (MDIsChannelEvent(eref) || MDIsSysexEvent(eref)) {
1620 stopref = eref;
1621 eref = NULL;
1622 break; /* not found */
1623 }
1624 }
1625
1626 if (eref == NULL) {
1627 /* Pass 2: find the first text meta event */
1628 MDPointerSetPosition(ptr, -1);
1629 while ((eref = MDPointerForward(ptr)) != NULL) {
1630 if (MDIsTextMetaEvent(eref) && MDGetCode(eref) == kMDMetaText)
1631 break;
1632 if (eref == stopref)
1633 break; /* not found */
1634 }
1635 }
1636
1637 if (eref != NULL && eref != stopref) {
1638 len = MDGetMessagePartial(eref, (unsigned char *)outName, 0, length - 1);
1639 outName[len] = 0;
1640 } else {
1641 outName[0] = 0;
1642 }
1643
1644 MDPointerRelease(ptr);
1645 }
1646
1647 /* --------------------------------------
1648 ��� MDTrackGuessDeviceName
1649 -------------------------------------- */
1650 void
1651 MDTrackGuessDeviceName(MDTrack *inTrack, char *outName, int32_t length)
1652 {
1653 MDPointer *ptr;
1654 MDEvent *eref, *stopref;
1655 char name[256];
1656 char c;
1657 char *p;
1658 int n, port;
1659 int32_t len;
1660
1661 ptr = MDPointerNew(inTrack);
1662
1663 port = -1;
1664
1665 /* Pass 1: find the device name meta event */
1666 while ((eref = MDPointerForward(ptr)) != NULL) {
1667 if (MDIsTextMetaEvent(eref) && MDGetCode(eref) == kMDMetaDeviceName)
1668 break;
1669 if (MDIsChannelEvent(eref) || MDIsSysexEvent(eref)) {
1670 stopref = eref;
1671 eref = NULL;
1672 break; /* not found */
1673 }
1674 }
1675
1676 if (eref == NULL) {
1677 /* Pass 2: find the instrument name meta event */
1678 MDPointerSetPosition(ptr, -1);
1679 while ((eref = MDPointerForward(ptr)) != NULL) {
1680 if (MDIsTextMetaEvent(eref) && MDGetCode(eref) == kMDMetaInstrumentName)
1681 break;
1682 if (eref == stopref)
1683 break; /* not found */
1684 }
1685 }
1686
1687 if (eref == NULL || eref == stopref) {
1688 /* Pass 3: find the port number meta event */
1689 MDPointerSetPosition(ptr, -1);
1690 while ((eref = MDPointerForward(ptr)) != NULL) {
1691 if (MDGetKind(eref) == kMDEventPortNumber) {
1692 port = MDGetData1(eref);
1693 break;
1694 }
1695 if (eref == stopref)
1696 break; /* not found */
1697 }
1698 }
1699
1700 if (eref == NULL || eref == stopref) {
1701 /* Pass 4: guess from the track name */
1702 MDTrackGuessName(inTrack, name, 250);
1703 if (sscanf(name, "[%c%d]", &c, &n) == 2
1704 || sscanf(name, "(%c%d)", &c, &n) == 2
1705 || sscanf(name, "<%c%d>", &c, &n) == 2
1706 || sscanf(name, "{%c%d}", &c, &n) == 2
1707 || sscanf(name, "%c%d:", &c, &n) == 2) {
1708 if (isalpha(c))
1709 port = toupper(c) - 'A';
1710 } else {
1711 for (n = 0, p = name; name[n] != 0; n++) {
1712 /* Purge non-alphanumeric characters */
1713 if (isalnum(name[n]))
1714 *p++ = toupper(name[n]);
1715 }
1716 *p = 0;
1717 if (strncmp(name, "PART", 4) == 0 || strncmp(name, "PORT", 4) == 0) {
1718 if (isalpha(name[4]))
1719 port = name[4] - 'A';
1720 else if (isdigit(name[4]))
1721 port = atoi(name + 4);
1722 } else port = 0;
1723 }
1724 }
1725
1726 name[0] = 0;
1727 if (port >= 0) {
1728 sprintf(name, "(Device %d)", (int)(port + 1));
1729 } else if (eref != NULL && eref != stopref) {
1730 len = MDGetMessagePartial(eref, (unsigned char *)name, 0, 255);
1731 name[len] = 0;
1732 }
1733 if (name[0] == 0) {
1734 /* No clue */
1735 /* strcpy(name, "(Device 1)"); */
1736 }
1737
1738 strncpy(outName, name, length - 1);
1739 outName[length - 1] = 0;
1740
1741 MDPointerRelease(ptr);
1742 }
1743
1744 #ifdef __MWERKS__
1745 #pragma mark ====== Attribute manipulations ======
1746 #endif
1747
1748 MDTrackAttribute
1749 MDTrackGetAttribute(const MDTrack *inTrack)
1750 {
1751 return inTrack->attribute;
1752 }
1753
1754 void
1755 MDTrackSetAttribute(MDTrack *inTrack, MDTrackAttribute inAttribute)
1756 {
1757 inTrack->attribute = inAttribute;
1758 }
1759
1760 #ifdef __MWERKS__
1761 #pragma mark ====== Debugging functions ======
1762 #endif
1763
1764 void
1765 MDTrackDump(const MDTrack *inTrack)
1766 {
1767 MDPointer *pt;
1768 MDEvent *ev;
1769 char buf[256];
1770 FILE *fp = fopen("Alchemusica.dump", "w");
1771 if (fp == NULL)
1772 fp = stdout;
1773 pt = MDPointerNew((MDTrack *)inTrack);
1774 while ((ev = MDPointerForward(pt)) != NULL) {
1775 fprintf(fp, "%12d ", (int)MDGetTick(ev));
1776 MDEventToKindString(ev, buf, sizeof buf);
1777 fprintf(fp, "%s ", buf);
1778 fprintf(fp, "%d %d %d %d ", (int)MDGetCode(ev), (int)MDGetChannel(ev), (int)MDGetData1(ev), (int)MDGetDuration(ev));
1779 fprintf(fp, "(@%p)\n", ev);
1780 }
1781 if (fp != NULL)
1782 fclose(fp);
1783 }
1784
1785 int
1786 MDTrackRecache(MDTrack *inTrack, int check)
1787 {
1788 MDPointer *pt1, *pt2;
1789 MDEvent *ev1;
1790 int32_t nch[18];
1791 int32_t i, pos;
1792 MDTickType tick, lastTick;
1793 MDBlock *block;
1794 int errcnt = 0;
1795
1796 pt1 = MDPointerNew((MDTrack *)inTrack);
1797 pt2 = MDPointerNew((MDTrack *)inTrack);
1798 if (pt1 == NULL || pt2 == NULL)
1799 return kMDErrorOutOfMemory;
1800 lastTick = kMDNegativeTick;
1801 for (i = 0; i < 18; i++)
1802 nch[i] = 0;
1803
1804 pos = -1;
1805 while ((ev1 = MDPointerForward(pt1)) != NULL) {
1806 pos = MDPointerGetPosition(pt1);
1807 if (check && (MDGetKind(ev1) < 1 || MDGetKind(ev1) > kMDEventStop)) {
1808 fprintf(stderr, "#%d: invalid event kind %d\n", (int)pos, (int)MDGetKind(ev1));
1809 errcnt++;
1810 }
1811 tick = MDGetTick(ev1);
1812 if (check && tick < lastTick) {
1813 fprintf(stderr, "#%d: tick disorder %d (last tick = %d)\n", (int)pos, (int)tick, (int)lastTick);
1814 errcnt++;
1815 }
1816 lastTick = tick;
1817 if (MDIsChannelEvent(ev1)) {
1818 if (check && (unsigned)(MDGetChannel(ev1)) >= 16) {
1819 fprintf(stderr, "#%d: channel number (%ud) >= 16\n", (int)pos, (unsigned int)MDGetChannel(ev1));
1820 errcnt++;
1821 } else
1822 nch[MDGetChannel(ev1)]++;
1823 } else if (MDIsSysexEvent(ev1)) {
1824 nch[16]++;
1825 } else nch[17]++;
1826 }
1827 ++pos;
1828 if (check && pos != inTrack->num) {
1829 fprintf(stderr, "The track->num (%d) does not match the number of events (%d)\n", pos, inTrack->num);
1830 errcnt++;
1831 }
1832 inTrack->num = pos;
1833 if (check && lastTick >= inTrack->duration) {
1834 fprintf(stderr, "The tick of the last event (%qd) exceeds the track duration (%qd)\n",
1835 (int64_t)lastTick, (int64_t)inTrack->duration);
1836 errcnt++;
1837 }
1838 for (i = 0; i < 18; i++) {
1839 if (check && nch[i] != inTrack->nch[i]) {
1840 fprintf(stderr, "The track->nch[%d] (%d) does not seem correct (%d)\n", (int)i, inTrack->nch[i], nch[i]);
1841 errcnt++;
1842 }
1843 inTrack->nch[i] = nch[i];
1844 }
1845
1846 lastTick = kMDNegativeTick;
1847 for (block = inTrack->first; block != NULL; block = block->next) {
1848 tick = kMDNegativeTick;
1849 for (i = 0; i < block->num; i++) {
1850 MDTickType tick2;
1851 ev1 = &block->events[i];
1852 tick2 = MDGetTick(ev1);
1853 if (MDHasDuration(ev1))
1854 tick2 += MDGetDuration(ev1);
1855 if (tick2 > tick)
1856 tick = tick2;
1857 }
1858 if (check && (block->largestTick >= 0 && tick != block->largestTick)) {
1859 fprintf(stderr, "The largestTick(%d) does not match the largest tick(%d) in block %p\n", (int)block->largestTick, (int)tick, block);
1860 errcnt++;
1861 }
1862 block->largestTick = tick;
1863 if (tick > lastTick)
1864 lastTick = tick;
1865 }
1866 if (lastTick >= inTrack->duration) {
1867 if (check) {
1868 fprintf(stderr, "The track duration (%d) is not greater than the largest tick (%d)\n", (int)inTrack->duration, (int)lastTick);
1869 errcnt++;
1870 }
1871 inTrack->duration = lastTick + 1;
1872 }
1873
1874 MDPointerRelease(pt1);
1875 MDPointerRelease(pt2);
1876 return errcnt;
1877 }
1878
1879
1880 #ifdef __MWERKS__
1881 #pragma mark ====== MDPointer manipulations (private functions) ======
1882 #endif
1883
1884 static void
1885 MDTrackAttachPointer(const MDTrack *inTrack, MDPointer *inPointer)
1886 {
1887 if (inTrack == NULL || inPointer == NULL)
1888 return;
1889 inPointer->next = inTrack->pointer;
1890
1891 /* pointer is a 'mutable' member, so this cast is acceptable */
1892 ((MDTrack *)inTrack)->pointer = inPointer;
1893 }
1894
1895 static void
1896 MDTrackDetachPointer(const MDTrack *inTrack, MDPointer *inPointer)
1897 {
1898 MDPointer *currRef, *prevRef;
1899 if (inTrack == NULL || inPointer == NULL)
1900 return;
1901 currRef = inTrack->pointer;
1902 prevRef = NULL;
1903 while (currRef != NULL) {
1904 if (currRef == inPointer) {
1905 if (prevRef == NULL) {
1906 /* pointer is a 'mutable' member, so this cast is acceptable */
1907 ((MDTrack *)inTrack)->pointer = currRef->next;
1908 } else {
1909 prevRef->next = currRef->next;
1910 }
1911 break;
1912 }
1913 prevRef = currRef;
1914 currRef = currRef->next;
1915 }
1916 }
1917
1918 #ifdef __MWERKS__
1919 #pragma mark -
1920 #pragma mark ====== MDPointer functions ======
1921 #endif
1922
1923 /* --------------------------------------
1924 ��� MDPointerNew
1925 -------------------------------------- */
1926 MDPointer *
1927 MDPointerNew(MDTrack *inTrack)
1928 {
1929 MDPointer *theRef = (MDPointer *)malloc(sizeof(MDPointer));
1930 if (theRef == NULL)
1931 return NULL; /* out of memory */
1932
1933 theRef->refCount = 1;
1934 theRef->parent = NULL;
1935 theRef->next = NULL;
1936 theRef->block = NULL;
1937 theRef->position = -1;
1938 theRef->index = 0;
1939 theRef->removed = 0;
1940 theRef->autoAdjust = 0;
1941 /* theRef->allocated = 1; */
1942 if (inTrack != NULL)
1943 MDPointerSetTrack(theRef, inTrack);
1944 return theRef;
1945 }
1946
1947 /* --------------------------------------
1948 ��� MDPointerRetain
1949 -------------------------------------- */
1950 void
1951 MDPointerRetain(MDPointer *inPointer)
1952 {
1953 inPointer->refCount++;
1954 }
1955
1956 /* --------------------------------------
1957 ��� MDPointerRelease
1958 -------------------------------------- */
1959 void
1960 MDPointerRelease(MDPointer *inPointer)
1961 {
1962 if (inPointer == NULL)
1963 return;
1964 if (--inPointer->refCount == 0) {
1965 MDPointerSetTrack(inPointer, NULL);
1966 free(inPointer);
1967 }
1968 }
1969
1970 /* --------------------------------------
1971 ��� MDPointerCopy
1972 -------------------------------------- */
1973 void
1974 MDPointerCopy(MDPointer *inDest, const MDPointer *inSrc)
1975 {
1976 if (inDest->parent == inSrc->parent) {
1977 inDest->block = inSrc->block;
1978 inDest->position = inSrc->position;
1979 inDest->index = inSrc->index;
1980 inDest->removed = inSrc->removed;
1981 } else {
1982 MDPointerSetPosition(inDest, MDPointerGetPosition(inSrc));
1983 }
1984 }
1985
1986 /* --------------------------------------
1987 ��� MDPointerSetTrack
1988 -------------------------------------- */
1989 void
1990 MDPointerSetTrack(MDPointer *inPointer, MDTrack *inTrack)
1991 {
1992 if (inPointer->parent != inTrack) {
1993 if (inPointer->parent != NULL)
1994 MDTrackDetachPointer(inPointer->parent, inPointer);
1995 inPointer->parent = inTrack;
1996 if (inTrack != NULL)
1997 MDTrackAttachPointer(inTrack, inPointer);
1998 inPointer->position = -1;
1999 if (inTrack != NULL)
2000 inPointer->block = inTrack->first;
2001 else inPointer->block = NULL;
2002 inPointer->index = -1;
2003 inPointer->removed = 0;
2004 }
2005 }
2006
2007 /* --------------------------------------
2008 ��� MDPointerGetTrack
2009 -------------------------------------- */
2010 MDTrack *
2011 MDPointerGetTrack(const MDPointer *inPointer)
2012 {
2013 return inPointer->parent;
2014 }
2015
2016 /* --------------------------------------
2017 ��� MDPointerUpdateBlock
2018 -------------------------------------- */
2019 static int
2020 MDPointerUpdateBlock(MDPointer *inPointer)
2021 {
2022 int32_t num;
2023 int32_t position;
2024
2025 num = inPointer->parent->num;
2026 position = inPointer->position;
2027
2028 if (num == 0) {
2029 inPointer->block = NULL;
2030 inPointer->index = inPointer->position = -1;
2031 return 0;
2032 } else if (position < num / 2) {
2033 /* Search the position starting from the first block */
2034 inPointer->block = inPointer->parent->first;
2035 inPointer->index = 0;
2036 if (position < 0) {
2037 inPointer->index = inPointer->position = -1;
2038 return 0;
2039 } else {
2040 while (position >= inPointer->block->num) {
2041 position -= inPointer->block->num;
2042 inPointer->block = inPointer->block->next;
2043 }
2044 inPointer->index = position;
2045 return 1;
2046 }
2047 } else {
2048 /* Search the position starting from the last block */
2049 inPointer->block = inPointer->parent->last;
2050 inPointer->index = inPointer->block->num;
2051 if (position >= num) {
2052 inPointer->position = num;
2053 return 0;
2054 } else {
2055 int32_t offset = num - position;
2056 while (offset > inPointer->block->num) {
2057 offset -= inPointer->block->num;
2058 inPointer->block = inPointer->block->last;
2059 }
2060 inPointer->index = inPointer->block->num - offset;
2061 return 1;
2062 }
2063 }
2064 }
2065
2066 /* --------------------------------------
2067 ��� MDPointerSetPosition
2068 -------------------------------------- */
2069 int
2070 MDPointerSetPosition(MDPointer *inPointer, int32_t inPos)
2071 {
2072 if (inPointer->parent == NULL)
2073 return 0; /* always false */
2074
2075 inPointer->position = inPos;
2076 inPointer->removed = 0;
2077 return MDPointerUpdateBlock(inPointer);
2078 }
2079
2080 /* --------------------------------------
2081 ��� MDPointerSetRelativePosition
2082 -------------------------------------- */
2083 int
2084 MDPointerSetRelativePosition(MDPointer *inPointer, int32_t inOffset)
2085 {
2086 int32_t num;
2087
2088 if (inPointer->parent == NULL)
2089 return 0; /* always false */
2090 num = inPointer->parent->num;
2091
2092 if (inOffset == 0 || num == 0)
2093 return (inPointer->position >= 0 && inPointer->position < num); /* do nothing */
2094
2095 inPointer->removed = 0;
2096 if (inPointer->position + inOffset < 0) {
2097 inPointer->block = inPointer->parent->first;
2098 inPointer->index = inPointer->position = -1;
2099 return 0;
2100 } else if (inPointer->position + inOffset >= num) {
2101 inPointer->block = inPointer->parent->last;
2102 inPointer->index = inPointer->block->num;
2103 inPointer->position = num;
2104 return 0;
2105 } else {
2106 inPointer->position += inOffset;
2107 /* Move temporarily to the top of the current block */
2108 inOffset += inPointer->index;
2109 inPointer->index = 0;
2110 if (inOffset > 0) {
2111 /* Search forward */
2112 while (inOffset >= inPointer->block->num) {
2113 inOffset -= inPointer->block->num;
2114 inPointer->block = inPointer->block->next;
2115 }
2116 inPointer->index = inOffset;
2117 } else if (inOffset < 0) {
2118 /* Search backward */
2119 do {
2120 inPointer->block = inPointer->block->last;
2121 inOffset += inPointer->block->num;
2122 } while (inOffset < 0);
2123 inPointer->index = inOffset;
2124 }
2125 return 1;
2126 }
2127
2128 }
2129
2130 /* --------------------------------------
2131 ��� MDPointerGetPosition
2132 -------------------------------------- */
2133 int32_t
2134 MDPointerGetPosition(const MDPointer *inPointer)
2135 {
2136 return inPointer->position;
2137 }
2138
2139 /* --------------------------------------
2140 ��� MDPointerSetAutoAdjust
2141 -------------------------------------- */
2142 void
2143 MDPointerSetAutoAdjust(MDPointer *inPointer, char flag)
2144 {
2145 inPointer->autoAdjust = (flag != 0);
2146 }
2147
2148 /* --------------------------------------
2149 ��� MDPointerIsAutoAdjust
2150 -------------------------------------- */
2151 int
2152 MDPointerIsAutoAdjust(const MDPointer *inPointer)
2153 {
2154 return inPointer->autoAdjust;
2155 }
2156
2157 /* --------------------------------------
2158 ��� MDPointerIsRemoved
2159 -------------------------------------- */
2160 int
2161 MDPointerIsRemoved(const MDPointer *inPointer)
2162 {
2163 return inPointer->removed;
2164 }
2165
2166 /* --------------------------------------
2167 ��� MDPointerJumpToTick
2168 -------------------------------------- */
2169 int
2170 MDPointerJumpToTick(MDPointer *inPointer, MDTickType inTick)
2171 {
2172 int32_t num;
2173 MDEvent event;
2174
2175 if (inPointer->parent == NULL)
2176 return 0; /* always false */
2177 num = inPointer->parent->num;
2178
2179 /* There are no events */
2180 if (num == 0)
2181 return 0;
2182
2183 inPointer->removed = 0;
2184
2185 /* Move to the top of the current block */
2186 inPointer->position -= inPointer->index;
2187 if (inPointer->block == NULL)
2188 inPointer->block = inPointer->parent->first;
2189 inPointer->index = 0;
2190
2191 /* dummy event for comparison only */
2192 MDEventInit(&event);
2193 MDSetTick(&event, inTick);
2194
2195 /* Look for the block whose first event >= inTick */
2196 if (MDIsTickGreaterOrEqual(inPointer->block->events, &event)) {
2197 /* The first event is already >= inTick */
2198 /* Search backward */
2199 while (inPointer->block->last != NULL) {
2200 if (MDIsTickLess(inPointer->block->last->events, &event))
2201 break;
2202 inPointer->block = inPointer->block->last;
2203 inPointer->position -= inPointer->block->num;
2204 }
2205 } else {
2206 /* Search forward */
2207 do {
2208 inPointer->position += inPointer->block->num;
2209 inPointer->block = inPointer->block->next;
2210 } while (inPointer->block != NULL && MDIsTickLess(inPointer->block->events, &event));
2211 }
2212
2213 if (inPointer->block != NULL &&
2214 (inPointer->block->last == NULL ||
2215 MDIsTickLess(inPointer->block->last->events + inPointer->block->last->num - 1, &event))) {
2216 /* If this is the first block, or the last event in the previous block is < inEvent,
2217 then the first event in this block is the goal */
2218 inPointer->index = 0;
2219 } else {
2220 /* The goal is contained in the last block */
2221 if (inPointer->block == NULL) {
2222 inPointer->block = inPointer->parent->last;
2223 } else {
2224 /* inPointer->block->last should not be NULL (that case is already processed in the
2225 previous "if" statement) */
2226 inPointer->block = inPointer->block->last;
2227 }
2228 inPointer->position -= inPointer->block->num;
2229
2230 /* Look in this block for the first event which is >= inTick */
2231 /* (If there are no such events, then the current position becomes the
2232 "end of sequence") */
2233 for (inPointer->index = 0; inPointer->index < inPointer->block->num; inPointer->index++) {
2234 if (MDIsTickGreaterOrEqual(inPointer->block->events + inPointer->index, &event))
2235 break;
2236 }
2237 inPointer->position += inPointer->index;
2238 }
2239
2240 return (inPointer->position < num);
2241 }
2242
2243 /* --------------------------------------
2244 ��� MDPointerJumpToLast
2245 -------------------------------------- */
2246 int
2247 MDPointerJumpToLast(MDPointer *inPointer)
2248 {
2249 if (inPointer->parent == NULL)
2250 return 0;
2251 if (inPointer->parent->last == NULL)
2252 return 0;
2253 inPointer->position = inPointer->parent->num - 1;
2254 inPointer->block = inPointer->parent->last;
2255 inPointer->index = inPointer->parent->last->num - 1;
2256 inPointer->removed = 0;
2257 return 1;
2258 }
2259
2260 /* --------------------------------------
2261 ��� MDPointerLookForEvent
2262 -------------------------------------- */
2263 int
2264 MDPointerLookForEvent(MDPointer *inPointer, const MDEvent *inEvent)
2265 {
2266 int32_t savePos;
2267 MDBlock *saveBlock;
2268 MDTickType tick;
2269
2270 if (inPointer->parent == NULL || inPointer->parent->num == 0 || inEvent == NULL)
2271 return 0;
2272
2273 /* Move to the top event in the current block */
2274 inPointer->position -= inPointer->index;
2275 inPointer->index = 0;
2276
2277 savePos = inPointer->position;
2278 saveBlock = inPointer->block;
2279 tick = MDGetTick(inEvent);
2280
2281 /* Search forward */
2282 while (inPointer->block != NULL && MDGetTick(inPointer->block->events) <= tick) {
2283 /* This if-statement is violating ANSI standard (i.e. it assumes arbitrary two pointers
2284 can be compared). However, this is allowed in most platforms. */
2285 if (inPointer->block->events <= inEvent
2286 && inEvent < inPointer->block->events + inPointer->block->num) {
2287 goto found;
2288 }
2289 inPointer->position += inPointer->block->num;
2290 inPointer->block = inPointer->block->next;
2291 }
2292
2293 inPointer->position = savePos;
2294 inPointer->block = saveBlock;
2295
2296 /* Search backward */
2297 while (inPointer->block != NULL && MDGetTick(inPointer->block->events) >= tick) {
2298 if (inPointer->block->last != NULL) {
2299 inPointer->block = inPointer->block->last;
2300 inPointer->position -= inPointer->block->num;
2301 } else break;
2302 /* Another illegal if-statement */
2303 if (inPointer->block->events <= inEvent
2304 && inEvent < inPointer->block->events + inPointer->block->num) {
2305 goto found;
2306 }
2307 }
2308
2309 /* Not found */
2310 inPointer->position = savePos;
2311 inPointer->block = saveBlock;
2312 return 0;
2313
2314 found:
2315 /* Found */
2316 inPointer->index = (int)(inEvent - inPointer->block->events);
2317 inPointer->position += inPointer->index;
2318 inPointer->removed = 0;
2319 return 1;
2320 }
2321
2322 /* --------------------------------------
2323 ��� MDPointerNextPos
2324 -------------------------------------- */
2325 static int
2326 MDPointerNextPos(MDPointer *inPointer)
2327 {
2328 inPointer->removed = 0;
2329 if (inPointer->block == NULL) {
2330 if (inPointer->parent == NULL || inPointer->parent->num == 0)
2331 return 0; /* No event: no change */
2332 MDPointerUpdateBlock(inPointer);
2333 }
2334 if (++(inPointer->position) == 0) {
2335 inPointer->block = inPointer->parent->first;
2336 inPointer->index = 0;
2337 if (inPointer->block == NULL)
2338 return 0;
2339 } else {
2340 if (++(inPointer->index) >= inPointer->block->num) {
2341 if (inPointer->block->next == NULL) {
2342 return 0;
2343 }
2344 inPointer->block = inPointer->block->next;
2345 inPointer->index = 0;
2346 }
2347 }
2348 return 1;
2349 }
2350
2351 /* --------------------------------------
2352 ��� MDPointerPreviousPos
2353 -------------------------------------- */
2354 static int
2355 MDPointerPreviousPos(MDPointer *inPointer)
2356 {
2357 if (inPointer->position <= 0) {
2358 if (inPointer->position == 0) {
2359 inPointer->block = NULL;
2360 inPointer->index = -1;
2361 inPointer->position = -1;
2362 }
2363 return 0;
2364 } else {
2365 if ((inPointer->position)-- == inPointer->parent->num) {
2366 inPointer->block = inPointer->parent->last;
2367 inPointer->index = inPointer->block->num - 1;
2368 } else {
2369 if (--(inPointer->index) < 0) {
2370 inPointer->block = inPointer->block->last; /* This should not be NULL */
2371 inPointer->index = inPointer->block->num - 1;
2372 }
2373 }
2374 }
2375 inPointer->removed = 0;
2376 return 1;
2377 }
2378
2379 /* --------------------------------------
2380 ��� MDPointerCurrent
2381 -------------------------------------- */
2382 MDEvent *
2383 MDPointerCurrent(const MDPointer *inPointer)
2384 {
2385 if (inPointer->parent == NULL ||
2386 (inPointer->position < 0 || inPointer->position >= inPointer->parent->num)) {
2387 return NULL;
2388 } else {
2389 return inPointer->block->events + inPointer->index;
2390 }
2391 }
2392
2393 /* --------------------------------------
2394 ��� MDPointerForward
2395 -------------------------------------- */
2396 MDEvent *
2397 MDPointerForward(MDPointer *inPointer)
2398 {
2399 if (MDPointerNextPos(inPointer)) {
2400 return MDPointerCurrent(inPointer);
2401 } else return NULL;
2402 }
2403
2404 /* --------------------------------------
2405 ��� MDPointerBackward
2406 -------------------------------------- */
2407 MDEvent *
2408 MDPointerBackward(MDPointer *inPointer)
2409 {
2410 if (MDPointerPreviousPos(inPointer)) {
2411 return MDPointerCurrent(inPointer);
2412 } else return NULL;
2413 }
2414
2415 /* --------------------------------------
2416 ��� MDPointerForwardWithSelector
2417 -------------------------------------- */
2418 MDEvent *
2419 MDPointerForwardWithSelector(MDPointer *inPointer, MDEventSelector inSelector, void *inUserData)
2420 {
2421 MDEvent *ep;
2422 int32_t position;
2423 while ((ep = MDPointerForward(inPointer)) != NULL) {
2424 position = MDPointerGetPosition(inPointer);
2425 if ((*inSelector)(ep, position, inUserData))
2426 return ep;
2427 }
2428 return NULL;
2429 }
2430
2431 /* --------------------------------------
2432 ��� MDPointerBackwardWithSelector
2433 -------------------------------------- */
2434 MDEvent *
2435 MDPointerBackwardWithSelector(MDPointer *inPointer, MDEventSelector inSelector, void *inUserData)
2436 {
2437 MDEvent *ep;
2438 int32_t position;
2439 while ((ep = MDPointerBackward(inPointer)) != NULL) {
2440 position = MDPointerGetPosition(inPointer);
2441 if ((*inSelector)(ep, position, inUserData))
2442 return ep;
2443 }
2444 return NULL;
2445 }
2446
2447 /* --------------------------------------
2448 ��� MDPointerSetPositionWithPointSet
2449 -------------------------------------- */
2450 int
2451 MDPointerSetPositionWithPointSet(MDPointer *inPointer, IntGroup *inPointSet, int32_t offset, int *outIndex)
2452 {
2453 int32_t index, position, pos, len;
2454 if (inPointSet == NULL)
2455 return 0;
2456 index = position = 0;
2457 while ((len = IntGroupGetInterval(inPointSet, index)) >= 0) {
2458 if (offset - position < len) {
2459 pos = IntGroupGetStartPoint(inPointSet, index);
2460 if (outIndex != NULL)
2461 *outIndex = index;
2462 return MDPointerSetPosition(inPointer, pos + (offset - position));
2463 }
2464 position += len;
2465 index++;
2466 }
2467 if (index > 0)
2468 index--;
2469 if (outIndex != NULL)
2470 *outIndex = index;
2471 return MDPointerSetPosition(inPointer, position);
2472 }
2473
2474 /* --------------------------------------
2475 ��� MDPointerForwardWithPointSet
2476 -------------------------------------- */
2477 MDEvent *
2478 MDPointerForwardWithPointSet(MDPointer *inPointer, IntGroup *inPointSet, int *index)
2479 {
2480 int32_t pt;
2481 int n;
2482 if (index == NULL) {
2483 n = -1;
2484 index = &n;
2485 }
2486 if (!MDPointerNextPos(inPointer)) {
2487 /* No more event */
2488 *index = -1;
2489 return NULL;
2490 }
2491 if (*index >= 0) {
2492 if ((pt = IntGroupGetEndPoint(inPointSet, *index)) >= 0) {
2493 if (inPointer->position >= pt) {
2494 (*index)++;
2495 pt = IntGroupGetStartPoint(inPointSet, *index);
2496 if (pt < 0)
2497 goto end_of_pset;
2498 MDPointerSetRelativePosition(inPointer, pt - inPointer->position);
2499 }
2500 return MDPointerCurrent(inPointer);
2501 } else goto end_of_pset; /* This should not happen */
2502 } else {
2503 if (!IntGroupLookup(inPointSet, inPointer->position, index)) {
2504 pt = IntGroupGetStartPoint(inPointSet, *index);
2505 if (pt < 0)
2506 goto end_of_pset;
2507 MDPointerSetRelativePosition(inPointer, pt - inPointer->position);
2508 }
2509 return MDPointerCurrent(inPointer);
2510 }
2511 end_of_pset:
2512 /* No more point in pointSet */
2513 MDPointerSetPosition(inPointer, inPointer->parent->num);
2514 return NULL;
2515 }
2516
2517 /* --------------------------------------
2518 ��� MDPointerBackwardWithPointSet
2519 -------------------------------------- */
2520 MDEvent *
2521 MDPointerBackwardWithPointSet(MDPointer *inPointer, IntGroup *inPointSet, int *index)
2522 {
2523 int32_t pt;
2524 int n;
2525 if (index == NULL) {
2526 n = -1;
2527 index = &n;
2528 }
2529 if (!MDPointerPreviousPos(inPointer)) {
2530 *index = -1;
2531 return NULL;
2532 }
2533 if (*index >= 0) {
2534 if ((pt = IntGroupGetStartPoint(inPointSet, *index)) >= 0) {
2535 if (inPointer->position < pt) {
2536 (*index)--;
2537 pt = IntGroupGetEndPoint(inPointSet, *index);
2538 if (pt < 0)
2539 goto pset_exhausted;
2540 MDPointerSetRelativePosition(inPointer, (pt - 1) - inPointer->position);
2541 }
2542 return MDPointerCurrent(inPointer);
2543 } else goto pset_exhausted; /* This should not happen */
2544 } else {
2545 if (!IntGroupLookup(inPointSet, inPointer->position, index)) {
2546 (*index)--;
2547 pt = IntGroupGetEndPoint(inPointSet, *index);
2548 if (pt < 0)
2549 goto pset_exhausted;
2550 MDPointerSetRelativePosition(inPointer, (pt - 1) - inPointer->position);
2551 }
2552 return MDPointerCurrent(inPointer);
2553 }
2554 pset_exhausted:
2555 MDPointerSetPosition(inPointer, -1);
2556 return NULL;
2557 }
2558
2559 /* --------------------------------------
2560 ��� MDPointerInsertAnEvent
2561 -------------------------------------- */
2562 MDStatus
2563 MDPointerInsertAnEvent(MDPointer *inPointer, const MDEvent *inEvent)
2564 {
2565 MDEvent *ep1, *ep2;
2566 MDTickType tick, ptick, tick1, tick2;
2567 MDStatus sts = kMDNoError;
2568 MDTrack *track;
2569
2570 if (inPointer == NULL)
2571 return kMDNoError;
2572 track = MDPointerGetTrack(inPointer);
2573
2574 /* Check whether the pointer is in the correct position */
2575 ep1 = MDPointerBackward(inPointer);
2576 ep2 = MDPointerForward(inPointer);
2577 tick1 = (ep1 == NULL ? kMDNegativeTick : MDGetTick(ep1));
2578 tick2 = (ep2 == NULL ? kMDMaxTick : MDGetTick(ep2));
2579 tick = MDGetTick(inEvent);
2580 if (tick1 > tick || tick > tick2)
2581 MDPointerJumpToTick(inPointer, tick);
2582
2583 /* Insert the event */
2584 if (MDTrackInsertBlanks(inPointer->parent, inPointer, 1) == 1) {
2585 ep1 = MDPointerCurrent(inPointer);
2586 MDEventCopy(ep1, inEvent, 1);
2587 if (MDHasDuration(ep1))
2588 ptick = MDGetTick(ep1) + MDGetDuration(ep1);
2589 else ptick = kMDNegativeTick;
2590 /* Update nch[] fields */
2591 if (MDIsChannelEvent(ep1))
2592 track->nch[MDGetChannel(ep1) & 15]++;
2593 else if (MDIsSysexEvent(ep1))
2594 track->nch[16]++;
2595 else track->nch[17]++;
2596 } else sts = kMDErrorOutOfMemory;
2597
2598 /* Update track duration if necessary */
2599 if (sts == kMDNoError) {
2600 tick1 = (ptick > tick ? ptick : tick);
2601 if (tick1 >= MDTrackGetDuration(track))
2602 MDTrackSetDuration(track, tick1 + 1);
2603 }
2604
2605 return sts;
2606 }
2607
2608 /* --------------------------------------
2609 ��� MDPointerDeleteAnEvent
2610 -------------------------------------- */
2611 MDStatus
2612 MDPointerDeleteAnEvent(MDPointer *inPointer, MDEvent *outEvent)
2613 {
2614 MDEvent *ep1;
2615 MDTrack *track;
2616
2617 if (inPointer == NULL || (ep1 = MDPointerCurrent(inPointer)) == NULL)
2618 return kMDNoError;
2619 track = MDPointerGetTrack(inPointer);
2620
2621 if (outEvent != NULL)
2622 MDEventCopy(outEvent, ep1, 1);
2623 if (MDIsChannelEvent(ep1))
2624 track->nch[MDGetChannel(ep1) & 15]--;
2625 else if (MDIsSysexEvent(ep1))
2626 track->nch[16]--;
2627 else track->nch[17]--;
2628 MDTrackDeleteEvents(inPointer->parent, inPointer, 1);
2629 return kMDNoError;
2630 }
2631
2632 /* --------------------------------------
2633 ��� MDPointerReplaceAnEvent
2634 -------------------------------------- */
2635 MDStatus
2636 MDPointerReplaceAnEvent(MDPointer *inPointer, const MDEvent *inEvent, MDEvent *outEvent)
2637 {
2638 MDEvent *ep;
2639 MDTrack *track;
2640 MDTickType oldTick;
2641 int oldHasDuration;
2642 if (inPointer == NULL || (ep = MDPointerCurrent(inPointer)) == NULL)
2643 return kMDNoError;
2644 track = MDPointerGetTrack(inPointer);
2645 oldHasDuration = MDHasDuration(ep);
2646 if (outEvent != NULL)
2647 MDEventCopy(outEvent, ep, 1);
2648 if (MDIsChannelEvent(ep))
2649 track->nch[MDGetChannel(ep) & 15]--;
2650 else if (MDIsSysexEvent(ep))
2651 track->nch[16]--;
2652 else track->nch[17]--;
2653 oldTick = MDGetTick(ep);
2654 MDEventCopy(ep, inEvent, 1);
2655 MDSetTick(ep, oldTick);
2656 if (MDIsChannelEvent(ep))
2657 track->nch[MDGetChannel(ep) & 15]++;
2658 else if (MDIsSysexEvent(ep))
2659 track->nch[16]++;
2660 else track->nch[17]++;
2661 if (oldTick != MDGetTick(inEvent))
2662 return MDPointerChangeTick(inPointer, MDGetTick(inEvent), -1);
2663 else if (MDHasDuration(inEvent) || oldHasDuration) {
2664 if (MDHasDuration(inEvent)) {
2665 MDTickType tick1 = MDGetTick(inEvent) + MDGetDuration(inEvent);
2666 if (tick1 >= MDTrackGetDuration(track))
2667 MDTrackSetDuration(track, tick1 + 1);
2668 }
2669 inPointer->block->largestTick = kMDNegativeTick;
2670 }
2671 return kMDNoError;
2672 }
2673
2674 /* --------------------------------------
2675 ��� MDPointerChangeTick
2676 -------------------------------------- */
2677 MDStatus
2678 MDPointerChangeTick(MDPointer *inPointer, MDTickType inTick, int32_t inPosition)
2679 {
2680 MDTrack *track;
2681 MDEvent *ep, *ep1;
2682 MDTickType tick, tick_last, tick_next;
2683 MDPointer *newPointer = NULL;
2684 MDStatus sts = kMDNoError;
2685 int oldAdjustFlag;
2686
2687 if (inPointer == NULL || (ep = MDPointerCurrent(inPointer)) == NULL)
2688 return kMDNoError;
2689
2690 tick = MDGetTick(ep);
2691 if (tick == inTick)
2692 return kMDNoError;
2693
2694 track = MDPointerGetTrack(inPointer);
2695
2696 if (inPosition < 0) {
2697 /* Check whether in-place change is possible */
2698 tick_last = ((ep1 = MDPointerBackward(inPointer)) != NULL ? MDGetTick(ep1) : kMDNegativeTick);
2699 MDPointerForward(inPointer);
2700 tick_next = ((ep1 = MDPointerForward(inPointer)) != NULL ? MDGetTick(ep1) : kMDMaxTick);
2701 MDPointerBackward(inPointer);
2702 if (tick_last <= inTick && inTick <= tick_next) {
2703 MDSetTick(ep, inTick);
2704 inPointer->block->largestTick = kMDNegativeTick;
2705 MDTrackUpdateLargestTickForBlock(track, inPointer->block);
2706 goto exit;
2707 }
2708 }
2709
2710 /* Insert/delete is required */
2711 newPointer = MDPointerNew(track);
2712 if (newPointer == NULL)
2713 return kMDErrorOutOfMemory;
2714 if (inPosition >= 0) {
2715 MDPointerSetPosition(newPointer, inPosition + (inPosition >= MDPointerGetPosition(inPointer) ? 1 : 0));
2716 tick_last = ((ep1 = MDPointerBackward(newPointer)) != NULL ? MDGetTick(ep1) : kMDNegativeTick);
2717 MDPointerForward(newPointer);
2718 tick_next = ((ep1 = MDPointerForward(newPointer)) != NULL ? MDGetTick(ep1) : kMDMaxTick);
2719 MDPointerBackward(newPointer);
2720 }
2721 if (inPosition < 0 || tick_last > inTick || inTick > tick_next)
2722 MDPointerJumpToTick(newPointer, inTick);
2723
2724 if (MDPointerGetPosition(newPointer) == MDPointerGetPosition(inPointer)) {
2725 MDSetTick(ep, inTick);
2726 MDPointerRelease(newPointer);
2727 goto exit;
2728 }
2729
2730 oldAdjustFlag = MDPointerIsAutoAdjust(inPointer);
2731 MDPointerSetAutoAdjust(inPointer, 1);
2732 MDPointerSetAutoAdjust(newPointer, 1);
2733
2734 /* Insert a blank */
2735 if (MDTrackInsertBlanks(track, newPointer, 1) == 1) {
2736 ep1 = MDPointerCurrent(newPointer);
2737 ep = MDPointerCurrent(inPointer); /* May have moved while inserting a blank */
2738 MDEventMove(ep1, ep, 1);
2739 MDSetTick(ep1, inTick);
2740 /* Delete the previous position */
2741 MDTrackDeleteEvents(track, inPointer, 1);
2742 ep = MDPointerCurrent(newPointer); /* May have moved while deleting */
2743 } else sts = kMDErrorOutOfMemory;
2744
2745 MDPointerSetPosition(inPointer, MDPointerGetPosition(newPointer));
2746 MDPointerSetAutoAdjust(inPointer, oldAdjustFlag);
2747 MDPointerRelease(newPointer);
2748
2749 exit:
2750 /* Let the track duration greater than the last tick */
2751 if (sts == kMDNoError) {
2752 if (MDHasDuration(ep))
2753 inTick += MDGetDuration(ep);
2754 if (inTick >= MDTrackGetDuration(track))
2755 MDTrackSetDuration(track, inTick + 1);
2756 if (inPointer->block->largestTick >= 0 && inTick > inPointer->block->largestTick)
2757 inPointer->block->largestTick = inTick;
2758 }
2759 return sts;
2760 }
2761
2762 /* --------------------------------------
2763 ��� MDPointerSetDuration
2764 -------------------------------------- */
2765 MDStatus
2766 MDPointerSetDuration(MDPointer *inPointer, MDTickType inDuration)
2767 {
2768 MDEvent *ep;
2769 if (inPointer == NULL || (ep = MDPointerCurrent(inPointer)) == NULL)
2770 return kMDNoError;
2771
2772 /* We do not check here the validity of the event type */
2773 MDSetDuration(ep, inDuration);
2774
2775 /* Invalidate largestTick and request recalculation later */
2776 inPointer->block->largestTick = kMDNegativeTick;
2777
2778 return kMDNoError;
2779 }
2780
2781 /* --------------------------------------
2782 ��� MDPointerCheck
2783 -------------------------------------- */
2784 MDStatus
2785 MDPointerCheck(const MDPointer *inPointer)
2786 {
2787 MDTrack *track;
2788 MDBlock *block;
2789 int32_t pos;
2790 int err = 0;
2791 if (inPointer == NULL)
2792 return kMDNoError;
2793 track = inPointer->parent;
2794 if (track == NULL) {
2795 fprintf(stderr, "MDPointerCheck: track is NULL\n");
2796 err++;
2797 }
2798 pos = inPointer->position;
2799 if (pos == -1) {
2800 if (inPointer->block != NULL) {
2801 fprintf(stderr, "MDPointerCheck: position is -1 but block is not NULL\n");
2802 err++;
2803 }
2804 if (inPointer->index != -1) {
2805 fprintf(stderr, "MDPointerCheck: position is -1 but index is not -1\n");
2806 err++;
2807 }
2808 } else {
2809 block = track->first;
2810 if (block == NULL) {
2811 fprintf(stderr, "MDPointerCheck: position (%d) >= 0 but track has no data\n", pos);
2812 err++;
2813 } else if (inPointer->block == NULL) {
2814 fprintf(stderr, "MDPointerCheck: position (%d) >= 0 but block is NULL\n", pos);
2815 err++;
2816 } else {
2817 while (block != NULL && pos >= block->num) {
2818 if (pos == block->num && block->next == NULL)
2819 break;
2820 pos -= block->num;
2821 block = block->next;
2822 }
2823 if (block == NULL) {
2824 fprintf(stderr, "MDPointerCheck: block exhausts before position (%d)\n", (int)inPointer->position);
2825 err++;
2826 } else if (block != inPointer->block || pos != inPointer->index) {
2827 fprintf(stderr, "MDPointerCheck: position (%d) is index %d in block %p but inPointer claims index %d in block %p\n", (int)inPointer->position, (int)(pos), block, (int)inPointer->index, inPointer->block);
2828 err++;
2829 }
2830 }
2831 }
2832 return (err > 0 ? kMDErrorInternalError : kMDNoError);
2833 }
2834
2835 #if 0
2836 #pragma mark ====== MDTrackMerger functions ======
2837 #endif
2838
2839 /* --------------------------------------
2840 ��� MDTrackMergerNew
2841 -------------------------------------- */
2842 MDTrackMerger *
2843 MDTrackMergerNew(void)
2844 {
2845 MDTrackMerger *merger = (MDTrackMerger *)malloc(sizeof(MDTrackMerger));
2846 if (merger == NULL)
2847 return NULL; /* out of memory */
2848 memset(merger, 0, sizeof(MDTrackMerger));
2849 merger->refCount = 1;
2850 return merger;
2851 }
2852
2853 /* --------------------------------------
2854 ��� MDTrackMergerRetain
2855 -------------------------------------- */
2856 void
2857 MDTrackMergerRetain(MDTrackMerger *inMerger)
2858 {
2859 if (inMerger == NULL)
2860 return;
2861 inMerger->refCount++;
2862 }
2863
2864 /* --------------------------------------
2865 ��� MDTrackMergerRelease
2866 -------------------------------------- */
2867 void
2868 MDTrackMergerRelease(MDTrackMerger *inMerger)
2869 {
2870 if (inMerger == NULL)
2871 return;
2872 if (--(inMerger->refCount) == 0) {
2873 /* Deallocate */
2874 int i;
2875 if (inMerger->npointers > 0) {
2876 for (i = 0; i < inMerger->npointers; i++) {
2877 MDPointerRelease(inMerger->pointers[i]);
2878 }
2879 free(inMerger->pointers);
2880 }
2881 free(inMerger);
2882 }
2883 }
2884
2885 /* --------------------------------------
2886 ��� MDTrackMergerAddTrack
2887 -------------------------------------- */
2888 int
2889 MDTrackMergerAddTrack(MDTrackMerger *inMerger, MDTrack *inTrack)
2890 {
2891 MDPointer *pt;
2892 if (inMerger == NULL)
2893 return -1;
2894 if (inMerger->npointers % 8 == 0) {
2895 /* Expand the storage */
2896 MDPointer **pointers;
2897 if (inMerger->npointers == 0)
2898 pointers = (MDPointer **)malloc(sizeof(MDPointer *) * 8);
2899 else
2900 pointers = (MDPointer **)realloc(inMerger->pointers, sizeof(MDPointer *) * (inMerger->npointers + 8));
2901 if (pointers == NULL)
2902 return -1;
2903 memset(pointers + inMerger->npointers, 0, 8 * sizeof(MDPointer *));
2904 inMerger->pointers = pointers;
2905 }
2906 pt = MDPointerNew(inTrack);
2907 if (pt == NULL)
2908 return -1;
2909 MDPointerSetPosition(pt, 0);
2910 inMerger->pointers[inMerger->npointers++] = pt;
2911 return inMerger->npointers;
2912 }
2913
2914 /* --------------------------------------
2915 ��� MDTrackMergerRemoveTrack
2916 -------------------------------------- */
2917 int
2918 MDTrackMergerRemoveTrack(MDTrackMerger *inMerger, MDTrack *inTrack)
2919 {
2920 int i;
2921 if (inMerger == NULL)
2922 return -1;
2923 for (i = inMerger->npointers - 1; i >= 0; i--) {
2924 if (MDPointerGetTrack(inMerger->pointers[i]) == inTrack) {
2925 /* Remove this track */
2926 MDPointerRelease(inMerger->pointers[i]);
2927 memmove(inMerger->pointers + i, inMerger->pointers + (i + 1), sizeof(MDPointer *) * (inMerger->npointers - (i + 1)));
2928 inMerger->npointers--;
2929 if (inMerger->npointers > 0 && inMerger->idx >= inMerger->npointers)
2930 inMerger->idx--;
2931 return inMerger->npointers;
2932 }
2933 }
2934 /* Not found */
2935 return -1;
2936 }
2937
2938 /* --------------------------------------
2939 ��� MDTrackMergerGetTrack
2940 -------------------------------------- */
2941 MDTrack *
2942 MDTrackMergerGetTrack(MDTrackMerger *inMerger, int num)
2943 {
2944 if (inMerger == NULL || num < 0 || num >= inMerger->npointers)
2945 return NULL;
2946 return MDPointerGetTrack(inMerger->pointers[num]);
2947 }
2948
2949 /* --------------------------------------
2950 ��� MDTrackMergerJumpToTick
2951 -------------------------------------- */
2952 MDEvent *
2953 MDTrackMergerJumpToTick(MDTrackMerger *inMerger, MDTickType inTick, MDTrack **outTrack)
2954 {
2955 int i, n, idx;
2956 MDEvent *ep;
2957 MDTrack *tr;
2958 if (inMerger == NULL)
2959 return NULL;
2960 ep = NULL;
2961 tr = NULL;
2962 n = idx = inMerger->idx;
2963 for (i = 0; i < inMerger->npointers; i++) {
2964 MDPointer *pt = inMerger->pointers[n];
2965 if (MDPointerJumpToTick(pt, inTick)) {
2966 MDEvent *ep1 = MDPointerCurrent(pt);
2967 if (ep1 != NULL) {
2968 if (ep == NULL || MDGetTick(ep) > MDGetTick(ep1)) {
2969 ep = ep1;
2970 tr = MDPointerGetTrack(pt);
2971 idx = n;
2972 }
2973 }
2974 }
2975 if (++n == inMerger->npointers)
2976 n = 0;
2977 }
2978 inMerger->idx = idx;
2979 if (outTrack != NULL)
2980 *outTrack = tr;
2981 return ep;
2982 }
2983
2984 /* --------------------------------------
2985 ��� MDTrackMergerCurrent
2986 -------------------------------------- */
2987 MDEvent *
2988 MDTrackMergerCurrent(MDTrackMerger *inMerger, MDTrack **outTrack)
2989 {
2990 int i, idx;
2991 MDEvent *ep;
2992 MDTrack *tr;
2993 if (inMerger == NULL)
2994 return NULL;
2995 ep = NULL;
2996 tr = NULL;
2997 idx = inMerger->idx;
2998 for (i = 0; i < inMerger->npointers; i++) {
2999 MDPointer *pt = inMerger->pointers[i];
3000 MDEvent *ep1 = MDPointerCurrent(pt);
3001 if (ep1 != NULL) {
3002 if (ep == NULL || MDGetTick(ep) > MDGetTick(ep1)) {
3003 ep = ep1;
3004 tr = MDPointerGetTrack(pt);
3005 idx = i;
3006 }
3007 }
3008 }
3009 inMerger->idx = idx;
3010 if (outTrack != NULL)
3011 *outTrack = tr;
3012 return ep;
3013 }
3014
3015 /* --------------------------------------
3016 ��� MDTrackMergerForward
3017 -------------------------------------- */
3018 MDEvent *
3019 MDTrackMergerForward(MDTrackMerger *inMerger, MDTrack **outTrack)
3020 {
3021 if (inMerger != NULL && inMerger->npointers > 0 && inMerger->idx < inMerger->npointers) {
3022 MDPointerForward(inMerger->pointers[inMerger->idx]);
3023 return MDTrackMergerCurrent(inMerger, outTrack);
3024 }
3025 return NULL;
3026 }
3027
3028 /* --------------------------------------
3029 ��� MDTrackMergerBackward
3030 -------------------------------------- */
3031 MDEvent *
3032 MDTrackMergerBackward(MDTrackMerger *inMerger, MDTrack **outTrack)
3033 {
3034 int i, idx;
3035 MDEvent *ep;
3036 MDTrack *tr;
3037 if (inMerger == NULL || inMerger->npointers <= 0 || inMerger->idx >= inMerger->npointers)
3038 return NULL;
3039 ep = NULL;
3040 tr = NULL;
3041 idx = inMerger->idx;
3042 for (i = inMerger->npointers - 1; i >= 0; i--) {
3043 MDPointer *pt = inMerger->pointers[i];
3044 MDEvent *ep1;
3045 if (inMerger->idx == i || MDPointerGetPosition(pt) >= MDTrackGetNumberOfEvents(MDPointerGetTrack(pt))) {
3046 MDPointerBackward(pt);
3047 }
3048 ep1 = MDPointerCurrent(pt);
3049 if (ep1 != NULL) {
3050 if (ep == NULL || MDGetTick(ep) < MDGetTick(ep1)) {
3051 ep = ep1;
3052 tr = MDPointerGetTrack(pt);
3053 idx = i;
3054 }
3055 }
3056 }
3057 inMerger->idx = idx;
3058 if (outTrack != NULL)
3059 *outTrack = tr;
3060 return ep;
3061 }

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