home | links | feminist | studies | wishlist | cooking | !blog

MIDI Functions for UCB Logo

What to find here


0. contents

0. contents
1. motivation, copyright, author
2. installation
4. usage
5. implementation
6. known bugs
7. todo
8. links, credits etc


1. motivation, copyright, author

For "Spezielle Kapitel der Schulinformatik" Professor Erich Neuwirth
uses the Free Software Logo implementation "MSWLogo" from
http://www.softronix.com/logo.html, which is a dialect of
LOGO derived from the original UCB Logo by Brian Harvey et al. of which 
particularly the midi functions (with wrappers) are relevant for his
course. Since this dialect only works on MicroSoft Windows, a patch to use 
the midi functions in GNU/Linux was needed.

This patch must of course remain under the GNU GPL Version 2 just like the
programs it is based on. See http://www.gnu.org/copyleft/gpl.html for
further information. See the links below for the original and current
versions of ucblogo and mswlogo.

Alexander Oelzant 


2. installation

Packages for Debian GNU/Linux Sarge are provided here, the patch should however
apply cleanly to any other version of ucblogo. If you want to compile
the package yourself, make sure that libasound2 and the asound2 development
package (providing /usr/include/alsa) exist.

You can either make a debian package yourself with (chmod a+x debian/rules;
dpkg-buildpackage -rfakeroot or dpkg-source -x ucblogo_5.5-1.dsc; cd
ucblogo-5.5; dpkg-buildpackage), or you can proceed in the usual way:

> curl http://www.cs.berkeley.edu/~bh/downloads/ucblogo.tar.gz | tar -xzv
or
> curl http://tigerente.htu.tuwien.ac.at/~aoe/mystuff/ucblogo_midi/ucblogo_5.5.orig.tar.gz | tar -xzv
> mv ucblogo ucblogo-5.5
> cd ucblogo-5.5
> curl http://tigerente.htu.tuwien.ac.at/~aoe/mystuff/ucblogo_midi/ucblogo_5.5-1.diff.gz | gzip -d |  patch -p1
> ./configure
> make
# make install

The default is to include midi capabilities, configure should therefore
output the line

checking for snd_seq_event_output in -lasound... yes

If the check is negative, see above - you are probably missing the alsa
(asound2) libraries or dev packages. Another possibility of failure might be
an old installation with  instead of ;
I don't have a configure check for that yet, so you might have to remove
the "1 ||" at the beginning of mmwind.c.

(For the documentation, the build system also wants LaTeX. If you only want
the logo executable, you can ignore the error when make'ing docs and
proceed straight to make install)

If all else fails, it is also possible to rebuild configure and config.h.in
using autoconf e. g. by calling the command "autoreconf".

If you want to try out the patched version but are not ready to sacrifice
your distro version, it is wise to tell ./logo where to find the logo
standard libraries where many of the default commands like foreach, `,
while etc are defined. this can be accomplished by either giving make
a LIBLOC variable (also see debian/rules)

> make LIBLOC=/usr/share/ucblogo

or by configuring that option from the start

> ./configure   --libdir=/usr/share/ucblogo

Otherwise, errors about supposedly builtin commands could arise like the
following:

I don't know how  to while
I don't know how  to foreach
...


4. usage

If you have a distro version of ucblogo installed, you can test your freshly
compiled version right away without installation, provided you set the LIBLOC
path as described in the previous chapter.

Since ucblogo comes without readline support, the official announcement
suggests using rlwrap as a replacement. This versatile utility provides all
the advantages that full readline integration has including history support
and is thus second best to linking with libreadline (see also
http://www.cs.berkeley.edu/~bh/announce).

The modified logo provides three new commands: midiopen, midimessage and
midiclose.

midiopen takes 0 or 2 parameters. Default client:port are 128:0, which is
the default sequencer client configuration with alsa. If (midiopen :client
:port) is called, e. g. (midiopen 64 0), this client is used instead. This
might be preferable if you have a hardware midi device like a synthesizer
connected to the MPU401 midi port or just want to use the wavetable device
built into some soundcards. You can get a list of valid client:port
combinations with pmidi -l.

The recommended way is to start a timidity process as an alsa sequencer
client:

> timidity -iAD -Os -q0/0 -k0 --reverb=d --chorus=d
or
> timidity -iA -Ol -Os -q0/0 -k0 --reverb=d --chorus=d --verbose=3 | grep -ivE "ME_NONE|output data .2048."

The former version politely daemonizes after start, the latter command is
intended mainly for debugging as it outputs all midi messages to the
terminal and does not fork.

As all of this is intended for use with Prof. Neuwirth's mididefs.lgo, a
caveat is in order here: as only the midi commands have been hacked into
UCB logo, some others (notably dllopen/dllcall) will not work. Also, it
seems that either this implementation has a slight discrepancy with the
original or ucblogo has different output handling from mswlogo. This boils
down to the fact that a few changes are necessary to mididefs.lgo before it
works with the modified ucblogo:

- the file has to be converted from dos to unix (cr/lf to lf only),
   otherwise logo complains with
 too many inputs to midi.rescale  in noteon
 ]midimessage (list 208 + :chan - 1 (midi.rescale :press 0 1) 0)
- all midimessage commands have to be preceded with "run" or "ignore",
  otherwise logo does not know what to do with the [] output:
 ? noteon 1 60 1
 You don't say what to do with []  in noteon
- the dllopen/dllcall commands have to be removed and replaced
  with e. g. wait int :millisec / (1000/60)
  (implementing dlopen/dlsym would be possible, and it would be even
  easier to just write a waitmilli logo call; an unthinkably ugly
  alternative would further be the usage of (shell [usleep (:millisec *
  1000)], but the exec overhead is sizeable, albeit uncalculable, thus
  making this possibility hardly a practical one.

This commandline converts the original mididefs.lgo to a version
suitable for ucblogo:

> < mididefs.lgo.orig  sed -e 's/\r//' -e 's/midimessage/run &/g' -e 's/dllload [^ ]*//' -e 's/.*dllcall.*/wait int :millisec \/ (1000\/60)/' > mididefs.lgo

(note that the first ">" is supposed to symbolise the unix prompt, the
other greater/lesser than signs are to be copied verbatim)

Another caveat is that timidity needs to have patches installed in order to
be able to produce midi sounds. If you hear sporadic or no audio, you
likely do not have a full set installed. See the timidity homepage or the
TK707 manual (under Links below) for instructions how to build, install
and configure TiMidity++.

Finally, in order to communicate through the ALSA sequencer infrastructure,
the programs (logo and timidity) need to be able to access
/dev/snd/seq. If it does not exist (not too unlikely with respect to the
Linux kernel team recently abandoning devfs), you can make your own by
issuing 

# mkdir /dev/snd
# mknod /dev/snd/seq c 116 1

You'll also need to be able to open/read/write to it, so

# chmod 666 /dev/snd/seq 
or 
# chmod 660 /dev/snd/seq
# chgrp audio /dev/snd/seq
# adduser  audio 

(provided an audio group exists. substitute  with the name of
the user you want to run logo/timidity)


5. implementation

The logo part was easy: apart from adding the relevant interface lines
to init.c and globals.h, I only had to port parts of mmwind.c from the
mswlogo distribution. Helpfiles for the new commands are also provided
in the directory of the same name.

The alsa midi sequencer part proved somewhat more difficult; since I could
not find any tutorial-style documentation on the subject of programming 
a midi sequencer client to send events to another midi sequencer device,
I looked at the source code of relevant projects, namely pmidi, 
pmidi, tk707 source and some ltraces. pmidi however seems to be an
offline midi player technically (it puts timestamps on the events as opposed 
to sending them at once), and tk707 is versatile, but far from being a
simple programming example.

In the end I only forgot to start the queue, which prevented TiMidity from
receiving any messages. After that it worked instanteneously. I was
particularly pleased with the snd_midi_event_encode interface which takes
any midi message and packs it into an event that can directly be sent to
the sequencer.

The current sequence of relevant midi-related function calls is as follows:

lmidiopen
 snd_seq_open
 snd_seq_alloc_queue
 snd_seq_client_id
 snd_seq_create_simple_port (wrapper for snd_seq_create_port)
 snd_seq_connect_to
 snd_seq_start_queue

midimessage
 snd_seq_ev_clear (macro)
 snd_midi_event_new (macro)
 snd_midi_event_init (macro)
 snd_midi_event_no_status
 snd_midi_event_reset_encode
 snd_seq_ev_set_dest
 snd_seq_ev_set_source
 snd_midi_event_encode
 snd_seq_ev_schedule_real
 snd_seq_event_output
 snd_seq_drain_output

The long midi message for sysex events (0xf0) have not been implemented
yet as there are currenty no special commands I want to send to any
devices. This is not likely to change, but it should be straightforward to
implement this functionality.
 

6. known bugs

Return value of midimessage confuses default mididefs.lgo. See
modifications under "usage".

midiopen does not complain if connected to an inexistent sequencer. This
should be fixed.


7. todo

midiopen does not complain if connected to an inexistent sequencer. This
should be fixed.

Implement waitmilli in a proper fashion.

check for  instead of  via autoconf

Long midi messages for sysex events (0xf0, 240)


8. links, credits etc


http://homepage.univie.ac.at/erich.neuwirth/midilogo/midilogo.zip

Prof. Erich Neuwirth's Eurologo 2005 contribution introducing the
noteon/noteoff functions as didactic constructs for combining combining
computer science and musical education. See also the PDF only at
http://eurologo2005.oeiizk.waw.pl/PDF/E2005Neuwirth.pdf


http://www.alsa-project.org/

The ALSA project (Advance Linux Sound Architecture) provides the foundation
for all current midi sequencing under GNU/Linux. They also have extensive
documentation on the used functions under
http://www.alsa-project.org/alsa-doc/alsa-lib/


http://www.cs.berkeley.edu/~bh/

UCB Logo can be obtained directly from Brian Harvey's homepage, where his
book "Computer Science Logo Style" is also provided online in PDF and HTML 
versions.


http://www.softronix.com/

The makers of MSWLogo, a C++ relative partly derived from usblogo, have put
their product under the GPL Version 2, therefore I feel no remorse copying
most of the mmwind.c file from their code. Thanks for providing this
code to the community!


http://www.timidity.jp/

TiMidity++ (based on TiMidity by Tuukka Toivonen) is actively developed by 
Masanao Izumo . Besides the ALSA sequencer interface there
is another remote interface that might be usable fir the purpose of playing
midi events live; however previous experience has shown that method to be
less accurate, it also looks slighlty out of date (hardly any mention in
the docs).
For configuring timidity (if your distro/OS does not provide patches in a
package), see their homepage or in the tk707 manual below.


http://sourceforge.net/projects/pmidi

Written by Steve Ratcliffe 
Simple midi application for playin midi files through the ALSA midi
sequencer interface. Some code (mainly the lines for finding the name
of the sequencer) is from this project. 


http://www-lmc.imag.fr/lmc-edp/Pierre.Saramito/tk707

TK707 is a drum machine for the ALSA midi interface, it partly helped me
understand how events can be sent to the destination device at once.
They also have some documentation on how to compile and install timidity
and to use it as a midi sequencer device in the installation manual under
http://www-lmc.imag.fr/lmc-edp/Pierre.Saramito/tk707/tk707.html#SEC8


http://www.midiox.com/app.htm
ftp://ftp.cs.ruu.nl/pub/MIDI/PROGRAMS/mf2tsrc.zip

Source to t2mf and mf2t is available from Jamie O'Connell. The C syntax is
a little out of date, but it can be compiled with gcc using a sequence 
similar to the following

> curl -O ftp://ftp.cs.ruu.nl/pub/MIDI/PROGRAMS/mf2tsrc.zip 
> mkdir mf2tsrc
> cd mf2tsrc
> unzip -x ../mf2tsrc.zip
> sed -ie '/extern.*sys_errlist/d' mf2t.c t2mf.c 
> make -f makefile.unx
> cp t2mf mf2t ~/bin
provided ~/bin is in your $PATH or
# cp t2mf mf2t /usr/local/bin


for my trusty editor vim: textwidth=75