Skip to content

Commit cc96543

Browse files
committed
working better
1 parent 8be4c1b commit cc96543

File tree

1 file changed

+65
-17
lines changed

1 file changed

+65
-17
lines changed

src/musicxml_massage_export.lua

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
function plugindef()
2+
finaleplugin.RequireDocument = false
23
finaleplugin.RequireSelection = false
34
finaleplugin.NoStore = true
45
finaleplugin.Author = "Robert Patterson"
@@ -8,24 +9,55 @@ function plugindef()
89
finaleplugin.CategoryTags = "Document"
910
finaleplugin.MinJWLuaVersion = 0.74
1011
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:
12+
This script reads a musicxml file exported from Finale and makes modifies it to
13+
improve the importing into Dorico or MuseScore. The best process is as follows:
1314
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.
15+
1. Export your document as uncompressed MusicXML.
16+
2. Run this plugin on the output *.musicxml document.
17+
3. The massaged file name has " massaged" appended to the file name.
18+
3. Import the massaged *.musicxml into Dorico or MuseScore.
1719
1820
Here is a list of some of the changes the script makes:
1921
2022
- 8va/8vb and 15ma/15mb symbols are extended to include the last note and extended left to include leading grace notes.
23+
24+
Due to a limitation in the xml parser, all xml processing instructions are removed. These are metadata that neither
25+
Dorico nor MuseScore use, so their removal should not affect importing into those programs.
2126
]]
2227
return "Massage MusicXML...", "", "Massages the MusicXML for the current open document."
2328
end
2429

25-
local mixin = require("library.mixin")
26-
2730
local text_extension = ".musicxml"
2831

32+
local function remove_processing_instructions(file_path)
33+
-- Open the original file for reading
34+
local input_file <close> = io.open(file_path, "r")
35+
if not input_file then
36+
error("Cannot open file: " .. file_path)
37+
end
38+
-- Read the contents of the file
39+
local lines = {}
40+
for line in input_file:lines() do
41+
-- Keep the XML declaration (<?xml ... ?>), remove other processing instructions (<?...?>)
42+
if line:match("^%s*<%?xml") or not line:match("^%s*<%?.*%?>") then
43+
table.insert(lines, line)
44+
end
45+
end
46+
-- Close the input file
47+
input_file:close()
48+
-- Open the file for writing (overwrite the original file)
49+
local output_file <close> = io.open(file_path, "w")
50+
if not output_file then
51+
error("Cannot open file for writing: " .. file_path)
52+
end
53+
-- Write the cleaned lines to the file
54+
for _, line in ipairs(lines) do
55+
output_file:write(line .. "\n")
56+
end
57+
-- Close the output file
58+
output_file:close()
59+
end
60+
2961
function do_open_dialog(document)
3062
local path_name = finale.FCString()
3163
local file_name = finale.FCString()
@@ -35,18 +67,17 @@ function do_open_dialog(document)
3567
file_path:SplitToPathAndFile(path_name, file_name)
3668
end
3769
local full_file_name = file_name.LuaString
38-
local extension = mixin.FCMString()
39-
:SetLuaString(file_name.LuaString)
40-
:ExtractFileExtension()
70+
local extension = finale.FCString(file_name.LuaString)
71+
extension:ExtractFileExtension()
4172
if extension.Length > 0 then
4273
file_name:TruncateAt(file_name:FindLast("." .. extension.LuaString))
4374
end
4475
file_name:AppendLuaString(text_extension)
45-
local open_dialog = mixin.FCMFileOpenDialog(finenv.UI())
46-
:SetWindowTitle(finale.FCString("Open MusicXML for " .. full_file_name))
47-
:AddFilter(finale.FCString("*" .. text_extension), finale.FCString("MusicXML File"))
48-
:SetInitFolder(path_name)
49-
:SetFileName(file_name)
76+
local open_dialog = finale.FCFileOpenDialog(finenv.UI())
77+
open_dialog:SetWindowTitle(finale.FCString("Open MusicXML for " .. full_file_name))
78+
open_dialog:AddFilter(finale.FCString("*" .. text_extension), finale.FCString("MusicXML File"))
79+
open_dialog:SetInitFolder(path_name)
80+
open_dialog:SetFileName(file_name)
5081
open_dialog:AssureFileExtension(text_extension)
5182
if not open_dialog:Execute() then
5283
return nil
@@ -73,7 +104,6 @@ function fix_octave_shift(xml_measure)
73104
elseif shift_type == "up" or shift_type == "down" then
74105
local sign = shift_type == "down" and 1 or -1 -- direction to transpose grace notes
75106
local octaves = (octave_shift:IntAttribute("size", 8) - 1) / 7
76-
print (sign, octaves, "size:", octave_shift:IntAttribute("size", 8))
77107
local prev_grace_note
78108
local prev_note = xml_direction:PreviousSiblingElement("note")
79109
while prev_note do
@@ -112,6 +142,20 @@ function process_xml(score_partwise)
112142
end
113143
end
114144

145+
function append_massaged_to_filename(filepath)
146+
-- Extract the path, filename, and extension
147+
local path, filename, extension = filepath:match("^(.-)([^\\/]-)%.([^\\/%.]+)$")
148+
149+
-- Check if the path extraction was successful
150+
if not path or not filename or not extension then
151+
error("Invalid file path format")
152+
end
153+
154+
-- Construct the new file path with " massaged" appended to the filename
155+
local new_filepath = path .. filename .. " massaged." .. extension
156+
return new_filepath
157+
end
158+
115159
function music_xml_massage_export()
116160
local documents = finale.FCDocuments()
117161
documents:LoadAll()
@@ -120,6 +164,8 @@ function music_xml_massage_export()
120164
if not xml_file then
121165
return
122166
end
167+
-- tinyxml2 can't parse processing instructions, so remove them
168+
remove_processing_instructions(xml_file) -- hopefully not necessary forever
123169
local musicxml = tinyxml2.XMLDocument()
124170
local result = musicxml:LoadFile(xml_file)
125171
if result ~= tinyxml2.XML_SUCCESS then
@@ -131,7 +177,9 @@ function music_xml_massage_export()
131177
error("File " .. xml_file .. " does not appear to be a Finale-exported MusicXML file.")
132178
end
133179
process_xml(score_partwise)
134-
musicxml:SaveFile(xml_file)
180+
local output_name = append_massaged_to_filename(xml_file)
181+
musicxml:SaveFile(output_name)
182+
finenv.UI():AlertInfo("Processed to " .. output_name .. ".", "Processed File")
135183
end
136184

137185
music_xml_massage_export()

0 commit comments

Comments
 (0)