forked from finale-lua/lua-scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscore.lua
More file actions
855 lines (716 loc) · 27.6 KB
/
score.lua
File metadata and controls
855 lines (716 loc) · 27.6 KB
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
--[[
$module Score
]] --
local library = require("library.general_library")
local configuration = require("library.configuration")
local measurement = require("library.measurement")
local config = {use_uppercase_staff_names = false, hide_default_whole_rests = false}
configuration.get_parameters("score.config.txt", config)
local score = {}
local CLEF_MAP = {treble = 0, alto = 1, tenor = 2, bass = 3, percussion = 12, grand_staff = {0, 3}, organ = {0, 3, 3}, treble_8ba = 5, tenor_voice = 5}
local BRACE_MAP = {
none = finale.GRBRAC_NONE,
plain = finale.GRBRAC_PLAIN,
chorus = finale.GRBRAC_CHORUS,
piano = finale.GRBRAC_PIANO,
reverse_chorus = finale.GRBRAC_REVERSECHORUS,
reverse_piano = finale.GRBRAC_REVERSEPIANO,
curved_chorus = finale.GRBRAC_CURVEDCHORUS,
reverse_curved_chorus = finale.GRBRAC_REVERSECURVEDCHORUS,
desk = finale.GRBRAC_DESK,
reverse_desk = finale.GRBRAC_REVERSEDESK,
}
local KEY_MAP = {} -- defined verbosely to be able to use "#" in key names
KEY_MAP.c = 0
KEY_MAP.g = -1
KEY_MAP.d = -2
KEY_MAP.a = -3
KEY_MAP.e = -4
KEY_MAP.b = -5
KEY_MAP["f#"] = -6
KEY_MAP["c#"] = -7
KEY_MAP["g#"] = -8
KEY_MAP["d#"] = -9
KEY_MAP["a#"] = -10
KEY_MAP["e#"] = -11
KEY_MAP["b#"] = -12
KEY_MAP.f = 1
KEY_MAP.bb = 2 -- Bb, just lowercase
KEY_MAP.eb = 3 -- Eb, just lowercase
KEY_MAP.ab = 4 -- Ab, just lowercase
KEY_MAP.db = 5 -- Db, just lowercase
KEY_MAP.gb = 6 -- Gb, just lowercase
KEY_MAP.cb = 7 -- Cb, just lowercase
KEY_MAP.fb = 8 -- Fb, just lowercase
local VOICE_INSTRUMENTS = {
finale.FFUUID_ALTOVOICE,
finale.FFUUID_BARITONEVOICE,
finale.FFUUID_BASSBAROTONEVOICE,
finale.FFUUID_BASSVOICE,
finale.FFUUID_BEATBOX,
finale.FFUUID_CHOIRAAHS,
finale.FFUUID_CHOIROOHS,
finale.FFUUID_CONTRALTOVOICE,
finale.FFUUID_COUNTERTENORVOICE,
finale.FFUUID_MEZZOSOPRANOVOICE,
finale.FFUUID_SOPRANOVOICE,
finale.FFUUID_TALKBOX,
finale.FFUUID_TENORVOICE,
finale.FFUUID_VOCALPERCUSSION,
finale.FFUUID_VOCALS,
finale.FFUUID_VOICE,
finale.FFUUID_YODEL
}
--[[
% create_default_config
Many of the "create ensemble" plugins use the same configuration. This function
creates that configuration object.
: (table) the configuration object
]]
function score.create_default_config()
local default_config = {
use_large_time_signatures = false,
use_large_measure_numbers = false,
use_keyless_staves = false,
show_default_whole_rests = true,
score_page_width = "8.5i",
score_page_height = "11i",
part_page_width = "8.5i",
part_page_height = "11i",
systems_per_page = 1,
max_measures_per_system = 0, -- 0 means "as many as possible"
large_measure_number_space = "14s",
}
configuration.get_parameters("score_create_new_score_defaults.config.txt", default_config)
return default_config
end
--[[
% delete_all_staves
Deletes all staves in the current document.
]]
function score.delete_all_staves()
local staves = finale.FCStaves()
staves:LoadAll()
for staff in each(staves) do
staff:DeleteData()
end
staves:SaveAll()
end
--[[
% reset_and_clear_score
Resets and clears the score to begin creating a new ensemble
]]
function score.reset_and_clear_score()
score.delete_all_staves()
end
--[[
% set_show_staff_time_signature
Sets whether or not to show the time signature on the staff.
@ staff_id (number) the staff_id for the staff
@ [show_time_signature] (boolean) whether or not to show the time signature, true if not specified
: (number) the staff_id for the staff
]]
function score.set_show_staff_time_signature(staff_id, show_time_signature)
local staff = finale.FCStaff()
staff:Load(staff_id)
if show_time_signature == nil then
staff.ShowScoreTimeSignatures = true
else
staff.ShowScoreTimeSignatures = show_time_signature
end
staff:Save()
return staff_id
end
--[[
% set_show_all_staves_time_signature
Sets whether or not to show the time signature on the staff.
@ [show_time_signature] (boolean) whether or not to show the time signature, true if not specified
]]
function score.set_show_all_staves_time_signature(show_time_signature)
local staves = finale.FCStaves()
staves:LoadAll()
for staff in each(staves) do
score.set_show_staff_time_signature(staff:GetItemNo(), show_time_signature)
end
end
--[[
% set_staff_transposition
Sets the transposition for a staff. Used for instruments that are not concert pitch (e.g., Bb Clarinet or F Horn)
@ staff_id (number) the staff_id for the staff
@ key (string) the key signature ("C", "F", "Bb", "C#" etc.)
@ interval (number) the interval number of steps to transpose the notes by
@ [clef] (string) the clef to set, "treble", "alto", "tenor", or "bass"
: (number) the staff_id for the staff
]]
function score.set_staff_transposition(staff_id, key, interval, clef)
local staff = finale.FCStaff()
staff:Load(staff_id)
staff.TransposeAlteration = KEY_MAP[key:lower()]
staff.TransposeInterval = interval or 0
if clef then
staff.TransposeClefIndex = CLEF_MAP[clef]
staff.TransposeUseClef = true
end
staff:Save()
return staff_id
end
--[[
% set_staff_allow_hiding
Sets whether the staff is allowed to hide when it is empty.
@ staff_id (number) the staff_id for the staff
@ [allow_hiding] (boolean) whether or not to allow the staff to hide, true if not specified
: (number) the staff_id for the staff
]]
function score.set_staff_allow_hiding(staff_id, allow_hiding)
local staff = finale.FCStaff()
staff:Load(staff_id)
staff.AllowHiding = allow_hiding or true
staff:Save()
return staff_id
end
--[[
% set_staff_keyless
Sets whether or not the staff is keyless.
@ staff_id (number) the staff_id for the staff
@ [is_keyless] (boolean) whether the staff is keyless, true if not specified
: (number) the staff_id for the staff
]]
function score.set_staff_keyless(staff_id, is_keyless)
local staff = finale.FCStaff()
staff:Load(staff_id)
staff.NoKeySigShowAccidentals = is_keyless or true
staff:Save()
return staff_id
end
--[[
% set_staff_keyless
Sets whether or not all staves are keyless.
@ [is_keyless] (boolean) whether the staff is keyless, true if not specified
]]
function score.set_all_staves_keyless(is_keyless)
local staves = finale.FCStaves()
staves:LoadAll()
for staff in each(staves) do
score.set_staff_keyless(staff:GetItemNo(), is_keyless)
end
end
--[[
% set_staff_show_default_whole_rests
Sets whether to show default whole rests on a particular staff.
@ staff_id (number) the staff_id for the staff
@ [show_whole_rests] (boolean) whether to show default whole rests, true if not specified
: (number) the staff_id for the staff
]]
function score.set_staff_show_default_whole_rests(staff_id, show_whole_rests)
local staff = finale.FCStaff()
staff:Load(staff_id)
staff:SetDisplayEmptyRests(show_whole_rests)
staff:Save()
return staff_id
end
--[[
% set_all_staves_show_default_whole_rests
Sets whether or not all staves show default whole rests.
@ [show_whole_rests] (boolean) whether to show default whole rests, true if not specified
]]
function score.set_all_staves_show_default_whole_rests(show_whole_rests)
local staves = finale.FCStaves()
staves:LoadAll()
for staff in each(staves) do
score.set_staff_show_default_whole_rests(staff:GetItemNo(), show_whole_rests)
end
end
--[[
% add_space_above_staff
This is the equivalent of "Add Vertical Space" in the Setup Wizard. It adds space above the staff as well as adds the staff to Staff List 1, which allows it to show tempo markings.
@ staff_id (number) the staff_id for the staff
: (number) the staff_id for the staff
]]
function score.add_space_above_staff(staff_id)
local lists = finale.FCStaffLists()
lists:SetMode(finale.SLMODE_CATEGORY_SCORE)
lists:LoadAll()
local list = lists:GetItemAt(0)
list:AddStaff(staff_id)
list:Save()
-- could be faster
local system_staves = finale.FCSystemStaves()
system_staves:LoadAllForItem(1)
for system_staff in each(system_staves) do
if system_staff.Staff == staff_id then
system_staff.Distance = system_staff.Distance + measurement.convert_to_EVPUs(tostring("6s"))
end
system_staff:Save()
end
end
--[[
% set_staff_full_name
Sets the full name for the staff.
If two instruments are on the same staff, this will also add the related numbers. For instance, if horn one and 2 are on the same staff, this will show Horn 1/2. `double` sets the first number. In this example, `double` should be `1` to show Horn 1/2. If the staff is for horn three and four, `double` should be `3`.
@ staff (FCStaff) the staff
@ full_name (string) the full name to set
@ [double] (number) the number of the first instrument if two instruments share the staff
]]
function score.set_staff_full_name(staff, full_name, double)
local str = finale.FCString()
if config.use_uppercase_staff_names then
str.LuaString = string.upper(full_name):gsub("%^FLAT%(%)", "^flat()")
else
str.LuaString = full_name
end
if (double ~= nil) then
str.LuaString = str.LuaString .. "^baseline(" .. measurement.convert_to_EVPUs("1s") .. ") " .. double ..
"\r^baseline(" .. measurement.convert_to_EVPUs("1s") .. ") " .. (double + 1)
end
staff:SaveNewFullNameString(str)
end
--[[
% set_staff_short_name
Sets the abbreviated name for the staff.
If two instruments are on the same staff, this will also add the related numbers. For instance, if horn one and 2 are on the same staff, this will show Horn 1/2. `double` sets the first number. In this example, `double` should be `1` to show Horn 1/2. If the staff is for horn three and four, `double` should be `3`.
@ staff (FCStaff) the staff
@ short_name (string) the abbreviated name to set
@ [double] (number) the number of the first instrument if two instruments share the staff
]]
function score.set_staff_short_name(staff, short_name, double)
local str = finale.FCString()
if config.use_uppercase_staff_names then
str.LuaString = string.upper(short_name):gsub("%^FLAT%(%)", "^flat()")
else
str.LuaString = short_name
end
if (double ~= nil) then
str.LuaString = str.LuaString .. "^baseline(" .. measurement.convert_to_EVPUs("1s") .. ") " .. double ..
"\r^baseline(" .. measurement.convert_to_EVPUs("1s") .. ") " .. (double + 1)
end
staff:SaveNewAbbreviatedNameString(str)
end
--[[
% create_staff
Creates a staff at the end of the score.
@ full_name (string) the abbreviated name
@ short_name (string) the abbreviated name
@ type (string) the `__FCStaffBase` type (e.g., finale.FFUUID_TRUMPETC)
@ clef (string) the clef for the staff (e.g., "treble", "bass", "tenor")
@ [double] (number) the number of the first instrument if two instruments share the staff
: (number) the staff_id for the new staff
]]
function score.create_staff(full_name, short_name, type, clef, double)
local staff_id = finale.FCStaves.Append()
if staff_id then
-- Load the created staff
local staff = finale.FCStaff()
staff:Load(staff_id)
staff.InstrumentUUID = type
staff:SetDefaultClef(CLEF_MAP[clef])
if config.hide_default_whole_rests then
staff:SetDisplayEmptyRests(false)
end
score.set_staff_full_name(staff, full_name, double)
score.set_staff_short_name(staff, short_name, double)
-- Save and return
staff:Save()
return staff:GetItemNo()
end
return -1
end
--[[
% create_staff_spaced
Creates a staff at the end of the score with a space above it. This is equivalent to using `score.create_staff` then `score.add_space_above_staff`.
@ full_name (string) the abbreviated name
@ short_name (string) the abbreviated name
@ type (string) the `__FCStaffBase` type (e.g., finale.FFUUID_TRUMPETC)
@ clef (string) the clef for the staff (e.g., "treble", "bass", "tenor")
@ [double] (number) the number of the first instrument if two instruments share the staff
: (number) the staff_id for the new staff
]]
function score.create_staff_spaced(full_name, short_name, type, clef)
local staff_id = score.create_staff(full_name, short_name, type, clef)
score.add_space_above_staff(staff_id)
return staff_id
end
--[[
% create_staff_percussion
Creates a percussion staff at the end of the score.
@ full_name (string) the abbreviated name
@ short_name (string) the abbreviated name
: (number) the staff_id for the new staff
]]
function score.create_staff_percussion(full_name, short_name)
local staff_id = score.create_staff(full_name, short_name, finale.FFUUID_PERCUSSIONGENERAL, "percussion")
local staff = finale.FCStaff()
staff:Load(staff_id)
staff:SetNotationStyle(finale.STAFFNOTATION_PERCUSSION)
staff:SavePercussionLayout(1, 0)
return staff_id
end
--[[
% create_group
Creates a percussion staff at the end of the score.
@ start_staff (number) the staff_id for the first staff
@ end_staff (number) the staff_id for the last staff
@ brace_name (string) the name for the brace (e.g., "none", "plain", "piano")
@ has_barline (boolean) whether or not barlines should continue through all staves in the group
@ level (number) the indentation level for the group bracket
@ [full_name] (string) the full name for the group
@ [short_name] (string) the abbreviated name for the group
]]
function score.create_group(start_staff, end_staff, brace_name, has_barline, level, full_name, short_name)
local sg_cmper = {}
local staff_groups = finale.FCGroups()
staff_groups:LoadAll()
for sg in each(staff_groups) do
table.insert(sg_cmper, sg:GetItemID())
end
table.sort(sg_cmper)
local sg = finale.FCGroup()
sg:SetStartStaff(start_staff)
sg:SetEndStaff(end_staff)
sg:SetStartMeasure(1)
sg:SetEndMeasure(32767)
sg:SetBracketStyle(BRACE_MAP[brace_name])
if start_staff == end_staff then
sg:SetBracketSingleStaff(true)
end
if (has_barline) then
sg:SetDrawBarlineMode(finale.GROUPBARLINESTYLE_THROUGH)
end
local bracket_position = -12 * level
if brace_name == "desk" then
bracket_position = bracket_position - 6
end
sg:SetBracketHorizontalPos(bracket_position)
-- names
if full_name then
local str = finale.FCString()
str.LuaString = full_name
sg:SaveNewFullNameBlock(str)
sg:SetShowGroupName(true)
sg:SetFullNameHorizontalOffset(measurement.convert_to_EVPUs("2s"))
end
if short_name then
local str = finale.FCString()
str.LuaString = short_name
sg:SaveNewAbbreviatedNameBlock(str)
sg:SetShowGroupName(true)
end
if sg_cmper[1] == nil then
sg:SaveNew(1)
else
local save_num = sg_cmper[1] + 1
sg:SaveNew(save_num)
end
end
--[[
% create_group_primary
Creates a primary group with the "curved_chorus" bracket.
@ start_staff (number) the staff_id for the first staff
@ end_staff (number) the staff_id for the last staff
@ [full_name] (string) the full name for the group
@ [short_name] (string) the abbreviated name for the group
]]
function score.create_group_primary(start_staff, end_staff, full_name, short_name)
score.create_group(start_staff, end_staff, "curved_chorus", true, 1, full_name, short_name)
end
--[[
% create_group_secondary
Creates a primary group with the "desk" bracket.
@ start_staff (number) the staff_id for the first staff
@ end_staff (number) the staff_id for the last staff
@ [full_name] (string) the full name for the group
@ [short_name] (string) the abbreviated name for the group
]]
function score.create_group_secondary(start_staff, end_staff, full_name, short_name)
score.create_group(start_staff, end_staff, "desk", false, 2, full_name, short_name)
end
--[[
% calc_system_scalings
_EXPERIMENTAL_
Calculates the system scaling to fit the desired number of systems on each page.
Currently produces the incorrect values. Should not be used in any production-ready
scripts.
@ systems_per_page (number) the number of systems that should fit on each page
: (number, number) the desired scaling factors—first_page_scaling, global_scaling
]]
function score.calc_system_scalings(systems_per_page)
local score_page_format_prefs = finale.FCPageFormatPrefs()
score_page_format_prefs:LoadScore()
local page_height = score_page_format_prefs:GetPageHeight()
local margin_top = score_page_format_prefs:GetLeftPageTopMargin()
local margin_bottom = score_page_format_prefs:GetLeftPageBottomMargin()
local available_height = page_height - margin_top - margin_bottom
local staff_systems = finale.FCStaffSystems()
staff_systems:LoadAll()
-- use first staff and not second in case second is not defined
local system = staff_systems:GetItemAt(0)
local first_system_height = system:CalcHeight(false)
-- update margins to use second system height
local system_height = first_system_height
system_height = system_height - score_page_format_prefs:GetFirstSystemTop()
system_height = system_height + score_page_format_prefs:GetSystemTop()
-- apply staff scaling
local staff_height = score_page_format_prefs:GetSystemStaffHeight() / 16
local staff_scaling = staff_height / measurement.convert_to_EVPUs("4s")
first_system_height = first_system_height * staff_scaling
system_height = system_height * staff_scaling
local total_systems_height = (system_height * (systems_per_page or 1))
local first_page_total_systems_height = first_system_height + total_systems_height - system_height
local global_scaling = available_height / total_systems_height
local first_page_scaling = available_height / first_page_total_systems_height
return math.floor(first_page_scaling * 100), math.floor(global_scaling * 100)
end
--[[
% set_global_system_scaling
Sets the system scaling for every system in the score.
@ scaling (number) the scaling factor
]]
function score.set_global_system_scaling(scaling)
local format = finale.FCPageFormatPrefs()
format:LoadScore()
format:SetSystemScaling(scaling)
format:Save()
local staff_systems = finale.FCStaffSystems()
staff_systems:LoadAll()
for system in each(staff_systems) do
system:SetResize(scaling)
system:Save()
end
finale.FCStaffSystems.UpdateFullLayout()
end
--[[
% set_global_system_scaling
Sets the system scaling for a specific system in the score.
@ system_number (number) the system number to set the scaling for
@ scaling (number) the scaling factor
]]
function score.set_single_system_scaling(system_number, scaling)
local staff_systems = finale.FCStaffSystems()
staff_systems:LoadAll()
local system = staff_systems:GetItemAt(system_number)
if system then
system:SetResize(scaling)
system:Save()
end
end
--[[
% set_large_time_signatures_settings
Updates the document settings for large time signatures.
]]
function score.set_large_time_signatures_settings()
local font_preferences = finale.FCFontPrefs()
font_preferences:Load(finale.FONTPREF_TIMESIG)
local font_info = font_preferences:CreateFontInfo()
font_info:SetSize(40)
font_info.Name = "EngraverTime"
font_preferences:SetFontInfo(font_info)
font_preferences:Save()
local distance_preferences = finale.FCDistancePrefs()
distance_preferences:Load(1)
distance_preferences:SetTimeSigBottomVertical(-290)
distance_preferences:Save()
end
--[[
% use_large_time_signatures
Sets the system scaling for a specific system in the score.
@ uses_large_time_signatures (boolean) the system number to set the scaling for
@ staves_with_time_signatures (table) a table where all values are the staff_id for every staff with a time signature
]]
function score.use_large_time_signatures(uses_large_time_signatures, staves_with_time_signatures)
if not uses_large_time_signatures then
return
end
score.set_large_time_signatures_settings()
score.set_show_all_staves_time_signature(false)
for _, staff_id in ipairs(staves_with_time_signatures) do
score.set_show_staff_time_signature(staff_id, true)
end
end
--[[
% use_large_measure_numbers
Adds large measure numbers below every measure in the score.
@ distance (string) the distance between the bottom staff and the measure numbers (e.g., "12s" for 12 spaces)
]]
function score.use_large_measure_numbers(distance)
local systems = finale.FCStaffSystem()
systems:Load(1)
local font_size = 0
for m in loadall(finale.FCMeasureNumberRegions()) do
m:SetUseScoreInfoForParts(false)
local font_preferences = finale.FCFontPrefs()
font_preferences:Load(finale.FONTPREF_MEASURENUMBER)
local font = font_preferences:CreateFontInfo()
m:SetMultipleFontInfo(font, false)
m:SetShowOnTopStaff(false, false)
m:SetShowOnSystemStart(false, false)
m:SetShowOnBottomStaff(true, false)
m:SetExcludeOtherStaves(true, false)
m:SetShowMultiples(true, false)
m:SetHideFirstNumber(false, false)
m:SetMultipleAlignment(finale.MNALIGN_CENTER, false)
m:SetMultipleJustification(finale.MNJUSTIFY_CENTER, false)
-- Sets the position in accordance to the system scaling
local position = -1 * measurement.convert_to_EVPUs(distance)
m:SetMultipleVerticalPosition(position, false)
m:Save()
font_size = font:GetSize()
end
-- extend bottom system margin to cover measure numbers if needed
local score_page_format_prefs = finale.FCPageFormatPrefs()
score_page_format_prefs:LoadScore()
local system_margin_bottom = score_page_format_prefs:GetSystemBottom()
local needed_margin = font_size * 4 + measurement.convert_to_EVPUs(distance)
if system_margin_bottom < needed_margin then
score_page_format_prefs:SetSystemBottom(needed_margin)
score_page_format_prefs:Save()
local staff_systems = finale.FCStaffSystems()
staff_systems:LoadAll()
for staff_system in each(staff_systems) do
staff_system:SetBottomMargin(needed_margin)
staff_system:Save()
end
end
end
--[[
% set_max_measures_per_system
Sets the maximum number of measures per system.
@ max_measures_per_system (number) maximum number of measures per system
]]
function score.set_max_measures_per_system(max_measures_per_system)
if max_measures_per_system == 0 then
return
end
local score_page_format_prefs = finale.FCPageFormatPrefs()
score_page_format_prefs:LoadScore()
local page_width = score_page_format_prefs:GetPageWidth()
local page_margin_left = score_page_format_prefs:GetLeftPageLeftMargin()
local page_margin_right = score_page_format_prefs:GetLeftPageRightMargin()
local system_width = page_width - page_margin_left - page_margin_right
local format = finale.FCPageFormatPrefs()
format:LoadScore()
local system_scaling = format:GetSystemScaling()
local scaled_system_width = system_width / (system_scaling / 100)
local music_spacing_preferences = finale.FCMusicSpacingPrefs()
music_spacing_preferences:Load(1)
music_spacing_preferences:SetMinMeasureWidth(scaled_system_width / max_measures_per_system)
music_spacing_preferences:Save()
end
--[[
% set_score_page_size
Sets the score page size.
@ width (string) the page height (e.g., "8.5i" for 8.5 inches)
@ height (string) the page width (e.g., "11i" for 11 inches)
]]
function score.set_score_page_size(width, height)
local score_page_format_prefs = finale.FCPageFormatPrefs()
score_page_format_prefs:LoadScore()
score_page_format_prefs.PageWidth = measurement.convert_to_EVPUs(width)
score_page_format_prefs.PageHeight = measurement.convert_to_EVPUs(height)
score_page_format_prefs:Save()
local pages = finale.FCPages()
pages:LoadAll()
for page in each(pages) do
page:SetWidth(measurement.convert_to_EVPUs(width))
page:SetHeight(measurement.convert_to_EVPUs(height))
end
pages:SaveAll()
end
--[[
% set_all_parts_page_size
Sets the page size for all parts.
@ width (string) the page height (e.g., "8.5i" for 8.5 inches)
@ height (string) the page width (e.g., "11i" for 11 inches)
]]
function score.set_all_parts_page_size(width, height)
local part_page_format_prefs = finale.FCPageFormatPrefs()
part_page_format_prefs:LoadParts()
part_page_format_prefs.PageWidth = measurement.convert_to_EVPUs(width)
part_page_format_prefs.PageHeight = measurement.convert_to_EVPUs(height)
part_page_format_prefs:Save()
local parts = finale.FCParts()
parts:LoadAll()
local pages = finale.FCPages()
for part in each(parts) do
part:SwitchTo()
if not part:IsScore() then
pages:LoadAll()
for page in each(pages) do
page:SetWidth(measurement.convert_to_EVPUs(width))
page:SetHeight(measurement.convert_to_EVPUs(height))
end
pages:SaveAll()
end
end
end
--[[
% apply_config
When creating an ensemble, this function is used to apply the configuration.
The inputted config file must have a all the fields in the default config file
(created with `score.create_default_config`).
The options field must contain the following items:
- `force_staves_show_time_signatures` (table) a table where all values are the staff_id for every staff with a time signature
used if `uses_large_time_signatures` is true
@ config (table) the config file
@ options (table) ensemble-specific options
]]
function score.apply_config(config, options) -- luacheck: ignore config
score.set_score_page_size(config.score_page_width, config.score_page_height)
score.set_all_parts_page_size(config.part_page_width, config.part_page_height)
library.update_layout()
score.set_all_staves_keyless(config.use_keyless_staves)
score.set_all_staves_show_default_whole_rests(config.show_default_whole_rests)
score.use_large_time_signatures(config.use_large_time_signatures, options.force_staves_show_time_signatures)
if config.use_large_measure_numbers then
score.use_large_measure_numbers(config.large_measure_number_space)
end
local first_page_scaling, global_scaling = score.calc_system_scalings(config.systems_per_page)
score.set_global_system_scaling(global_scaling)
for i = 0, config.systems_per_page - 1, 1 do
score.set_single_system_scaling(i, first_page_scaling)
end
score.set_max_measures_per_system(config.max_measures_per_system)
library.update_layout()
end
--[[
% calc_voice_staff
Determines whether the staff is a voice instrument.
@ staff_num (number) The number of the staff to check.
: (boolean) True if the staff is a voice instrument.
]]
function score.calc_voice_staff(staff_num)
local is_voice_staff = false
local staff = finale.FCStaff()
if staff:Load(staff_num) then
local staff_instrument = staff:GetInstrumentUUID()
for _, v in pairs(VOICE_INSTRUMENTS) do
if staff_instrument == v then
is_voice_staff = true
end
end
end
return is_voice_staff
end
--[[
% calc_has_optimized_systems()
Deterimines if this score contains optimized systems
: (boolean) True if an optimized system is found
]]
function score.calc_has_optimized_systems()
local staff_systems = finale.FCStaffSystems()
staff_systems:LoadAll()
local scroll_view = finale.FCSystemStaves()
scroll_view:LoadScrollView()
for staff_system in each(staff_systems) do
local next_system = finale.FCSystemStaves()
next_system:LoadAllForItem(staff_system.ItemNo)
if next_system.Count ~= scroll_view.Count then
return true
end
for staff_index = 0, next_system.Count - 1 do
if next_system:GetItemAt(staff_index).Staff ~= scroll_view:GetItemAt(staff_index).Staff then
return true
end
end
end
return false
end
return score