-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfull127_piano.lcb
executable file
·2504 lines (2323 loc) · 118 KB
/
full127_piano.lcb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/**
Widget is a virtual mouse piano
Description:
This widget allows for creation of scalable piano controls.
Note that this is a purely graphical control that produces no
sound on it's own. It is meant to be attached to a musical engine
such as a MIDI playback library.
------------------------------------------------------------------------------------------------------------------------------------
Name: noteOn
Type: message
Syntax: noteOn <pNoteNum>, <pNoteName>
OS: mac,ios,android,win
Platforms: desktop,mobile
Summary: Sent when a key on the piano set to it's 'on' state.
Example:
on noteOn pNoteNum,pNoteName
put "noteOn " & pNoteNum && pNoteName
end noteOn
Parameters:
pNoteNum: The MIDI note number(s) of the note key (exp. 63), this can be an item delimited list of multiple key numbers (chords)
pNoteName: The Name of the note key (exp. D#Eb), this can be an item delimited list of multiple key numbers (chords)
Description:
Handle the <noteOn> message in the widget's object script to respond to
'note down' clicks on the piano's individual note keys.
Name: noteOff
Type: message
Syntax: noteOff <pNoteNum>, <pNoteName>
OS: mac,ios,android,win
Platforms: desktop,mobile
Summary: Sent when a key on the piano released from it's 'on' state.
Example:
on noteOff pNoteNum,pNoteName
put "noteOff " & pNoteNum && pNoteName
end noteOff
Parameters:
pNoteNum:The MIDI note number(s) of the note key (exp. 63), this can be an item delimited list of multiple key numbers (chords)
pNoteName: The Name of the note key (exp. D#Eb), this can be an item delimited list of multiple key names (chords)
Description:
Handle the <noteOff> message in the widget's object script to respond to
'note release' messages from the piano's individual note keys.
------------------------------------------------------------------------------------------------------------------------------------
Name: borderWidth
Type: property
Syntax: set the borderWidth of <widget> to <number>
Syntax: get the borderWidth of <widget>
Summary: The stroke width for piano keys outlines
Description:
The <borderWidth> property controls thickness of lines used to draw the
widget's piano keys outlines.
Name: borderColor
Type: property
Syntax: get the borderColor of widget
Syntax: set the borderColor of widget to <color>
Summary: The color used to draw the outlinnes of the piano keys
Description:
The <borderColor> property controls the color used to draw the outlinnes of the piano keys.
------------------------------------------------------------------------------------------------------------------------------------
Name: accidentalsColor
Type: property
Synonyms: blackKeysColors
Syntax: set the accidentalsColor of <widget> to <color>
Syntax: get the accidentalsColor of <widget>
Summary: The fill color for accidentals (black) keys
Description:
The <accidentalsColor> property controls the default color used to fill
the piano's accidentals (black) keys. This property is the same as <blackKeysColors>
Name: blackKeysColor
Type: property
Synonyms: accidentalsColor
Syntax: set the blackKeysColor of <widget> to <color>
Syntax: get the blackKeysColor of <widget>
Summary: The fill color for accidentals (black) keys
Description:
The <blackKeysColor> property controls the default color used to fill
the piano's accidentals (black) keys. This property is the same as <accidentalsColor>
Name: whiteKeysColor
Type: property
Synonyms: naturalsColor
Syntax: set the whiteKeysColor of <widget> to <color>
Syntax: get the whiteKeysColor of <widget>
Summary: The fill color for naturals (white) keys
Description:
The <whiteKeysColor> property controls the default color used to fill
the piano's naturals (white) keys. This property is the same as <naturalsColor>
Name: naturalsColor
Type: property
Synonyms: whiteKeysColors
Syntax: set the naturalsColor of <widget> to <color>
Syntax: get the naturalsColor of <widget>
Summary: The fill color for naturals (white) keys
Description:
The <naturalsColor> property controls the default color used to fill
the piano's naturals (white) keys. This property is the same as <whiteKeysColors>
------------------------------------------------------------------------------------------------------------------------------------
Name: hiliteColor
Type: property
Syntax: set the hiliteColor of <widget> to <color>
Syntax: get the hiliteColor of <widget>
Summary: The fill color when piano keys are hilited
Description:
The <hiliteColor> property controls the color used to draw the
widget's piano key fill color while hilighted.
Name: colorNotes
Type: property
Syntax: set the colorNotes of <widget> to <pColorsSpaceNotesPairedLineList>
Syntax: get the colorNotes of <widget>
Example:
on mouseUp
-- clear all keys individual color settings:
set the colorNotes of widget "Piano Widget" to reset
-- set color white and 50% transparency for ALL C# keys, MIDI note 60, D#4 (same as Eb4), Gb 5th octave
-- and then also set color to 50% grey, no transparency, for all Ab/G# keys:
set the colorNotes of widget "Piano Widget" to "255,255,255,127 C#,60,D#4,F#Gb5" & \
cr & "127,127,127,255 G#"
put the colorNotes of widget "Piano Widget"
end mouseUp
Summary: The colorNotes piano keys as line list or colors and note pairs
Description:
The <colorNotes> property can be used to set colors for individual
piano keys using the format R,G,B,A followed by a comma delimited list
of keys, by MIDI note numbers or note names, seperated by a single space.
If a note name is used without an octave number then that note is colorized
on all 10.5 octaves. Set the <colorNotes> to empty, reset or pass an empty
string to clear all key colorization, reverting key colors to those
specified by the <accidentalsColor>/<blackKeysColor> and
<naturalsColor>/<whiteKeysColor> properties.
Multiple lines of color and note-lists can be set, any duplicates
will ovewrite previously set colorKeys.
The property returns a line delimited list of RGBA, blank space, with
a note number-list, followed by a space, and then the same note list
as note-names, for any keys that have been colorized.
Name: hilitedNotes
Type: property
Syntax: set the hilitedNotes of <widget> to <pHilightNotes>
Syntax: get the hilitedNotes of <widget>
Example:
on mouseUp
-- clear all
set the hilitedNotes of widget "Piano Widget" to empty
-- hilte ALL C# keys, MIDI note 60, D#4 (same as Eb4), Gb 5th octave:
set the hilitedNotes of widget "Piano Widget" to "C#,60,D#4,F#Gb5"
put the hilitedNotes of widget "Piano Widget"
end mouseUp
Summary: The hilighted piano keys as list of notes
Description:
The <hilitedNotes> property can be used to set the piano keys
to hilite using a comma seperated list of keys, by MIDI note number or note name.
If a note name is used without an octave number then that note is
hilited on all 10.5 octaves.
Set to empty or pass an empty string to clear all key hilites.
The property returns the list as two lines,
Line one lists MIDI note numbers and the second line list same keys as note names.
lockToTonicWithScale
Name: lockToTonicWithScale
Type: property
Syntax: set the lockToTonicWithScale of <widget> to <pRootAndScaleFormula>
Syntax: get the lockToTonicWithScale of <widget>
Example:
on mouseUp
-- clear any previously set scale:
set the lockToTonicWithScale of widget "Piano Widget" to empty
-- the following form locks to a scale of the C,C#,D#,E keys enabled:
set the lockToTonicWithScale of widget "Piano Widget" to "C 1,3,4"
-- the following form sets to a same scale of the C,C#,D#,E keys enabled:
set the lockToTonicWithScale of widget "Piano Widget" to "C H,W,h"
get the lockToTonicWithScale of widget "Piano Widget"
-- 'it' now contains "C,C#,D#,E"
end mouseUp
Summary: lockToTonicWithScale are the piano keys that are enabled or empty if no scale
Description:
The <lockToTonicWithScale> property can be set to Root Note as a NoteName followed
by a space and then by a comma delimited list of either numeric offsets,
between 1 and 11 that represent half-steps from the root note, or using the
style H,W,WH (case insenstive) often used to describe musical scales or modes.
H meaning Halfstep, W for Wholestep, and combining H and W for Halfstep+Wholestep.
Piano keys that will be enabled are then determine from this root + formula pair
and any keys that are not in the resulting note-name list will be locked.
Set <lockToTonicWithScale> to empty to clear the scale and unlock all piano keys.
Getting the <lockToTonicWithScale> returns a comma delimited list of notes in the
scale, rather than the formula used, or empty. This returned list can then be
used with the <lockToScale> property.
Name: lockToScale
Type: property
Syntax: set the lockToScale of <widget> to <pNoteNamesList>
Syntax: get the lockToScale of <widget>
Example:
on mouseUp
-- clear any previously set scale:
set the lockToScale of widget "Piano Widget" to empty
-- and then lock all piano keys that are NOT in the list of Note Names,
-- any octave number on the end of NoteNames will be ignored, and the full
-- Sharp AND Flat NoteName will appear in the returned list
set the lockToScale of widget "Piano Widget" to "C#,D#4,F#Gb,G#"
get the lockToScale of widget "Piano Widget"
-- 'it' now contains "C#Db,D#Eb,F#Gb,G#Ab"
end mouseUp
Summary: lockToScale are the piano keys that are enabled or empty if no scale
Description:
The <lockToScale> property can be set to a comma delimited list of Note Names
(ie C#,D,Eb,A#Bb,etc.) any piano keys with note names that are NOT in the list
will be disabled. Use this property to lock the Piano to a musical scale.
Get the lockToScale property to see a list of notes that are currently enabled.
If no scale has been applied then the property will contain empty.
Name: chordFormula
Type: property
Syntax: set the chordFormula of <widget> to <pChordFormula>
Syntax: get the chordFormula of <widget>
Example:
on mouseUp
-- keys will trigger a 1st-Inversion Major Triad Chord:
set the chordFormula of widget "Piano Widget" -5,-8
end mouseUp
Summary: Specifies additional keys that each key should trigger
Description:
The <chordFormula> property if optionally specified, can be set to a list
of integers to indicate which additional piano key(s) should be triggered
based on the half-step distance from the origin root key. For example,
to trigger the same note name as the root key but 1 octave lower set
this property to -12, for one octave lower and one octave higher set
this property to -12,12. To clear the current <chordFormula> set it to empty.
Name: chordPreset
Type: property
Syntax: set the chordPreset of <widget> to <pChordPresetName>
Example:
on mouseUp
-- the chordFormula will be set to "3,7":
set the chordPreset of widget "Piano Widget" to "Minor Triad"
end mouseUp
Summary: A name from a list of names of premade <chordFormula>
Description:
The <chordPreset> is a convience property that can be set to a chord
name from a list of premade named <chordFormula>. Use the <chordPresets>
property to retreive a line delimited list of valid chord names.
<chordPreset> is a "write-only" property, after a <chordPreset> name is passed
and the <chordFormula> is updated, this property is reset and returns "...".
Name: chordPresets
Type: property
Syntax: get the chordPresets of <widget>
Example:
on mouseUp
put the chordPresets of widget "Piano Widget"
end mouseUp
Summary: Line delimited list of preset names of premade <chordFormula>
Description:
Use the <chordPresets> property to retreive a line delimited list of
valid names to use in conjunction with the <chordPreset> property.
------------------------------------------------------------------------------------------------------------------------------------
Name: lowOctave
Type: property
Syntax: set the lowOctave of <widget> to <number>
Syntax: get the lowOctave of <widget>
Example:
on mouseUp
-- set the left most octave to start at MIDI Note Number 0 (C-1)
set the lowOctave of widget "Piano Widget" to -1
-- set the right most octave to start at MIDI Note Number 36 (C2)
set the highOctave of widget "Piano Widget" to 2
get the octaveCount of of widget "Piano Widget" -- octaveCount containss 4
end mouseUp
Summary: The starting, left most octave for the piano's visible note range
Description:
The <lowOctave> property is used in conjunction with <highOctave> to
specify the visible note range of the piano's keyboard by specifying the
starting octave and ending octave between -1 (which starts at MIDI note 0 C)
to 9 (Which starts at MIDI number 120 C and is actually 7/12th of an octave
ending at the MIDI Note 127 G). If lowOctave is greater than highOctave or
highOctave is less than lowOctave then the opposite property will
automatically be ajusted to match, resulting in a single octave range.
Name: highOctave
Type: property
Syntax: set the highOctave of <widget> to <number>
Syntax: get the highOctave of <widget>
Example:
on mouseUp
-- set the left most octave to start at MIDI Note Number 0 (C-1)
set the lowOctave of widget "Piano Widget" to -1
-- set the right most octave to start at MIDI Note Number 36 (C2)
set the highOctave of widget "Piano Widget" to 2
get the octaveCount of of widget "Piano Widget" -- octaveCount containss 4
end mouseUp
Summary: The ending, right most octave for the piano's visible note range
Description:
The <highOctave> property is used in conjunction with <lowOctave> to
specify the visible note range of the piano's keyboard by specifying the
starting octave and ending octave between -1 (which starts at MIDI note 0 C)
to 9 (Which starts at MIDI number 120 C and is actually 7/12th of an octave
ending at the MIDI Note 127 G). If lowOctave is greater than highOctave or
highOctave is less than lowOctave then the opposite property will
automatically be ajusted to match, resulting in a single octave range.
Name: octaveCount
Type: property
Syntax: get the octaveCount of <widget>
Example:
on mouseUp
-- set the left most octave to start at MIDI Note Number 0 (C-1)
set the lowOctave of widget "Piano Widget" to -1
-- set the right most octave to start at MIDI Note Number 36 (C2)
set the highOctave of widget "Piano Widget" to 2
get the octaveCount of of widget "Piano Widget" -- octaveCount containss 4
end mouseUp
Summary: The amount of octaves in the piano's current visible note range.
Description:
The <octaveCount> is a read-only property that returns the amount of
octaves that are currently visible on the Piano's keyboard. It is the
same as the count from <lowOctave> to <highOctave>.
*/
------------------------------------------------------------------------------------------------------------------------------------
widget org.openxtalk.widget.pianowidget
-- dependancy declarations
use com.livecode.canvas
use com.livecode.string
use com.livecode.char
use com.livecode.array
use com.livecode.list
use com.livecode.widget
use com.livecode.engine
use com.livecode.library.widgetutils
metadata title is "Piano Widget"
metadata author is "Paul McClernan, Bernd Niggemann"
metadata version is "1.3.7"
metadata preferredSize is "600,100"
metadata _ide is "true" -- ? default load at startup
metadata userVisible is "true" -- Show Widget in ... ?
metadata svgicon is "M0,0v69.6c0,1.4,1.1,2.5,2.4,2.5h9.7c0.8,0,1.5-0.4,2-1.1c0.4,0.7,1.1,1.1,2,1.1h9.8c0.8,0,1.5-0.4,1.9-1.1 c0.4,0.6,1.1,1.1,1.9,1.1h9.8c0.8,0,1.5-0.4,1.9-1.1c0.4,0.6,1.1,1.1,1.9,1.1h9.8c0.8,0,1.5-0.4,2-1.1c0.4,0.7,1.1,1.1,2,1.1h9.7 c0.8,0,1.5-0.4,1.9-1.1c0.4,0.6,1.1,1.1,1.9,1.1h9.7c0.8,0,1.5-0.4,1.9-1.1c0.4,0.6,1.1,1.1,1.9,1.1H94c1.3,0,2.4-1.1,2.4-2.5V0H0z M95.4,69.6c0,0.8-0.6,1.5-1.4,1.5h-9.8c-0.8,0-1.4-0.7-1.4-1.5V46.9h2.5c1,0,1.9-0.9,1.9-2V1h8.1L95.4,69.6z M80.4,71.1h-9.7 c-0.8,0-1.4-0.7-1.4-1.5V46.9h2.5c1,0,1.9-0.9,1.9-2V1h3.6v43.9c0,1.1,0.9,2,1.9,2h2.5v22.7C81.8,70.4,81.2,71.1,80.4,71.1z M57,71.1c-0.8,0-1.4-0.7-1.4-1.5V46.9h2.5c1,0,1.9-0.9,1.9-2V1h3.7v43.9c0,1.1,0.9,2,1.9,2h2.5v22.7c0,0.8-0.6,1.5-1.4,1.5 L57,71.1z M53.1,71.1h-9.8c-0.8,0-1.4-0.7-1.4-1.5V1H50v43.9c0,1.1,0.9,2,1.9,2h2.5v22.7C54.5,70.4,53.8,71.1,53.1,71.1z M28.3,69.6V46.9h2.5c1,0,1.9-0.9,1.9-2V1h8.1v68.6c0,0.8-0.6,1.5-1.4,1.5h-9.8C28.9,71.1,28.3,70.4,28.3,69.6z M14.7,69.6V46.9 h2.5c1,0,1.9-0.9,1.9-2V1h3.7v43.6l0,0v0.3c0,1.1,0.9,2,1.9,2h2.5v22.7c0,0.8-0.6,1.5-1.4,1.5H16C15.3,71.1,14.7,70.4,14.7,69.6z M12.1,71.1H2.4c-0.8,0-1.4-0.7-1.4-1.5V1h8.1v43.9c0,1.1,0.9,2,1.9,2h2.5v22.7C13.5,70.4,12.9,71.1,12.1,71.1z"
----------------------------------------------------------------------------------------------- Properties --------------------------------------------------------------------------------------
property SVGIconPath get GetIconSVGPath
metadata SVGIconPath.user_visible is "false"
private handler GetIconSVGPath() returns String
return "M0,0v69.6c0,1.4,1.1,2.5,2.4,2.5h9.7c0.8,0,1.5-0.4,2-1.1c0.4,0.7,1.1,1.1,2,1.1h9.8c0.8,0,1.5-0.4,1.9-1.1 c0.4,0.6,1.1,1.1,1.9,1.1h9.8c0.8,0,1.5-0.4,1.9-1.1c0.4,0.6,1.1,1.1,1.9,1.1h9.8c0.8,0,1.5-0.4,2-1.1c0.4,0.7,1.1,1.1,2,1.1h9.7 c0.8,0,1.5-0.4,1.9-1.1c0.4,0.6,1.1,1.1,1.9,1.1h9.7c0.8,0,1.5-0.4,1.9-1.1c0.4,0.6,1.1,1.1,1.9,1.1H94c1.3,0,2.4-1.1,2.4-2.5V0H0z M95.4,69.6c0,0.8-0.6,1.5-1.4,1.5h-9.8c-0.8,0-1.4-0.7-1.4-1.5V46.9h2.5c1,0,1.9-0.9,1.9-2V1h8.1L95.4,69.6z M80.4,71.1h-9.7 c-0.8,0-1.4-0.7-1.4-1.5V46.9h2.5c1,0,1.9-0.9,1.9-2V1h3.6v43.9c0,1.1,0.9,2,1.9,2h2.5v22.7C81.8,70.4,81.2,71.1,80.4,71.1z M57,71.1c-0.8,0-1.4-0.7-1.4-1.5V46.9h2.5c1,0,1.9-0.9,1.9-2V1h3.7v43.9c0,1.1,0.9,2,1.9,2h2.5v22.7c0,0.8-0.6,1.5-1.4,1.5 L57,71.1z M53.1,71.1h-9.8c-0.8,0-1.4-0.7-1.4-1.5V1H50v43.9c0,1.1,0.9,2,1.9,2h2.5v22.7C54.5,70.4,53.8,71.1,53.1,71.1z M28.3,69.6V46.9h2.5c1,0,1.9-0.9,1.9-2V1h8.1v68.6c0,0.8-0.6,1.5-1.4,1.5h-9.8C28.9,71.1,28.3,70.4,28.3,69.6z M14.7,69.6V46.9 h2.5c1,0,1.9-0.9,1.9-2V1h3.7v43.6l0,0v0.3c0,1.1,0.9,2,1.9,2h2.5v22.7c0,0.8-0.6,1.5-1.4,1.5H16C15.3,71.1,14.7,70.4,14.7,69.6z M12.1,71.1H2.4c-0.8,0-1.4-0.7-1.4-1.5V1h8.1v43.9c0,1.1,0.9,2,1.9,2h2.5v22.7C13.5,70.4,12.9,71.1,12.1,71.1z"
end handler
public handler getChromaticNumberForNoteName(in pKey as String) returns optional Number
variable tVarListA as List
variable tVarListB as List
variable tOffset as Number
put ["C","C#","C#Db","Db","D","D#","D#Eb","Eb","E","F","F#","F#Gb","Gb","G","G#","G#Ab","Ab","A","A#","A#Bb","Bb","B"] into tVarListA
put [1, 2, 2, 2, 3, 4, 4, 4, 5, 6, 7, 7, 7, 8, 9, 9, 9, 10, 11, 11, 11, 12 ] into tVarListB
put the index of pKey in tVarListA into tOffset
-- log tOffset
if tOffset > 0 then
return element tOffset of tVarListB
else
return -1
end if
end handler
-- constant kNoteNamesList is ["C","C#","C#Db","Db","D","D#","D#Eb","Eb","E","F","F#","F#Gb","Gb","G","G#","G#Ab","Ab","A","A#","A#Bb","Bb","B"]
property lockToTonicWithScale get mScaleNotes set setLockToTonicWithScale
metadata lockToTonicWithScale.user_visible is "false"
private handler setLockToTonicWithScale(pTonicAndScale as String) returns nothing
variable tTonicStr as String
variable tNotesStr as String
variable tScaleStr as String
variable tTonicAndScale as List
variable tScale as List
variable tScaleOffset as Number
variable tScaleOffsets as List
variable tScaleGoodStr as String
variable tRootNumber as Number
variable tCtr as Number
variable tOffset as Number
variable tNoteNamesList as List
variable tNoteValidNamesList as List
variable tNoteValidOffsetsStrList as List
variable tStepList as List
variable tStepValues as List
variable tStepValue as Number
variable tStepTotal as List
if pTonicAndScale is the empty string then
unlockAllPianoKeys()
else
split pTonicAndScale by " " into tTonicAndScale
put element 1 of tTonicAndScale into tTonicStr
put ["C","C#","C#Db","Db","D","D#","D#Eb","Eb","E","F","F#","F#Gb","Gb","G","G#","G#Ab","Ab","A","A#","A#Bb","Bb","B"] into tNoteValidNamesList
put ["1","2","3","4","5","6","7","8","9","10","11"] into tNoteValidOffsetsStrList
put ["C","C#Db","D","D#Eb","E","F","F#Gb","G","G#Ab","A","A#Bb","B"] into tNoteNamesList
put ["H","h", "W","w","HW","WH","hw","wh","WH","hW","Hw","3H","3h","2W","2w","4h","4h"] into tStepList
put [1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4] into tStepValues
if ( the index of tTonicStr in tNoteValidNamesList > 0 ) then
put element 2 of tTonicAndScale into tScaleStr
put getSharpOrFlatToSharpAndFlat(tTonicStr) into tTonicStr
put getChromaticNumberForNoteName(tTonicStr) into tRootNumber
-- log [tScaleStr,tTonicStr,tRootNumber]
put tTonicStr & "," into tScaleGoodStr
split tScaleStr by "," into tScale
if ((the index of (element 1 of tScale) in tStepList) > 0 ) then -- Do HalfSteps,WholeSteps formula
put 0 into tScaleOffset
repeat with tCtr from 1 up to (the number of elements in tScale)
put (the index of (element tCtr of tScale) in tStepList) into tOffset
if tOffset>0 then
put (element tOffset of tStepValues) into tStepValue
-- log tStepValue
put tScaleOffset + tStepValue into tScaleOffset
push tScaleOffset onto tScaleOffsets
end if
end repeat
else if ((the index of (element 1 of tScale) in tNoteValidOffsetsStrList) > 0 ) then
repeat with tCtr from 1 up to (the number of elements in tScale)
put (the index of (element tCtr of tScale) in tNoteValidOffsetsStrList) into tOffset
if tOffset>0 then
put ((element tOffset of tNoteValidOffsetsStrList) parsed as number) into tStepValue
push tStepValue onto tScaleOffsets
end if
end repeat
end if
if tScaleOffsets is not the empty list then
-- log tScaleGoodStr
repeat with tCtr from 1 up to (the number of elements in tScaleOffsets)
put tRootNumber+ (element tCtr of tScaleOffsets) into tOffset
repeat forever
if tOffset > 12 then
subtract 12 from tOffset
else
exit repeat
end if
end repeat
put element tOffset of tNoteNamesList into tNotesStr
put tNotesStr & "," after tScaleGoodStr
end repeat
-- log tScaleGoodStr
setLockedToScale(tScaleGoodStr)
end if
end if
end if
end handler
private handler getLockToTonicWithScale( ) returns String
getLockedToScale()
return mScaleNotes
end handler
private handler unlockAllPianoKeys()
variable tOctave as Array
variable tBlackKeysList as List
variable tBlackKey as Array
variable tWhiteKeysList as List
variable tWhiteKey as Array
variable tKeyIteration as Number
variable tOctaveIteration as Number
repeat with tOctaveIteration from 1 up to 11
put element tOctaveIteration of mOctaveList into tOctave
put tOctave["OctaveBlackKeysList"] into tBlackKeysList
repeat with tKeyIteration from 1 up to 5
put element tKeyIteration of tBlackKeysList into tBlackKey
if tBlackKey["KeyNumber"] <128 then
put false into tBlackKey["keyLocked"]
put tBlackKey into element tKeyIteration of tBlackKeysList
end if
end repeat
put tBlackKeysList into tOctave["OctaveBlackKeysList"]
put tOctave["OctaveWhiteKeysList"] into tWhiteKeysList
repeat with tKeyIteration from 1 up to 7
put element tKeyIteration of tWhiteKeysList into tWhiteKey
if tWhiteKey["KeyNumber"] <128 then
put false into tWhiteKey["keyLocked"]
put tWhiteKey into element tKeyIteration of tWhiteKeysList
end if
end repeat
put tWhiteKeysList into tOctave["OctaveWhiteKeysList"]
put tOctave into element tOctaveIteration of mOctaveList
end repeat
put "" into mScaleNotes
end handler
property lockToScale get getLockedToScale set setLockedToScale
metadata lockToScale.user_visible is "true"
private variable mScaleNotes as String
private handler setLockedToScale(pScaleNotes as String) returns nothing
variable tOctave as Array
variable tBlackKeysList as List
variable tBlackKey as Array
variable tWhiteKeysList as List
variable tWhiteKey as Array
variable tNumStr as String
variable tKeysList as List
variable tKey as optional any
variable tKeyIteration as Number
variable tOctaveIteration as Number
setHilitedNotes("") --- Clear hilities first so that there is no keys stuck on hilited
if pScaleNotes is the empty string then
unlockAllPianoKeys()
else
------------------------------------------------------------------------ Set All Locked First ------------------------------------------------------------------------
repeat with tOctaveIteration from 1 up to 11
put element tOctaveIteration of mOctaveList into tOctave
put tOctave["OctaveBlackKeysList"] into tBlackKeysList
repeat with tKeyIteration from 1 up to 5
put element tKeyIteration of tBlackKeysList into tBlackKey
if tBlackKey["KeyNumber"] <128 then
put true into tBlackKey["keyLocked"]
put tBlackKey into element tKeyIteration of tBlackKeysList
end if
end repeat
put tBlackKeysList into tOctave["OctaveBlackKeysList"]
put tOctave["OctaveWhiteKeysList"] into tWhiteKeysList
repeat with tKeyIteration from 1 up to 7
put element tKeyIteration of tWhiteKeysList into tWhiteKey
if tWhiteKey["KeyNumber"] <128 then
put true into tWhiteKey["keyLocked"]
put tWhiteKey into element tKeyIteration of tWhiteKeysList
end if
end repeat
put tWhiteKeysList into tOctave["OctaveWhiteKeysList"]
put tOctave into element tOctaveIteration of mOctaveList
end repeat
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
split pScaleNotes by "," into tKeysList
put "" into pScaleNotes
repeat for each element tKey in tKeysList
--- check if it's a sharp without flat or flat without sharp
if tKey parsed as number is not nothing then
next repeat
end if
if the number of chars in tKey > 1 then
if ((char 2 of tKey is "#") and (the number of chars in tKey < 4)) or (char 2 of tKey is "b") then
if (char -1 of tKey) parsed as number is not nothing then
repeat forever
if the last char of tKey is in "-012356789" then
delete the last char of tKey
else
exit repeat
end if
end repeat
end if
put getSharpOrFlatToSharpAndFlat(tKey) into tKey
put tKey & tNumStr into tKey
end if
end if
put tKey &"," after pScaleNotes
repeat with tOctaveIteration from 1 up to 11
put element tOctaveIteration of mOctaveList into tOctave
put tOctave["OctaveBlackKeysList"] into tBlackKeysList
repeat with tKeyIteration from 1 up to 5
put element tKeyIteration of tBlackKeysList into tBlackKey
if tBlackKey["KeyNumber"] >127 then
exit repeat
end if
if tBlackKey["KeyName"] is tKey then
put false into tBlackKey["keyLocked"]
put tBlackKey into element tKeyIteration of tBlackKeysList
end if
end repeat
put tBlackKeysList into tOctave["OctaveBlackKeysList"]
put tOctave["OctaveWhiteKeysList"] into tWhiteKeysList
repeat with tKeyIteration from 1 up to 7
put element tKeyIteration of tWhiteKeysList into tWhiteKey
if tWhiteKey["KeyNumber"] >127 then
exit repeat
end if
if tWhiteKey["KeyName"] is tKey then
put false into tWhiteKey["keyLocked"]
put tWhiteKey into element tKeyIteration of tWhiteKeysList
end if
end repeat
put tWhiteKeysList into tOctave["OctaveWhiteKeysList"]
put tOctave into element tOctaveIteration of mOctaveList
end repeat
end repeat
if the number of chars in pScaleNotes >1 then
delete the last char of pScaleNotes
end if
put pScaleNotes into mScaleNotes
end if
redraw all
end handler
private handler getLockedToScale() returns String
variable tScaleNotesList as List
variable tScaleNotesNewList as List
variable tScaleNote as String
variable tCtr as Number
put the empty list into tScaleNotesNewList
split mScaleNotes by "," into tScaleNotesList
repeat for each element tScaleNote in tScaleNotesList
if ((the index of (tScaleNote) in tScaleNotesNewList) > 0 ) then
-- if mScaleNote is among the elements of mScaleNotesNewList then
next repeat
else
push tScaleNote onto tScaleNotesNewList
end if
end repeat
combine tScaleNotesNewList with "," into mScaleNotes
return mScaleNotes
end handler
property hilitedNotesRefresh get getHilitedNotesRefresh set setHilitedNotesRefresh
-- metadata hilitedNotes.user_visible is "false"
private variable mHilitedNotesRefresh as Boolean
private handler setHilitedNotesRefresh(in pBool as Boolean) returns nothing
put pBool into mHilitedNotesRefresh
if mHilitedNotesRefresh then
redraw all
end if
end handler
private handler getHilitedNotesRefresh() returns Boolean
return mHilitedNotesRefresh
end handler
property hilitedNotes get getHilitedNotes set setHilitedNotes
metadata hilitedNotes.user_visible is "false"
private variable mHilitedNotes as String
private handler setHilitedNotes(pHilightNotes as String) returns nothing
variable tOctave as Array
variable tBlackKeysList as List
variable tBlackKey as Array
variable tWhiteKeysList as List
variable tWhiteKey as Array
variable tNumStr as String
variable tKeysList as List
variable tKey as optional any
variable tKeyIteration as Number
variable tOctaveIteration as Number
------------------------------------------------------------------------ Clear All Hilights First ------------------------------------------------------------------------
repeat with tOctaveIteration from 1 up to 11
put element tOctaveIteration of mOctaveList into tOctave
put tOctave["OctaveBlackKeysList"] into tBlackKeysList
repeat with tKeyIteration from 1 up to 5
put element tKeyIteration of tBlackKeysList into tBlackKey
put false into tBlackKey["KeyHilited"]
put tBlackKey into element tKeyIteration of tBlackKeysList
end repeat
put tBlackKeysList into tOctave["OctaveBlackKeysList"]
put tOctave["OctaveWhiteKeysList"] into tWhiteKeysList
repeat with tKeyIteration from 1 up to 7
put element tKeyIteration of tWhiteKeysList into tWhiteKey
put false into tWhiteKey["KeyHilited"]
put tWhiteKey into element tKeyIteration of tWhiteKeysList
end repeat
put tWhiteKeysList into tOctave["OctaveWhiteKeysList"]
put tOctave into element tOctaveIteration of mOctaveList
end repeat
-- redraw all
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
split pHilightNotes by "," into tKeysList
repeat for each element tKey in tKeysList
--- check if it's a sharp without flat or flat
if the number of chars in tKey > 1 then
if ((char 2 of tKey is "#") and (the number of chars in tKey < 4)) or (char 2 of tKey is "b") then
if (char -1 of tKey) parsed as number is not nothing then
repeat forever
if the last char of tKey is in "-012356789" then
put the last char of tKey before tNumStr
delete the last char of tKey
else
exit repeat
end if
end repeat
end if
put getSharpOrFlatToSharpAndFlat(tKey) into tKey
put tKey & tNumStr into tKey
end if
end if
repeat with tOctaveIteration from 1 up to 11
put element tOctaveIteration of mOctaveList into tOctave
put tOctave["OctaveBlackKeysList"] into tBlackKeysList
repeat with tKeyIteration from 1 up to 5
put element tKeyIteration of tBlackKeysList into tBlackKey
if tBlackKey["KeyName"] is tKey then
put true into tBlackKey["KeyHilited"]
put tBlackKey into element tKeyIteration of tBlackKeysList
else if (tBlackKey["KeyName"] & tOctave["OctaveName"]) is tKey then
put true into tBlackKey["KeyHilited"]
put tBlackKey into element tKeyIteration of tBlackKeysList
else if tBlackKey["KeyNumber"] is tKey parsed as number then
put true into tBlackKey["KeyHilited"]
put tBlackKey into element tKeyIteration of tBlackKeysList
end if
end repeat
put tBlackKeysList into tOctave["OctaveBlackKeysList"]
put tOctave["OctaveWhiteKeysList"] into tWhiteKeysList
repeat with tKeyIteration from 1 up to 7
put element tKeyIteration of tWhiteKeysList into tWhiteKey
if tWhiteKey["KeyName"] is tKey then
put true into tWhiteKey["KeyHilited"]
put tWhiteKey into element tKeyIteration of tWhiteKeysList
else if tWhiteKey["KeyName"] & tOctave["OctaveName"] is tKey then
put true into tWhiteKey["KeyHilited"]
put tWhiteKey into element tKeyIteration of tWhiteKeysList
else if tWhiteKey["KeyNumber"] is tKey parsed as number then
put true into tWhiteKey["KeyHilited"]
put tWhiteKey into element tKeyIteration of tWhiteKeysList
end if
end repeat
put tWhiteKeysList into tOctave["OctaveWhiteKeysList"]
put tOctave into element tOctaveIteration of mOctaveList
end repeat
end repeat
if mHilitedNotesRefresh then
redraw all
end if
end handler
property addHilitedNotes get getAddHilitedNotes set setAddHilitedNotes
metadata addHilitedNotes.user_visible is "false"
private handler setAddHilitedNotes(in pHilightNotes as String) returns nothing
variable tOctave as Array
variable tBlackKeysList as List
variable tBlackKey as Array
variable tWhiteKeysList as List
variable tWhiteKey as Array
variable tNumStr as String
variable tKeysList as List
variable tKey as optional any
variable tKeyIteration as Number
variable tOctaveIteration as Number
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
split pHilightNotes by "," into tKeysList
repeat for each element tKey in tKeysList
--- add check if its a number first then do different lookup
--- check if it's a sharp without flat or flat
if the number of chars in tKey > 1 then
if ((char 2 of tKey is "#") and (the number of chars in tKey < 4)) or (char 2 of tKey is "b") then
if (char -1 of tKey) parsed as number is not nothing then
repeat forever
if the last char of tKey is in "-012356789" then
put the last char of tKey before tNumStr
delete the last char of tKey
else
exit repeat
end if
end repeat
end if
put getSharpOrFlatToSharpAndFlat(tKey) into tKey
put tKey & tNumStr into tKey
end if
end if
repeat with tOctaveIteration from 1 up to 11
put element tOctaveIteration of mOctaveList into tOctave
put tOctave["OctaveBlackKeysList"] into tBlackKeysList
repeat with tKeyIteration from 1 up to 5
put element tKeyIteration of tBlackKeysList into tBlackKey
if tBlackKey["KeyName"] is tKey then
put true into tBlackKey["KeyHilited"]
put tBlackKey into element tKeyIteration of tBlackKeysList
else if (tBlackKey["KeyName"] & tOctave["OctaveName"]) is tKey then
put true into tBlackKey["KeyHilited"]
put tBlackKey into element tKeyIteration of tBlackKeysList
else if tBlackKey["KeyNumber"] is tKey parsed as number then
put true into tBlackKey["KeyHilited"]
put tBlackKey into element tKeyIteration of tBlackKeysList
end if
end repeat
put tBlackKeysList into tOctave["OctaveBlackKeysList"]
put tOctave["OctaveWhiteKeysList"] into tWhiteKeysList
repeat with tKeyIteration from 1 up to 7
put element tKeyIteration of tWhiteKeysList into tWhiteKey
if tWhiteKey["KeyName"] is tKey then
put true into tWhiteKey["KeyHilited"]
put tWhiteKey into element tKeyIteration of tWhiteKeysList
else if tWhiteKey["KeyName"] & tOctave["OctaveName"] is tKey then
put true into tWhiteKey["KeyHilited"]
put tWhiteKey into element tKeyIteration of tWhiteKeysList
else if tWhiteKey["KeyNumber"] is tKey parsed as number then
put true into tWhiteKey["KeyHilited"]
put tWhiteKey into element tKeyIteration of tWhiteKeysList
end if
end repeat
put tWhiteKeysList into tOctave["OctaveWhiteKeysList"]
put tOctave into element tOctaveIteration of mOctaveList
end repeat
end repeat
if mHilitedNotesRefresh then
redraw all
end if
end handler
private handler getAddHilitedNotes() returns any
return nothing
end handler
property unhiliteNotes get getUnhiliteNotes set setUnhiliteNotes
metadata uhiliteNotes.user_visible is "false"
private handler setUnhiliteNotes(in pHilightNotes as optional String) returns nothing
variable tOctave as Array
variable tBlackKeysList as List
variable tBlackKey as Array
variable tWhiteKeysList as List
variable tWhiteKey as Array
variable tNumStr as String
variable tKeysList as List
variable tKey as optional any
variable tKeyIteration as Number
variable tOctaveIteration as Number
if pHilightNotes is not nothing and pHilightNotes is not the empty string then
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
split pHilightNotes by "," into tKeysList
repeat for each element tKey in tKeysList
--- add check if its a number first then do different lookup
--- check if it's a sharp without flat or flat
if the number of chars in tKey > 1 then
if ((char 2 of tKey is "#") and (the number of chars in tKey < 4)) or (char 2 of tKey is "b") then
if (char -1 of tKey) parsed as number is not nothing then
repeat forever
if the last char of tKey is in "-012356789" then
put the last char of tKey before tNumStr
delete the last char of tKey
else
exit repeat
end if
end repeat
end if
put getSharpOrFlatToSharpAndFlat(tKey) into tKey
put tKey & tNumStr into tKey
end if
end if
repeat with tOctaveIteration from 1 up to 11
put element tOctaveIteration of mOctaveList into tOctave
put tOctave["OctaveBlackKeysList"] into tBlackKeysList
repeat with tKeyIteration from 1 up to 5
put element tKeyIteration of tBlackKeysList into tBlackKey
if tBlackKey["KeyName"] is tKey then
put false into tBlackKey["KeyHilited"]
put tBlackKey into element tKeyIteration of tBlackKeysList
else if (tBlackKey["KeyName"] & tOctave["OctaveName"]) is tKey then
put false into tBlackKey["KeyHilited"]
put tBlackKey into element tKeyIteration of tBlackKeysList
else if tBlackKey["KeyNumber"] is tKey parsed as number then
put false into tBlackKey["KeyHilited"]
put tBlackKey into element tKeyIteration of tBlackKeysList
end if
end repeat
put tBlackKeysList into tOctave["OctaveBlackKeysList"]
put tOctave["OctaveWhiteKeysList"] into tWhiteKeysList
repeat with tKeyIteration from 1 up to 7
put element tKeyIteration of tWhiteKeysList into tWhiteKey
if tWhiteKey["KeyName"] is tKey then
put false into tWhiteKey["KeyHilited"]
put tWhiteKey into element tKeyIteration of tWhiteKeysList
else if tWhiteKey["KeyName"] & tOctave["OctaveName"] is tKey then
put false into tWhiteKey["KeyHilited"]
put tWhiteKey into element tKeyIteration of tWhiteKeysList
else if tWhiteKey["KeyNumber"] is tKey parsed as number then
put false into tWhiteKey["KeyHilited"]
put tWhiteKey into element tKeyIteration of tWhiteKeysList
end if
end repeat
put tWhiteKeysList into tOctave["OctaveWhiteKeysList"]
put tOctave into element tOctaveIteration of mOctaveList
end repeat
end repeat
if mHilitedNotesRefresh then
redraw all
end if
end if
end handler
private handler getUnhiliteNotes() returns any
return nothing
end handler
private handler getHilitedNotes() returns String
variable tOctave as Array
variable tBlackKeysList as List
variable tBlackKey as Array
variable tWhiteKeysList as List
variable tWhiteKey as Array
variable tPath as Path
variable tNamesString as String
variable tNoteNumsString as String
variable tOctaveIteration as Number
put "" into tNamesString
put "" into tNoteNumsString
repeat with tOctaveIteration from 1 up to 11
put element (tOctaveIteration) of mOctaveList into tOctave
put tOctave["OctaveBlackKeysList"] into tBlackKeysList
repeat for each element tBlackKey in tBlackKeysList
if tBlackKey["KeyHilited"] is true then
put tBlackKey["KeyNumber"] formatted as string & "," after tNoteNumsString
put tBlackKey["KeyName"] & tOctave["OctaveName"] & "," after tNamesString
end if
end repeat
put tOctave["OctaveWhiteKeysList"] into tWhiteKeysList
repeat for each element tWhiteKey in tWhiteKeysList
if tWhiteKey["KeyHilited"] is true then
put tWhiteKey["KeyNumber"] formatted as string & "," after tNoteNumsString
put tWhiteKey["KeyName"] & tOctave["OctaveName"] & "," after tNamesString
end if
end repeat
end repeat
if tNamesString is not the empty string then
if the last char of tNamesString is "," then