issued version with help and -x -b flags
authorDirk Koopman <djk@tobit.co.uk>
Sat, 24 Sep 2016 17:34:03 +0000 (18:34 +0100)
committerDirk Koopman <djk@tobit.co.uk>
Sat, 24 Sep 2016 17:34:03 +0000 (18:34 +0100)
mscore-halve

index ee5990a115dc3e9fd26e7e141f3ba931cdfb111e..88ae78054b9e81c3df07d4b3ebe1b4865b7f9855 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 #
 # A program for processing Musescore XML files and halving the times of all the notes
 # together with anything else that may be relevant (eg Time Sig, rests, trailing
 #
 
 use strict;
+
+require 5.10.1;
+
 use XML::LibXML;
 use File::Basename;
+use File::Temp qw{ :mktemp };
 use IO::File;
 use v5.10;
 use utf8;
 
+our $VERSION = "1.0";
+
 our %half = (                                  # decode from one note length to its half
                         qw(
                                   maxima long
@@ -38,7 +44,7 @@ our %half = (                                 # decode from one note length to its half
 our %yesno = ( qw(yes 1 no 0) ); # used for turning translating yes/no text values
 
 
-our $dbg = 1;                                  # show debugging
+our $dbg = 0;                                  # show debugging
 our $removebeam = 1;                   # if set remove any BeamMode clauses
 
 usage() unless @ARGV;
@@ -46,27 +52,60 @@ usage() unless @ARGV;
 binmode STDOUT, "utf8";
 
 foreach my $fn (@ARGV) {
-       my ($name, $path, $suffix) = fileparse($fn, qr/\.[^.]*/);
-       my ($ifn, $ofn);
-       if ($suffix eq ".mscx") {
-               $ifn = $fn;
-               $ofn = $path . $name . "-halved" . $suffix;
+
+       if ($fn =~ /^-\w/) {
+               usage() if $fn =~ /^\-+[\?h]/i;
+               $dbg ^= 1 if $fn =~ /^\-+x/;
+               $removebeam ^= 1 if $fn =~ /^\-+b/;
        } else {
-               usage();
-       }
+               my ($ifn, $ofn, $tfn);
 
-       process($ifn, $ofn);
+               my ($name, $path, $suffix) = fileparse($fn, qr/\.[^.]*/);
+               if ($suffix eq ".mscx" || $suffix eq ".mscz") {
+                       $ifn = $fn;
+                       $ofn = $path . $name . "-halved.mscx";
+
+                       # extract out the zipped up .mscx file from an .mscz archive
+                       if ($suffix eq '.mscz') {
+                               $tfn = mktemp("/tmp/msczXXXXXXX");
+                               my $xifn = $ifn;
+                               $xifn =~ s/z$/x/; 
+                               system("unzip -p $ifn $xifn > $tfn");
+                               $ifn = $tfn;    # the tmp file is the actual input. 
+                       }
+               } else {
+                       usage("Only Musescore .mscx or .mscz files allowed (got: $fn)");
+               }
+               
+               process($ifn, $ofn, $fn);
+               unlink $tfn if $tfn;
+       }
 }
 
 exit 0;
 
 sub process
 {
-       my ($ifn, $ofn) = @_;
+       my ($ifn, $ofn, $fn) = @_;
 
-       my $of = IO::File->new(">$ofn") or die "Cannot open $ofn $!\n";
        my $p = XML::LibXML->new();
-       my $doc = $p->load_xml(location=>$ifn);
+       my $doc = eval { $p->load_xml(location=>$ifn) };
+
+       usage("Invalid Musescore file detected (in $fn) $@") unless $doc;
+
+       my $version;
+       
+       my ($muse) = $doc->findnodes('/museScore');
+       if ($muse) {
+               my ($v) = $muse->findnodes('./@version');
+               $version = $v->to_literal if $v;
+       }
+       if (!$version || $version < 2) {
+               $version ||= "Unknown";
+               usage("Version $version detected in $fn, this program will only work with MuseScore 2 (or greater) files");
+       }
+
+       my $of = IO::File->new(">$ofn") or usage("Cannot open $ofn $!");
 
        foreach my $staff ($doc->findnodes('/museScore/Score/Staff')) {
                my ($sigN, $sigD);              # current time sig values (may be needed later)
@@ -225,6 +264,26 @@ sub display
 
 sub usage
 {
-       say "$0: usage <filename.mscx> ...";
+       my $s = shift;
+       my ($name, $path, $suffix) = fileparse($0, qr/\.[^.]*/);
+       $name = "$name$suffix: ";
+
+       if ($s) {
+               say "\n${name}$s\n";
+               $name = "\t";
+       }
+       say "${name}version $VERSION usage: [-b] [-x] <filename.msc[xz]> ...\n";
+       say "\tA program to halve the note values of a MuseScore 2.x file.\n";
+       say "\tThis designed to be used to convert 'early music' note values";
+       say "\tinto something more 'modern'. It will also sort out things like";
+       say "\tinter-syllablic hyphenation if it comes across trailing hyphens";
+       say "\tsuch as come from imported Finale musicxml files.";
+       say "\n\tfilenames: 'a.mscz' (or 'a.mscx') will be written to 'a-halved.mscx'.";
+       say "\tYou can do several files at a time!\n";
+       say "\n\tArguments:";
+       say "\t-b - normally any beaming is converted to auto, use this to retain beaming info";
+       say "\t-x - enable debugging (actually more a stream of conscienceness)";
+       say;
+       
        exit 1;
 }