changeset 522:60c744f652f4 trunk

[svn] amidi-plug (MIDI through ALSA seq) input plugin added, brand new and completely written from scratch :)
author giacomo
date Thu, 26 Jan 2006 18:43:59 -0800
parents 54cd4bac0c0a
children 42380ff32bad
files Plugins/Input/Makefile.am Plugins/Input/amidi-plug/Makefile.am Plugins/Input/amidi-plug/amidi-plug.c Plugins/Input/amidi-plug/amidi-plug.h Plugins/Input/amidi-plug/amidi-plug.logo.xpm Plugins/Input/amidi-plug/amidi-plug.midiicon.xpm Plugins/Input/amidi-plug/i_common.h Plugins/Input/amidi-plug/i_configure.c Plugins/Input/amidi-plug/i_configure.h Plugins/Input/amidi-plug/i_fileinfo.c Plugins/Input/amidi-plug/i_fileinfo.h Plugins/Input/amidi-plug/i_midi.c Plugins/Input/amidi-plug/i_midi.h Plugins/Input/amidi-plug/i_seq.c Plugins/Input/amidi-plug/i_seq.h Plugins/Input/amidi-plug/i_utils.c Plugins/Input/amidi-plug/i_utils.h
diffstat 17 files changed, 4179 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/Plugins/Input/Makefile.am	Thu Jan 26 17:24:48 2006 -0800
+++ b/Plugins/Input/Makefile.am	Thu Jan 26 18:43:59 2006 -0800
@@ -1,2 +1,2 @@
-ALL_PLUGINS = mpg123 aac modplug vorbis tonegen cdaudio sid wav flac console timidity musepack sexypsf adplug wma
+ALL_PLUGINS = mpg123 aac modplug vorbis tonegen cdaudio sid wav flac console timidity musepack sexypsf adplug wma amidi-plug
 SUBDIRS = $(INPUT_PLUGINS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/Makefile.am	Thu Jan 26 18:43:59 2006 -0800
@@ -0,0 +1,18 @@
+if ENABLE_AMIDIPLUG
+
+lib_LTLIBRARIES = libamidi-plug.la
+
+endif
+
+noinst_HEADERS = amidi-plug.h i_seq.h i_midi.h i_configure.h \
+                 i_fileinfo.h i_utils.h i_common.h
+
+libdir = $(plugindir)/$(INPUT_PLUGIN_DIR)
+
+libamidi_plug_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+libamidi_plug_la_LIBADD = $(GTK_LIBS) @ALSA_LIBS@ -lpthread
+libamidi_plug_la_SOURCES = amidi-plug.c i_seq.c i_midi.c \
+                           i_configure.c i_utils.c i_fileinfo.c \
+                           amidi-plug.logo.xpm amidi-plug.midiicon.xpm
+
+INCLUDES = $(GTK_CFLAGS) @ALSA_CFLAGS@ -I$(top_builddir)/intl -I$(top_srcdir)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/amidi-plug.c	Thu Jan 26 18:43:59 2006 -0800
@@ -0,0 +1,687 @@
+/*
+*
+* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+*
+*/
+
+#include "amidi-plug.h"
+
+
+InputPlugin *get_iplugin_info(void)
+{
+  amidiplug_ip.description = g_strdup_printf(_("AMIDI-Plug %s (MIDI Player)"), AMIDIPLUG_VERSION);
+  return &amidiplug_ip;
+}
+
+
+static gint amidiplug_is_our_file( gchar * filename )
+{
+#ifdef MIDIFILE_PROBE_MAGICBYTES
+    FILE * fp;
+    gchar magic_bytes[4];
+
+    fp = fopen( filename , "rb" );
+    fread( magic_bytes , 1 , 4 , fp );
+
+    if ( !strncmp( magic_bytes , "MThd" , 4 ) )
+    {
+      fclose( fp );
+      DEBUGMSG( "MIDI found, %s is a standard midi file\n" , filename );
+      return TRUE;
+    }
+
+    if ( !strncmp( magic_bytes , "RIFF" , 4 ) )
+    {
+      /* skip the four bytes after RIFF,
+         then read the next four */
+      fseek( fp , 4 , SEEK_CUR );
+      fread( magic_bytes , 1 , 4 , fp );
+      if ( !strncmp( magic_bytes , "RMID" , 4 ) )
+      {
+        fclose( fp );
+        DEBUGMSG( "MIDI found, %s is a riff midi file\n" , filename );
+        return TRUE;
+      }
+    }
+    fclose( fp );
+#else
+    gchar * ext = strrchr( filename, '.' );
+    /* check the filename extension */
+    if ( ( ext ) &&
+         (( !strcasecmp(ext,".mid") ) || ( !strcasecmp(ext,".midi") ) ||
+          ( !strcasecmp(ext,".rmi") ) || ( !strcasecmp(ext,".rmid") )) )
+      return TRUE;
+#endif
+  return FALSE;
+}
+
+
+static void amidiplug_init( void )
+{
+  gchar * alsaversion;
+  g_log_set_handler(NULL , G_LOG_LEVEL_WARNING , g_log_default_handler , NULL);
+  DEBUGMSG( "init, read configuration\n" );
+  /* read configuration */
+  alsaversion = (gchar *)snd_asoundlib_version(); /* get ALSA-lib version */
+  i_configure_cfg_read( alsaversion );
+  amidiplug_playing_status = AMIDIPLUG_STOP;
+}
+
+
+static void amidiplug_cleanup( void )
+{
+  g_free( amidiplug_ip.description );
+}
+
+
+static void amidiplug_configure( void )
+{
+  if ( amidiplug_gui_prefs.config_win )
+  {
+    return;
+  }
+  else
+  {
+    GSList * wports = NULL;
+    GSList * scards = NULL;
+    /* get an updated list of writable ALSA MIDI ports and ALSA-enabled sound cards*/
+    DEBUGMSG( "get an updated list of writable ALSA MIDI ports\n" );
+    wports = i_seq_port_get_list();
+    DEBUGMSG( "get an updated list of ALSA-enabled sound cards\n" );
+    scards = i_seq_card_get_list();
+    /* display them in our nice config dialog */
+    DEBUGMSG( "opening config window\n" );
+    i_configure_gui( wports , scards );
+    /* free the cards list and the ports list */
+    i_seq_card_free_list( scards );
+    i_seq_port_free_list( wports );
+  }
+}
+
+
+static void amidiplug_aboutbox( void )
+{
+  i_about_gui();
+}
+
+
+static void amidiplug_file_info_box( gchar * filename )
+{
+  i_fileinfo_gui( filename );
+}
+
+
+static void amidiplug_stop( void )
+{
+  DEBUGMSG( "STOP request at tick: %i\n" , midifile.playing_tick );
+  pthread_mutex_lock( &amidiplug_playing_mutex );
+  if (( amidiplug_playing_status == AMIDIPLUG_PLAY ) ||
+      ( amidiplug_playing_status == AMIDIPLUG_STOP ))
+  {
+    amidiplug_playing_status = AMIDIPLUG_STOP;
+    pthread_mutex_unlock( &amidiplug_playing_mutex );
+    pthread_join( amidiplug_play_thread , NULL );
+    DEBUGMSG( "STOP activated (play thread joined)\n" );
+  }
+  else if ( amidiplug_playing_status == AMIDIPLUG_PAUSE )
+  {
+    amidiplug_playing_status = AMIDIPLUG_STOP;
+    DEBUGMSG( "STOP activated (from PAUSE to STOP)\n" );
+    pthread_mutex_unlock( &amidiplug_playing_mutex );
+  }
+  else /* AMIDIPLUG_ERR */
+  {
+    DEBUGMSG( "STOP activated (in error handling, ok)\n" );
+    pthread_mutex_unlock( &amidiplug_playing_mutex );
+  }
+  /* kill the sequencer (while it has been already killed if we come from
+     pause, it's safe to do anyway since it checks for multiple calls */
+  i_seq_off();
+  /* free midi data (same as above) */
+  i_midi_free( &midifile );
+}
+
+
+static void amidiplug_pause( gshort paused )
+{
+  if ( paused )
+  {
+    DEBUGMSG( "PAUSE request at tick: %i\n" , midifile.playing_tick );
+    pthread_mutex_lock( &amidiplug_playing_mutex );
+    /* this cond is used to avoid race conditions */
+    while ( amidiplug_playing_status != AMIDIPLUG_PLAY )
+      pthread_cond_wait( &amidiplug_playing_cond , &amidiplug_playing_mutex );
+    amidiplug_playing_status = AMIDIPLUG_PAUSE;
+    pthread_mutex_unlock( &amidiplug_playing_mutex );
+
+    pthread_join( amidiplug_play_thread , NULL );
+    DEBUGMSG( "PAUSE activated (play thread joined)\n" , midifile.playing_tick );
+
+    /* kill the sequencer */
+    i_seq_off();
+  }
+  else
+  {
+    DEBUGMSG( "PAUSE deactivated, returning to tick %i\n" , midifile.playing_tick );
+    /* revive the sequencer */
+    i_seq_on( 0 , NULL );
+    /* re-set initial tempo */
+    i_midi_setget_tempo( &midifile );
+    i_seq_queue_set_tempo( midifile.current_tempo , midifile.ppq );
+    /* get back to the previous state */
+    amidiplug_skipto( midifile.playing_tick );
+
+    pthread_mutex_lock( &amidiplug_playing_mutex );
+    /* play play play! */
+    DEBUGMSG( "PAUSE deactivated, starting play thread again\n" );
+    pthread_create(&amidiplug_play_thread, NULL, amidiplug_play_loop, NULL);
+    /* this cond is used to avoid race conditions */
+    while ( amidiplug_playing_status != AMIDIPLUG_PLAY )
+      pthread_cond_wait( &amidiplug_playing_cond , &amidiplug_playing_mutex );
+    pthread_mutex_unlock( &amidiplug_playing_mutex );
+  }
+}
+
+
+static void amidiplug_seek( gint time )
+{
+  DEBUGMSG( "SEEK requested (time %i), pausing song...\n" , time );
+  pthread_mutex_lock( &amidiplug_playing_mutex );
+  /* this cond is used to avoid race conditions */
+  while ( amidiplug_playing_status != AMIDIPLUG_PLAY )
+      pthread_cond_wait( &amidiplug_playing_cond , &amidiplug_playing_mutex );
+  amidiplug_playing_status = AMIDIPLUG_PAUSE;
+  pthread_mutex_unlock( &amidiplug_playing_mutex );
+
+  pthread_join( amidiplug_play_thread , NULL );
+  DEBUGMSG( "SEEK requested (time %i), song paused\n" , time );
+  /* kill the sequencer */
+  i_seq_off();
+  /* revive the sequencer */
+  i_seq_on( 0 , NULL );
+  /* re-set initial tempo */
+  i_midi_setget_tempo( &midifile );
+  i_seq_queue_set_tempo( midifile.current_tempo , midifile.ppq );
+  /* get back to the previous state */
+  DEBUGMSG( "SEEK requested (time %i), moving to tick %i of %i\n" ,
+            time , (gint)((time * 1000000) / midifile.avg_microsec_per_tick) , midifile.max_tick );
+  midifile.playing_tick = (gint)((time * 1000000) / midifile.avg_microsec_per_tick);
+  amidiplug_skipto( midifile.playing_tick );
+  /* play play play! */
+  DEBUGMSG( "SEEK done, starting play thread again\n" );
+  pthread_create(&amidiplug_play_thread, NULL, amidiplug_play_loop, NULL);
+}
+
+
+static gint amidiplug_get_time( void )
+{
+  gint pt;
+  pthread_mutex_lock( &amidiplug_playing_mutex );
+  if (( amidiplug_playing_status == AMIDIPLUG_PLAY ) ||
+      ( amidiplug_playing_status == AMIDIPLUG_PAUSE ))
+  {
+    pthread_mutex_unlock( &amidiplug_playing_mutex );
+    pthread_mutex_lock(&amidiplug_gettime_mutex);
+    pt = midifile.playing_tick;
+    pthread_mutex_unlock(&amidiplug_gettime_mutex);
+    return (gint)((pt * midifile.avg_microsec_per_tick) / 1000);
+  }
+  else if ( amidiplug_playing_status == AMIDIPLUG_STOP )
+  {
+    pthread_mutex_unlock( &amidiplug_playing_mutex );
+    DEBUGMSG( "GETTIME on stopped song, returning -1\n" , time );
+    return -1;
+  }
+  else /* AMIDIPLUG_ERR */
+  {
+    pthread_mutex_unlock( &amidiplug_playing_mutex );
+    DEBUGMSG( "GETTIME on halted song (an error occurred?), returning -1 and stopping the player\n" , time );
+    xmms_remote_stop(0);
+    return -1;
+  }
+}
+
+
+static void amidiplug_set_volume( gint  l , gint  r )
+{
+  gchar mixer_card[10];
+  snprintf( mixer_card , 8 , "hw:%i" , amidiplug_cfg.mixer_card_id );
+  mixer_card[9] = '\0';
+  /* set volume */
+  i_seq_mixer_set_volume( l , r , mixer_card , amidiplug_cfg.mixer_control_name ,
+                          amidiplug_cfg.mixer_control_id );
+}
+
+
+static void amidiplug_get_song_info( gchar * filename , gchar ** title , gint * length )
+{
+  /* song title, get it from the filename */
+  *title = G_PATH_GET_BASENAME(filename);
+
+  /* sure, it's possible to calculate the length of a MIDI file anytime,
+     but the file must be entirely parsed to calculate it; this could lead
+     to performance loss, for now it's safer to calculate the length only
+     right before playing the file */
+  *length = -1;
+  return;
+}
+
+
+static void amidiplug_play( gchar * filename )
+{
+  gint port_count = 0;
+  DEBUGMSG( "PLAY requested, midifile init\n" );
+  /* midifile init */
+  i_midi_init( &midifile );
+
+  /* get the number of selected alsa ports */
+  port_count = i_util_str_count( amidiplug_cfg.seq_writable_ports , ':' );
+  if ( port_count < 1 )
+  {
+    g_warning( "No ALSA ports selected\n" );
+    amidiplug_playing_status = AMIDIPLUG_ERR;
+    return;
+  }
+
+  DEBUGMSG( "PLAY requested, opening file: %s\n" , filename );
+  midifile.file_pointer = fopen( filename , "rb" );
+  if (!midifile.file_pointer)
+  {
+    g_warning( "Cannot open %s\n" , filename );
+    amidiplug_playing_status = AMIDIPLUG_ERR;
+    return;
+  }
+  midifile.file_name = filename;
+
+  switch( i_midi_file_read_id( &midifile ) )
+  {
+    case MAKE_ID('R', 'I', 'F', 'F'):
+    {
+      DEBUGMSG( "PLAY requested, RIFF chunk found, processing...\n" );
+      /* read riff chunk */
+      if ( !i_midi_file_parse_riff( &midifile ) )
+        WARNANDBREAKANDPLAYERR( "%s: invalid file format (riff parser)\n" , filename );
+
+      /* if that was read correctly, go ahead and read smf data */
+    }
+
+    case MAKE_ID('M', 'T', 'h', 'd'):
+    {
+      DEBUGMSG( "PLAY requested, MThd chunk found, processing...\n" );
+      if ( !i_midi_file_parse_smf( &midifile , port_count ) )
+        WARNANDBREAKANDPLAYERR( "%s: invalid file format (smf parser)\n" , filename );
+
+      if ( midifile.time_division < 1 )
+        WARNANDBREAKANDPLAYERR( "%s: invalid time division (%i)\n" , filename , midifile.time_division );
+
+      DEBUGMSG( "PLAY requested, setting ppq and tempo...\n" );
+      /* fill midifile.ppq and midifile.tempo using time_division */
+      if ( !i_midi_setget_tempo( &midifile ) )
+        WARNANDBREAKANDPLAYERR( "%s: invalid values while setting ppq and tempo\n" , filename );
+
+      DEBUGMSG( "PLAY requested, sequencer init\n" );
+      /* sequencer on */
+      if ( !i_seq_on( 1 , amidiplug_cfg.seq_writable_ports ) )
+        WARNANDBREAKANDPLAYERR( "%s: ALSA problem, play aborted\n" , filename );
+
+      DEBUGMSG( "PLAY requested, setting sequencer queue tempo...\n" );
+      /* set sequencer queue tempo using ppq and tempo (call only after i_midi_setget_tempo) */
+      if ( !i_seq_queue_set_tempo( midifile.current_tempo , midifile.ppq ) )
+      {
+        i_seq_off(); /* kill the sequencer */
+        WARNANDBREAKANDPLAYERR( "%s: ALSA queue problem, play aborted\n" , filename );
+      }
+
+      /* fill midifile.length, keeping in count tempo-changes */
+      i_midi_setget_length( &midifile );
+      DEBUGMSG( "PLAY requested, song length calculated: %i msec\n" , (gint)(midifile.length / 1000) );
+
+      /* our length is in microseconds, but the player wants milliseconds */
+      amidiplug_ip.set_info( G_PATH_GET_BASENAME(filename) , (gint)(midifile.length / 1000) , -1 , -1 , -1 );
+
+      /* play play play! */
+      DEBUGMSG( "PLAY requested, starting play thread\n" );
+      amidiplug_playing_status = AMIDIPLUG_PLAY;
+      pthread_create(&amidiplug_play_thread, NULL, amidiplug_play_loop, NULL);
+      break;
+    }
+
+    default:
+    {
+      amidiplug_playing_status = AMIDIPLUG_ERR;
+      g_warning( "%s is not a Standard MIDI File\n" , filename );
+      break;
+    }
+  }
+
+  fclose( midifile.file_pointer );
+  return;
+}
+
+
+
+void * amidiplug_play_loop( void * arg )
+{
+  snd_seq_event_t ev;
+  gint i;
+  gboolean rewind = FALSE;
+
+  pthread_mutex_lock( &amidiplug_playing_mutex );
+  if ( amidiplug_playing_status != AMIDIPLUG_PAUSE )
+  {
+    DEBUGMSG( "PLAY thread, rewind tracks to their first event\n" );
+    rewind = TRUE;
+  }
+  else
+  {
+    DEBUGMSG( "PLAY thread, do not rewind tracks to their first event (coming from a PAUSE status)\n" );
+    amidiplug_playing_status = AMIDIPLUG_PLAY;
+    pthread_cond_signal( &amidiplug_playing_cond );
+  }
+  pthread_mutex_unlock( &amidiplug_playing_mutex );
+
+  if ( rewind )
+  {
+    /* initialize current position in each track */
+    for (i = 0; i < midifile.num_tracks; ++i)
+      midifile.tracks[i].current_event = midifile.tracks[i].first_event;
+    snd_seq_start_queue(sc.seq, sc.queue, NULL);
+  }
+
+  /* common settings for all our events */
+  snd_seq_ev_clear(&ev);
+  ev.queue = sc.queue;
+  ev.source.port = 0;
+  ev.flags = SND_SEQ_TIME_STAMP_TICK;
+
+  DEBUGMSG( "PLAY thread, start the play loop\n" );
+  for (;;)
+  {
+    midievent_t * event = NULL;
+    midifile_track_t * event_track = NULL;
+    gint i, min_tick = midifile.max_tick + 1;
+
+    /* search next event */
+    for (i = 0; i < midifile.num_tracks; ++i)
+    {
+      midifile_track_t * track = &midifile.tracks[i];
+      midievent_t * e2 = track->current_event;
+      if (( e2 ) && ( e2->tick < min_tick ))
+      {
+        min_tick = e2->tick;
+        event = e2;
+        event_track = track;
+      }
+    }
+
+    /* check if the song has been stopped */
+    pthread_mutex_lock( &amidiplug_playing_mutex );
+    if ( amidiplug_playing_status != AMIDIPLUG_PLAY )
+    {
+      DEBUGMSG( "PLAY thread, PAUSE or STOP requested, exiting from play loop\n" );
+      event = NULL;
+    }
+    pthread_mutex_unlock( &amidiplug_playing_mutex );
+
+    if (!event)
+      break; /* end of song reached */
+
+    /* advance pointer to next event */
+    event_track->current_event = event->next;
+
+    /* output the event */
+    ev.type = event->type;
+    ev.time.tick = event->tick - midifile.skip_offset;
+    ev.dest = sc.dest_port[event->port];
+
+    switch (ev.type)
+    {
+      case SND_SEQ_EVENT_NOTEON:
+      case SND_SEQ_EVENT_NOTEOFF:
+      case SND_SEQ_EVENT_KEYPRESS:
+      {
+        snd_seq_ev_set_fixed(&ev);
+        ev.data.note.channel = event->data.d[0];
+        ev.data.note.note = event->data.d[1];
+        ev.data.note.velocity = event->data.d[2];
+        break;
+      }
+      case SND_SEQ_EVENT_CONTROLLER:
+      {
+        snd_seq_ev_set_fixed(&ev);
+        ev.data.control.channel = event->data.d[0];
+        ev.data.control.param = event->data.d[1];
+        ev.data.control.value = event->data.d[2];
+        break;
+      }
+      case SND_SEQ_EVENT_PGMCHANGE:
+      case SND_SEQ_EVENT_CHANPRESS:
+      {
+        snd_seq_ev_set_fixed(&ev);
+        ev.data.control.channel = event->data.d[0];
+        ev.data.control.value = event->data.d[1];
+        break;
+      }
+      case SND_SEQ_EVENT_PITCHBEND:
+      {
+        snd_seq_ev_set_fixed(&ev);
+        ev.data.control.channel = event->data.d[0];
+        ev.data.control.value = ((event->data.d[1]) | ((event->data.d[2]) << 7)) - 0x2000;
+        break;
+      }
+      case SND_SEQ_EVENT_SYSEX:
+      {
+        snd_seq_ev_set_variable(&ev, event->data.length, event->sysex);
+        break;
+      }
+      case SND_SEQ_EVENT_TEMPO:
+      {
+        snd_seq_ev_set_fixed(&ev);
+        ev.dest.client = SND_SEQ_CLIENT_SYSTEM;
+        ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER;
+        ev.data.queue.queue = sc.queue;
+        ev.data.queue.param.value = event->data.tempo;
+        DEBUGMSG( "PLAY thread, processing tempo event with value %i on tick %i\n" ,
+                  event->data.tempo , event->tick );
+        pthread_mutex_lock(&amidiplug_gettime_mutex);
+        midifile.current_tempo = event->data.tempo;
+        pthread_mutex_unlock(&amidiplug_gettime_mutex);
+        break;
+      }
+      default:
+      {
+        DEBUGMSG( "PLAY thread, encountered invalid event type %i\n" , ev.type );
+        break;
+      }
+    }
+
+    pthread_mutex_lock(&amidiplug_gettime_mutex);
+    midifile.playing_tick = event->tick;
+    pthread_mutex_unlock(&amidiplug_gettime_mutex);
+
+    snd_seq_event_output(sc.seq, &ev);
+    snd_seq_drain_output(sc.seq);
+    snd_seq_sync_output_queue(sc.seq);
+  }
+
+  /* schedule queue stop at end of song */
+  snd_seq_ev_set_fixed(&ev);
+  ev.type = SND_SEQ_EVENT_STOP;
+  ev.time.tick = midifile.max_tick - midifile.skip_offset;
+  ev.dest.client = SND_SEQ_CLIENT_SYSTEM;
+  ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER;
+  ev.data.queue.queue = sc.queue;
+  snd_seq_event_output(sc.seq, &ev);
+  snd_seq_drain_output(sc.seq);
+  /* snd_seq_sync_output_queue(sc.seq); */
+
+  pthread_mutex_lock( &amidiplug_playing_mutex );
+  if ( amidiplug_playing_status != AMIDIPLUG_PAUSE )
+  {
+    amidiplug_playing_status = AMIDIPLUG_STOP;
+    DEBUGMSG( "PLAY thread, song stopped/ended\n" );
+    
+  }
+  pthread_mutex_unlock( &amidiplug_playing_mutex );
+
+  pthread_exit(NULL);
+}
+
+
+/* amidigplug_skipto: re-do all events that influence the playing of our
+   midi file; re-do them using a time-tick of 0, so they are processed
+   istantaneously and proceed this way until the playing_tick is reached;
+   also obtain the correct skip_offset from the playing_tick */
+void amidiplug_skipto( gint playing_tick )
+{
+  snd_seq_event_t ev;
+  gint i;
+
+  /* this check is always made, for safety*/
+  if ( playing_tick >= midifile.max_tick )
+    playing_tick = midifile.max_tick - 1;
+
+  /* initialize current position in each track */
+  for (i = 0; i < midifile.num_tracks; ++i)
+    midifile.tracks[i].current_event = midifile.tracks[i].first_event;
+
+  /* common settings for all our events */
+  snd_seq_ev_clear(&ev);
+  ev.queue = sc.queue;
+  ev.source.port = 0;
+  ev.flags = SND_SEQ_TIME_STAMP_TICK;
+
+  snd_seq_start_queue(sc.seq, sc.queue, NULL);
+
+  DEBUGMSG( "SKIPTO request, starting skipto loop\n" );
+  for (;;)
+  {
+    midievent_t * event = NULL;
+    midifile_track_t * event_track = NULL;
+    gint i, min_tick = midifile.max_tick + 1;
+
+    /* search next event */
+    for (i = 0; i < midifile.num_tracks; ++i)
+    {
+      midifile_track_t * track = &midifile.tracks[i];
+      midievent_t * e2 = track->current_event;
+      if (( e2 ) && ( e2->tick < min_tick ))
+      {
+        min_tick = e2->tick;
+        event = e2;
+        event_track = track;
+      }
+    }
+
+    /* unlikely here... unless very strange MIDI files are played :) */
+    if (!event)
+    {
+      DEBUGMSG( "SKIPTO request, reached the last event but not the requested tick (!)\n" );
+      break; /* end of song reached */
+    }
+
+    /* reached the requested tick, job done */
+    if ( event->tick >= playing_tick )
+    {
+      DEBUGMSG( "SKIPTO request, reached the requested tick, exiting from skipto loop\n" );
+      break;
+    }
+
+    /* advance pointer to next event */
+    event_track->current_event = event->next;
+
+    /* output the event */
+    ev.type = event->type;
+    ev.time.tick = event->tick;
+    ev.dest = sc.dest_port[event->port];
+
+    switch (ev.type)
+    {
+      /* do nothing for these
+      case SND_SEQ_EVENT_NOTEON:
+      case SND_SEQ_EVENT_NOTEOFF:
+      case SND_SEQ_EVENT_KEYPRESS:
+      {
+        break;
+      } */
+      case SND_SEQ_EVENT_CONTROLLER:
+      {
+        snd_seq_ev_set_fixed(&ev);
+        ev.data.control.channel = event->data.d[0];
+        ev.data.control.param = event->data.d[1];
+        ev.data.control.value = event->data.d[2];
+        ev.time.tick = 0;
+        snd_seq_event_output(sc.seq, &ev);
+        snd_seq_drain_output(sc.seq);
+        snd_seq_sync_output_queue(sc.seq);
+        break;
+      }
+      case SND_SEQ_EVENT_PGMCHANGE:
+      case SND_SEQ_EVENT_CHANPRESS:
+      {
+        snd_seq_ev_set_fixed(&ev);
+        ev.data.control.channel = event->data.d[0];
+        ev.data.control.value = event->data.d[1];
+        ev.time.tick = 0;
+        snd_seq_event_output(sc.seq, &ev);
+        snd_seq_drain_output(sc.seq);
+        snd_seq_sync_output_queue(sc.seq);
+        break;
+      }
+      case SND_SEQ_EVENT_PITCHBEND:
+      {
+        snd_seq_ev_set_fixed(&ev);
+        ev.data.control.channel = event->data.d[0];
+        ev.data.control.value = ((event->data.d[1]) | ((event->data.d[2]) << 7)) - 0x2000;
+        ev.time.tick = 0;
+        snd_seq_event_output(sc.seq, &ev);
+        snd_seq_drain_output(sc.seq);
+        snd_seq_sync_output_queue(sc.seq);
+        break;
+      }
+      case SND_SEQ_EVENT_SYSEX:
+      {
+        snd_seq_ev_set_variable(&ev, event->data.length, event->sysex);
+        ev.time.tick = 0;
+        snd_seq_event_output(sc.seq, &ev);
+        snd_seq_drain_output(sc.seq);
+        snd_seq_sync_output_queue(sc.seq);
+        break;
+      }
+      case SND_SEQ_EVENT_TEMPO:
+      {
+        snd_seq_ev_set_fixed(&ev);
+        ev.dest.client = SND_SEQ_CLIENT_SYSTEM;
+        ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER;
+        ev.data.queue.queue = sc.queue;
+        ev.data.queue.param.value = event->data.tempo;
+        pthread_mutex_lock(&amidiplug_gettime_mutex);
+        midifile.current_tempo = event->data.tempo;
+        pthread_mutex_unlock(&amidiplug_gettime_mutex);
+        ev.time.tick = 0;
+        snd_seq_event_output(sc.seq, &ev);
+        snd_seq_drain_output(sc.seq);
+        snd_seq_sync_output_queue(sc.seq);
+        break;
+      }
+    }
+  }
+
+  midifile.skip_offset = playing_tick;
+
+  return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/amidi-plug.h	Thu Jan 26 18:43:59 2006 -0800
@@ -0,0 +1,115 @@
+/*
+*
+* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+*
+*/
+
+#ifndef _I_AMIDIPLUG_H
+#define _I_AMIDIPLUG_H 1
+
+#define AMIDIPLUG_STOP	0
+#define AMIDIPLUG_PLAY	1
+#define AMIDIPLUG_PAUSE	2
+#define AMIDIPLUG_ERR	3
+
+#include "i_common.h"
+#include <audacious/plugin.h>
+#include <audacious/beepctrl.h>
+#include <pthread.h>
+#include "i_configure.h"
+#include "i_seq.h"
+#include "i_midi.h"
+#include "i_fileinfo.h"
+#include "i_utils.h"
+
+
+/* if this is defined, possible midi files are
+   checked by looking at their first (magic) bytes
+   instead of just reading the file extension */
+#define MIDIFILE_PROBE_MAGICBYTES 1
+
+
+static pthread_t amidiplug_play_thread;
+static pthread_mutex_t amidiplug_gettime_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t amidiplug_playing_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t amidiplug_playing_cond = PTHREAD_COND_INITIALIZER;
+
+gint amidiplug_playing_status = AMIDIPLUG_STOP;
+
+midifile_t midifile;
+sequencer_client_t sc =
+{
+  NULL,		/* seq */
+  0,		/* client_port */
+  0,		/* queue */
+  NULL,		/* dest_port */
+  0		/* dest_port_num */
+};
+
+amidiplug_cfg_t amidiplug_cfg =
+{
+  NULL,		/* seq_writable_ports */
+  0,		/* mixer_card_id */
+  NULL,		/* mixer_control_name */
+  0		/* mixer_control_id */
+};
+
+void * amidiplug_play_loop( void * );
+void amidiplug_skipto( gint );
+static void amidiplug_init( void );
+static void amidiplug_cleanup( void );
+static void amidiplug_aboutbox( void );
+static void amidiplug_configure( void );
+static gint amidiplug_is_our_file( gchar * );
+static void amidiplug_play( gchar * );
+static void amidiplug_stop( void );
+static void amidiplug_pause( gshort );
+static void amidiplug_seek( gint );
+static gint amidiplug_get_time( void );
+static void amidiplug_set_volume( gint , gint );
+static void amidiplug_get_song_info( gchar * , gchar ** , gint * );
+static void amidiplug_file_info_box( gchar * );
+
+InputPlugin amidiplug_ip =
+{
+  NULL,				/* handle */
+  NULL,				/* filename */
+  NULL,				/* description */
+  amidiplug_init,		/* init */
+  amidiplug_aboutbox,		/* aboutbox */
+  amidiplug_configure,		/* configure */
+  amidiplug_is_our_file,	/* is_our_file */
+  NULL,				/* scan_dir */
+  amidiplug_play,		/* play_file */
+  amidiplug_stop,		/* stop */
+  amidiplug_pause,		/* pause */
+  amidiplug_seek,		/* seek */
+  NULL,				/* set_eq */
+  amidiplug_get_time,		/* get_time */
+  NULL,				/* get_volume */
+  amidiplug_set_volume,		/* set_volume */
+  amidiplug_cleanup,		/* cleanup */
+  NULL,				/* get_vis_type */
+  NULL,				/* add_vis_pcm */
+  NULL,				/* set_info */
+  NULL,				/* set_info_text */
+  amidiplug_get_song_info,	/* get_song_info */
+  amidiplug_file_info_box,	/* file_info_box */
+  NULL				/* output */
+};
+
+#endif /* !_I_AMIDIPLUG_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/amidi-plug.logo.xpm	Thu Jan 26 18:43:59 2006 -0800
@@ -0,0 +1,743 @@
+/* XPM */
+static char * amidiplug_xpm_logo[] = {
+"398 123 617 2",
+"  	c #FFFFFF",
+". 	c #FCFCFC",
+"+ 	c #FAFAFA",
+"@ 	c #F9F9F9",
+"# 	c #F8F8F8",
+"$ 	c #F7F7F7",
+"% 	c #F5F5F5",
+"& 	c #F4F4F4",
+"* 	c #F3F3F3",
+"= 	c #F1F1F1",
+"- 	c #EFEFEF",
+"; 	c #EEEEEE",
+"> 	c #F0F0F0",
+", 	c #EDEDED",
+"' 	c #EBEBEB",
+") 	c #EAEAEA",
+"! 	c #E9E9E9",
+"~ 	c #E8E8E8",
+"{ 	c #E3E3E3",
+"] 	c #E2E2E2",
+"^ 	c #E0E0E0",
+"/ 	c #DEDEDE",
+"( 	c #E4E4E4",
+"_ 	c #DADADA",
+": 	c #5C5C5C",
+"< 	c #4B4B4B",
+"[ 	c #4A4A4A",
+"} 	c #464646",
+"| 	c #454545",
+"1 	c #414141",
+"2 	c #404040",
+"3 	c #3C3C3C",
+"4 	c #383838",
+"5 	c #373737",
+"6 	c #393939",
+"7 	c #3A3A3A",
+"8 	c #3B3B3B",
+"9 	c #363636",
+"0 	c #3D3D3D",
+"a 	c #3E3E3E",
+"b 	c #3F3F3F",
+"c 	c #424242",
+"d 	c #434343",
+"e 	c #444444",
+"f 	c #474747",
+"g 	c #484848",
+"h 	c #494949",
+"i 	c #4C4C4C",
+"j 	c #4D4D4D",
+"k 	c #4E4E4E",
+"l 	c #343434",
+"m 	c #333333",
+"n 	c #323232",
+"o 	c #313131",
+"p 	c #303030",
+"q 	c #2F2F2F",
+"r 	c #2E2E2E",
+"s 	c #2D2D2D",
+"t 	c #2C2C2C",
+"u 	c #2B2B2B",
+"v 	c #2A2A2A",
+"w 	c #292929",
+"x 	c #282828",
+"y 	c #272727",
+"z 	c #262626",
+"A 	c #252525",
+"B 	c #1E1E1E",
+"C 	c #1C1C1C",
+"D 	c #1B1B1B",
+"E 	c #1A1A1A",
+"F 	c #181818",
+"G 	c #161616",
+"H 	c #202020",
+"I 	c #A0A0A0",
+"J 	c #FEFEFE",
+"K 	c #747474",
+"L 	c #000000",
+"M 	c #010101",
+"N 	c #020202",
+"O 	c #030303",
+"P 	c #040404",
+"Q 	c #050505",
+"R 	c #060606",
+"S 	c #070707",
+"T 	c #080808",
+"U 	c #090909",
+"V 	c #0A0A0A",
+"W 	c #0C0C0C",
+"X 	c #0D0D0D",
+"Y 	c #0E0E0E",
+"Z 	c #0F0F0F",
+"` 	c #101010",
+" .	c #111111",
+"..	c #121212",
+"+.	c #131313",
+"@.	c #141414",
+"#.	c #151515",
+"$.	c #171717",
+"%.	c #191919",
+"&.	c #1D1D1D",
+"*.	c #1F1F1F",
+"=.	c #DFDFDF",
+"-.	c #232323",
+";.	c #252523",
+">.	c #2B2B28",
+",.	c #2C2C29",
+"'.	c #2C2C2A",
+").	c #2D2D2A",
+"!.	c #2D2D2B",
+"~.	c #2E2E2B",
+"{.	c #2E2E2C",
+"].	c #2F2F2C",
+"^.	c #30302D",
+"/.	c #242423",
+"(.	c #272723",
+"_.	c #272724",
+":.	c #282824",
+"<.	c #292925",
+"[.	c #292926",
+"}.	c #2A2A26",
+"|.	c #2D2D28",
+"1.	c #2E2E2A",
+"2.	c #2F2F2A",
+"3.	c #30302B",
+"4.	c #2E302F",
+"5.	c #2E3131",
+"6.	c #303333",
+"7.	c #313434",
+"8.	c #303434",
+"9.	c #2F312F",
+"0.	c #2E2E29",
+"a.	c #2C2C28",
+"b.	c #2C2C27",
+"c.	c #2B2B26",
+"d.	c #2C2C26",
+"e.	c #2E2E28",
+"f.	c #2E2E27",
+"g.	c #2D2D27",
+"h.	c #1E1E1B",
+"i.	c #282825",
+"j.	c #33332F",
+"k.	c #32322F",
+"l.	c #32322E",
+"m.	c #31312E",
+"n.	c #30302C",
+"o.	c #242422",
+"p.	c #A4A4A4",
+"q.	c #868686",
+"r.	c #0B0B0B",
+"s.	c #171716",
+"t.	c #A2A295",
+"u.	c #BEBEAE",
+"v.	c #BEBEAF",
+"w.	c #BEBEB0",
+"x.	c #BFBFB0",
+"y.	c #C0C0B0",
+"z.	c #C0C0B2",
+"A.	c #C1C1B2",
+"B.	c #C2C2B2",
+"C.	c #7E7E74",
+"D.	c #5F5F4F",
+"E.	c #B9B998",
+"F.	c #BCBC99",
+"G.	c #BCBC9A",
+"H.	c #BDBD9A",
+"I.	c #BEBE9A",
+"J.	c #BEBE9B",
+"K.	c #C1C19E",
+"L.	c #C2C29E",
+"M.	c #C3C39F",
+"N.	c #9EAA9F",
+"O.	c #92A4A4",
+"P.	c #92A5A5",
+"Q.	c #93A6A6",
+"R.	c #94A6A6",
+"S.	c #A8B3A3",
+"T.	c #C4C4A0",
+"U.	c #C5C5A0",
+"V.	c #C6C6A1",
+"W.	c #C6C6A0",
+"X.	c #C7C7A1",
+"Y.	c #C9C9A2",
+"Z.	c #7C7C65",
+"`.	c #949487",
+" +	c #CDCDBC",
+".+	c #CDCDBB",
+"++	c #A3A394",
+"@+	c #0B0B0A",
+"#+	c #191918",
+"$+	c #8B8B80",
+"%+	c #9E9E92",
+"&+	c #9F9F92",
+"*+	c #A0A093",
+"=+	c #A0A094",
+"-+	c #A1A194",
+";+	c #67675F",
+">+	c #686857",
+",+	c #D2D2AB",
+"'+	c #D3D3AC",
+")+	c #D4D4AD",
+"!+	c #D5D5AD",
+"~+	c #D5D5AE",
+"{+	c #D6D6AE",
+"]+	c #D6D6AF",
+"^+	c #D7D7AF",
+"/+	c #AEB6A0",
+"(+	c #9AA69A",
+"_+	c #9AA698",
+":+	c #9AA699",
+"<+	c #B5BCA3",
+"[+	c #DBDBB1",
+"}+	c #DADAB1",
+"|+	c #DBDBB0",
+"1+	c #DADAB0",
+"2+	c #969679",
+"3+	c #6C6C64",
+"4+	c #9E9E91",
+"5+	c #9E9E90",
+"6+	c #99998C",
+"7+	c #98988B",
+"8+	c #848478",
+"9+	c #111110",
+"0+	c #B0B0B0",
+"a+	c #959595",
+"b+	c #0C0C0E",
+"c+	c #0E0E10",
+"d+	c #131314",
+"e+	c #696957",
+"f+	c #D8D8B0",
+"g+	c #D6D6AD",
+"h+	c #D7D7AE",
+"i+	c #D8D8AF",
+"j+	c #DBDBB2",
+"k+	c #DCDCB2",
+"l+	c #DCDCB1",
+"m+	c #A8A888",
+"n+	c #0F0F11",
+"o+	c #0E0E0F",
+"p+	c #0A0A0C",
+"q+	c #09090A",
+"r+	c #080809",
+"s+	c #070708",
+"t+	c #060608",
+"u+	c #0B0B0C",
+"v+	c #181817",
+"w+	c #1C1C1B",
+"x+	c #6F6F5C",
+"y+	c #D7D7B0",
+"z+	c #D9D9B0",
+"A+	c #D9D9B1",
+"B+	c #DADAB2",
+"C+	c #B9B995",
+"D+	c #161615",
+"E+	c #161614",
+"F+	c #141413",
+"G+	c #C0C0C0",
+"H+	c #A5A5A5",
+"I+	c #A4A497",
+"J+	c #AAAA9C",
+"K+	c #AAAA9D",
+"L+	c #ABAB9D",
+"M+	c #ACAC9E",
+"N+	c #ACAC9F",
+"O+	c #ADAD9F",
+"P+	c #AEAEA0",
+"Q+	c #5B5B54",
+"R+	c #777762",
+"S+	c #DCDCB3",
+"T+	c #DDDDB3",
+"U+	c #DDDDB2",
+"V+	c #C5C59F",
+"W+	c #4F4F46",
+"X+	c #B6B6A6",
+"Y+	c #BABAAA",
+"Z+	c #B9B9AA",
+"`+	c #B8B8A8",
+" @	c #4F4F49",
+".@	c #595959",
+"+@	c #3C3C39",
+"@@	c #BCBCAD",
+"#@	c #BDBDAE",
+"$@	c #C0C0B1",
+"%@	c #5B5B55",
+"&@	c #808069",
+"*@	c #DBDBB3",
+"=@	c #DCDCB4",
+"-@	c #DDDDB4",
+";@	c #DEDEB4",
+">@	c #CECEA6",
+",@	c #57574C",
+"'@	c #BDBDAC",
+")@	c #C4C4B3",
+"!@	c #C3C3B2",
+"~@	c #63635B",
+"{@	c #CBCBCB",
+"]@	c #ABABAB",
+"^@	c #282826",
+"/@	c #292927",
+"(@	c #2A2A28",
+"_@	c #2B2B29",
+":@	c #84846C",
+"<@	c #D6D6B0",
+"[@	c #DEDEB3",
+"}@	c #DEDEB2",
+"|@	c #D5D5AC",
+"1@	c #3F3F36",
+"2@	c #232321",
+"3@	c #222220",
+"4@	c #212120",
+"5@	c #21211F",
+"6@	c #20201E",
+"7@	c #1F1F1D",
+"8@	c #6B6B6B",
+"9@	c #FBFBFB",
+"0@	c #515144",
+"a@	c #80806A",
+"b@	c #81816A",
+"c@	c #81816B",
+"d@	c #82826B",
+"e@	c #82826C",
+"f@	c #83836C",
+"g@	c #84846D",
+"h@	c #84846E",
+"i@	c #85856E",
+"j@	c #86866E",
+"k@	c #85856D",
+"l@	c #7E7E67",
+"m@	c #7E7E66",
+"n@	c #7D7D66",
+"o@	c #7A7A63",
+"p@	c #D3D3D3",
+"q@	c #BCBCBC",
+"r@	c #212121",
+"s@	c #222222",
+"t@	c #242424",
+"u@	c #525252",
+"v@	c #D4D4D4",
+"w@	c #AFAFAF",
+"x@	c #636363",
+"y@	c #D6D6D6",
+"z@	c #353535",
+"A@	c #505050",
+"B@	c #C3C3C3",
+"C@	c #818181",
+"D@	c #4F4F4F",
+"E@	c #565656",
+"F@	c #585858",
+"G@	c #5D5D5D",
+"H@	c #5E5E5E",
+"I@	c #5F5F5F",
+"J@	c #606060",
+"K@	c #646464",
+"L@	c #676767",
+"M@	c #666666",
+"N@	c #686868",
+"O@	c #6A6A6A",
+"P@	c #656565",
+"Q@	c #6C6C6C",
+"R@	c #707070",
+"S@	c #616161",
+"T@	c #717171",
+"U@	c #727272",
+"V@	c #6E6E6E",
+"W@	c #737373",
+"X@	c #7A7A7A",
+"Y@	c #757575",
+"Z@	c #777777",
+"`@	c #797979",
+" #	c #535353",
+".#	c #7B7B7B",
+"+#	c #767676",
+"@#	c #6D6D6D",
+"##	c #7E7E7E",
+"$#	c #575757",
+"%#	c #515151",
+"&#	c #626262",
+"*#	c #7C7C7C",
+"=#	c #838383",
+"-#	c #848484",
+";#	c #858585",
+">#	c #888888",
+",#	c #5A5A5A",
+"'#	c #7D7D7D",
+")#	c #8C8C8C",
+"!#	c #8D8D8D",
+"~#	c #909090",
+"{#	c #919191",
+"]#	c #929292",
+"^#	c #939393",
+"/#	c #949494",
+"(#	c #898989",
+"_#	c #969696",
+":#	c #979797",
+"<#	c #555555",
+"[#	c #989898",
+"}#	c #828282",
+"|#	c #8E8E8E",
+"1#	c #8B8B8B",
+"2#	c #8F8F8F",
+"3#	c #545454",
+"4#	c #787878",
+"5#	c #878787",
+"6#	c #999999",
+"7#	c #8A8A8A",
+"8#	c #ECECEC",
+"9#	c #7F7F7F",
+"0#	c #5B5B5B",
+"a#	c #6F6F6F",
+"b#	c #696969",
+"c#	c #9A9A9A",
+"d#	c #FDFDFD",
+"e#	c #AAAAAA",
+"f#	c #808080",
+"g#	c #9B9B9B",
+"h#	c #9C9C9C",
+"i#	c #C1C1C1",
+"j#	c #F2F2F2",
+"k#	c #CCCCCC",
+"l#	c #9D9D9D",
+"m#	c #E5E5E5",
+"n#	c #9E9E9E",
+"o#	c #F6F6F6",
+"p#	c #C8C8C8",
+"q#	c #9F9F9F",
+"r#	c #BFBFBF",
+"s#	c #A1A1A1",
+"t#	c #BEBEBE",
+"u#	c #DDDDDD",
+"v#	c #BABABA",
+"w#	c #A2A2A2",
+"x#	c #DCDCDC",
+"y#	c #A3A3A3",
+"z#	c #A6A6A6",
+"A#	c #ACACAC",
+"B#	c #ADADAD",
+"C#	c #AEAEAE",
+"D#	c #B1B1B1",
+"E#	c #B2B2B2",
+"F#	c #B4B4B4",
+"G#	c #B8B8B8",
+"H#	c #B9B9B9",
+"I#	c #BBBBBB",
+"J#	c #BDBDBD",
+"K#	c #C6C6C6",
+"L#	c #C7C7C7",
+"M#	c #CACACA",
+"N#	c #CECECE",
+"O#	c #D2D2D2",
+"P#	c #D8D8D8",
+"Q#	c #D9D9D9",
+"R#	c #D7D7D7",
+"S#	c #DBDBDB",
+"T#	c #A8A8A8",
+"U#	c #D1D1D1",
+"V#	c #D0D0D0",
+"W#	c #CFCFCF",
+"X#	c #C9C9C9",
+"Y#	c #B7B7B7",
+"Z#	c #C5C5C5",
+"`#	c #C4C4C4",
+" $	c #B6B6B6",
+".$	c #B5B5B5",
+"+$	c #B3B3B3",
+"@$	c #A7A7A7",
+"#$	c #A9A9A9",
+"$$	c #C2C2C2",
+"%$	c #D5D5D5",
+"&$	c #CDCDCD",
+"*$	c #E6E6E6",
+"=$	c #E7E7E7",
+"-$	c #E1E1E1",
+";$	c #8A8989",
+">$	c #6D6B6B",
+",$	c #646262",
+"'$	c #A4A3A3",
+")$	c #AEADAD",
+"!$	c #D4D3D3",
+"~$	c #818080",
+"{$	c #969595",
+"]$	c #A5A4A4",
+"^$	c #8A8888",
+"/$	c #838181",
+"($	c #727070",
+"_$	c #817F7F",
+":$	c #858484",
+"<$	c #868484",
+"[$	c #777575",
+"}$	c #6E6C6C",
+"|$	c #888686",
+"1$	c #BFBEBE",
+"2$	c #898888",
+"3$	c #797878",
+"4$	c #706E6E",
+"5$	c #9F9E9E",
+"6$	c #7A7878",
+"7$	c #DFDEDE",
+"8$	c #656363",
+"9$	c #8D8B8B",
+"0$	c #747373",
+"a$	c #666464",
+"b$	c #C6C5C5",
+"c$	c #EAE9E9",
+"d$	c #999898",
+"e$	c #BDBCBC",
+"f$	c #939292",
+"g$	c #CAC9C9",
+"h$	c #9A9999",
+"i$	c #7E7D7D",
+"j$	c #6C6A6A",
+"k$	c #686666",
+"l$	c #8C8B8B",
+"m$	c #6F6D6D",
+"n$	c #D8D7D7",
+"o$	c #7B7979",
+"p$	c #8E8D8D",
+"q$	c #AAA9A9",
+"r$	c #9E9D9D",
+"s$	c #AFAEAE",
+"t$	c #8B8A8A",
+"u$	c #7E7C7C",
+"v$	c #959494",
+"w$	c #919090",
+"x$	c #8F8E8E",
+"y$	c #6B6969",
+"z$	c #767575",
+"A$	c #929191",
+"B$	c #7C7B7B",
+"C$	c #6F6E6E",
+"D$	c #949393",
+"E$	c #737171",
+"F$	c #828181",
+"G$	c #B7B6B6",
+"H$	c #A9A8A8",
+"I$	c #939191",
+"J$	c #B2B1B1",
+"K$	c #B5B4B4",
+"L$	c #FAF9F9",
+"M$	c #ABA9A9",
+"N$	c #7F7D7D",
+"O$	c #BEBDBD",
+"P$	c #878585",
+"Q$	c #747272",
+"R$	c #D1D0D0",
+"S$	c #A6A4A4",
+"T$	c #9B9999",
+"U$	c #C1C0C0",
+"V$	c #BCBBBB",
+"W$	c #DAD9D9",
+"X$	c #C0BFBF",
+"Y$	c #B1B0B0",
+"Z$	c #969494",
+"`$	c #908F8F",
+" %	c #ABAAAA",
+".%	c #9C9B9B",
+"+%	c #D7D6D6",
+"@%	c #DEDDDD",
+"#%	c #C7C6C6",
+"$%	c #A6A5A5",
+"%%	c #807F7F",
+"&%	c #7C7A7A",
+"*%	c #CDCCCC",
+"=%	c #CFCECE",
+"-%	c #676565",
+";%	c #9A9898",
+">%	c #716F6F",
+",%	c #696767",
+"'%	c #797777",
+")%	c #C5C4C4",
+"!%	c #B9B8B8",
+"~%	c #706F6F",
+"{%	c #727171",
+"]%	c #A1A0A0",
+"^%	c #6A6868",
+"/%	c #7D7B7B",
+"(%	c #8D8C8C",
+"_%	c #B3B2B2",
+":%	c #BAB9B9",
+"<%	c #CBCACA",
+"[%	c #696868",
+"}%	c #717070",
+"|%	c #9D9B9B",
+"1%	c #7A7979",
+"2%	c #C3C2C2",
+"3%	c #ECEBEB",
+"4%	c #EFEEEE",
+"5%	c #8E8C8C",
+"6%	c #767474",
+"7%	c #ADACAC",
+"8%	c #989696",
+"9%	c #B4B3B3",
+"0%	c #ACABAB",
+"a%	c #757373",
+"b%	c #C4C3C3",
+"c%	c #807E7E",
+"d%	c #787676",
+"e%	c #A7A6A6",
+"f%	c #8F8D8D",
+"g%	c #BBBABA",
+"h%	c #908E8E",
+"i%	c #D0CFCF",
+"j%	c #7D7C7C",
+"k%	c #838282",
+"l%	c #9D9C9C",
+"m%	c #868585",
+"n%	c #9B9A9A",
+"o%	c #8C8A8A",
+"p%	c #A3A2A2",
+"q%	c #C8C7C7",
+"r%	c #DBDADA",
+"s%	c #9E9C9C",
+"t%	c #E1E0E0",
+"u%	c #848383",
+"v%	c #888787",
+"w%	c #858383",
+"x%	c #848282",
+"y%	c #757474",
+"z%	c #A09F9F",
+"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ",
+"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ",
+"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ",
+"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ",
+"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ",
+"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ",
+"                                                                        . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @ # # # # # # # # # # # # # # # # $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % & * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * = = = = = = = = = = = = = - ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; - - - - - - - - - - - - - > > > > > > ; , , , ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; , ' ' ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ~ ~ ~ ~ ~ ~ { ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ^ / / / / / ( #                                                                       ",
+"                                                                      _ : < [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ } } } } } } } } } } } } } } } } | 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 5 5 5 5 5 5 4 4 4 4 4 4 4 4 4 6 6 6 6 7 7 7 7 7 7 8 8 3 3 3 4 4 4 4 6 6 6 6 7 7 7 7 7 4 9 9 9 9 9 5 5 4 4 4 4 4 4 4 6 7 7 7 7 8 8 3 3 3 0 0 a a b 2 2 1 1 c c d e e | } } | e e } } } f g g h [ [ [ < i i i i i j j j k k k j j j j j j i i i < < [ [ h g g f e c c 1 2 b b a 0 3 8 7 7 4 4 5 9 9 l l m n n o p p q r r s s t t u v v w x x x y y z A B C C C C C C C C D D D E E E E E E E E F G G G G G H I J                                                                     ",
+"                                                                    . K L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O O P P Q R R S T U V W W X Y Y Z `  .....+.@.#.G G $.F F %.E D D C C &.&.B B B B B *.*.*.*.*.*.*.B B B B &.&.C C D D E E F F F G G #.@.@.+... .` ` Z Y Y X W W V U T T S R R Q P P P O N N N N N N N N N N M M M M M M M M M M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L m '                                                                     ",
+"                                                                    =.-.L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M M N N N O P P Q Q R S T U V W X X V ;.>.,.'.).!.~.{.].^./.E (._.:.:.<.[.}.|.1.2.2.2.3.3.4.5.5.6.7.8.8.8.8.8.9.2.2.1.1.0.0.|.a.b.b.c.d.e.f.g.g.h.i.j.k.l.l.m.^.n.n.].o.R T S R Q Q P O O N N N M M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L O p.J                                                                   ",
+"                                                                  J q.L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M M N N O O P P Q R R S T U r.W X X Y s.t.u.v.w.x.y.y.z.A.B.C.D.E.F.G.H.I.J.J.K.L.L.M.M.M.M.N.O.O.P.Q.Q.R.R.R.R.S.T.T.U.V.W.W.W.W.W.W.W.X.Y.Y.Y.Y.Z.`. + + + +.+.+.+.+.+++@+U T S R Q Q P O O N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L a >                                                                   ",
+"                                                                  ] x L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O O P P Q R S T U V W W X Y Y #+$+%+%+&+&+*+=+-+-+t.;+>+,+,+'+'+)+)+!+~+{+{+]+^+^+^+/+(+_+_+:+(+(+(+(+(+<+[+}+}+[+[+[+[+[+[+[+[+|+|+|+1+|+2+3+%+%+%+4+5+5+5+6+7+8+9+V T T R R Q P P O O N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L T 0+                                                                  ",
+"                                                                J a+L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M M N N N O P P Q R R S T V V W X X Y Z Y ` b+c+`  ...d+@.#.G F e+,+'+'+)+)+~+~+{+]+^+^+f+f+f+{+!+g+{+{+{+h+h+h+h+i+j+j+j+k+k+k+k+k+k+l+l+[+[+[+[+|+m+n+` o+b+p+q+r+r+T s+t+U V U T S R Q P P O O N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L k %                                                                 ",
+"                                                                ) o L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O O P P Q R R T T V r.W X Y Y Z u+@.@.@.#.G s.v+F %.w+E x+'+'+)+!+~+{+{+]+^+y+f+f+z+A+A+}+B+B+B+j+j+j+k+k+k+k+k+k+k+k+k+k+k+k+k+k+k+k+l+l+l+C+v+E F v+s.s.D+E+@.F+D+@+V V T S R R Q P P O N N N M M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L W G+                                                                ",
+"                                                                H+L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O O P P Q R S T U V W W X Y Z ` ,.I+J+K+L+M+M+N+O+P+P+Q+R+'+)+!+~+{+]+^+y+f+f+f+A+A+B+B+B+j+j+j+S+S+S+S+S+S+S+S+S+T+T+T+T+T+U+U+k+k+k+k+k+k+V+W+X+Y+Y+Y+Y+Y+Y+Y+Z+`+ @r.V T T S R Q P P O O N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L .@$                                                               ",
+"                                                              - 8 L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O O P P Q R R S T V V W X Y Y Z ` +@`+@@#@#@u.v.x.y.$@y.%@&@)+!+~+{+]+^+y+f+f+A+A+B+B+B+j+j+*@S+S+S+=@=@-@-@-@-@-@-@-@-@;@T+T+T+T+T+T+U+U+U+U+>@,@'@)@)@!@!@!@!@!@!@!@~@W V U T S R Q P P O O N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ` {@                                                              ",
+"                                                              ]@Q L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O O P P Q R S T U V r.W X Y Y Z ` #.^@^@^@/@(@(@_@'.'.{.*.:@{+{+{+<@f+f+f+A+B+B+B+B+j+S+=@=@=@=@-@;@;@;@;@;@;@;@;@;@;@;@;@;@;@;@;@;@;@;@;@[@}@|@1@o.2@2@3@4@5@6@6@7@7@9+W V V T S R R Q P P O N N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L 8@9@                                                            ",
+"                                                            & [ L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M M N N N O O P P Q R S T U V W W X Y Z ` ` ....+.@.#.G G F F %.E D 0@a@a@a@b@c@d@e@e@f@g@g@h@h@h@i@i@i@i@j@j@j@j@j@j@j@j@j@j@j@j@i@i@k@g@:@&@l@l@l@m@n@o@<.G @.@.+... .` Z Y Y X W r.V T T R R Q P P O O N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L F p@                                                            ",
+"                                                            q@V L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O O P P Q R R S T V r.W X Y Y Z `  .....+.@.#.G $.F %.E E D C &.B B *.H r@r@s@s@-.-.t@t@t@A A A A A A A A t@t@t@-.-.s@s@r@H H *.B B &.C D E %.F F G G #.@.+... .` ` Z Y X W W V U T S R Q Q P O O N N N M M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L K 9@                                                          ",
+"                                                          % u@L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N M M M N P R S T U U Q Q Q R T Z `  ...+.Z V V r.r.#.%.E D C C B B *.H H r@s@s@-.-.G  . ...#.t@A A A A r@.... .` D -.-.s@s@r@H H *.B &.C C E E %.$.W T T T V .... .` Z V P P O O S T S R R P N M M L L N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L D v@                                                          ",
+"                                                        J w@r.L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N M L L L L O Q R S T S L L L L O Y Z ` `  .V L L L L ..$.F F %.E D D C C &.B B *.H *.r.N N N T H s@s@s@r@D N N N N +.H *.B B &.&.C C D E E F F $.G @.P L L L N ` ` ` ` Y R L L L L P V U T T P L L L L L P Q Q P P P P P P P P P P P P N L L L L L N P P P P L L L L L L O O O O O O O O O O O O N N O M L L L L L M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L x@&                                                         ",
+"                                                        y@A L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M L L L L L N N N N N M L L M M O P Q R R R R S T T T T T U T R O N N N P W Y Y Y T Q O O O N U ..+.+.@.@.@.G G $.$.F %.E E F O L M L L M C -.t@A G L L L L L Z r q p p W L L L L L w 6 7 7 8 3 3 a a a b b 2 2 2 A L L L L L r@b b a 3 Z L L L L O p 6 4 4 5 9 z@l m n o p q r s E L L L L L +.*.C F +.N L L L L L N N M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L T a+.                                                       ",
+"                                                      , A@L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M L L L L L M M M M N N N N N M L N O O O O Q R R R L L O P O O Q V V r.r.W W Y Z Y Y Z ` ` +. .L L M M M L @.D C H ` L L L L L T z z y x U L L L L L C r r r r q o p p p p p p p o C L L L L L ` q s t t U L L L L L E z -.s@r@r@B E &.E %.F $.G G ` L L L L L Q ......@.N L L L L L P r.T T Q L L L L L L N P N N Q O M P N N N N N X  .V L L L L L L L L L L L L L L L L L G B@                                                      ",
+"                                                    + C@L L L L L L L L L L L L L L L L L L L L R A Z W W W M L L L L L L U X X V L L L L L L Y l 9 9 9 5 5 4 B B 4 &.` ` ` O L L L L L P ` ` ` X L L L L L L t@.. . .T L L L L L +.2 c c c c d d C w e e A @.@. .L L L L L @.d &.@.@.r.L L L L L b j j j k k D@2 Z j u@u@| F F G N L L L L 2 E@4 F F ` L L L L &.F@.@t %.E U M M M N < G@G@H@H@H@I@b F J@K@K@K@d C C r.P P P  .H@L@M@n C F P P P P t@N@O@O@O@O@O@P@#.k O@8@8@Q@O@p E R M M M M 1 R@R@N@t@ .L L L L T S@T@U@G@%.P L L L L B V@U@U@U@U@Q@G E@W@W@W@W@W@W@4 P L L L L T P@X@X@Y@*.L L L L L &.K X@X@X@X@< -.Z@X@X@`@`@`@`@: P L L L L M  #.#.#+#*.L L L L L ..@#X@X@F@O L L L L L t Y@Z@Z@Z@i p W@+#+#+#Y@Y@.###N@Z L L L L L L L L L L L L L L L L L 7 ]                                                     ",
+"                                                  J 0+Z L L L L L L L L L L L L L L L L L L L L A l F F F ` L L L L L L Q $.%.F V L L L L L L 9 E@E@E@$#$#$#H@0 h u@r@D D G N L L L L L G C C C ` L L L L L  .4 C C C T L L L L L 6 K@K@P@P@M@M@L@n %#L@P@r B B G L L L L L 6 K@A *.*.W L L L L W &#R@T@T@T@U@U@.@H T@K K .@H r@&.M L L L P K@`@} s@s@@.L L L L 9 ##*#7 t@t@W M M M T V@=#-#-#;#;#q.$#s@=#>#>#>#,#y z Z P Q Q +.'#)#!#k y s@R Q Q Q w )#~#~#~#~#{#)#-.J@]#]#]#]#]#A@A W N M M M c ^#/#~#8 C L L L L N U@a+a+>#u W L L L L $.(#_#_#:#:#a+6 <#:#:#:#:#[#[#M@V L L L L L : [#[#:#A@L L L L L V *#[#[#[#[#C@r@}#[#[#[#:#:#:#|#r@L L L L L p {#_#a+I@L L L L L L : /#/#1#z L L L L L W +#{#{#~#-#0 U@~#2#2#|#|#|#|#!#: P L L L L L L L L L L L L L L L L L M@&                                                   ",
+"                                                  y@A L L L L L L L L L L L L L L L L L L L L Y b &.F F G P L L L L L L ` %.%.@.M L L L L L @.A@E@E@$#$#$#F@J@4 $#b E E D r.L L L L L U r@D D E Q L L L L L s t C C F M L L L L R  #K@P@P@P@M@M@K@q &#N@H@s@B B W L L L L N 3#,#H *.B S L L L L D Q@R@T@T@U@U@U@j 9 K K K k r@r@%.L L L L ` V@4#a s@s@Z L L L L | ##*#9 t@-.U M M N Y K -#-#;#;#q.q.<#s@-#>#(#(#G@y y  .R R R ..*#!#|#u@x -.T R R R -.1#~#{#{#{#]#~#r  #^#]#]#^#^#&#A ..N N M M u {#/#/#i H O L L L L $#_#_#]#a @.L L L L P Y@:#:#:#:#[#H@s ^#[#[#[#[#[#5#H L L L L L p /#[#6#*#Y L L L L L u@[#[#[#[#_#3 E@[#[#[#[#[#[#[#,#L L L L L T W@_#_#7#B L L L L L B >#/#/#M@P L L L L L z@|#]#]#{#O@g (#~#~#2#2#2#|#|#5#p L L L L L L L L L L L L L L L L L T a+.                                                 ",
+"                                                8#D@L L L L L L L L L L L L L L L L L L L L N l o $.F F X L L L L L L T F %.F U L L L L L M 6 E@E@E@$#$#$#H@} [ E@z E E F O L L L L L &.B D D @.L L L L L R c H C C Z L L L L L *.S@K@P@P@M@M@M@F@5 M@N@D@&.B C R L L L L ` x@[ B *.D N L L L L n R@T@T@T@U@U@U@6 j K K Y@c r@r@@.L L L L E K 4#5 s@s@r.L L L L k 9#.#l t@s@T N N N Z Y@-#;#;#q.q.5#3#t@;#(#(#7#K@y y ..R R R ..'#|#|#: x t@V S R R H (#{#]#]#]#]#]#c 2 ]#^#^#/#/#K A F N N N N C )#a+a+x@s@T L L L L 4 a+_#_#F@E L L L L L F@[#[#[#[#[#9#C -#[#[#[#[#6#a+0 O L L L L Z -#6#6#/#q L L L L L *.2#6#6#6#6#U@A !#6#6#6#[#[#[#(#E L L L L L 8 /#:#:#0#L L L L L L G@a+a+!#s L L L L L T a#]#]#]#)#< M@~#~#~#~#~#2#2#2#Y@` L L L L L L L L L L L L L L L L L G B@                                                ",
+"                                              # ##L L L L L L L L L L L L L L L L L L L L L C c D $.F #.N L L L L L M +.F F +.M L L L L L F %#E@E@$#$#$#F@J@9 F@} D E E Z L L L L L Q v D D E U L L L L L B a D C D R L L L L L 2 K@P@P@P@M@M@L@0 %#N@N@3 B B %.L L L L L -.b#5 *.*.G L L L L L i T@T@T@U@U@U@R@x : K K K 4 r@r@Y L L L L t@4#+#n s@r@U L L L L 0#9#`@p t@s@T N N N $..#;#;#q.q.5#># #x q.7#7#7#N@y x @.T T T Y `@2#2#x@x A W T T T D q.]#]#]#^#^#^#u@t ]#/#/#/#/#C@w C N N N N Y C@_#_#4#t@X L L L L s@~#:#:#W@B P L L L L n a+[#[#[#[#{#s@b#6#6#6#6#6#6#M@V L L L L L S@c#c#c#I@M L L L L Q K c#c#c#c#{#v O@c#c#6#6#6#6#[#D@L L L L L W ##[#[#7#C L L L L L B 7#_#_#R@T L L L L L p !#^#^#]#4#c =#{#{#~#~#~#~#2#|#A@L L L L L L L L L L L L L L L L L L 4 ^                                               ",
+"                                          d#/ >#W L L L L L L L L L L L L L L L L L L L L S 2 t $.$.$.V L L L L L L V F F F T L L L L L O a E@E@$#$#$#$#H@h g F@r E E F Q L L L L L C z D D $.N L L L L L 0 u C C G L L L L L V $#K@P@P@M@M@M@K@p J@N@K@t B B ..L L L L L 2 N@v *.*.Y L L L L Q H@R@T@T@U@U@W@O@y O@K Y@T@q r@H V L L L L l X@K s s@H S L L M L K@9#4#r t@r@R N N O %.*#;#q.q.5#>#>#%#v >#7#1#1#b#y x G T U U U Y@~#~#Q@x z X U U U @.}#^#^#/#/#/#/#J@t@2#a+a+a+a+)#n H O O N N N W@_#_#>#t @.L M L L X =#[#[#>#w U L L L L E !#6#6#6#6#6#k d [#c#c#c#c#c#;#D L L L L L n :#c#c#q.@.L L L L L 2 [#c#c#c#c#G@m a+c#c#c#c#c#c#}#` L L L L L < :#[#[#0#L L L L L L H@_#_#{#z@L L L L L R M@/#/#^#{#F@E@~#]#{#{#{#~#~#~#-#t@L L L L L L L L L L L L L L L L L L P@&                                             ",
+"                                          + e#X L L L L L L L L L L L L L L L L L L L L L s 2 %.$.$...M L L L L L N #.F F ..L L L L L L D u@E@E@$#$#$#F@&#5 $#k B E E  .L L L L L O n &.D D Y L L L L L ` [ *.C C W L L L L L t@&#K@P@P@M@M@M@.@z@L@N@G@r@B &.U L L L L P $#&#s@B B T L L L L +.N@T@T@U@U@U@W@J@x R@K Y@V@x r@*.S L L L L f X@R@x s@*.P L M M T Q@f#Z@t t@H P O O O C 9#q.5#5#>#>#(#3#c (#1#1#)#8@y x G V V V U Y@~#{#K x x ` V V V Z *#/#/#/#/#/#a+U@w )#_#_#_#_#]#a -.S P O O N S@:#:#]#7 E L M M M L K [#[#/#8 ` L L L L P X@6#6#c#c#c#T@*.|#c#c#c#c#c#_#6 N L L L L  .q.g#g#:#5 L L L L L F 1#g#g#g#g#(#s@'#g#c#c#c#c#c#:#a L L L L L G q.6#6#1#C L L L L L s@)#:#:#+#V L L L L L t@1#/#/#/#-#c 4#]#]#]#]#{#{#~#~#O@T L L L L L L L L L L L L L L L L L T a+.                                           ",
+"                                          ! h L L L L L L L L L L L L L L L L L L L L L @.g y $.$.G R L L L L L L X F F $.R L L L L L P 1 E@E@$#$#$#F@H@[ f F@9 %.E %.R L L L L L #.o E D %.Q L L L L L r 0 D C E P L L L L L e K@P@P@P@M@M@N@2 [ N@N@< &.&.E N L L L L #.P@3#B B D N L L L L z a#T@T@U@U@W@W@A@l K Y@Y@L@-.H &.N L L L L $#X@Q@A s@&.N M M M Y U@f#K x t@*.P O O P r@}#5#5#>#>#(#7#<#g 7#)#)#!#T@x w $.W W W U K {#]#X@w x ` W W W T +#/#a+a+a+_#_#9#z ;#_#_#_#_#_#< t@V P P O O i :#[#:#< H N M M M M F@6#6#6#E@%.L L L L L 0#c#c#c#c#c#1#D X@c#c#g#g#g#g#x@T L L L L L M@h#h#h#O@P L L L L L N@h#h#h#h#c#} i c#g#g#g#g#g#g#X@U L L L L L $#6#c#[#F@L L L L L M &#[#:#/#a L L L L L M I@a+/#/#/#N@i |#^#]#]#]#]#{#{#|#c L M L L L L L L L L L L L L L L L L G i#J                                         ",
+"                                        # W@L L L L L L L L L L L L L L L L L L L L L Q 3 0 F $.$.Z L L L L L L P G F F ` L L L L L L B  #E@E@$#$#$#F@&#9 E@ #r@E E +.L L L L L L l t@D D ..L L L L L Q [ v D C @.L L L L L ` ,#K@P@P@M@M@M@L@o I@N@L@5 &.&.G L L L L L s Q@c B B G L L L L L 2 T@T@U@U@U@W@W@a f Y@Y@Y@G@H H E L L L L O K@.#M@s@s@E M M M M $.4#C@U@y t@B O P P P t@=#5#>#>#(#(#7#u@g 7#)#!#!#Y@w w $.W W X U R@]#]#}#s w +.X X W T R@_#_#_#_#_#_#5#t@*#:#:#:#:#[#H@z Y P P P O n _#[#[#K@r@R M M M M z@:#6#6#W@B N L L L L l [#c#c#c#c#:#o F@g#g#g#g#g#g#-#F L L L L L m 6#h#h#|#D L L L L L n [#h#h#h#h#`@t@)#h#h#h#h#h#g#_#l L L L L L C !#c#c#7#E L L L L L s@|#[#[###` L L L L L C q.a+a+a+!#g @#/#^#^#]#]#]#]#{#f#%.L M L L L L L L L L L L L L L L L L 9 ^                                         ",
+"                                      d#p.r.L L L L L L L L L L L L L L L L L L L L L s@[ -.$.$.G P L L L L L L ` F F G Q L L L L L Q c E@E@$#$#$#F@H@h } .@b %.E %.T L L L L L ` 0 E E E T L L L L L C k &.D D U L L L L L x x@P@P@P@M@M@M@: o M@N@x@y &.&.X L L L L L [ Q@l B B Y L L L L N $#T@T@U@U@U@W@R@v ,#Y@Y@+#u@H H G L L L L X @#.#H@r@s@F L M M M B *#C@V@A t@D P P Q Q u ;#>#>#(#7#7#1#%#g 1#!#|#|#+#w w F X X Y T O@^#^#q.p v @.Y Y Y r.N@_#_#_#:#:#:#|#t R@[#[#[#[#[#a#z +.Q Q P P s@]#6#6#4#-.r.M M M M -.^#c#c#(#x T L L L L E 2#g#g#g#g#g#J@r _#h#h#h#h#h#:#9 N L L L L ..(#h#h#g#f L L L L L Y =#h#h#h#h#:#q S@h#h#h#h#h#h#h#R@P L L L L L x@c#c#c#E@L L L L L M &#[#[#_#g L L L L L L <#a+_#a+a+K d >#/#/#^#^#]#]#]#]#J@P L M L L L L L L L L L L L L L L L L K@j#                                      ",
+"                                      k#F L L L L L L L L L L L L L L L L M L L L L W | 4 $.$.$.W L L L L L L S $.F F Z L L L L L L s@3#E@E@$#$#$#F@&#9 E@E@x %.E #.M L L L L L q r E E G M L L L L L 2 7 D D F N L L L L N h P@P@P@M@M@M@L@| h N@N@F@B &.C R L L L L U G@M@y B &.T L L L L ` M@T@T@U@U@W@W@8@t@M@Y@Y@+#f H H  .L L L L %.K *#E@s@s@@.M M M N t@##}#Q@t@A E P Q Q R t q.>#(#7#7#1#1#%#h )#|#|#2#`@v v F Y Y Y U O@/#/#)#9 v $.Z Z Z Y G@:#:#[#[#[#[#^#4 &#[#[#[#6#6#C@x E Q R Q Q @.>#c#c#7#t  .N M M M Z ;#c#c#a+7 W L L L L P .#g#g#g#h#h#C@D 5#h#h#h#h#h#h#H@S L L L L L N@l#l#l#+#R L L L L L .@l#l#l#l#l#N@u a+l#l#l#h#h#h#^#x L L L L L A ]#g#g#7#E L L L L L s@2#6#6#-#@.L L L L L F ;#_#_#_#]# #H@^#/#/#/#^#^#^#]#)#9 L M M L L L L L L L L L L L L L L L R ]#.                                     ",
+"                                    m#d L L L L L L L L L L L L L L L L L L L L L N l h *.$.$.@.N L L L L L M ..F F G P L L L L L S f E@E@$#$#$#$#I@h } .@g E %.%.V L L L L L U e *.E E W L L L L L `  #y D D  .L L L L L @.G@K@P@P@M@M@M@M@p : N@N@g C B %.M L L L L %.N@: *.B D O L L L L C @#T@U@U@U@W@W@&#z a#Y@+#Y@8 H H W L L L L s@4#*#j s@s@Z N N N O r f#}#L@t@A F S T U U 7 >#(#7#7#1#1#)#D@j !#|#2#~###s v &.#.G $.#.O@/#a+|#7 u &.E D D D F@[#[#[#[#[#6#:#d A@6#6#c#c#c#)#p B #.%.E %.C '#c#c#/#7 %.Z #.@.@.+.W@g#g#c#j #.U Y Y X X H@h#h#h#h#h#^#r@8@h#h#h#l#l#l#=##.L P O O N 9 c#l#n#/#s@L L L L L A :#n#n#n#n#2#-.+#l#l#l#l#l#l#l#K@L L L L L Q R@h#h#c#$#L L L L L M K@c#6#[#<#L L L L L L D@_#:#_#_#}#2 ##a+/#/#/#/#^#^#^#`@ .L N L L L L L L L L L L L L L L L L #.i#J                                   ",
+"                                  o#O@L L L L L L L L L L L L L L L L L M L L L L D < n G $.$.Y L L L L L L U $.F F +.L L L L L L A <#E@E@$#$#$#F@x@9 E@F@q %.%.F R L L L L L A 3 %.E E T L L L L L r A@C D D W L L L L L p K@P@P@P@M@M@M@H@p M@b#N@z@&.&.$.L L L L L n Q@< C &.E M L L L L m R@T@U@U@U@W@K  #v W@+#+#K m H H V L L L L m X@*#e s@s@Y N N P R b }#}#&#t@A F S S T T c (#7#7#1#)#)#)#i D@|#2#~#~#}#q u H $.F F F O@a+_#]#2 t -.r@s@s@-.F@6#6#6#6#c#c#6#k | c#c#c#c#c#/#8 s@t@[ $#z@y *#c#g#c#[ B E H &.4 b W@g#g#g#O@D Y #.@.+. .,#h#h#h#h#h#g#} | h#l#l#l#l#l#[#l N Q Q P O v c#n#n#l# #L M L L L &./#n#n#n#n#l#A@b g#n#n#n#n#l#l#2#C L L L L L L@h#h#h#1#E L L L L L F@c#c#c#(#E L L L L L 4 _#:#:#:#_#&#D@{#a+a+/#/#/#/#^#]# #L M N L L L L L L L L L L L L L L L L z@/                                   ",
+"                                d#I V L L L L L L L L L L L L L L L L M L L L L S 2 f C $.$.$.+.L L L L L N @.$.F F G M L L L L T g E@E@$#$#$#$#I@i | .@D@B %.%.%.T L L L L Q | z E E E V L L L L Q i 7 E D D ` L L L L O k K@P@P@M@M@L@N@} } b#b#K@x &.&.F L L L L L i @#8 &.&.D O L L L L i T@T@U@U@W@W@W@d e +#+#+#R@u H H r.L L L L e *#.#3 s@s@Y L L L L < }#=#J@t@A G L L L L } 7#7#1#)#)#!#!#[  #~#~#{#]#=#q t %.L L L L N@_#:#a+} t E L L L L 3#c#c#c#c#c#c#c#: 4 [#g#g#g#h#c#g A R 5 h G L ##g#g#g#M@r@R L M t@G Y@h#h#h#;#-.R L L L L x@l#h#l#l#l#l#U@*.{#l#n#n#n#n#n#,#R L L L L 4 l#n#n#n#C@X L L L L x c#n#n#n#n#n#f#H >#n#n#n#n#n#n#l#F@L L L L L `@l#h#h#g#F@L L L L L R@g#c#c#c#: L L L L L F@[#[#[#:#:#1#} U@_#_#a+a+/#/#/#/#>#x L N N L L L L L L L L L L L L L L L L J@j#                                ",
+"                                p#F L L L L L L L L L L L L L L L L M L L L L L v k 7 s@H C %.G O L L M L B A s@B D F R N L M L u <#E@E@$#$#$#F@x@5 E@.@e y t@H C X N L M M &.k t y s@B  .N L L M B 0#6 v z r@G Q N L R F I@P@P@M@M@L@L@N@p 0#b#b#I@l t z B S P L Q ` I@8@d p x H r.S L T ` S@T@U@U@W@W@K U@u E@+#+#Z@R@b n w @.W L S r.<#*#.#k 5 r F W L R W $#=#=#N@a l *.X M R W  #7#1#)#)#!#|#|#[ <#{#{#]#]#>#u@a -...S Q  .V@:#[#:#M@c y ..T N ..H@g#c#g#g#h#h#h#8@o a+h#h#h#h#h#R@0 C 4 a D E ;#h#h#h#=#c C +.M t@%.f#h#h#h#_# #H $.N ` F U@l#l#l#l#n#n#)#F .#n#n#n#n#n#n#5#r D S V D E@n#n#q#q#c#e C V U C e n#q#q#q#q#q#c#9 ,#n#q#q#q#q#n#n#(#x +.P C z 7#l#l#l#l#)#t G L E B C@g#g#g#g#|#o %.L %.&.S@[#[#[#[#[#[#U@| )#_#_#_#a+a+a+/#/#T@V L O L L L L L L L L L L L L L L L L R ]#.                               ",
+"                              ] 0 L L L L L L L L L L L L L L L L M M L L L L ..g D@k k j [ g | 1 e +.a e k %#A@k i h } f #.0 } %#E@E@E@$#$#$#H@k e .@.@.@F@E@3#%#i i &.4 i u@G@: : .@E@%#A@t@n A@E@&#S@J@H@,#E@3#o A 3#.@P@M@M@M@M@L@L@I@p M@b#b#b#b#L@K@J@0#d G F@H@Q@V@@#Q@b#K@J@k ` ,#&#R@U@U@W@W@K K @#A P@+#+#Z@4#Z@Y@R@8@x@@.F@@#+#'###'#*#4#U@b#@. #U@*#-#-#;#-#f#`@W@&.h X@C@)#)#!#!#|#2#|#h E@{#]#^#^#/#/#~#5#q.c u q.]#[#6#6#6#_#)#7#<#r@q.]#h#h#h#h#h#h#h#+#w ~#l#l#l#l#l#h#:#2#f#| .#|#c#l#l#l#l#6#~#f#G @#|#[#l#l#l#l#g#]#>#B I@{#[#n#n#n#n#n#n#c#p ,#n#n#n#n#q#q#q#:#^#d 6 ]#[#I q#q#q#q#c#/#F@v 2#[#I I I I I I I a#t@^#q#q#q#q#q#q#n#_#4#E f#a+l#n#n#n#n#l#a+}#C R@/#c#h#h#h#g#g#/#(#v K@{#_#c#6#6#[#[#[#]#j &#_#_#_#_#_#a+a+/#]#| L M O L L L L L L L L L L L L L L L L @.r#J                             ",
+"                            % M@L L L L L L L L L L L L L L L L L N L L L L P 7 D@D@A@A@A@A@%#%#E@,#z@u@u@ # # # #3#3#E@J@p 3#E@E@E@E@$#$#$#F@K@z@E@.@.@.@,#,#,#0#0#P@n <#: G@H@H@I@I@I@J@P@m u@S@S@&#&#&#&#x@x@M@8 < P@P@P@M@M@M@L@L@N@h d N@b#b#O@O@O@8@8@8@A@p Q@@#@#V@V@V@a#a#R@F@-.V@T@U@U@U@W@W@K K K@t@V@+#+#Z@4#4#4#`@X@@#B V@*#*#'#####9#9#f#+#@.N@=#=#-#;#;#q.5#>#}#B 0#7#1#)#!#!#|#2#2#|#h $#]#^#^#/#a+a+_#_#:#g r _#6#6#c#c#c#g#g#h#M@*./#h#h#l#l#l#l#l#l#}#z 7#n#n#n#n#n#n#n#n#{#| X@l#l#l#l#l#l#l#l#:#q S@l#l#l#l#l#l#n#n#h#3 f l#n#n#n#n#n#n#n#n#.@t 6#q#q#q#q#q#q#q#q#K C ]#I I I I I I I I 5#C -#I I I I I I I I /#-.V@I I I q#q#q#q#q#c#5 ,#n#n#n#n#n#n#n#n#h#u@d [#l#h#h#h#h#h#g#g#O@3 {#c#c#c#6#6#6#[#[#'#2 -#:#:#_#_#_#a+a+a+=#E L O N L L L L L L L L L L L L L L L L 9 /                             ",
+"                          . c#T L L L L L L L L L L L L L L L L N M L L L L H j D@D@A@A@A@A@%#%#K@8 j u@u@ # # #3#3#3#J@c h <#E@E@E@E@$#$#$#H@k c .@.@.@,#,#,#,#0#H@E@6 G@H@H@H@H@I@I@I@J@J@n I@S@S@&#&#&#x@x@x@P@q H@P@P@P@M@M@M@L@L@N@o ,#b#b#b#O@O@O@8@8@8@7 i @#@#@#V@V@V@a#a#R@} 4 T@T@U@U@U@W@K K K F@z@K +#Z@Z@4#4#`@`@X@P@z Y@*#'#'#####9#f#f#T@C R@=#-#-#;#q.q.5#>#C@s@K@1#)#)#!#|#2#2#~#2#h F@^#/#/#a+a+_#:#:#[#D@n _#c#c#c#g#g#h#h#h#U@H {#l#n#n#n#n#n#n#n#)#q 9#n#n#n#n#n#n#n#n#:#9 K@n#n#n#n#n#n#n#n#h#f g l#n#n#n#n#n#n#n#n#K@t@:#n#n#n#n#n#n#n#q#C@E (#q#q#q#q#q#q#q#I {#&.U@I I I I I I I I h#9 F@I I I I I I I I q#F@z@g#I I I I I I I q#+#x 2#q#q#q#n#n#n#n#n#(#q X@l#l#l#h#h#h#h#h#/#c L@c#c#c#c#c#6#6#6#_#: E@/#:#:#:#_#_#_#a+/#x@R L P M L L L L L L L L L L L L L L L L J@j#                          ",
+"                          B@#.L L L L L L L L L L L L L L L L M N L L L L W e D@D@A@A@A@A@%#%#,#u@a u@u@u@ # # #3#3#$#J@5 3#<#E@E@E@$#$#$#F@P@5 <#.@.@.@,#,#,#0#: P@7 u@G@H@H@H@H@I@I@J@x@} g S@S@S@&#&#&#x@x@K@<#6 K@P@P@P@M@M@M@L@L@&#s P@b#b#b#O@O@O@8@8@b#r S@@#@#@#V@V@V@a#a#V@9 <#T@T@U@U@W@W@K K K f | +#+#Z@Z@4#4#`@X@X@,#7 X@*#'#####9#9#f#C@O@o 4#-#-#;#q.q.5#>#>###l V@)#)#!#|#2#2#~#{#|#g ,#/#/#a+_#_#:#:#[#6#J@} _#c#g#g#h#h#h#l#l#f#z@)#n#n#n#n#n#n#q#q#/#4 K q#q#q#q#q#q#q#q#h#[ A@n#n#n#n#n#n#n#n#n#L@l [#n#n#n#n#n#n#n#n#-#*.(#n#n#n#q#q#q#q#q#a+H Q@q#q#q#q#I I I I n#d f n#I I I I I I I I 8@-._#I I I I I I I I >#*.}#I I I I I I I I [#m x@q#q#q#q#q#n#n#n#h#F@e [#l#l#l#l#h#h#h#h#Z@7 )#g#g#c#c#c#6#6#6#7#c `@[#:#:#:#_#_#_#a+~#5 L N Q L L L L L L L L L L L L L L L L R ]#9@                        ",
+"                        / 9 L L L L L L L L L L L L L L L L L O L L L L L p k D@D@A@A@A@A@%#u@x@z@D@u@u@ # # #3#3#3#&#2 i <#E@E@E@E@$#$#$#H@A@c .@.@.@,#,#0#: : H@H@9 : G@H@H@H@I@I@I@J@K@n 0#S@S@&#&#&#&#x@x@M@7 u@P@P@P@M@M@M@M@L@N@i a N@b#b#b#O@O@O@8@8@I@n O@@#@#V@V@V@a#a#R@O@r P@T@U@U@U@W@W@K K W@4 $#+#+#Z@4#4#4#`@X@X@i } *#*#'#####9#f#f#C@&#4 ##-#-#;#q.5#>#>#(#*#z@Y@)#!#|#|#2#~#{#{#|#} H@/#a+_#_#:#[#[#6#c#M@} _#g#h#h#h#l#l#n#n#;#9 (#q#q#q#q#I I I I 6#c L@I I I I I I q#q#q#,#b h#q#q#q#q#q#q#q#q#*#z !#n#n#n#n#n#n#n#n#a+v R@q#q#q#q#q#q#q#q#n#| c n#I I I I I I I I K H /#I I I I s#s#s#s#{#H `@s#s#s#s#s#s#s#s#n#0 D@q#I I I I I I I I 8@r /#I q#q#q#q#q#q#n#7#r X@n#n#l#l#l#l#h#h#:#g I@c#g#g#c#c#c#c#6#[#8@h ~#[#[#:#:#:#_#_#_#*#+.L P P L L L L L L L L L L L L L L L L +.t#J                       ",
+"                      j#H@L L L L L L L L L L L L L L L L L O M L L L L F [ D@D@D@A@A@A@%#%#I@[ e u@u@u@ # # #3#3#.@,#4 <#<#E@E@E@E@$#$#F@P@z@<#.@,#,#0#0#0#: : K@a k G@H@H@H@H@I@I@I@&#<#7 S@S@S@&#&#&#x@x@x@x@q S@P@P@P@M@M@M@L@L@N@m E@N@b#b#O@O@O@O@8@Q@g c Q@@#@#V@V@V@a#a#R@J@q @#T@U@U@U@W@W@K K V@q x@+#Z@Z@4#4#`@`@X@`@2  #*#'#'###9#9#f#C@}#.@0 f#-#;#q.q.5#>#(#7#4#m Z@!#!#|#2#~#{#{#]#2#| &#a+_#_#:#[#[#6#c#c#b#f :#h#l#l#n#n#n#n#q#)#9 =#I I I I I I I I l#[ $#I I I I I I I I I V@l [#I I q#q#q#q#q#q#2#w *#q#q#q#q#q#q#q#q#h#e D@n#q#q#q#q#q#q#q#I 8@&.^#I I I I I I I I {#&.+#s#s#s#s#s#s#s#s#q#e | q#s#s#s#s#s#s#s#s#+#H ~#s#s#s#s#I I I I ^#v V@I I I q#q#q#q#q#l#3#e 6#n#n#n#l#l#l#l#h#*#5 q.g#g#g#g#c#c#c#6#]#[ N@[#[#[#:#:#:#_#_#a+E@L L R N L L L L L L L L L L L L L L L L l u#                      ",
+"                    . ~#Q L L L L L L L L L L L L L L L L N O L L L L R a D@D@D@A@A@A@A@%#3#J@9 %#u@u@ # # # #3#3#K@4 k <#<#E@E@E@$#$#$#H@A@1 ,#,#,#0#0#0#: : G@&#n 0#G@H@H@H@H@I@I@I@M@5 3#S@S@S@&#&#&#x@x@P@j 3 K@P@P@P@M@M@M@L@L@S@t K@N@b#b#O@O@O@8@8@O@n F@@#@#@#V@V@V@a#a#R@D@0 R@T@U@U@U@W@K K K N@q @#+#Z@Z@4#4#`@X@X@4#5 J@*#'#####9#f#f#C@}#A@e }#-#;#q.5#>#>#(#7#+#z@##!#|#2#~#~#{#]#^#2#e P@_#_#:#[#[#6#c#c#g#O@} :#l#n#n#n#q#q#q#I ~#4 *#I I s#s#s#s#s#s#I E@< I s#s#s#s#s#I I I '#v |#I I I I I I I I [#4 S@q#q#q#q#q#q#q#q#q#I@a c#q#q#q#q#I I I I !#H '#I I I I I I I I q#d g I s#s#s#s#s#s#s#s#Z@B ~#s#s#s#s#s#s#s#s#[#y K@s#s#s#s#s#s#s#I I I@z@[#I I I I q#q#q#q#>#s .#n#n#n#n#l#l#l#l#6#%# #6#h#g#g#g#c#c#c#c#X@1 (#[#[#[#:#:#:#_#_#)#u L N S L L L L L L L L L L L L L L L L L H@j#                    ",
+"                    v#@.L L L L L L L L L L L L L L L L M P L L L L L y k D@D@D@A@A@A@A@%#&#2 [ u@u@u@ # # #3#3#,#E@3 <#<#E@E@E@E@$#$#F@M@z@E@,#,#,#0#0#0#: : &#} f G@G@H@H@H@I@I@I@J@I@n I@S@S@S@&#&#&#x@x@L@l $#K@P@P@P@M@M@M@L@N@A@0 N@N@b#b#O@O@O@8@8@P@s P@Q@@#@#V@V@V@a#a#a#7 u@T@T@U@U@W@W@K K K ,#l W@+#Z@4#4#4#`@X@X@W@o b#'#'#####9#f#f#C@C@g j -#;#q.q.5#>#(#7#7#a#9 f#|#2#2#~#{#]#^#^#2#e L@:#:#[#6#6#c#g#g#h#8@e _#n#n#q#q#I I I I a+a +#s#w#w#w#w#w#w#w#w#S@e n#w#w#w#s#s#s#s#s#1#v f#I I I I I I I I n#k [ n#I I I I I I q#I *#n )#I I I I I I I I g#b K@I I I I I s#s#s#s#R@t@_#s#s#s#s#s#s#s#s#:#s@b#w#w#w#w#w#w#s#s#s#H@u c#s#s#s#s#s#s#s#s#~#x Z@I I I I I I q#q#l#3#e c#n#n#n#n#n#l#l#l#;#5 C@h#h#g#g#g#g#c#c#_#3#,#_#[#[#[#[#:#:#_#_#W@V L Q R L L L L L L L L L L L L L L L L R 2#9@                  ",
+"                  x#o L L L L L L L L L L L L L L L L L P M L L L L ` f D@D@D@A@A@A@A@A@F@F@7 u@u@u@u@ # # #3#3#K@4 A@<#<#E@E@E@$#F@F@J@A@b ,#,#,#,#0#0#0#: : K@m ,#G@G@H@H@H@I@I@I@K@d h S@S@S@&#&#&#&#x@K@J@q &#K@P@P@M@M@M@M@L@O@m <#N@N@b#b#O@O@O@8@Q@.@m 8@Q@@#@#V@V@V@a#a#T@q &#T@T@U@U@W@W@K K +#k d +#+#Z@4#4#`@`@X@X@R@p U@'#####9#f#f#C@}#C@d E@;#;#q.5#>#>#(#7#1#R@7 ;#|#2#~#{#]#]#^#/#~#} L@[#[#6#6#c#g#g#h#l#@#c a+q#q#I I I I s#s#[#c V@w#w#w#w#w#w#w#w#y#Q@3 c#w#w#w#w#w#w#w#w#_#9 R@s#s#s#s#I I I I I &#5 c#I I I I I I I I ]#9 +#I I I I I I I I I x@%#h#I I s#s#s#s#s#s#^#4 ;#s#s#s#s#s#s#w#w#s#$#k I w#w#w#w#w#w#w#w#|#z (#s#s#s#s#s#s#s#s#I 3#i q#I I I I I I q#q#>#r 7#q#n#n#n#n#n#l#l#g#$#A@h#h#h#g#g#g#c#c#c#;#b >#6#[#[#[#[#:#:#_#/#g L L T O L L L L L L L L L L L L L L L L +.t#J                 ",
+"                > F@L L L L L L L L L L L L L L L L L O P L L L L L 7 <#E@E@E@E@$#$#F@F@c#9 <#,#,#0#0#0#: : : *#8@c H@H@&#@#V@V@V@a#a#c#4 8@R@R@R@T@T@T@U@U@5#M@k Y@+#+#+#+#+#Z@Z@4#h#z@Y@.#*#*#*#*#'#'#'#|#K@3#9#9#f#f#f#C@C@}#}#g#z@'#-#-#-#;#;#q.q.5#/#G@: >#(#7#7#7#1#1#)#)#6#l (#{#]#]#]#/#/#/#a+n#0#&#[#[#[#6#c#c#g#h#l#^#0 [#q#I s#w#w#p.p.H+z#A@U@]@A#B#C#w@0+D#E#F#>#2 A#G#H#v#I#J#t#r#G+I#k f#K#L#p#M#{@k#N#O#v@{#g M#P#P#P#P#Q#Q#_ _ R#E@~#S#u#/ / / / / =.=.e#e P#=.=.=.=.=.=.=.=.x#3#-#=./ / / / / u#u#u#T#p {@x#x#/ / u#u#u#x#_  #*#x#S#S#S#_ _ Q#P#R#y#[ G+v@p@O#U#V#W#N#N#X#K@;#{@M#M#X#p#p#p#L#L#I F@Y#K#K#K#Z#`#`#`#B@r#0#2#G+G+G+r#t#t#t#J#J#_#0#F#v#v#v#H#G#G#G#G# $G@I  $.$.$F#F#+$E#E#E#_#N@F#0+w@C#C#B#B#A#A#e#&#0+A#T#T#@$z#z#H+H+p.7#Y L N V M L L L L L L L L L L L L L L L M l u#                ",
+"              + )#L L L L L L L L L L L L L L L L L N R L L L L L L [ O@O@8@8@Q@Q@Q@@#V@e#t 8@R@R@T@T@U@U@W@W@1#&#u@+#+#f#y#p.p.H+z#H+D#6 n#z#z#z#z#z#@$T#T#+$P@W@#$#$e#e#e#e#e#]@]@D#4 p.B#C#C#C#w@w@0+0+H#K@K E#E#+$+$F#F#.$.$ $0+3 B#G#G#H#v#v#I#q@q@i#K@X@r#r#G+G+i#$$$$B@`#0+e v#L#p#p#X#M#M#{@k#k#J@=#W#V#U#O#O#p@v@%$y@C#g &$Q#_ S#x#u#/ =.^ S#F@^#m#*$=$~ ! ' 8#, - e#[ ( & o## @ 9@d#J   & E@@$                  q@<#d#                  &#q@                  {@E@                    K@G#                  &$g                     : e#                  i#j >           J d#. j#&#p.o#% & j#= > - ; , w@O@S#~ ~ *$*$( ( ] ] _ a#@$/ u#x#S#_ Q#P#R#R#p.*#k#p@O#U#V#W#N#N#k#K#R@F#X#p#L#K#Z#`#`#$$$$g#|#`#t#t#q@q@I#v#H#G#F#Y@K# $F#+$E#E#D#0+w@C#}#L L L R T L L L L L L L L L L L L L L L L M ,#>               ",
+"            J F# .L L L L L L L L L L L L L L L L L R N L L L L L M z@O@O@8@Q@Q@Q@@#@#V@[#2 S@R@R@T@U@U@U@W@K ##;#d +#+#X@I H+H+z#z#z#C#} ]#z#@$@$@$@$T#T#T#B#q.I@#$#$e#e#e#e#]@]@A#w@[ c#B#C#C#C#w@w@0+0++$##K@E#E#+$+$F#F#.$.$ $0+| H+G#G#H#v#v#I#q@q@t#W@b#r#r#G+G+i#$$$$B@`#C#a E#L#p#p#X#M#M#{@k#M#&#K W#V#V#O#O#p@v@%$y@C#c M#Q#_ S#x#u#/ =.^ _ 3#~#m#*$*$~ ! ) 8#, ; T#[ ( & o#$ # + . J   * <#@$                  I#E@.                   H@q@                  i#0#                    .@G+                  r#E@                  J [ G+                  z#3##           J . 9@! } .$o#% & j#j#> - ; , ~#&#{ ! ~ =$*$m#( ] ] U#[ +$/ u#x#S#_ _ P#R#R#-#'#U#p@O#U#V#W#N#&$k#v#$#q@X#p#L#K#Z#`#`#$$$$K h#$$t#t#q@q@I#v#H#G#z#b#B@F#F#+$E#D#0+0+w@C#: L L L M V Q L L L L L L L L L L L L L L L L R 2#9@            ",
+"            S#u L L L L L L L L L L L L L L L L L Q P L L L L L L V z u@3#3#<#E@E@E@$#$#8@6 | F@.@,#.@F@F@F@.@,#,#t ,#0#: +###########.#p P@.#*#*#*#*#'#'#'###0#a *#######9#9#9#9#f###m Q@f#C@}#}#}#}#}#=#-#,#d f#f#f#C@C@}#}#}#=#.#q T@-#;#;#;#q.q.q.5#5#[ h >#(#7#7#1#1#)#)#)#X@r 9#|#2#~#~#~#|#!#!#!#g u@~#~#~#{#]#]#^#^#/#4#l 1#_#:#[#[#6#c#c#g#[#c N@q#q#I h#h#h#l#n#q#+#2 c#y#p.H+z#z#w#y#p.q#g U@#$e#]@B#C#w@0+E#+$##g C#G#v#v#I#I#q@q@q@F#g -#t#t#t#t#t#t#t#r#r#;#[ q@r#r#v#v#v#H#H#H#E#2 !#G#G#G#G#Y#Y# $q@ $Z@h +$F#F#F#F#+$E#G#G+I m C@e##$T#z#H+p.y#`#D#0#0 ^#_#a+/#/#]#]#6#V#1#v V@|#)#)#1#7#7#(#E#M#k 2 ;#q.;#-#-#-#=#7#M#A#x 8@f#9#9#####'#'#^#k#K@3 V@V@V@V@Q@Q@Q@8@:#]@t H@b#b#N@N@N@L@L@M@h#H@2 P@K@x@x@&#&#&#: J@1#q 0#,#,#,#.@F@F@F@$#u@%.L L L L O W N L L L L L L L L L L L L L L L L E r#J           ",
+"          > F@M L L L L L L L L L L L L L L L L O T L L L L L L O $.C C C C C C C C C C C C C C C C C C C C C C &.&.&.C &.&.C C C C &.B r@t@A z z z z z z z z z y z z z z z z z z z z z y z z z z z z z z z z y y z z z z z z z z y x x y y y y y y y y y x x x x x x x x x x x x x w x x x x x x v v v v v v v v u u u u u t t t t s s s s r r r q q q p p p o o n n n m m l l l z@z@9 9 9 5 5 5 4 4 4 6 6 6 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 6 6 6 4 4 4 5 5 5 9 9 z@z@l l l m m n n n o o p p q .@p r r r s s t t t t 3 Z@v v v v v v w w w w @#W@x x x x x y y y y s ]@H@z z z z z z z z z .@i#[ A A A A A A A A z g#v#6 t@t@t@t@t@t@t@t@z@F#^#t@-.-.-.-.-.-.-.-.1 .$ #s@s@s@s@s@s@s@s@s@A@g#u r@r@r@r@r@r@r@r@H J@M@*.H H H H H H H H C P L L L L L T V L L L L L L L L L L L L L L L L Y g =.          ",
+"        9@2#Q L L L L L L L L L L L L L L L L N V N L L L L L L ` D E D D D D D D C C C C C C C C C C C C C C C C C C C C &.&.B B s@t@z z z z z z z z z z z z z z z z z z z y z z z z z z z z z z z y z z z z z z z z z z z y z z z z y y y y y y x y y y y y y y y y y y x y y x x x x x x x x w v x w w w w w w v v v t u v u t t t t s s r r p q q q p p p o o n n l z@m l l l z@z@9 9 9 5 7 7 4 6 7 7 7 7 7 8 3 3 2 3 3 3 3 3 3 3 3 3 3 2 c 3 3 3 3 8 8 7 7 7 7 d 0 4 4 4 4 5 9 9 9 9 7 d 5 m l l l m m n n n P@f o p p p q q r r r m 2#3 s t t t t t t t t 3#6#o v v t t t t t t u ~#{#r r r r r r r r s 3 G#C@r s s t t t t t t P@p#R@t t t t t t t t v f#t#g u u u u u u u u v {#g#r v s s s s s s t o h#b#t t t t t t t t t 9 _#1 u u u v v v v v v D L L L L L M Z W L L L L L L L L L L L L L L L R r K@j#        ",
+"        v#+.L L L L L L L L L L L L L L L L N G X L L L L L L E g [ [ < < < < j j i i i i k k k k k k %#A@D@D@A@A@A@A@A@%# #E@: 0#,#,#0#0#0#0#: G@H@J@S@I@J@J@J@J@J@J@S@S@S@M@&#&#&#&#&#&#K@K@K@K@P@O@M@P@P@M@M@M@M@M@L@L@O@@#b#N@N@O@Q@Q@Q@Q@@#V@U@T@V@V@a#a#R@R@R@R@R@U@`@K U@W@W@W@K K K Y@+#`@##Z@Z@Z@4#4#`@`@X@X@X@=#}#*#'#}#-#;#;#q.q.5#(#2#7#7#7#1#)#)#|#|#2#~#a+[#]#]#^#/#a+_#_#:#[#[#s#I n#q#I I s#w#w#y#y#z#B#z#z#z#z#@$@$T#T#T##$w@+$e#e#e#e#e#e#e#]@]@]@Y#D#e#e#e#e#e#e#e#e#e#B#v#0+e#A#B#B#A#A#A#A#A#.$I#C#A#A#A#A#A#A#A#A#A#t#G#A#A#A#A#A#A#A#A#A#0+Z#+$A#B#w@0+0+0+0+0+0+I#L#+$F#F#F#F#F#F#F#F#F#`#Z#F#F#F#F#F#F#F#F#F# $M#G+F#F#F#F#F#F#F#F#E#v#M#H#E#E#E#E#E#E#E#E#D#q@Z#E#D#+$+$E#E#E#E#E#E#J#J#0+0+0+0+0+w@w@C#C#w@J#E#B#B#A#A#A#]@]@e#e#)#Z L L L L L T C ..O L L L L M M N N N P P P O M  .r./#.       ",
+"      ' 9 L L L L L L L L L L L L L L L L L ..H P L L L L L S i K@K@K@P@P@P@M@M@M@L@L@L@N@N@N@b#b#O@O@O@O@8@8@Q@Q@Q@V@T@Y@+#Z@4#4#4#4#`@`@`@X@X@X@X@.#.#.#*#*#*#'#'#'#########9#9#f#f#f#f#C@C@}#}#}#=#=#=#-#-#-#;#;#q.q.q.5#5#>#>#>#(#(#(#7#7#1#1#)#)#)#!#!#|#|#|#2#2#~#~#{#{#]#]#]#^#/#/#/#a+_#_#:#:#[#[#6#c#c#c#g#h#h#l#n#n#q#I I s#w#y#p.p.H+z#z#@$T##$e#]@A#A#B#C#w@0+D#E#+$F#F#.$ $Y#G#H#v#I#I#q@J#t#r#r#G+i#$$$$B@`#`#Z#Z#K#K#L#L#p#p#p#X#X#M#M#M#M#M#M#{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#M#X#X#X#X#X#p#p#p#p#L#L#L#L#K#K#K#K#Z#Z#Z#`#`#`#B@B@B@$$$$$$i#i#G+G+G+r#r#r#t#t#v#J@L L L L L L ..z x W T R S T U V V V U T T R N L L t '       ",
+"      ~ t@U N L L L L L L L L L L L L L L S w E L L L L L L q &#K@K@K@P@P@M@M@M@M@L@L@N@N@N@N@b#b#O@O@O@8@8@Q@V@T@K +#Z@Z@Z@4#4#4#4#`@`@`@`@X@X@X@.#.#.#*#*#*#*#'#'#'#######9#9#9#f#f#f#C@C@C@}#}#}#=#=#-#-#-#-#;#;#q.q.q.5#5#>#>#>#(#(#7#7#7#1#1#)#)#)#!#!#|#|#|#2#2#~#~#{#{#]#]#^#^#/#/#/#a+_#_#:#:#[#[#6#c#c#g#g#h#h#l#n#n#q#I s#w#w#y#p.p.H+z#@$T#T##$e#]@A#B#C#C#0+0+D#E#+$F#.$ $Y#G#G#v#v#I#q@J#t#t#r#G+i#$$$$B@`#`#Z#K#K#L#L#p#p#p#X#X#M#M#M#M#{@{@{@{@{@k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#{@{@{@{@{@{@{@{@{@{@{@{@{@{@k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#M#X#X#X#X#X#p#p#p#p#L#L#L#L#K#K#K#K#Z#Z#Z#`#`#`#B@B@B@$$$$$$i#i#G+G+G+r#r#r#t#t#]@r L L L L L r.&.[ 4 F ..Z Z Y X r.U R P N M L L L 3 &       ",
+"      # j t@t@@.U Q N M L L L L L L L L L r@0 V L L L L L ..,#K@K@K@P@P@P@M@M@M@L@L@L@N@N@N@b#b#b#O@O@8@@#R@K +#+#+#Z@Z@Z@Z@4#4#4#4#`@`@`@X@X@X@X@.#.#.#*#*#*#*#'#'#########9#9#9#f#f#f#C@C@C@}#}#}#=#=#-#-#-#;#;#;#q.q.q.5#5#>#>#>#(#(#7#7#7#1#1#)#)#)#!#!#|#|#|#2#~#~#~#{#{#]#]#^#^#/#/#a+a+_#_#:#:#[#[#6#c#c#g#h#h#l#n#n#q#I I s#w#w#y#p.H+z#z#@$T##$e#e#A#A#B#C#w@0+D#E#+$F#F# $ $Y#G#H#v#I#q@J#t#t#r#G+i#$$$$B@`#`#Z#K#K#L#L#p#p#X#X#M#M#M#M#{@{@{@k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#X#X#X#X#X#p#p#p#p#L#L#L#L#K#K#K#K#Z#Z#Z#`#`#`#B@B@B@$$$$$$i#i#G+G+G+r#r#t#t#t#>#W L L L L U H n A@s@+.V S P N M L L L L L L L L 4#J       ",
+"      J _#U @.Y V U T S Q P O M M L L L  .%#3 N L L L L N c K@K@K@K@P@P@P@M@M@M@L@L@L@N@N@N@b#b#O@Q@R@W@Y@+#+#+#+#Z@Z@Z@Z@4#4#4#4#`@`@`@`@X@X@X@.#.#.#*#*#*#*#'#'#'#########9#9#f#f#f#f#C@C@}#}#}#}#=#=#-#-#-#;#;#;#q.q.q.5#5#>#>#>#(#(#7#7#7#1#1#)#)#)#!#!#|#|#|#2#~#~#~#{#{#]#]#^#^#/#/#a+a+_#_#:#[#[#[#6#c#c#g#h#h#l#n#n#q#I I s#w#w#y#p.H+z#z#T#T##$e#]@A#A#C#C#w@0+D#E#+$F#.$ $Y#G#H#v#v#q@q@J#t#r#G+G+i#$$B@`#`#Z#K#K#L#L#p#p#X#X#M#M#{@{@{@k#k#k#k#k#k#k#k#&$&$&$&$&$&$&$&$k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#X#X#X#X#X#p#p#p#p#L#L#L#L#K#K#K#Z#Z#Z#Z#`#`#`#B@B@B@$$$$i#i#i#G+G+G+r#r#t#t#G#k L L L L N x D@u P L L L L L L L L L L L L L Q J#        ",
+"        O#` P O M L L L L L M M M L L L ..G@t O L L L L t@I@K@K@K@P@P@P@M@M@M@M@L@L@N@N@N@b#8@a#U@Y@Y@Y@+#+#+#+#Z@Z@Z@Z@4#4#4#4#4#`@`@`@X@X@X@X@.#.#.#*#*#*#*#'#'#'#######9#9#9#f#f#f#f#C@C@}#}#}#=#=#=#-#-#-#;#;#q.q.q.q.5#5#>#>#>#(#(#7#7#7#1#1#)#)#)#!#!#|#|#|#2#~#~#~#{#{#]#]#^#^#/#/#a+a+_#_#:#[#[#6#6#c#c#g#h#h#l#n#n#q#I I s#w#y#p.p.H+z#@$T#T#e#e#]@A#B#C#w@0+D#E#E#F#F# $ $Y#G#H#v#I#q@J#t#r#G+G+i#$$B@`#`#Z#K#K#L#p#p#X#X#M#M#M#{@{@k#k#k#k#k#&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#M#M#M#M#M#M#M#M#{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#X#X#X#X#p#p#p#p#p#L#L#L#K#K#K#K#Z#Z#Z#`#`#`#B@B@B@$$$$$$i#i#i#G+G+G+r#r#t#t#s#C L L L N B S@H L L L L L L L L L L L L L L y ~         ",
+"        > z@N N L L L L L L L L L L L L M s@H T L L L U u@K@K@K@K@P@P@P@M@M@M@L@L@L@N@O@V@U@K Y@Y@Y@Y@+#+#+#+#+#Z@Z@Z@Z@4#4#4#4#`@`@`@`@X@X@X@.#.#.#.#*#*#*#'#'#'#########9#9#9#f#f#f#C@C@C@}#}#}#=#=#=#-#-#-#;#;#q.q.q.q.5#5#>#>#>#(#(#7#7#7#1#1#)#)#)#!#!#|#|#2#2#~#~#~#{#{#]#]#^#^#/#/#a+a+_#_#:#[#[#6#6#c#c#g#h#h#l#n#n#q#I s#w#w#y#p.p.z#z#@$T##$e#e#A#A#B#C#w@0+D#E#+$F#.$ $Y#G#H#v#v#q@q@J#t#r#G+i#$$$$B@`#Z#K#K#L#p#p#X#X#M#M#{@{@k#k#k#k#&$&$&$&$N#N#N#N#N#N#N#N#N#N#N#N#N#&$&$&$&$&$&$&$k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#M#M#{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@M#M#M#M#M#M#X#X#X#X#X#p#p#p#p#p#L#L#L#K#K#K#K#Z#Z#Z#`#`#`#B@B@B@$$$$$$i#i#G+G+G+r#r#r#t#q@4#S L L P &.n P L L L L L L L L L L L L L L 3#+         ",
+"        d#+#L M L L L L L L L L L L L L L ..t@W L L L l &#x@K@K@K@P@P@P@M@M@M@L@b#@#U@K K Y@Y@Y@Y@+#+#+#+#+#+#Z@Z@Z@4#4#4#4#4#`@`@`@X@X@X@X@X@.#.#.#*#*#*#*#'#'#'#######9#9#9#9#f#f#f#C@C@C@}#}#}#=#=#=#-#-#-#;#;#q.q.q.5#5#5#>#>#>#(#(#7#7#7#1#1#)#)#)#!#!#|#|#2#2#~#~#~#{#]#]#]#^#^#/#/#a+_#_#:#:#[#[#6#c#c#g#g#h#l#l#n#q#I I s#w#y#p.p.H+z#@$T#T#e#e#A#A#B#C#w@0+D#E#+$F#.$ $Y#G#H#v#I#q@J#t#r#G+i#$$$$`#`#Z#K#K#p#p#X#M#M#M#{@k#k#&$&$&$N#N#N#W#W#W#W#W#W#W#V#V#V#V#V#V#W#W#W#W#W#N#N#N#N#N#N#N#N#N#&$k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@M#M#M#M#M#M#M#X#X#X#X#p#p#p#p#p#L#L#L#K#K#K#K#Z#Z#Z#`#`#`#`#B@B@$$$$$$i#i#i#G+G+G+r#r#t#t#F#a L L T z A L L L L L L L L L L L L L L L l#          ",
+"          v#O L L L L L L L L L L L L L L U t@..M L $.,#&#x@x@K@K@K@K@K@P@N@Q@T@Y@+#+#+#+#+#+#+#+#+#+#Z@Z@4#4#4#4#4#4#4#`@`@`@X@X@X@X@X@X@.#.#.#*#*#*#*#'#'#'#########9#9#9#f#f#f#f#C@C@C@}#}#}#=#=#=#-#-#-#;#;#;#q.q.q.5#5#>#>#>#(#(#(#7#7#7#1#1#)#)#!#!#|#|#|#2#2#~#~#~#{#]#]#]#^#/#/#a+a+_#_#:#[#[#6#6#c#g#g#h#l#n#n#q#I s#s#w#y#p.H+z#z#T#T#e#e#A#A#C#C#0+D#E#+$F#.$ $Y#G#v#v#q@J#t#r#G+i#$$B@`#Z#K#L#p#X#M#{@k#k#&$N#N#W#V#V#U#O#O#O#O#p@v@v@v@v@v@v@v@v@v@v@v@v@v@v@v@v@p@p@p@O#O#O#O#U#U#U#V#V#V#V#W#W#N#N#N#N#N#N#N#&$k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@M#M#M#M#M#M#M#M#M#M#X#X#X#p#p#p#p#p#p#p#L#K#K#K#K#K#K#Z#Z#`#`#`#`#`#B@$$$$$$$$$$i#G+G+G+G+r#t#t#t#t#t#/#..N r.s G L L L L L L L L L L L L L L @.R#          ",
+"          ( s@L L L L L L L L L L L L L L N *.C C +.2 J@J@J@J@J@S@S@&#M@U@Z@4#4#4#4#4#4#4#4#4#4#4#4#4#4#4#`@`@`@X@X@X@X@X@X@X@X@.#.#.#.#.#.#*#*#*#*#*#'#'#'#############9#9#f#f#f#f#f#f#f#}#}#}#}#}#}#=#-#-#-#-#-#-#;#q.q.q.q.5#5#5#>#>#>#(#(#7#7#7#1#1#1#)#)#!#!#|#|#|#2#2#~#~#{#{#]#]#^#^#/#a+a+_#_#:#[#[#6#c#c#g#h#h#n#n#q#I s#w#y#p.p.H+z#T#T#e#e#A#A#C#w@0+D#E#+$F# $Y#G#H#v#I#q@t#t#G+i#$$B@`#Z#K#L#p#p#X#M#{@k#k#&$N#N#W#V#V#U#U#U#O#O#O#O#p@p@p@p@p@p@p@p@p@O#O#O#O#O#O#O#O#U#U#U#V#V#V#V#V#W#W#W#N#N#N#N#N#N#N#N#N#N#&$&$&$&$N#&$&$&$&$&$N#N#N#N#N#N#N#N#N#N#N#N#N#W#W#W#W#W#W#V#V#V#V#V#V#V#V#V#V#V#V#V#V#V#V#V#W#W#W#W#W#W#N#N#N#N#N#N#&$&$&$k#k#k#k#{@{@{@M#M#M#M#X#p#p#p#p#L#L#K#K#K#K#Z#`#`#`#B@B@B@$$$$$$i#G+G+G+G+G+r#t#t#t#J#J#q@q@q@I#I#v#v#v#H#H#G#F#F@F @.r V L L L L L L L L L L L L L L 7 *           ",
+"          + ,#L L L L L L L L L L L L L L L &.a [ s@ #.@.@.@,#H@J@J@S@N@*#f#f#f#f#f#f#f#f#f#f#f#f#f#f#f#f#f#f#f#f#f#f#C@C@C@C@C@C@C@}#}#}#}#}#}#=#-#-#-#-#-#-#;#;#;#q.q.q.q.5#>#>#>#>#>#(#(#(#(#7#7#7#7#1#)#)#)#)#)#!#!#|#|#|#2#2#2#~#~#~#{#{#]#]#^#]#/#/#/#/#a+a+_#:#[#[#6#6#c#c#g#g#h#h#l#l#n#n#q#I I I w#w#w#y#p.p.H+z#z#@$T#T##$e#]@]@A#B#w@0+0+D#E#+$F#F#.$ $Y#G#H#v#v#I#q@J#t#t#r#G+i#$$$$`#`#Z#K#L#p#M#{@k#k#&$N#N#W#V#U#U#O#O#v@v@%$y@P#Q#Q#_ _ S#x#x#u#/ / =.^ ^ -$] ] { ( m#m#*$=$~ ~ ~ ~ ! ! ) ) ) ) ) ' 8#8#, , ; ; ; - - > > > > = j#j#j#j#* * & & & & % % o#o#o#o#o#$ $ $ $ # # # # # # # # # # # # # # # $ $ o#o#o#o#% % & & & * * j#j#j#= > > > - ; ; ; ; ; , 8#8#8#' ) ! ~ *$m#( ( { ] -$^ =./ u#x#S#_ Q#P#R#y@y@%$v@p@O#O#U#V#W#W#N#&$&$k#{@M#M#X#X#p#A#i 8 p O L L L L L L L L L L L L L L 4#J           ",
+"            q#L L L L L L L L L L L L L L L T z +.s@%#u@u@u@ #E@.@I@M@8@K 9#7#^#:#6#c#c#c#c#c#c#c#c#c#c#c#c#c#c#c#c#g#g#g#h#h#h#h#h#h#h#l#l#n#n#n#n#n#q#I I I I I s#w#w#w#w#y#p.p.p.p.H+H+z#z#z#@$T#T#T##$#$e#e#]@]@A#A#B#B#C#C#w@w@0+0+D#D#E#E#+$F#F#.$.$ $Y#Y#G#G#H#v#v#I#q@q@J#t#t#r#G+G+i#$$$$B@`#Z#Z#K#L#p#p#X#M#M#k#k#&$N#N#V#V#U#O#O#v@v@%$y@R#P#P#_ _ S#x#u#/ =.^ ^ ] ] ( ( m#*$=$~ ! ) ' 8#, ; - > = j#* & % o#$ # @ + 9@. . d#d#J J                                                                                                                                                                                                                                                               J J d#. + + # o#% & j#= > - ; 8#' ) ! ~ =$*$m#( { ] ] ^ ^ / N#u@u ..L L L L L L L L L L L L L L Q J#            ",
+"            %$+.L L L L L L L L L L L L L L L L L $.z@a } [ < < i i i j A@3#0#P@U@##1#_#l#s#w#y#y#y#y#y#y#y#y#y#p.p.p.p.p.p.p.H+H+H+H+z#z#z#z#@$@$@$T#T#T##$#$#$e#e#e#]@]@A#A#A#B#B#C#C#C#w@0+0+0+D#D#E#E#+$+$F#F#.$.$ $Y#Y#G#G#H#H#v#v#I#q@q@J#t#t#r#G+G+i#$$$$B@`#`#Z#K#K#L#p#p#X#M#M#k#k#&$N#N#W#V#U#O#O#p@v@%$y@y@R#P#Q#_ _ x#x#u#/ =.^ -$] { ( ( m#*$=$~ ! ) ' 8#, ; - > = j#* & % o#$ # @ + 9@. . d#J J                                                                                                                                                                                                                                                                                                           J . 9@+ # $ o#& & j#= > - ; 8#8#) ) ~ ~ =$m#y@F#)#o L L L L L L L L L L L L L L L L y ~             ",
+"            & d L L L L L L L L L L L L L L L L L L L O W @.D A s n 4 3 2 c e | } g k <#&#R@=#]#h#H+T#e#e#e#e#e#e#e#]@]@]@]@]@A#A#A#A#B#B#B#B#C#B#B#C#C#C#C#w@w@0+0+0+D#D#E#E#E#+$+$F#F#.$.$ $ $Y#Y#G#G#H#H#v#v#I#q@q@J#J#t#r#r#G+G+i#$$$$B@`#`#Z#K#K#L#p#p#X#M#{@{@k#&$N#N#W#V#U#O#O#p@v@v@y@y@R#P#Q#_ _ x#x#u#/ =.^ ^ ] ] ( ( m#*$=$~ ! ) ' 8#, ; - > = j#* & % o#$ # @ + 9@. d#J J                                                                                                                                                                                                                                                                                                                                 J . 9@+ @ # $ o#& & j#= > - 8#! =$*$m#( ] v@e#+#| G L L L L L L L L L L L L L L L L L 3#+             ",
+"            J -#L L L L L L L L L L L L L L L L L L L L L L L L L L L R V Z +.D z p 4 b } [ D@E@H@Q@.#|#I C#G#t#G+G+G+G+G+G+r#t#J#q@I#H#G# $F#D#w@C#C#C#C#w@w@0+0+0+0+D#E#E#E#E#+$F#F#F#.$ $ $ $Y#G#G#G#H#v#v#v#I#q@q@J#J#t#t#r#G+G+i#$$$$B@`#`#Z#K#K#L#p#p#X#M#M#{@k#&$N#N#W#V#V#U#O#p@v@v@%$y@R#P#P#_ _ S#x#u#/ / =.^ -$] { ( m#*$=$~ ! ! ) ' 8#, ; - > = j#* & % o#$ # @ + 9@. J J J                                                                                                                                                                                                                                                                                                                                 J . 9@+ # $ o#% & * j#> ; *$/ y@W#M#v#^#0#x R L L L L L L L L L L L L L L L L L L L l#              ",
+"              i#Q L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M U Z G C y z@2 i 3#S@R@C@_#T# $G+Z#L#K#B@G+t#I#H# $F#D#C#A#]@]@A#A#A#A#B#B#C#C#C#C#w@w@0+0+D#D#D#E#E#+$+$F#F#.$.$ $ $Y#Y#G#G#H#H#v#v#I#q@q@J#t#t#r#r#G+G+i#$$$$B@`#`#Z#K#K#L#p#X#X#M#{@{@k#&$N#N#W#V#U#O#O#p@v@%$y@y@R#P#Q#_ _ S#x#u#/ / ^ ^ ] ] { ( m#*$*$~ ~ ) ) 8#8#; ; - > = j#* & % o#$ # + + . d#J J                                                                                                                                                                                                                                                                                                                       J J . + @ # o#% & * j#> ; *$u#v@r#)#} @.L L L L L L L L L L L L L L L L L L L L L @.R#              ",
+"              ) t L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L N V ..%.r@v 7 [ G@T@-#_#H+w@+$F#+$0+C#]@T#T#T#T#T##$#$#$e#e#e#]@]@]@A#A#B#B#B#C#C#w@w@0+0+0+D#D#E#E#+$+$F#F#.$.$ $ $Y#G#G#H#H#v#v#I#q@q@J#J#t#r#r#G+G+i#$$$$B@`#`#Z#K#K#L#p#p#X#M#M#k#k#&$N#N#W#V#V#O#O#p@v@v@y@y@R#P#P#_ _ S#x#u#/ / ^ ^ -$] { ( m#*$=$~ ! ) ) ' 8#, ; - > = j#* & o#o## # + 9@. d#J J                                                                                                                                                                                                                                                                                                         J . 9@@ # o#% & j#= > - 8#^ `#}#l T L L L L L L L L L L L L L L L L L L L L L L L 7 *               ",
+"              . P@L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L P V ` E x 7 i G@V@##5#q.=#=#=#=#-#-#-#-#-#-#;#q.q.q.q.q.5#5#5#>#>#>#>#(#7#7#7#7#1#1#)#)#)#)#!#|#1#7#1#1#)#)#)#!#|#|#|#2#2#~#~#~#{#]#]#]#^#^#/#/#a+_#_#_#:#:#_#/#/#a+a+_#_#:#[#[#6#6#c#c#g#h#h#h#[#6#6#c#c#g#h#h#l#n#n#q#I I I w#w#y#y#p.p.H+z#@$@$T##$e#e#]@A#A#B#C#C#A#e#e#]@A#A#B#C#w@0+0+D#E#+$F#F#.$ $Y#G#H#v#I#q@q@t#t#G+G+i#i#$$$$$$B@B@`#`#`#Z#Z#K#$$$$$$$$$$B@B@`#`#`#Z#Z#K#K#K#K#L#L#p#p#p#p#X#X#M#M#M#{@{@k#k#k#M#K#K#K#L#L#L#p#p#p#p#p#p#p#`#i#i#i#i#i#i#i#i#G+G+G+G+G+G+G+r#r#r#t#t#t#t#J#J#q@q@q@I#I#v#v#v#H#H#G#G#Y#Y# $ $ $.$F#w@A#e##$T#z#H+p.y#w#I q#n#l#h#g#6#[#:#_#a+/#/#]#]#{#~#2#|#|#!#)#)#7#7#7#-#j H L L L L L L L L L L L L L L L L L L L L L L L L L L 4#J               ",
+"                z#L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M N N N N O P P Q R R R S T V W X Z  ...+.#.G $.F %.E C C &.B *.H H r@s@s@-.t@A A A t@t@t@t@-.s@s@r@H *.B &.C D E %.F $.G @.+... .` Z Y X W r.U T R Q Q P O N N N M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L Q J#                ",
+"                _ %.L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O P P Q R S T U r.W X Y Y ` ` ....@.@.G G F F E E D C &.B B *.H H H r@r@r@s@s@s@r@r@r@H H *.*.B &.C C E E %.F G G @.@.....` ` Y Y X r.V T S R Q P P O N N N M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L y ~                 ",
+"                o#} L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O O P Q R R T T V r.W X Y Z ` ` ....@.@.#.G $.F F %.E D C C C &.&.B B B B B B B B B &.&.C C D E E %.F $.G #.@.@.....` ` Y Y X W r.U T S R Q P O O N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L 3#+                 ",
+"                J >#L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O O P P Q R S T U V W X Y Y Z ` ` ....+.@.@.G G $.F F F %.E E E E D D D D D D E E E E %.%.F F $.G G @.@.+.....` ` Y Y X W r.V T S R Q P P O O N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L I                   ",
+"                  p#V L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O P P Q R R S T V r.W X Y Y Y ` `  .....+.@.@.#.G G G $.F F F F F F F F F F F F $.G G G #.@.@.+..... .` ` Y Y X W r.V U T R R Q P P O N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L +.R#                  ",
+"                  ; p L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O O P P Q R R T T V r.W W X Y Y Z ` `  .......+.@.@.@.@.#.G G G G G G G G #.@.@.@.@.+....... .` ` Z Y Y X W r.V U T S R Q P P O O N N N M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L 7 *                   ",
+"                  . 8@L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M M N N N O O P P Q R R T T U V r.W X Y Y Y Z ` ` `  .............+.+.@.@.+.+............. .` ` ` Z Y Y X X W r.V U T S R Q P P O O N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L `@J                   ",
+"                    E#L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N N O P P P Q R R S T U V r.W W X Y Y Y Y Y ` ` ` ` ` ` ` `  . .` ` ` ` ` ` ` ` Y Y Y Y X W W r.V V T T S R R Q P P O N N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L P G+                    ",
+"                    ] H L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N N O P P P Q R R S T T U V r.r.W W X X Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y X X W W r.V V U T T R R Q P P P O O N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L y ~                     ",
+"                    # j L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M M N N N N O O P P Q Q R R S T T U V V V r.W W W W W W X X X X X X W W W W W W r.V V U T T T R R R Q P P P O O N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L E@+                     ",
+"                    J _#L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M M N N N N O O P P P P R R R R S T T T U U V V V V V V V V V V V V V U U T T T S S R R R Q P P P O O N N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L I                       ",
+"                      O#Z L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M M N N N N N N N N N O O O O O O O O O O O O O O N N N N N N N N M M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L +.P#                      ",
+"                      j#a L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L h %                       ",
+"                      J {#O L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S R Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y X ..+.+.+.+.+.+.+.+.+.G F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F E C C C C C C C C C C C C C C C C C C C C C C C C C C C C C B s@s@s@s@s@s@s@s@s@s@s@s@s@s@s@s@s@s@s@-.z z z z z z z z z v t t t t t t t t t t t t t t t q 3 w#                        ",
+"                        ; &$t#q@q@q@q@q@q@q@q@q@B#Y@B#q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@q@G+$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$M#&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$N#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#v@R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#S#x#x#x#x#x#x#x#x#x#=.^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ] ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( =$=$=$=$=$=$=$=$=$=$=$=$=$=$=$=$=$=$=$~ ) ) ) ) ) ) ) ) ) 8#, , , , , , , , , , , , , , , - % .                         ",
+"                                            5#2#r U@[ R#                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ",
+"                                            k s@p $#s A@)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   ",
+"                                          X#i v A@-#X#A@c#                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  ",
+"                                          X#.@z G#    $#v R#                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                ",
+"                                          X#0#K       n#u@G#                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      X#X#^#^#                                                                                                                                                  ",
+"                                          X#3#-#      G#i                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   ) X#^#X#X#X#X#                                                                                                                                                  ",
+"                                          G#| G#      n#l                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               X#T#T#X#      X#X#                                                                                                                                                  ",
+"                        ) ) ) ) ) ) ) ) ) G#5 #$) ) ) c {#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) R#G#5#G#R#) ) ) ) ) G#G#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) )                         ",
+"                        T#T#T#T#T#T#T#T#T#T#s $#T#T#u 9 T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#c#a#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#;$>$,$,$y#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#-#-#T#T#T#T#T#T#T#T#T#T#T#T#c#a#a#-#T#T#T#T#T#T#T#T#-#-#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#                        ",
+"                                          ) d !#  n n )                                                                       T#)                                                                                                                                           '$)$              T#)     !$~$,$,${$                ]$,$>$^$/           !$/$,$,$($;$=           B@_$,$,$:$<$[$}$|$1$.                 !$/$,$,$($;$=             ) T#                %$/$,$,$:$2$3$4$5$%               = ,$6$                                                                                                          X#X#                    ) T#T#)                     X#X#                                                                                                  T#)                                             ",
+"                                            a#n $.b -#                                                                        T#)                                                                                                                                         7$8$9$              T#)       . ,$,$0$              ] a$,$b$                9@,$,$=.                9@,$a$+     c$d$,$^$9@                9@,$,$=.                ) T#                  . ,$a$+     e$,$f$              g$,$h$                                                                                                          X#X#                ) T#T#)                         ^#                                                                                                    T#)                                             ",
+"                        ) ) ) ) ) ) ) ) R#C@G A 5 G#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) c#R#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ~ i$,$j$! ) ) ) ) ) ) c#R#) ) ) S#k$,$,$S#) ) ) ) ) ) l$m$,$u#) ) ) ) ) ) ) ) n$,$m$! ) ) ) ) ) ) ) ) n$,$o$) ) ) ) ) p$,$q$) ) ) ) ) ) ) ) n$,$m$! ) ) ) ) ) ) ) ) R#c#) ) ) ) ) ) ) ) ) Q#,$o$) ) ) ( ,$a$! ) ) ) ) ) ) r$,$s$) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) G#G#) ) ) ) ) ) ) G#c#R#) ) ) ) ) ) ) ) ) ) ) ) ) G#G#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) c#R#) ) ) ) ) ) ) ) ) )                         ",
+"                        T#T#T#T#T#T#T#`@r T S G T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#t$u$,$,$l#T#T#T#T#T#T#a#c#T#T#T#v$0$j$,$w$T#T#T#T#T#x$2$8$y$T#T#T#T#T#T#T#T#T#f$,$z$T#T#T#T#T#T#T#T#T#A$,$B$T#T#T#T#T#d$,$C$T#T#T#T#T#T#T#T#f$,$z$T#T#T#T#T#T#T#T#T#c#a#T#T#T#T#T#T#T#T#T#D$,$B$T#T#T#H+,$,$@$T#T#T#T#T#T#E$,$[#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#-#-#T#T#T#T#T#-#S@-#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#S@T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#                        ",
+"                                    `@8 Q W b '#X#                                                                            T#)                                                                                                                                     > F$+ 4$,$K#            T#)       G$]$d$,$H$        o#x$S#,$I$                  J$,$q$                  s$,$G$          @ ,$a$J               J$,$q$                  ) T#                  K$,$G#      -$,$o$            9@k$a$L$            M$,$,$v$  . N$,$E$              J O$_$P$y$,$,$,$Q$+                                           X#X#      ) T#X#                                X#X#                                                                                                      T#)                                             ",
+"                                  T#5 l +.G#R#-#K )                                                                           T#)                                                                                                                                     h$R$  x$,$S$            T#)       T$U$V$,$<$        H$W$X$,$Y$                  Z$,$b$                  `$,$v@          d#,$,$9@              Z$,$b$                  ) T#                  d$,$%$       %,$J$            / ,$_$              d#a$,$K$    o#,$w$              .%8$!$  +%8$J#P#@%                                            X#X#    X#T#)                                   ^#                                                ) X#X#X#                                                T#)                                             ",
+"                        ) ) ) ) ) 5#6 ` #$) c#X@5 $#g#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) c#R#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) #%l$) ) $%,$%%) ) ) ) ) ) c#R#) ) ) &%*%=%,$-%*$) ) v@{$) ;%,$U$) ) ) ) ) ) ) ) ) [$,$R$) ) ) ) ) ) ) ) ) >%,$/ ) ) ) ) ) u#,$,%) ) ) ) ) ) ) ) [$,$R$) ) ) ) ) ) ) ) ) R#c#) ) ) ) ) ) ) ) ) '%,$=.) ) =%k$z$( ) ) ) ) ) ) Y$,$d$) ) ) ) ) ) ) x#,$,$)%) ) {@,$]$) ) ) ) ) ) !%,$f$) ) -$,$Q$) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) G#G#) ) G#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) G#G#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) R#5#c#G#I@#$) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) c#R#) ) ) ) ) ) ) ) ) )                         ",
+"                        T#T#T#T#T#.@F 9 c#P@2 p y u@s $#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#z#~%5$T#T#D$,$a$z#T#T#T#T#T#a#c#T#T#@$a$H+@$a$,$6#T#T#3$s#T#{%,$]%T#T#T#T#T#T#T#T#H+8$8$z#T#T#T#T#T#T#T#T#s#,$^%T#T#T#T#T#T#:#,$>%T#T#T#T#T#T#T#H+8$8$z#T#T#T#T#T#T#T#T#T#c#a#T#T#T#T#T#T#T#T#z#8$y$T#H+!#k$4$5$T#T#T#T#T#T#T#/%,$(%T#T#T#T#T#T#T#:#,$,$y#T#T#7#,$A$T#T#T#T#T#T#Q$,$/#T#T#q#,$-%T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#-#-#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#c#a#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#-#a#T#T#c#-#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#                        ",
+"                                  -#..X@) | {#X#'#X#-#i                                                                       T#)                                                                                                                                 _%s$      = ,$,$7$          T#)     { 6$    ^$,$:%  <%G#  d#[%}%                  @%,$u$                  U#,$x$            G$,$$%              @%,$u$                    ) T#                ^ ,$}$^$P$|%{@d#                1%,$]               2%,$[$      .%,$3%            4$,$4%    g$,$5%                                                X#X#                                        ^#                                          X#^#X#  X#T#T#                                                    T#)                                             ",
+"                                  G#+.R#  I@{#) c#T#  n R#                                                                    T#)                                                                                                                               ) o$@         6%,$1$          T#)     #%Z$    7%,$8%# 5%.   m#,$x$                  U$,$d$                  9%,$0%            2$,$=.              U$,$d$              + 9$;$:$a%l$@             b%,$S$                        & ,$^%d#              0%,${$      B$}$              c%,$%     ;$a$S#                                                X#X#                                      X#X#                                      X#^#X#  X#^#X#)                                                       T#)                                             ",
+"                        ) ) ) ) ) ) v }#) |#x K M@c#R#8 R#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) c#R#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ;$d%_$_$_$_$_$}$,${$) ) ) ) ) c#R#) ) ]%e%) ) U$,$E$'$K#) ) :%,$'$) ) ) ) ) ) ) ) ) .%,$q$) ) ) ) ) ) ) ) ) f%,$g%) ) ) ) ) %$8$|$) ) ) ) ) ) ) ) .%,$q$) ) ) ) ) ) ) ) ) ) R#c#) ) ) ) ) ) ) ) 5$,$J$) ) ) ) ) ) ) ) ) ) ) ) `#,$/$) ) ) ) ) ) ) ) h%,$q$) ) { 8$P$) ) ) ) ) ) ) i%>%r#!  %a$G$) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) G#G#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) G#G#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) R#c#G#) R#c#G#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) c#R#) ) ) ) ) ) ) ) ) )                         ",
+"                        T#T#T#T#T#T#9 } -#T#`@x l a#T#v !#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#A$j%T#T#T#T#T#T#(%,$m$T#T#T#T#T#a#c#T#T#[$]#T#T#w#,$,$&%T#T#T#k%,$A$T#T#T#T#T#T#T#T#T#0$,$D$T#T#T#T#T#T#T#T#T#>$,$l%T#T#T#T#T#3$a$l#T#T#T#T#T#T#T#T#0$,$D$T#T#T#T#T#T#T#T#T#T#c#a#T#T#T#T#T#T#T#T#6%,${$T#T#T#T#T#T#T#T#T#T#T#T#m%,$F$T#T#T#T#T#T#T#T#>%,$a+T#T#:#,$k%T#T#T#T#T#T#T#T#c#~%Q$B$n%T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#-#-#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#S@T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#-#a#!#-#a#a#c#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#                        ",
+"                                    G#i '#X#    ) S@) 2 )                                                                     T#)                                                                                                                           o#(%#             c$,$8$o#        T#)     E$!       6$^%,       o%,$!                 J }$,$3%                * ,$-%d#        G$8$K#                J }$,$3%                    ) T#                4$,$,                         `$,$<%                >$,$4%    p%,$q%              r%m$3%                                                          X#X#                                    ^#                                X#5#n#T#T#X#)                                                                   T#)                                             ",
+"                                      *#| X#    G#`@a#a#                                                                      T#)                                                                                                                           Z$x#              9@,$,$K#        T#)   3%,$9@      l%9%      + ^%,$9@                @%,$,$.                 #%,$4$.     3%s%>$<%                  @%,$,$.                     ) T#              t%,$,$.                       d#}$,$=                 ,%,$N#v@p%P$,$t%              E$,$N#=$; J                                                     X#X#                                  X#X#                          ) n#S@K T#X#) ) X#X#T#^#^#^#^#^#^#^#K ^#                                              T#)                                             ",
+"                        ) ) ) ) ) ) ) ) G#m b b A@$.S@) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) c#R#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) R$6$,$u%) ) ) ) ) ) `#o$,$,$^%J#) ) ) c#X#:$>%,$i$2%) ) ) ) ) ) v%'%,$,$j%F#) ) ) ) ) S#:$}$,$,$i$b$) ) ) ) ) &$w%^%,$,$E$x%u$N$$%/ ) ) ) ) ) ) ) ) S#:$}$,$,$i$b$) ) ) ) ) ) ) ) ) R#c#) ) ) ) ) x#:$m$,$,$N$F#) ) ) ) ) ) ) ) ) 9%o$,$,$y%s$) ) ) ) ) ) ) ]$^%>%z%{ '%,$z$u#) ) ) ) ) ) [$,$,$,$,$j$s$) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) G#G#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) G#G#) ) ) ) ) ) ) ) R#G#G#c#5#.@3#*#5#5#5#5#c#G#G#R#) ) ) ) G#c#5#G#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) c#R#) ) ) ) ) ) ) ) ) )                         ",
+"                        T#T#T#T#T#T#T#T#T#c#$#A@d 4 T#T#T#T#z#g#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#c#a#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#s#[$u$@$T#@$A$,$-%T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#-#-#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#S@a#S@S@S@S@S@S@a#-#-#c#T#T#T#T#T#T#T#T#T#T#T#T#T#T#-#S@-#c#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#                        ",
+"                                                ) P@)     X#J@A#                                                                                                                                                                                                                                                                                                                                                                                                                                                                              u%,$;       { ,$^$                                                                                              )                                               T#X#                                                                                                          ",
+"                                                  } n#X#h < N@                                                                                                                                                                                                                                                                                                                                                                                                                                                                                4$,$U#    ~ N$B$3%                                                                                                                                          X#K )   ) X#X#X#X#X#X#X#X#                                                                                        ",
+"                                            u@n#&#8 A@i G@G#                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  7$`$}$/$9$9$1$9@                                                                                                                                            X#K ^#^#T#X#X#X#X#X#X#-#X#X#X#X#X#X#X#X#X#X#X#X#                                                                  ",
+"                                          S@5 `@-#c#|#                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        X#G#^#X#X#X#X#X#X#X#X#X#X#X#T#)                                                               ",
+"                                      X#K k   )   c#P@)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   ) T#^#X#X#                                                        ",
+"                                      n#U@`@      R#8                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           X#X#T#                                                      ",
+"                                      X#N@v `@R#) 8 `@                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              )                                                       ",
+"                                        n#I@x g G@6 X#                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ",
+"                                              6#s#                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          ",
+"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ",
+"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ",
+"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/amidi-plug.midiicon.xpm	Thu Jan 26 18:43:59 2006 -0800
@@ -0,0 +1,312 @@
+/* XPM */
+static char * amidiplug_xpm_midiicon[] = {
+"48 52 257 2",
+"  	c None",
+". 	c #000000",
+"+ 	c #232323",
+"@ 	c #1F1F1F",
+"# 	c #DADADA",
+"$ 	c #FFFFFF",
+"% 	c #F6F6F6",
+"& 	c #CFCFCF",
+"* 	c #707070",
+"= 	c #FEFEFE",
+"- 	c #FBFBFB",
+"; 	c #EDEDED",
+"> 	c #C0C0C0",
+", 	c #F7F7F7",
+"' 	c #D7D7D7",
+") 	c #F1F1F1",
+"! 	c #B7B7B7",
+"~ 	c #D2D2D2",
+"{ 	c #AEAEAE",
+"] 	c #070707",
+"^ 	c #646464",
+"/ 	c #FDFDFD",
+"( 	c #B8B8B8",
+"_ 	c #DCDCDC",
+": 	c #A4A4A3",
+"< 	c #0E0E0E",
+"[ 	c #3A3A3A",
+"} 	c #454545",
+"| 	c #4E4E4E",
+"1 	c #BFBFBF",
+"2 	c #F5F5F4",
+"3 	c #B5B5B5",
+"4 	c #F9F9F9",
+"5 	c #FCFCFC",
+"6 	c #CBCBCB",
+"7 	c #A5A5A5",
+"8 	c #505050",
+"9 	c #424242",
+"0 	c #434343",
+"a 	c #959595",
+"b 	c #F4F4F4",
+"c 	c #ACACAC",
+"d 	c #ECECEC",
+"e 	c #C3C3C3",
+"f 	c #C2C2C2",
+"g 	c #C9C9C8",
+"h 	c #A8A8A8",
+"i 	c #787878",
+"j 	c #464646",
+"k 	c #FCFCFB",
+"l 	c #F4F4F3",
+"m 	c #ABABAB",
+"n 	c #515151",
+"o 	c #474747",
+"p 	c #464645",
+"q 	c #5D5D5C",
+"r 	c #A9A9A9",
+"s 	c #777777",
+"t 	c #FDFDFC",
+"u 	c #FAFAFA",
+"v 	c #F2F2F2",
+"w 	c #F3F3F3",
+"x 	c #AAAAAA",
+"y 	c #A0A09F",
+"z 	c #8A8A8A",
+"A 	c #7A7A7A",
+"B 	c #6C6C6C",
+"C 	c #5A5A5A",
+"D 	c #A4A4A4",
+"E 	c #A2A2A2",
+"F 	c #9F9F9F",
+"G 	c #949494",
+"H 	c #484848",
+"I 	c #818181",
+"J 	c #A3A3A3",
+"K 	c #A1A1A1",
+"L 	c #B2B2B2",
+"M 	c #393939",
+"N 	c #9C9C9C",
+"O 	c #767676",
+"P 	c #E7E7E7",
+"Q 	c #C6C6C5",
+"R 	c #BABAB9",
+"S 	c #6B6B6B",
+"T 	c #FAFAF9",
+"U 	c #F8F8F7",
+"V 	c #686867",
+"W 	c #F6F6F5",
+"X 	c #F5F5F5",
+"Y 	c #EDEDEB",
+"Z 	c #9D9D9D",
+"` 	c #A3A3A2",
+" .	c #535353",
+"..	c #393938",
+"+.	c #9B9B9A",
+"@.	c #9E9E9E",
+"#.	c #676767",
+"$.	c #B1B1B1",
+"%.	c #6A6A6A",
+"&.	c #FBFBFA",
+"*.	c #F9F9F8",
+"=.	c #383838",
+"-.	c #676766",
+";.	c #F3F3F2",
+">.	c #B3B3B3",
+",.	c #A1A1A0",
+"'.	c #A2A2A1",
+").	c #747474",
+"!.	c #AFAFAE",
+"~.	c #666666",
+"{.	c #F2F2F1",
+"].	c #696969",
+"^.	c #F8F8F8",
+"/.	c #F1F1F0",
+"(.	c #939392",
+"_.	c #9C9C9B",
+":.	c #9E9E9D",
+"<.	c #777776",
+"[.	c #F2F2F0",
+"}.	c #F0F0F0",
+"|.	c #F7F7F6",
+"1.	c #F0F0EF",
+"2.	c #EFEFEE",
+"3.	c #EFEFED",
+"4.	c #F3F3F1",
+"5.	c #F1F1EF",
+"6.	c #EEEEED",
+"7.	c #EEEEEC",
+"8.	c #383837",
+"9.	c #373737",
+"0.	c #EEEEEE",
+"a.	c #EDEDEC",
+"b.	c #EFEFEF",
+"c.	c #ECECEB",
+"d.	c #373736",
+"e.	c #F0F0EE",
+"f.	c #363636",
+"g.	c #EBEBEA",
+"h.	c #606060",
+"i.	c #B0B0AF",
+"j.	c #8F8F8F",
+"k.	c #B6B6B6",
+"l.	c #999998",
+"m.	c #9D9D9C",
+"n.	c #9B9B99",
+"o.	c #999999",
+"p.	c #9A9A99",
+"q.	c #B1B1B0",
+"r.	c #8A8A89",
+"s.	c #616160",
+"t.	c #EAEAE9",
+"u.	c #EAEAE8",
+"v.	c #ECECEA",
+"w.	c #555555",
+"x.	c #E9E9E8",
+"y.	c #E9E9E7",
+"z.	c #9F9F9E",
+"A.	c #737373",
+"B.	c #B5B5B4",
+"C.	c #737372",
+"D.	c #B4B4B3",
+"E.	c #8C8C8B",
+"F.	c #AAAAA9",
+"G.	c #959594",
+"H.	c #979797",
+"I.	c #A7A7A7",
+"J.	c #989898",
+"K.	c #898988",
+"L.	c #626261",
+"M.	c #363635",
+"N.	c #EBEBE9",
+"O.	c #E8E8E7",
+"P.	c #E8E8E6",
+"Q.	c #9B9B9B",
+"R.	c #8D8D8C",
+"S.	c #717170",
+"T.	c #979796",
+"U.	c #B3B3B2",
+"V.	c #898989",
+"W.	c #70706E",
+"X.	c #929291",
+"Y.	c #949493",
+"Z.	c #616161",
+"`.	c #E7E7E6",
+" +	c #E6E6E4",
+".+	c #6D6D6C",
+"++	c #9A9A9A",
+"@+	c #969696",
+"#+	c #989897",
+"$+	c #969695",
+"%+	c #6C6C6B",
+"&+	c #E5E5E4",
+"*+	c #E7E7E5",
+"=+	c #E5E5E3",
+"-+	c #E4E4E2",
+";+	c #B1B1AF",
+">+	c #353535",
+",+	c #BAB8B4",
+"'+	c #6E6B62",
+")+	c #565248",
+"!+	c #23211D",
+"~+	c #4F4F4F",
+"{+	c #949492",
+"]+	c #A7A7A5",
+"^+	c #989896",
+"/+	c #A5A5A3",
+"(+	c #E6E5E4",
+"_+	c #625E55",
+":+	c #9C9A94",
+"<+	c #D8D7D5",
+"[+	c #89867F",
+"}+	c #626262",
+"|+	c #E6E6E5",
+"1+	c #D7D6D3",
+"2+	c #5A564D",
+"3+	c #656259",
+"4+	c #F5F4F4",
+"5+	c #69655C",
+"6+	c #D5D4D1",
+"7+	c #8F8D86",
+"8+	c #A7A7A6",
+"9+	c #888887",
+"0+	c #868685",
+"a+	c #353534",
+"b+	c #959593",
+"c+	c #CCCBC8",
+"d+	c #C4C2BF",
+"e+	c #C4C3BF",
+"f+	c #716D65",
+"g+	c #E3E2E0",
+"h+	c #67635A",
+"i+	c #67645B",
+"j+	c #59564C",
+"k+	c #6E6E6D",
+"l+	c #919190",
+"m+	c #ACACAB",
+"n+	c #6D6D6D",
+"o+	c #90908F",
+"p+	c #8B8881",
+"q+	c #C0BEBA",
+"r+	c #8C8982",
+"s+	c #706D64",
+"t+	c #E0DFDD",
+"u+	c #E4E4E3",
+"v+	c #DDDDDB",
+"w+	c #68645C",
+"x+	c #D3D2D0",
+"y+	c #8B8882",
+"z+	c #F7F6F6",
+"A+	c #85827B",
+"B+	c #E3E3E1",
+"C+	c #A3A3A1",
+"D+	c #8D8D8D",
+"E+	c #E3E3E2",
+"F+	c #E2E2E0",
+"G+	c #E1E1DF",
+"H+	c #8C8C8C",
+"  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + @                       ",
+". # $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % & * .                   ",
+". $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ = = = = = = = = = = = = - % ; > .                 ",
+". $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ = = = = = = = = = = = = = = , ' $ ) ! .               ",
+". $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ = = = = = = = = = = = = = = = = , ~ $ $ ; { ]             ",
+". $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ^ > = = = = = = = = = = = = = = / / % ( $ / $ _ : <           ",
+". $ $ $ $ $ $ $ $ $ $ $ $ $ $ = = [ } | 1 = = = = = = = [ [ [ [ [ [ / 2 3 $ 4 5 $ 6 7 .         ",
+". $ $ $ $ $ $ $ $ $ $ $ $ = = = = [ > 8 9 0 a = = = / / [ [ [ [ [ [ 5 b c d e 6 ( f g h .       ",
+". $ $ $ $ $ $ $ $ $ $ [ = = = = = [ = = 1 i j / / / / / [ 5 5 5 5 [ k l m n o p j j q r .       ",
+". $ $ $ $ $ $ $ $ = = [ = = = = = [ = / / / s / t 5 5 5 [ 5 5 k - [ u v w > x y z A B } .       ",
+". $ $ $ $ $ C D D D E [ F D D D E [ D G G G H G I J J K [ J J J L M N E J O , P Q g R A .       ",
+". $ $ $ $ = S = = = = [ / / / / / [ 5 5 5 5 [ 5 k - - - [ - T 4 4 M 4 , U V W X X X Y r .       ",
+". $ $ = = = S E D D F [ D D J s [ [ J J J K [ Z J J `  .M N E F M ..+.F @.#.X 2 2 w w $..       ",
+". $ = = / / %./ / / t [ 5 5 5 [ [ [ - - - - [ &.u u M M M *.*.=.=.=.% 2 2 -.b l w ;.;.3 .       ",
+". $ / / / / %.K J @.[ [ >.J J s [ K J ` ,.M M N E '.O M @.F F ).=.!.@.@.@.~.;.;.;.{.{.3 .       ",
+". $ / t 5 5 ].5 5 [ [ [ - - - &.&.u u u M M M *.^.^.^., W W W 2 b b l l ;.~.v v {././.3 .       ",
+". $ 5 5 5 5 (.J J s [ s ` ` E E E E E E _.M @.K K y F F F F @.:.:.:.Z Z Z <.[././.}.}.3 .       ",
+". $ k k - - - - &.&.u u u u u T T 4 ^.^.^.U U |.X X X 2 l l l w ;.{.{.{.{.[.}.}.1.2.3.3 .       ",
+". $ - - - &.&.u u u u T T T 4 4 ^.^.U U , % X X 2 2 l w w w 4.{.{.{.) /.5.1.1.2.6.6.7.3 .       ",
+". $ &.u u u u u T T 4 M M M M M M , , % 2 2 2 b l w ;.;.8.9.9.9.9.9.5.1.1.0.0.6.7.a.a.3 .       ",
+". $ u u T T 4 4 4 4 4 M M M M M ..W W 2 b b b ;.;.;.;.{.9.9.9.9.9.9.b.6.6.6.7.a.a.d c.3 .       ",
+". $ T 4 4 4 4 *.*.^., M , |.|.W =.b b l l ;.;.9.v {././.9./.1.1.2.d.6.6.7.a.Y Y c.c.c.3 .       ",
+". $ 4 *.*.*.^.^., |.|...|.X X b =.l l ;.v v {.9.[./.}.}.9.e.2.6.6.f.a.a.Y Y c.c.g.g.g.3 .       ",
+". $ ^.^.^.^.h.i.y F j.=.k.:.:.:.=.l.Z m.m.m.n.9.o._._.l.9.p.o.o.q.f.r.l.l.s.g.g.g.t.u.3 .       ",
+". $ U |.|.|.#.% % 2 2 =.l w w ;.9.{.{.) /.5.1.9.1.1.2.7.f.a.a.a.Y f.v.v.g.w.g.t.x.x.y.3 .       ",
+". $ % % % W #.).z.A.=.=.B.Z C.9.9.D.N _._._.E.9.F.p.G.f.f.H.l.G f.f.I.J.K.L.x.x.y.y.y.3 .       ",
+". $ W W W 2 ~.b ;.8.8.8.{.) 9.9.9.5.1.b.2.2.2.d.7.a.f.f.f.c.v.f.f.M.N.x.x.L.x.y.O.O.P.3 .       ",
+". $ X b l l ~.l.Z Q.9.R.N N m 9.E.+.+.+.+.S.f.f.T.U.V.f.l.J.J.W.M.X.T.T.Y.Z.O.O.P.P.P.3 .       ",
+". $ l l ;.v ~.{.{./././.}.1.1.2.2.2.0.a.a.f.f.f.c.c.g.g.g.N.N.x.y.y.O.O.O.^ P.`.`.`. +3 .       ",
+". $ v {.{.{..+N N N _._._.+.+.++p.o.o.l.l.V.f.@+J.J.J.#+#+T.T.T.T.@+$+$+$+%+`.`. + +&+3 .       ",
+". $ {.{.{./.1.1.1.1.1.2.3.6.6.a.a.Y c.v.v.g.g.g.g.t.t.x.y.y.y.P.P.P.P.`.`.*+ +&+&+&+&+3 .       ",
+". $ ) /.1.1.1.1.2.2.3.6.6.a.a.c.c.v.v.g.g.N.t.t.t.x.y.y.O.P.P.P.P.`.*+*+ + +&+&+=+=+=+3 .       ",
+". $ 1.1.b.2.2.2.3.6.6.f.c.c.c.v.v.f.N.N.t.t.t.x.y.O.O.P.P.P.P.*+*+*+ + +&+=+=+=+=+=+-+3 .       ",
+". $ 2.2.2.2.3.6.7.c.c.f.f.c.v.N.N.M.M.t.u.O.O.O.O.P.P.P.`.*+*+*+ + +=+=+=+=+=+=+=+-+-+3 .       ",
+". $ 2.2.6.6.7.c.c.c.c.f.$.f.N.N.t.M.;+>+O.O.O.,+,+,+,+,+,+,+,+,+,+,+,+,+,+,+,+,+,+,+,+,+,+,+,+'+",
+". $ 6.6.Y c.c.v.g.g.g.f.N.N.u.u.u.>+O.P.P.`.`.,+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+!+",
+". $ Y c.v.g.~+I.J.#+{+M.]+^+^+@+$+>+/+$+$+$+$+,+)+$ (+_+)+)+:+$ $ )+$ $ $ $ )+$ $ = W <+[+)+)+!+",
+". $ v.g.g.g.}+t.t.t.t.M.u.P.P.P.P.>+`.*+*+*+|+,+)+$ $ 1+2+3+4+$ $ )+)+$ $ )+)+$ $ )+5+6+$ 7+)+!+",
+". $ N.N.t.t.}+8+#+9+M.>+/+/+$+0+a+a+: $+a G.b+,+)+$ c+$ d+e+c+$ $ )+)+$ $ )+)+$ $ )+)+f+$ g+)+!+",
+". $ t.t.t.u.L.x.x.>+>+>+P.*+*+a+a+a+ + +=+=+=+,+)+$ h+l $ 4+i+$ $ )+)+$ $ )+)+$ $ )+)+j+$ 4 )+!+",
+". $ u.x.x.x.L.Y.Y.k+>+l+$+$+m+n+a+o+b+b+b+b+X.,+)+$ )+p+q+r+)+$ $ )+)+$ $ )+)+$ $ )+)+s+$ t+)+!+",
+". $ x.x.x.P.Z.`.`.`.*+*+*+|+|+ +=+=+=+=+u+u+v+,+)+$ )+)+)+)+)+$ $ )+)+$ $ )+)+$ $ )+w+x+= y+)+!+",
+". $ y.`.`.`.%+$+$+$+a a a G.b+b+b+Y.Y.{+{+{+$+,+)+$ )+)+)+)+)+$ $ )+$ $ $ $ )+$ $ = z+1+A+)+)+!+",
+". $ `.*+*+*+|+|+|+|+ + +=+u+u+u+-+-+-+-+-+-+-+,+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+!+",
+". $ *+|+|+|+ + + + +u+u+-+-+-+-+-+-+-+-+-+B+B+'+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+",
+". $ |+ + + + +&+u+-+-+-+-+-+-+-+-+-+-+B+B+B+B+B+: : : ` ` ` ` C+C+C+C+C+C+C+C+C+C+C+C+D+.       ",
+". #  + + +=+-+-+-+-+-+-+-+-+-+-+E+B+B+B+B+B+B+B+B+F+F+F+F+G+G+G+G+G+G+G+G+G+G+G+G+G+G+++.       ",
+". f 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 ++H+.       ",
+"  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .       ",
+"                                                                                                ",
+"                                                                                                ",
+"                                                                                                "};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_common.h	Thu Jan 26 18:43:59 2006 -0800
@@ -0,0 +1,61 @@
+/*
+*
+* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+*
+*/
+
+#ifndef _I_COMMON_H
+#define _I_COMMON_H 1
+
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <glib.h>
+
+#define _(String) (String)
+#define N_(String) String
+#define textdomain(Domain)
+#define bindtextdomain(Package, Directory)
+
+#define WARNANDBREAK(...) { g_warning(__VA_ARGS__); break; }
+#define WARNANDBREAKANDPLAYERR(...) { amidiplug_playing_status = AMIDIPLUG_ERR; g_warning(__VA_ARGS__); break; }
+
+#ifdef DEBUG
+#define DEBUGMSG(...) { fprintf(stderr, "amidi-plug(%s:%s:%d): ", __FILE__, __FUNCTION__, (int) __LINE__); fprintf(stderr, __VA_ARGS__); }
+#else
+#define DEBUGMSG(...)
+#endif /* DEBUG */
+
+
+#define AMIDIPLUG_VERSION "0.1"
+#define PLAYER_NAME "Audacious"
+#define G_PATH_GET_BASENAME(x) g_path_get_basename(x)
+#define G_STRING_PRINTF(...) g_string_printf(__VA_ARGS__)
+
+/* multi-purpose data bucket */
+typedef struct
+{
+  gint bint[2];
+  gchar * bcharp[2];
+  gpointer bpointer[2];
+}
+data_bucket_t;
+
+#endif /* !_I_COMMON_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_configure.c	Thu Jan 26 18:43:59 2006 -0800
@@ -0,0 +1,433 @@
+/*
+*
+* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+*
+*/
+
+
+#include "i_configure.h"
+
+/* internals */
+void i_configure_upd_portlist( void );
+void i_configure_upd_mixercardlist( void );
+gchar * i_configure_read_seq_ports_default( gchar * );
+gboolean i_configure_ev_checktoggle( GtkTreeModel * , GtkTreePath * , GtkTreeIter * , gpointer );
+void i_configure_ev_changetoggle( GtkCellRendererToggle * , gchar * , gpointer );
+
+
+void i_configure_gui( GSList * wports , GSList * scards )
+{
+  GtkWidget *configwin_vbox;
+  GtkWidget *port_lv, *port_lv_sw, *port_frame;
+  GtkWidget *mixer_card_cmb_evbox, *mixer_card_cmb, *mixer_vbox, *mixer_frame;
+  GtkWidget *hseparator, *hbuttonbox, *button_ok, *button_cancel;
+  GtkListStore *port_liststore, *mixer_card_liststore;
+  GtkTreeIter iter;
+  GtkTreeSelection *port_lv_sel;
+  GtkCellRenderer *port_lv_toggle_rndr, *port_lv_text_rndr, *mixer_card_cmb_text_rndr;
+  GtkTreeViewColumn *port_lv_toggle_col, *port_lv_portnum_col;
+  GtkTreeViewColumn *port_lv_clientname_col, *port_lv_portname_col;
+  gchar **portstring_from_cfg = NULL;
+
+  if ( amidiplug_gui_prefs.config_win )
+    return;
+
+  if ( strlen( amidiplug_cfg.seq_writable_ports ) > 0 )
+    portstring_from_cfg = g_strsplit( amidiplug_cfg.seq_writable_ports , "," , 0 );
+
+  amidiplug_gui_prefs.config_win = gtk_window_new( GTK_WINDOW_TOPLEVEL );
+  gtk_window_set_type_hint( GTK_WINDOW(amidiplug_gui_prefs.config_win), GDK_WINDOW_TYPE_HINT_DIALOG );
+  gtk_window_set_title( GTK_WINDOW(amidiplug_gui_prefs.config_win), "AMIDI-Plug - configuration" );
+  gtk_container_set_border_width( GTK_CONTAINER(amidiplug_gui_prefs.config_win), 10 );
+  g_signal_connect( G_OBJECT(amidiplug_gui_prefs.config_win) ,
+                    "destroy" , G_CALLBACK(i_configure_ev_destroy) , NULL );
+
+  configwin_vbox = gtk_vbox_new( FALSE , 0 );
+  gtk_container_add( GTK_CONTAINER(amidiplug_gui_prefs.config_win) , configwin_vbox );
+
+  port_liststore = gtk_list_store_new( LISTPORT_N_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_STRING ,
+                                       G_TYPE_STRING , G_TYPE_STRING , G_TYPE_POINTER );
+
+  /* append ALSA MIDI ports */
+  while ( wports != NULL )
+  {
+    gint i = 0;
+    gboolean toggled = FALSE;
+    data_bucket_t * portinfo = (data_bucket_t *)wports->data;
+    GString * portstring = g_string_new("");
+    G_STRING_PRINTF( portstring , "%i:%i" ,
+                     portinfo->bint[0] , portinfo->bint[1] );
+    gtk_list_store_append( port_liststore , &iter );
+
+    /* in the existing configuration there may be previously selected ports */
+    if ( portstring_from_cfg )
+    {
+      /* check if current row contains a port selected by user */
+      for ( i = 0 ; portstring_from_cfg[i] != NULL ; i++ )
+      {
+        /* if it's one of the selected ports, toggle its checkbox */
+        if ( !strcmp( portstring->str, portstring_from_cfg[i] ) )
+          toggled = TRUE;
+      }
+    }
+
+    gtk_list_store_set( port_liststore , &iter ,
+                        LISTPORT_TOGGLE_COLUMN , toggled ,
+                        LISTPORT_PORTNUM_COLUMN , portstring->str ,
+                        LISTPORT_CLIENTNAME_COLUMN , portinfo->bcharp[0] ,
+                        LISTPORT_PORTNAME_COLUMN , portinfo->bcharp[1] ,
+                        LISTPORT_POINTER_COLUMN , portinfo , -1 );
+
+    g_string_free( portstring , TRUE );
+    /* on with next */
+    wports = wports->next;
+  }
+
+  /* this string array is not needed anymore */
+  g_strfreev( portstring_from_cfg );
+
+  port_lv = gtk_tree_view_new_with_model( GTK_TREE_MODEL(port_liststore) );
+  amidiplug_gui_prefs.port_treeview = port_lv;
+  g_object_unref( port_liststore );
+  port_lv_toggle_rndr = gtk_cell_renderer_toggle_new();
+  gtk_cell_renderer_toggle_set_radio( GTK_CELL_RENDERER_TOGGLE(port_lv_toggle_rndr) , FALSE );
+  gtk_cell_renderer_toggle_set_active( GTK_CELL_RENDERER_TOGGLE(port_lv_toggle_rndr) , TRUE );
+  g_signal_connect( port_lv_toggle_rndr , "toggled" ,
+                    G_CALLBACK(i_configure_ev_changetoggle) , port_liststore );
+  port_lv_text_rndr = gtk_cell_renderer_text_new();
+  port_lv_toggle_col = gtk_tree_view_column_new_with_attributes( "", port_lv_toggle_rndr,
+                                                                 "active", LISTPORT_TOGGLE_COLUMN, NULL );
+  port_lv_portnum_col = gtk_tree_view_column_new_with_attributes( "Port", port_lv_text_rndr,
+                                                                  "text", LISTPORT_PORTNUM_COLUMN, NULL );
+  port_lv_clientname_col = gtk_tree_view_column_new_with_attributes( "Client name", port_lv_text_rndr,
+                                                                     "text", LISTPORT_CLIENTNAME_COLUMN, NULL );
+  port_lv_portname_col = gtk_tree_view_column_new_with_attributes( "Port name", port_lv_text_rndr,
+                                                                   "text", LISTPORT_PORTNAME_COLUMN, NULL );
+  gtk_tree_view_append_column( GTK_TREE_VIEW(port_lv), port_lv_toggle_col );
+  gtk_tree_view_append_column( GTK_TREE_VIEW(port_lv), port_lv_portnum_col );
+  gtk_tree_view_append_column( GTK_TREE_VIEW(port_lv), port_lv_clientname_col );
+  gtk_tree_view_append_column( GTK_TREE_VIEW(port_lv), port_lv_portname_col );
+
+  port_lv_sel = gtk_tree_view_get_selection( GTK_TREE_VIEW(port_lv) );
+  gtk_tree_selection_set_mode( GTK_TREE_SELECTION(port_lv_sel) , GTK_SELECTION_SINGLE );
+
+  port_lv_sw = gtk_scrolled_window_new( NULL , NULL );
+  gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(port_lv_sw),
+                                  GTK_POLICY_NEVER, GTK_POLICY_NEVER );
+  port_frame = gtk_frame_new( "ALSA output ports" );
+
+  gtk_container_add( GTK_CONTAINER(port_lv_sw) , port_lv );
+  gtk_container_set_border_width( GTK_CONTAINER(port_lv_sw) , 5 );
+  gtk_container_add( GTK_CONTAINER(port_frame) , port_lv_sw );
+  gtk_box_pack_start( GTK_BOX(configwin_vbox) , port_frame , TRUE , TRUE , 0 );
+
+  /**********************/
+  /*** MIXER SETTINGS ***/
+  mixer_card_liststore = gtk_list_store_new( LISTMIXER_N_COLUMNS , G_TYPE_STRING , G_TYPE_INT ,
+                                             G_TYPE_INT , G_TYPE_STRING );
+  mixer_card_cmb = gtk_combo_box_new_with_model( GTK_TREE_MODEL(mixer_card_liststore) );
+  amidiplug_gui_prefs.mixercard_combo = mixer_card_cmb;
+  /* fill models with sound cards and relative mixer controls */
+  while ( scards != NULL )
+  {
+    data_bucket_t * cardinfo = (data_bucket_t *)scards->data;
+    GString * desc_cardmix_string = g_string_new( "" );
+    GSList * mixctl_list = cardinfo->bpointer[0];
+    while ( mixctl_list != NULL )
+    {
+      data_bucket_t * mixctlinfo = (data_bucket_t *)mixctl_list->data;
+      G_STRING_PRINTF( desc_cardmix_string , "%s - ctl: %s (ID %i)" , cardinfo->bcharp[0] ,
+                       mixctlinfo->bcharp[0] , mixctlinfo->bint[0] );
+      gtk_list_store_append( mixer_card_liststore , &iter );
+      gtk_list_store_set( mixer_card_liststore , &iter ,
+                          LISTMIXER_DESC_COLUMN , desc_cardmix_string->str ,
+                          LISTMIXER_CARDID_COLUMN , cardinfo->bint[0] ,
+                          LISTMIXER_MIXCTLID_COLUMN , mixctlinfo->bint[0] ,
+                          LISTMIXER_MIXCTLNAME_COLUMN , mixctlinfo->bcharp[0] , -1 );
+      /* check if this corresponds to the value previously selected by user */
+      if ( ( cardinfo->bint[0] == amidiplug_cfg.mixer_card_id ) &&
+           ( !strcasecmp( mixctlinfo->bcharp[0] , amidiplug_cfg.mixer_control_name ) ) &&
+           ( mixctlinfo->bint[0] == amidiplug_cfg.mixer_control_id ) )
+        gtk_combo_box_set_active_iter( GTK_COMBO_BOX(mixer_card_cmb) , &iter );
+      mixctl_list = mixctl_list->next;
+    }
+    g_string_free( desc_cardmix_string , TRUE );
+    /* on with next */
+    scards = scards->next;
+  }
+  /* free the instance of liststore, we already have one in the combo box */
+  g_object_unref( mixer_card_liststore );
+  /* create renderer to display text in the mixer combo box */
+  mixer_card_cmb_text_rndr = gtk_cell_renderer_text_new();
+  gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(mixer_card_cmb) , mixer_card_cmb_text_rndr , TRUE );
+  gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(mixer_card_cmb) , mixer_card_cmb_text_rndr , "text" , 0 );
+
+  /* the event box is needed to display a tooltip for the mixer combo box */
+  mixer_card_cmb_evbox = gtk_event_box_new();
+  gtk_container_add( GTK_CONTAINER(mixer_card_cmb_evbox) , mixer_card_cmb );
+  mixer_vbox = gtk_vbox_new( FALSE , 0 );
+  gtk_container_set_border_width( GTK_CONTAINER(mixer_vbox) , 5 );
+  gtk_box_pack_start( GTK_BOX(mixer_vbox) , mixer_card_cmb_evbox , TRUE , TRUE , 0 );
+
+  mixer_frame = gtk_frame_new( "Mixer settings" );
+  gtk_container_add( GTK_CONTAINER(mixer_frame) , mixer_vbox );
+  gtk_box_pack_start( GTK_BOX(configwin_vbox) , mixer_frame , TRUE , TRUE , 0 );
+
+  /* horizontal separator and buttons */
+  hseparator = gtk_hseparator_new();
+  gtk_box_pack_start( GTK_BOX(configwin_vbox) , hseparator , FALSE , FALSE , 4 );
+  hbuttonbox = gtk_hbutton_box_new();
+  gtk_button_box_set_layout( GTK_BUTTON_BOX(hbuttonbox) , GTK_BUTTONBOX_END );
+  button_cancel = gtk_button_new_from_stock( GTK_STOCK_CANCEL );
+  g_signal_connect( G_OBJECT(button_cancel) , "clicked" , G_CALLBACK(i_configure_ev_bcancel) , NULL );
+  gtk_container_add( GTK_CONTAINER(hbuttonbox) , button_cancel );
+  button_ok = gtk_button_new_from_stock( GTK_STOCK_OK );
+  g_signal_connect( G_OBJECT(button_ok) , "clicked" , G_CALLBACK(i_configure_ev_bok) , NULL );
+  gtk_container_add( GTK_CONTAINER(hbuttonbox) , button_ok );
+  gtk_box_pack_start( GTK_BOX(configwin_vbox) , hbuttonbox , FALSE , FALSE , 0 );
+
+  /* tooltips */
+  amidiplug_gui_prefs.config_tips = gtk_tooltips_new();
+  gtk_tooltips_set_tip( GTK_TOOLTIPS(amidiplug_gui_prefs.config_tips) , port_lv ,
+                        "* Select ALSA output ports *\n"
+                        "MIDI events will be sent to the ports selected here. At least one "
+                        "port must be selected in order to play MIDI with AMIDI-Plug. Unless "
+                        "you know what you're doing, you'll probably want to use the "
+                        "wavetable synthesizer ports." , "" );
+  gtk_tooltips_set_tip( GTK_TOOLTIPS(amidiplug_gui_prefs.config_tips) , mixer_card_cmb_evbox ,
+                        "* Select ALSA mixer control *\n"
+                        "AMIDI-Plug outputs directly through ALSA, it doesn't use effect "
+                        "and ouput plugins from the player. While playing with AMIDI-Plug, "
+                        "the player volume will manipulate the control you select here. "
+                        "Unless you know what you're doing, you'll probably want to select "
+                        "the Synth control here." , "" );
+
+  gtk_widget_show_all( amidiplug_gui_prefs.config_win );
+}
+
+
+void i_configure_upd_portlist( void )
+{
+  GtkTreeModel * liststore;
+  GString *wp = g_string_new( "" );
+  /* get the model of the port list control */
+  liststore = gtk_tree_view_get_model( GTK_TREE_VIEW(amidiplug_gui_prefs.port_treeview) );
+  /* after the following foreach, wp contains a comma-separated list of selected ports */
+  gtk_tree_model_foreach( liststore , i_configure_ev_checktoggle , wp );
+  /* free previous */
+  g_free( amidiplug_cfg.seq_writable_ports );
+  /* update point amidiplug_cfg.seq_writable_ports
+     so it points to the new list of ports */
+  amidiplug_cfg.seq_writable_ports = g_strdup( wp->str );
+  /* not needed anymore */
+  g_string_free( wp , TRUE );
+  return;
+}
+
+
+void i_configure_upd_mixercardlist( void )
+{
+  GtkTreeModel * liststore;
+  GtkTreeIter iter;
+  /* get the model of the card-mixer list control */
+  liststore = gtk_combo_box_get_model( GTK_COMBO_BOX(amidiplug_gui_prefs.mixercard_combo) );
+  /* get the selected item */
+  if ( gtk_combo_box_get_active_iter( GTK_COMBO_BOX(amidiplug_gui_prefs.mixercard_combo) , &iter ) )
+  {
+    /* free previous */
+    g_free( amidiplug_cfg.mixer_control_name );
+    /* update amidiplug_cfg.mixer_card_id and amidiplug_cfg.mixer_control_name */
+    gtk_tree_model_get( GTK_TREE_MODEL(liststore) , &iter ,
+                        LISTMIXER_CARDID_COLUMN , &amidiplug_cfg.mixer_card_id ,
+                        LISTMIXER_MIXCTLID_COLUMN , &amidiplug_cfg.mixer_control_id ,
+                        LISTMIXER_MIXCTLNAME_COLUMN , &amidiplug_cfg.mixer_control_name , -1 );
+  }
+  return;
+}
+
+
+gboolean i_configure_ev_checktoggle( GtkTreeModel * model , GtkTreePath * path ,
+                                     GtkTreeIter * iter , gpointer wpp )
+{
+  gboolean toggled = FALSE;
+  gchar * portstring;
+  GString * wps = wpp;
+  gtk_tree_model_get ( model , iter ,
+                       LISTPORT_TOGGLE_COLUMN , &toggled ,
+                       LISTPORT_PORTNUM_COLUMN , &portstring , -1 );
+  /* check if the row points to an enabled port */
+  if ( toggled )
+  {
+    /* if this is not the first port added to wp, use comma as separator */
+    if ( wps->str[0] != '\0' ) g_string_append_c( wps , ',' );
+    g_string_append( wps , portstring );
+  }
+  g_free( portstring );
+  return FALSE;
+}
+
+
+void i_configure_ev_changetoggle( GtkCellRendererToggle * rdtoggle ,
+                                  gchar * path_str , gpointer data )
+{
+  GtkTreeModel *model = (GtkTreeModel *)data;
+  GtkTreeIter iter;
+  GtkTreePath *path = gtk_tree_path_new_from_string( path_str );
+  gboolean toggled;
+
+  gtk_tree_model_get_iter( model , &iter , path );
+  gtk_tree_model_get( model , &iter , LISTPORT_TOGGLE_COLUMN , &toggled , -1);
+
+  toggled ^= 1;
+  gtk_list_store_set( GTK_LIST_STORE(model), &iter , LISTPORT_TOGGLE_COLUMN , toggled , -1);
+
+  gtk_tree_path_free (path);
+}
+
+
+void i_configure_ev_destroy( void )
+{
+  g_object_unref( amidiplug_gui_prefs.config_tips );
+  amidiplug_gui_prefs.config_tips = NULL;
+  amidiplug_gui_prefs.config_win = NULL;
+}
+
+
+void i_configure_ev_bcancel( void )
+{
+  gtk_widget_destroy(amidiplug_gui_prefs.config_win);
+}
+
+
+void i_configure_ev_bok( void )
+{
+  /* update amidiplug_cfg.seq_writable_ports
+     using the selected values from the port list */
+  i_configure_upd_portlist();
+
+  /* update amidiplug_cfg.mixer_card_id and amidiplug_cfg.mixer_control_name
+     using the selected values from the card-mixer combo list */
+  i_configure_upd_mixercardlist();
+
+  /* save settings */
+  i_configure_cfg_save();
+
+  gtk_widget_destroy(amidiplug_gui_prefs.config_win);
+}
+
+
+gchar * i_configure_read_seq_ports_default( gchar * alsaversion )
+{
+  FILE * fp = NULL;
+  gchar ** alsaversion_toks = NULL;
+  /* first try, get seq ports from proc on card0 */
+  fp = fopen( "/proc/asound/card0/wavetableD1" , "rb" );
+  if ( fp )
+  {
+    gchar buffer[100];
+    while ( !feof( fp ) )
+    {
+      fgets( buffer , 100 , fp );
+      if (( strlen( buffer ) > 11 ) && ( !strncasecmp( buffer , "addresses: " , 11 ) ))
+      {
+        /* change spaces between ports (65:0 65:1 65:2 ...)
+           into commas (65:0,65:1,65:2,...) */
+        g_strdelimit( &buffer[11] , " " , ',' );
+        /* remove lf and cr from the end of the string */
+        g_strdelimit( &buffer[11] , "\r\n" , '\0' );
+        /* ready to go */
+        DEBUGMSG( "init, default values for seq ports detected: %s\n" , &buffer[11] );
+        fclose( fp );
+        return g_strdup( &buffer[11] );
+      }
+    }
+    fclose( fp );
+  }
+
+  /* second try, go with different "possible" defaults depending on ALSA version;
+     this is just a fallback, not expected to work all of the times; expecially
+     considering that the lib version is checked, not the driver one (even if
+     the version number is most likely the same) */
+  alsaversion_toks = g_strsplit( alsaversion , "." , 4 );
+  if ( strtol( alsaversion_toks[0] , NULL , 10 ) < 2 )
+  {
+    if ( strtol( alsaversion_toks[1] , NULL , 10 ) < 1 )
+    {
+      if ( strtol( alsaversion_toks[2] , NULL , 10 ) < 11 )
+      {
+        /* alsa version <= 1.0.10 */
+        g_strfreev( alsaversion_toks );
+        DEBUGMSG( "init, default seq port value tentatively set to 65:0 (ALSA %s)\n" , alsaversion );
+        return g_strdup( "65:0" );
+      }
+    }
+  }
+  /* alsa version > 1.0.10 */
+  g_strfreev( alsaversion_toks );
+  DEBUGMSG( "init, default seq port value tentatively set to 17:0 (ALSA %s)\n" , alsaversion );
+  return g_strdup( "17:0" );
+}
+
+
+void i_configure_cfg_read( gchar * alsaversion )
+{
+  ConfigFile *cfgfile;
+  cfgfile = xmms_cfg_open_default_file();
+
+  if (!cfgfile)
+  {
+    /* use defaults */
+    amidiplug_cfg.seq_writable_ports = i_configure_read_seq_ports_default( alsaversion );
+    amidiplug_cfg.mixer_card_id = 0;
+    amidiplug_cfg.mixer_control_name = g_strdup( "Synth" );
+    amidiplug_cfg.mixer_control_id = 0;
+  }
+  else
+  {
+    if ( !xmms_cfg_read_string( cfgfile , "amidi-plug" , "writable_ports" , &amidiplug_cfg.seq_writable_ports ) )
+      amidiplug_cfg.seq_writable_ports = i_configure_read_seq_ports_default( alsaversion ); /* default value */
+
+    if ( !xmms_cfg_read_int( cfgfile , "amidi-plug" , "mixer_card_id" , &amidiplug_cfg.mixer_card_id ) )
+      amidiplug_cfg.mixer_card_id = 0; /* default value */
+
+    if ( !xmms_cfg_read_string( cfgfile , "amidi-plug" , "mixer_control_name" , &amidiplug_cfg.mixer_control_name ) )
+      amidiplug_cfg.mixer_control_name = g_strdup( "Synth" ); /* default value */
+
+    if ( !xmms_cfg_read_int( cfgfile , "amidi-plug" , "mixer_control_id" , &amidiplug_cfg.mixer_control_id ) )
+      amidiplug_cfg.mixer_control_id = 0; /* default value */
+
+    xmms_cfg_free(cfgfile);
+  }
+}
+
+
+void i_configure_cfg_save( void )
+{
+  ConfigFile *cfgfile;
+  cfgfile = xmms_cfg_open_default_file();
+
+  if (!cfgfile)
+    cfgfile = xmms_cfg_new();
+
+  xmms_cfg_write_string( cfgfile , "amidi-plug" , "writable_ports" , amidiplug_cfg.seq_writable_ports );
+  xmms_cfg_write_int( cfgfile , "amidi-plug" , "mixer_card_id" , amidiplug_cfg.mixer_card_id );
+  xmms_cfg_write_string( cfgfile , "amidi-plug" , "mixer_control_name" , amidiplug_cfg.mixer_control_name );
+  xmms_cfg_write_int( cfgfile , "amidi-plug" , "mixer_control_id" , amidiplug_cfg.mixer_control_id );
+
+  xmms_cfg_write_default_file(cfgfile);
+  xmms_cfg_free(cfgfile);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_configure.h	Thu Jan 26 18:43:59 2006 -0800
@@ -0,0 +1,78 @@
+/*
+*
+* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+*
+*/
+
+#ifndef _I_CONFIGURE_H
+#define _I_CONFIGURE_H 1
+
+#include "i_common.h"
+#include <gtk/gtk.h>
+#include <audacious/configfile.h>
+
+
+enum
+{
+  LISTPORT_TOGGLE_COLUMN,
+  LISTPORT_PORTNUM_COLUMN,
+  LISTPORT_CLIENTNAME_COLUMN,
+  LISTPORT_PORTNAME_COLUMN,
+  LISTPORT_POINTER_COLUMN,
+  LISTPORT_N_COLUMNS
+};
+
+enum
+{
+  LISTMIXER_DESC_COLUMN,
+  LISTMIXER_CARDID_COLUMN,
+  LISTMIXER_MIXCTLID_COLUMN,
+  LISTMIXER_MIXCTLNAME_COLUMN,
+  LISTMIXER_N_COLUMNS
+};
+
+typedef struct
+{
+  gchar * seq_writable_ports;
+  gint mixer_card_id;
+  gchar * mixer_control_name;
+  gint mixer_control_id;
+}
+amidiplug_cfg_t;
+
+extern amidiplug_cfg_t amidiplug_cfg;
+
+typedef struct
+{
+  GtkWidget * config_win;
+  GtkWidget * port_treeview;
+  GtkWidget * mixercard_combo;
+  GtkTooltips * config_tips;
+}
+amidiplug_gui_prefs_t;
+
+static amidiplug_gui_prefs_t amidiplug_gui_prefs = { NULL , NULL , NULL , NULL };
+
+void i_configure_gui( GSList * , GSList * );
+void i_configure_ev_destroy( void );
+void i_configure_ev_bcancel( void );
+void i_configure_ev_bok( void );
+void i_configure_cfg_save( void );
+void i_configure_cfg_read( gchar * );
+
+
+#endif /* !_I_CONFIGURE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_fileinfo.c	Thu Jan 26 18:43:59 2006 -0800
@@ -0,0 +1,254 @@
+/*
+*
+* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+*
+*/
+
+
+#include "i_fileinfo.h"
+/* this is needed to retrieve information */
+#include "i_midi.h"
+/* icon from gnome-mime-audio-midi.png of the GNOME ICON SET */
+#include "amidi-plug.midiicon.xpm"
+
+static amidiplug_gui_fileinfo_t amidiplug_gui_fileinfo = { NULL };
+
+
+gint i_fileinfo_midiparse( gchar * filename , midifile_t * mf )
+{
+  i_midi_init( mf );
+  DEBUGMSG( "FILEINFO requested, opening file: %s\n" , filename );
+  mf->file_pointer = fopen( filename , "rb" );
+  if (!mf->file_pointer)
+  {
+    g_warning( "Cannot open %s\n" , filename );
+    return 0;
+  }
+  mf->file_name = filename;
+
+  switch( i_midi_file_read_id( mf ) )
+  {
+    case MAKE_ID('R', 'I', 'F', 'F'):
+    {
+      DEBUGMSG( "FILEINFO requested, RIFF chunk found, processing...\n" );
+      /* read riff chunk */
+      if ( !i_midi_file_parse_riff( mf ) )
+        WARNANDBREAK( "%s: invalid file format (riff parser)\n" , filename );
+
+      /* if that was read correctly, go ahead and read smf data */
+    }
+
+    case MAKE_ID('M', 'T', 'h', 'd'):
+    {
+      DEBUGMSG( "FILEINFO requested, MThd chunk found, processing...\n" );
+      /* we don't care about port count here, pass 1 */
+      if ( !i_midi_file_parse_smf( mf , 1 ) )
+        WARNANDBREAK( "%s: invalid file format (smf parser)\n" , filename );
+
+      if ( mf->time_division < 1 )
+        WARNANDBREAK( "%s: invalid time division (%i)\n" , filename , mf->time_division );
+
+      /* fill mf->ppq and mf->tempo using time_division */
+      if ( !i_midi_setget_tempo( mf ) )
+        WARNANDBREAK( "%s: invalid values while setting ppq and tempo\n" , filename );
+
+      /* fill mf->length, keeping in count tempo-changes */
+      i_midi_setget_length( mf );
+
+      /* ok, mf has been filled with information; successfully return */
+      fclose( mf->file_pointer );
+      return 1;
+    }
+
+    default:
+    {
+      g_warning( "%s is not a Standard MIDI File\n" , filename );
+      break;
+    }
+  }
+
+  /* something failed */
+  fclose( mf->file_pointer );
+  return 0;
+}
+
+
+void i_fileinfo_ev_destroy( void )
+{
+  amidiplug_gui_fileinfo.fileinfo_win = NULL;
+}
+
+
+void i_fileinfo_ev_close( void )
+{
+  gtk_widget_destroy( amidiplug_gui_fileinfo.fileinfo_win );
+}
+
+
+void i_fileinfo_table_add_entry( gchar * field_text , gchar * value_text ,
+                                 GtkWidget * table , guint line , PangoAttrList * attrlist )
+{
+  GtkWidget *field, *value;
+  field = gtk_label_new( field_text );
+  gtk_label_set_attributes( GTK_LABEL(field) , attrlist );
+  gtk_misc_set_alignment( GTK_MISC(field) , 0 , 0 );
+  gtk_label_set_justify( GTK_LABEL(field) , GTK_JUSTIFY_LEFT );
+  gtk_table_attach( GTK_TABLE(table) , field , 0 , 1 , line , (line + 1) ,
+                    GTK_FILL , GTK_FILL , 5 , 2 );
+  value = gtk_label_new( value_text );
+  gtk_misc_set_alignment( GTK_MISC(value) , 0 , 0 );
+  gtk_label_set_justify( GTK_LABEL(value) , GTK_JUSTIFY_LEFT );
+  gtk_table_attach( GTK_TABLE(table) , value , 1 , 2 , line , (line + 1) ,
+                    GTK_FILL , GTK_FILL , 5 , 2 );
+  return;
+}
+
+
+void i_fileinfo_gui( gchar * filename )
+{
+  GtkWidget *fileinfowin_vbox;
+  GtkWidget *title_hbox , *title_icon_image , *title_name_f_label , *title_name_v_entry;
+  GtkWidget *info_frame , *info_table;
+  GtkWidget *footer_hbbox, *footer_bclose;
+  GdkPixbuf *title_icon_pixbuf;
+  PangoAttrList *pangoattrlist;
+  PangoAttribute *pangoattr;
+  GString *value_gstring;
+  gchar *title , *filename_utf8;
+  gint bpm = 0, wavg_bpm = 0;
+  midifile_t mf;
+
+  if ( amidiplug_gui_fileinfo.fileinfo_win )
+    return;
+
+  /****************** midifile parser ******************/
+  if ( !i_fileinfo_midiparse( filename , &mf ) )
+    return;
+  /* midifile is filled with information at this point,
+     bpm information is needed too */
+  i_midi_get_bpm( &mf , &bpm , &wavg_bpm );
+  /*****************************************************/
+
+  amidiplug_gui_fileinfo.fileinfo_win = gtk_window_new( GTK_WINDOW_TOPLEVEL );
+  gtk_window_set_type_hint( GTK_WINDOW(amidiplug_gui_fileinfo.fileinfo_win), GDK_WINDOW_TYPE_HINT_DIALOG );
+  gtk_window_set_resizable( GTK_WINDOW(amidiplug_gui_fileinfo.fileinfo_win) , FALSE );
+  gtk_window_set_position( GTK_WINDOW(amidiplug_gui_fileinfo.fileinfo_win) , GTK_WIN_POS_CENTER );
+  g_signal_connect( G_OBJECT(amidiplug_gui_fileinfo.fileinfo_win) ,
+                    "destroy" , G_CALLBACK(i_fileinfo_ev_destroy) , NULL );
+  gtk_container_set_border_width( GTK_CONTAINER(amidiplug_gui_fileinfo.fileinfo_win), 10 );
+
+  fileinfowin_vbox = gtk_vbox_new( FALSE , 10 );
+  gtk_container_add( GTK_CONTAINER(amidiplug_gui_fileinfo.fileinfo_win) , fileinfowin_vbox );
+
+  /* pango attributes */
+  pangoattrlist = pango_attr_list_new();
+  pangoattr = pango_attr_weight_new( PANGO_WEIGHT_BOLD );
+  pangoattr->start_index = 0;
+  pangoattr->end_index = G_MAXINT;
+  pango_attr_list_insert( pangoattrlist , pangoattr );
+
+  /******************
+   *** TITLE LINE ***/
+  title_hbox = gtk_hbox_new( FALSE , 5 );
+  gtk_box_pack_start( GTK_BOX(fileinfowin_vbox) , title_hbox , FALSE , FALSE , 0 );
+
+  title_icon_pixbuf = gdk_pixbuf_new_from_xpm_data( (const gchar **)amidiplug_xpm_midiicon );
+  title_icon_image = gtk_image_new_from_pixbuf( title_icon_pixbuf );
+  g_object_unref( title_icon_pixbuf );
+  gtk_misc_set_alignment( GTK_MISC(title_icon_image) , 0 , 0 );
+  gtk_box_pack_start( GTK_BOX(title_hbox) , title_icon_image , FALSE , FALSE , 0 );
+
+  title_name_f_label = gtk_label_new( _("Name:") );
+  gtk_label_set_attributes( GTK_LABEL(title_name_f_label) , pangoattrlist );
+  gtk_box_pack_start( GTK_BOX(title_hbox) , title_name_f_label , FALSE , FALSE , 0 );
+
+  title_name_v_entry = gtk_entry_new();
+  gtk_editable_set_editable( GTK_EDITABLE(title_name_v_entry) , FALSE );
+  gtk_widget_set_size_request( GTK_WIDGET(title_name_v_entry) , 200 , -1 );
+  gtk_box_pack_start(GTK_BOX(title_hbox) , title_name_v_entry , TRUE , TRUE , 0 );
+
+  /*********************
+   *** MIDI INFO BOX ***/
+  info_frame = gtk_frame_new( _(" MIDI Info ") );
+  gtk_box_pack_start( GTK_BOX(fileinfowin_vbox) , info_frame , TRUE , TRUE , 0 );
+  info_table = gtk_table_new( 6 , 2 , FALSE );
+  gtk_container_set_border_width( GTK_CONTAINER(info_table) , 5 );
+  gtk_container_add( GTK_CONTAINER(info_frame) , info_table );
+  value_gstring = g_string_new( "" );
+
+  /* midi format */
+  G_STRING_PRINTF( value_gstring , "type %i" , mf.format );
+  i_fileinfo_table_add_entry( _("Format:") , value_gstring->str , info_table , 0 , pangoattrlist );
+  /* midi length */
+  G_STRING_PRINTF( value_gstring , "%i" , (gint)(mf.length / 1000) );
+  i_fileinfo_table_add_entry( _("Length (msec):") , value_gstring->str , info_table , 1 , pangoattrlist );
+  /* midi num of tracks */
+  G_STRING_PRINTF( value_gstring , "%i" , mf.num_tracks );
+  i_fileinfo_table_add_entry( _("Num of Tracks:") , value_gstring->str , info_table , 2 , pangoattrlist );
+  /* midi bpm */
+  if ( bpm > 0 )
+    G_STRING_PRINTF( value_gstring , "%i" , bpm ); /* fixed bpm */
+  else
+    G_STRING_PRINTF( value_gstring , _("variable") ); /* variable bpm */
+  i_fileinfo_table_add_entry( _("BPM:") , value_gstring->str , info_table , 3 , pangoattrlist );
+  /* midi weighted average bpm */
+  if ( bpm > 0 )
+    G_STRING_PRINTF( value_gstring , "/" ); /* fixed bpm, don't care about wavg_bpm */
+  else
+    G_STRING_PRINTF( value_gstring , "%i" , wavg_bpm ); /* variable bpm, display wavg_bpm */
+  i_fileinfo_table_add_entry( _("BPM (wavg):") , value_gstring->str , info_table , 4 , pangoattrlist );
+  /* midi time division */
+  G_STRING_PRINTF( value_gstring , "%i" , mf.time_division );
+  i_fileinfo_table_add_entry( _("Time Div:") , value_gstring->str , info_table , 5 , pangoattrlist );
+
+  g_string_free( value_gstring , TRUE );
+
+  /**************
+   *** FOOTER ***/
+  footer_hbbox = gtk_hbutton_box_new();
+  gtk_button_box_set_layout( GTK_BUTTON_BOX(footer_hbbox) , GTK_BUTTONBOX_END );
+  footer_bclose = gtk_button_new_from_stock( GTK_STOCK_CLOSE );
+  g_signal_connect( G_OBJECT(footer_bclose) , "clicked" , G_CALLBACK(i_fileinfo_ev_close) , NULL );
+  gtk_container_add( GTK_CONTAINER(footer_hbbox) , footer_bclose );
+  gtk_box_pack_start( GTK_BOX(fileinfowin_vbox) , footer_hbbox , FALSE , FALSE , 0 );
+
+
+  /* utf8-ize filename and set window title */
+  filename_utf8 = g_strdup(g_filename_to_utf8( filename , -1 , NULL , NULL , NULL ));
+  if ( !filename_utf8 )
+  {
+    /* utf8 fallback */
+    gchar *chr , *convert_str = g_strdup( filename );
+    for ( chr = convert_str ; *chr ; chr++ )
+    {
+      if ( *chr & 0x80 )
+        *chr = '?';
+    }
+    filename_utf8 = g_strconcat( convert_str , _("  (invalid UTF-8)") , NULL );
+    g_free(convert_str);
+  }
+  title = g_strdup_printf( "%s - " PLAYER_NAME , g_basename(filename_utf8));
+  gtk_window_set_title( GTK_WINDOW(amidiplug_gui_fileinfo.fileinfo_win) , title);
+  g_free(title);
+  /* set the text for the filename header too */
+  gtk_entry_set_text( GTK_ENTRY(title_name_v_entry) , filename_utf8 );
+  gtk_editable_set_position( GTK_EDITABLE(title_name_v_entry) , -1 );
+  g_free(filename_utf8);
+
+  gtk_widget_grab_focus( GTK_WIDGET(footer_bclose) );
+  gtk_widget_show_all( amidiplug_gui_fileinfo.fileinfo_win );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_fileinfo.h	Thu Jan 26 18:43:59 2006 -0800
@@ -0,0 +1,38 @@
+/*
+*
+* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+*
+*/
+
+#ifndef _I_FILEINFO_H
+#define _I_FILEINFO_H 1
+
+#include "i_common.h"
+#include <gtk/gtk.h>
+#include <audacious/util.h>
+
+
+typedef struct
+{
+  GtkWidget * fileinfo_win;
+}
+amidiplug_gui_fileinfo_t;
+
+void i_fileinfo_gui( gchar * );
+
+
+#endif /* !_I_FILEINFO_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_midi.c	Thu Jan 26 18:43:59 2006 -0800
@@ -0,0 +1,671 @@
+/*
+*
+* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006
+*
+* MIDI (SMF) parser based on aplaymidi.c from ALSA-utils
+* aplaymidi.c is Copyright (c) 2004 Clemens Ladisch <clemens@ladisch.de>
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+*
+*/
+
+
+#include "i_midi.h"
+
+#define ERRMSG_MIDITRACK() { g_warning( "%s: invalid MIDI data (offset %#x)" , mf->file_name , mf->file_offset ); return 0; }
+
+
+/* skip a certain number of bytes */
+void i_midi_file_skip_bytes( midifile_t * mf , gint bytes )
+{
+  while (bytes > 0)
+  {
+    i_midi_file_read_byte(mf);
+    --bytes;
+  }
+}
+
+
+/* reads a single byte */
+gint i_midi_file_read_byte( midifile_t * mf )
+{
+  ++mf->file_offset;
+  return getc(mf->file_pointer);
+}
+
+
+/* reads a little-endian 32-bit integer */
+gint i_midi_file_read_32_le( midifile_t * mf )
+{
+  gint value;
+  value = i_midi_file_read_byte(mf);
+  value |= i_midi_file_read_byte(mf) << 8;
+  value |= i_midi_file_read_byte(mf) << 16;
+  value |= i_midi_file_read_byte(mf) << 24;
+  return !feof(mf->file_pointer) ? value : -1;
+}
+
+
+/* reads a 4-character identifier */
+gint i_midi_file_read_id( midifile_t * mf )
+{
+  return i_midi_file_read_32_le(mf);
+}
+
+
+/* reads a fixed-size big-endian number */
+gint i_midi_file_read_int( midifile_t * mf , gint bytes )
+{
+  gint c, value = 0;
+
+  do {
+    c = i_midi_file_read_byte(mf);
+    if (c == EOF) return -1;
+    value = (value << 8) | c;
+  } while (--bytes);
+
+  return value;
+}
+
+
+/* reads a variable-length number */
+gint i_midi_file_read_var( midifile_t * mf )
+{
+  gint value, c;
+
+  c = i_midi_file_read_byte(mf);
+  value = c & 0x7f;
+  if (c & 0x80) {
+    c = i_midi_file_read_byte(mf);
+    value = (value << 7) | (c & 0x7f);
+    if (c & 0x80) {
+      c = i_midi_file_read_byte(mf);
+      value = (value << 7) | (c & 0x7f);
+      if (c & 0x80) {
+        c = i_midi_file_read_byte(mf);
+        value = (value << 7) | c;
+        if (c & 0x80)
+          return -1;
+      }
+    }
+  }
+  return !feof(mf->file_pointer) ? value : -1;
+}
+
+
+/* allocates a new event */
+midievent_t * i_midi_file_new_event(midifile_track_t * track, gint sysex_length)
+{
+  midievent_t * event;
+
+  event = malloc(sizeof(midievent_t) + sysex_length);
+  /* check_mem(event); */
+
+  event->next = NULL;
+
+  /* append at the end of the track's linked list */
+  if (track->current_event)
+    track->current_event->next = event;
+  else
+    track->first_event = event;
+  track->current_event = event;
+
+  return event;
+}
+
+
+/* reads one complete track from the file */
+gint i_midi_file_read_track( midifile_t * mf , midifile_track_t * track ,
+                             gint track_end , gint port_count )
+{
+  gint tick = 0;
+  guchar last_cmd = 0;
+  guchar port = 0;
+
+  /* the current file position is after the track ID and length */
+  while ( mf->file_offset < track_end )
+  {
+    guchar cmd;
+    midievent_t *event;
+    gint delta_ticks, len, c;
+
+    delta_ticks = i_midi_file_read_var(mf);
+    if ( delta_ticks < 0 )
+      break;
+    tick += delta_ticks;
+
+    c = i_midi_file_read_byte(mf);
+    if (c < 0)
+      break;
+
+    if (c & 0x80) {
+      /* have command */
+      cmd = c;
+      if (cmd < 0xf0)
+        last_cmd = cmd;
+    } else {
+      /* running status */
+      ungetc(c, mf->file_pointer);
+      mf->file_offset--;
+      cmd = last_cmd;
+      if (!cmd)
+        ERRMSG_MIDITRACK();
+    }
+
+    switch (cmd >> 4)
+    {
+      /* maps SMF events to ALSA sequencer events */
+      static guchar cmd_type[] = {
+        [0x8] = SND_SEQ_EVENT_NOTEOFF,
+        [0x9] = SND_SEQ_EVENT_NOTEON,
+        [0xa] = SND_SEQ_EVENT_KEYPRESS,
+        [0xb] = SND_SEQ_EVENT_CONTROLLER,
+        [0xc] = SND_SEQ_EVENT_PGMCHANGE,
+        [0xd] = SND_SEQ_EVENT_CHANPRESS,
+        [0xe] = SND_SEQ_EVENT_PITCHBEND
+      };
+
+      case 0x8: /* channel msg with 2 parameter bytes */
+      case 0x9:
+      case 0xa:
+      case 0xb:
+      case 0xe:
+      {
+        event = i_midi_file_new_event(track, 0);
+        event->type = cmd_type[cmd >> 4];
+        event->port = port;
+        event->tick = tick;
+        event->data.d[0] = cmd & 0x0f;
+        event->data.d[1] = i_midi_file_read_byte(mf) & 0x7f;
+        event->data.d[2] = i_midi_file_read_byte(mf) & 0x7f;
+      }
+      break;
+
+      case 0xc: /* channel msg with 1 parameter byte */
+      case 0xd:
+      {
+        event = i_midi_file_new_event(track, 0);
+        event->type = cmd_type[cmd >> 4];
+        event->port = port;
+        event->tick = tick;
+        event->data.d[0] = cmd & 0x0f;
+        event->data.d[1] = i_midi_file_read_byte(mf) & 0x7f;
+      }
+      break;
+
+      case 0xf:
+      {
+        switch (cmd)
+        {
+          case 0xf0: /* sysex */
+          case 0xf7: /* continued sysex, or escaped commands */
+          {
+            len = i_midi_file_read_var(mf);
+            if (len < 0)
+              ERRMSG_MIDITRACK();
+            if (cmd == 0xf0)
+              ++len;
+            event = i_midi_file_new_event(track, len);
+            event->type = SND_SEQ_EVENT_SYSEX;
+            event->port = port;
+            event->tick = tick;
+            event->data.length = len;
+            if (cmd == 0xf0) {
+              event->sysex[0] = 0xf0;
+              c = 1;
+            } else {
+              c = 0;
+            }
+            for (; c < len; ++c)
+              event->sysex[c] = i_midi_file_read_byte(mf);
+          }
+          break;
+
+          case 0xff: /* meta event */
+          {
+            c = i_midi_file_read_byte(mf);
+            len = i_midi_file_read_var(mf);
+            if (len < 0)
+              ERRMSG_MIDITRACK();
+
+            switch (c)
+            {
+              case 0x21: /* port number */
+              {
+                if (len < 1)
+                  ERRMSG_MIDITRACK();
+                port = i_midi_file_read_byte(mf) % port_count;
+                i_midi_file_skip_bytes(mf,(len - 1));
+              }
+              break;
+
+              case 0x2f: /* end of track */
+              {
+                track->end_tick = tick;
+                i_midi_file_skip_bytes(mf,(track_end - mf->file_offset));
+                return 1;
+              }
+
+              case 0x51: /* tempo */
+              {
+                if (len < 3)
+                  ERRMSG_MIDITRACK();
+                if (mf->smpte_timing) {
+                  /* SMPTE timing doesn't change */
+                  i_midi_file_skip_bytes(mf,len);
+                } else {
+                  event = i_midi_file_new_event(track, 0);
+                  event->type = SND_SEQ_EVENT_TEMPO;
+                  event->port = port;
+                  event->tick = tick;
+                  event->data.tempo = i_midi_file_read_byte(mf) << 16;
+                  event->data.tempo |= i_midi_file_read_byte(mf) << 8;
+                  event->data.tempo |= i_midi_file_read_byte(mf);
+                  i_midi_file_skip_bytes(mf,(len - 3));
+                }
+              }
+              break;
+
+              default: /* ignore all other meta events */
+              {
+                i_midi_file_skip_bytes(mf,len);
+              }
+              break;
+            }
+          }
+          break;
+
+          default: /* invalid Fx command */
+            ERRMSG_MIDITRACK();
+        }
+      }
+      break;
+
+      default: /* cannot happen */
+        ERRMSG_MIDITRACK();
+    }
+  }
+  ERRMSG_MIDITRACK();
+}
+
+
+/* read a MIDI file in Standard MIDI Format */
+/* return values: 0 = error , 1 = ok */
+gint i_midi_file_parse_smf( midifile_t * mf , gint port_count )
+{
+  gint header_len, i;
+
+  /* the curren position is immediately after the "MThd" id */
+  header_len = i_midi_file_read_int(mf,4);
+  if ( header_len < 6 )
+  {
+    g_warning( "%s: invalid file format\n" , mf->file_name );
+    return 0;
+  }
+
+  mf->format = i_midi_file_read_int(mf,2);
+  if (( mf->format != 0 ) && ( mf->format != 1 ))
+  {
+    g_warning( "%s: type %d format is not supported\n" , mf->file_name , mf->format);
+    return 0;
+  }
+
+  mf->num_tracks = i_midi_file_read_int(mf,2);
+  if (( mf->num_tracks < 1 ) || ( mf->num_tracks > 1000 ))
+  {
+    g_warning( "%s: invalid number of tracks (%d)\n" , mf->file_name , mf->num_tracks );
+    mf->num_tracks = 0;
+    return 0;
+  }
+
+  mf->tracks = calloc( mf->num_tracks , sizeof(midifile_track_t) );
+  if ( !mf->tracks )
+  {
+    g_warning( "out of memory\n" );
+    mf->num_tracks = 0;
+    return 0;
+  }
+
+  mf->time_division = i_midi_file_read_int(mf,2);
+  if ( mf->time_division < 0 )
+  {
+    g_warning( "%s: invalid file format\n" , mf->file_name );
+    return 0;
+  }
+
+  mf->smpte_timing = !!(mf->time_division & 0x8000);
+
+  /* read tracks */
+  for ( i = 0 ; i < mf->num_tracks ; ++i )
+  {
+    gint len;
+
+    /* search for MTrk chunk */
+    for (;;)
+    {
+      gint id = i_midi_file_read_id(mf);
+      len = i_midi_file_read_int(mf,4);
+      if ( feof(mf->file_pointer) )
+      {
+        g_warning( "%s: unexpected end of file\n" , mf->file_name );
+        return 0;
+      }
+      if (( len < 0 ) || ( len >= 0x10000000))
+      {
+        g_warning( "%s: invalid chunk length %d\n" , mf->file_name , len );
+        return 0;
+      }
+      if ( id == MAKE_ID('M', 'T', 'r', 'k') )
+        break;
+      i_midi_file_skip_bytes(mf,len);
+    }
+
+    if ( !i_midi_file_read_track( mf , &mf->tracks[i] , mf->file_offset + len , port_count ) )
+      return 0;
+  }
+
+  /* calculate the max_tick for the entire file */
+  mf->max_tick = 0;
+  for ( i = 0 ; i < mf->num_tracks ; ++i )
+  {
+    if ( mf->tracks[i].end_tick > mf->max_tick )
+      mf->max_tick = mf->tracks[i].end_tick;
+  }
+
+  /* ok, success */
+  return 1;
+}
+
+
+/* read a MIDI file enclosed in RIFF format */
+/* return values: 0 = error , 1 = ok */
+gint i_midi_file_parse_riff( midifile_t * mf )
+{
+  /* skip file length (4 bytes) */
+  i_midi_file_skip_bytes(mf,4);
+
+  /* check file type ("RMID" = RIFF MIDI) */
+  if ( i_midi_file_read_id(mf) != MAKE_ID('R', 'M', 'I', 'D') )
+    return 0;
+
+  /* search for "data" chunk */
+  for (;;)
+  {
+    gint id = i_midi_file_read_id(mf);
+    gint len = i_midi_file_read_32_le(mf);
+
+    if ( feof(mf->file_pointer) )
+      return 0;
+
+    if ( id == MAKE_ID('d', 'a', 't', 'a') )
+      break;
+
+    if (len < 0)
+      return 0;
+
+    i_midi_file_skip_bytes(mf,((len + 1) & ~1));
+  }
+
+  /* the "data" chunk must contain data in SMF format */
+  if ( i_midi_file_read_id(mf) != MAKE_ID('M', 'T', 'h', 'd') )
+    return 0;
+
+  /* ok, success */
+  return 1;
+}
+
+
+/* midifile init */
+void i_midi_init( midifile_t * mf )
+{
+  mf->file_pointer = NULL;
+  mf->file_name = NULL;
+  mf->file_offset = 0;
+  mf->num_tracks = 0;
+  mf->tracks = NULL;
+  mf->max_tick = 0;
+  mf->smpte_timing = 0;
+  mf->format = 0;
+  mf->time_division = 0;
+  mf->ppq = 0;
+  mf->current_tempo = 0;
+  mf->playing_tick = 0;
+  mf->avg_microsec_per_tick = 0;
+  mf->length = 0;
+  mf->skip_offset = 0;
+  return;
+}
+
+
+void i_midi_free( midifile_t * mf )
+{
+  if ( mf->tracks )
+  {
+    gint i;
+    /* free event list for each track */
+    for ( i = 0 ; i < mf->num_tracks ; ++i )
+    {
+      midievent_t * event = mf->tracks[i].first_event;
+      midievent_t * event_tmp = NULL;
+      while( event )
+      {
+        event_tmp = event;
+        event = event->next;
+        free( event_tmp );
+      }
+    }
+    /* free track array */
+    free( mf->tracks );
+    mf->tracks = NULL;
+  }
+}
+
+
+/* queue set tempo */
+gint i_midi_setget_tempo( midifile_t * mf )
+{
+  gint smpte_timing , i = 0;
+  gint time_division = mf->time_division;
+
+  /* interpret and set tempo */
+  smpte_timing = !!(time_division & 0x8000);
+  if (!smpte_timing)
+  {
+    /* time_division is ticks per quarter */
+    mf->current_tempo = 500000;
+    mf->ppq = time_division;
+  }
+  else
+  {
+    /* upper byte is negative frames per second */
+    i = 0x80 - ((time_division >> 8) & 0x7f);
+    /* lower byte is ticks per frame */
+    time_division &= 0xff;
+    /* now pretend that we have quarter-note based timing */
+    switch (i)
+    {
+      case 24:
+        mf->current_tempo = 500000;
+        mf->ppq = 12 * time_division;
+        break;
+      case 25:
+        mf->current_tempo = 400000;
+        mf->ppq = 10 * time_division;
+        break;
+      case 29: /* 30 drop-frame */
+        mf->current_tempo = 100000000;
+        mf->ppq = 2997 * time_division;
+        break;
+      case 30:
+        mf->current_tempo = 500000;
+        mf->ppq = 15 * time_division;
+        break;
+      default:
+        g_warning("Invalid number of SMPTE frames per second (%d)\n", i);
+        return 0;
+    }
+  }
+  DEBUGMSG( "MIDI tempo set -> time division: %i\n" , midifile.time_division );
+  DEBUGMSG( "MIDI tempo set -> tempo: %i\n" , midifile.current_tempo );
+  DEBUGMSG( "MIDI tempo set -> ppq: %i\n" , midifile.ppq );
+  return 1;
+}
+
+
+/* this will set the midi length in microseconds
+   COMMENT: this will also reset current position in each track! */
+void i_midi_setget_length( midifile_t * mf )
+{
+  gint length_microsec = 0, last_tick = 0, i = 0;
+  /* get the first microsec_per_tick ratio */
+  gint microsec_per_tick = (gint)(mf->current_tempo / mf->ppq);
+
+  /* initialize current position in each track */
+  for (i = 0; i < mf->num_tracks; ++i)
+    mf->tracks[i].current_event = mf->tracks[i].first_event;
+
+  /* search for tempo events in each track; in fact, since the program
+     currently supports type 0 and type 1 MIDI files, we should find
+     tempo events only in one track */
+  DEBUGMSG( "LENGTH calc: starting calc loop\n" );
+  for (;;)
+  {
+    midievent_t * event = NULL;
+    midifile_track_t * event_track = NULL;
+    gint i, min_tick = mf->max_tick + 1;
+
+    /* search next event */
+    for ( i = 0 ; i < mf->num_tracks ; ++i )
+    {
+      midifile_track_t * track = &mf->tracks[i];
+      midievent_t * e2 = track->current_event;
+      if (e2 && e2->tick < min_tick)
+      {
+        min_tick = e2->tick;
+        event = e2;
+        event_track = track;
+      }
+    }
+
+    if (!event)
+    {
+      /* calculate the remaining length */
+      length_microsec += ( microsec_per_tick * ( mf->max_tick - last_tick ) );
+      break; /* end of song reached */
+    }
+
+    /* advance pointer to next event */
+    event_track->current_event = event->next;
+
+    /* check if this is a tempo event */
+    if ( event->type == SND_SEQ_EVENT_TEMPO )
+    {
+      DEBUGMSG( "LENGTH calc: tempo event (%i) encountered during calc on tick %i\n" ,
+                event->data.tempo , event->tick );
+      /* increment length_microsec with the amount of microsec before tempo change */
+      length_microsec += ( microsec_per_tick * ( event->tick - last_tick ) );
+      /* now update last_tick and the microsec_per_tick ratio */
+      last_tick = event->tick;
+      microsec_per_tick = (gint)(event->data.tempo / mf->ppq);
+    }
+  }
+
+  /* IMPORTANT
+     this couple of important values is set by i_midi_set_length */
+  mf->length = length_microsec;
+  mf->avg_microsec_per_tick = (gint)(length_microsec / mf->max_tick);
+
+  return;
+}
+
+
+/* this will get the weighted average bpm of the midi file;
+   if the file has a variable bpm, 'bpm' is set to -1;
+   COMMENT: this will also reset current position in each track! */
+void i_midi_get_bpm( midifile_t * mf , gint * bpm , gint * wavg_bpm )
+{
+  gint i = 0 , last_tick = 0;
+  guint weighted_avg_tempo = 0;
+  gboolean is_monotempo = TRUE;
+  gint last_tempo = mf->current_tempo;
+
+  /* initialize current position in each track */
+  for ( i = 0 ; i < mf->num_tracks ; ++i )
+    mf->tracks[i].current_event = mf->tracks[i].first_event;
+
+  /* search for tempo events in each track; in fact, since the program
+     currently supports type 0 and type 1 MIDI files, we should find
+     tempo events only in one track */
+  DEBUGMSG( "BPM calc: starting calc loop\n" );
+  for (;;)
+  {
+    midievent_t * event = NULL;
+    midifile_track_t * event_track = NULL;
+    gint i, min_tick = mf->max_tick + 1;
+
+    /* search next event */
+    for ( i = 0 ; i < mf->num_tracks ; ++i )
+    {
+      midifile_track_t * track = &mf->tracks[i];
+      midievent_t * e2 = track->current_event;
+      if (e2 && e2->tick < min_tick)
+      {
+        min_tick = e2->tick;
+        event = e2;
+        event_track = track;
+      }
+    }
+
+    if (!event)
+    {
+      /* calculate the remaining length */
+      weighted_avg_tempo += (guint)( last_tempo * ((gfloat)( mf->max_tick - last_tick ) / (gfloat)mf->max_tick ) );
+      break; /* end of song reached */
+    }
+
+    /* advance pointer to next event */
+    event_track->current_event = event->next;
+
+    /* check if this is a tempo event */
+    if ( event->type == SND_SEQ_EVENT_TEMPO )
+    {
+      /* check if this is a tempo change (real change, tempo should be
+         different) in the midi file (and it shouldn't be at tick 0); */
+      if (( is_monotempo ) && ( event->tick > 0 ) && ( event->data.tempo != last_tempo ))
+        is_monotempo = FALSE;
+
+      DEBUGMSG( "BPM calc: tempo event (%i) encountered during calc on tick %i\n" ,
+                event->data.tempo , event->tick );
+      /* add the previous tempo change multiplied for its weight (the tick interval for the tempo )  */
+      weighted_avg_tempo += (guint)( last_tempo * ((gfloat)( event->tick - last_tick ) / (gfloat)mf->max_tick ) );
+      /* now update last_tick and the microsec_per_tick ratio */
+      last_tick = event->tick;
+      last_tempo = event->data.tempo;
+    }
+  }
+
+  DEBUGMSG( "BPM calc: weighted average tempo: %i\n" , weighted_avg_tempo );
+
+  *wavg_bpm = (gint)( 60000000 / weighted_avg_tempo );
+
+  DEBUGMSG( "BPM calc: weighted average bpm: %i\n" , *wavg_bpm );
+
+  if ( is_monotempo )
+    *bpm = *wavg_bpm; /* the song has fixed bpm */
+  else
+    *bpm = -1; /* the song has variable bpm */
+
+  return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_midi.h	Thu Jan 26 18:43:59 2006 -0800
@@ -0,0 +1,107 @@
+/*
+*
+* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+*
+*/
+
+#ifndef _I_MIDI_H
+#define _I_MIDI_H 1
+
+#include "i_common.h"
+#include <alsa/asoundlib.h>
+
+#define MAKE_ID(c1, c2, c3, c4) ((c1) | ((c2) << 8) | ((c3) << 16) | ((c4) << 24))
+
+/* MIDI event we care of */
+#define MIDI_EVENT_NOTEOFF	1
+#define MIDI_EVENT_NOTEON	2
+#define MIDI_EVENT_KEYPRESS	3
+#define MIDI_EVENT_CONTROLLER	4
+#define MIDI_EVENT_PGMCHANGE	5
+#define MIDI_EVENT_CHANPRESS	6
+#define MIDI_EVENT_PITCHBEND	7
+#define MIDI_EVENT_SYSEX	8
+#define MIDI_EVENT_TEMPO	9
+
+
+struct midievent_stru {
+  struct midievent_stru * next;		/* linked list */
+  guchar type;				/* SND_SEQ_EVENT_xxx */
+  guchar port;				/* port index */
+  guint tick;
+  union {
+    guchar d[3];			/* channel and data bytes */
+    gint tempo;
+    guint length;			/* length of sysex data */
+  } data;
+  guchar sysex[0];
+};
+
+typedef struct midievent_stru midievent_t;
+
+typedef struct
+{
+  midievent_t * first_event;	/* list of all events in this track */
+  gint end_tick;			/* length of this track */
+  midievent_t * current_event;	/* used while loading and playing */
+}
+midifile_track_t;
+
+typedef struct
+{
+  FILE * file_pointer;
+  gchar * file_name;
+  gint file_offset;
+
+  gint num_tracks;
+  midifile_track_t *tracks;
+
+  gushort format;
+  guint max_tick;
+  gint smpte_timing;
+
+  gint time_division;
+  gint ppq;
+  gint current_tempo;
+
+  gint playing_tick;
+  gint avg_microsec_per_tick;
+  gint length;
+
+  gint skip_offset;
+}
+midifile_t;
+
+extern midifile_t midifile;
+
+midievent_t * i_midi_file_new_event( midifile_track_t * , gint );
+void i_midi_file_skip_bytes( midifile_t * , gint );
+gint i_midi_file_read_byte( midifile_t * );
+gint i_midi_file_read_32_le( midifile_t * );
+gint i_midi_file_read_id( midifile_t * );
+gint i_midi_file_read_int( midifile_t * , gint );
+gint i_midi_file_read_var( midifile_t * );
+gint i_midi_file_read_track( midifile_t * , midifile_track_t * , gint , gint );
+gint i_midi_file_parse_riff( midifile_t * );
+gint i_midi_file_parse_smf( midifile_t * , gint );
+void i_midi_init( midifile_t * );
+void i_midi_free( midifile_t * );
+gint i_midi_setget_tempo( midifile_t * );
+void i_midi_setget_length( midifile_t * );
+void i_midi_get_bpm( midifile_t * , gint * , gint * );
+
+#endif /* !_I_MIDI_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_seq.c	Thu Jan 26 18:43:59 2006 -0800
@@ -0,0 +1,425 @@
+/*
+*
+* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+*
+*/
+
+
+#include "i_seq.h"
+
+
+/* activate sequencer client */
+gint i_seq_on( gshort with_wparse , gchar * wports_str )
+{
+  if ( !i_seq_open() )
+    return 0;
+
+  if ( !i_seq_port_create() )
+  {
+    i_seq_close();
+    return 0;
+  }
+
+  if ( !i_seq_queue_create() )
+  {
+    i_seq_close();
+    return 0;
+  }
+
+  if (( with_wparse > 0 ) && ( wports_str ))
+    i_seq_port_wparse( wports_str );
+
+  if ( !i_seq_port_connect() )
+  {
+    i_seq_queue_free();
+    i_seq_close();
+    return 0;
+  }
+
+  /* success */
+  return 1;
+}
+
+
+/* shutdown sequencer client */
+gint i_seq_off( void )
+{
+  if ( sc.seq )
+  {
+    i_seq_port_disconnect();
+    i_seq_queue_free();
+    i_seq_close();
+    sc.seq = NULL;
+    /* return 1 here */
+    return 1;
+  }
+  /* return 2 if it was already freed */
+  return 2;
+}
+
+
+/* create sequencer client */
+gint i_seq_open( void )
+{
+  gint err;
+  err = snd_seq_open(&sc.seq, "default", SND_SEQ_OPEN_DUPLEX, 0);
+  if (err < 0)
+    return 0;
+  snd_seq_set_client_name(sc.seq, "amidi-plug");
+  return 1;
+}
+
+
+/* free sequencer client */
+gint i_seq_close( void )
+{
+  if ( snd_seq_close( sc.seq ) < 0 )
+    return 0; /* fail */
+  else
+    return 1; /* success */
+}
+
+
+/* create queue */
+gint i_seq_queue_create( void )
+{
+  sc.queue = snd_seq_alloc_named_queue( sc.seq , "AMIDI-Plug" );
+  if ( sc.queue < 0 )
+    return 0; /* fail */
+  else
+    return 1; /* success */
+}
+
+
+/* free queue */
+gint i_seq_queue_free( void )
+{
+  if ( snd_seq_free_queue( sc.seq , sc.queue ) < 0 )
+    return 0; /* fail */
+  else
+    return 1; /* success */
+}
+
+
+/* queue set tempo */
+gint i_seq_queue_set_tempo( gint tempo , gint ppq )
+{
+  /* interpret and set tempo */
+  snd_seq_queue_tempo_alloca( &sc.queue_tempo );
+  snd_seq_queue_tempo_set_tempo( sc.queue_tempo , tempo );
+  snd_seq_queue_tempo_set_ppq( sc.queue_tempo , ppq );
+
+  if ( snd_seq_set_queue_tempo( sc.seq , sc.queue , sc.queue_tempo ) < 0 )
+  {
+    g_warning( "Cannot set queue tempo (%u/%i)\n",
+               snd_seq_queue_tempo_get_tempo(sc.queue_tempo),
+               snd_seq_queue_tempo_get_ppq(sc.queue_tempo) );
+    return 0;
+  }
+  return 1;
+}
+
+
+/* create sequencer port */
+gint i_seq_port_create( void )
+{
+  sc.client_port = snd_seq_create_simple_port( sc.seq , "AMIDI-Plug" , 0 ,
+                                               SND_SEQ_PORT_TYPE_MIDI_GENERIC |
+                                               SND_SEQ_PORT_TYPE_APPLICATION );
+  if ( sc.client_port < 0 )
+    return 0; /* fail */
+  else
+    return 1; /* success */
+}
+
+
+/* port connection */
+gint i_seq_port_connect( void )
+{
+  gint i = 0 , err = 0;
+  for ( i = 0 ; i < sc.dest_port_num ; i++ )
+  {
+    if ( snd_seq_connect_to( sc.seq , sc.client_port ,
+                             sc.dest_port[i].client ,
+                             sc.dest_port[i].port ) < 0 )
+      ++err;
+  }
+  /* if these values are equal, it means
+     that all port connections failed */
+  if ( err == i )
+    return 0; /* fail */
+  else
+    return 1; /* success */
+}
+
+
+/* port disconnection */
+gint i_seq_port_disconnect( void )
+{
+  gint i = 0 , err = 0;
+  for ( i = 0 ; i < sc.dest_port_num ; i++ )
+  {
+    if ( snd_seq_disconnect_to( sc.seq , sc.client_port ,
+                                sc.dest_port[i].client ,
+                                sc.dest_port[i].port ) < 0 )
+      ++err;
+  }
+  /* if these values are equal, it means
+     that all port disconnections failed */
+  if ( err == i )
+    return 0; /* fail */
+  else
+    return 1; /* success */
+}
+
+
+/* parse writable ports */
+gint i_seq_port_wparse( gchar * wportlist )
+{
+  gint i = 0 , err = 0;
+  gchar **portstr = g_strsplit( wportlist , "," , 0 );
+
+  sc.dest_port_num = 0;
+
+  /* fill sc.dest_port_num with the writable port number */
+  while ( portstr[sc.dest_port_num] != NULL )
+    ++sc.dest_port_num;
+
+  /* check if there is already an allocated array and free it */
+  if ( sc.dest_port )
+    free( sc.dest_port );
+
+  if ( sc.dest_port_num > 0 )
+  /* allocate the array of writable ports */
+    sc.dest_port = calloc( sc.dest_port_num , sizeof(snd_seq_addr_t) );
+
+  for ( i = 0 ; i < sc.dest_port_num ; i++ )
+  {
+    if ( snd_seq_parse_address( sc.seq , &sc.dest_port[i] , portstr[i] ) < 0 )
+      ++err;
+  }
+
+  g_strfreev( portstr );
+
+  /* if these values are equal, it means
+     that all port translations failed */
+  if ( err == i )
+    return 0; /* fail */
+  else
+    return 1; /* success */
+}
+
+
+/* get a list of writable ALSA MIDI ports
+   use the data_bucket_t here...
+   bint[0] = client id , bint[1] = port id
+   bcharp[0] = client name , bcharp[1] = port name
+   bpointer[0] = (not used) , bpointer[1] = (not used) */
+GSList * i_seq_port_get_list( void )
+{
+  snd_seq_t * pseq;
+  snd_seq_open( &pseq , "default" , SND_SEQ_OPEN_DUPLEX , 0 );
+
+  GSList * wports = NULL;
+  snd_seq_client_info_t *cinfo;
+  snd_seq_port_info_t *pinfo;
+
+  snd_seq_client_info_alloca( &cinfo );
+  snd_seq_port_info_alloca( &pinfo );
+
+  snd_seq_client_info_set_client( cinfo , -1 );
+  while ( snd_seq_query_next_client( pseq , cinfo ) >= 0 )
+  {
+    gint client = snd_seq_client_info_get_client( cinfo );
+    snd_seq_port_info_set_client( pinfo , client );
+    snd_seq_port_info_set_port( pinfo , -1 );
+    while (snd_seq_query_next_port( pseq , pinfo ) >= 0 )
+    {
+      if ((snd_seq_port_info_get_capability(pinfo)
+           & (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE))
+          == (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE))
+      {
+        data_bucket_t * portinfo = (data_bucket_t*)g_malloc(sizeof(data_bucket_t));
+        portinfo->bint[0] = snd_seq_port_info_get_client( pinfo );
+        portinfo->bint[1] = snd_seq_port_info_get_port( pinfo );
+        portinfo->bcharp[0] = g_strdup(snd_seq_client_info_get_name(cinfo));
+        portinfo->bcharp[1] = g_strdup(snd_seq_port_info_get_name(pinfo));
+        wports = g_slist_append( wports , portinfo );
+      }
+    }
+  }
+  /* snd_seq_port_info_free( pinfo );
+     snd_seq_client_info_free( cinfo ); */
+  snd_seq_close( pseq );
+  return wports;
+}
+
+
+void i_seq_port_free_list( GSList * wports )
+{
+  GSList * start = wports;
+  while ( wports != NULL )
+  {
+    data_bucket_t * portinfo = wports->data;
+    g_free( (gpointer)portinfo->bcharp[0] );
+    g_free( (gpointer)portinfo->bcharp[1] );
+    g_free( portinfo );
+    wports = wports->next;
+  }
+  g_slist_free( start );
+  return;
+}
+
+
+/* get a list of available sound cards and relative mixer controls;
+   use the data_bucket_t here...
+   bint[0] = card id , bint[1] = (not used)
+   bcharp[0] = card name , bcharp[1] = (not used)
+   bpointer[0] = list (GSList) of mixer controls on the card , bpointer[1] = (not used) */
+GSList * i_seq_card_get_list( void )
+{
+  gint soundcard_id = -1;
+  GSList * scards = NULL;
+
+  snd_card_next( &soundcard_id );
+  while ( soundcard_id > -1 )
+  {
+    /* card container */
+    data_bucket_t * cardinfo = (data_bucket_t*)g_malloc(sizeof(data_bucket_t));
+    cardinfo->bint[0] = soundcard_id;
+    /* snd_card_get_name calls strdup on its own */
+    snd_card_get_name( soundcard_id , &cardinfo->bcharp[0] );
+    /* for each sound card, get a list of available mixer controls */
+    cardinfo->bpointer[0] = i_seq_mixctl_get_list( soundcard_id );
+
+    scards = g_slist_append( scards , cardinfo );
+    snd_card_next( &soundcard_id );
+  }
+  return scards;
+}
+
+
+void i_seq_card_free_list( GSList * scards )
+{
+  GSList * start = scards;
+  while ( scards != NULL )
+  {
+    data_bucket_t * cardinfo = scards->data;
+    g_free( (gpointer)cardinfo->bcharp[0] );
+    g_free( cardinfo );
+    scards = scards->next;
+  }
+  g_slist_free( start );
+  return;
+}
+
+
+/* get a list of available mixer controls for a given sound card;
+   use the data_bucket_t here...
+   bint[0] = control id , bint[1] = (not used)
+   bcharp[0] = control name , bcharp[1] = (not used)
+   bpointer[0] = (not used) , bpointer[1] = (not used) */
+GSList * i_seq_mixctl_get_list( gint soundcard_id )
+{
+  GSList * mixctls = NULL;
+  snd_mixer_t * mixer_h;
+  snd_mixer_selem_id_t * mixer_selem_id;
+  snd_mixer_elem_t * mixer_elem;
+  gchar card[10];
+
+  snprintf( card , 8 , "hw:%i" , soundcard_id );
+  card[9] = '\0';
+
+  snd_mixer_selem_id_alloca( &mixer_selem_id );
+  snd_mixer_open( &mixer_h , 0 );
+  snd_mixer_attach( mixer_h , card );
+  snd_mixer_selem_register( mixer_h , NULL , NULL );
+  snd_mixer_load( mixer_h );
+  for ( mixer_elem = snd_mixer_first_elem( mixer_h ) ; mixer_elem ;
+        mixer_elem = snd_mixer_elem_next( mixer_elem ) )
+  {
+    data_bucket_t * mixctlinfo = (data_bucket_t*)g_malloc(sizeof(data_bucket_t));
+    snd_mixer_selem_get_id( mixer_elem , mixer_selem_id );
+    mixctlinfo->bint[0] = snd_mixer_selem_id_get_index(mixer_selem_id);
+    mixctlinfo->bcharp[0] = g_strdup(snd_mixer_selem_id_get_name(mixer_selem_id));
+    mixctls = g_slist_append( mixctls , mixctlinfo );
+  }
+  snd_mixer_close( mixer_h );
+  return mixctls;
+}
+
+
+void i_seq_mixctl_free_list( GSList * mixctls )
+{
+  GSList * start = mixctls;
+  while ( mixctls != NULL )
+  {
+    data_bucket_t * mixctlinfo = mixctls->data;
+    g_free( (gpointer)mixctlinfo->bcharp[0] );
+    g_free( mixctlinfo );
+    mixctls = mixctls->next;
+  }
+  g_slist_free( start );
+  return;
+}
+
+
+gint i_seq_mixer_set_volume( gint left_volume , gint right_volume ,
+                            gchar * mixer_card , gchar * mixer_control_name , gint mixer_control_id )
+{
+  snd_mixer_t * mixer_h;
+  snd_mixer_selem_id_t * mixer_selem_id;
+  snd_mixer_elem_t * mixer_elem;
+
+  snd_mixer_selem_id_alloca( &mixer_selem_id );
+  snd_mixer_selem_id_set_index( mixer_selem_id , mixer_control_id );
+  snd_mixer_selem_id_set_name( mixer_selem_id , mixer_control_name );
+
+  snd_mixer_open( &mixer_h , 0 );
+  snd_mixer_attach( mixer_h , mixer_card );
+  snd_mixer_selem_register( mixer_h , NULL , NULL);
+  snd_mixer_load( mixer_h );
+
+  mixer_elem = snd_mixer_find_selem( mixer_h , mixer_selem_id );
+
+  if ( ( mixer_elem ) && ( snd_mixer_selem_has_playback_volume( mixer_elem ) ) )
+  {
+    glong pv_min , pv_max , pv_range;
+
+    snd_mixer_selem_get_playback_volume_range( mixer_elem , &pv_min , &pv_max );
+    pv_range = pv_max - pv_min;
+    if ( pv_range > 0 )
+    {
+      if ( snd_mixer_selem_has_playback_channel( mixer_elem , SND_MIXER_SCHN_FRONT_LEFT ) )
+      {
+        DEBUGMSG( "SET VOLUME requested, setting left channel to %i%%\n" , left_volume );
+        snd_mixer_selem_set_playback_volume( mixer_elem , SND_MIXER_SCHN_FRONT_LEFT ,
+                                             (gint)(((gdouble)pv_range * ((gdouble)left_volume*.01)) + pv_min) );
+      }
+      if ( snd_mixer_selem_has_playback_channel( mixer_elem , SND_MIXER_SCHN_FRONT_RIGHT ) )
+      {
+        DEBUGMSG( "SET VOLUME requested, setting right channel to %i%%\n" , right_volume );
+        snd_mixer_selem_set_playback_volume( mixer_elem , SND_MIXER_SCHN_FRONT_RIGHT ,
+                                             (gint)(((gdouble)pv_range * ((gdouble)right_volume*.01)) + pv_min) );
+      }
+    }
+  }
+
+  snd_mixer_close( mixer_h );
+  /* for now, always return 1 here */
+  return 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_seq.h	Thu Jan 26 18:43:59 2006 -0800
@@ -0,0 +1,61 @@
+/*
+*
+* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+*
+*/
+
+#ifndef _I_SEQ_H
+#define _I_SEQ_H 1
+
+#include "i_common.h"
+#include <alsa/asoundlib.h>
+
+typedef struct
+{
+  snd_seq_t * seq;
+  gint client_port;
+  gint queue;
+
+  snd_seq_addr_t * dest_port;
+  gint dest_port_num;
+
+  snd_seq_queue_tempo_t * queue_tempo;
+}
+sequencer_client_t;
+
+extern sequencer_client_t sc;
+
+gint i_seq_on( gshort , gchar * );
+gint i_seq_off( void );
+gint i_seq_open( void );
+gint i_seq_close( void );
+gint i_seq_port_create( void );
+gint i_seq_port_connect( void );
+gint i_seq_port_disconnect( void );
+gint i_seq_queue_create( void );
+gint i_seq_queue_free( void );
+gint i_seq_queue_set_tempo( gint , gint );
+gint i_seq_mixer_set_volume( gint , gint , gchar * , gchar * , gint );
+gint i_seq_port_wparse( gchar * );
+GSList * i_seq_port_get_list( void );
+GSList * i_seq_card_get_list( void );
+GSList * i_seq_mixctl_get_list( gint );
+void i_seq_port_free_list( GSList * );
+void i_seq_card_free_list( GSList * );
+void i_seq_mixctl_free_list( GSList * );
+
+#endif /* !_I_SEQ_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_utils.c	Thu Jan 26 18:43:59 2006 -0800
@@ -0,0 +1,137 @@
+/*
+*
+* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+*
+*/
+
+
+#include "i_utils.h"
+#include "amidi-plug.logo.xpm"
+
+static amidiplug_gui_about_t amidiplug_gui_about = { NULL };
+
+void i_about_ev_destroy( void );
+void i_about_ev_bok( void );
+
+
+/* count the number of occurrencies of a specific character 'c'
+   in the string 'string' (it must be a null-terminated string) */
+gint i_util_str_count( gchar * string , gchar c )
+{
+  gint i = 0 , count = 0;
+  while ( string[i] != '\0' )
+  {
+    if ( string[i] == c )
+      ++count;
+    ++i;
+  }
+  return count;
+}
+
+
+void i_about_gui( void )
+{
+  GtkWidget *logoandinfo_vbox , *aboutwin_vbox;
+  GtkWidget *logo_image , *logo_frame;
+  GtkWidget *info_frame , *info_scrolledwin , *info_textview;
+  GtkWidget *hseparator , *hbuttonbox , *button_ok;
+  GtkTextBuffer *info_textbuffer;
+  GdkPixbuf *logo_pixbuf;
+
+  if ( amidiplug_gui_about.about_win )
+    return;
+
+  amidiplug_gui_about.about_win = gtk_window_new( GTK_WINDOW_TOPLEVEL );
+  gtk_window_set_type_hint( GTK_WINDOW(amidiplug_gui_about.about_win), GDK_WINDOW_TYPE_HINT_DIALOG );
+  gtk_window_set_title( GTK_WINDOW(amidiplug_gui_about.about_win), "AMIDI-Plug - about" );
+  gtk_window_set_resizable( GTK_WINDOW(amidiplug_gui_about.about_win) , FALSE );
+  gtk_container_set_border_width( GTK_CONTAINER(amidiplug_gui_about.about_win), 10 );
+  g_signal_connect( G_OBJECT(amidiplug_gui_about.about_win) ,
+                    "destroy" , G_CALLBACK(i_about_ev_destroy) , NULL );
+
+  aboutwin_vbox = gtk_vbox_new( FALSE , 0 );
+
+  logoandinfo_vbox = gtk_vbox_new( TRUE , 2 );
+  gtk_container_add( GTK_CONTAINER(amidiplug_gui_about.about_win) , aboutwin_vbox );
+
+  logo_pixbuf = gdk_pixbuf_new_from_xpm_data( (const gchar **)amidiplug_xpm_logo );
+  logo_image = gtk_image_new_from_pixbuf( logo_pixbuf );
+  g_object_unref( logo_pixbuf );
+
+  logo_frame = gtk_frame_new( NULL );
+  gtk_container_add( GTK_CONTAINER(logo_frame) , logo_image );
+  gtk_box_pack_start( GTK_BOX(logoandinfo_vbox) , logo_frame , TRUE , TRUE , 0 );
+
+  info_textview = gtk_text_view_new();
+  info_textbuffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(info_textview) );
+  gtk_text_view_set_editable( GTK_TEXT_VIEW(info_textview) , FALSE );
+  gtk_text_view_set_cursor_visible( GTK_TEXT_VIEW(info_textview) , FALSE );
+  gtk_text_view_set_justification( GTK_TEXT_VIEW(info_textview) , GTK_JUSTIFY_LEFT );
+  gtk_text_view_set_left_margin( GTK_TEXT_VIEW(info_textview) , 10 );
+
+  gtk_text_buffer_set_text( info_textbuffer ,
+                            "\nAMIDI-Plug " AMIDIPLUG_VERSION
+                            "\nplay MIDI music through the ALSA sequencer\n"
+                            "http://www.develia.org/projects.php?p=amidiplug\n\n"
+                            "written by Giacomo Lozito\n"
+                            "< james@develia.org >\n\n\n"
+                            "special thanks to...\n\n"
+                            "Clemens Ladisch and Jaroslav Kysela\n"
+                            "for their cool programs aplaymidi and amixer; those\n"
+                            "were really useful, along with alsa-lib docs, in order\n"
+                            "to learn more about the ALSA API\n\n"
+                            "Alfredo Spadafina\n"
+                            "for the nice midi keyboard logo\n\n"
+                            "Tony Vroon\n"
+                            "for the good help with alpha testing\n\n"
+                            , -1 );
+
+  info_scrolledwin = gtk_scrolled_window_new( NULL , NULL );
+  gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(info_scrolledwin) ,
+                                  GTK_POLICY_NEVER , GTK_POLICY_ALWAYS );
+  gtk_container_add( GTK_CONTAINER(info_scrolledwin) , info_textview );
+  info_frame = gtk_frame_new( NULL );
+  gtk_container_add( GTK_CONTAINER(info_frame) , info_scrolledwin );
+
+  gtk_box_pack_start( GTK_BOX(logoandinfo_vbox) , info_frame , TRUE , TRUE , 0 );
+
+  gtk_box_pack_start( GTK_BOX(aboutwin_vbox) , logoandinfo_vbox , TRUE , TRUE , 0 );
+
+  /* horizontal separator and buttons */
+  hseparator = gtk_hseparator_new();
+  gtk_box_pack_start( GTK_BOX(aboutwin_vbox) , hseparator , FALSE , FALSE , 4 );
+  hbuttonbox = gtk_hbutton_box_new();
+  gtk_button_box_set_layout( GTK_BUTTON_BOX(hbuttonbox) , GTK_BUTTONBOX_END );
+  button_ok = gtk_button_new_from_stock( GTK_STOCK_OK );
+  g_signal_connect( G_OBJECT(button_ok) , "clicked" , G_CALLBACK(i_about_ev_bok) , NULL );
+  gtk_container_add( GTK_CONTAINER(hbuttonbox) , button_ok );
+  gtk_box_pack_start( GTK_BOX(aboutwin_vbox) , hbuttonbox , FALSE , FALSE , 0 );
+
+  gtk_widget_show_all( amidiplug_gui_about.about_win );
+}
+
+
+void i_about_ev_destroy( void )
+{
+  amidiplug_gui_about.about_win = NULL;
+}
+
+
+void i_about_ev_bok( void )
+{
+  gtk_widget_destroy(amidiplug_gui_about.about_win);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_utils.h	Thu Jan 26 18:43:59 2006 -0800
@@ -0,0 +1,38 @@
+/*
+*
+* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+*
+*/
+
+#ifndef _I_UTILS_H
+#define _I_UTILS_H 1
+
+#include "i_common.h"
+#include <gtk/gtk.h>
+
+
+typedef struct
+{
+  GtkWidget * about_win;
+}
+amidiplug_gui_about_t;
+
+void i_about_gui( void );
+gint i_util_str_count( gchar * , gchar );
+
+
+#endif /* !_I_UTILS_H */