Skip to content

Commit 6b16234

Browse files
committed
first draft
1 parent 5cbd049 commit 6b16234

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed

src/musicxml_massage_export.lua

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
function plugindef()
2+
finaleplugin.RequireSelection = false
3+
finaleplugin.NoStore = true
4+
finaleplugin.Author = "Robert Patterson"
5+
finaleplugin.Copyright = "CC0 https://creativecommons.org/publicdomain/zero/1.0/"
6+
finaleplugin.Version = "1.0"
7+
finaleplugin.Date = "September 24, 2024"
8+
finaleplugin.CategoryTags = "Document"
9+
finaleplugin.MinJWLuaVersion = 0.74
10+
finaleplugin.Notes = [[
11+
This script reads a musicxml file exported from the current open document and makes changes to
12+
improve the xml over what Finale produces. The best process is as follows:
13+
14+
1. Export the current open document as uncompressed MusicXML.
15+
2. Keeping your document open, run this plugin on the output *.musicxml document.
16+
3. Import the massaged *.musicxml into a different program.
17+
18+
Here is a list of some of the changes the script makes:
19+
20+
- 8va/8vb and 15ma/15mb symbols are extended to include the last note and extended left to include leading grace notes.
21+
]]
22+
return "Massage MusicXML...", "", "Massages the MusicXML for the current open document."
23+
end
24+
25+
local mixin = require("library.mixin")
26+
27+
local text_extension = ".musicxml"
28+
29+
function do_open_dialog(document)
30+
local path_name = finale.FCString()
31+
local file_name = finale.FCString()
32+
local file_path = finale.FCString()
33+
document:GetPath(file_path)
34+
file_path:SplitToPathAndFile(path_name, file_name)
35+
local full_file_name = file_name.LuaString
36+
local extension = mixin.FCMString()
37+
:SetLuaString(file_name.LuaString)
38+
:ExtractFileExtension()
39+
if extension.Length > 0 then
40+
file_name:TruncateAt(file_name:FindLast("." .. extension.LuaString))
41+
end
42+
file_name:AppendLuaString(text_extension)
43+
local open_dialog = mixin.FCMFileOpenDialog(finenv.UI())
44+
:SetWindowTitle(finale.FCString("Open MusicXML for " .. full_file_name))
45+
:AddFilter(finale.FCString("*" .. text_extension), finale.FCString("MusicXML File"))
46+
:SetInitFolder(path_name)
47+
:SetFileName(file_name)
48+
open_dialog:AssureFileExtension(text_extension)
49+
if not open_dialog:Execute() then
50+
return nil
51+
end
52+
local selected_file_name = finale.FCString()
53+
open_dialog:GetFileName(selected_file_name)
54+
return selected_file_name.LuaString
55+
end
56+
57+
function process_document(score_partwise)
58+
local doc_region = finale.FCMusicRegion()
59+
doc_region:SetFullDocument()
60+
-- Finale-exported musicxml files are score-partwise, as is the eachcell() function
61+
local xml_part = score_partwise:FirstChildElement("part")
62+
for staff in eachstaff(doc_region) do
63+
if not xml_part then
64+
error("No xml part element found for staff " .. staff .. ".")
65+
end
66+
local staff_region = finale.FCMusicRegion()
67+
staff_region:SetFullDocument()
68+
staff_region:SetStartStaff(staff)
69+
staff_region:SetEndStaff(staff)
70+
local xml_measure = xml_part:FirstChildElement("measure")
71+
for measure in eachcell(staff_region) do
72+
if not xml_measure or xml_measure:IntAttribute("number") ~= measure then
73+
error("No xml measure element found for measure " .. measure .. " in staff " .. staff .. ".")
74+
end
75+
print("staff", staff, "measure", measure)
76+
xml_measure = xml_measure:NextSiblingElement("measure")
77+
end
78+
xml_part = xml_part:NextSiblingElement("part")
79+
end
80+
end
81+
82+
function music_xml_massage_export()
83+
local documents = finale.FCDocuments()
84+
documents:LoadAll()
85+
local document = documents:FindCurrent()
86+
local xml_file = do_open_dialog(document)
87+
if not xml_file then
88+
return
89+
end
90+
local musicxml = tinyxml2.XMLDocument()
91+
local result = musicxml:LoadFile(xml_file)
92+
if result ~= tinyxml2.XML_SUCCESS then
93+
error("Unable to open " .. xml_file .. ".")
94+
return
95+
end
96+
local score_partwise = musicxml:FirstChildElement("score-partwise")
97+
if not score_partwise then
98+
error("File " .. xml_file .. " does not appear to be a Finale-exported MusicXML file.")
99+
end
100+
process_document(score_partwise)
101+
musicxml:SaveFile(xml_file)
102+
end
103+
104+
music_xml_massage_export()

0 commit comments

Comments
 (0)