Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/Ruby_bindings/MDRubyPointer.m

Parent Directory Parent Directory | Revision Log Revision Log


Revision 146 - (show annotations) (download)
Sun Dec 17 04:05:28 2017 UTC (6 years, 5 months ago) by toshinagata1964
File size: 34934 byte(s)
Xcode project is updated so that ppc/i386 universal binary can be built (as before)
1 //
2 // MDRubyPointer.m
3 // Alchemusica
4 //
5 // Created by Toshi Nagata on 08/03/30.
6 // Copyright 2008-2017 Toshi Nagata. All rights reserved.
7 //
8 /*
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation version 2 of the License.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17 */
18
19 #import "MyDocument.h"
20 #import "MyMIDISequence.h"
21 #import "MDObjects.h"
22
23 #include "MDRuby.h"
24
25 // Pointer class
26 VALUE rb_cMRPointer = Qfalse;
27
28 #pragma mark ====== Event kind symbols ======
29
30 static struct {
31 const char *name;
32 int kind;
33 int code;
34 VALUE sym;
35 } sMREventNameTable[] = {
36 { "null", kMDEventNull, 0, 0 },
37 { "meta", kMDEventMeta, 0, 0 },
38 { "tempo", kMDEventTempo, 0, 0 },
39 { "time_signature", kMDEventTimeSignature, 0, 0 },
40 { "key", kMDEventKey, 0, 0 },
41 { "smpte", kMDEventSMPTE, 0, 0 },
42 { "port", kMDEventPortNumber, 0, 0 },
43 { "text", kMDEventMetaText, 0, 0 },
44 { "copyright", kMDEventMetaText, kMDMetaCopyright, 0 },
45 { "sequence", kMDEventMetaText, kMDMetaSequenceName, 0 },
46 { "instrument", kMDEventMetaText, kMDMetaInstrumentName, 0 },
47 { "lyric", kMDEventMetaText, kMDMetaLyric, 0 },
48 { "marker", kMDEventMetaText, kMDMetaMarker, 0 },
49 { "cue", kMDEventMetaText, kMDMetaCuePoint, 0 },
50 { "progname", kMDEventMetaText, kMDMetaProgramName, 0 },
51 { "devname", kMDEventMetaText, kMDMetaDeviceName, 0 },
52 { "message", kMDEventMetaMessage, 0, 0 },
53 { "program", kMDEventProgram, 0, 0 },
54 { "note", kMDEventNote, 0, 0 },
55 { "control", kMDEventControl, 0, 0 },
56 { "bank_high", kMDEventControl, 0, 0 },
57 { "modulation", kMDEventControl, 1, 0 },
58 { "portament_time", kMDEventControl, 5, 0 },
59 { "data_entry", kMDEventControl, 6, 0 },
60 { "volume", kMDEventControl, 7, 0 },
61 { "pan", kMDEventControl, 10, 0 },
62 { "expression", kMDEventControl, 11, 0 },
63 { "bank_low", kMDEventControl, 32, 0 },
64 { "hold", kMDEventControl, 64, 0 },
65 { "portamento", kMDEventControl, 65, 0 },
66 { "sostenuto", kMDEventControl, 66, 0 },
67 { "soft", kMDEventControl, 67, 0 },
68 { "resonance", kMDEventControl, 71, 0 },
69 { "release", kMDEventControl, 72, 0 },
70 { "attack", kMDEventControl, 73, 0 },
71 { "cutoff", kMDEventControl, 74, 0 },
72 { "portament_cont", kMDEventControl, 84, 0 },
73 { "reverb", kMDEventControl, 91, 0 },
74 { "chorus", kMDEventControl, 93, 0 },
75 { "var_effect", kMDEventControl, 94, 0 },
76 { "data_inc", kMDEventControl, 96, 0 },
77 { "data_dec", kMDEventControl, 97, 0 },
78 { "nrpn_low", kMDEventControl, 98, 0 },
79 { "nrpn_high", kMDEventControl, 99, 0 },
80 { "rpn_low", kMDEventControl, 100, 0 },
81 { "rpn_high", kMDEventControl, 101, 0 },
82 { "all_sounds_off", kMDEventControl, 120, 0 },
83 { "reset_all_controllers", kMDEventControl, 121, 0 },
84 { "all_notes_off", kMDEventControl, 123, 0 },
85 { "omni_off", kMDEventControl, 124, 0 },
86 { "omni_on", kMDEventControl, 125, 0 },
87 { "mono", kMDEventControl, 126, 0 },
88 { "poly", kMDEventControl, 127, 0 },
89 { "pitch_bend", kMDEventPitchBend, 0, 0 },
90 { "channel_pressure", kMDEventChanPres, 0, 0 },
91 { "key_pressure", kMDEventKeyPres, 0, 0 },
92 { "sysex", kMDEventSysex, 0, 0 },
93 { "sysex_cont", kMDEventSysexCont, 0, 0 },
94 { NULL }
95 };
96
97 static VALUE sNoteSymbol;
98
99 static const int sMREventNameTableCount = sizeof(sMREventNameTable) / sizeof(sMREventNameTable[0]) - 1;
100 static BOOL sMREventNameTableInitialized = NO;
101
102 static void
103 s_MREventNameTableInitialize(void)
104 {
105 int i;
106 for (i = 0; i < sMREventNameTableCount; i++) {
107 sMREventNameTable[i].sym = ID2SYM(rb_intern(sMREventNameTable[i].name));
108 if (sMREventNameTable[i].kind == kMDEventNote)
109 sNoteSymbol = sMREventNameTable[i].sym;
110 }
111 sMREventNameTableInitialized = YES;
112 }
113
114 VALUE
115 MREventSymbolFromEventKindAndCode(int kind, int code, int *is_generic)
116 {
117 int i, j, f = 0;
118 if (!sMREventNameTableInitialized)
119 s_MREventNameTableInitialize();
120 if (kind == kMDEventNote && code >= 0) {
121 char notename[6], buf[12];
122 code = (unsigned char)code;
123 MDEventNoteNumberToNoteName((unsigned char)code, notename);
124 snprintf(buf, sizeof buf, "%s(%d)", notename, code);
125 if (is_generic != NULL)
126 *is_generic = 1;
127 return rb_str_new2(buf);
128 }
129 for (i = 0; i < sMREventNameTableCount; i++) {
130 if (kind == sMREventNameTable[i].kind) {
131 if ((kind == kMDEventMetaText || kind == kMDEventControl) && code >= 0) {
132 for (j = i + 1; j < sMREventNameTableCount; j++) {
133 if (sMREventNameTable[j].kind != kind)
134 break;
135 if (sMREventNameTable[j].code == code) {
136 f = 1;
137 i = j;
138 break;
139 }
140 }
141 }
142 if (is_generic != NULL)
143 *is_generic = f;
144 return sMREventNameTable[i].sym;
145 }
146 }
147 return 0;
148 }
149
150 int
151 MREventKindAndCodeFromEventSymbol(VALUE sym, int *code, int *is_generic)
152 {
153 int i, c, kind, f = 0;
154 int symtype;
155
156 if (!sMREventNameTableInitialized)
157 s_MREventNameTableInitialize();
158 symtype = TYPE(sym);
159 if (FIXNUM_P(sym) || symtype == T_STRING) {
160 /* May be a note event */
161 c = -1;
162 if (symtype == T_STRING)
163 c = MDEventNoteNameToNoteNumber(StringValuePtr(sym));
164 else
165 c = FIX2INT(sym);
166 if (c >= 0 && c < 128) {
167 if (code != NULL)
168 *code = c;
169 if (is_generic != NULL)
170 *is_generic = 0;
171 return kMDEventNote;
172 }
173 }
174
175 if (symtype != T_SYMBOL) {
176 sym = ID2SYM(rb_intern(StringValuePtr(sym)));
177 }
178 for (i = 0; i < sMREventNameTableCount; i++) {
179 if (sym == sMREventNameTable[i].sym) {
180 kind = sMREventNameTable[i].kind;
181 c = sMREventNameTable[i].code;
182 if (kind == kMDEventMetaText || kind == kMDEventControl) {
183 if (c == 0 && sMREventNameTable[i - 1].kind != kind)
184 f = 1;
185 }
186 if (is_generic != NULL)
187 *is_generic = f;
188 if (code != NULL)
189 *code = c;
190 return sMREventNameTable[i].kind;
191 }
192 }
193 return -1;
194 }
195
196 #pragma mark ====== Pointer alloc/init/release ======
197
198 static MRPointerInfo *
199 s_MRPointerInfoFromValue(VALUE val)
200 {
201 MRPointerInfo *ip;
202 if (rb_obj_is_kind_of(val, rb_cMRPointer)) {
203 Data_Get_Struct(val, MRPointerInfo, ip);
204 return ip;
205 }
206 rb_raise(rb_eTypeError, "Cannot get Pointer information from object");
207 }
208
209 static void
210 s_MRPointer_Release(void *p)
211 {
212 MRPointerInfo *ip = (MRPointerInfo *)p;
213 if (ip->pointer != NULL) {
214 MDPointerRelease(ip->pointer);
215 ip->pointer = NULL;
216 }
217 [MyDocument unregisterDocumentTrackInfo: &(ip->trackInfo)];
218 free(ip);
219 }
220
221 static VALUE
222 s_MRPointer_Alloc(VALUE klass)
223 {
224 MRPointerInfo *ip = ALLOC(MRPointerInfo);
225 memset(ip, 0, sizeof(MRPointerInfo));
226 [MyDocument registerDocumentTrackInfo: &(ip->trackInfo)];
227 return Data_Wrap_Struct(klass, 0, s_MRPointer_Release, ip);
228 }
229
230 void
231 s_MRPointer_InitWithTrackInfo(VALUE val, MDTrack *track, MyDocument *doc, int num, int position)
232 {
233 MRPointerInfo *ip;
234 Data_Get_Struct(val, MRPointerInfo, ip);
235 ip->trackInfo.doc = doc;
236 ip->trackInfo.track = track;
237 if (num < 0 && doc != nil)
238 ip->trackInfo.num = [[doc myMIDISequence] lookUpTrack: track];
239 else ip->trackInfo.num = num;
240 ip->pointer = MDPointerNew(track);
241 if (position >= 0)
242 MDPointerSetPosition(ip->pointer, position);
243 }
244
245 /*
246 * call-seq:
247 * Pointer.new
248 * Pointer.new(doc, n)
249 * Pointer.new(track)
250 *
251 * Creates a new Pointer object.
252 */
253 static VALUE
254 s_MRPointer_Initialize(int argc, VALUE *argv, VALUE self)
255 {
256 VALUE val1, val2, val3;
257 MyDocument *doc = nil;
258 MDTrack *track;
259 int num = -1, position = -1;
260 rb_scan_args(argc, argv, "03", &val1, &val2, &val3);
261 if (NIL_P(val1)) {
262 track = MDTrackNew();
263 } else if (rb_obj_is_kind_of(val1, rb_cMRTrack)) {
264 MyDocumentTrackInfo *trackInfoPtr = TrackInfoFromMRTrackValue(val1);
265 doc = trackInfoPtr->doc;
266 track = trackInfoPtr->track;
267 num = trackInfoPtr->num;
268 val3 = val2;
269 } else if (rb_obj_is_kind_of(val1, rb_cMRSequence)) {
270 doc = MyDocumentFromMRSequenceValue(val1);
271 num = NUM2INT(rb_Integer(val2));
272 if (num < 0 || num >= [[doc myMIDISequence] trackCount])
273 rb_raise(rb_eRangeError, "track count (%d) out of range", num);
274 track = [[doc myMIDISequence] getTrackAtIndex: num]; // Not retained
275 } else {
276 rb_raise(rb_eTypeError, "invalid argument; the first argument must be either Sequence or Track");
277 }
278 if (val3 != Qnil)
279 position = NUM2INT(rb_Integer(val3));
280 s_MRPointer_InitWithTrackInfo(self, track, doc, num, position);
281 return Qnil;
282 }
283
284 static VALUE
285 s_MRPointer_InitializeCopy(VALUE self, VALUE val)
286 {
287 MRPointerInfo *ip, *ip2;
288 Data_Get_Struct(self, MRPointerInfo, ip);
289 if (!rb_obj_is_kind_of(val, rb_cMRPointer))
290 rb_raise(rb_eTypeError, "Pointer instance is expected");
291 Data_Get_Struct(val, MRPointerInfo, ip2);
292 ip->trackInfo = ip2->trackInfo;
293 ip->pointer = MDPointerNew(ip->trackInfo.track);
294 if (ip->pointer == NULL)
295 rb_raise(rb_eNoMemError, "out of memory while duplicating an Pointer object");
296 MDPointerCopy(ip->pointer, ip2->pointer);
297 return self;
298 }
299
300 MDPointer *
301 MDPointerFromMRPointerValue(VALUE val)
302 {
303 MRPointerInfo *ip;
304 if (rb_obj_is_kind_of(val, rb_cMRPointer)) {
305 Data_Get_Struct(val, MRPointerInfo, ip);
306 if (ip->pointer != NULL)
307 return ip->pointer;
308 }
309 rb_raise(rb_eTypeError, "Cannot get MDPointer from object");
310 }
311
312 VALUE
313 MRPointerValueFromTrackInfo(MDTrack *track, MyDocument *doc, int num, int position)
314 {
315 VALUE val = s_MRPointer_Alloc(rb_cMRPointer);
316 s_MRPointer_InitWithTrackInfo(val, track, doc, num, position);
317 return val;
318 }
319
320 #pragma mark ====== Ruby methods ======
321
322 /*
323 * call-seq:
324 * pointer.position=(n)
325 * pointer.moveto(n)
326 *
327 * Set the current position. The method "moveto" returns true if the resulting pointer
328 * points to an event, otherwise returns false. The method "position=" always returns
329 * 'n'; this is the feature of Ruby.
330 */
331 static VALUE
332 s_MRPointer_SetPosition(VALUE self, VALUE val)
333 {
334 MDPointer *pt = MDPointerFromMRPointerValue(self);
335 int position = NUM2INT(val);
336 if (MDPointerSetPosition(pt, position))
337 return Qtrue;
338 else return Qfalse;
339 }
340
341 /*
342 * call-seq:
343 * pointer.position
344 * pointer.position(n)
345 *
346 * No argument: get the current position. With argument: set the current position;
347 * returns true if the resulting pointer points to an event, otherwise returns false.
348 */
349 static VALUE
350 s_MRPointer_Position(int argc, VALUE *argv, VALUE self)
351 {
352 VALUE val;
353 int position;
354 MDPointer *pt = MDPointerFromMRPointerValue(self);
355 rb_scan_args(argc, argv, "01", &val);
356 if (val == Qnil) {
357 position = MDPointerGetPosition(pt);
358 return INT2NUM(position);
359 } else {
360 return s_MRPointer_SetPosition(self, val);
361 }
362 }
363
364 /*
365 * call-seq:
366 * pointer.moveby(n)
367 *
368 * Move the pointer by n. Returns true if the resulting pointer points to an event,
369 * otherwise returns false.
370 */
371 static VALUE
372 s_MRPointer_MoveBy(VALUE self, VALUE val)
373 {
374 MDPointer *pt = MDPointerFromMRPointerValue(self);
375 int n = NUM2INT(val);
376 if (MDPointerSetRelativePosition(pt, n))
377 return Qtrue;
378 else return Qfalse;
379 }
380
381 /*
382 * call-seq:
383 * pointer.track
384 *
385 * Get the parent track as an Track object.
386 */
387 static VALUE
388 s_MRPointer_Track(VALUE self)
389 {
390 MRPointerInfo *ip = s_MRPointerInfoFromValue(self);
391 MyDocumentTrackInfo *tip = &ip->trackInfo;
392 return MRTrackValueFromTrackInfo(tip->track, tip->doc, tip->num);
393 }
394
395 /*
396 * call-seq:
397 * pointer.top
398 *
399 * Move to the top of the track.
400 */
401 VALUE
402 MRPointer_Top(VALUE self)
403 {
404 return s_MRPointer_SetPosition(self, INT2NUM(-1));
405 }
406
407 /*
408 * call-seq:
409 * pointer.bottom
410 *
411 * Move to the bottom of the track.
412 */
413 VALUE
414 MRPointer_Bottom(VALUE self)
415 {
416 return s_MRPointer_SetPosition(self, INT2NUM(0x3fffffff));
417 }
418
419 /*
420 * call-seq:
421 * pointer.next
422 *
423 * Move forward. If the pointer goes over the end of track, returns false;
424 * otherwise returns true.
425 */
426 VALUE
427 MRPointer_Next(VALUE self)
428 {
429 MDPointer *pt = MDPointerFromMRPointerValue(self);
430 if (MDPointerForward(pt) == NULL) {
431 return Qfalse;
432 } else return Qtrue;
433 }
434
435 /*
436 * call-seq:
437 * pointer.last
438 *
439 * Move backward. If the pointer goes over the beginning of track, returns false;
440 * otherwise returns true.
441 */
442 VALUE
443 MRPointer_Last(VALUE self)
444 {
445 MDPointer *pt = MDPointerFromMRPointerValue(self);
446 if (MDPointerBackward(pt) == NULL) {
447 return Qfalse;
448 } else return Qtrue;
449 }
450
451 /*
452 * call-seq:
453 * pointer.next_in_selection
454 *
455 * Move forward within the selection. If no more event is present within selection, the pointer
456 * is set to the end of track and returns false; otherwise returns true.
457 */
458 VALUE
459 MRPointer_NextInSelection(VALUE self)
460 {
461 MRPointerInfo *ip = s_MRPointerInfoFromValue(self);
462 MDPointer *pt = ip->pointer;
463 IntGroup *pset = [[ip->trackInfo.doc selectionOfTrack: ip->trackInfo.num] pointSet];
464 if (MDPointerForwardWithPointSet(pt, pset, NULL) == NULL) {
465 return Qfalse;
466 } else return Qtrue;
467 }
468
469 /*
470 * call-seq:
471 * pointer.last_in_selection
472 *
473 * Move backward within the selection. If no more event is present within selection, the pointer
474 * is set to the top of track and returns false; otherwise returns true.
475 */
476 VALUE
477 MRPointer_LastInSelection(VALUE self)
478 {
479 MRPointerInfo *ip = s_MRPointerInfoFromValue(self);
480 MDPointer *pt = ip->pointer;
481 IntGroup *pset = [[ip->trackInfo.doc selectionOfTrack: ip->trackInfo.num] pointSet];
482 if (MDPointerBackwardWithPointSet(pt, pset, NULL) == NULL) {
483 return Qfalse;
484 } else return Qtrue;
485 }
486
487 /*
488 * call-seq:
489 * pointer.jump_to_tick(tick)
490 *
491 * Move to the first event having the tick not smaller than the given value.
492 * If such an event does not exist, the pointer is moved to the bottom and
493 * returns false. Otherwise returns true.
494 */
495 static VALUE
496 s_MRPointer_JumpToTick(VALUE self, VALUE val)
497 {
498 MDPointer *pt = MDPointerFromMRPointerValue(self);
499 MDTickType tick = (MDTickType)floor(NUM2DBL(val) + 0.5);
500 if (MDPointerJumpToTick(pt, tick))
501 return Qtrue;
502 else return Qfalse;
503 }
504
505 static void
506 s_MRPointer_OutOfBoundsError(MDPointer *pt)
507 {
508 static const char *msg = "the pointer points outside the track";
509 if (pt != NULL)
510 rb_raise(rb_eStandardError, "%s (position = %d)", msg, (int)MDPointerGetPosition(pt));
511 else
512 rb_raise(rb_eStandardError, "%s", msg);
513 }
514
515 static void
516 s_MRPointer_BadKindError(MDPointer *pt)
517 {
518 char buf[64];
519 MDEvent *ep;
520 if (pt != NULL && (ep = MDPointerCurrent(pt)) != NULL)
521 MDEventToKindString(ep, buf, sizeof buf);
522 else buf[0] = 0;
523 rb_raise(rb_eStandardError, "event kind (%s) not suitable for this operation", buf);
524 }
525
526 /*
527 * call-seq:
528 * pointer.kind
529 *
530 * Returns the "kind" of the event. Returns one of the following symbols:
531 * :null, :meta, :tempo, :time_signature, :key, :smpte, :port, :text, :message,
532 * :program, :note, :control, :pitch_bend, :channel_pressure, :key_pressure,
533 * :sysex, :sysex_cont
534 */
535 static VALUE
536 s_MRPointer_Kind(VALUE self)
537 {
538 int kind;
539 /* int code; */
540 MDPointer *pt = MDPointerFromMRPointerValue(self);
541 MDEvent *ep = MDPointerCurrent(pt);
542 if (ep == NULL)
543 s_MRPointer_OutOfBoundsError(pt);
544 kind = MDGetKind(ep);
545 /* code = MDGetCode(ep); */
546 return MREventSymbolFromEventKindAndCode(kind, -1, NULL); /* returns the generic symbol */
547 }
548
549 /*
550 * call-seq:
551 * pointer.kind=(symbol)
552 *
553 * Set the "kind" of the event. The kind must be one of the symbols listed in
554 * pointer.kind().
555 */
556 static VALUE
557 s_MRPointer_SetKind(VALUE self, VALUE val)
558 {
559 int kind, code;
560 MRPointerInfo *ip = s_MRPointerInfoFromValue(self);
561 MDPointer *pt = ip->pointer;
562 MDEvent *ep = MDPointerCurrent(pt);
563 MDEvent event;
564 if (ep == NULL)
565 s_MRPointer_OutOfBoundsError(pt);
566 kind = MREventKindAndCodeFromEventSymbol(val, &code, NULL);
567 if (kind < 0)
568 rb_raise(rb_eArgError, "the value to set must be a symbol (:meta, :tempo, etc.)");
569 if (kind == MDGetKind(ep) && (code == MDGetCode(ep) || (kind != kMDEventMetaText && kind != kMDEventControl)))
570 return val; // No operation
571 MDEventClear(&event);
572 MDEventDefault(&event, kind);
573 if (code != 0)
574 MDSetCode(&event, code);
575 MDSetTick(&event, MDGetTick(ep));
576 if (kind == kMDEventMetaText && ep->kind == kMDEventMetaText) {
577 MDCopyMessage(&event, ep);
578 } else if (kind == kMDEventControl && ep->kind == kMDEventControl) {
579 MDSetData1(&event, MDGetData1(ep));
580 }
581 if (ip->trackInfo.doc != nil) {
582 MDEventObject *newEvent = [[[MDEventObject alloc] init] autorelease];
583 MDEventMove(&newEvent->event, &event, 1);
584 newEvent->position = MDPointerGetPosition(pt);
585 [ip->trackInfo.doc replaceEvent: newEvent inTrack: ip->trackInfo.num];
586 } else {
587 MDEventClear(ep);
588 MDEventMove(ep, &event, 1);
589 }
590 return val;
591 }
592
593 /*
594 * call-seq:
595 * pointer.code
596 *
597 * Returns the code of the event. Only meaningful for the following event kind:
598 * :meta, :text, :message, :note, :control, :key_pressure. Otherwise, nil is returned.
599 */
600 static VALUE
601 s_MRPointer_Code(VALUE self)
602 {
603 int kind, code;
604 MDPointer *pt = MDPointerFromMRPointerValue(self);
605 MDEvent *ep = MDPointerCurrent(pt);
606 if (ep == NULL)
607 s_MRPointer_OutOfBoundsError(pt);
608 kind = MDGetKind(ep);
609 if (kind != kMDEventMeta && kind != kMDEventMetaText && kind != kMDEventMetaMessage && kind != kMDEventNote && kind != kMDEventControl && kind != kMDEventKeyPres)
610 return Qnil;
611 code = MDGetCode(ep);
612 return INT2NUM(code);
613 }
614
615 /*
616 * call-seq:
617 * pointer.code=(val)
618 *
619 * Set the code of the event. Only meaningful for the following event kind:
620 * :meta, :text, :message, :note, :control, :key_pressure. The value must be
621 * 0..127.
622 */
623 static VALUE
624 s_MRPointer_SetCode(VALUE self, VALUE val)
625 {
626 int kind, code;
627 MRPointerInfo *ip = s_MRPointerInfoFromValue(self);
628 MDPointer *pt = ip->pointer;
629 MDEvent *ep = MDPointerCurrent(pt);
630 if (ep == NULL)
631 s_MRPointer_OutOfBoundsError(pt);
632 kind = MDGetKind(ep);
633 if (kind != kMDEventMeta && kind != kMDEventMetaText && kind != kMDEventMetaMessage && kind != kMDEventNote && kind != kMDEventControl && kind != kMDEventKeyPres)
634 s_MRPointer_BadKindError(pt);
635 code = NUM2INT(val);
636 // if (code < 0 || code >= 128)
637 // rb_raise(rb_eRangeError, "the code value (%d) must be 0..127", code);
638 if (code < 0)
639 code = 0;
640 else if (code >= 128)
641 code = 127;
642 if (ip->trackInfo.doc != nil) {
643 MDEventFieldData ed;
644 ed.ucValue[0] = kind;
645 ed.ucValue[1] = code;
646 [ip->trackInfo.doc changeValue: ed.whole ofType: kMDEventFieldKindAndCode atPosition: MDPointerGetPosition(pt) inTrack: ip->trackInfo.num];
647 } else {
648 MDSetCode(ep, code);
649 }
650 return val;
651 }
652
653 /*
654 * call-seq:
655 * pointer.control_kind
656 *
657 * If the event is a control event, then returns the symbol representing the
658 * event.code. Otherwise, returns nil.
659 */
660 static VALUE
661 s_MRPointer_ControlKind(VALUE self)
662 {
663 int kind;
664 int code;
665 MDPointer *pt = MDPointerFromMRPointerValue(self);
666 MDEvent *ep = MDPointerCurrent(pt);
667 if (ep == NULL)
668 s_MRPointer_OutOfBoundsError(pt);
669 kind = MDGetKind(ep);
670 code = MDGetCode(ep);
671 if (kind == kMDEventControl)
672 return MREventSymbolFromEventKindAndCode(kind, code, NULL);
673 else return Qnil;
674 }
675
676 /*
677 * call-seq:
678 * pointer.text_kind
679 *
680 * If the event is a text meta event, then returns the symbol representing the
681 * event.code. Otherwise, returns nil.
682 */
683 static VALUE
684 s_MRPointer_TextKind(VALUE self)
685 {
686 int kind;
687 int code;
688 MDPointer *pt = MDPointerFromMRPointerValue(self);
689 MDEvent *ep = MDPointerCurrent(pt);
690 if (ep == NULL)
691 s_MRPointer_OutOfBoundsError(pt);
692 kind = MDGetKind(ep);
693 code = MDGetCode(ep);
694 if (kind == kMDEventMetaText)
695 return MREventSymbolFromEventKindAndCode(kind, code, NULL);
696 else return Qnil;
697 }
698
699 VALUE
700 MRPointer_GetDataSub(const MDEvent *ep)
701 {
702 int kind;
703 VALUE vals[5];
704 kind = MDGetKind(ep);
705 switch (kind) {
706 case kMDEventProgram:
707 case kMDEventPitchBend:
708 case kMDEventControl:
709 case kMDEventChanPres:
710 case kMDEventKeyPres:
711 case kMDEventPortNumber:
712 return INT2NUM(MDGetData1(ep));
713 case kMDEventTempo:
714 return rb_float_new(MDGetTempo(ep));
715 case kMDEventMetaText:
716 case kMDEventMetaMessage:
717 case kMDEventSysex:
718 case kMDEventSysexCont: {
719 int32_t messageLength;
720 int32_t i;
721 const char *cp = (const char *)MDGetMessageConstPtr(ep, &messageLength);
722 if (kind == kMDEventSysex || kind == kMDEventSysexCont) {
723 vals[0] = rb_ary_new2(messageLength);
724 for (i = 0; i < messageLength; i++) {
725 rb_ary_store(vals[0], i, INT2FIX((unsigned char)cp[i]));
726 }
727 return vals[0];
728 } else {
729 if (kind == kMDEventMetaText) {
730 /* Chop at the first null byte */
731 for (i = 0; i < messageLength; i++) {
732 if (cp[i] == 0)
733 break;
734 }
735 messageLength = i;
736 }
737 return rb_str_new(cp, messageLength);
738 }
739 }
740 case kMDEventSMPTE: {
741 const MDSMPTERecord *rp = MDGetSMPTERecordPtr(ep);
742 vals[0] = INT2NUM(rp->hour);
743 vals[1] = INT2NUM(rp->min);
744 vals[2] = INT2NUM(rp->sec);
745 vals[3] = INT2NUM(rp->frame);
746 vals[4] = INT2NUM(rp->subframe);
747 return rb_ary_new4(5, vals);
748 }
749 case kMDEventTimeSignature: {
750 const unsigned char *cup = MDGetMetaDataPtr(ep);
751 vals[0] = INT2NUM(cup[0]);
752 vals[1] = INT2NUM(1 << cup[1]);
753 vals[2] = INT2NUM(cup[1]);
754 vals[3] = INT2NUM(cup[2]);
755 return rb_ary_new4(4, vals);
756 }
757 case kMDEventKey: {
758 char buf[16];
759 const char *cp = (const char *)MDGetMetaDataPtr(ep);
760 MDEventToDataString(ep, buf, sizeof buf);
761 vals[0] = rb_str_new2(buf);
762 vals[1] = INT2NUM(cp[0]);
763 vals[2] = INT2NUM(cp[1] & 1);
764 return rb_ary_new4(3, vals);
765 }
766 default:
767 return Qnil;
768 }
769 }
770
771 /*
772 * call-seq:
773 * pointer.data
774 *
775 * Returns the data of the event. Only meaningful for the following event kind:
776 * :port, :program, :pitch_bend, :control, :channel_pressure, :key_pressure => integer
777 * :text, :message, :sysex, :sysex_cont => string
778 * :tempo => float
779 * :time_signature, :smpte => array of integers
780 * :key => [string, number of key accidentals, major(1) or minor(0)]
781 * Otherwise, nil is returned.
782 */
783 static VALUE
784 s_MRPointer_Data(VALUE self)
785 {
786 MDPointer *pt = MDPointerFromMRPointerValue(self);
787 MDEvent *ep = MDPointerCurrent(pt);
788 if (ep == NULL)
789 s_MRPointer_OutOfBoundsError(pt);
790 return MRPointer_GetDataSub(ep);
791 }
792
793 void
794 MRPointer_SetDataSub(VALUE val, MDEvent *ep, MyDocument *doc, int trackNo, int32_t position)
795 {
796 int kind, data, mode;
797 MDEventFieldData ed;
798 kind = MDGetKind(ep);
799 switch (kind) {
800 case kMDEventMetaText:
801 case kMDEventMetaMessage:
802 case kMDEventSysex:
803 case kMDEventSysexCont: {
804 int32_t messageLength;
805 const unsigned char *cp;
806 StringValue(val);
807 cp = (const unsigned char *)RSTRING_PTR(val);
808 messageLength = (int)RSTRING_LEN(val);
809 if (doc != nil) {
810 [doc changeMessage: [NSData dataWithBytes: cp length: messageLength] atPosition: position inTrack: trackNo];
811 } else {
812 MDSetMessageLength(ep, messageLength);
813 MDSetMessage(ep, cp);
814 }
815 return;
816 }
817 case kMDEventPitchBend:
818 data = NUM2INT(val);
819 if (data < -8192)
820 data = -8192;
821 else if (data >= 8192)
822 data = 8191;
823 ed.intValue = data;
824 mode = kMDEventFieldData;
825 break;
826 case kMDEventPortNumber:
827 case kMDEventProgram:
828 case kMDEventControl:
829 case kMDEventChanPres:
830 case kMDEventKeyPres:
831 data = NUM2INT(val);
832 if (data < 0)
833 data = 0;
834 else if (data >= 128)
835 data = 127;
836 ed.intValue = data;
837 mode = kMDEventFieldData;
838 break;
839 case kMDEventTempo:
840 ed.floatValue = (float)NUM2DBL(val);
841 mode = kMDEventFieldTempo;
842 break;
843 case kMDEventSMPTE:
844 ed.smpte.hour = NUM2INT(Ruby_ObjectAtIndex(val, 0));
845 ed.smpte.min = NUM2INT(Ruby_ObjectAtIndex(val, 1));
846 ed.smpte.sec = NUM2INT(Ruby_ObjectAtIndex(val, 2));
847 ed.smpte.frame = NUM2INT(Ruby_ObjectAtIndex(val, 3));
848 ed.smpte.subframe = NUM2INT(Ruby_ObjectAtIndex(val, 4));
849 mode = kMDEventFieldSMPTE;
850 break;
851 case kMDEventTimeSignature: {
852 unsigned int ui;
853 VALUE valn;
854 ed.ucValue[0] = NUM2INT(Ruby_ObjectAtIndex(val, 0));
855 ui = NUM2INT(Ruby_ObjectAtIndex(val, 1));
856 ed.ucValue[1] = 0;
857 while ((ui >>= 1) != 0)
858 ed.ucValue[1]++;
859 if ((valn = Ruby_ObjectAtIndex(val, 2)) != Qnil)
860 ed.ucValue[2] = NUM2INT(valn);
861 else ed.ucValue[2] = 24;
862 if ((valn = Ruby_ObjectAtIndex(val, 3)) != Qnil)
863 ed.ucValue[3] = NUM2INT(valn);
864 else ed.ucValue[3] = 8;
865 mode = kMDEventFieldMetaData;
866 break;
867 }
868 case kMDEventKey: {
869 VALUE vals[3];
870 if (TYPE(val) == T_ARRAY) {
871 vals[0] = (RARRAY_PTR(val))[0];
872 vals[1] = (RARRAY_PTR(val))[1];
873 vals[2] = (RARRAY_PTR(val))[2];
874 } else if (TYPE(val) == T_STRING) {
875 vals[0] = val;
876 vals[1] = Qnil;
877 vals[2] = Qnil;
878 } else if (FIXNUM_P(val)) {
879 vals[0] = Qnil;
880 vals[1] = val;
881 vals[2] = Qnil;
882 } else {
883 vals[0] = rb_funcall(val, rb_intern("inspect"), 0);
884 rb_raise(rb_eTypeError, "Bad argument for key signature: %s", StringValuePtr(vals[0]));
885 }
886 if (TYPE(vals[0]) == T_STRING) {
887 char *p = StringValuePtr(vals[0]);
888 int n = MDEventDataStringToEvent(ep, p, &ed);
889 if (n != kMDEventFieldMetaData)
890 rb_raise(rb_eTypeError, "the string '%s' is not a valid key signature representation", p);
891 } else {
892 int n1 = NUM2INT(vals[1]);
893 if (n1 < -7 || n1 > 7)
894 rb_raise(rb_eRangeError, "the number of accidentals (%d) is out of bounds", n1);
895 ed.ucValue[0] = n1;
896 ed.ucValue[1] = (NUM2INT(vals[2]) & 1);
897 }
898 mode = kMDEventFieldMetaData;
899 break;
900 }
901 default:
902 rb_raise(rb_eStandardError, "invalid type for setting data");
903 break;
904 }
905
906 if (doc != nil) {
907 [doc changeValue: ed.whole ofType: mode atPosition: position inTrack: trackNo];
908 } else {
909 switch (mode) {
910 case kMDEventFieldData:
911 MDSetData1(ep, ed.intValue);
912 break;
913 case kMDEventFieldSMPTE:
914 *(MDGetSMPTERecordPtr(ep)) = ed.smpte;
915 break;
916 case kMDEventFieldMetaData:
917 memmove(MDGetMetaDataPtr(ep), ed.ucValue, 4);
918 break;
919 case kMDEventFieldTempo:
920 MDSetTempo(ep, ed.floatValue);
921 break;
922 }
923 }
924 }
925
926 /*
927 * call-seq:
928 * pointer.data=(val)
929 *
930 * Set the code of the event. Only meaningful for the following event kind:
931 * :program, :pitch_bend, :control, :channel_pressure, :key_pressure <= integer;
932 * The value must be -8192..8191 for pitch bend, 0..127 for others.
933 * :text, :message, :sysex, :sysex_cont <= string
934 * :tempo <= float
935 * :time_signature, :smpte <= array of integers
936 * :key <= string or integer (number of key accidentals) or [string, integer, integer]
937 */
938 static VALUE
939 s_MRPointer_SetData(VALUE self, VALUE val)
940 {
941 MRPointerInfo *ip = s_MRPointerInfoFromValue(self);
942 MDPointer *pt = ip->pointer;
943 MDEvent *ep = MDPointerCurrent(pt);
944 if (ep == NULL)
945 s_MRPointer_OutOfBoundsError(pt);
946 MRPointer_SetDataSub(val, ep, ip->trackInfo.doc, ip->trackInfo.num, MDPointerGetPosition(pt));
947 return val;
948 }
949
950 /*
951 * call-seq:
952 * pointer.duration
953 *
954 * Returns the duration of the event. Only meaningful for the note event.
955 * Otherwise, nil is returned.
956 */
957 static VALUE
958 s_MRPointer_Duration(VALUE self)
959 {
960 int kind, du;
961 MDPointer *pt = MDPointerFromMRPointerValue(self);
962 MDEvent *ep = MDPointerCurrent(pt);
963 if (ep == NULL)
964 s_MRPointer_OutOfBoundsError(pt);
965 kind = MDGetKind(ep);
966 if (kind != kMDEventNote)
967 return Qnil;
968 du = MDGetDuration(ep);
969 return INT2NUM(du);
970 }
971
972 /*
973 * call-seq:
974 * pointer.duration=(val)
975 *
976 * Set the duration of the event. Only meaningful for the note event.
977 */
978 static VALUE
979 s_MRPointer_SetDuration(VALUE self, VALUE val)
980 {
981 int kind, du;
982 MRPointerInfo *ip = s_MRPointerInfoFromValue(self);
983 MDPointer *pt = ip->pointer;
984 MDEvent *ep = MDPointerCurrent(pt);
985 if (ep == NULL)
986 s_MRPointer_OutOfBoundsError(pt);
987 kind = MDGetKind(ep);
988 if (kind != kMDEventNote)
989 s_MRPointer_BadKindError(pt);
990 du = NUM2INT(rb_Integer(val));
991 if (du < 1)
992 rb_raise(rb_eRangeError, "the duration value (%d) must be a positive integer", du);
993 if (ip->trackInfo.doc != nil) {
994 [ip->trackInfo.doc changeDuration: du atPosition: MDPointerGetPosition(pt) inTrack: ip->trackInfo.num];
995 } else {
996 MDPointerSetDuration(pt, du);
997 }
998 return val;
999 }
1000
1001 /*
1002 * call-seq:
1003 * pointer.velocity
1004 *
1005 * Returns the note-on velocity of the event. Only meaningful for the note event.
1006 * Otherwise, nil is returned.
1007 */
1008 static VALUE
1009 s_MRPointer_Velocity(VALUE self)
1010 {
1011 int kind, vel;
1012 MDPointer *pt = MDPointerFromMRPointerValue(self);
1013 MDEvent *ep = MDPointerCurrent(pt);
1014 if (ep == NULL)
1015 s_MRPointer_OutOfBoundsError(pt);
1016 kind = MDGetKind(ep);
1017 if (kind != kMDEventNote)
1018 return Qnil;
1019 vel = MDGetNoteOnVelocity(ep);
1020 return INT2NUM(vel);
1021 }
1022
1023 /*
1024 * call-seq:
1025 * pointer.velocity=(val)
1026 *
1027 * Set the note-on velocity of the event. Only meaningful for the note event.
1028 * The value must be 1..127.
1029 */
1030 static VALUE
1031 s_MRPointer_SetVelocity(VALUE self, VALUE val)
1032 {
1033 int kind, vel;
1034 MRPointerInfo *ip = s_MRPointerInfoFromValue(self);
1035 MDPointer *pt = ip->pointer;
1036 MDEvent *ep = MDPointerCurrent(pt);
1037 if (ep == NULL)
1038 s_MRPointer_OutOfBoundsError(pt);
1039 kind = MDGetKind(ep);
1040 if (kind != kMDEventNote)
1041 s_MRPointer_BadKindError(pt);
1042 vel = NUM2INT(val);
1043 if (vel < 1 || vel >= 128)
1044 rb_raise(rb_eRangeError, "the velocity value (%d) must be 1..127", vel);
1045 if (ip->trackInfo.doc != nil) {
1046 MDEventFieldData ed;
1047 ed.ucValue[0] = vel;
1048 ed.ucValue[1] = MDGetNoteOffVelocity(ep);
1049 [ip->trackInfo.doc changeValue: ed.whole ofType: kMDEventFieldVelocities atPosition: MDPointerGetPosition(pt) inTrack: ip->trackInfo.num];
1050 } else {
1051 MDSetNoteOnVelocity(ep, vel);
1052 }
1053 return val;
1054 }
1055
1056 /*
1057 * call-seq:
1058 * pointer.release_velocity
1059 *
1060 * Returns the note-off velocity of the event. Only meaningful for the note event.
1061 * Otherwise, nil is returned.
1062 */
1063 static VALUE
1064 s_MRPointer_ReleaseVelocity(VALUE self)
1065 {
1066 int kind, vel;
1067 MDPointer *pt = MDPointerFromMRPointerValue(self);
1068 MDEvent *ep = MDPointerCurrent(pt);
1069 if (ep == NULL)
1070 s_MRPointer_OutOfBoundsError(pt);
1071 kind = MDGetKind(ep);
1072 if (kind != kMDEventNote)
1073 return Qnil;
1074 vel = MDGetNoteOffVelocity(ep);
1075 return INT2NUM(vel);
1076 }
1077
1078 /*
1079 * call-seq:
1080 * pointer.release_velocity=(val)
1081 *
1082 * Set the note-on velocity of the event. Only meaningful for the note event.
1083 * The value must be 0..127.
1084 */
1085 static VALUE
1086 s_MRPointer_SetReleaseVelocity(VALUE self, VALUE val)
1087 {
1088 int kind, vel;
1089 MRPointerInfo *ip = s_MRPointerInfoFromValue(self);
1090 MDPointer *pt = ip->pointer;
1091 MDEvent *ep = MDPointerCurrent(pt);
1092 if (ep == NULL)
1093 s_MRPointer_OutOfBoundsError(pt);
1094 kind = MDGetKind(ep);
1095 if (kind != kMDEventNote)
1096 s_MRPointer_BadKindError(pt);
1097 vel = NUM2INT(val);
1098 if (vel < 1 || vel >= 128)
1099 rb_raise(rb_eRangeError, "the velocity value (%d) must be 1..127", vel);
1100 if (ip->trackInfo.doc != nil) {
1101 MDEventFieldData ed;
1102 ed.ucValue[0] = MDGetNoteOnVelocity(ep);
1103 ed.ucValue[1] = vel;
1104 [ip->trackInfo.doc changeValue: ed.whole ofType: kMDEventFieldVelocities atPosition: MDPointerGetPosition(pt) inTrack: ip->trackInfo.num];
1105 } else {
1106 MDSetNoteOffVelocity(ep, vel);
1107 }
1108 return val;
1109 }
1110
1111 /*
1112 * call-seq:
1113 * pointer.tick
1114 *
1115 * Returns the tick of the event.
1116 */
1117 static VALUE
1118 s_MRPointer_Tick(VALUE self)
1119 {
1120 MDTickType tick;
1121 MDPointer *pt = MDPointerFromMRPointerValue(self);
1122 MDEvent *ep = MDPointerCurrent(pt);
1123 if (ep == NULL)
1124 s_MRPointer_OutOfBoundsError(pt);
1125 tick = MDGetTick(ep);
1126 return INT2NUM(tick);
1127 }
1128
1129 /*
1130 * call-seq:
1131 * pointer.tick=(val)
1132 *
1133 * Set the tick of the event. This may cause a change in event order, but it
1134 * will only happen when the cached modification events are sent to MyDocument
1135 * (see the comment in s_MRPointerScheduleEventModification)
1136 */
1137 static VALUE
1138 s_MRPointer_SetTick(VALUE self, VALUE val)
1139 {
1140 MDTickType tick;
1141 MRPointerInfo *ip = s_MRPointerInfoFromValue(self);
1142 MDPointer *pt = ip->pointer;
1143 MDEvent *ep = MDPointerCurrent(pt);
1144 if (ep == NULL)
1145 s_MRPointer_OutOfBoundsError(pt);
1146 tick = (MDTickType)NUM2DBL(val);
1147 if (ip->trackInfo.doc != nil) {
1148 [ip->trackInfo.doc changeTick: tick atPosition: MDPointerGetPosition(pt) inTrack: ip->trackInfo.num originalPosition: kMDNegativeTick];
1149 } else {
1150 MDPointerChangeTick(pt, tick, -1);
1151 }
1152 return val;
1153 }
1154
1155 /*
1156 * call-seq:
1157 * pointer.selected?
1158 *
1159 * Returns whether the event is selected.
1160 */
1161 static VALUE
1162 s_MRPointer_SelectedP(VALUE self)
1163 {
1164 const MRPointerInfo *ip = s_MRPointerInfoFromValue(self);
1165 if (ip != NULL && ip->trackInfo.doc != NULL) {
1166 BOOL flag = [ip->trackInfo.doc isSelectedAtPosition: MDPointerGetPosition(ip->pointer) inTrack: ip->trackInfo.num];
1167 return (flag ? Qtrue : Qfalse);
1168 }
1169 return Qfalse;
1170 }
1171
1172 #pragma mark ====== Initialize class ======
1173
1174 void
1175 MRPointerInitClass(void)
1176 {
1177 if (rb_cMRPointer != Qfalse)
1178 return;
1179
1180 rb_cMRPointer = rb_define_class("Pointer", rb_cObject);
1181 rb_define_alloc_func(rb_cMRPointer, s_MRPointer_Alloc);
1182 rb_define_private_method(rb_cMRPointer, "initialize", s_MRPointer_Initialize, -1);
1183 rb_define_private_method(rb_cMRPointer, "initialize_copy", s_MRPointer_InitializeCopy, 1);
1184 rb_define_method(rb_cMRPointer, "position", s_MRPointer_Position, -1);
1185 rb_define_method(rb_cMRPointer, "position=", s_MRPointer_SetPosition, 1);
1186 rb_define_method(rb_cMRPointer, "move_to", s_MRPointer_SetPosition, 1);
1187 rb_define_method(rb_cMRPointer, "move_by", s_MRPointer_MoveBy, 1);
1188 rb_define_method(rb_cMRPointer, "track", s_MRPointer_Track, 0);
1189 rb_define_method(rb_cMRPointer, "top", MRPointer_Top, 0);
1190 rb_define_method(rb_cMRPointer, "bottom", MRPointer_Bottom, 0);
1191 rb_define_method(rb_cMRPointer, "next", MRPointer_Next, 0);
1192 rb_define_method(rb_cMRPointer, "last", MRPointer_Last, 0);
1193 rb_define_method(rb_cMRPointer, "next_in_selection", MRPointer_NextInSelection, 0);
1194 rb_define_method(rb_cMRPointer, "last_in_selection", MRPointer_LastInSelection, 0);
1195 rb_define_method(rb_cMRPointer, "jump_to_tick", s_MRPointer_JumpToTick, 1);
1196 rb_define_method(rb_cMRPointer, "kind", s_MRPointer_Kind, 0);
1197 rb_define_method(rb_cMRPointer, "kind=", s_MRPointer_SetKind, 1);
1198 rb_define_method(rb_cMRPointer, "code", s_MRPointer_Code, 0);
1199 rb_define_method(rb_cMRPointer, "code=", s_MRPointer_SetCode, 1);
1200 rb_define_method(rb_cMRPointer, "control_kind", s_MRPointer_ControlKind, 0);
1201 rb_define_method(rb_cMRPointer, "text_kind", s_MRPointer_TextKind, 0);
1202 rb_define_method(rb_cMRPointer, "data", s_MRPointer_Data, 0);
1203 rb_define_method(rb_cMRPointer, "data=", s_MRPointer_SetData, 1);
1204 rb_define_method(rb_cMRPointer, "tick", s_MRPointer_Tick, 0);
1205 rb_define_method(rb_cMRPointer, "tick=", s_MRPointer_SetTick, 1);
1206 rb_define_method(rb_cMRPointer, "duration", s_MRPointer_Duration, 0);
1207 rb_define_method(rb_cMRPointer, "duration=", s_MRPointer_SetDuration, 1);
1208 rb_define_method(rb_cMRPointer, "velocity", s_MRPointer_Velocity, 0);
1209 rb_define_method(rb_cMRPointer, "velocity=", s_MRPointer_SetVelocity, 1);
1210 rb_define_method(rb_cMRPointer, "release_velocity", s_MRPointer_ReleaseVelocity, 0);
1211 rb_define_method(rb_cMRPointer, "release_velocity=", s_MRPointer_SetReleaseVelocity, 1);
1212 rb_define_method(rb_cMRPointer, "selected?", s_MRPointer_SelectedP, 0);
1213 }

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