From bf37301235c853c4c9fde8d0b29e8cb6ed6d24e1 Mon Sep 17 00:00:00 2001 From: Dirk Koopman Date: Sat, 24 Sep 2016 18:34:03 +0100 Subject: [PATCH] issued version with help and -x -b flags --- mscore-halve | 87 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 73 insertions(+), 14 deletions(-) diff --git a/mscore-halve b/mscore-halve index ee5990a..88ae780 100755 --- a/mscore-halve +++ b/mscore-halve @@ -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 @@ -12,12 +12,18 @@ # 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 ..."; + 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] ...\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; } -- 2.34.1