Mercurial > gub
changeset 6060:0247125e995d
lilypondcairo: bump to 2.13.46, include windows and midi2ly patches.
author | Jan Nieuwenhuizen <janneke@gnu.org> |
---|---|
date | Mon, 24 Jan 2011 15:23:33 +0100 |
parents | 2b278c103efd |
children | 71bcdbdd76e7 |
files | gub/specs/lilypondcairo.py patches/0001-Midi2ly-grok-midi-files-with-up-to-256-tracks-was-32.patch patches/0001-Use-g_spawn_sync-instead-of-system-.-Fixes-1429.patch patches/lilypond-midi2ly-preview.patch |
diffstat | 4 files changed, 1201 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/gub/specs/lilypondcairo.py Mon Jan 24 21:36:43 2011 +0100 +++ b/gub/specs/lilypondcairo.py Mon Jan 24 15:23:33 2011 +0100 @@ -6,11 +6,14 @@ # in. Hmm. class Lilypondcairo (lilypond.Lilypond): - source = 'http://lilypond.org/download/source/v2.13/lilypond-2.13.42.tar.gz' + source = 'http://lilypond.org/download/source/v2.13/lilypond-2.13.46.tar.gz' dependencies = [x.replace ('pango', 'pangocairo') for x in lilypond.Lilypond.dependencies] patches = [ '0003-Start-OTF-font-from-E800-avoids-hardcoded-linux-unic.patch', + '0001-Use-g_spawn_sync-instead-of-system-.-Fixes-1429.patch', + '0001-Midi2ly-grok-midi-files-with-up-to-256-tracks-was-32.patch', + 'lilypond-midi2ly-preview.patch', ] def get_conflict_dict (self): return {'': ['lilypond']} @@ -21,7 +24,9 @@ for x in lilypond.Lilypond__mingw.dependencies] patches = [ '0003-Start-OTF-font-from-E800-avoids-hardcoded-linux-unic.patch', - '0001-MINGW32-Prepend-cwd-to-PATH.-Fixes-invoking-as-lilyp.patch', + '0001-Use-g_spawn_sync-instead-of-system-.-Fixes-1429.patch', + '0001-Midi2ly-grok-midi-files-with-up-to-256-tracks-was-32.patch', + 'lilypond-midi2ly-preview.patch', ] def get_conflict_dict (self): return {'': ['lilypond']}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/0001-Midi2ly-grok-midi-files-with-up-to-256-tracks-was-32.patch Mon Jan 24 15:23:33 2011 +0100 @@ -0,0 +1,51 @@ +From 85c0ce205e1a9b5fad4ac79d02292ac1231db532 Mon Sep 17 00:00:00 2001 +From: Jan Nieuwenhuizen <janneke@gnu.org> +Date: Tue, 18 Jan 2011 15:31:58 +0100 +Subject: [PATCH] Midi2ly: grok midi files with up to 256 tracks, was 32. Fixes #1479. + +--- + scripts/midi2ly.py | 13 +++++++++++-- + 1 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/scripts/midi2ly.py b/scripts/midi2ly.py +index 86c32ba..b03e1a8 100644 +--- a/scripts/midi2ly.py ++++ b/scripts/midi2ly.py +@@ -712,11 +712,20 @@ def dump_channel (thread, skip): + + return '\n '.join (lines) + '\n' + ++def number2ascii (i): ++ s = '' ++ i += 1 ++ while i > 0: ++ m = (i - 1) % 26 ++ s = '%c' % (m + ord ('A')) + s ++ i = (i - m)/26 ++ return s ++ + def track_name (i): +- return 'track%c' % (i + ord ('A')) ++ return 'track' + number2ascii (i) + + def channel_name (i): +- return 'channel%c' % (i + ord ('A')) ++ return 'channel' + number2ascii (i) + + def dump_track (channels, n): + s = '\n' +diff --git a/python/midi.c b/python/midi.c +index 972410f..4e6368a 100644 +--- a/python/midi.c ++++ b/python/midi.c +@@ -388,7 +388,7 @@ midi_parse (unsigned char **midi,unsigned char *midi_end) + format = get_number (midi, *midi + 2, 2); + tracks = get_number (midi, *midi + 2, 2); + +- if (tracks > 32) ++ if (tracks > 256) + return midi_error (__FUNCTION__, ": too many tracks: ", compat_itoa (tracks)); + + division = get_number (midi, *midi + 2, 2) * 4; +-- +1.7.1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/0001-Use-g_spawn_sync-instead-of-system-.-Fixes-1429.patch Mon Jan 24 15:23:33 2011 +0100 @@ -0,0 +1,290 @@ +From 11d5b22d4eb69696b43e576db3d16793dd166d93 Mon Sep 17 00:00:00 2001 +From: Jan Nieuwenhuizen <janneke@gnu.org> +Date: Fri, 21 Jan 2011 15:02:31 +0100 +Subject: [PATCH] Use g_spawn_sync () instead of system (). Fixes #1429. + +Avoid the opening of a DOS box, console window, command window or +power shell during PostScript to PDF conversion on some versions of +Microsoft Windows [with GUB 6976be5 or newer]. + +Bypass the shell, thus avoiding quoting (think spaces or other special +characters in a file name), mangling and shell-incompatibilities. +--- + lily/general-scheme.cc | 62 ++++++++++++++++++++++++++++ + lily/include/lily-guile.hh | 2 +- + lily/lily-guile.cc | 6 +-- + scm/backend-library.scm | 98 ++++++++++++++------------------------------ + scm/framework-ps.scm | 8 ++- + scm/ps-to-png.scm | 2 + + 6 files changed, 103 insertions(+), 75 deletions(-) + +diff --git a/lily/general-scheme.cc b/lily/general-scheme.cc +index 14ef697..5989350 100644 +--- a/lily/general-scheme.cc ++++ b/lily/general-scheme.cc +@@ -23,6 +23,7 @@ + #include <cstdio> + #include <ctype.h> + #include <cstring> /* memset */ ++#include <glib.h> + using namespace std; + + #include "dimensions.hh" +@@ -663,3 +664,64 @@ LY_DEFINE (ly_format, "ly:format", + + return scm_take_locale_stringn (result, len); + } ++ ++int ++ly_run_command (char *argv[], char **standard_output, char **standard_error) ++{ ++ GError *error = 0; ++ int exit_status = 0; ++ int flags = G_SPAWN_SEARCH_PATH; ++ if (!standard_output) ++ flags |= G_SPAWN_STDOUT_TO_DEV_NULL; ++ if (!standard_error) ++ flags |= G_SPAWN_STDERR_TO_DEV_NULL; ++ if (!g_spawn_sync (0, argv, 0, GSpawnFlags (flags), ++ 0, 0, ++ standard_output, standard_error, ++ &exit_status, &error)) ++ { ++ fprintf (stderr, "failed (%d): %s: %s\n", exit_status, argv[0], error->message); ++ g_error_free (error); ++ if (!exit_status) ++ exit_status = -1; ++ } ++ ++ return exit_status; ++} ++ ++LY_DEFINE (ly_spawn, "ly:spawn", ++ 1, 0, 1, (SCM command, SCM rest), ++ "Simple interface to g_spawn_sync" ++ " @var{str}." ++ " The error is formatted with @code{format} and @var{rest}.") ++ ++{ ++ LY_ASSERT_TYPE (scm_is_string, command, 1); ++ ++ int argc = scm_is_pair (rest) ? scm_ilength (rest) : 0; ++ char **argv = new char*[argc + 2]; ++ ++ int n = 0; ++ argv[n++] = ly_scm2str0 (command); ++ for (SCM s = rest; scm_is_pair (s); s = scm_cdr (s)) ++ argv[n++] = ly_scm2str0 (scm_car (s)); ++ argv[n] = 0; ++ ++ char *standard_output = 0; ++ char *standard_error = 0; ++ int exit_status = be_verbose_global ++ ? ly_run_command (argv, &standard_output, &standard_error) ++ : ly_run_command (argv, 0, 0); ++ ++ if (be_verbose_global) ++ { ++ fprintf (stderr, "\n%s", standard_output); ++ fprintf (stderr, "%s", standard_error); ++ } ++ ++ for (int i = 0; i < n; i++) ++ free (argv[i]); ++ delete[] argv; ++ ++ return scm_from_int (exit_status); ++} +diff --git a/lily/include/lily-guile.hh b/lily/include/lily-guile.hh +index 6dcc050..3fefd5d 100644 +--- a/lily/include/lily-guile.hh ++++ b/lily/include/lily-guile.hh +@@ -66,7 +66,7 @@ Interval ly_scm2interval (SCM); + Drul_array<Real> ly_scm2realdrul (SCM); + Slice int_list_to_slice (SCM l); + SCM ly_interval2scm (Drul_array<Real>); +-char *ly_scm2newstr (SCM str, size_t *lenp); ++char *ly_scm2str0 (SCM str); + + Real robust_scm2double (SCM, double); + int robust_scm2int (SCM, int); +diff --git a/lily/lily-guile.cc b/lily/lily-guile.cc +index f0ff8ca..1763a5c 100644 +--- a/lily/lily-guile.cc ++++ b/lily/lily-guile.cc +@@ -138,12 +138,10 @@ ly_string2scm (string const &str) + str.length ()); + } + +- + char * +-ly_scm2newstr (SCM str, size_t *lenp) ++ly_scm2str0 (SCM str) + { +- char* p = scm_to_locale_stringn(str, lenp); +- return p; ++ return scm_to_locale_string (str); + } + + /* +diff --git a/scm/backend-library.scm b/scm/backend-library.scm +index ec81b2f..f21decd 100644 +--- a/scm/backend-library.scm ++++ b/scm/backend-library.scm +@@ -23,23 +23,12 @@ + (scm paper-system) + (ice-9 optargs)) + +-(define-public (ly:system command . rest) +- (let* ((status 0) +- (dev-null "/dev/null") +- (silenced (if (or (ly:get-option 'verbose) +- (not (access? dev-null W_OK))) +- command +- (format #f "~a > ~a 2>&1 " command dev-null)))) +- (if (ly:get-option 'verbose) +- (begin +- (ly:message (_ "Invoking `~a'...") command)) +- (ly:progress "\n")) +- +- (set! status +- (if (pair? rest) +- (system-with-env silenced (car rest)) +- (system silenced))) +- ++(define-public (ly:system command) ++ (if (ly:get-option 'verbose) ++ (begin ++ (ly:message (_ "Invoking `~a'...") (string-join command))) ++ (ly:progress "\n")) ++ (let ((status (apply ly:spawn command))) + (if (> status 0) + (begin + (ly:message (_ "`~a' failed (~a)") command status) +@@ -47,22 +36,6 @@ + ;; hmmm. what's the best failure option? + (throw 'ly-file-failed))))) + +-(define-public (system-with-env cmd env) +- +- "Execute CMD in fork, with ENV (a list of strings) as the environment" +- (let* +- ;; laziness: should use execle? +- +- ((pid (primitive-fork))) +- (if (= 0 pid) +- ;; child +- (begin +- (environ env) +- (system cmd)) +- +- ;; parent +- (cdr (waitpid pid))))) +- + (define-public (sanitize-command-option str) + "Kill dubious shell quoting" + +@@ -91,41 +64,32 @@ + (dir-basename name ".ps" ".eps") + ".pdf")) + (is-eps (string-match "\\.eps$" name)) +- (paper-size-string (if is-eps +- "-dEPSCrop" +- (ly:format "-dDEVICEWIDTHPOINTS=~$\ +- -dDEVICEHEIGHTPOINTS=~$" +- paper-width paper-height))) +- +- (cmd (ly:format +- "~a\ +- ~a\ +- ~a\ +- ~a\ +- -dCompatibilityLevel=1.4\ +- -dNOPAUSE\ +- -dBATCH\ +- -r1200\ +- -sDEVICE=pdfwrite\ +- -sOutputFile=~S\ +- -c .setpdfwrite\ +- -f ~S\ +-" +- (search-gs) +- (if (ly:get-option 'verbose) "" "-q") +- (if (or (ly:get-option 'gs-load-fonts) +- (ly:get-option 'gs-load-lily-fonts)) +- "-dNOSAFER" +- "-dSAFER") +- paper-size-string +- pdf-name +- name))) +- ;; The wrapper on windows cannot handle `=' signs, +- ;; gs has a workaround with #. +- (if (eq? PLATFORM 'windows) +- (begin +- (set! cmd (string-regexp-substitute "=" "#" cmd)) +- (set! cmd (string-regexp-substitute "-dSAFER " "" cmd)))) ++ (*unspecified* (if #f #f)) ++ (cmd ++ (remove (lambda (x) (eq? x *unspecified*)) ++ (list ++ (search-gs) ++ (if (ly:get-option 'verbose) *unspecified* "-q") ++ (if (or (ly:get-option 'gs-load-fonts) ++ (ly:get-option 'gs-load-lily-fonts) ++ (eq? PLATFORM 'windows)) ++ "-dNOSAFER" ++ "-dSAFER") ++ ++ (if is-eps ++ "-dEPSCrop" ++ (ly:format "-dDEVICEWIDTHPOINTS=~$" paper-width)) ++ (if is-eps ++ *unspecified* ++ (ly:format "-dDEVICEHEIGHTPOINTS=~$" paper-height)) ++ "-dCompatibilityLevel=1.4" ++ "-dNOPAUSE" ++ "-dBATCH" ++ "-r1200" ++ "-sDEVICE=pdfwrite" ++ (string-append "-sOutputFile=" pdf-name) ++ "-c.setpdfwrite" ++ (string-append "-f" name))))) + + (ly:message (_ "Converting to `~a'...") pdf-name) + (ly:progress "\n") +diff --git a/scm/framework-ps.scm b/scm/framework-ps.scm +index b79c1a3..c4d1d01 100644 +--- a/scm/framework-ps.scm ++++ b/scm/framework-ps.scm +@@ -267,10 +267,12 @@ + (let* ((dir-name (tmpnam)) + (files '()) + (status 0) +- (embed #f)) ++ (embed #f) ++ (cwd (getcwd))) + (mkdir dir-name #o700) +- (set! status (ly:system +- (format "cd ~a && fondu -force '~a'" dir-name filename))) ++ (chdir dir-name) ++ (set! status (ly:system (list "fondu" "-force" file-name))) ++ (chdir cwd) + (set! files (dir-listing dir-name)) + (for-each + (lambda (f) +diff --git a/scm/ps-to-png.scm b/scm/ps-to-png.scm +index 4436ea3..17f8222 100644 +--- a/scm/ps-to-png.scm ++++ b/scm/ps-to-png.scm +@@ -27,6 +27,8 @@ + (lily) + ) + ++;; FIXME: use backend-library for duplicates and stubs; lilypond-ps2png.scm is no more ++ + (define-public _ gettext) + + (define PLATFORM +-- +1.7.1 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/lilypond-midi2ly-preview.patch Mon Jan 24 15:23:33 2011 +0100 @@ -0,0 +1,853 @@ +From 2005e201323314c8439d6aca062386c70c784294 Mon Sep 17 00:00:00 2001 +From: Jan Nieuwenhuizen <janneke@gnu.org> +Date: Mon, 24 Jan 2011 14:15:36 +0100 +Subject: [PATCH 1/5] Midi2ly: Whitespace nits. + +--- + scripts/midi2ly.py | 213 ++++++++++++++++++++++++++-------------------------- + 1 files changed, 107 insertions(+), 106 deletions(-) + +diff --git a/scripts/midi2ly.py b/scripts/midi2ly.py +index b03e1a8..43000c1 100644 +--- a/scripts/midi2ly.py ++++ b/scripts/midi2ly.py +@@ -5,7 +5,7 @@ + # This file is part of LilyPond, the GNU music typesetter. + # + # Copyright (C) 1998--2011 Han-Wen Nienhuys <hanwen@xs4all.nl> +-# Jan Nieuwenhuizen <janneke@gnu.org> ++# Jan Nieuwenhuizen <janneke@gnu.org> + # + # LilyPond is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by +@@ -87,7 +87,7 @@ def warranty (): + + %s + %s +-''' % ( _ ('Copyright (c) %s by') % '2001--2011', ++''' % ( _ ('Copyright (c) %s by') % '1998--2011', + '\n '.join (authors), + _ ('Distributed under terms of the GNU General Public License.'), + _ ('It comes with NO WARRANTY.'))) +@@ -97,7 +97,7 @@ def progress (s): + + def warning (s): + progress (_ ("warning: ") + s) +- ++ + def error (s): + progress (_ ("error: ") + s) + raise Exception (_ ("Exiting... ")) +@@ -119,7 +119,7 @@ class Duration: + if clocks <= 0: + self.clocks = duration_quant_clocks + (self.dur, self.num, self.den) = self.dur_num_den (clocks) +- ++ + def dur_num_den (self, clocks): + for i in range (len (allowed_tuplet_clocks)): + if clocks == allowed_tuplet_clocks[i]: +@@ -143,7 +143,7 @@ class Duration: + s = '%d*%d' % (self.dur, self.num) + else: + s = '%d*%d/%d' % (self.dur, self.num, self.den) +- ++ + global reference_note + reference_note.duration = self + +@@ -246,10 +246,10 @@ class Note: + n = 6; a = 1; o = o - 1 + + return (o, n, a) +- ++ + def __repr__ (self): + s = chr ((self.notename + 2) % 7 + ord ('a')) +- return 'Note(%s %s)' % (s, self.duration.dump()) ++ return 'Note(%s %s)' % (s, self.duration.dump ()) + + def dump (self, dump_dur = 1): + global reference_note +@@ -260,25 +260,25 @@ class Note: + else: + delta = self.pitch - reference_note.pitch + commas = sign (delta) * (abs (delta) / 12) +- if ((sign (delta) \ +- * (self.notename - reference_note.notename) + 7) \ +- % 7 >= 4) \ +- or ((self.notename == reference_note.notename) \ +- and (abs (delta) > 4) and (abs (delta) < 12)): ++ if (((sign (delta) ++ * (self.notename - reference_note.notename) + 7) ++ % 7 >= 4) ++ or ((self.notename == reference_note.notename) ++ and (abs (delta) > 4) and (abs (delta) < 12))): + commas = commas + sign (delta) +- ++ + if commas > 0: + s = s + "'" * commas + elif commas < 0: + s = s + "," * -commas + + ## FIXME: compile fix --jcn +- if dump_dur and (global_options.explicit_durations \ +- or self.duration.compare (reference_note.duration)): ++ if (dump_dur and (global_options.explicit_durations ++ or self.duration.compare (reference_note.duration))): + s = s + self.duration.dump () + + reference_note = self +- ++ + # TODO: move space + return s + ' ' + +@@ -294,7 +294,7 @@ class Time: + + def __repr__ (self): + return 'Time(%d/%d)' % (self.num, self.den) +- ++ + def dump (self): + global time + time = self +@@ -307,12 +307,12 @@ class Tempo: + + def __repr__ (self): + return 'Tempo(%d)' % self.bpm () +- ++ + def bpm (self): + return 4 * 60 / self.seconds_per_1 +- ++ + def dump (self): +- return '\n ' + '\\tempo 4 = %d ' % (self.bpm()) + '\n ' ++ return '\n ' + '\\tempo 4 = %d ' % (self.bpm ()) + '\n ' + + class Clef: + clefs = ('"bass_8"', 'bass', 'violin', '"violin^8"') +@@ -321,7 +321,7 @@ class Clef: + + def __repr__ (self): + return 'Clef(%s)' % self.clefs[self.type] +- ++ + def dump (self): + return '\n \\clef %s\n ' % self.clefs[self.type] + +@@ -346,7 +346,7 @@ class Key: + k = (ord ('cfbeadg'[self.flats % 7]) - ord ('a') - 2 -2 * self.minor + 7) % 7 + else: + k = (ord ('cgdaebf'[self.sharps % 7]) - ord ('a') - 2 -2 * self.minor + 7) % 7 +- ++ + if not self.minor: + name = chr ((k + 2) % 7 + ord ('a')) + else: +@@ -386,7 +386,7 @@ class Text: + 'LYRIC', + 'MARKER', + 'CUE_POINT',) +- ++ + def __init__ (self, type, text): + self.clocks = 0 + self.type = type +@@ -397,8 +397,8 @@ class Text: + if self.type == midi.LYRIC: + s = '"%s"' % self.text + d = Duration (self.clocks) +- if global_options.explicit_durations \ +- or d.compare (reference_note.duration): ++ if (global_options.explicit_durations ++ or d.compare (reference_note.duration)): + s = s + Duration (self.clocks).dump () + s = s + ' ' + else: +@@ -412,9 +412,9 @@ class Text: + + def split_track (track): + chs = {} +- for i in range(16): ++ for i in range (16): + chs[i] = [] +- ++ + for e in track: + data = list (e[1]) + if data[0] > 0x7f and data[0] < 0xf0: +@@ -452,7 +452,7 @@ def end_note (pitches, notes, t, e): + (lt, vel) = pitches[e] + del pitches[e] + +- i = len (notes) - 1 ++ i = len (notes) - 1 + while i > 0: + if notes[i][0] > lt: + i = i -1 +@@ -484,20 +484,20 @@ def events_on_channel (channel): + t = quantise_clocks (t, start_quant_clocks) + + +- if e[1][0] == midi.NOTE_OFF \ +- or (e[1][0] == midi.NOTE_ON and e[1][2] == 0): ++ if (e[1][0] == midi.NOTE_OFF ++ or (e[1][0] == midi.NOTE_ON and e[1][2] == 0)): + end_note (pitches, notes, t, e[1][1]) +- ++ + elif e[1][0] == midi.NOTE_ON: + if not pitches.has_key (e[1][1]): + pitches[e[1][1]] = (t, e[1][2]) +- ++ + # all include ALL_NOTES_OFF +- elif e[1][0] >= midi.ALL_SOUND_OFF \ +- and e[1][0] <= midi.POLY_MODE_ON: ++ elif (e[1][0] >= midi.ALL_SOUND_OFF ++ and e[1][0] <= midi.POLY_MODE_ON): + for i in pitches: + end_note (pitches, notes, t, i) +- ++ + elif e[1][0] == midi.META_EVENT: + if e[1][1] == midi.END_OF_TRACK: + for i in pitches: +@@ -511,7 +511,7 @@ def events_on_channel (channel): + events.append ((t, Tempo (seconds_per_1))) + elif e[1][1] == midi.TIME_SIGNATURE: + (num, dur, clocks4, count32) = map (ord, e[1][2]) +- den = 2 ** dur ++ den = 2 ** dur + events.append ((t, Time (num, den))) + elif e[1][1] == midi.KEY_SIGNATURE: + (alterations, minor) = map (ord, e[1][2]) +@@ -530,16 +530,16 @@ def events_on_channel (channel): + # Better do Note.calc () at dump time? + global_options.key = k + +- elif e[1][1] == midi.LYRIC \ +- or (global_options.text_lyrics and e[1][1] == midi.TEXT_EVENT): ++ elif (e[1][1] == midi.LYRIC ++ or (global_options.text_lyrics and e[1][1] == midi.TEXT_EVENT)): + if last_lyric: + last_lyric.clocks = t - last_time + events.append ((last_time, last_lyric)) + last_time = t + last_lyric = Text (midi.LYRIC, e[1][2]) + +- elif e[1][1] >= midi.SEQUENCE_NUMBER \ +- and e[1][1] <= midi.CUE_POINT: ++ elif (e[1][1] >= midi.SEQUENCE_NUMBER ++ and e[1][1] <= midi.CUE_POINT): + events.append ((t, Text (e[1][1], e[1][2]))) + else: + if global_options.verbose: +@@ -556,7 +556,7 @@ def events_on_channel (channel): + last_lyric.clocks = clocks_per_4 + events.append ((last_time, last_lyric)) + last_lyric = 0 +- ++ + i = 0 + while len (notes): + if i < len (events) and notes[0][0] >= events[i][0]: +@@ -575,17 +575,17 @@ def unthread_notes (channel): + todo = [] + for e in channel: + t = e[0] +- if e[1].__class__ == Note \ +- and ((t == start_busy_t \ +- and e[1].clocks + t == end_busy_t) \ +- or t >= end_busy_t): ++ if (e[1].__class__ == Note ++ and ((t == start_busy_t ++ and e[1].clocks + t == end_busy_t) ++ or t >= end_busy_t)): + thread.append (e) + start_busy_t = t + end_busy_t = t + e[1].clocks +- elif e[1].__class__ == Time \ +- or e[1].__class__ == Key \ +- or e[1].__class__ == Text \ +- or e[1].__class__ == Tempo: ++ elif (e[1].__class__ == Time ++ or e[1].__class__ == Key ++ or e[1].__class__ == Text ++ or e[1].__class__ == Tempo): + thread.append (e) + else: + todo.append (e) +@@ -598,12 +598,12 @@ def gcd (a,b): + if b == 0: + return a + c = a +- while c: ++ while c: + c = a % b + a = b + b = c + return a +- ++ + def dump_skip (skip, clocks): + return skip + Duration (clocks).dump () + ' ' + +@@ -629,7 +629,7 @@ def dump_chord (ch): + s = s + i.dump (dump_dur = 0 ) + s = s + '>' + +- s = s + notes[0].duration.dump() + ' ' ++ s = s + notes[0].duration.dump () + ' ' + reference_note = r + return s + +@@ -638,17 +638,17 @@ def dump_bar_line (last_bar_t, t, bar_count): + bar_t = time.bar_clocks () + if t - last_bar_t >= bar_t: + bar_count = bar_count + (t - last_bar_t) / bar_t +- ++ + if t - last_bar_t == bar_t: + s = '|\n %% %d\n ' % bar_count + last_bar_t = t + else: + # urg, this will barf at meter changes + last_bar_t = last_bar_t + (t - last_bar_t) / bar_t * bar_t +- ++ + return (s, last_bar_t, bar_count) + +- ++ + def dump_channel (thread, skip): + global reference_note, time + +@@ -668,9 +668,9 @@ def dump_channel (thread, skip): + else: + if ch: + chs.append ((last_e[0], ch)) +- ++ + ch = [e[1]] +- ++ + last_e = e + + if ch: +@@ -679,9 +679,9 @@ def dump_channel (thread, skip): + last_t = 0 + last_bar_t = 0 + bar_count = 1 +- ++ + lines = [''] +- for ch in chs: ++ for ch in chs: + t = ch[0] + + i = lines[-1].rfind ('\n') + 1 +@@ -696,16 +696,16 @@ def dump_channel (thread, skip): + (s, last_bar_t, bar_count) = dump_bar_line (last_bar_t, + t, bar_count) + lines[-1] = lines[-1] + s +- ++ + lines[-1] = lines[-1] + dump_chord (ch[1]) + + clocks = 0 + for i in ch[1]: + if i.clocks > clocks: + clocks = i.clocks +- ++ + last_t = t + clocks +- ++ + (s, last_bar_t, bar_count) = dump_bar_line (last_bar_t, + last_t, bar_count) + lines[-1] = lines[-1] + s +@@ -771,10 +771,10 @@ def dump_track (channels, n): + def thread_first_item (thread): + for chord in thread: + for event in chord: +- if (event[1].__class__ == Note +- or (event[1].__class__ == Text ++ if (event[1].__class__ == Note ++ or (event[1].__class__ == Text + and event[1].type == midi.LYRIC)): +- ++ + return event[1] + return None + +@@ -802,20 +802,20 @@ def guess_clef (track): + return Clef (3) + else: + return Clef (2) +- ++ + + def convert_midi (in_file, out_file): + global clocks_per_1, clocks_per_4, key + global start_quant_clocks +- global duration_quant_clocks ++ global duration_quant_clocks + global allowed_tuplet_clocks + + str = open (in_file, 'rb').read () + midi_dump = midi.parse (str) +- ++ + clocks_per_1 = midi_dump[0][1] + clocks_per_4 = clocks_per_1 / 4 +- ++ + if global_options.start_quant: + start_quant_clocks = clocks_per_1 / global_options.start_quant + +@@ -833,19 +833,19 @@ def convert_midi (in_file, out_file): + + tag = '%% Lily was here -- automatically converted by %s from %s' % ( program_name, in_file) + +- ++ + s = '' + s = tag + '\n\\version "2.7.38"\n\n' + for i in range (len (tracks)): + s = s + dump_track (tracks[i], i) + + s = s + '\n\\score {\n <<\n' +- ++ + i = 0 + for t in tracks: + track = track_name (i) + item = track_first_item (t) +- ++ + if item and item.__class__ == Note: + s = s + ' \\context Staff=%s \\%s\n' % (track, track) + elif item and item.__class__ == Text: +@@ -872,44 +872,44 @@ def get_option_parser (): + + p.add_option ('-a', '--absolute-pitches', + action='store_true', +- help=_ ("print absolute pitches")) ++ help=_ ('print absolute pitches')) + p.add_option ('-d', '--duration-quant', +- metavar= _("DUR"), +- help=_ ("quantise note durations on DUR")) ++ metavar=_ ('DUR'), ++ help=_ ('quantise note durations on DUR')) + p.add_option ('-e', '--explicit-durations', + action='store_true', +- help=_ ("print explicit durations")) +- p.add_option("-h", "--help", +- action="help", +- help=_ ("show this help and exit")) +- p.add_option('-k', '--key', help=_ ("set key: ALT=+sharps|-flats; MINOR=1"), +- metavar=_ ("ALT[:MINOR]"), ++ help=_ ('print explicit durations')) ++ p.add_option('-h', '--help', ++ action='help', ++ help=_ ('show this help and exit')) ++ p.add_option('-k', '--key', help=_ ('set key: ALT=+sharps|-flats; MINOR=1'), ++ metavar=_ ('ALT[:MINOR]'), + default='0'), +- p.add_option ('-o', '--output', help=_ ("write output to FILE"), +- metavar=_("FILE"), ++ p.add_option ('-o', '--output', help=_ ('write output to FILE'), ++ metavar=_('FILE'), + action='store') +- p.add_option ('-s', '--start-quant',help= _ ("quantise note starts on DUR"), +- metavar=_ ("DUR")) ++ p.add_option ('-s', '--start-quant',help= _ ('quantise note starts on DUR'), ++ metavar=_ ('DUR')) + p.add_option ('-t', '--allow-tuplet', +- metavar=_ ("DUR*NUM/DEN"), +- action = "append", +- dest="allowed_tuplets", +- help=_ ("allow tuplet durations DUR*NUM/DEN"), ++ metavar=_ ('DUR*NUM/DEN'), ++ action = 'append', ++ dest='allowed_tuplets', ++ help=_ ('allow tuplet durations DUR*NUM/DEN'), + default=[]) +- p.add_option ('-V', '--verbose', help=_ ("be verbose"), ++ p.add_option ('-V', '--verbose', help=_ ('be verbose'), + action='store_true' + ), +- p.version = "midi2ly (LilyPond) @TOPLEVEL_VERSION@" +- p.add_option("--version", +- action="version", +- help=_ ("show version number and exit")) +- p.add_option ('-w', '--warranty', help=_ ("show warranty and copyright"), ++ p.version = 'midi2ly (LilyPond) @TOPLEVEL_VERSION@' ++ p.add_option ('--version', ++ action='version', ++ help=_ ('show version number and exit')) ++ p.add_option ('-w', '--warranty', help=_ ('show warranty and copyright'), + action='store_true', + ), +- p.add_option ('-x', '--text-lyrics', help=_ ("treat every text as a lyric"), ++ p.add_option ('-x', '--text-lyrics', help=_ ('treat every text as a lyric'), + action='store_true') + +- p.add_option_group (ly.display_encode (_ ("Examples")), ++ p.add_option_group (ly.display_encode (_ ('Examples')), + description = r''' + $ midi2ly --key=-2:1 --duration-quant=32 --allow-tuplet=4*2/3 --allow-tuplet=2*4/3 foo.midi + ''') +@@ -923,13 +923,13 @@ def get_option_parser (): + + + def do_options (): +- opt_parser = get_option_parser() ++ opt_parser = get_option_parser () + (options, args) = opt_parser.parse_args () + + if not args or args[0] == '-': + opt_parser.print_help () +- ly.stderr_write ('\n%s: %s %s\n' % (program_name, _ ("error: "), +- _ ("no files specified on command line."))) ++ ly.stderr_write ('\n%s: %s %s\n' % (program_name, _ ('error: '), ++ _ ('no files specified on command line.'))) + sys.exit (2) + + if options.duration_quant: +@@ -949,20 +949,20 @@ def do_options (): + + options.key = Key (sharps, flats, minor) + +- ++ + if options.start_quant: + options.start_quant = int (options.start_quant) +- ++ + options.allowed_tuplets = [map (int, a.replace ('/','*').split ('*')) + for a in options.allowed_tuplets] +- ++ + global global_options + global_options = options + + return args + +-def main(): +- files = do_options() ++def main (): ++ files = do_options () + + for f in files: + g = f +@@ -990,5 +990,6 @@ def main(): + pass + + convert_midi (f, o) ++ + if __name__ == '__main__': +- main() ++ main () +-- +1.7.1 + +From 7b3a9b122d7ef1eb70fdabaac466b7b0c23a1df2 Mon Sep 17 00:00:00 2001 +From: Jan Nieuwenhuizen <janneke@gnu.org> +Date: Mon, 24 Jan 2011 14:29:37 +0100 +Subject: [PATCH 2/5] Midi2ly: add --preview option. + +--- + scripts/midi2ly.py | 23 +++++++++++++++++------ + 1 files changed, 17 insertions(+), 6 deletions(-) + +diff --git a/scripts/midi2ly.py b/scripts/midi2ly.py +index 43000c1..1b3723e 100644 +--- a/scripts/midi2ly.py ++++ b/scripts/midi2ly.py +@@ -62,7 +62,7 @@ start_quant_clocks = 0 + + duration_quant_clocks = 0 + allowed_tuplet_clocks = [] +- ++bar_max = 0 + + ################################################################ + +@@ -689,14 +689,20 @@ def dump_channel (thread, skip): + lines.append ('') + + if t - last_t > 0: +- lines[-1] = lines[-1] + dump_skip (skip, t-last_t) ++ d = t - last_t ++ if bar_max and t > time.bar_clocks () * bar_max: ++ d = time.bar_clocks () * bar_max - last_t ++ lines[-1] = lines[-1] + dump_skip (skip, d) + elif t - last_t < 0: + errorport.write ('BUG: time skew') + + (s, last_bar_t, bar_count) = dump_bar_line (last_bar_t, + t, bar_count) +- lines[-1] = lines[-1] + s + ++ if bar_max and bar_count > bar_max: ++ break ++ ++ lines[-1] = lines[-1] + s + lines[-1] = lines[-1] + dump_chord (ch[1]) + + clocks = 0 +@@ -707,7 +713,7 @@ def dump_channel (thread, skip): + last_t = t + clocks + + (s, last_bar_t, bar_count) = dump_bar_line (last_bar_t, +- last_t, bar_count) ++ last_t, bar_count) + lines[-1] = lines[-1] + s + + return '\n '.join (lines) + '\n' +@@ -886,8 +892,10 @@ def get_option_parser (): + metavar=_ ('ALT[:MINOR]'), + default='0'), + p.add_option ('-o', '--output', help=_ ('write output to FILE'), +- metavar=_('FILE'), ++ metavar=_ ('FILE'), + action='store') ++ p.add_option ('-p', '--preview', help=_ ('preview of first 4 bars'), ++ action='store_true') + p.add_option ('-s', '--start-quant',help= _ ('quantise note starts on DUR'), + metavar=_ ('DUR')) + p.add_option ('-t', '--allow-tuplet', +@@ -949,10 +957,13 @@ def do_options (): + + options.key = Key (sharps, flats, minor) + +- + if options.start_quant: + options.start_quant = int (options.start_quant) + ++ global bar_max ++ if options.preview: ++ bar_max = 4 ++ + options.allowed_tuplets = [map (int, a.replace ('/','*').split ('*')) + for a in options.allowed_tuplets] + +-- +1.7.1 + +From 7a2766a80beb907df0b291584c1a84b6b4fe4c4f Mon Sep 17 00:00:00 2001 +From: Jan Nieuwenhuizen <janneke@gnu.org> +Date: Mon, 24 Jan 2011 14:30:37 +0100 +Subject: [PATCH 3/5] Midi2ly: bug fix for --allow-tuplets. + +--- + scripts/midi2ly.py | 8 +++++++- + 1 files changed, 7 insertions(+), 1 deletions(-) + +diff --git a/scripts/midi2ly.py b/scripts/midi2ly.py +index 1b3723e..afe5c5a 100644 +--- a/scripts/midi2ly.py ++++ b/scripts/midi2ly.py +@@ -830,7 +830,10 @@ def convert_midi (in_file, out_file): + + allowed_tuplet_clocks = [] + for (dur, num, den) in global_options.allowed_tuplets: +- allowed_tuplet_clocks.append (clocks_per_1 / den) ++ allowed_tuplet_clocks.append (clocks_per_1 / dur * num / den) ++ ++ if global_options.verbose: ++ print 'allowed tuplet clocks:', allowed_tuplet_clocks + + tracks = [] + for t in midi_dump[1]: +@@ -967,6 +970,9 @@ def do_options (): + options.allowed_tuplets = [map (int, a.replace ('/','*').split ('*')) + for a in options.allowed_tuplets] + ++ if options.verbose: ++ sys.stderr.write ('Allowed tuplets: %s\n' % `options.allowed_tuplets`) ++ + global global_options + global_options = options + +-- +1.7.1 + +From a013e110e10a1531521d73455b89bd0b00fbf3d0 Mon Sep 17 00:00:00 2001 +From: Jan Nieuwenhuizen <janneke@gnu.org> +Date: Mon, 24 Jan 2011 15:13:05 +0100 +Subject: [PATCH 4/5] midi.c: resurrect debug printing. + +--- + python/midi.c | 11 ++++++----- + 1 files changed, 6 insertions(+), 5 deletions(-) + +diff --git a/python/midi.c b/python/midi.c +index 4e6368a..2ec5224 100644 +--- a/python/midi.c ++++ b/python/midi.c +@@ -60,7 +60,8 @@ compat_itoa (int i) + #if 0 + int x = 0; + int *track = &x; +-#define debug_print(f, args...) fprintf (stderr, "%s:%d: track: %p :" f, __FUNCTION__, __LINE__, *track, ##args) ++#define urg_debug_print(f, args...) fprintf (stderr, "%s:%d: track: %p: " f, __FUNCTION__, __LINE__, *track, ##args) ++#define debug_print(f, args...) fprintf (stderr, f, ##args) + #else + #define debug_print(f, args...) + #endif +@@ -161,7 +162,7 @@ get_number (unsigned char ** str, unsigned char * end_str, int length) + sum = (sum << 8) + (unsigned char) (*str)[i]; + + *str += length; +- debug_print ("%d:\n", sum); ++ debug_print ("%ld:\n", sum); + return sum; + } + +@@ -178,7 +179,7 @@ get_variable_length_number (unsigned char **str, unsigned char * end_str) + if (!(x & 0x80)) + break; + } +- debug_print ("%d:\n", sum); ++ debug_print ("%ld:\n", sum); + return sum; + } + +@@ -312,8 +313,8 @@ midi_parse_track (unsigned char **track, unsigned char *track_end) + + track_len = get_number (track, *track + 4, 4); + +- debug_print ("track_len: %u\n", track_len); +- debug_print ("track_size: %u\n", track_size); ++ debug_print ("track_len: %lu\n", track_len); ++ debug_print ("track_size: %lu\n", track_size); + debug_print ("track begin: %p\n", track); + debug_print ("track end: %p\n", track + track_len); + +-- +1.7.1 + +From 0996f6663b2635491b5efa385e0e3a581fb96292 Mon Sep 17 00:00:00 2001 +From: Jan Nieuwenhuizen <janneke@gnu.org> +Date: Mon, 24 Jan 2011 15:17:10 +0100 +Subject: [PATCH 5/5] Midi2ly: in --preview mode, only parse first eight 4/4 bars (12288 clocks). + +--- + python/midi.c | 26 +++++++++++++++----------- + scripts/midi2ly.py | 3 ++- + 2 files changed, 17 insertions(+), 12 deletions(-) + +diff --git a/python/midi.c b/python/midi.c +index 2ec5224..187268b 100644 +--- a/python/midi.c ++++ b/python/midi.c +@@ -292,7 +292,7 @@ read_event (unsigned char **track, unsigned char *end, PyObject *time, + } + + static PyObject * +-midi_parse_track (unsigned char **track, unsigned char *track_end) ++midi_parse_track (unsigned char **track, unsigned char *track_end, int clocks_max) + { + unsigned int time = 0; + unsigned long track_len, track_size; +@@ -338,7 +338,8 @@ midi_parse_track (unsigned char **track, unsigned char *track_end) + time += dt; + if (dt) + pytime = PyInt_FromLong (time); +- ++ if (clocks_max && time > clocks_max) ++ break; + pyev = read_event (track, track_end, pytime, + &running_status); + if (pyev) +@@ -356,21 +357,23 @@ pymidi_parse_track (PyObject *self, PyObject *args) + { + unsigned char *track, *track_end; + unsigned long track_size; ++ int clocks_max; + + debug_print ("%s", "\n"); +- if (!PyArg_ParseTuple (args, "s#", &track, &track_size)) ++ if (!PyArg_ParseTuple (args, "s#|i", &track, &track_size, &clocks_max)) + return 0; ++ debug_print ("clocks_max: %d\n", clocks_max); + + if (track_size < 0) + return midi_error (__FUNCTION__, ": negative track size: ", compat_itoa (track_size)); + + track_end = track + track_size; + +- return midi_parse_track (&track, track_end); ++ return midi_parse_track (&track, track_end, clocks_max); + } + + static PyObject * +-midi_parse (unsigned char **midi,unsigned char *midi_end) ++midi_parse (unsigned char **midi,unsigned char *midi_end, int clocks_max) + { + PyObject *pymidi = 0; + unsigned long header_len; +@@ -404,7 +407,7 @@ midi_parse (unsigned char **midi,unsigned char *midi_end) + + /* Tracks */ + for (i = 0; i < tracks; i++) +- PyList_Append (pymidi, midi_parse_track (midi, midi_end)); ++ PyList_Append (pymidi, midi_parse_track (midi, midi_end, clocks_max)); + + pymidi = Py_BuildValue ("(OO)", Py_BuildValue ("(ii)", format, division), + pymidi); +@@ -416,10 +419,12 @@ pymidi_parse (PyObject *self, PyObject *args) + { + unsigned char *midi, *midi_end; + unsigned long midi_size; ++ int clocks_max; + + debug_print ("%s", "\n"); +- if (!PyArg_ParseTuple (args, "s#", &midi, &midi_size)) ++ if (!PyArg_ParseTuple (args, "s#|i", &midi, &midi_size, &clocks_max)) + return 0; ++ debug_print ("clocks_max: %d\n", clocks_max); + + if (memcmp (midi, "MThd", 4)) + { +@@ -431,14 +436,13 @@ pymidi_parse (PyObject *self, PyObject *args) + + midi_end = midi + midi_size; + +- return midi_parse (&midi, midi_end); ++ return midi_parse (&midi, midi_end, clocks_max); + } + +- + static PyMethodDef MidiMethods[] = + { +- {"parse", pymidi_parse, 1}, +- {"parse_track", pymidi_parse_track, 1}, ++ {"parse", pymidi_parse, METH_VARARGS}, ++ {"parse_track", pymidi_parse_track, METH_VARARGS}, + {0, 0} /* Sentinel */ + }; + +diff --git a/scripts/midi2ly.py b/scripts/midi2ly.py +index afe5c5a..9ce050b 100644 +--- a/scripts/midi2ly.py ++++ b/scripts/midi2ly.py +@@ -817,7 +817,8 @@ def convert_midi (in_file, out_file): + global allowed_tuplet_clocks + + str = open (in_file, 'rb').read () +- midi_dump = midi.parse (str) ++ clocks_max = bar_max * clocks_per_1 * 2 ++ midi_dump = midi.parse (str, clocks_max) + + clocks_per_1 = midi_dump[0][1] + clocks_per_4 = clocks_per_1 / 4 +-- +1.7.1 +