From 7597f8b630316f1b3bbc3964ed48a6a20250f16a Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 13 Nov 2010 13:55:48 -0500 Subject: [PATCH] Update abcplay.sh -> abcplay.py and improve signal handling. I hadn't looked at abcplay.sh for a while, and I like Python more now than I did whenever I'd written the Bash version, so I rewrote the script in Python. On ^C, the new version skips to the next refnum (the old version skipped to the next file). --- posts/abcplay.mdwn | 3 +- posts/abcplay/abcplay.py | 87 ++++++++++++++++++++++++++++++++++++++++ posts/abcplay/abcplay.sh | 40 ------------------ 3 files changed, 89 insertions(+), 41 deletions(-) create mode 100755 posts/abcplay/abcplay.py delete mode 100755 posts/abcplay/abcplay.sh diff --git a/posts/abcplay.mdwn b/posts/abcplay.mdwn index 3873260..6df247c 100644 --- a/posts/abcplay.mdwn +++ b/posts/abcplay.mdwn @@ -19,7 +19,7 @@ search tools and repositories listed on the [ABC homepage][ABC] and [JC's page][JC]. To make playing ABC files as easy as possible, I've written a little -script, [[abcplay.sh]], which uses `abc2midi` to generate a MIDI file +script, [[abcplay.py]], which uses `abc2midi` to generate a MIDI file for each tune and then plays them with [timidity++][]. [Bill Whipple]: http://www.wiplstix.com/ @@ -33,4 +33,5 @@ for each tune and then plays them with [timidity++][]. [timidity++]: http://timidity.sourceforge.net/ [[!tag tags/fun]] +[[!tag tags/python]] [[!tag tags/tools]] diff --git a/posts/abcplay/abcplay.py b/posts/abcplay/abcplay.py new file mode 100755 index 0000000..a3cd6c7 --- /dev/null +++ b/posts/abcplay/abcplay.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# +# Copyright (C) 2009-2010 W. Trevor King +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program. If not, see +# . + +from subprocess import Popen +from tempfile import mkstemp +from time import time +from os import remove + + +class ABCPlayer (object): + def __init__(self): + f,self._tempfile = mkstemp(prefix='abcplay-', suffix='.midi') + self._last_interrupt = 0 + self._p = None + + def cleanup(self): + remove(self._tempfile) + + def play_files(self, filenames): + for filename in filenames: + refnums = list(self._refnums(filename)) + while len(refnums) > 0: + refnum = refnums.pop(0) + try: + self.play(filename, refnum) + except KeyboardInterrupt: + self._kill_p() + if self._return_after_interrupt(): + return + + def _return_after_interrupt(self): + t = time() + ret = t-self._last_interrupt < 1 + self._last_interrupt = t + return ret + + def _refnums(self, filename): + with open(filename, 'r') as f: + for line in f: + if line.startswith('X:'): + yield int(line[len('X:'):]) + + def play(self, filename, refnum): + self._convert_to_midi(filename, refnum) + self._play_midi() + + def _convert_to_midi(self, filename, refnum): + self._p = Popen( + ['abc2midi', filename, str(refnum), '-o', self._tempfile]) + self._p.wait() + self._p = None + + def _play_midi(self): + self._p = Popen(['timidity', self._tempfile]) + self._p.wait() + self._p = None + + def _kill_p(self): + if self._p != None: + self._p.terminate() + self._p.wait() + self._p = None + + +if __name__ == '__main__': + import sys + + p = ABCPlayer() + try: + p.play_files(sys.argv[1:]) + finally: + p.cleanup() diff --git a/posts/abcplay/abcplay.sh b/posts/abcplay/abcplay.sh deleted file mode 100755 index ccc01e0..0000000 --- a/posts/abcplay/abcplay.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2009-2010 W. Trevor King -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this program. If not, see -# . - - -MIDI_FILE=`mktemp --tmpdir abcmidi-XXXXXX` - -USER_INTERRUPT=13 -LAST_SIGINT=0 -# Clean up and exit on SIGTERM (default signal from kill command) -trap 'rm -f "$MIDI_FILE"; exit $USER_INTERRUPT' TERM HUP -# Clean up and continue to next song on SIGINT (^C) -# If two SIGINTS come in the same second, exit. -trap 'rm -f "$MIDI_FILE"; TIME=`date +%s`; - let "DELAY = TIME - LAST_SIGINT"; - if [ "$DELAY" -eq 0 ] || [ "$DELAY" -eq 1 ]; then exit $USER_INTERRUPT; fi - LAST_SIGINT="$TIME";' INT - -for ABC_FILE in $*; do - grep '^X:' "$ABC_FILE" | cut -d: -f2 | while read REFNUM - do - abc2midi "$ABC_FILE" "$REFNUM" -o "$MIDI_FILE" - timidity "$MIDI_FILE" - rm -f "$MIDI_FILE" - done -done -- 2.26.2