Skip to content

Commit b941259

Browse files
committed
Update musicxml_massage_export.lua
Implemented standalone menu for "Single File" and removed other options so FOLDER extraction always uses the source directory and appends to the output filename. Now using lfs in place of osutils.
1 parent 9934547 commit b941259

File tree

1 file changed

+55
-124
lines changed

1 file changed

+55
-124
lines changed

src/musicxml_massage_export.lua

Lines changed: 55 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,32 @@ function plugindef()
44
finaleplugin.NoStore = true
55
finaleplugin.Author = "Robert Patterson (folder scanning added by Carl Vine)"
66
finaleplugin.Copyright = "CC0 https://creativecommons.org/publicdomain/zero/1.0/"
7-
finaleplugin.Version = "1.0.4"
8-
finaleplugin.Date = "October 1, 2024"
7+
finaleplugin.Version = "1.0.5"
8+
finaleplugin.Date = "October 2, 2024"
99
finaleplugin.LoadLuaOSUtils = true
1010
finaleplugin.CategoryTags = "Document"
1111
finaleplugin.MinJWLuaVersion = 0.74
12+
finaleplugin.AdditionalMenuOptions = [[
13+
Massage MusicXML Single File
14+
]]
15+
finaleplugin.AdditionalUndoText = [[
16+
Massage MusicXML Single File
17+
]]
18+
finaleplugin.AdditionalDescriptions = [[
19+
Massage a MusicXML file to improve importing to Dorico and MuseScore
20+
]]
21+
finaleplugin.AdditionalPrefixes = [[
22+
do_single_file = true
23+
]]
24+
finaleplugin.ScriptGroupName = "Staff Explode"
1225
finaleplugin.Notes = [[
13-
This script reads a musicxml file exported from Finale and modifies it to
14-
improve the importing into Dorico or MuseScore. The best process is as follows:
26+
This script reads musicxml files exported from Finale and modifies them to
27+
improve importing into Dorico or MuseScore. The best process is as follows:
1528
1629
1. Export your document as uncompressed MusicXML.
1730
2. Run this plugin on the output *.musicxml document.
1831
3. The massaged file name has " massaged" appended to the file name.
19-
3. Import the massaged *.musicxml into Dorico or MuseScore.
32+
3. Import the massaged *.musicxml file into Dorico or MuseScore.
2033
2134
Here is a list of some of the changes the script makes:
2235
@@ -25,13 +38,14 @@ function plugindef()
2538
Due to a limitation in the xml parser, all xml processing instructions are removed. These are metadata that neither
2639
Dorico nor MuseScore use, so their removal should not affect importing into those programs.
2740
]]
28-
return "Massage MusicXML...",
29-
"Massage MusicXML",
30-
"Massages MusicXML to make it easier to import to Dorico and MuseScore."
41+
return "Massage MusicXML Folder",
42+
"Massage MusicXML Folder",
43+
"Massage a folder of MusicXML files to improve importing to Dorico and MuseScore."
3144
end
3245

46+
do_single_file = do_single_file or false
3347
local xml_extension = ".musicxml"
34-
local add_to_filename = "massaged"
48+
local add_to_filename = " massaged"
3549

3650
local function alert_error(file_list)
3751
local msg = (#file_list > 1 and "These files do not " or "This file does not ")
@@ -62,56 +76,6 @@ local function remove_processing_instructions(input_name, output_name)
6276
output_file:close()
6377
end
6478

65-
local function choose_extraction_method()
66-
local fs = finale.FCString
67-
local dialog = finale.FCCustomLuaWindow()
68-
dialog:SetTitle(fs(plugindef()))
69-
local stat = dialog:CreateStatic(0, 0)
70-
stat:SetText(fs("Massage the MusicXML for:"))
71-
stat:SetWidth(150)
72-
local labels = finale.FCStrings()
73-
labels:CopyFromStringTable{ "one MusicXML file", "a folder of MusicXML files" }
74-
local method = dialog:CreateRadioButtonGroup(0, 20, 2)
75-
method:SetText(labels)
76-
method:SetWidth(160)
77-
method:SetSelectedItem(1) -- assume "folder"
78-
dialog:CreateOkButton()
79-
dialog:CreateCancelButton()
80-
local ok = (dialog:ExecuteModal(nil) == finale.EXECMODAL_OK)
81-
return ok, (method:GetSelectedItem() == 1)
82-
end
83-
84-
local function choose_new_folder_dialog()
85-
local fs = finale.FCString
86-
local dialog = finale.FCCustomLuaWindow()
87-
dialog:SetTitle(fs(plugindef()))
88-
local stat = dialog:CreateStatic(0, 0)
89-
stat:SetText(fs("Select a Different Folder"))
90-
stat:SetWidth(150)
91-
stat = dialog:CreateStatic(0, 15)
92-
stat:SetText(fs("for the Massaged Files:"))
93-
stat:SetWidth(150)
94-
local labels = finale.FCStrings()
95-
labels:CopyFromStringTable{ "YES", "NO" }
96-
local new_folder = dialog:CreateRadioButtonGroup(0, 35, 2)
97-
new_folder:SetText(labels)
98-
new_folder:SetWidth(80)
99-
new_folder:SetSelectedItem(0)
100-
local add = dialog:CreateCheckbox(0, 85)
101-
add:SetText(fs("Don't Add \"" .. add_to_filename .. "\" to Filenames"))
102-
add:SetWidth(210)
103-
add:SetCheck(1)
104-
stat = dialog:CreateStatic(15, 100)
105-
stat:SetText(fs("When Using a Different Folder"))
106-
stat:SetWidth(180)
107-
dialog:CreateOkButton()
108-
dialog:CreateCancelButton()
109-
local ok = (dialog:ExecuteModal(nil) == finale.EXECMODAL_OK)
110-
local do_change_filename = (add:GetCheck() == 0)
111-
local select_new_folder = (new_folder:GetSelectedItem() == 0)
112-
return ok, select_new_folder, do_change_filename
113-
end
114-
11579
function fix_octave_shift(xml_measure)
11680
for xml_direction in xmlelements(xml_measure, "direction") do
11781
local xml_direction_type = xml_direction:FirstChildElement("direction-type")
@@ -167,14 +131,12 @@ function process_xml(score_partwise)
167131
end
168132
end
169133

170-
function process_one_file(input_file, output_file, do_change_filename)
171-
if do_change_filename then -- add "massaged" to output_file
172-
local path, filename, extension = output_file:match("^(.-)([^\\/]-)%.([^\\/%.]+)$")
173-
if not path or not filename or not extension then
174-
error("Invalid file path format")
175-
end
176-
output_file = path .. filename .. " " .. add_to_filename .. "." .. extension
134+
function process_one_file(input_file)
135+
local path, filename, extension = input_file:match("^(.-)([^\\/]-)%.([^\\/%.]+)$")
136+
if not path or not filename or not extension then
137+
error("Invalid file path format")
177138
end
139+
local output_file = path .. filename .. add_to_filename .. xml_extension
178140

179141
remove_processing_instructions(input_file, output_file)
180142
local musicxml = tinyxml2.XMLDocument()
@@ -193,73 +155,39 @@ function process_one_file(input_file, output_file, do_change_filename)
193155
return ""
194156
end
195157

196-
function do_open_directory()
197-
local src_dialog = finale.FCFolderBrowseDialog(finenv.UI())
198-
src_dialog:SetWindowTitle(finale.FCString("Open Folder of MusicXML Files:"))
199-
if not src_dialog:Execute() then
158+
function process_directory(path_name)
159+
local folder_dialog = finale.FCFolderBrowseDialog(finenv.UI())
160+
folder_dialog:SetWindowTitle(finale.FCString("Select Folder of MusicXML Files:"))
161+
folder_dialog:SetFolderPath(path_name)
162+
if not folder_dialog:Execute() then
200163
return nil -- user cancelled
201164
end
202165
local selected_directory = finale.FCString()
203-
src_dialog:GetFolderPath(selected_directory)
166+
folder_dialog:GetFolderPath(selected_directory)
204167
local src_dir = selected_directory.LuaString
205-
local out_dir = src_dir -- duplicate source to output (for now)
206-
207-
local ok, select_new_folder, do_change_filename = choose_new_folder_dialog()
208-
if not ok then return end -- cancelled
209-
if select_new_folder then -- choose alternate destination dir
210-
local out_dialog = finale.FCFolderBrowseDialog(finenv.UI())
211-
out_dialog:SetWindowTitle(finale.FCString("Choose Folder for Massaged Files:"))
212-
if not out_dialog:Execute() then return end -- user cancelled
213168

214-
out_dialog:GetFolderPath(selected_directory)
215-
out_dir = selected_directory.LuaString
216-
end
217-
if out_dir == src_dir then -- user might "choose" same folder as original
218-
do_change_filename = true -- always change filenames in same directory
219-
end
220-
local osutils = finenv.EmbeddedLuaOSUtils and require("luaosutils")
221-
if not osutils then return end -- can't get a directory listing
222-
local options = finenv.UI():IsOnWindows() and "/b /ad" or "-1"
223-
local file_list = osutils.process.list_dir(src_dir, options)
224-
if file_list == "" then return end -- empty directory
225-
226-
-- run through the file list, identifying valid candidates
169+
-- scan the directory, identifying valid candidate files
227170
local error_list = {}
228-
for x_file in file_list:gmatch("([^\r\n]*)[\r\n]?") do
229-
if x_file:sub(-xml_extension:len()) == xml_extension then
230-
local src_file = src_dir .. "/" .. x_file
231-
local dest_file = out_dir .. "/" .. x_file
232-
local file_error = process_one_file(src_file, dest_file, do_change_filename)
171+
local lfs = require("lfs")
172+
for file in lfs.dir(src_dir) do
173+
if file ~= "." and file ~= ".." and file:sub(-xml_extension:len()) == xml_extension then
174+
local file_error = process_one_file(src_dir .. "/" .. file)
233175
if file_error ~= "" then
234176
table.insert(error_list, file_error)
235177
end
178+
236179
end
237180
end
238181
if #error_list > 0 then
239182
alert_error(error_list)
240183
end
241184
end
242185

243-
function do_open_dialog(document)
244-
local path_name = finale.FCString()
245-
local file_name = finale.FCString()
246-
local file_path = finale.FCString()
247-
if document then
248-
document:GetPath(file_path)
249-
file_path:SplitToPathAndFile(path_name, file_name)
250-
end
251-
local full_file_name = file_name.LuaString
252-
local extension = finale.FCString(file_name.LuaString)
253-
extension:ExtractFileExtension()
254-
if extension.Length > 0 then
255-
file_name:TruncateAt(file_name:FindLast("." .. extension.LuaString))
256-
end
257-
file_name:AppendLuaString(xml_extension)
186+
function do_open_dialog(path_name)
258187
local open_dialog = finale.FCFileOpenDialog(finenv.UI())
259-
open_dialog:SetWindowTitle(finale.FCString("Open MusicXML for " .. full_file_name))
188+
open_dialog:SetWindowTitle(finale.FCString("Select a MusicXML File:"))
260189
open_dialog:AddFilter(finale.FCString("*" .. xml_extension), finale.FCString("MusicXML File"))
261190
open_dialog:SetInitFolder(path_name)
262-
open_dialog:SetFileName(file_name)
263191
open_dialog:AssureFileExtension(xml_extension)
264192
if not open_dialog:Execute() then
265193
return nil
@@ -270,22 +198,25 @@ function do_open_dialog(document)
270198
end
271199

272200
function music_xml_massage_export()
273-
local ok, full_directory = choose_extraction_method()
274-
if not ok then return end -- user cancelled
201+
local documents = finale.FCDocuments()
202+
documents:LoadAll()
203+
local document = documents:FindCurrent()
204+
local path_name = finale.FCString()
205+
if document then -- extract active pathname
206+
document:GetPath(path_name)
207+
path_name:SplitToPathAndFile(path_name, nil)
208+
end
275209

276-
if full_directory then
277-
do_open_directory()
278-
else -- only one file
279-
local documents = finale.FCDocuments()
280-
documents:LoadAll()
281-
local document = documents:FindCurrent()
282-
local xml_file = do_open_dialog(document)
210+
if do_single_file then
211+
local xml_file = do_open_dialog(path_name)
283212
if xml_file then
284-
local file_error = process_one_file(xml_file, xml_file, true)
213+
local file_error = process_one_file(xml_file)
285214
if file_error ~= "" then
286215
alert_error{file_error}
287216
end
288217
end
218+
else
219+
process_directory(path_name)
289220
end
290221
end
291222

0 commit comments

Comments
 (0)