@@ -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."
3144end
3245
46+ do_single_file = do_single_file or false
3347local xml_extension = " .musicxml"
34- local add_to_filename = " massaged"
48+ local add_to_filename = " massaged"
3549
3650local 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 ()
6377end
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-
11579function 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
168132end
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 " "
194156end
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
241184end
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)
270198end
271199
272200function 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
290221end
291222
0 commit comments