one. Two SIGINTs in less than one second will kill the abcplay.py
process. This should be familiar to users of mpg123_ or ogg123_.
+You can also play LilyPond_ files (converted to MIDI via ``lilypond``)
+by using the ``--ly`` option::
+
+ abcplay.py --ly somefile.ly anotherfile.ly
+
.. _abc2midi: http://abc.sourceforge.net/abcMIDI/
.. _timidity: http://timidity.sourceforge.net/
.. _mpg123: http://www.mpg123.org/
.. _ogg123: http://www.vorbis.com
+.. _LilyPond: http://lilypond.org/
"""
import shlex
from tempfile import mkstemp
from time import time
from os import remove
+import os.path
-REFNUM_SEP = ':'
-
-class ABCPlayer (object):
- def __init__(self, abc2midi_options=None, timidity_options=None):
+class MIDIPlayer (object):
+ def __init__(self, to_midi_program=None,
+ to_midi_options=None, timidity_options=None):
f,self._tempfile = mkstemp(prefix='abcplay-', suffix='.midi')
- self._abc2midi = ['abc2midi']
- if abc2midi_options:
- self._abc2midi.extend(abc2midi_options)
+ self._to_midi = [to_midi_program]
+ if to_midi_options:
+ self._to_midi.extend(to_midi_options)
self._timidity = ['timidity']
if timidity_options:
self._timidity.extend(timidity_options)
remove(self._tempfile)
def play_files(self, filenames):
- for filename in filenames:
- if REFNUM_SEP in filename:
- fields = filename.split(REFNUM_SEP)
- filename = fields[0]
- refnums = fields[1:]
- else:
- 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
+ raise NotImplementedError()
def _return_after_interrupt(self):
t = time()
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)
+ def play(self, filename, **kwargs):
+ self._convert_to_midi(filename, **kwargs)
self._play_midi()
- def _convert_to_midi(self, filename, refnum):
- self._p = Popen(
- self._abc2midi + [filename, str(refnum), '-o', self._tempfile])
- self._p.wait()
- self._p = None
+ def _convert_to_midi(self, filename, **kwargs):
+ raise NotImplementedError()
def _play_midi(self):
self._p = Popen(self._timidity + [self._tempfile])
self._p.wait()
self._p = None
+
+class ABCPlayer (MIDIPlayer):
+ refnum_sep = ':'
+
+ def __init__(self, abc2midi_options=None, timidity_options=None):
+ super(ABCPlayer, self).__init__(
+ 'abc2midi', abc2midi_options, timidity_options)
+
+ def play_files(self, filenames):
+ for filename in filenames:
+ if self.refnum_sep in filename:
+ fields = filename.split(self.refnum_sep)
+ filename = fields[0]
+ refnums = fields[1:]
+ else:
+ refnums = list(self._refnums(filename))
+ while len(refnums) > 0:
+ refnum = refnums.pop(0)
+ try:
+ self.play(filename, refnum=refnum)
+ except KeyboardInterrupt:
+ self._kill_p()
+ if self._return_after_interrupt():
+ return
+
+ def _refnums(self, filename):
+ with open(filename, 'r') as f:
+ for line in f:
+ if line.startswith('X:'):
+ yield int(line[len('X:'):])
+
+ def _convert_to_midi(self, filename, refnum):
+ self._p = Popen(
+ self._to_midi + [filename, str(refnum), '-o', self._tempfile])
+ self._p.wait()
+ self._p = None
+
+
+class LilyPondPlayer (MIDIPlayer):
+ def __init__(self, lilypond_options=None, timidity_options=None):
+ default_lilypond_options = [
+ '-dbackend=null', # don't create a typeset version
+ '-ddelete-intermediate-files', # clean up after ourselves
+ ]
+ if lilypond_options:
+ lilypond_options = default_lilypond_options + lilypond_options
+ else:
+ lilypond_options = default_lilypond_options
+ super(LilyPondPlayer, self).__init__(
+ 'lilypond', lilypond_options, timidity_options)
+
+ def play_files(self, filenames):
+ for filename in filenames:
+ try:
+ self.play(filename)
+ except KeyboardInterrupt:
+ self._kill_p()
+ if self._return_after_interrupt():
+ return
+
+ def _convert_to_midi(self, filename):
+ ofilename,ext = os.path.splitext(self._tempfile)
+ assert ext == '.midi', ext # lilypond adds suffix automatically
+ #-dmidi-extension=midi
+ self._p = Popen(
+ self._to_midi + ['-o', ofilename, filename])
+ self._p.wait()
+ self._p = None
+
+
if __name__ == '__main__':
import sys
import optparse
help='Extra options to pass to abc2midi.')
p.add_option('-t', '--timidity', dest='timidity',
help='Extra options to pass to timidity.')
+ p.add_option('-l', '--ly', dest='use_lilypond', action='store_true',
+ help='Use LilyPond input instead of ABC.')
+ p.add_option('--lilypond', dest='lilypond',
+ help='Extra options to pass to LilyPond.')
options,args = p.parse_args()
del p
timidity = options.timidity
if timidity:
timidity = shlex.split(timidity)
-
- p = ABCPlayer(abc2midi, timidity)
+ lilypond = options.lilypond
+ if lilypond:
+ lilypond = shlex.split(lilypond)
+
+ if options.use_lilypond:
+ p = LilyPondPlayer(lilypond, timidity)
+ else:
+ p = ABCPlayer(abc2midi, timidity)
try:
p.play_files(args)
finally: