+1.5.18.jcn1
+===========
+
+* Moved python modules to ./python.
+
+* Better python module stepmake support.
+
+* Bugfix ly2dvi etc: LILYPONDPREFIX should override datadir.
+
+1.5.18
+======
+
1.5.17.jcn6 - aka: `pgwit! Ah, dacht dat-i zo wel aardig was.'
===========
# descent order into subdirectories
#
-SUBDIRS = buildscripts scripts flower lily \
+SUBDIRS = buildscripts python scripts \
+ flower lily \
mf ly tex ps scm \
- modules midi2ly po make intl \
+ midi2ly po make intl \
debian $(builddir)/stepmake \
Documentation input \
mutopia ports
MAJOR_VERSION=1
MINOR_VERSION=5
PATCH_LEVEL=18
-MY_PATCH_LEVEL=
+MY_PATCH_LEVEL=jcn1
# use the above to send patches: MY_PATCH_LEVEL is always empty for a
# released version.
depth = ..
-#STEPMAKE_TEMPLATES=script install install-out po
STEPMAKE_TEMPLATES=script install po
-INSTALLATION_FILES=$(outdir)/gettext.py $(outdir)/lilylib.py
-INSTALLATION_DIR=$(datadir)/python
-
include $(depth)/make/stepmake.make
# Should we install these? This should be handled by sysadmin or
-"""This module allows python programs to use GNU gettext message catalogs.
-
-Author: James Henstridge <james@daa.com.au>
-(This is loosely based on gettext.pl in the GNU gettext distribution)
-
-The best way to use it is like so:
- import gettext
- gettext.bindtextdomain(PACKAGE, LOCALEDIR)
- gettext.textdomain(PACKAGE)
- _ = gettext.gettext
- print _('Hello World')
-
-where PACKAGE is the domain for this package, and LOCALEDIR is usually
-'$prefix/share/locale' where $prefix is the install prefix.
-
-If you have more than one catalog to use, you can directly create catalog
-objects. These objects are created as so:
- import gettext
- cat = gettext.Catalog(PACKAGE, localedir=LOCALEDIR)
- _ = cat.gettext
- print _('Hello World')
-
-The catalog object can also be accessed as a dictionary (ie cat['hello']).
-
-There are also some experimental features. You can add to the catalog, just
-as you would with a normal dictionary. When you are finished, you can call
-its save method, which will create a new .mo file containing all the
-translations:
- import gettext
- cat = Catalog()
- cat['Hello'] = 'konichiwa'
- cat.save('./tmp.mo')
-
-Once you have written an internationalized program, you can create a .po file
-for it with "xgettext --keyword=_ fillename ...". Then do the translation and
-compile it into a .mo file, ready for use with this module. Note that you
-will have to use C style strings (ie. use double quotes) for proper string
-extraction.
-"""
-import os, string
-
-prefix = '/usr/local'
-localedir = prefix + '/share/locale'
-
-def _expandLang(str):
- langs = [str]
- # remove charset ...
- if '.' in str:
- langs.append(string.split(str, '.')[0])
- # also add 2 character language code ...
- if len(str) > 2:
- langs.append(str[:2])
- return langs
-
-lang = []
-for env in 'LANGUAGE', 'LC_ALL', 'LC_MESSAGES', 'LANG':
- if os.environ.has_key(env):
- lang = string.split(os.environ[env], ':')
- lang = map(_expandLang, lang)
- lang = reduce(lambda a, b: a + b, lang)
- break
-if 'C' not in lang:
- lang.append('C')
-
-# remove duplicates
-i = 0
-while i < len(lang):
- j = i + 1
- while j < len(lang):
- if lang[i] == lang[j]:
- del lang[j]
- else:
- j = j + 1
- i = i + 1
-del i, j
-
-if os.environ.has_key('PY_XGETTEXT'):
- xgettext = os.environ['PY_XGETTEXT']
-else:
- xgettext = None
-
-del os, string
-
-error = 'gettext.error'
-
-def _lsbStrToInt(str):
- return ord(str[0]) + \
- (ord(str[1]) << 8) + \
- (ord(str[2]) << 16) + \
- (ord(str[3]) << 24)
-def _msbStrToInt(str):
- return (ord(str[0]) << 24) + \
- (ord(str[1]) << 16) + \
- (ord(str[2]) << 8) + \
- ord(str[3])
-def _intToLsbStr(int):
- return chr(int & 0xff) + \
- chr((int >> 8) & 0xff) + \
- chr((int >> 16) & 0xff) + \
- chr((int >> 24) & 0xff)
-
-def _getpos(levels = 0):
- """Returns the position in the code where the function was called.
- The function uses some knowledge about python stack frames."""
- import sys
- # get access to the stack frame by generating an exception.
- try:
- raise RuntimeError
- except RuntimeError:
- frame = sys.exc_traceback.tb_frame
- frame = frame.f_back # caller's frame
- while levels > 0:
- frame = frame.f_back
- levels = levels - 1
- return (frame.f_globals['__name__'],
- frame.f_code.co_name,
- frame.f_lineno)
-
-class Catalog:
- def __init__(self, domain=None, localedir=localedir):
- self.domain = domain
- self.localedir = localedir
- self.cat = {}
- if not domain: return
- for self.lang in lang:
- if self.lang == 'C':
- return
- catalog = "%s//%s/LC_MESSAGES/%s.mo" % (
- localedir, self.lang, domain)
- try:
- f = open(catalog, "rb")
- buffer = f.read()
- del f
- break
- except IOError:
- pass
- else:
- return # assume C locale
-
- strToInt = _lsbStrToInt
- if strToInt(buffer[:4]) != 0x950412de:
- # catalog is encoded with MSB offsets.
- strToInt = _msbStrToInt
- if strToInt(buffer[:4]) != 0x950412de:
- # magic number doesn't match
- raise error, 'Bad magic number in %s' % (catalog,)
-
- self.revision = strToInt(buffer[4:8])
- nstrings = strToInt(buffer[8:12])
- origTabOffset = strToInt(buffer[12:16])
- transTabOffset = strToInt(buffer[16:20])
- for i in range(nstrings):
- origLength = strToInt(buffer[origTabOffset:
- origTabOffset+4])
- origOffset = strToInt(buffer[origTabOffset+4:
- origTabOffset+8])
- origTabOffset = origTabOffset + 8
- origStr = buffer[origOffset:origOffset+origLength]
-
- transLength = strToInt(buffer[transTabOffset:
- transTabOffset+4])
- transOffset = strToInt(buffer[transTabOffset+4:
- transTabOffset+8])
- transTabOffset = transTabOffset + 8
- transStr = buffer[transOffset:transOffset+transLength]
-
- self.cat[origStr] = transStr
-
- def gettext(self, string):
- """Get the translation of a given string"""
- if self.cat.has_key(string):
- return self.cat[string]
- else:
- return string
- # allow catalog access as cat(str) and cat[str] and cat.gettext(str)
- __getitem__ = gettext
- __call__ = gettext
-
- # this is experimental code for producing mo files from Catalog objects
- def __setitem__(self, string, trans):
- """Set the translation of a given string"""
- self.cat[string] = trans
- def save(self, file):
- """Create a .mo file from a Catalog object"""
- try:
- f = open(file, "wb")
- except IOError:
- raise error, "can't open " + file + " for writing"
- f.write(_intToLsbStr(0x950412de)) # magic number
- f.write(_intToLsbStr(0)) # revision
- f.write(_intToLsbStr(len(self.cat))) # nstrings
-
- oIndex = []; oData = ''
- tIndex = []; tData = ''
- for orig, trans in self.cat.items():
- oIndex.append((len(orig), len(oData)))
- oData = oData + orig + '\0'
- tIndex.append((len(trans), len(tData)))
- tData = tData + trans + '\0'
- oIndexOfs = 20
- tIndexOfs = oIndexOfs + 8 * len(oIndex)
- oDataOfs = tIndexOfs + 8 * len(tIndex)
- tDataOfs = oDataOfs + len(oData)
- f.write(_intToLsbStr(oIndexOfs))
- f.write(_intToLsbStr(tIndexOfs))
- for length, offset in oIndex:
- f.write(_intToLsbStr(length))
- f.write(_intToLsbStr(offset + oDataOfs))
- for length, offset in tIndex:
- f.write(_intToLsbStr(length))
- f.write(_intToLsbStr(offset + tDataOfs))
- f.write(oData)
- f.write(tData)
-
-_cat = None
-_cats = {}
-
-if xgettext:
- class Catalog:
- def __init__(self, domain, localedir):
- self.domain = domain
- self.localedir = localedir
- self._strings = {}
- def gettext(self, string):
- # there is always one level of redirection for calls
- # to this function
- pos = _getpos(2) # get this function's caller
- if self._strings.has_key(string):
- if pos not in self._strings[string]:
- self._strings[string].append(pos)
- else:
- self._strings[string] = [pos]
- return string
- __getitem__ = gettext
- __call__ = gettext
- def __setitem__(self, item, data):
- pass
- def save(self, file):
- pass
- def output(self, fp):
- import string
- fp.write('# POT file for domain %s\n' % (self.domain,))
- for str in self._strings.keys():
- pos = map(lambda x: "%s(%s):%d" % x,
- self._strings[str])
- pos.sort()
- length = 80
- for p in pos:
- if length + len(p) > 74:
- fp.write('\n#:')
- length = 2
- fp.write(' ')
- fp.write(p)
- length = length + 1 + len(p)
- fp.write('\n')
- if '\n' in str:
- fp.write('msgid ""\n')
- lines = string.split(str, '\n')
- lines = map(lambda x:
- '"%s\\n"\n' % (x,),
- lines[:-1]) + \
- ['"%s"\n' % (lines[-1],)]
- fp.writelines(lines)
- else:
- fp.write('msgid "%s"\n' % (str,))
- fp.write('msgstr ""\n')
-
- import sys
- if hasattr(sys, 'exitfunc'):
- _exitchain = sys.exitfunc
- else:
- _exitchain = None
- def exitfunc(dir=xgettext, _exitchain=_exitchain):
- # actually output all the .pot files.
- import os
- for file in _cats.keys():
- fp = open(os.path.join(dir, file + '.pot'), 'w')
- cat = _cats[file]
- cat.output(fp)
- fp.close()
- if _exitchain: _exitchain()
- sys.exitfunc = exitfunc
- del sys, exitfunc, _exitchain, xgettext
-
-def bindtextdomain(domain, localedir=localedir):
- global _cat
- if not _cats.has_key(domain):
- _cats[domain] = Catalog(domain, localedir)
- if not _cat: _cat = _cats[domain]
-
-def textdomain(domain):
- global _cat
- if not _cats.has_key(domain):
- _cats[domain] = Catalog(domain)
- _cat = _cats[domain]
-
-def gettext(string):
- if _cat == None: raise error, "No catalog loaded"
- return _cat.gettext(string)
-
-_ = gettext
-
-def dgettext(domain, string):
- if domain is None:
- return gettext(string)
- if not _cats.has_key(domain):
- raise error, "Domain '" + domain + "' not loaded"
- return _cats[domain].gettext(string)
-
-def test():
- import sys
- global localedir
- if len(sys.argv) not in (2, 3):
- print "Usage: %s DOMAIN [LOCALEDIR]" % (sys.argv[0],)
- sys.exit(1)
- domain = sys.argv[1]
- if len(sys.argv) == 3:
- bindtextdomain(domain, sys.argv[2])
- textdomain(domain)
- info = gettext('') # this is where special info is often stored
- if info:
- print "Info for domain %s, lang %s." % (domain, _cat.lang)
- print info
- else:
- print "No info given in mo file."
-
-if __name__ == '__main__':
- test()
-
-# lilylib.py -- options and stuff
-#
-# source file of the GNU LilyPond music typesetter
-
-import os
-from __main__ import *
-
-try:
- import gettext
- gettext.bindtextdomain ('lilypond', '@localedir@')
- gettext.textdomain ('lilypond')
- _ = gettext.gettext
-except:
- def _ (s):
- return s
-
-program_version = '@TOPLEVEL_VERSION@'
-if program_version == '@' + 'TOPLEVEL_VERSION' + '@':
- program_version = '1.5.17'
-
-
-original_dir = os.getcwd ()
-temp_dir = os.path.join (original_dir, '%s.dir' % program_name)
-
-errorport = sys.stderr
-keep_temp_dir_p = 0
-verbose_p = 0
-
-
-def identify ():
- sys.stdout.write ('%s (GNU LilyPond) %s\n' % (program_name, program_version))
-
-def warranty ():
- identify ()
- sys.stdout.write ('\n')
- sys.stdout.write (_ ('Copyright (c) %s by' % ' 2001'))
- sys.stdout.write ('\n')
- sys.stdout.write (' Han-Wen Nienhuys')
- sys.stdout.write (' Jan Nieuwenhuizen')
- sys.stdout.write ('\n')
- sys.stdout.write (_ (r'''
-Distributed under terms of the GNU General Public License. It comes with
-NO WARRANTY.'''))
- sys.stdout.write ('\n')
-
-def progress (s):
- errorport.write (s + '\n')
-
-def warning (s):
- progress (_ ("warning: ") + s)
-
-def error (s):
-
-
- '''Report the error S. Exit by raising an exception. Please
- do not abuse by trying to catch this error. If you do not want
- a stack trace, write to the output directly.
-
- RETURN VALUE
-
- None
-
- '''
-
- progress (_ ("error: ") + s)
- raise _ ("Exiting ... ")
-
-def getopt_args (opts):
- '''Construct arguments (LONG, SHORT) for getopt from list of options.'''
- short = ''
- long = []
- for o in opts:
- if o[1]:
- short = short + o[1]
- if o[0]:
- short = short + ':'
- if o[2]:
- l = o[2]
- if o[0]:
- l = l + '='
- long.append (l)
- return (short, long)
-
-def option_help_str (o):
- '''Transform one option description (4-tuple ) into neatly formatted string'''
- sh = ' '
- if o[1]:
- sh = '-%s' % o[1]
-
- sep = ' '
- if o[1] and o[2]:
- sep = ','
-
- long = ''
- if o[2]:
- long= '--%s' % o[2]
-
- arg = ''
- if o[0]:
- if o[2]:
- arg = '='
- arg = arg + o[0]
- return ' ' + sh + sep + long + arg
-
-
-def options_help_str (opts):
- '''Convert a list of options into a neatly formatted string'''
- w = 0
- strs =[]
- helps = []
-
- for o in opts:
- s = option_help_str (o)
- strs.append ((s, o[3]))
- if len (s) > w:
- w = len (s)
-
- str = ''
- for s in strs:
- str = str + '%s%s%s\n' % (s[0], ' ' * (w - len(s[0]) + 3), s[1])
- return str
-
-def help ():
- ls = [(_ ("Usage: %s [OPTION]... FILE") % program_name),
- ('\n\n'),
- (help_summary),
- ('\n\n'),
- (_ ("Options:")),
- ('\n'),
- (options_help_str (option_definitions)),
- ('\n\n'),
- (_ ("Report bugs to %s") % 'bug-lilypond@gnu.org'),
- ('\n')]
- map (sys.stdout.write, ls)
-
-def setup_temp ():
- """
- Create a temporary directory, and return its name.
- """
- global temp_dir
- if not keep_temp_dir_p:
- temp_dir = tempfile.mktemp (program_name)
- try:
- os.mkdir (temp_dir, 0777)
- except OSError:
- pass
-
- return temp_dir
-
-
-def system (cmd, ignore_error = 0):
- """Run CMD. If IGNORE_ERROR is set, don't complain when CMD returns non zero.
-
- RETURN VALUE
-
- Exit status of CMD
- """
-
- if verbose_p:
- progress (_ ("Invoking `%s\'") % cmd)
- st = os.system (cmd)
- if st:
- name = re.match ('[ \t]*([^ \t]*)', cmd).group (1)
- msg = name + ': ' + _ ("command exited with value %d") % st
- if ignore_error:
- warning (msg + ' ' + _ ("(ignored)") + ' ')
- else:
- error (msg)
-
- return st
-
-
-def cleanup_temp ():
- if not keep_temp_dir_p:
- if verbose_p:
- progress (_ ("Cleaning %s...") % temp_dir)
- shutil.rmtree (temp_dir)
-
-
-def strip_extension (f, ext):
- (p, e) = os.path.splitext (f)
- if e == ext:
- e = ''
- return p + e
-
-# END Library
-
endif
export LILYPONDPREFIX:=$(depth)/
-export PYTHONPATH:=$(buildscript-dir)/$(outdir):$(PYTHONPATH)
+export PYTHONPATH:=$(topdir)/python:$(PYTHONPATH)
# guile load path?
SUBDIRS = include
MODULE_LIBS=$(depth)/flower
-HELP2MAN_EXECS = midi2ly
+HELP2MAN_EXECS = midi2ly-old
STEPMAKE_TEMPLATES=c++ executable po help2man
include $(depth)/make/stepmake.make
-depth = ..
-
-# Hmm, name dir midi too, then?
-NAME=midi
-
-
-# compile fucks up on without autoconf -I flag.
-STEPMAKE_TEMPLATES=c install python-module
-
-INSTALLATION_FILES=$(outdir)/midi.so
-INSTALLATION_DIR=$(datadir)/python
-
-# do nothing; module ins't used yet.
-
-include $(depth)/make/stepmake.make
-
-/*
- midi.c -- implement Python midi parser module
-
- source file of the GNU LilyPond music typesetter
-
- (c) 2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
- Jan Nieuwenhuizen <janneke@gnu.org>
-
-*/
-
-/*
-
-python2
-import midi
-s = open ("s.midi").read ()
-midi.parse_track (s)
-midi.parse (s)
-
-*/
-
-#include "config.h"
-
-/* urg */
-#if HAVE_PYTHON2_PYTHON_H
-#include <python2/Python.h>
-#elif HAVE_PYTHON2_1_PYTHON_H
-#include <python2.1/Python.h>
-#elif HAVE_PYTHON2_0_PYTHON_H
-#include <python2.0/Python.h>
-#elif HAVE_PYTHON1_5_PYTHON_H
-#include <python1.5/Python.h>
-#elif HAVE_PYTHON_PYTHON_H
-#define assert(x)
-#include <python/Python.h>
-#elif HAVE_PYTHON_H
-#define assert(x)
-#include <Python.h>
-#else
-#error Need Python.h
-#endif
-
-#if 0
-int x = 0;
-int *track = &x;
-#define debug_print(f, args...) fprintf (stderr, "%s:%d: track: %p :" f, __FUNCTION__, __LINE__, *track, ##args)
-#else
-#define debug_print(f, args...)
-#endif
-
-static PyObject *Midi_error;
-static PyObject *Midi_warning;
-
-static PyObject *
-midi_error (char *s)
-{
- PyErr_SetString (Midi_error, s);
- return 0;
-}
-
-static PyObject *
-midi_warning (char *s)
-{
- PyErr_SetString (Midi_warning, s);
- return 0;
-}
-
-
-typedef struct message {
- unsigned char msg;
- char * description;
-} message_t;
-
-message_t channelVoiceMessages[] = {
- 0x80, "NOTE_OFF",
- 0x90, "NOTE_ON",
- 0xA0, "POLYPHONIC_KEY_PRESSURE",
- 0xB0, "CONTROLLER_CHANGE",
- 0xC0, "PROGRAM_CHANGE",
- 0xD0, "CHANNEL_KEY_PRESSURE",
- 0xE0, "PITCH_BEND",
- 0,0
-};
-
-message_t channelModeMessages[] = {
- 0x78, "ALL_SOUND_OFF",
- 0x79, "RESET_ALL_CONTROLLERS",
- 0x7A, "LOCAL_CONTROL",
- 0x7B, "ALL_NOTES_OFF",
- 0x7C, "OMNI_MODE_OFF",
- 0x7D, "OMNI_MODE_ON",
- 0x7E, "MONO_MODE_ON",
- 0x7F, "POLY_MODE_ON",
- 0,0
-};
-
-message_t metaEvents[] = {
- 0x00, "SEQUENCE_NUMBER",
- 0x01, "TEXT_EVENT",
- 0x02, "COPYRIGHT_NOTICE",
- 0x03, "SEQUENCE_TRACK_NAME",
- 0x04, "INSTRUMENT_NAME",
- 0x05, "LYRIC",
- 0x06, "MARKER",
- 0x07, "CUE_POINT",
- 0x20, "MIDI_CHANNEL_PREFIX",
- 0x21, "MIDI_PORT",
- 0x2F, "END_OF_TRACK",
- 0x51, "SET_TEMPO",
- 0x54, "SMTPE_OFFSET",
- 0x58, "TIME_SIGNATURE",
- 0x59, "KEY_SIGNATURE",
- 0x7F, "SEQUENCER_SPECIFIC_META_EVENT",
- 0xFF, "META_EVENT",
- 0,0
-};
-
-void
-add_constants (PyObject *dict)
-{
- message_t * p[] = {metaEvents, channelModeMessages, channelVoiceMessages ,0};
- int i,j;
- for ( j =0; p[j]; j++)
- for ( i = 0; p[j][i].description; i++)
- PyDict_SetItemString (dict, p[j][i].description, Py_BuildValue ("i", p[j][i].msg));
-}
-
-unsigned long int
-get_number (unsigned char ** str, unsigned char * end_str, int length)
-{
- /* # MIDI uses big-endian for everything */
- long sum = 0;
- int i = 0;
-
- for (; i < length; i++)
- sum = (sum << 8) + (unsigned char) (*str)[i];
-
- *str += length;
- debug_print ("%d:\n", sum);
- return sum;
-}
-
-unsigned long int
-get_variable_length_number (unsigned char **str, unsigned char * end_str)
-{
- long sum = 0;
- int i = 0;
- while (*str < end_str)
- {
- unsigned char x = **str;
- (*str) ++;
- sum = (sum << 7) + (x & 0x7F);
- if (!(x & 0x80))
- break;
- }
- debug_print ("%d:\n", sum);
- return sum;
-}
-
-PyObject *
-read_one_byte (unsigned char **track, unsigned char *end,
- unsigned char x)
-{
- PyObject *pyev = Py_BuildValue ("(i)", x);
- debug_print ("%x:%s", x, "event\n");
-
- return pyev;
-}
-
-PyObject *
-read_two_bytes (unsigned char **track, unsigned char *end,
- unsigned char x)
-{
- PyObject *pyev = Py_BuildValue ("(ii)", x, (*track)[0]);
- *track += 1;
- debug_print ("%x:%s", x, "event\n");
- return pyev;
-}
-
-PyObject *
-read_three_bytes (unsigned char **track, unsigned char *end,
- unsigned char x)
-{
- PyObject *pyev = Py_BuildValue ("(iii)", x, (*track)[0],
- (*track)[1]);
-
- *track += 2;
- debug_print ("%x:%s", x, "event\n");
- return pyev;
-}
-
-PyObject *
-read_string (unsigned char **track, unsigned char *end)
-{
- unsigned long length = get_variable_length_number (track, end);
- if (length > end - *track)
- length = end - *track;
-
- *track += length;
- return Py_BuildValue ("s#", ((*track) -length), length);
-}
-
-typedef PyObject* (*Read_midi_event)
- (unsigned char **track, unsigned char *end,
- unsigned char x);
-
-
-static PyObject *
-read_f0_byte (unsigned char **track, unsigned char *end,
- unsigned char x)
-
-{
- debug_print ("%x:%s", x, "event\n");
- if (x == 0xff)
- {
- unsigned char z = (*track)[0 ];
- *track += 1;
- debug_print ("%x:%s", z, "f0-event\n");
-
- return Py_BuildValue ("(iiO)", x, z, read_string (track, end));
- }
-
- return Py_BuildValue ("(iO)", x, read_string (track, end));
-}
-
-Read_midi_event read_midi_event [16] =
-{
- read_one_byte, // 0
- read_one_byte, // 10
- read_one_byte, // 20
- read_one_byte, // 30
- read_one_byte, // 40
- read_one_byte, // 50
- read_one_byte, // 60 data entry.
- read_two_bytes, // 70 all notes off
- read_three_bytes, // 80 note off
- read_three_bytes, // 90 note on
- read_three_bytes, // a0 poly aftertouch
- read_three_bytes, // b0 control
- read_two_bytes, // c0 prog change
- read_two_bytes, // d0 ch aftertouch
- read_three_bytes, // e0 pitchwheel range
- read_f0_byte, // f0
-};
-
-
-static PyObject *
-read_event (unsigned char **track, unsigned char *end, PyObject *time,
- unsigned char *running_status)
-{
- int rsb_skip = ((**track & 0x80)) ? 1 :0;
-
- unsigned char x = (rsb_skip) ? (*track)[0]: *running_status;
-
- PyObject * bare_event = 0;
- debug_print ("%x:%s", x, "event\n");
- *running_status = x;
- *track += rsb_skip;
-
- // printf ("%x %x %d next %x\n", x, (*track)[0], rsb_skip, (*track)[1]);
- bare_event = (*read_midi_event[x >> 4]) (track, end, x);
- if (bare_event)
- return Py_BuildValue ("(OO)", time, bare_event);
- else
- return NULL;
-}
-
-static PyObject *
-midi_parse_track (unsigned char **track, unsigned char *track_end)
-{
- unsigned int time = 0;
- unsigned char running_status;
- unsigned long track_len, track_size;
- PyObject *pytrack = 0;
-
- debug_print ("%s", "\n");
-
- track_size = track_end - *track;
-
- debug_print ("%s", "\n");
- if (strcmp (*track, "MTrk"))
- return midi_error (__FUNCTION__ ": MTrk expected");
-
- *track += 4;
-
- 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 begin: %p\n", track);
- debug_print ("track end: %p\n", track + track_len);
-
- if (track_len > track_size)
- return midi_error (__FUNCTION__ ": track size corrupt");
-
- pytrack = PyList_New (0);
-
- track_end = *track + track_len;
-
- {
- PyObject *pytime = PyInt_FromLong (0L);
- while (*track < track_end)
- {
- long dt = get_variable_length_number(track, track_end);
- PyObject *pyev = 0;
-
- time += dt;
- if (dt)
- pytime = PyInt_FromLong (time);
-
- pyev = read_event (track, track_end, pytime,
- &running_status);
- if (pyev)
- PyList_Append (pytrack, pyev);
- }
- }
-
- *track = track_end;
- return pytrack;
-}
-
-
-static PyObject *
-pymidi_parse_track (PyObject *self, PyObject *args)
-{
- unsigned char *track, *track_end;
- unsigned long track_size, track_len;
-
- PyObject * sobj = PyTuple_GetItem (args, 0);
-
- debug_print ("%s", "\n");
- if (!PyArg_ParseTuple (args, "s#", &track, &track_size))
- return 0;
-
- if (track_size < 0)
- return midi_error (__FUNCTION__ ": negative track size");
-
- track_end = track + track_size;
-
- return midi_parse_track (&track, track_end);
-}
-
-static PyObject *
-midi_parse (unsigned char **midi,unsigned char *midi_end)
-{
- PyObject *pymidi = 0;
- unsigned long header_len;
- unsigned format, tracks;
- int division;
- int i;
-
- debug_print ("%s", "\n");
-
- /* Header */
- header_len = get_number (midi, *midi + 4, 4);
-
-
- if (header_len < 6)
- return midi_error (__FUNCTION__ ": header too short");
-
- format = get_number (midi, *midi + 2, 2);
- tracks = get_number (midi, *midi + 2, 2);
-
- if (tracks > 32)
- return midi_error (__FUNCTION__ ": too many tracks");
-
- division = get_number (midi, *midi + 2, 2) * 4;
-
-
- if (division < 0)
- /* return midi_error ("can't handle non-metrical time"); */
- ;
- *midi += header_len - 6;
-
- pymidi = PyList_New (0);
-
- /* Tracks */
- for (i = 0; i < tracks; i++)
- PyList_Append (pymidi, midi_parse_track (midi, midi_end));
-
- pymidi = Py_BuildValue ("(OO)", Py_BuildValue ("(ii)", format, division),
- pymidi);
- return pymidi;
-}
-
-static PyObject *
-pymidi_parse (PyObject *self, PyObject *args)
-{
- unsigned char *midi, *midi_end;
- unsigned long midi_size, midi_len;
-
- PyObject *sobj = PyTuple_GetItem (args, 0);
-
- debug_print ("%s", "\n");
- if (!PyArg_ParseTuple (args, "s#", &midi, &midi_size))
- return 0;
-
- if (strcmp (midi, "MThd"))
- return midi_error (__FUNCTION__ ": MThd expected");
-
- midi += 4;
-
- midi_end = midi + midi_size;
-
- return midi_parse (&midi, midi_end);
-}
-
-
-static PyMethodDef MidiMethods[] =
-{
- {"parse", pymidi_parse, 1},
- {"parse_track", pymidi_parse_track, 1},
- {0, 0} /* Sentinel */
-};
-
-initmidi ()
-{
- PyObject *m, *d;
- m = Py_InitModule ("midi", MidiMethods);
- d = PyModule_GetDict (m);
-
- Midi_error = PyString_FromString ("midi.error");
- PyDict_SetItemString (d, "error", Midi_error);
- add_constants (d);
- Midi_warning = PyString_FromString ("midi.warning");
- PyDict_SetItemString (d, "warning", Midi_warning);
-}
--- /dev/null
+depth = ..
+
+INSTALLATION_FILES=$(PY_MODULES) $(OUT_PY_MODULES) $(OUT_SO_MODULES)
+INSTALLATION_DIR=$(datadir)/python
+
+STEPMAKE_TEMPLATES=c python-module install po
+
+include $(depth)/make/stepmake.make
+
+$(outdir)/midi.lo: $(outdir)/config.h
--- /dev/null
+"""This module allows python programs to use GNU gettext message catalogs.
+
+Author: James Henstridge <james@daa.com.au>
+(This is loosely based on gettext.pl in the GNU gettext distribution)
+
+The best way to use it is like so:
+ import gettext
+ gettext.bindtextdomain(PACKAGE, LOCALEDIR)
+ gettext.textdomain(PACKAGE)
+ _ = gettext.gettext
+ print _('Hello World')
+
+where PACKAGE is the domain for this package, and LOCALEDIR is usually
+'$prefix/share/locale' where $prefix is the install prefix.
+
+If you have more than one catalog to use, you can directly create catalog
+objects. These objects are created as so:
+ import gettext
+ cat = gettext.Catalog(PACKAGE, localedir=LOCALEDIR)
+ _ = cat.gettext
+ print _('Hello World')
+
+The catalog object can also be accessed as a dictionary (ie cat['hello']).
+
+There are also some experimental features. You can add to the catalog, just
+as you would with a normal dictionary. When you are finished, you can call
+its save method, which will create a new .mo file containing all the
+translations:
+ import gettext
+ cat = Catalog()
+ cat['Hello'] = 'konichiwa'
+ cat.save('./tmp.mo')
+
+Once you have written an internationalized program, you can create a .po file
+for it with "xgettext --keyword=_ fillename ...". Then do the translation and
+compile it into a .mo file, ready for use with this module. Note that you
+will have to use C style strings (ie. use double quotes) for proper string
+extraction.
+"""
+import os, string
+
+prefix = '/usr/local'
+localedir = prefix + '/share/locale'
+
+def _expandLang(str):
+ langs = [str]
+ # remove charset ...
+ if '.' in str:
+ langs.append(string.split(str, '.')[0])
+ # also add 2 character language code ...
+ if len(str) > 2:
+ langs.append(str[:2])
+ return langs
+
+lang = []
+for env in 'LANGUAGE', 'LC_ALL', 'LC_MESSAGES', 'LANG':
+ if os.environ.has_key(env):
+ lang = string.split(os.environ[env], ':')
+ lang = map(_expandLang, lang)
+ lang = reduce(lambda a, b: a + b, lang)
+ break
+if 'C' not in lang:
+ lang.append('C')
+
+# remove duplicates
+i = 0
+while i < len(lang):
+ j = i + 1
+ while j < len(lang):
+ if lang[i] == lang[j]:
+ del lang[j]
+ else:
+ j = j + 1
+ i = i + 1
+del i, j
+
+if os.environ.has_key('PY_XGETTEXT'):
+ xgettext = os.environ['PY_XGETTEXT']
+else:
+ xgettext = None
+
+del os, string
+
+error = 'gettext.error'
+
+def _lsbStrToInt(str):
+ return ord(str[0]) + \
+ (ord(str[1]) << 8) + \
+ (ord(str[2]) << 16) + \
+ (ord(str[3]) << 24)
+def _msbStrToInt(str):
+ return (ord(str[0]) << 24) + \
+ (ord(str[1]) << 16) + \
+ (ord(str[2]) << 8) + \
+ ord(str[3])
+def _intToLsbStr(int):
+ return chr(int & 0xff) + \
+ chr((int >> 8) & 0xff) + \
+ chr((int >> 16) & 0xff) + \
+ chr((int >> 24) & 0xff)
+
+def _getpos(levels = 0):
+ """Returns the position in the code where the function was called.
+ The function uses some knowledge about python stack frames."""
+ import sys
+ # get access to the stack frame by generating an exception.
+ try:
+ raise RuntimeError
+ except RuntimeError:
+ frame = sys.exc_traceback.tb_frame
+ frame = frame.f_back # caller's frame
+ while levels > 0:
+ frame = frame.f_back
+ levels = levels - 1
+ return (frame.f_globals['__name__'],
+ frame.f_code.co_name,
+ frame.f_lineno)
+
+class Catalog:
+ def __init__(self, domain=None, localedir=localedir):
+ self.domain = domain
+ self.localedir = localedir
+ self.cat = {}
+ if not domain: return
+ for self.lang in lang:
+ if self.lang == 'C':
+ return
+ catalog = "%s//%s/LC_MESSAGES/%s.mo" % (
+ localedir, self.lang, domain)
+ try:
+ f = open(catalog, "rb")
+ buffer = f.read()
+ del f
+ break
+ except IOError:
+ pass
+ else:
+ return # assume C locale
+
+ strToInt = _lsbStrToInt
+ if strToInt(buffer[:4]) != 0x950412de:
+ # catalog is encoded with MSB offsets.
+ strToInt = _msbStrToInt
+ if strToInt(buffer[:4]) != 0x950412de:
+ # magic number doesn't match
+ raise error, 'Bad magic number in %s' % (catalog,)
+
+ self.revision = strToInt(buffer[4:8])
+ nstrings = strToInt(buffer[8:12])
+ origTabOffset = strToInt(buffer[12:16])
+ transTabOffset = strToInt(buffer[16:20])
+ for i in range(nstrings):
+ origLength = strToInt(buffer[origTabOffset:
+ origTabOffset+4])
+ origOffset = strToInt(buffer[origTabOffset+4:
+ origTabOffset+8])
+ origTabOffset = origTabOffset + 8
+ origStr = buffer[origOffset:origOffset+origLength]
+
+ transLength = strToInt(buffer[transTabOffset:
+ transTabOffset+4])
+ transOffset = strToInt(buffer[transTabOffset+4:
+ transTabOffset+8])
+ transTabOffset = transTabOffset + 8
+ transStr = buffer[transOffset:transOffset+transLength]
+
+ self.cat[origStr] = transStr
+
+ def gettext(self, string):
+ """Get the translation of a given string"""
+ if self.cat.has_key(string):
+ return self.cat[string]
+ else:
+ return string
+ # allow catalog access as cat(str) and cat[str] and cat.gettext(str)
+ __getitem__ = gettext
+ __call__ = gettext
+
+ # this is experimental code for producing mo files from Catalog objects
+ def __setitem__(self, string, trans):
+ """Set the translation of a given string"""
+ self.cat[string] = trans
+ def save(self, file):
+ """Create a .mo file from a Catalog object"""
+ try:
+ f = open(file, "wb")
+ except IOError:
+ raise error, "can't open " + file + " for writing"
+ f.write(_intToLsbStr(0x950412de)) # magic number
+ f.write(_intToLsbStr(0)) # revision
+ f.write(_intToLsbStr(len(self.cat))) # nstrings
+
+ oIndex = []; oData = ''
+ tIndex = []; tData = ''
+ for orig, trans in self.cat.items():
+ oIndex.append((len(orig), len(oData)))
+ oData = oData + orig + '\0'
+ tIndex.append((len(trans), len(tData)))
+ tData = tData + trans + '\0'
+ oIndexOfs = 20
+ tIndexOfs = oIndexOfs + 8 * len(oIndex)
+ oDataOfs = tIndexOfs + 8 * len(tIndex)
+ tDataOfs = oDataOfs + len(oData)
+ f.write(_intToLsbStr(oIndexOfs))
+ f.write(_intToLsbStr(tIndexOfs))
+ for length, offset in oIndex:
+ f.write(_intToLsbStr(length))
+ f.write(_intToLsbStr(offset + oDataOfs))
+ for length, offset in tIndex:
+ f.write(_intToLsbStr(length))
+ f.write(_intToLsbStr(offset + tDataOfs))
+ f.write(oData)
+ f.write(tData)
+
+_cat = None
+_cats = {}
+
+if xgettext:
+ class Catalog:
+ def __init__(self, domain, localedir):
+ self.domain = domain
+ self.localedir = localedir
+ self._strings = {}
+ def gettext(self, string):
+ # there is always one level of redirection for calls
+ # to this function
+ pos = _getpos(2) # get this function's caller
+ if self._strings.has_key(string):
+ if pos not in self._strings[string]:
+ self._strings[string].append(pos)
+ else:
+ self._strings[string] = [pos]
+ return string
+ __getitem__ = gettext
+ __call__ = gettext
+ def __setitem__(self, item, data):
+ pass
+ def save(self, file):
+ pass
+ def output(self, fp):
+ import string
+ fp.write('# POT file for domain %s\n' % (self.domain,))
+ for str in self._strings.keys():
+ pos = map(lambda x: "%s(%s):%d" % x,
+ self._strings[str])
+ pos.sort()
+ length = 80
+ for p in pos:
+ if length + len(p) > 74:
+ fp.write('\n#:')
+ length = 2
+ fp.write(' ')
+ fp.write(p)
+ length = length + 1 + len(p)
+ fp.write('\n')
+ if '\n' in str:
+ fp.write('msgid ""\n')
+ lines = string.split(str, '\n')
+ lines = map(lambda x:
+ '"%s\\n"\n' % (x,),
+ lines[:-1]) + \
+ ['"%s"\n' % (lines[-1],)]
+ fp.writelines(lines)
+ else:
+ fp.write('msgid "%s"\n' % (str,))
+ fp.write('msgstr ""\n')
+
+ import sys
+ if hasattr(sys, 'exitfunc'):
+ _exitchain = sys.exitfunc
+ else:
+ _exitchain = None
+ def exitfunc(dir=xgettext, _exitchain=_exitchain):
+ # actually output all the .pot files.
+ import os
+ for file in _cats.keys():
+ fp = open(os.path.join(dir, file + '.pot'), 'w')
+ cat = _cats[file]
+ cat.output(fp)
+ fp.close()
+ if _exitchain: _exitchain()
+ sys.exitfunc = exitfunc
+ del sys, exitfunc, _exitchain, xgettext
+
+def bindtextdomain(domain, localedir=localedir):
+ global _cat
+ if not _cats.has_key(domain):
+ _cats[domain] = Catalog(domain, localedir)
+ if not _cat: _cat = _cats[domain]
+
+def textdomain(domain):
+ global _cat
+ if not _cats.has_key(domain):
+ _cats[domain] = Catalog(domain)
+ _cat = _cats[domain]
+
+def gettext(string):
+ if _cat == None: raise error, "No catalog loaded"
+ return _cat.gettext(string)
+
+_ = gettext
+
+def dgettext(domain, string):
+ if domain is None:
+ return gettext(string)
+ if not _cats.has_key(domain):
+ raise error, "Domain '" + domain + "' not loaded"
+ return _cats[domain].gettext(string)
+
+def test():
+ import sys
+ global localedir
+ if len(sys.argv) not in (2, 3):
+ print "Usage: %s DOMAIN [LOCALEDIR]" % (sys.argv[0],)
+ sys.exit(1)
+ domain = sys.argv[1]
+ if len(sys.argv) == 3:
+ bindtextdomain(domain, sys.argv[2])
+ textdomain(domain)
+ info = gettext('') # this is where special info is often stored
+ if info:
+ print "Info for domain %s, lang %s." % (domain, _cat.lang)
+ print info
+ else:
+ print "No info given in mo file."
+
+if __name__ == '__main__':
+ test()
+
--- /dev/null
+# lilylib.py -- options and stuff
+#
+# source file of the GNU LilyPond music typesetter
+
+import os
+from __main__ import *
+try:
+ import gettext
+ gettext.bindtextdomain ('lilypond', localedir)
+ gettext.textdomain ('lilypond')
+ _ = gettext.gettext
+except:
+ def _ (s):
+ return s
+
+if program_version == '@' + 'TOPLEVEL_VERSION' + '@':
+ program_version = '1.5.17'
+
+def identify ():
+ sys.stdout.write ('%s (GNU LilyPond) %s\n' % (program_name, program_version))
+
+def warranty ():
+ identify ()
+ sys.stdout.write ('\n')
+ sys.stdout.write (_ ('Copyright (c) %s by' % ' 2001'))
+ sys.stdout.write ('\n')
+ sys.stdout.write (' Han-Wen Nienhuys')
+ sys.stdout.write (' Jan Nieuwenhuizen')
+ sys.stdout.write ('\n')
+ sys.stdout.write (_ (r'''
+Distributed under terms of the GNU General Public License. It comes with
+NO WARRANTY.'''))
+ sys.stdout.write ('\n')
+
+def progress (s):
+ errorport.write (s + '\n')
+
+def warning (s):
+ progress (_ ("warning: ") + s)
+
+def error (s):
+
+
+ '''Report the error S. Exit by raising an exception. Please
+ do not abuse by trying to catch this error. If you do not want
+ a stack trace, write to the output directly.
+
+ RETURN VALUE
+
+ None
+
+ '''
+
+ progress (_ ("error: ") + s)
+ raise _ ("Exiting ... ")
+
+def getopt_args (opts):
+ '''Construct arguments (LONG, SHORT) for getopt from list of options.'''
+ short = ''
+ long = []
+ for o in opts:
+ if o[1]:
+ short = short + o[1]
+ if o[0]:
+ short = short + ':'
+ if o[2]:
+ l = o[2]
+ if o[0]:
+ l = l + '='
+ long.append (l)
+ return (short, long)
+
+def option_help_str (o):
+ '''Transform one option description (4-tuple ) into neatly formatted string'''
+ sh = ' '
+ if o[1]:
+ sh = '-%s' % o[1]
+
+ sep = ' '
+ if o[1] and o[2]:
+ sep = ','
+
+ long = ''
+ if o[2]:
+ long= '--%s' % o[2]
+
+ arg = ''
+ if o[0]:
+ if o[2]:
+ arg = '='
+ arg = arg + o[0]
+ return ' ' + sh + sep + long + arg
+
+
+def options_help_str (opts):
+ '''Convert a list of options into a neatly formatted string'''
+ w = 0
+ strs =[]
+ helps = []
+
+ for o in opts:
+ s = option_help_str (o)
+ strs.append ((s, o[3]))
+ if len (s) > w:
+ w = len (s)
+
+ str = ''
+ for s in strs:
+ str = str + '%s%s%s\n' % (s[0], ' ' * (w - len(s[0]) + 3), s[1])
+ return str
+
+def help ():
+ ls = [(_ ("Usage: %s [OPTION]... FILE") % program_name),
+ ('\n\n'),
+ (help_summary),
+ ('\n\n'),
+ (_ ("Options:")),
+ ('\n'),
+ (options_help_str (option_definitions)),
+ ('\n\n'),
+ (_ ("Report bugs to %s") % 'bug-lilypond@gnu.org'),
+ ('\n')]
+ map (sys.stdout.write, ls)
+
+def setup_temp ():
+ """
+ Create a temporary directory, and return its name.
+ """
+ global temp_dir
+ if not keep_temp_dir_p:
+ temp_dir = tempfile.mktemp (program_name)
+ try:
+ os.mkdir (temp_dir, 0777)
+ except OSError:
+ pass
+
+ return temp_dir
+
+
+def system (cmd, ignore_error = 0):
+ """Run CMD. If IGNORE_ERROR is set, don't complain when CMD returns non zero.
+
+ RETURN VALUE
+
+ Exit status of CMD
+ """
+
+ if verbose_p:
+ progress (_ ("Invoking `%s\'") % cmd)
+ st = os.system (cmd)
+ if st:
+ name = re.match ('[ \t]*([^ \t]*)', cmd).group (1)
+ msg = name + ': ' + _ ("command exited with value %d") % st
+ if ignore_error:
+ warning (msg + ' ' + _ ("(ignored)") + ' ')
+ else:
+ error (msg)
+
+ return st
+
+
+def cleanup_temp ():
+ if not keep_temp_dir_p:
+ if verbose_p:
+ progress (_ ("Cleaning %s...") % temp_dir)
+ shutil.rmtree (temp_dir)
+
+
+def strip_extension (f, ext):
+ (p, e) = os.path.splitext (f)
+ if e == ext:
+ e = ''
+ return p + e
+
+# END Library
+
--- /dev/null
+/*
+ midi.c -- implement Python midi parser module
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+ Jan Nieuwenhuizen <janneke@gnu.org>
+
+*/
+
+/*
+
+python2
+import midi
+s = open ("s.midi").read ()
+midi.parse_track (s)
+midi.parse (s)
+
+*/
+
+#include "config.h"
+
+/* urg */
+#if HAVE_PYTHON2_PYTHON_H
+#include <python2/Python.h>
+#elif HAVE_PYTHON2_1_PYTHON_H
+#include <python2.1/Python.h>
+#elif HAVE_PYTHON2_0_PYTHON_H
+#include <python2.0/Python.h>
+#elif HAVE_PYTHON1_5_PYTHON_H
+#include <python1.5/Python.h>
+#elif HAVE_PYTHON_PYTHON_H
+#define assert(x)
+#include <python/Python.h>
+#elif HAVE_PYTHON_H
+#define assert(x)
+#include <Python.h>
+#else
+#error Need Python.h
+#endif
+
+#if 0
+int x = 0;
+int *track = &x;
+#define debug_print(f, args...) fprintf (stderr, "%s:%d: track: %p :" f, __FUNCTION__, __LINE__, *track, ##args)
+#else
+#define debug_print(f, args...)
+#endif
+
+static PyObject *Midi_error;
+static PyObject *Midi_warning;
+
+static PyObject *
+midi_error (char *s)
+{
+ PyErr_SetString (Midi_error, s);
+ return 0;
+}
+
+static PyObject *
+midi_warning (char *s)
+{
+ PyErr_SetString (Midi_warning, s);
+ return 0;
+}
+
+
+typedef struct message {
+ unsigned char msg;
+ char * description;
+} message_t;
+
+message_t channelVoiceMessages[] = {
+ 0x80, "NOTE_OFF",
+ 0x90, "NOTE_ON",
+ 0xA0, "POLYPHONIC_KEY_PRESSURE",
+ 0xB0, "CONTROLLER_CHANGE",
+ 0xC0, "PROGRAM_CHANGE",
+ 0xD0, "CHANNEL_KEY_PRESSURE",
+ 0xE0, "PITCH_BEND",
+ 0,0
+};
+
+message_t channelModeMessages[] = {
+ 0x78, "ALL_SOUND_OFF",
+ 0x79, "RESET_ALL_CONTROLLERS",
+ 0x7A, "LOCAL_CONTROL",
+ 0x7B, "ALL_NOTES_OFF",
+ 0x7C, "OMNI_MODE_OFF",
+ 0x7D, "OMNI_MODE_ON",
+ 0x7E, "MONO_MODE_ON",
+ 0x7F, "POLY_MODE_ON",
+ 0,0
+};
+
+message_t metaEvents[] = {
+ 0x00, "SEQUENCE_NUMBER",
+ 0x01, "TEXT_EVENT",
+ 0x02, "COPYRIGHT_NOTICE",
+ 0x03, "SEQUENCE_TRACK_NAME",
+ 0x04, "INSTRUMENT_NAME",
+ 0x05, "LYRIC",
+ 0x06, "MARKER",
+ 0x07, "CUE_POINT",
+ 0x20, "MIDI_CHANNEL_PREFIX",
+ 0x21, "MIDI_PORT",
+ 0x2F, "END_OF_TRACK",
+ 0x51, "SET_TEMPO",
+ 0x54, "SMTPE_OFFSET",
+ 0x58, "TIME_SIGNATURE",
+ 0x59, "KEY_SIGNATURE",
+ 0x7F, "SEQUENCER_SPECIFIC_META_EVENT",
+ 0xFF, "META_EVENT",
+ 0,0
+};
+
+void
+add_constants (PyObject *dict)
+{
+ message_t * p[] = {metaEvents, channelModeMessages, channelVoiceMessages ,0};
+ int i,j;
+ for ( j =0; p[j]; j++)
+ for ( i = 0; p[j][i].description; i++)
+ PyDict_SetItemString (dict, p[j][i].description, Py_BuildValue ("i", p[j][i].msg));
+}
+
+unsigned long int
+get_number (unsigned char ** str, unsigned char * end_str, int length)
+{
+ /* # MIDI uses big-endian for everything */
+ long sum = 0;
+ int i = 0;
+
+ for (; i < length; i++)
+ sum = (sum << 8) + (unsigned char) (*str)[i];
+
+ *str += length;
+ debug_print ("%d:\n", sum);
+ return sum;
+}
+
+unsigned long int
+get_variable_length_number (unsigned char **str, unsigned char * end_str)
+{
+ long sum = 0;
+ int i = 0;
+ while (*str < end_str)
+ {
+ unsigned char x = **str;
+ (*str) ++;
+ sum = (sum << 7) + (x & 0x7F);
+ if (!(x & 0x80))
+ break;
+ }
+ debug_print ("%d:\n", sum);
+ return sum;
+}
+
+PyObject *
+read_one_byte (unsigned char **track, unsigned char *end,
+ unsigned char x)
+{
+ PyObject *pyev = Py_BuildValue ("(i)", x);
+ debug_print ("%x:%s", x, "event\n");
+
+ return pyev;
+}
+
+PyObject *
+read_two_bytes (unsigned char **track, unsigned char *end,
+ unsigned char x)
+{
+ PyObject *pyev = Py_BuildValue ("(ii)", x, (*track)[0]);
+ *track += 1;
+ debug_print ("%x:%s", x, "event\n");
+ return pyev;
+}
+
+PyObject *
+read_three_bytes (unsigned char **track, unsigned char *end,
+ unsigned char x)
+{
+ PyObject *pyev = Py_BuildValue ("(iii)", x, (*track)[0],
+ (*track)[1]);
+
+ *track += 2;
+ debug_print ("%x:%s", x, "event\n");
+ return pyev;
+}
+
+PyObject *
+read_string (unsigned char **track, unsigned char *end)
+{
+ unsigned long length = get_variable_length_number (track, end);
+ if (length > end - *track)
+ length = end - *track;
+
+ *track += length;
+ return Py_BuildValue ("s#", ((*track) -length), length);
+}
+
+typedef PyObject* (*Read_midi_event)
+ (unsigned char **track, unsigned char *end,
+ unsigned char x);
+
+
+static PyObject *
+read_f0_byte (unsigned char **track, unsigned char *end,
+ unsigned char x)
+
+{
+ debug_print ("%x:%s", x, "event\n");
+ if (x == 0xff)
+ {
+ unsigned char z = (*track)[0 ];
+ *track += 1;
+ debug_print ("%x:%s", z, "f0-event\n");
+
+ return Py_BuildValue ("(iiO)", x, z, read_string (track, end));
+ }
+
+ return Py_BuildValue ("(iO)", x, read_string (track, end));
+}
+
+Read_midi_event read_midi_event [16] =
+{
+ read_one_byte, // 0
+ read_one_byte, // 10
+ read_one_byte, // 20
+ read_one_byte, // 30
+ read_one_byte, // 40
+ read_one_byte, // 50
+ read_one_byte, // 60 data entry.
+ read_two_bytes, // 70 all notes off
+ read_three_bytes, // 80 note off
+ read_three_bytes, // 90 note on
+ read_three_bytes, // a0 poly aftertouch
+ read_three_bytes, // b0 control
+ read_two_bytes, // c0 prog change
+ read_two_bytes, // d0 ch aftertouch
+ read_three_bytes, // e0 pitchwheel range
+ read_f0_byte, // f0
+};
+
+
+static PyObject *
+read_event (unsigned char **track, unsigned char *end, PyObject *time,
+ unsigned char *running_status)
+{
+ int rsb_skip = ((**track & 0x80)) ? 1 :0;
+
+ unsigned char x = (rsb_skip) ? (*track)[0]: *running_status;
+
+ PyObject * bare_event = 0;
+ debug_print ("%x:%s", x, "event\n");
+ *running_status = x;
+ *track += rsb_skip;
+
+ // printf ("%x %x %d next %x\n", x, (*track)[0], rsb_skip, (*track)[1]);
+ bare_event = (*read_midi_event[x >> 4]) (track, end, x);
+ if (bare_event)
+ return Py_BuildValue ("(OO)", time, bare_event);
+ else
+ return NULL;
+}
+
+static PyObject *
+midi_parse_track (unsigned char **track, unsigned char *track_end)
+{
+ unsigned int time = 0;
+ unsigned char running_status;
+ unsigned long track_len, track_size;
+ PyObject *pytrack = 0;
+
+ debug_print ("%s", "\n");
+
+ track_size = track_end - *track;
+
+ debug_print ("%s", "\n");
+ if (strcmp (*track, "MTrk"))
+ return midi_error (__FUNCTION__ ": MTrk expected");
+
+ *track += 4;
+
+ 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 begin: %p\n", track);
+ debug_print ("track end: %p\n", track + track_len);
+
+ if (track_len > track_size)
+ return midi_error (__FUNCTION__ ": track size corrupt");
+
+ pytrack = PyList_New (0);
+
+ track_end = *track + track_len;
+
+ {
+ PyObject *pytime = PyInt_FromLong (0L);
+ while (*track < track_end)
+ {
+ long dt = get_variable_length_number(track, track_end);
+ PyObject *pyev = 0;
+
+ time += dt;
+ if (dt)
+ pytime = PyInt_FromLong (time);
+
+ pyev = read_event (track, track_end, pytime,
+ &running_status);
+ if (pyev)
+ PyList_Append (pytrack, pyev);
+ }
+ }
+
+ *track = track_end;
+ return pytrack;
+}
+
+
+static PyObject *
+pymidi_parse_track (PyObject *self, PyObject *args)
+{
+ unsigned char *track, *track_end;
+ unsigned long track_size, track_len;
+
+ PyObject * sobj = PyTuple_GetItem (args, 0);
+
+ debug_print ("%s", "\n");
+ if (!PyArg_ParseTuple (args, "s#", &track, &track_size))
+ return 0;
+
+ if (track_size < 0)
+ return midi_error (__FUNCTION__ ": negative track size");
+
+ track_end = track + track_size;
+
+ return midi_parse_track (&track, track_end);
+}
+
+static PyObject *
+midi_parse (unsigned char **midi,unsigned char *midi_end)
+{
+ PyObject *pymidi = 0;
+ unsigned long header_len;
+ unsigned format, tracks;
+ int division;
+ int i;
+
+ debug_print ("%s", "\n");
+
+ /* Header */
+ header_len = get_number (midi, *midi + 4, 4);
+
+
+ if (header_len < 6)
+ return midi_error (__FUNCTION__ ": header too short");
+
+ format = get_number (midi, *midi + 2, 2);
+ tracks = get_number (midi, *midi + 2, 2);
+
+ if (tracks > 32)
+ return midi_error (__FUNCTION__ ": too many tracks");
+
+ division = get_number (midi, *midi + 2, 2) * 4;
+
+
+ if (division < 0)
+ /* return midi_error ("can't handle non-metrical time"); */
+ ;
+ *midi += header_len - 6;
+
+ pymidi = PyList_New (0);
+
+ /* Tracks */
+ for (i = 0; i < tracks; i++)
+ PyList_Append (pymidi, midi_parse_track (midi, midi_end));
+
+ pymidi = Py_BuildValue ("(OO)", Py_BuildValue ("(ii)", format, division),
+ pymidi);
+ return pymidi;
+}
+
+static PyObject *
+pymidi_parse (PyObject *self, PyObject *args)
+{
+ unsigned char *midi, *midi_end;
+ unsigned long midi_size, midi_len;
+
+ PyObject *sobj = PyTuple_GetItem (args, 0);
+
+ debug_print ("%s", "\n");
+ if (!PyArg_ParseTuple (args, "s#", &midi, &midi_size))
+ return 0;
+
+ if (strcmp (midi, "MThd"))
+ return midi_error (__FUNCTION__ ": MThd expected");
+
+ midi += 4;
+
+ midi_end = midi + midi_size;
+
+ return midi_parse (&midi, midi_end);
+}
+
+
+static PyMethodDef MidiMethods[] =
+{
+ {"parse", pymidi_parse, 1},
+ {"parse_track", pymidi_parse_track, 1},
+ {0, 0} /* Sentinel */
+};
+
+initmidi ()
+{
+ PyObject *m, *d;
+ m = Py_InitModule ("midi", MidiMethods);
+ d = PyModule_GetDict (m);
+
+ Midi_error = PyString_FromString ("midi.error");
+ PyDict_SetItemString (d, "error", Midi_error);
+ add_constants (d);
+ Midi_warning = PyString_FromString ("midi.warning");
+ PyDict_SetItemString (d, "warning", Midi_warning);
+}
SEXECUTABLES=convert-ly lilypond-book ly2dvi abc2ly as2text etf2ly musedata2ly pmx2ly mup2ly midi2ly
STEPMAKE_TEMPLATES=script help2man po
+LOCALSTEPMAKE_TEMPLATES = lilypond
HELP2MAN_EXECS = $(SEXECUTABLES)
include $(depth)/make/stepmake.make
import tempfile
import traceback
-datadir = ''
-
-if '@datadir@' == ('@' + 'datadir' + '@'):
+# if set, LILYPONDPREFIX must take prevalence
+# if datadir is not set, we're doing a build and LILYPONDPREFIX
+datadir = '@datadir@'
+if os.environ.has_key ('LILYPONDPREFIX') \
+ or '@datadir@' == '@' + 'datadir' + '@':
datadir = os.environ['LILYPONDPREFIX']
else:
datadir = '@datadir@'
-while datadir[-1] == os.sep:
- datadir = datadir[:-1]
-
-
sys.path.append (os.path.join (datadir, 'python'))
-sys.path.append (os.path.join (datadir, 'buildscripts/out'))
+sys.path.append (os.path.join (datadir, 'python/out'))
+
+program_name = 'ly2dvi'
+program_version = '@TOPLEVEL_VERSION@'
+original_dir = os.getcwd ()
+temp_dir = os.path.join (original_dir, '%s.dir' % program_name)
+errorport = sys.stderr
+keep_temp_dir_p = 0
+verbose_p = 0
try:
import gettext
except:
pass
-program_name = 'ly2dvi'
-package_name = 'lilypond'
help_summary = _ ("Generate .dvi with LaTeX for LilyPond")
option_definitions = [
from lilylib import *
-# verbose_p = 1 # arg!
-
layout_fields = ['dedication', 'title', 'subtitle', 'subsubtitle',
'footer', 'head', 'composer', 'arranger', 'instrument',
'opus', 'piece', 'metre', 'meter', 'poet', 'texttranslator']
return pfa
-(sh, long) = getopt_args (__main__.option_definitions)
+(sh, long) = getopt_args (option_definitions)
try:
(options, files) = getopt.getopt(sys.argv[1:], sh, long)
except getopt.error, s:
other converters, while leaving midi specific stuff here
'''
+import os
+import sys
+
+# if set, LILYPONDPREFIX must take prevalence
+# if datadir is not set, we're doing a build and LILYPONDPREFIX
+datadir = '@datadir@'
+if os.environ.has_key ('LILYPONDPREFIX') \
+ or '@datadir@' == '@' + 'datadir' + '@':
+ datadir = os.environ['LILYPONDPREFIX']
+else:
+ datadir = '@datadir@'
+
+sys.path.append (os.path.join (datadir, 'python'))
+sys.path.append (os.path.join (datadir, 'python/out'))
+
+
import getopt
import __main__
import sys
import string
-
-sys.path.append ('@datadir@/python')
-sys.path.append ('@datadir@/buildscripts/out')
-sys.path.append ('@datadir@/modules/out')
-
import midi
+
+localedir = '@localedir@'
try:
import gettext
- gettext.bindtextdomain ('lilypond', '@localedir@')
+ gettext.bindtextdomain ('lilypond', localedir)
gettext.textdomain ('lilypond')
_ = gettext.gettext
except:
def _ (s):
return s
-# Attempt to fix problems with limited stack size set by Python!
-# Sets unlimited stack size. Note that the resource module only
-# is available on UNIX.
-try:
- import resource
- resource.setrlimit (resource.RLIMIT_STACK, (-1, -1))
-except:
- pass
+program_name = 'midi2ly'
+program_version = '@TOPLEVEL_VERSION@'
+
+errorport = sys.stderr
+verbose_p = 0
+
+# temp_dir = os.path.join (original_dir, '%s.dir' % program_name)
+# original_dir = os.getcwd ()
+# keep_temp_dir_p = 0
+
-program_name = 'midi2ly [experimental]'
-package_name = 'lilypond'
help_summary = _ ("Convert MIDI to LilyPond source")
option_definitions = [
('', 'x', 'text-lyrics', _ ("treat every text as a lyric")),
]
-from lilylib import *
+# from lilylib import *
+import lilylib
+
class Duration:
s = s + ' \\context Lyrics=%s \\%s\n' % (track, track)
s = s + ' >\n}\n'
- progress (_ ("%s output to `%s'...") % ('LY', o))
+ lilylib.progress (_ ("%s output to `%s'...") % ('LY', o))
if o == '-':
h = sys.stdout
h.close ()
-(sh, long) = getopt_args (__main__.option_definitions)
+(sh, long) = lilylib.getopt_args (option_definitions)
try:
(options, files) = getopt.getopt(sys.argv[1:], sh, long)
except getopt.error, s:
errorport.write (_ ("error: ") + _ ("getopt says: `%s\'" % s))
errorport.write ('\n')
errorport.write ('\n')
- help ()
+ lilylib.help ()
sys.exit (2)
for opt in options:
if 0:
pass
elif o == '--help' or o == '-h':
- help ()
+ lilylib.help ()
errorport.write ('\n')
errorport.write (_ ("Example:"))
errorport.write (r'''
elif o == '--verbose' or o == '-V':
verbose_p = 1
elif o == '--version' or o == '-v':
- identify ()
+ lilylib.identify ()
sys.exit (0)
elif o == '--warranty' or o == '-w':
status = system ('lilypond -w', ignore_error = 1)
if not files or files[0] == '-':
# FIXME: read from stdin when files[0] = '-'
- help ()
+ lilylib.help ()
errorport.write (program_name + ":" + _ ("error: ") + _ ("no files specified on command line.") + '\n')
sys.exit (2)
for f in files:
g = f
- g = strip_extension (g, '.midi')
- g = strip_extension (g, '.mid')
- g = strip_extension (g, '.MID')
+ g = lilylib.strip_extension (g, '.midi')
+ g = lilylib.strip_extension (g, '.mid')
+ g = lilylib.strip_extension (g, '.MID')
(outdir, outbase) = ('','')
if not output_name:
import operator
import tempfile
-sys.path.append ('@datadir@/python')
-sys.path.append ('@datadir@/buildscripts/out')
-sys.path.append ('@datadir@/modules/out')
+
+# if set, LILYPONDPREFIX must take prevalence
+# if datadir is not set, we're doing a build and LILYPONDPREFIX
+datadir = '@datadir@'
+if os.environ.has_key ('LILYPONDPREFIX') \
+ or '@datadir@' == '@' + 'datadir' + '@':
+ datadir = os.environ['LILYPONDPREFIX']
+else:
+ datadir = '@datadir@'
+
+sys.path.append (os.path.join (datadir, 'python'))
+sys.path.append (os.path.join (datadir, 'python/out'))
+
+program_name = 'ly2dvi'
+program_version = '@TOPLEVEL_VERSION@'
+original_dir = os.getcwd ()
+temp_dir = os.path.join (original_dir, '%s.dir' % program_name)
+errorport = sys.stderr
+keep_temp_dir_p = 0
+verbose_p = 0
try:
import gettext
def _ (s):
return s
-# Attempt to fix problems with limited stack size set by Python!
-# Sets unlimited stack size. Note that the resource module only
-# is available on UNIX.
-try:
- import resource
- resource.setrlimit (resource.RLIMIT_STACK, (-1, -1))
-except:
- pass
program_name = 'mup2ly'
-package_name = 'lilypond'
help_summary = _ ("Convert mup to LilyPond source")
option_definitions = [
import __main__
+# if set, LILYPONDPREFIX must take prevalence
+# if datadir is not set, we're doing a build and LILYPONDPREFIX
+datadir = '@datadir@'
+if os.environ.has_key ('LILYPONDPREFIX') \
+ or '@datadir@' == '@' + 'datadir' + '@':
+ datadir = os.environ['LILYPONDPREFIX']
+else:
+ datadir = '@datadir@'
+
+sys.path.append (os.path.join (datadir, 'python'))
+sys.path.append (os.path.join (datadir, 'python/out'))
+
+program_name = 'build-lily'
+program_version = '@TOPLEVEL_VERSION@'
+
+original_dir = os.getcwd ()
+temp_dir = os.path.join (original_dir, '%s.dir' % program_name)
+errorport = sys.stderr
+keep_temp_dir_p = 0
+verbose_p = 0
+remove_previous_p = 0
+
url = 'file:/home/ftp/pub/gnu/LilyPond/development/lilypond-*.tar.gz'
url = 'ftp://appel.lilypond.org/pub/gnu/LilyPond/development/lilypond-*.tar.gz'
url = 'ftp://ftp.cs.uu.nl/pub/GNU/LilyPond/development/lilypond-*.tar.gz'
-remove_previous_p = 0
+
+build_root = os.path.join (os.environ ['HOME'], 'usr', 'src')
+release_dir = build_root + '/releases'
+patch_dir = build_root + '/patches'
-sys.path.append ('@datadir@/python')
-sys.path.append ('@datadir@/buildscripts/out')
try:
import gettext
pass
-program_name = 'build-lily'
-package_name = 'lilypond'
help_summary = _ ("Fetch and rebuild from latest source package")
-build_root = os.path.join (os.environ ['HOME'], 'usr', 'src')
-release_dir = build_root + '/releases'
-patch_dir = build_root + '/patches'
-original_dir = os.getcwd ()
-temp_dir = os.path.join (original_dir, '%s.dir' % program_name)
-
-
option_definitions = [
('DIR', 'b', 'build-root', _ ("unpack and build in DIR [%s]") % build_root),
('COMMAND', 'c', 'command', _ ("execute COMMAND, subtitute:") \
-$(PYTHON_MODULE): $(outdir)/config.h $(LO_FILES)
- $(LD) $(SHARED_FLAGS) -o $@ $(LO_FILES) $(LDFLAGS)
+$(outdir)/%$(SHARED_LIB_SUFFIX): $(outdir)/%.lo
+ $(LD) $(SHARED_FLAGS) -o $@ $< $(LDFLAGS)
-default: $(PYTHON_MODULE)
\ No newline at end of file
+default: $(OUT_PY_MODULES) $(OUT_SO_MODULES)
\ No newline at end of file
+PY_MODULES = $(wildcard *.py)
+PY_IN_FILES = $(wildcard *.py.in)
+OUT_PY_MODULES = $($(addprefix $(outdir)/, $(PY_IN_FILES:.in=)
SHARED_LIB_SUFFIX = .so
-
-PYTHON_MODULE = $(outdir)/$(NAME)$(SHARED_LIB_SUFFIX)
-INSTALL_SHARED_LIBRARY = $(SHARED_LIB_PREFIX)$(NAME)$(SHARED_LIB_SUFFIX)
-
-LO_FILES += $(addprefix $(outdir)/, $(Y_FILES:.y=.lo) $(C_FILES:.c=.lo) $(L_FILES:.l=.lo))
+OUT_SO_MODULES = $(addprefix $(outdir)/, $(C_FILES:.c=$(SHARED_LIB_SUFFIX)))