Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/Ruby_bindings/MDRubyEventSet.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: 41274 byte(s)
Xcode project is updated so that ppc/i386 universal binary can be built (as before)
1 /*
2 * MDRubyEventSet.m
3 * Alchemusica
4 *
5 * Created by Toshi Nagata on 09/01/24.
6 * Copyright 2009-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 "MDRubyEventSet.h"
19 #include "MDRubyTrack.h"
20 #include "MDRubyPointer.h"
21 #import "MyDocument.h"
22 #import "MDObjects.h"
23
24 #pragma mark ====== MRPointSet Class ======
25
26 /* The MRPointSet class is dependent only on IntGroup */
27
28 VALUE rb_cIntGroup;
29
30 IntGroup *
31 IntGroupFromValue(VALUE val)
32 {
33 IntGroup *pset;
34 if (!rb_obj_is_kind_of(val, rb_cIntGroup))
35 val = rb_funcall(rb_cIntGroup, rb_intern("new"), 1, val);
36 Data_Get_Struct(val, IntGroup, pset);
37 return pset;
38 }
39
40 VALUE
41 ValueFromIntGroup(IntGroup *pset)
42 {
43 if (pset == NULL)
44 return Qnil;
45 IntGroupRetain(pset);
46 return Data_Wrap_Struct(rb_cIntGroup, 0, (void (*)(void *))IntGroupRelease, pset);
47 }
48
49 void
50 MRPointSet_RaiseIfError(int err)
51 {
52 if (err != 0) {
53 const char *s;
54 switch (err) {
55 case kMDErrorOutOfMemory: s = "out of memory"; break;
56 case kMDErrorOutOfRange: s = "out of range"; break;
57 default: s = ""; break;
58 }
59 rb_raise(rb_eStandardError, "%s error occurred during IntGroup operation", s);
60 }
61 }
62
63 /* Allocator */
64 VALUE
65 MRPointSet_Alloc(VALUE klass)
66 {
67 IntGroup *pset = IntGroupNew();
68 return Data_Wrap_Struct(klass, 0, (void (*)(void *))IntGroupRelease, pset);
69 }
70
71 /* Iterator block for initializer */
72 static VALUE
73 s_MRPointSet_Initialize_i(VALUE val, VALUE pset1)
74 {
75 MRPointSet_RaiseIfError(IntGroupAdd((IntGroup *)pset1, NUM2INT(val), 1));
76 return Qnil;
77 }
78
79 /*
80 * call-seq:
81 * MRPointSet.new(arg1, arg2, ...)
82 * MRPointSet.new(arg1, arg2, ...) { |n| ... }
83 *
84 * Create a new pointset. Arg1, arg2,... are one of the following: MRPointSet, Range,
85 * Enumerable, Integer.
86 * If a block is given, it is executed for each element in the arguments, and
87 * a new pointset including the returned value (only non-negative integers) is returned.
88 */
89 static VALUE
90 s_MRPointSet_Initialize(int argc, VALUE *argv, VALUE self)
91 {
92 IntGroup *pset1;
93 Data_Get_Struct(self, IntGroup, pset1);
94 while (argc-- > 0) {
95 VALUE arg = *argv++;
96 int type = TYPE(arg);
97 if (rb_obj_is_kind_of(arg, rb_cIntGroup))
98 rb_funcall(rb_cIntGroup, rb_intern("merge"), 1, arg);
99 else if (rb_obj_is_kind_of(arg, rb_cRange)) {
100 int sp, ep;
101 sp = NUM2INT(rb_funcall(arg, rb_intern("begin"), 0));
102 ep = NUM2INT(rb_funcall(arg, rb_intern("end"), 0));
103 if (RTEST(rb_funcall(arg, rb_intern("exclude_end?"), 0)))
104 ep--;
105 if (ep >= sp)
106 MRPointSet_RaiseIfError(IntGroupAdd(pset1, sp, ep - sp + 1));
107 } else if (rb_respond_to(arg, rb_intern("each")) && type != T_STRING)
108 rb_iterate(rb_each, arg, s_MRPointSet_Initialize_i, (VALUE)pset1);
109 else
110 MRPointSet_RaiseIfError(IntGroupAdd(pset1, NUM2INT(arg), 1));
111 }
112 if (rb_block_given_p()) {
113 IntGroup *pset2 = IntGroupNew();
114 int i, n;
115 for (i = 0; (n = IntGroupGetNthPoint(pset1, i)) >= 0; i++) {
116 n = NUM2INT(rb_yield(INT2NUM(n)));
117 if (n >= 0)
118 MRPointSet_RaiseIfError(IntGroupAdd(pset2, n, 1));
119 }
120 MRPointSet_RaiseIfError(IntGroupCopy(pset1, pset2));
121 }
122 return Qnil;
123 }
124
125 /*
126 * call-seq:
127 * pointset.clear
128 *
129 * Empty the pointset.
130 */
131 static VALUE
132 s_MRPointSet_Clear(VALUE self)
133 {
134 IntGroup *pset;
135 Data_Get_Struct(self, IntGroup, pset);
136 IntGroupClear(pset);
137 return self;
138 }
139
140 /*
141 * call-seq:
142 * pointset.dup
143 *
144 * Duplicate the pointset.
145 */
146 static VALUE
147 s_MRPointSet_InitializeCopy(VALUE self, VALUE val)
148 {
149 IntGroup *pset1, *pset2;
150 Data_Get_Struct(self, IntGroup, pset1);
151 if (!rb_obj_is_kind_of(val, rb_cIntGroup))
152 rb_raise(rb_eTypeError, "IntGroup instance is expected");
153 Data_Get_Struct(val, IntGroup, pset2);
154 IntGroupCopy(pset1, pset2);
155 return self;
156 }
157
158 /*
159 * call-seq:
160 * pointset.length
161 *
162 * Returns the number of points in the pointset.
163 */
164 static VALUE
165 s_MRPointSet_Length(VALUE self)
166 {
167 IntGroup *pset;
168 Data_Get_Struct(self, IntGroup, pset);
169 return INT2NUM(IntGroupGetCount(pset));
170 }
171
172 /*
173 * call-seq:
174 * pointset.member?(n)
175 *
176 * Check whether the argument is included in the pointset.
177 */
178 static VALUE
179 s_MRPointSet_MemberP(VALUE self, VALUE val)
180 {
181 IntGroup *pset;
182 int n = NUM2INT(val);
183 Data_Get_Struct(self, IntGroup, pset);
184 return (IntGroupLookup(pset, n, NULL) ? Qtrue : Qfalse);
185 }
186
187 /*
188 * call-seq:
189 * pointset[n]
190 *
191 * Returns the n-th point.
192 */
193 static VALUE
194 s_MRPointSet_ElementAtIndex(VALUE self, VALUE val)
195 {
196 IntGroup *pset;
197 int n;
198 int index = NUM2INT(rb_Integer(val));
199 Data_Get_Struct(self, IntGroup, pset);
200 n = IntGroupGetNthPoint(pset, index);
201 return (n >= 0 ? INT2NUM(n) : Qnil);
202 }
203
204 /*
205 * call-seq:
206 * pointset.each { |n| ... }
207 *
208 * Iterate the block for each point in the set.
209 */
210 static VALUE
211 s_MRPointSet_Each(VALUE self)
212 {
213 IntGroup *pset;
214 int i, j, sp, ep;
215 Data_Get_Struct(self, IntGroup, pset);
216 for (i = 0; (sp = IntGroupGetStartPoint(pset, i)) >= 0; i++) {
217 ep = IntGroupGetEndPoint(pset, i);
218 for (j = sp; j < ep; j++) {
219 rb_yield(INT2NUM(j));
220 }
221 }
222 return self;
223 }
224
225 /*
226 * call-seq:
227 * pointset.add(pset2)
228 *
229 * Add points in the argument to self.
230 */
231 static VALUE
232 s_MRPointSet_Add(VALUE self, VALUE val)
233 {
234 IntGroup *pset, *pset2;
235 if (OBJ_FROZEN(self))
236 rb_error_frozen("IntGroup");
237 Data_Get_Struct(self, IntGroup, pset);
238 if (rb_obj_is_kind_of(val, rb_cNumeric)) {
239 int n = NUM2INT(rb_Integer(val));
240 if (n < 0)
241 rb_raise(rb_eRangeError, "the integer group can contain only non-negative values");
242 IntGroupAdd(pset, n, 1);
243 } else {
244 pset2 = IntGroupFromValue(val);
245 IntGroupAddIntGroup(pset, pset2);
246 }
247 return self;
248 }
249
250 /*
251 * call-seq:
252 * pointset.delete(pset2)
253 *
254 * Remove points in the argument from self.
255 */
256 static VALUE
257 s_MRPointSet_Delete(VALUE self, VALUE val)
258 {
259 IntGroup *pset, *pset2;
260 if (OBJ_FROZEN(self))
261 rb_error_frozen("IntGroup");
262 Data_Get_Struct(self, IntGroup, pset);
263 if (rb_obj_is_kind_of(val, rb_cNumeric)) {
264 int n = NUM2INT(rb_Integer(val));
265 if (n >= 0 && IntGroupLookup(pset, n, NULL))
266 IntGroupRemove(pset, n, 1);
267 } else {
268 pset2 = IntGroupFromValue(val);
269 IntGroupRemoveIntGroup(pset, pset2);
270 }
271 return self;
272 }
273
274 /*
275 * call-seq:
276 * pointset.reverse(pset2)
277 *
278 * Reverse points in the argument from self.
279 */
280 static VALUE
281 s_MRPointSet_Reverse(VALUE self, VALUE val)
282 {
283 IntGroup *pset, *pset2;
284 if (OBJ_FROZEN(self))
285 rb_error_frozen("IntGroup");
286 Data_Get_Struct(self, IntGroup, pset);
287 if (rb_obj_is_kind_of(val, rb_cNumeric)) {
288 int n = NUM2INT(rb_Integer(val));
289 if (n >= 0 && IntGroupLookup(pset, n, NULL))
290 IntGroupReverse(pset, n, 1);
291 } else {
292 pset2 = IntGroupFromValue(val);
293 IntGroupReverseIntGroup(pset, pset2);
294 }
295 return self;
296 }
297
298 static VALUE
299 s_MRPointSet_Binary(VALUE self, VALUE val, int (*func)(const IntGroup *, const IntGroup *, IntGroup *))
300 {
301 IntGroup *pset1, *pset2, *pset3;
302 VALUE retval;
303 Data_Get_Struct(self, IntGroup, pset1);
304 pset2 = IntGroupFromValue(val);
305 /* retval = MRPointSet_Alloc(rb_cIntGroup); */
306 retval = rb_obj_dup(self); /* the return value will have the same class as self */
307 Data_Get_Struct(retval, IntGroup, pset3);
308 IntGroupClear(pset3);
309 MRPointSet_RaiseIfError(func(pset1, pset2, pset3));
310 return retval;
311 }
312
313 /*
314 * call-seq:
315 * pointset.union(pset2)
316 * pointset + pset2
317 * pointset | pset2
318 *
319 * Calculate the union set and return as a new pointset object.
320 * (pointset is first dup'ed, so the instance variables are copied to the returned value).
321 */
322 static VALUE
323 s_MRPointSet_Union(VALUE self, VALUE val)
324 {
325 return s_MRPointSet_Binary(self, val, IntGroupUnion);
326 }
327
328 /*
329 * call-seq:
330 * pointset.intersection(pset2)
331 * pointset & pset2
332 *
333 * Calculate the intersection set and return as a new pointset object.
334 * (pointset is first dup'ed, so the instance variables are copied to the returned value).
335 */
336 static VALUE
337 s_MRPointSet_Intersection(VALUE self, VALUE val)
338 {
339 return s_MRPointSet_Binary(self, val, IntGroupIntersect);
340 }
341
342 /*
343 * call-seq:
344 * pointset.difference(pset2)
345 * pointset - pset2
346 *
347 * Calculate the difference set and return as a new pointset object.
348 * (pointset is first dup'ed, so the instance variables are copied to the returned value).
349 */
350 static VALUE
351 s_MRPointSet_Difference(VALUE self, VALUE val)
352 {
353 return s_MRPointSet_Binary(self, val, IntGroupDifference);
354 }
355
356 /*
357 * call-seq:
358 * pointset.sym_difference(pset2)
359 * pointset ^ pset2
360 *
361 * Calculate the symmetric difference set and return as a new pointset object.
362 * (pointset is first dup'ed, so the instance variables are copied to the returned value).
363 */
364 static VALUE
365 s_MRPointSet_SymDifference(VALUE self, VALUE val)
366 {
367 return s_MRPointSet_Binary(self, val, IntGroupXor);
368 }
369
370 /*
371 * call-seq:
372 * pointset.convolute(pset2)
373 *
374 * Calculate the convolute set and return as a new pointset object.
375 * (pointset is first dup'ed, so the instance variables are copied to the returned value).
376 */
377 static VALUE
378 s_MRPointSet_Convolute(VALUE self, VALUE val)
379 {
380 return s_MRPointSet_Binary(self, val, IntGroupConvolute);
381 }
382
383 /*
384 * call-seq:
385 * pointset.deconvolute(pset2)
386 *
387 * Calculate the convolute set and return as a new pointset object.
388 * (pointset is first dup'ed, so the instance variables are copied to the returned value).
389 */
390 static VALUE
391 s_MRPointSet_Deconvolute(VALUE self, VALUE val)
392 {
393 return s_MRPointSet_Binary(self, val, IntGroupDeconvolute);
394 }
395
396 /*
397 * call-seq:
398 * pointset.range_at(n)
399 *
400 * Regard self as a set of integer ranges, and returns the n-th range as a Range object.
401 */
402 static VALUE
403 s_MRPointSet_RangeAt(VALUE self, VALUE val)
404 {
405 IntGroup *pset;
406 int n = NUM2INT(val);
407 int sp, ep;
408 Data_Get_Struct(self, IntGroup, pset);
409 sp = IntGroupGetStartPoint(pset, n);
410 if (sp < 0)
411 return Qnil;
412 ep = IntGroupGetEndPoint(pset, n) - 1;
413 return rb_funcall(rb_cRange, rb_intern("new"), 2, INT2NUM(sp), INT2NUM(ep));
414 }
415
416 /*
417 static VALUE
418 s_MRPointSet_Merge(VALUE self, VALUE val)
419 {
420 IntGroup *pset1, *pset2;
421 int i, sp, interval;
422 if (OBJ_FROZEN(self))
423 rb_error_frozen("IntGroup");
424 Data_Get_Struct(self, IntGroup, pset1);
425 pset2 = IntGroupFromValue(val);
426 for (i = 0; (sp = IntGroupGetStartPoint(pset2, i)) >= 0; i++) {
427 interval = IntGroupGetInterval(pset2, i);
428 MRPointSet_RaiseIfError(IntGroupAdd(pset1, sp, interval));
429 }
430 return self;
431 }
432
433 static VALUE
434 s_MRPointSet_Subtract(VALUE self, VALUE val)
435 {
436 IntGroup *pset1, *pset2;
437 int i, sp, interval;
438 if (OBJ_FROZEN(self))
439 rb_error_frozen("IntGroup");
440 Data_Get_Struct(self, IntGroup, pset1);
441 pset2 = IntGroupFromValue(val);
442 for (i = 0; (sp = IntGroupGetStartPoint(pset2, i)) >= 0; i++) {
443 interval = IntGroupGetInterval(pset2, i);
444 MRPointSet_RaiseIfError(IntGroupRemove(pset1, sp, interval));
445 }
446 return self;
447 }
448 */
449
450 /*
451 * call-seq:
452 * pointset.offset(n)
453 *
454 * Offset all points by n. n can be negative, but if it is smaller than the negative
455 * of the first point, an exception is raised.
456 */
457 static VALUE
458 s_MRPointSet_Offset(VALUE self, VALUE ofs)
459 {
460 IntGroup *pset1, *pset2;
461 int iofs;
462 VALUE val;
463 Data_Get_Struct(self, IntGroup, pset1);
464 pset2 = IntGroupNew();
465 if (pset2 == NULL || IntGroupCopy(pset2, pset1) != kMDNoError)
466 rb_raise(rb_eTypeError, "Cannot duplicate IntGroup");
467 iofs = NUM2INT(ofs);
468 if (IntGroupOffset(pset2, iofs) != 0)
469 rb_raise(rb_eRangeError, "Bad offset %d", iofs);
470 val = ValueFromIntGroup(pset2);
471 IntGroupRelease(pset2);
472 return val;
473 }
474
475 static VALUE
476 s_MRPointSet_Create(int argc, VALUE *argv, VALUE klass)
477 {
478 VALUE val = MRPointSet_Alloc(klass);
479 s_MRPointSet_Initialize(argc, argv, val);
480 return val;
481 }
482
483 /*
484 * call-seq:
485 * pointset.inspect(n)
486 *
487 * Returns the string representation of the pointset.
488 */
489 static VALUE
490 s_MRPointSet_Inspect(VALUE self)
491 {
492 int i, sp, ep;
493 IntGroup *pset;
494 char buf[64];
495 VALUE klass = CLASS_OF(self);
496 VALUE val = rb_funcall(klass, rb_intern("name"), 0);
497 Data_Get_Struct(self, IntGroup, pset);
498 rb_str_cat(val, "[", 1);
499 for (i = 0; (sp = IntGroupGetStartPoint(pset, i)) >= 0; i++) {
500 if (i > 0)
501 rb_str_cat(val, ", ", 2);
502 ep = IntGroupGetEndPoint(pset, i);
503 if (ep > sp + 1)
504 snprintf(buf, sizeof buf, "%d..%d", sp, ep - 1);
505 else
506 snprintf(buf, sizeof buf, "%d", sp);
507 rb_str_cat(val, buf, strlen(buf));
508 }
509 rb_str_cat(val, "]", 1);
510 return val;
511 }
512
513 #pragma mark ====== MREventSet Class ======
514
515 VALUE rb_cMREventSet;
516
517 /* Symbolic ID for instance variable names */
518 static ID s_ID_track, s_ID_eot_selected;
519
520 /*
521 * call-seq:
522 * MREventSet.new([track,] arg1, arg2, ...)
523 * MREventSet.new([track,] arg1, arg2, ...) { |n| ... }
524 *
525 * Create a new eventset. Arg1, arg2,... and block are handled as in MRPointSet.
526 * If track is given, then the created eventset is associated with the track.
527 * Otherwise, it is not associated with any track.
528 */
529 static VALUE
530 s_MREventSet_Initialize(int argc, VALUE *argv, VALUE self)
531 {
532 VALUE tval;
533 if (argc > 0 && rb_obj_is_kind_of(argv[0], rb_cMRTrack)) {
534 tval = argv[0];
535 argv++;
536 argc--;
537 } else tval = Qnil;
538 s_MRPointSet_Initialize(argc, argv, self);
539 rb_ivar_set(self, s_ID_track, tval);
540 rb_ivar_set(self, s_ID_eot_selected, Qfalse);
541 return Qnil;
542 }
543
544 VALUE
545 MREventSetValueFromIntGroupAndTrackInfo(IntGroup *pset, MDTrack *track, void *myDocument, int isEndOfTrackSelected)
546 {
547 VALUE val, tval;
548 IntGroup *pset2;
549 MyDocument *doc = (MyDocument *)myDocument;
550 tval = MRTrackValueFromTrackInfo(track, doc, -1);
551 val = MRPointSet_Alloc(rb_cMREventSet);
552 s_MREventSet_Initialize(1, &tval, val);
553 pset2 = IntGroupFromValue(val);
554 IntGroupCopy(pset2, pset);
555 if (isEndOfTrackSelected)
556 rb_ivar_set(val, s_ID_eot_selected, Qtrue);
557 return val;
558 }
559
560 /*
561 * call-seq:
562 * MREventSet.track
563 *
564 * Accessor (getter) function for @track.
565 */
566 VALUE
567 MREventSet_Track(VALUE self)
568 {
569 return rb_ivar_get(self, s_ID_track);
570 }
571
572 /*
573 * call-seq:
574 * MREventSet.eot_selected
575 *
576 * Accessor (getter) function for @eot_selected.
577 */
578 VALUE
579 MREventSet_EOTSelected(VALUE self)
580 {
581 return rb_ivar_get(self, s_ID_eot_selected);
582 }
583
584 /*
585 * call-seq:
586 * MREventSet.track=
587 *
588 * Accessor (setter) function for @track.
589 */
590 VALUE
591 MREventSet_SetTrack(VALUE self, VALUE val)
592 {
593 if (!rb_obj_is_kind_of(val, rb_cMRTrack))
594 rb_raise(rb_eTypeError, "track value must be Track type");
595 rb_ivar_set(self, s_ID_track, val);
596 return val;
597 }
598
599 /*
600 * call-seq:
601 * MREventSet.eot_selected=
602 *
603 * Accessor (setter) function for @eot_selected.
604 */
605 VALUE
606 MREventSet_SetEOTSelected(VALUE self, VALUE val)
607 {
608 rb_ivar_set(self, s_ID_eot_selected, val);
609 return val;
610 }
611
612 static VALUE
613 s_MREventSet_Pointer(VALUE self)
614 {
615 const MyDocumentTrackInfo *ip;
616 VALUE tval;
617 tval = rb_ivar_get(self, s_ID_track);
618 if (tval == Qnil)
619 rb_raise(rb_eStandardError, "Track is not given");
620 ip = TrackInfoFromMRTrackValue(tval);
621 return MRPointerValueFromTrackInfo(ip->track, ip->doc, ip->num, -1);
622 }
623
624 /*
625 * call-seq:
626 * MREventSet.each { |pt| ... }
627 *
628 * Iterate the block for each event. Pt is a Pointer value, and the same object
629 * is given for all block call.
630 */
631 static VALUE
632 s_MREventSet_Each(VALUE self)
633 {
634 MDPointer *pt;
635 IntGroup *pset;
636 int idx;
637 VALUE pval = s_MREventSet_Pointer(self);
638 pt = MDPointerFromMRPointerValue(pval);
639 pset = IntGroupFromValue(self);
640 idx = -1;
641 while (MDPointerForwardWithPointSet(pt, pset, &idx) != NULL) {
642 rb_yield(pval);
643 }
644 return self;
645 }
646
647 /*
648 * call-seq:
649 * MREventSet.reverse_each { |pt| ... }
650 *
651 * Iterate the block backward for each event. Pt is a Pointer value, and the same object
652 * is given for all block call.
653 */
654 static VALUE
655 s_MREventSet_ReverseEach(VALUE self)
656 {
657 MDPointer *pt;
658 IntGroup *pset;
659 int idx;
660 VALUE pval = s_MREventSet_Pointer(self);
661 pt = MDPointerFromMRPointerValue(pval);
662 MDPointerSetPosition(pt, kMDMaxPosition);
663 pset = IntGroupFromValue(self);
664 idx = -1;
665 while (MDPointerBackwardWithPointSet(pt, pset, &idx) != NULL) {
666 rb_yield(pval);
667 }
668 return self;
669 }
670
671 /*
672 * call-seq:
673 * MREventSet.each_with_index { |pt,i| ... }
674 *
675 * Iterate the block for each event. Pt is a Pointer value, and i is the index
676 * of the event within the event set.
677 */
678 static VALUE
679 s_MREventSet_EachWithIndex(VALUE self)
680 {
681 MDPointer *pt;
682 IntGroup *pset;
683 int idx;
684 int n;
685 VALUE pval = s_MREventSet_Pointer(self);
686 pt = MDPointerFromMRPointerValue(pval);
687 pset = IntGroupFromValue(self);
688 idx = -1;
689 n = 0;
690 while (MDPointerForwardWithPointSet(pt, pset, &idx) != NULL) {
691 rb_yield_values(2, pval, INT2NUM(n));
692 n++;
693 }
694 return self;
695 }
696
697 /*
698 * call-seq:
699 * MREventSet.reverse_each_with_index { |pt,i| ... }
700 *
701 * Iterate the block backward for each event. Pt is a Pointer value, and i is the index
702 * of the event within the event set (going downward from self.length-1 to 0)
703 */
704 static VALUE
705 s_MREventSet_ReverseEachWithIndex(VALUE self)
706 {
707 MDPointer *pt;
708 IntGroup *pset;
709 int idx;
710 int n;
711 VALUE pval = s_MREventSet_Pointer(self);
712 pt = MDPointerFromMRPointerValue(pval);
713 MDPointerSetPosition(pt, kMDMaxPosition);
714 pset = IntGroupFromValue(self);
715 idx = -1;
716 n = IntGroupGetCount(pset) - 1;
717 while (MDPointerBackwardWithPointSet(pt, pset, &idx) != NULL) {
718 rb_yield_values(2, pval, NUM2INT(n));
719 n--;
720 }
721 return self;
722 }
723
724 static VALUE
725 s_MREventSet_Select_sub(VALUE self, int reject)
726 {
727 const MyDocumentTrackInfo *ip;
728 VALUE tval, pval;
729 MDPointer *pt;
730 IntGroup *pset, *pset2;
731 int idx;
732 tval = rb_ivar_get(self, s_ID_track);
733 if (tval == Qnil)
734 rb_raise(rb_eStandardError, "Track is not given");
735 ip = TrackInfoFromMRTrackValue(tval);
736 pval = MRPointerValueFromTrackInfo(ip->track, ip->doc, ip->num, -1);
737 pt = MDPointerFromMRPointerValue(pval);
738 pset = IntGroupFromValue(self);
739 pset2 = IntGroupNew();
740 idx = -1;
741 while (MDPointerForwardWithPointSet(pt, pset, &idx) != NULL) {
742 if (RTEST(rb_yield(pval)))
743 IntGroupAdd(pset2, MDPointerGetPosition(pt), 1);
744 }
745 if (reject) {
746 IntGroupRemoveIntGroup(pset, pset2);
747 if (IntGroupGetCount(pset2) == 0)
748 tval = Qnil;
749 else tval = self;
750 } else {
751 tval = MREventSetValueFromIntGroupAndTrackInfo(pset2, ip->track, ip->doc, 0);
752 }
753 IntGroupRelease(pset2);
754 return tval;
755 }
756
757 /*
758 * call-seq:
759 * MREventSet.select { |pt| ... }
760 *
761 * Create a new event set from those for which the block returns true.
762 */
763 static VALUE
764 s_MREventSet_Select(VALUE self)
765 {
766 return s_MREventSet_Select_sub(self, 0);
767 }
768
769 /*
770 * call-seq:
771 * MREventSet.reject! { |pt| ... }
772 *
773 * Remove those events for which the block returns true. Returns nil if
774 * no events were removed, otherwise returns self.
775 */
776 static VALUE
777 s_MREventSet_Reject(VALUE self)
778 {
779 return s_MREventSet_Select_sub(self, 1);
780 }
781
782 /*
783 * call-seq:
784 * MREventSet.modify_tick(op, num) # op is either "=", "+", or "*"
785 * MREventSet.modify_tick(num) # same as ("+", num)
786 * MREventSet.modify_tick(array)
787 * MREventSet.modify_tick { |pt| }
788 *
789 * Modify the tick of the specified events.
790 * In the first form, the ticks are set, shift, or multiplied by the argument.
791 * The second form is equivalent to modify_tick("+", num) (i.e. shifted by the argument)
792 * In the third form, the new tick values are taken from the array.
793 * (If the number of objects in the array is less than the number of events in the given set,
794 * then the last value is repeated)
795 * In the fourth form, the new tick values are given by the block. The block arguments
796 * are the event pointer (note: the same pointer will be reused for every iteration).
797 */
798 static VALUE
799 s_MREventSet_ModifyTick(int argc, VALUE *argv, VALUE self)
800 {
801 const MyDocumentTrackInfo *ip;
802 VALUE tval, nval;
803 IntGroup *pset;
804 IntGroupObject *psobj;
805 id theData;
806 int n1, n2, mode;
807 MDTickType *tickp;
808 tval = rb_ivar_get(self, s_ID_track);
809 if (tval == Qnil)
810 rb_raise(rb_eStandardError, "Track is not given");
811 ip = TrackInfoFromMRTrackValue(tval);
812 pset = IntGroupFromValue(self);
813 n2 = IntGroupGetCount(pset);
814 if (n2 == 0)
815 return self;
816 psobj = [[[IntGroupObject alloc] initWithMDPointSet: pset] autorelease];
817 mode = MyDocumentModifyAdd;
818 if (argc >= 1) {
819 nval = argv[0];
820 if (rb_obj_is_kind_of(nval, rb_cString)) {
821 if (argc == 1)
822 rb_raise(rb_eStandardError, "Modify operation requires a single numeric argument");
823 n1 = RSTRING_PTR(nval)[0];
824 if (n1 == '=')
825 mode = MyDocumentModifyAdd;
826 else if (n1 == '*')
827 mode = MyDocumentModifyMultiply;
828 else if (n1 != '+')
829 rb_raise(rb_eStandardError, "Modify operation should be either '=', '+' or '*'");
830 nval = argv[1];
831 if (mode != MyDocumentModifySet && !rb_obj_is_kind_of(nval, rb_cNumeric))
832 rb_raise(rb_eStandardError, "Add or multiply operation requires a single numeric argument");
833 }
834 } else nval = Qnil;
835 if (nval == Qnil) {
836 /* The new tick values are given by the block */
837 VALUE pval = MRPointerValueFromTrackInfo(ip->track, ip->doc, ip->num, -1);
838 MDPointer *pt = MDPointerFromMRPointerValue(pval);
839 int idx = -1;
840 n1 = 0;
841 theData = [NSMutableData dataWithLength: sizeof(MDTickType) * n2];
842 tickp = (MDTickType *)[theData mutableBytes];
843 while (MDPointerForwardWithPointSet(pt, pset, &idx) != NULL) {
844 tickp[n1] = (MDTickType)NUM2DBL(rb_yield(pval));
845 n1++;
846 }
847 [MyDocument modifyTick: theData ofMultipleEventsAt: psobj forMDTrack: ip->track inDocument: ip->doc mode: MyDocumentModifySet destinationPositions: nil setSelection: YES];
848 return self;
849 } else if (rb_obj_is_kind_of(nval, rb_cNumeric)) {
850 if (mode == MyDocumentModifyMultiply)
851 theData = [NSNumber numberWithFloat: (float)NUM2DBL(rb_Float(nval))];
852 else
853 theData = [NSNumber numberWithInt: NUM2INT(rb_Integer(nval))];
854 [MyDocument modifyTick: theData ofMultipleEventsAt: psobj forMDTrack: ip->track inDocument: ip->doc mode: mode destinationPositions: nil setSelection: YES];
855 return self;
856 } else {
857 VALUE *nvalp;
858 int i;
859 nval = rb_ary_to_ary(nval);
860 n1 = (int)RARRAY_LEN(nval);
861 if (n1 == 0)
862 return self;
863 theData = [NSMutableData dataWithLength: sizeof(MDTickType) * n2];
864 tickp = (MDTickType *)[theData mutableBytes];
865 nvalp = RARRAY_PTR(nval);
866 for (i = 0; i < n1 && i < n2; i++) {
867 tickp[i] = NUM2INT(rb_Integer(nvalp[i]));
868 }
869 while (i < n2) {
870 tickp[i] = tickp[n1 - 1];
871 i++;
872 }
873 [MyDocument modifyTick: theData ofMultipleEventsAt: psobj forMDTrack: ip->track inDocument: ip->doc mode: MyDocumentModifySet destinationPositions: nil setSelection: YES];
874 return self;
875 }
876 }
877
878 /*
879 * call-seq:
880 * MREventSet.modify_code(op, num) # op is either "=", "+", or "*"
881 * MREventSet.modify_code(num) # same as ("+", num)
882 * MREventSet.modify_code(array)
883 * MREventSet.modify_code { |pt| }
884 *
885 * Modify the code of the specified events.
886 * In the first form, the codes are set, shift, or multiplied by the argument.
887 * The second form is equivalent to modify_code("+", num) (i.e. shifted by the argument)
888 * In the third form, the new code values are taken from the array.
889 * (If the number of objects in the array is less than the number of events in the given set,
890 * then the last value is repeated)
891 * In the fourth form, the new code values are given by the block. The block arguments
892 * are the event pointer (note: the same pointer will be reused for every iteration).
893 */
894 static VALUE
895 s_MREventSet_ModifyCode(int argc, VALUE *argv, VALUE self)
896 {
897 const MyDocumentTrackInfo *ip;
898 VALUE tval, nval;
899 int n1, n2, mode;
900 IntGroupObject *psobj;
901 IntGroup *pset;
902 id theData;
903 short *shortp;
904 VALUE *nvalp;
905 tval = rb_ivar_get(self, s_ID_track);
906 if (tval == Qnil)
907 rb_raise(rb_eStandardError, "Track is not given");
908 ip = TrackInfoFromMRTrackValue(tval);
909 pset = IntGroupFromValue(self);
910 n2 = IntGroupGetCount(pset);
911 if (n2 == 0)
912 return self;
913 psobj = [[[IntGroupObject alloc] initWithMDPointSet: pset] autorelease];
914 mode = MyDocumentModifyAdd;
915 if (argc >= 1) {
916 nval = argv[0];
917 if (rb_obj_is_kind_of(nval, rb_cString)) {
918 if (argc == 1)
919 rb_raise(rb_eStandardError, "Modify operation requires a single numeric argument");
920 n1 = RSTRING_PTR(nval)[0];
921 if (n1 == '=')
922 mode = MyDocumentModifySet;
923 else if (n1 == '*')
924 mode = MyDocumentModifyMultiply;
925 else if (n1 != '+')
926 rb_raise(rb_eStandardError, "Modify operation should be either '=', '+' or '*'");
927 nval = argv[1];
928 if (mode != MyDocumentModifySet && !rb_obj_is_kind_of(nval, rb_cNumeric))
929 rb_raise(rb_eStandardError, "Add or multiply operation requires a single numeric argument");
930 }
931 } else nval = Qnil;
932 if (nval == Qnil) {
933 VALUE pval = MRPointerValueFromTrackInfo(ip->track, ip->doc, ip->num, -1);
934 MDPointer *pt = MDPointerFromMRPointerValue(pval);
935 int idx = -1;
936 n1 = 0;
937 theData = [NSMutableData dataWithLength: sizeof(short) * n2];
938 shortp = (short *)[theData mutableBytes];
939 while (MDPointerForwardWithPointSet(pt, pset, &idx) != NULL) {
940 shortp[n1] = NUM2INT(rb_yield(pval));
941 n1++;
942 }
943 [MyDocument modifyCodes: theData ofMultipleEventsAt: psobj forMDTrack: ip->track inDocument: ip->doc mode: MyDocumentModifySet];
944 return self;
945 } else if (rb_obj_is_kind_of(nval, rb_cNumeric)) {
946 if (mode == MyDocumentModifyMultiply)
947 theData = [NSNumber numberWithFloat: (float)NUM2DBL(rb_Float(nval))];
948 else
949 theData = [NSNumber numberWithInt: NUM2INT(rb_Integer(nval))];
950 [MyDocument modifyCodes: theData ofMultipleEventsAt: psobj forMDTrack: ip->track inDocument: ip->doc mode: mode];
951 return self;
952 } else {
953 int i;
954 nval = rb_ary_to_ary(nval);
955 n1 = (int)RARRAY_LEN(nval);
956 if (n1 == 0)
957 return self;
958 theData = [NSMutableData dataWithLength: sizeof(short) * n2];
959 shortp = (short *)[theData mutableBytes];
960 nvalp = RARRAY_PTR(nval);
961 for (i = 0; i < n1 && i < n2; i++) {
962 shortp[i] = NUM2INT(rb_Integer(nvalp[i]));
963 }
964 while (i < n2) {
965 shortp[i] = shortp[n1 - 1];
966 i++;
967 }
968 [MyDocument modifyCodes: theData ofMultipleEventsAt: psobj forMDTrack: ip->track inDocument: ip->doc mode: MyDocumentModifySet];
969 return self;
970 }
971 }
972
973 static VALUE
974 s_MREventSet_ModifyDataSub(int argc, VALUE *argv, VALUE self, int kind)
975 {
976 const MyDocumentTrackInfo *ip;
977 VALUE tval, nval, pval;
978 int i, n1, n2, n3, mode;
979 IntGroupObject *psobj;
980 IntGroup *pset;
981 id theData;
982 float *floatp;
983 VALUE *nvalp;
984 MDPointer *pt;
985 MDEvent *ep;
986 int idx;
987
988 tval = rb_ivar_get(self, s_ID_track);
989 if (tval == Qnil)
990 rb_raise(rb_eStandardError, "Track is not given");
991 ip = TrackInfoFromMRTrackValue(tval);
992 pset = IntGroupFromValue(self);
993 n2 = IntGroupGetCount(pset);
994 if (n2 == 0)
995 return self;
996 psobj = [[[IntGroupObject alloc] initWithMDPointSet: pset] autorelease];
997 mode = MyDocumentModifyAdd;
998 if (argc >= 1) {
999 nval = argv[0];
1000 if (rb_obj_is_kind_of(nval, rb_cString)) {
1001 if (argc == 1)
1002 rb_raise(rb_eStandardError, "Modify operation requires a single numeric argument");
1003 n1 = RSTRING_PTR(nval)[0];
1004 if (n1 == '=')
1005 mode = MyDocumentModifySet;
1006 else if (n1 == '*')
1007 mode = MyDocumentModifyMultiply;
1008 else if (n1 != '+')
1009 rb_raise(rb_eStandardError, "Modify operation should be either '=', '+' or '*'");
1010 nval = argv[1];
1011 if (mode != MyDocumentModifySet && !rb_obj_is_kind_of(nval, rb_cNumeric))
1012 rb_raise(rb_eStandardError, "Add or multiply operation requires a single numeric argument");
1013 }
1014 } else nval = Qnil;
1015
1016 pval = MRPointerValueFromTrackInfo(ip->track, ip->doc, ip->num, -1);
1017 pt = MDPointerFromMRPointerValue(pval);
1018 idx = -1;
1019
1020 if (kind < 0 || kind == kMDEventNull) {
1021 /* Specify the kind from the selected event */
1022 kind = -1;
1023 while ((ep = MDPointerForwardWithPointSet(pt, pset, &idx)) != NULL) {
1024 char name1[32], name2[32];
1025 if (kind == -1) {
1026 kind = MDGetKind(ep);
1027 MDEventToKindString(ep, name1, sizeof name1);
1028 } else if (kind != MDGetKind(ep)) {
1029 MDEventToKindString(ep, name2, sizeof name2);
1030 rb_raise(rb_eStandardError, "event at %d is of different kind (%s) from the first event (%s)", (int)MDPointerGetPosition(pt), name1, name2);
1031 }
1032 }
1033 }
1034 MDPointerSetPosition(pt, -1);
1035
1036 n1 = 0;
1037 if (nval == Qnil)
1038 n3 = 0; /* block */
1039 else if (rb_obj_is_kind_of(nval, rb_cString) || rb_obj_is_kind_of(nval, rb_cNumeric))
1040 n3 = 1; /* single value */
1041 else if (rb_obj_is_kind_of(nval, rb_cArray)) {
1042 n1 = (int)RARRAY_LEN(nval);
1043 nvalp = RARRAY_PTR(nval);
1044 if ((kind == kMDEventTimeSignature && n1 >= 2 && rb_obj_is_kind_of(nvalp[0], rb_cNumeric))
1045 || (kind == kMDEventSMPTE && n1 == 5 && rb_obj_is_kind_of(nvalp[0], rb_cNumeric))
1046 || (kind == kMDEventKey && n1 >= 2 && rb_obj_is_kind_of(nvalp[0], rb_cString) && rb_obj_is_kind_of(nvalp[1], rb_cNumeric)))
1047 n3 = 1;
1048 else n3 = 2; /* array */
1049 } else {
1050 nval = rb_ary_to_ary(nval);
1051 n1 = (int)RARRAY_LEN(nval);
1052 nvalp = RARRAY_PTR(nval);
1053 n3 = 2; /* array */
1054 }
1055
1056 if (n3 == 2 && n1 == 0)
1057 return self;
1058
1059 if (kind == kMDEventMetaText || kind == kMDEventMetaMessage || kind == kMDEventSysex ||
1060 kind == kMDEventSysexCont || kind == kMDEventSMPTE || kind == kMDEventTimeSignature ||
1061 kind == kMDEventKey) {
1062 ID mid = rb_intern("data=");
1063 idx = -1;
1064 i = 0;
1065 while (MDPointerForwardWithPointSet(pt, pset, &idx) != NULL) {
1066 VALUE dval;
1067 if (n3 == 0)
1068 dval = rb_yield(pval);
1069 else if (n3 == 2) {
1070 if (i < n1)
1071 dval = nvalp[i];
1072 else
1073 dval = nvalp[n1 - 1];
1074 }
1075 else dval = nval;
1076 rb_funcall(pval, mid, 1, dval);
1077 i++;
1078 }
1079 return self;
1080 }
1081
1082 if (n3 == 0) {
1083 idx = -1;
1084 i = 0;
1085 theData = [NSMutableData dataWithLength: sizeof(float) * n2];
1086 floatp = (float *)[theData mutableBytes];
1087 while (MDPointerForwardWithPointSet(pt, pset, &idx) != NULL) {
1088 floatp[i] = (float)NUM2DBL(rb_Float(rb_yield(pval)));
1089 i++;
1090 }
1091 [MyDocument modifyData: theData forEventKind: kind ofMultipleEventsAt: psobj forMDTrack: ip->track inDocument: ip->doc mode: MyDocumentModifySet];
1092 return self;
1093 } else if (n3 == 1) {
1094 theData = [NSNumber numberWithFloat: (float)NUM2DBL(rb_Float(nval))];
1095 [MyDocument modifyData: theData forEventKind: kind ofMultipleEventsAt: psobj forMDTrack: ip->track inDocument: ip->doc mode: mode];
1096 return self;
1097 } else {
1098 theData = [NSMutableData dataWithLength: sizeof(float) * n2];
1099 floatp = (float *)[theData mutableBytes];
1100 for (i = 0; i < n1 && i < n2; n1++) {
1101 floatp[i] = (float)NUM2DBL(rb_Float(nvalp[i]));
1102 }
1103 while (i < n2) {
1104 floatp[i] = floatp[n1 - 1];
1105 }
1106 [MyDocument modifyData: theData forEventKind: kind ofMultipleEventsAt: psobj forMDTrack: ip->track inDocument: ip->doc mode: MyDocumentModifySet];
1107 return self;
1108 }
1109 }
1110
1111 /*
1112 * call-seq:
1113 * MREventSet.modify_data(op, num) # op is either "=", "+", or "*"
1114 * MREventSet.modify_data(num) # same as ("+", num)
1115 * MREventSet.modify_data(array)
1116 * MREventSet.modify_data { |pt| }
1117 *
1118 * Modify the code of the specified events.
1119 * In the first form, the data are set, shift, or multiplied by the argument.
1120 * The second form is equivalent to modify_data("+", num) (i.e. shifted by the argument)
1121 * In the third form, the new data values are taken from the array.
1122 * (If the number of objects in the array is less than the number of events in the given set,
1123 * then the last value is repeated)
1124 * In the fourth form, the new data values are given by the block. The block arguments
1125 * are the event pointer (note: the same pointer will be reused for every iteration).
1126 */
1127 static VALUE
1128 s_MREventSet_ModifyData(int argc, VALUE *argv, VALUE self)
1129 {
1130 return s_MREventSet_ModifyDataSub(argc, argv, self, -1);
1131 }
1132
1133 /*
1134 * call-seq:
1135 * MREventSet.modify_velocity(op, num) # op is either "=", "+", or "*"
1136 * MREventSet.modify_velocity(num) # same as ("+", num)
1137 * MREventSet.modify_velocity(array)
1138 * MREventSet.modify_velocity { |pt| }
1139 *
1140 * Modify the velocities of the specified events. All specified events must be note events.
1141 * In the first form, the velocities are set, shift, or multiplied by the argument.
1142 * The second form is equivalent to modify_velocity("+", num) (i.e. shifted by the argument)
1143 * In the third form, the new velocity values are taken from the array.
1144 * (If the number of objects in the array is less than the number of events in the given set,
1145 * then the last value is repeated)
1146 * In the fourth form, the new velocity values are given by the block. The block arguments
1147 * are the event pointer (note: the same pointer will be reused for every iteration).
1148 */
1149 static VALUE
1150 s_MREventSet_ModifyVelocity(int argc, VALUE *argv, VALUE self)
1151 {
1152 return s_MREventSet_ModifyDataSub(argc, argv, self, kMDEventNote);
1153 }
1154
1155 /*
1156 * call-seq:
1157 * MREventSet.modify_release_velocity(op, num) # op is either "=", "+", or "*"
1158 * MREventSet.modify_release_velocity(num) # same as ("+", num)
1159 * MREventSet.modify_release_velocity(array)
1160 * MREventSet.modify_release_velocity { |pt| }
1161 *
1162 * Modify the release velocities of the specified events. All specified events must be note events.
1163 * In the first form, the release velocities are set, shift, or multiplied by the argument.
1164 * The second form is equivalent to modify_release_velocity("+", num) (i.e. shifted by the argument)
1165 * In the third form, the new release velocity values are taken from the array.
1166 * (If the number of objects in the array is less than the number of events in the given set,
1167 * then the last value is repeated)
1168 * In the fourth form, the new release velocity values are given by the block. The block arguments
1169 * are the event pointer (note: the same pointer will be reused for every iteration).
1170 */
1171 static VALUE
1172 s_MREventSet_ModifyReleaseVelocity(int argc, VALUE *argv, VALUE self)
1173 {
1174 return s_MREventSet_ModifyDataSub(argc, argv, self, kMDEventInternalNoteOff);
1175 }
1176
1177 /*
1178 * call-seq:
1179 * MREventSet.modify_duration(op, num) # op is either "=", "+", or "*"
1180 * MREventSet.modify_duration(num) # same as ("+", num)
1181 * MREventSet.modify_duration(array)
1182 * MREventSet.modify_duration { |pt| }
1183 *
1184 * Modify the duration of the specified events.
1185 * In the first form, the durations are set, shift, or multiplied by the argument.
1186 * The second form is equivalent to modify_duration("+", num) (i.e. shifted by the argument)
1187 * In the third form, the new duration values are taken from the array.
1188 * (If the number of objects in the array is less than the number of events in the given set,
1189 * then the last value is repeated)
1190 * In the fourth form, the new duration values are given by the block. The block arguments
1191 * are the event pointer (note: the same pointer will be reused for every iteration).
1192 */
1193 static VALUE
1194 s_MREventSet_ModifyDuration(int argc, VALUE *argv, VALUE self)
1195 {
1196 const MyDocumentTrackInfo *ip;
1197 VALUE tval, nval;
1198 int n1, n2, mode;
1199 IntGroupObject *psobj;
1200 IntGroup *pset;
1201 id theData;
1202 MDTickType *tickp;
1203 VALUE *nvalp;
1204 tval = rb_ivar_get(self, s_ID_track);
1205 if (tval == Qnil)
1206 rb_raise(rb_eStandardError, "Track is not given");
1207 ip = TrackInfoFromMRTrackValue(tval);
1208 pset = IntGroupFromValue(self);
1209 n2 = IntGroupGetCount(pset);
1210 if (n2 == 0)
1211 return self;
1212 psobj = [[[IntGroupObject alloc] initWithMDPointSet: pset] autorelease];
1213 mode = MyDocumentModifyAdd;
1214 if (argc >= 1) {
1215 nval = argv[0];
1216 if (rb_obj_is_kind_of(nval, rb_cString)) {
1217 if (argc == 1)
1218 rb_raise(rb_eStandardError, "Modify operation requires a single numeric argument");
1219 n1 = RSTRING_PTR(nval)[0];
1220 if (n1 == '=')
1221 mode = MyDocumentModifySet;
1222 else if (n1 == '*')
1223 mode = MyDocumentModifyMultiply;
1224 else if (n1 != '+')
1225 rb_raise(rb_eStandardError, "Modify operation should be either '=', '+' or '*'");
1226 nval = argv[1];
1227 if (mode != MyDocumentModifySet && !rb_obj_is_kind_of(nval, rb_cNumeric))
1228 rb_raise(rb_eStandardError, "Add or multiply operation requires a single numeric argument");
1229 }
1230 } else nval = Qnil;
1231 if (nval == Qnil) {
1232 VALUE pval = MRPointerValueFromTrackInfo(ip->track, ip->doc, ip->num, -1);
1233 MDPointer *pt = MDPointerFromMRPointerValue(pval);
1234 int idx = -1;
1235 n1 = 0;
1236 theData = [NSMutableData dataWithLength: sizeof(MDTickType) * n2];
1237 tickp = (MDTickType *)[theData mutableBytes];
1238 while (MDPointerForwardWithPointSet(pt, pset, &idx) != NULL) {
1239 tickp[n1] = NUM2INT(rb_yield(pval));
1240 n1++;
1241 }
1242 [MyDocument modifyDurations: theData ofMultipleEventsAt: psobj forMDTrack: ip->track inDocument: ip->doc mode: MyDocumentModifySet];
1243 return self;
1244 } else if (rb_obj_is_kind_of(nval, rb_cNumeric)) {
1245 if (mode == MyDocumentModifyMultiply)
1246 theData = [NSNumber numberWithFloat: (float)NUM2DBL(rb_Float(nval))];
1247 else
1248 theData = [NSNumber numberWithLong: (int32_t)(NUM2INT(rb_Integer(nval)))];
1249 [MyDocument modifyDurations: theData ofMultipleEventsAt: psobj forMDTrack: ip->track inDocument: ip->doc mode: mode];
1250 return self;
1251 } else {
1252 int i;
1253 nval = rb_ary_to_ary(nval);
1254 n1 = (int)RARRAY_LEN(nval);
1255 if (n1 == 0)
1256 return self;
1257 theData = [NSMutableData dataWithLength: sizeof(MDTickType) * n2];
1258 tickp = (MDTickType *)[theData mutableBytes];
1259 nvalp = RARRAY_PTR(nval);
1260 for (i = 0; i < n2 && i < n2; i++) {
1261 tickp[i] = NUM2INT(rb_Integer(nvalp[i]));
1262 }
1263 while (i < n2) {
1264 tickp[i] = tickp[n1 - 1];
1265 i++;
1266 }
1267 [MyDocument modifyDurations: theData ofMultipleEventsAt: psobj forMDTrack: ip->track inDocument: ip->doc mode: MyDocumentModifySet];
1268 return self;
1269 }
1270 }
1271
1272 #pragma mark ====== Class definition (external entry) ======
1273
1274 void
1275 MREventSetInitClass(void)
1276 {
1277 /* class MRPointSet */
1278 rb_cIntGroup = rb_define_class("PointSet", rb_cObject);
1279 rb_include_module(rb_cIntGroup, rb_mEnumerable);
1280 rb_define_alloc_func(rb_cIntGroup, MRPointSet_Alloc);
1281 rb_define_method(rb_cIntGroup, "clear", s_MRPointSet_Clear, 0);
1282 rb_define_method(rb_cIntGroup, "initialize", s_MRPointSet_Initialize, -1);
1283 rb_define_method(rb_cIntGroup, "initialize_copy", s_MRPointSet_InitializeCopy, 1);
1284 rb_define_method(rb_cIntGroup, "length", s_MRPointSet_Length, 0);
1285 rb_define_alias(rb_cIntGroup, "size", "length");
1286 rb_define_method(rb_cIntGroup, "member?", s_MRPointSet_MemberP, 1);
1287 rb_define_alias(rb_cIntGroup, "include?", "member?");
1288 rb_define_method(rb_cIntGroup, "each", s_MRPointSet_Each, 0);
1289 rb_define_method(rb_cIntGroup, "[]", s_MRPointSet_ElementAtIndex, 1);
1290 rb_define_method(rb_cIntGroup, "add", s_MRPointSet_Add, 1);
1291 rb_define_alias(rb_cIntGroup, "<<", "add");
1292 rb_define_method(rb_cIntGroup, "delete", s_MRPointSet_Delete, 1);
1293 rb_define_method(rb_cIntGroup, "reverse", s_MRPointSet_Reverse, 1);
1294 rb_define_method(rb_cIntGroup, "merge", s_MRPointSet_Add, 1);
1295 rb_define_method(rb_cIntGroup, "subtract", s_MRPointSet_Delete, 1);
1296 rb_define_method(rb_cIntGroup, "union", s_MRPointSet_Union, 1);
1297 rb_define_method(rb_cIntGroup, "difference", s_MRPointSet_Difference, 1);
1298 rb_define_method(rb_cIntGroup, "intersection", s_MRPointSet_Intersection, 1);
1299 rb_define_method(rb_cIntGroup, "sym_difference", s_MRPointSet_SymDifference, 1);
1300 rb_define_method(rb_cIntGroup, "convolute", s_MRPointSet_Convolute, 1);
1301 rb_define_method(rb_cIntGroup, "deconvolute", s_MRPointSet_Deconvolute, 1);
1302 rb_define_method(rb_cIntGroup, "offset", s_MRPointSet_Offset, 1);
1303 rb_define_alias(rb_cIntGroup, "+", "union");
1304 rb_define_alias(rb_cIntGroup, "|", "union");
1305 rb_define_alias(rb_cIntGroup, "-", "difference");
1306 rb_define_alias(rb_cIntGroup, "&", "intersection");
1307 rb_define_alias(rb_cIntGroup, "^", "sym_difference");
1308 rb_define_method(rb_cIntGroup, "range_at", s_MRPointSet_RangeAt, 1);
1309 rb_define_method(rb_cIntGroup, "inspect", s_MRPointSet_Inspect, 0);
1310 rb_define_alias(rb_cIntGroup, "to_s", "inspect");
1311 rb_define_singleton_method(rb_cIntGroup, "[]", s_MRPointSet_Create, -1);
1312
1313 /* Class MREventSet: it is an MREventSet with an associated Track */
1314 rb_cMREventSet = rb_define_class("EventSet", rb_cIntGroup);
1315 rb_define_method(rb_cMREventSet, "initialize", s_MREventSet_Initialize, -1);
1316 rb_define_method(rb_cMREventSet, "track", MREventSet_Track, 0);
1317 rb_define_method(rb_cMREventSet, "eot_selected", MREventSet_EOTSelected, 0);
1318 rb_define_method(rb_cMREventSet, "track=", MREventSet_SetTrack, 1);
1319 rb_define_method(rb_cMREventSet, "eot_selected=", MREventSet_SetEOTSelected, 1);
1320 rb_define_method(rb_cMREventSet, "each", s_MREventSet_Each, 0);
1321 rb_define_method(rb_cMREventSet, "reverse_each", s_MREventSet_ReverseEach, 0);
1322 rb_define_method(rb_cMREventSet, "each_with_index", s_MREventSet_EachWithIndex, 0);
1323 rb_define_method(rb_cMREventSet, "reverse_each_with_index", s_MREventSet_ReverseEachWithIndex, 0);
1324 rb_define_method(rb_cMREventSet, "select", s_MREventSet_Select, 0);
1325 rb_define_method(rb_cMREventSet, "reject!", s_MREventSet_Reject, 0);
1326 rb_define_method(rb_cMREventSet, "modify_tick", s_MREventSet_ModifyTick, -1);
1327 rb_define_method(rb_cMREventSet, "modify_code", s_MREventSet_ModifyCode, -1);
1328 rb_define_method(rb_cMREventSet, "modify_data", s_MREventSet_ModifyData, -1);
1329 rb_define_method(rb_cMREventSet, "modify_velocity", s_MREventSet_ModifyVelocity, -1);
1330 rb_define_method(rb_cMREventSet, "modify_release_velocity", s_MREventSet_ModifyReleaseVelocity, -1);
1331 rb_define_method(rb_cMREventSet, "modify_duration", s_MREventSet_ModifyDuration, -1);
1332
1333 s_ID_track = rb_intern("@track");
1334 s_ID_eot_selected = rb_intern("@eot_selected");
1335 }

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