changeset 240:59d793da5395 trunk

[svn] - import amidi-plug 0.7 (among new features, a transposer to play midi files in different keys)
author giacomo
date Mon, 13 Nov 2006 04:51:30 -0800
parents e45005422574
children a1e15310703e
files ChangeLog src/amidi-plug/Makefile src/amidi-plug/amidi-plug.c src/amidi-plug/amidi-plug.h src/amidi-plug/i_backend.c src/amidi-plug/i_common.h src/amidi-plug/i_configure-alsa.c src/amidi-plug/i_configure-ap.c src/amidi-plug/i_configure-fluidsynth.c src/amidi-plug/i_configure-timidity.c src/amidi-plug/i_configure-timidity.h src/amidi-plug/i_configure.c src/amidi-plug/i_configure.h src/amidi-plug/i_midi.c src/amidi-plug/i_midi.h src/amidi-plug/i_utils.h src/amidi-plug/i_vfslayer.c src/amidi-plug/i_vfslayer.h
diffstat 18 files changed, 362 insertions(+), 65 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Nov 13 04:35:19 2006 -0800
+++ b/ChangeLog	Mon Nov 13 04:51:30 2006 -0800
@@ -1,3 +1,10 @@
+2006-11-13 12:35:19 +0000  Tony Vroon <chainsaw@gentoo.org>
+  revision [496]
+  FD leak fix by TiCPU, submitted in #audacious.
+  trunk/src/cue/cuesheet.c |    4 +++-
+  1 file changed, 3 insertions(+), 1 deletion(-)
+
+
 2006-11-11 18:56:43 +0000  William Pitcock <nenolod@nenolod.net>
   revision [490]
   - fix a potential segfault on x86
--- a/src/amidi-plug/Makefile	Mon Nov 13 04:35:19 2006 -0800
+++ b/src/amidi-plug/Makefile	Mon Nov 13 04:51:30 2006 -0800
@@ -5,7 +5,7 @@
 SUBDIRS = pcfg $(AMIDIPLUG_BACKENDS)
 
 noinst_HEADERS = amidi-plug.h i_backend.h i_midi.h i_midievent.h \
-                 i_configure.h i_configure_private.h \
+                 i_vfslayer.h i_configure.h i_configure_private.h \
                  i_configure-ap.h i_configure-alsa.h \
                  i_configure-fluidsynth.h i_configure-dummy.h \
                  i_fileinfo.h i_utils.h i_common.h \
@@ -15,7 +15,7 @@
 LIBDIR = $(plugindir)/$(INPUT_PLUGIN_DIR)
 
 LIBADD = $(GTK_LIBS) $(GMODULE_LIBS) -lpthread ./pcfg/libpcfg.a
-SOURCES = amidi-plug.c i_midi.c i_backend.c \
+SOURCES = amidi-plug.c i_vfslayer.c i_midi.c i_backend.c \
           i_configure.c i_configure-ap.c i_configure-alsa.c \
           i_configure-fluidsynth.c i_configure-dummy.c \
           i_utils.c i_fileinfo.c
--- a/src/amidi-plug/amidi-plug.c	Mon Nov 13 04:35:19 2006 -0800
+++ b/src/amidi-plug/amidi-plug.c	Mon Nov 13 04:51:30 2006 -0800
@@ -34,16 +34,16 @@
     VFSFile * fp;
     gchar magic_bytes[4];
 
-    fp = vfs_fopen( filename , "rb" );
+    fp = VFS_FOPEN( filename , "rb" );
 
     if ( fp == NULL )
       return FALSE;
 
-    vfs_fread( magic_bytes , 1 , 4 , fp );
+    VFS_FREAD( magic_bytes , 1 , 4 , fp );
 
     if ( !strncmp( magic_bytes , "MThd" , 4 ) )
     {
-      vfs_fclose( fp );
+      VFS_FCLOSE( fp );
       DEBUGMSG( "MIDI found, %s is a standard midi file\n" , filename );
       return TRUE;
     }
@@ -52,16 +52,16 @@
     {
       /* skip the four bytes after RIFF,
          then read the next four */
-      vfs_fseek( fp , 4 , SEEK_CUR );
-      vfs_fread( magic_bytes , 1 , 4 , fp );
+      VFS_FSEEK( fp , 4 , SEEK_CUR );
+      VFS_FREAD( magic_bytes , 1 , 4 , fp );
       if ( !strncmp( magic_bytes , "RMID" , 4 ) )
       {
-        vfs_fclose( fp );
+        VFS_FCLOSE( fp );
         DEBUGMSG( "MIDI found, %s is a riff midi file\n" , filename );
         return TRUE;
       }
     }
-    vfs_fclose( fp );
+    VFS_FCLOSE( fp );
 #else
     gchar * ext = strrchr( filename, '.' );
     /* check the filename extension */
@@ -391,7 +391,7 @@
   }
 
   DEBUGMSG( "PLAY requested, opening file: %s\n" , filename );
-  midifile.file_pointer = vfs_fopen( filename , "rb" );
+  midifile.file_pointer = VFS_FOPEN( filename , "rb" );
   if (!midifile.file_pointer)
   {
     g_warning( "Cannot open %s\n" , filename );
@@ -469,7 +469,7 @@
     }
   }
 
-  vfs_fclose( midifile.file_pointer );
+  VFS_FCLOSE( midifile.file_pointer );
   return;
 }
 
--- a/src/amidi-plug/amidi-plug.h	Mon Nov 13 04:35:19 2006 -0800
+++ b/src/amidi-plug/amidi-plug.h	Mon Nov 13 04:51:30 2006 -0800
@@ -27,11 +27,11 @@
 #define AMIDIPLUG_ERR	3
 
 #include "i_common.h"
-#include "audacious/plugin.h"
-#include "audacious/output.h"
-#include "audacious/beepctrl.h"
-#include "audacious/vfs.h"
+#include <audacious/plugin.h>
+#include <audacious/output.h>
+#include <audacious/beepctrl.h>
 #include <pthread.h>
+#include "i_vfslayer.h"
 #include "i_backend.h"
 #include "i_configure.h"
 #include "i_midi.h"
@@ -60,7 +60,11 @@
 amidiplug_cfg_ap_t amidiplug_cfg_ap =
 {
   NULL,		/* ap_seq_backend */
-  0		/* ap_opts_length_precalc */
+  0,		/* ap_opts_transpose_value */
+  0,		/* ap_opts_drumshift_value */
+  0,		/* ap_opts_length_precalc */
+  0,		/* ap_opts_comments_extract */
+  0		/* ap_opts_lyrics_extract */
 };
 
 
--- a/src/amidi-plug/i_backend.c	Mon Nov 13 04:35:19 2006 -0800
+++ b/src/amidi-plug/i_backend.c	Mon Nov 13 04:51:30 2006 -0800
@@ -20,6 +20,7 @@
 
 #include "i_backend.h"
 
+
 gboolean i_str_has_pref_and_suff( const gchar *str , gchar *pref , gchar *suff )
 {
   if ( (g_str_has_prefix( str , pref )) &&
--- a/src/amidi-plug/i_common.h	Mon Nov 13 04:35:19 2006 -0800
+++ b/src/amidi-plug/i_common.h	Mon Nov 13 04:51:30 2006 -0800
@@ -43,7 +43,7 @@
 #endif /* DEBUG */
 
 
-#define AMIDIPLUG_VERSION "0.6"
+#define AMIDIPLUG_VERSION "0.7"
 #define PLAYER_NAME "Audacious"
 #define PLAYER_LOCALRCDIR ".audacious"
 #define G_PATH_GET_BASENAME(x) g_path_get_basename(x)
--- a/src/amidi-plug/i_configure-alsa.c	Mon Nov 13 04:35:19 2006 -0800
+++ b/src/amidi-plug/i_configure-alsa.c	Mon Nov 13 04:51:30 2006 -0800
@@ -50,7 +50,6 @@
 };
 
 
-
 void i_configure_ev_portlv_changetoggle( GtkCellRendererToggle * rdtoggle ,
                                          gchar * path_str , gpointer data )
 {
--- a/src/amidi-plug/i_configure-ap.c	Mon Nov 13 04:35:19 2006 -0800
+++ b/src/amidi-plug/i_configure-ap.c	Mon Nov 13 04:51:30 2006 -0800
@@ -113,23 +113,37 @@
 }
 
 
-void i_configure_ev_settings_commit( gpointer settings_vbox )
+void i_configure_ev_settplay_commit( gpointer settplay_vbox )
 {
-  GtkWidget *settings_precalc_checkbt = g_object_get_data( G_OBJECT(settings_vbox) ,
+  GtkWidget *settplay_transpose_spinbt = g_object_get_data( G_OBJECT(settplay_vbox) ,
+                                                            "ap_opts_transpose_value" );
+  GtkWidget *settplay_drumshift_spinbt = g_object_get_data( G_OBJECT(settplay_vbox) ,
+                                                            "ap_opts_drumshift_value" );
+  amidiplug_cfg_ap.ap_opts_transpose_value = gtk_spin_button_get_value_as_int(
+    GTK_SPIN_BUTTON(settplay_transpose_spinbt) );
+  amidiplug_cfg_ap.ap_opts_drumshift_value = gtk_spin_button_get_value_as_int(
+    GTK_SPIN_BUTTON(settplay_drumshift_spinbt) );
+  return;
+}
+
+
+void i_configure_ev_settadva_commit( gpointer settadva_vbox )
+{
+  GtkWidget *settadva_precalc_checkbt = g_object_get_data( G_OBJECT(settadva_vbox) ,
                                                            "ap_opts_length_precalc" );
-  GtkWidget *settings_extractlyr_checkbt = g_object_get_data( G_OBJECT(settings_vbox) ,
+  GtkWidget *settadva_extractlyr_checkbt = g_object_get_data( G_OBJECT(settadva_vbox) ,
                                                               "ap_opts_lyrics_extract" );
-  GtkWidget *settings_extractcomm_checkbt = g_object_get_data( G_OBJECT(settings_vbox) ,
+  GtkWidget *settadva_extractcomm_checkbt = g_object_get_data( G_OBJECT(settadva_vbox) ,
                                                                "ap_opts_comments_extract" );
-  if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(settings_precalc_checkbt) ) )
+  if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(settadva_precalc_checkbt) ) )
     amidiplug_cfg_ap.ap_opts_length_precalc = 1;
   else
     amidiplug_cfg_ap.ap_opts_length_precalc = 0;
-  if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(settings_extractlyr_checkbt) ) )
+  if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(settadva_extractlyr_checkbt) ) )
     amidiplug_cfg_ap.ap_opts_lyrics_extract = 1;
   else
     amidiplug_cfg_ap.ap_opts_lyrics_extract = 0;
-  if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(settings_extractcomm_checkbt) ) )
+  if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(settadva_extractcomm_checkbt) ) )
     amidiplug_cfg_ap.ap_opts_comments_extract = 1;
   else
     amidiplug_cfg_ap.ap_opts_comments_extract = 0;
@@ -154,8 +168,13 @@
   GtkWidget *ap_page_vbox;
   GtkWidget *title_widget;
   GtkWidget *content_vbox; /* this vbox will contain two items of equal space (50%/50%) */
-  GtkWidget *settings_frame, *settings_vbox;
-  GtkWidget *settings_precalc_checkbt, *settings_extractcomm_checkbt, *settings_extractlyr_checkbt;
+  GtkWidget *settings_vbox; /* this vbox will contain all settings vbox (playback, advanced) */
+  GtkWidget *settplay_frame, *settplay_vbox;
+  GtkWidget *settplay_transpose_and_drumshift_hbox;
+  GtkWidget *settplay_transpose_hbox, *settplay_transpose_label1, *settplay_transpose_spinbt;
+  GtkWidget *settplay_drumshift_hbox, *settplay_drumshift_label1, *settplay_drumshift_spinbt;
+  GtkWidget *settadva_frame, *settadva_vbox;
+  GtkWidget *settadva_precalc_checkbt, *settadva_extractcomm_checkbt, *settadva_extractlyr_checkbt;
   GtkWidget *backend_lv_frame, *backend_lv, *backend_lv_sw;
   GtkWidget *backend_lv_hbox, *backend_lv_vbbox, *backend_lv_infobt;
   GtkListStore *backend_store;
@@ -231,34 +250,69 @@
   gtk_box_pack_start( GTK_BOX(backend_lv_vbbox) , backend_lv_infobt , FALSE , FALSE , 0 );
   gtk_container_add( GTK_CONTAINER(backend_lv_frame) , backend_lv_hbox );
 
-  settings_frame = gtk_frame_new( _("Advanced settings") );
-  settings_vbox = gtk_vbox_new( FALSE , 0 );
-  gtk_container_set_border_width( GTK_CONTAINER(settings_vbox), 4 );
-  settings_precalc_checkbt = gtk_check_button_new_with_label(
+  settings_vbox = gtk_vbox_new( FALSE , 2 );
+
+  settplay_frame = gtk_frame_new( _("Playback settings") );
+  settplay_vbox = gtk_vbox_new( FALSE , 0 );
+  gtk_container_set_border_width( GTK_CONTAINER(settplay_vbox), 4 );
+  settplay_transpose_and_drumshift_hbox = gtk_hbox_new( FALSE , 12 );
+  settplay_transpose_hbox = gtk_hbox_new( FALSE , 0 );
+  settplay_transpose_label1 = gtk_label_new( _("Transpose: ") );
+  settplay_transpose_spinbt = gtk_spin_button_new_with_range( -20 , 20 , 1 );
+  gtk_spin_button_set_value( GTK_SPIN_BUTTON(settplay_transpose_spinbt) ,
+                             amidiplug_cfg_ap.ap_opts_transpose_value );
+  gtk_box_pack_start( GTK_BOX(settplay_transpose_hbox) , settplay_transpose_label1 , FALSE , FALSE , 0 );
+  gtk_box_pack_start( GTK_BOX(settplay_transpose_hbox) , settplay_transpose_spinbt , FALSE , FALSE , 2 );
+  gtk_box_pack_start( GTK_BOX(settplay_transpose_and_drumshift_hbox) ,
+                      settplay_transpose_hbox , FALSE , FALSE , 0 );
+  settplay_drumshift_hbox = gtk_hbox_new( FALSE , 0 );
+  settplay_drumshift_label1 = gtk_label_new( _("Drum shift: ") );
+  settplay_drumshift_spinbt = gtk_spin_button_new_with_range( 0 , 127 , 1 );
+  gtk_spin_button_set_value( GTK_SPIN_BUTTON(settplay_drumshift_spinbt) ,
+                             amidiplug_cfg_ap.ap_opts_drumshift_value );
+  gtk_box_pack_start( GTK_BOX(settplay_drumshift_hbox) , settplay_drumshift_label1 , FALSE , FALSE , 0 );
+  gtk_box_pack_start( GTK_BOX(settplay_drumshift_hbox) , settplay_drumshift_spinbt , FALSE , FALSE , 2 );
+  gtk_box_pack_start( GTK_BOX(settplay_transpose_and_drumshift_hbox) ,
+                      settplay_drumshift_hbox , FALSE , FALSE , 0 );
+  gtk_box_pack_start( GTK_BOX(settplay_vbox) ,
+                      settplay_transpose_and_drumshift_hbox , FALSE , FALSE , 2 );
+  gtk_container_add( GTK_CONTAINER(settplay_frame) , settplay_vbox );
+  /* attach pointers of options to settplay_vbox so we can handle all of them in a single callback */
+  g_object_set_data( G_OBJECT(settplay_vbox) , "ap_opts_transpose_value" , settplay_transpose_spinbt );
+  g_object_set_data( G_OBJECT(settplay_vbox) , "ap_opts_drumshift_value" , settplay_drumshift_spinbt );
+  g_signal_connect_swapped( G_OBJECT(commit_button) , "ap-commit" ,
+                            G_CALLBACK(i_configure_ev_settplay_commit) , settplay_vbox );
+  gtk_box_pack_start( GTK_BOX(settings_vbox) , settplay_frame , TRUE , TRUE , 0 );
+
+  settadva_frame = gtk_frame_new( _("Advanced settings") );
+  settadva_vbox = gtk_vbox_new( FALSE , 0 );
+  gtk_container_set_border_width( GTK_CONTAINER(settadva_vbox), 4 );
+  settadva_precalc_checkbt = gtk_check_button_new_with_label(
                                _("pre-calculate length of MIDI files in playlist") );
   if ( amidiplug_cfg_ap.ap_opts_length_precalc )
-    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(settings_precalc_checkbt) , TRUE );
-  gtk_box_pack_start( GTK_BOX(settings_vbox) , settings_precalc_checkbt , FALSE , FALSE , 2 );
-  settings_extractcomm_checkbt = gtk_check_button_new_with_label(
+    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(settadva_precalc_checkbt) , TRUE );
+  gtk_box_pack_start( GTK_BOX(settadva_vbox) , settadva_precalc_checkbt , FALSE , FALSE , 2 );
+  settadva_extractcomm_checkbt = gtk_check_button_new_with_label(
                                    _("extract comments from MIDI file (if available)") );
   if ( amidiplug_cfg_ap.ap_opts_comments_extract )
-    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(settings_extractcomm_checkbt) , TRUE );
-  gtk_box_pack_start( GTK_BOX(settings_vbox) , settings_extractcomm_checkbt , FALSE , FALSE , 2 );
-  settings_extractlyr_checkbt = gtk_check_button_new_with_label(
+    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(settadva_extractcomm_checkbt) , TRUE );
+  gtk_box_pack_start( GTK_BOX(settadva_vbox) , settadva_extractcomm_checkbt , FALSE , FALSE , 2 );
+  settadva_extractlyr_checkbt = gtk_check_button_new_with_label(
                                   _("extract lyrics from MIDI file (if available)") );
   if ( amidiplug_cfg_ap.ap_opts_lyrics_extract )
-    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(settings_extractlyr_checkbt) , TRUE );
-  gtk_box_pack_start( GTK_BOX(settings_vbox) , settings_extractlyr_checkbt , FALSE , FALSE , 2 );
-  gtk_container_add( GTK_CONTAINER(settings_frame) , settings_vbox );
-  /* attach pointers of options to settings_vbox so we can handle all of them in a single callback */
-  g_object_set_data( G_OBJECT(settings_vbox) , "ap_opts_length_precalc" , settings_precalc_checkbt );
-  g_object_set_data( G_OBJECT(settings_vbox) , "ap_opts_comments_extract" , settings_extractcomm_checkbt );
-  g_object_set_data( G_OBJECT(settings_vbox) , "ap_opts_lyrics_extract" , settings_extractlyr_checkbt );
+    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(settadva_extractlyr_checkbt) , TRUE );
+  gtk_box_pack_start( GTK_BOX(settadva_vbox) , settadva_extractlyr_checkbt , FALSE , FALSE , 2 );
+  gtk_container_add( GTK_CONTAINER(settadva_frame) , settadva_vbox );
+  /* attach pointers of options to settadva_vbox so we can handle all of them in a single callback */
+  g_object_set_data( G_OBJECT(settadva_vbox) , "ap_opts_length_precalc" , settadva_precalc_checkbt );
+  g_object_set_data( G_OBJECT(settadva_vbox) , "ap_opts_comments_extract" , settadva_extractcomm_checkbt );
+  g_object_set_data( G_OBJECT(settadva_vbox) , "ap_opts_lyrics_extract" , settadva_extractlyr_checkbt );
   g_signal_connect_swapped( G_OBJECT(commit_button) , "ap-commit" ,
-                            G_CALLBACK(i_configure_ev_settings_commit) , settings_vbox );
+                            G_CALLBACK(i_configure_ev_settadva_commit) , settadva_vbox );
+  gtk_box_pack_start( GTK_BOX(settings_vbox) , settadva_frame , TRUE , TRUE , 0 );
 
   gtk_box_pack_start( GTK_BOX(content_vbox) , backend_lv_frame , TRUE , TRUE , 0 );
-  gtk_box_pack_start( GTK_BOX(content_vbox) , settings_frame , TRUE , TRUE , 0 );
+  gtk_box_pack_start( GTK_BOX(content_vbox) , settings_vbox , TRUE , TRUE , 0 );
   gtk_box_pack_start( GTK_BOX(ap_page_vbox) , content_vbox , TRUE , TRUE , 2 );
   gtk_container_add( GTK_CONTAINER(ap_page_alignment) , ap_page_vbox );
 
@@ -273,7 +327,20 @@
                         "synthesizer and/or want to pipe audio into effect and output plugins of the "
                         "player you'll want to use the good FluidSynth backend.\nPress the info "
                         "button to read specific information about each backend.") , "" );
-  gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , settings_precalc_checkbt ,
+  gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , settplay_transpose_spinbt ,
+                        _("* Transpose function *\n"
+                        "This option allows you to play the midi file transposed in a different key, "
+                        "by shifting of the desired number of semitones all its notes (excepting those "
+                        "on midi channel 10, reserved for percussions). Expecially useful if you wish "
+                        "to sing or play along with another instrument.") , "" );
+  gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , settplay_drumshift_spinbt ,
+                        _("* Drumshift function *\n"
+                        "This option allows you to shift notes on midi channel 10 (the standard "
+                        "percussions channel) of the desired number of semitones. This results in "
+                        "different drumset and percussions being used during midi playback, so if "
+                        "you wish to enhance (or reduce, or alter) percussion sounds, try to play "
+                        "with this value.") , "" );
+  gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , settadva_precalc_checkbt ,
                         _("* Pre-calculate MIDI length *\n"
                         "If this option is enabled, AMIDI-Plug will calculate the MIDI file "
                         "length as soon as the player requests it, instead of doing that only "
@@ -282,12 +349,12 @@
                         "Disable this option if you want faster playlist loading (when a lot "
                         "of MIDI files are added), enable it to display more information "
                         "in the playlist straight after loading.") , "" );
-  gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , settings_extractcomm_checkbt ,
+  gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , settadva_extractcomm_checkbt ,
                         _("* Extract comments from MIDI files *\n"
                         "Some MIDI files contain text comments (author, copyright, instrument notes, "
                         "etc.). If this option is enabled, AMIDI-Plug will extract and display comments "
                         "(if available) in the file information dialog.") , "" );
-  gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , settings_extractlyr_checkbt ,
+  gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , settadva_extractlyr_checkbt ,
                         _("* Extract lyrics from MIDI files *\n"
                         "Some MIDI files contain song lyrics. If this option is enabled, AMIDI-Plug "
                         "will extract and display song lyrics (if available) in the file "
--- a/src/amidi-plug/i_configure-fluidsynth.c	Mon Nov 13 04:35:19 2006 -0800
+++ b/src/amidi-plug/i_configure-fluidsynth.c	Mon Nov 13 04:51:30 2006 -0800
@@ -892,10 +892,10 @@
                           "This button resets the backend buffer parameters to default values.") , "" );
     gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , buffer_tuner_hscale ,
                           _("* FluidSynth backend buffer *\n"
-                          "If you notice skips during song playback and your system is not performing "
-                          "any cpu-intensive task (except FluidSynth itself), you may want to tune the "
-                          "buffer in order to prevent skipping. Try to move the \"handy buffer tuner\" "
-                          "a single step to the right until playback is fluid again.") , "" );
+                          "If you notice skips or slowness during song playback and your system is not "
+                          "performing any cpu-intensive task (except FluidSynth itself), you may want "
+                          "to adjust the buffer parameters. Try to move the \"handy buffer tuner\" "
+                          "some steps to the right until playback is fluid again.") , "" );
     gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , buffer_bufsize_spin ,
                           _("* FluidSynth backend buffer *\n"
                           "It is a good idea to make buffer adjustments with the \"handy buffer tuner\" "
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/amidi-plug/i_configure-timidity.c	Mon Nov 13 04:51:30 2006 -0800
@@ -0,0 +1,90 @@
+/*
+*
+* 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.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+*
+*/
+
+
+#include "i_configure-timidity.h"
+#include "backend-timidity/backend-timidity-icon.xpm"
+
+
+void i_configure_gui_tab_timi( GtkWidget * timi_page_alignment ,
+                               gpointer backend_list_p ,
+                               gpointer commit_button )
+{
+  GtkWidget *timi_page_vbox;
+  GtkWidget *title_widget;
+  GtkWidget *content_vbox; /* this vbox will contain two items of equal space (50%/50%) */
+  GSList * backend_list = backend_list_p;
+  gboolean timi_module_ok = FALSE;
+  gchar * timi_module_pathfilename;
+
+  timi_page_vbox = gtk_vbox_new( FALSE , 0 );
+
+  title_widget = i_configure_gui_draw_title( _("TIMIDITY BACKEND CONFIGURATION") );
+  gtk_box_pack_start( GTK_BOX(timi_page_vbox) , title_widget , FALSE , FALSE , 2 );
+
+  content_vbox = gtk_vbox_new( TRUE , 2 );
+
+  /* check if the TiMidity module is available */
+  while ( backend_list != NULL )
+  {
+    amidiplug_sequencer_backend_name_t * mn = backend_list->data;
+    if ( !strcmp( mn->name , "timidity" ) )
+    {
+      timi_module_ok = TRUE;
+      timi_module_pathfilename = mn->filename;
+      break;
+    }
+    backend_list = backend_list->next;
+  }
+
+  if ( timi_module_ok )
+  {
+  }
+  else
+  {
+    /* display "not available" information */
+    GtkWidget * info_label;
+    info_label = gtk_label_new( "TiMidity Backend not loaded or not available" );
+    gtk_box_pack_start( GTK_BOX(timi_page_vbox) , info_label , FALSE , FALSE , 2 );
+  }
+
+  gtk_box_pack_start( GTK_BOX(timi_page_vbox) , content_vbox , TRUE , TRUE , 2 );
+  gtk_container_add( GTK_CONTAINER(timi_page_alignment) , timi_page_vbox );
+}
+
+
+void i_configure_gui_tablabel_timi( GtkWidget * timi_page_alignment ,
+                                  gpointer backend_list_p ,
+                                  gpointer commit_button )
+{
+  GtkWidget *pagelabel_vbox, *pagelabel_image, *pagelabel_label;
+  GdkPixbuf *pagelabel_image_pix;
+  pagelabel_vbox = gtk_vbox_new( FALSE , 1 );
+  pagelabel_image_pix = gdk_pixbuf_new_from_xpm_data( (const gchar **)backend_timidity_icon_xpm );
+  pagelabel_image = gtk_image_new_from_pixbuf( pagelabel_image_pix ); g_object_unref( pagelabel_image_pix );
+  pagelabel_label = gtk_label_new( "" );
+  gtk_label_set_markup( GTK_LABEL(pagelabel_label) , "<span size=\"smaller\">TiMidity\nbackend</span>" );
+  gtk_label_set_justify( GTK_LABEL(pagelabel_label) , GTK_JUSTIFY_CENTER );
+  gtk_box_pack_start( GTK_BOX(pagelabel_vbox) , pagelabel_image , FALSE , FALSE , 1 );
+  gtk_box_pack_start( GTK_BOX(pagelabel_vbox) , pagelabel_label , FALSE , FALSE , 1 );
+  gtk_container_add( GTK_CONTAINER(timi_page_alignment) , pagelabel_vbox );
+  gtk_widget_show_all( timi_page_alignment );
+  return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/amidi-plug/i_configure-timidity.h	Mon Nov 13 04:51:30 2006 -0800
@@ -0,0 +1,30 @@
+/*
+*
+* 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.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+*
+*/
+
+#ifndef _I_CONFIGURE_TIMIDITY_H
+#define _I_CONFIGURE_TIMIDITY_H 1
+
+#include "i_configure.h"
+
+
+void i_configure_gui_tab_timi( GtkWidget * , gpointer , gpointer );
+void i_configure_gui_tablabel_timi( GtkWidget * , gpointer , gpointer );
+
+#endif /* !_I_CONFIGURE_TIMIDITY_H */
--- a/src/amidi-plug/i_configure.c	Mon Nov 13 04:35:19 2006 -0800
+++ b/src/amidi-plug/i_configure.c	Mon Nov 13 04:51:30 2006 -0800
@@ -27,7 +27,7 @@
 #include "i_configure-fluidsynth.h"
 #include "i_configure-dummy.h"
 #include "i_utils.h"
-#include "audacious/beepctrl.h"
+#include <audacious/beepctrl.h>
 
 
 amidiplug_cfg_backend_t * amidiplug_cfg_backend;
@@ -358,6 +358,8 @@
   {
     /* amidi-plug defaults */
     amidiplug_cfg_ap.ap_seq_backend = g_strdup( "alsa" );
+    amidiplug_cfg_ap.ap_opts_transpose_value = 0;
+    amidiplug_cfg_ap.ap_opts_drumshift_value = 0;
     amidiplug_cfg_ap.ap_opts_length_precalc = 0;
     amidiplug_cfg_ap.ap_opts_lyrics_extract = 0;
     amidiplug_cfg_ap.ap_opts_comments_extract = 0;
@@ -366,6 +368,10 @@
   {
     i_pcfg_read_string( cfgfile , "general" , "ap_seq_backend" ,
                         &amidiplug_cfg_ap.ap_seq_backend , "alsa" );
+    i_pcfg_read_integer( cfgfile , "general" , "ap_opts_transpose_value" ,
+                         &amidiplug_cfg_ap.ap_opts_transpose_value , 0 );
+    i_pcfg_read_integer( cfgfile , "general" , "ap_opts_drumshift_value" ,
+                         &amidiplug_cfg_ap.ap_opts_drumshift_value , 0 );
     i_pcfg_read_integer( cfgfile , "general" , "ap_opts_length_precalc" ,
                          &amidiplug_cfg_ap.ap_opts_length_precalc , 0 );
     i_pcfg_read_integer( cfgfile , "general" , "ap_opts_lyrics_extract" ,
@@ -392,6 +398,10 @@
   /* save amidi-plug config information */
   i_pcfg_write_string( cfgfile , "general" , "ap_seq_backend" ,
                        amidiplug_cfg_ap.ap_seq_backend );
+  i_pcfg_write_integer( cfgfile , "general" , "ap_opts_transpose_value" ,
+                        amidiplug_cfg_ap.ap_opts_transpose_value );
+  i_pcfg_write_integer( cfgfile , "general" , "ap_opts_drumshift_value" ,
+                        amidiplug_cfg_ap.ap_opts_drumshift_value );
   i_pcfg_write_integer( cfgfile , "general" , "ap_opts_length_precalc" ,
                         amidiplug_cfg_ap.ap_opts_length_precalc );
   i_pcfg_write_integer( cfgfile , "general" , "ap_opts_lyrics_extract" ,
--- a/src/amidi-plug/i_configure.h	Mon Nov 13 04:35:19 2006 -0800
+++ b/src/amidi-plug/i_configure.h	Mon Nov 13 04:51:30 2006 -0800
@@ -27,6 +27,8 @@
 typedef struct
 {
   gchar *	ap_seq_backend;
+  gint		ap_opts_transpose_value;
+  gint		ap_opts_drumshift_value;
   gint		ap_opts_length_precalc;
   gint		ap_opts_comments_extract;
   gint		ap_opts_lyrics_extract;
--- a/src/amidi-plug/i_midi.c	Mon Nov 13 04:35:19 2006 -0800
+++ b/src/amidi-plug/i_midi.c	Mon Nov 13 04:51:30 2006 -0800
@@ -43,7 +43,7 @@
 gint i_midi_file_read_byte( midifile_t * mf )
 {
   ++mf->file_offset;
-  return vfs_getc(mf->file_pointer);
+  return VFS_GETC(mf->file_pointer);
 }
 
 
@@ -55,7 +55,7 @@
   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 !vfs_feof(mf->file_pointer) ? value : -1;
+  return !VFS_FEOF(mf->file_pointer) ? value : -1;
 }
 
 
@@ -102,7 +102,7 @@
       }
     }
   }
-  return !vfs_feof(mf->file_pointer) ? value : -1;
+  return !VFS_FEOF(mf->file_pointer) ? value : -1;
 }
 
 
@@ -158,7 +158,7 @@
         last_cmd = cmd;
     } else {
       /* running status */
-      vfs_ungetc(c, mf->file_pointer);
+      VFS_UNGETC(c, mf->file_pointer);
       mf->file_offset--;
       cmd = last_cmd;
       if (!cmd)
@@ -181,7 +181,33 @@
       case 0x8: /* channel msg with 2 parameter bytes */
       case 0x9:
       case 0xa:
-      case 0xb:
+      {
+        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;
+        /* if this note is not in standard drum channel (10), apply transpose */
+        if ( event->data.d[0] != 9 )
+        {
+          gint data_tr = (i_midi_file_read_byte(mf) & 0x7f) +
+                           amidiplug_cfg_ap.ap_opts_transpose_value;
+          if ( data_tr > 127 ) data_tr = 127;
+          else if ( data_tr < 0 ) data_tr = 0;
+          event->data.d[1] = (guchar)data_tr;
+        }
+        else /* this note is in standard drum channel (10), apply drum shift */
+        {
+          gint data_ds = (i_midi_file_read_byte(mf) & 0x7f) +
+                           amidiplug_cfg_ap.ap_opts_drumshift_value; /* always > 0 */
+          if ( data_ds > 127 ) data_ds -= 127;
+          event->data.d[1] = (guchar)data_ds;
+        }
+        event->data.d[2] = i_midi_file_read_byte(mf) & 0x7f;
+      }
+      break;
+
+      case 0xb: /* channel msg with 2 parameter bytes */
       case 0xe:
       {
         event = i_midi_file_new_event(track, 0);
@@ -398,7 +424,7 @@
     {
       gint id = i_midi_file_read_id(mf);
       len = i_midi_file_read_int(mf,4);
-      if ( vfs_feof(mf->file_pointer) )
+      if ( VFS_FEOF(mf->file_pointer) )
       {
         g_warning( "%s: unexpected end of file\n" , mf->file_name );
         return 0;
@@ -447,7 +473,7 @@
     gint id = i_midi_file_read_id(mf);
     gint len = i_midi_file_read_32_le(mf);
 
-    if ( vfs_feof(mf->file_pointer) )
+    if ( VFS_FEOF(mf->file_pointer) )
       return 0;
 
     if ( id == MAKE_ID('d', 'a', 't', 'a') )
@@ -720,7 +746,7 @@
 {
   i_midi_init( mf );
   DEBUGMSG( "PARSE_FROM_FILENAME requested, opening file: %s\n" , filename );
-  mf->file_pointer = vfs_fopen( filename , "rb" );
+  mf->file_pointer = VFS_FOPEN( filename , "rb" );
   if (!mf->file_pointer)
   {
     g_warning( "Cannot open %s\n" , filename );
@@ -758,7 +784,7 @@
       i_midi_setget_length( mf );
 
       /* ok, mf has been filled with information; successfully return */
-      vfs_fclose( mf->file_pointer );
+      VFS_FCLOSE( mf->file_pointer );
       return 1;
     }
 
@@ -770,6 +796,6 @@
   }
 
   /* something failed */
-  vfs_fclose( mf->file_pointer );
+  VFS_FCLOSE( mf->file_pointer );
   return 0;
 }
--- a/src/amidi-plug/i_midi.h	Mon Nov 13 04:35:19 2006 -0800
+++ b/src/amidi-plug/i_midi.h	Mon Nov 13 04:51:30 2006 -0800
@@ -23,7 +23,7 @@
 
 #include "i_common.h"
 #include "i_midievent.h"
-#include "audacious/vfs.h"
+#include "i_vfslayer.h"
 
 #define MAKE_ID(c1, c2, c3, c4) ((c1) | ((c2) << 8) | ((c3) << 16) | ((c4) << 24))
 
--- a/src/amidi-plug/i_utils.h	Mon Nov 13 04:35:19 2006 -0800
+++ b/src/amidi-plug/i_utils.h	Mon Nov 13 04:51:30 2006 -0800
@@ -31,4 +31,5 @@
 void i_about_gui( void );
 gpointer i_message_gui( gchar * , gchar * , gint , gpointer , gboolean );
 
+
 #endif /* !_I_UTILS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/amidi-plug/i_vfslayer.c	Mon Nov 13 04:51:30 2006 -0800
@@ -0,0 +1,22 @@
+/*
+*
+* 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.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+*
+*/
+
+
+#include "i_vfslayer.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/amidi-plug/i_vfslayer.h	Mon Nov 13 04:51:30 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.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+*
+*/
+
+
+#ifndef _I_VFSLAYER_H
+#define _I_VFSLAYER_H 1
+
+#include "i_common.h"
+#include <audacious/vfs.h>
+
+
+#define VFS_FOPEN( x , y )		vfs_fopen( x , y )
+#define VFS_FCLOSE( x )			vfs_fclose( x )
+#define VFS_FREAD( x , y , z , w )	vfs_fread( x , y , z , w )
+#define VFS_FSEEK( x , y , z )		vfs_fseek( x , y , z )
+#define VFS_FEOF( x )			vfs_feof( x )
+#define VFS_GETC( x )			vfs_getc( x )
+#define VFS_UNGETC( x , y )		vfs_ungetc( x , y )
+
+
+#endif /* !_I_VFSLAYER_H */