changeset 1387:b0590e16329f trunk

[svn] import amidi-plug 0.5
author giacomo
date Mon, 10 Jul 2006 04:52:51 -0700
parents f0d2b02f0382
children b8e521f642e4
files ChangeLog Plugins/Input/amidi-plug/Makefile.in Plugins/Input/amidi-plug/amidi-plug-icon.xpm Plugins/Input/amidi-plug/amidi-plug.c Plugins/Input/amidi-plug/amidi-plug.h Plugins/Input/amidi-plug/backend-alsa/Makefile.in Plugins/Input/amidi-plug/backend-alsa/b-alsa-config.h Plugins/Input/amidi-plug/backend-alsa/b-alsa.c Plugins/Input/amidi-plug/backend-alsa/b-alsa.h Plugins/Input/amidi-plug/backend-alsa/backend-alsa-icon.xpm Plugins/Input/amidi-plug/backend-dummy/Makefile.in Plugins/Input/amidi-plug/backend-dummy/b-dummy-config.h Plugins/Input/amidi-plug/backend-dummy/b-dummy.c Plugins/Input/amidi-plug/backend-dummy/b-dummy.h Plugins/Input/amidi-plug/backend-dummy/backend-dummy-icon.xpm Plugins/Input/amidi-plug/backend-fluidsynth/Makefile.in Plugins/Input/amidi-plug/backend-fluidsynth/b-fluidsynth-config.h Plugins/Input/amidi-plug/backend-fluidsynth/b-fluidsynth.c Plugins/Input/amidi-plug/backend-fluidsynth/b-fluidsynth.h Plugins/Input/amidi-plug/backend-fluidsynth/backend-fluidsynth-icon.xpm Plugins/Input/amidi-plug/i_backend.c Plugins/Input/amidi-plug/i_backend.h Plugins/Input/amidi-plug/i_common.h Plugins/Input/amidi-plug/i_configure-alsa.c Plugins/Input/amidi-plug/i_configure-alsa.h Plugins/Input/amidi-plug/i_configure-ap.c Plugins/Input/amidi-plug/i_configure-ap.h Plugins/Input/amidi-plug/i_configure-dummy.c Plugins/Input/amidi-plug/i_configure-dummy.h Plugins/Input/amidi-plug/i_configure-fluidsynth.c Plugins/Input/amidi-plug/i_configure-fluidsynth.h Plugins/Input/amidi-plug/i_configure.c Plugins/Input/amidi-plug/i_configure.h Plugins/Input/amidi-plug/i_configure_private.h Plugins/Input/amidi-plug/i_fileinfo.c Plugins/Input/amidi-plug/i_fileinfo.h Plugins/Input/amidi-plug/i_midi.h Plugins/Input/amidi-plug/i_midievent.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 Plugins/Input/amidi-plug/pcfg/Makefile.in Plugins/Input/amidi-plug/pcfg/i_pcfg.c Plugins/Input/amidi-plug/pcfg/i_pcfg.h configure.ac m4/amidi-plug.m4 mk/rules.mk.in
diffstat 48 files changed, 8858 insertions(+), 1349 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Jul 10 04:42:53 2006 -0700
+++ b/ChangeLog	Mon Jul 10 04:52:51 2006 -0700
@@ -1,3 +1,12 @@
+2006-07-10 11:42:53 +0000  William Pitcock <nenolod@nenolod.net>
+  revision [1686]
+  - disconnect mms code
+  
+
+  Changes:        Modified:
+  +3 -0           trunk/Plugins/Input/wma/libffwma/allformats.c  
+
+
 2006-07-10 11:39:43 +0000  William Pitcock <nenolod@nenolod.net>
   revision [1684]
   - vast improvements to the songchange plugin
--- a/Plugins/Input/amidi-plug/Makefile.in	Mon Jul 10 04:42:53 2006 -0700
+++ b/Plugins/Input/amidi-plug/Makefile.in	Mon Jul 10 04:52:51 2006 -0700
@@ -2,19 +2,24 @@
 include ../../../mk/objective.mk
 
 OBJECTIVE_LIBS = libamidi-plug.so
+SUBDIRS = pcfg @AMIDIPLUG_BACKENDS@
 
-noinst_HEADERS = amidi-plug.h i_seq.h i_midi.h i_configure.h \
-                 i_fileinfo.h i_utils.h i_common.h
+noinst_HEADERS = amidi-plug.h i_backend.h i_midi.h i_midievent.h \
+                 i_configure.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 \
+                 amidi-plug-icon.xpm amidi-plug.logo.xpm \
+                 amidi-plug.midiicon.xpm
 
 LIBDIR = $(plugindir)/$(INPUT_PLUGIN_DIR)
 
-LIBADD = $(GTK_LIBS) $(ALSA_LIBS) -lpthread
-SOURCES = amidi-plug.c i_seq.c i_midi.c \
-          i_configure.c i_utils.c i_fileinfo.c
-
-DATA = amidi-plug.logo.xpm amidi-plug.midiicon.xpm
+LIBADD = $(GTK_LIBS) $(GMODULE_LIBS) -lpthread ./pcfg/libpcfg.a
+SOURCES = amidi-plug.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
 
 OBJECTS = ${SOURCES:.c=.o}
 
-CFLAGS += -fPIC -DPIC $(GTK_CFLAGS) $(ALSA_CFLAGS) \
-	-I../../../intl -I../../..
+CFLAGS += -fPIC -DPIC $(GTK_CFLAGS) $(GMODULE_CFLAGS) -DAMIDIPLUGDATADIR=\"$(AMIDIPLUGDATADIR)\" \
+          -I../../../intl -I../../..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/amidi-plug-icon.xpm	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,398 @@
+/* XPM */
+static char * amidi_plug_icon_xpm[] = {
+"48 48 347 2",
+"  	c #FFFFFF",
+". 	c #FAFAFA",
+"+ 	c #7E7E7E",
+"@ 	c #414141",
+"# 	c #646464",
+"$ 	c #858585",
+"% 	c #848484",
+"& 	c #828282",
+"* 	c #838383",
+"= 	c #868686",
+"- 	c #878787",
+"; 	c #888888",
+"> 	c #898989",
+", 	c #8A8A8A",
+"' 	c #595959",
+") 	c #4C4C4C",
+"! 	c #ADADAD",
+"~ 	c #F8F8F8",
+"{ 	c #575757",
+"] 	c #090909",
+"^ 	c #040404",
+"/ 	c #000000",
+"( 	c #010101",
+"_ 	c #030303",
+": 	c #050505",
+"< 	c #080808",
+"[ 	c #0C0C0C",
+"} 	c #2B2B28",
+"| 	c #494944",
+"1 	c #4B4B46",
+"2 	c #3C3C37",
+"3 	c #49493F",
+"4 	c #4C4C41",
+"5 	c #4F4F44",
+"6 	c #4B4D46",
+"7 	c #444A4A",
+"8 	c #4A4D47",
+"9 	c #4E4E42",
+"0 	c #4D4D41",
+"a 	c #43433D",
+"b 	c #4F4F49",
+"c 	c #4D4D47",
+"d 	c #181816",
+"e 	c #060606",
+"f 	c #020202",
+"g 	c #0E0E0E",
+"h 	c #929292",
+"i 	c #515151",
+"j 	c #0A0A0A",
+"k 	c #0D0D0D",
+"l 	c #40403C",
+"m 	c #6E6E66",
+"n 	c #717169",
+"o 	c #7C7C6A",
+"p 	c #CFCFA9",
+"q 	c #D1D1AA",
+"r 	c #D3D3AC",
+"s 	c #C8CAA9",
+"t 	c #AFB8A3",
+"u 	c #B0B9A4",
+"v 	c #C4C8A9",
+"w 	c #D7D7AE",
+"x 	c #D8D8AE",
+"y 	c #D7D7AD",
+"z 	c #727265",
+"A 	c #6C6C63",
+"B 	c #21211F",
+"C 	c #070707",
+"D 	c #8D8D8D",
+"E 	c #3F3F3B",
+"F 	c #63635C",
+"G 	c #65655E",
+"H 	c #7A7A68",
+"I 	c #D4D4AD",
+"J 	c #D6D6AF",
+"K 	c #D8D8B0",
+"L 	c #D9D9B1",
+"M 	c #DADAB2",
+"N 	c #DBDBB2",
+"O 	c #DCDCB2",
+"P 	c #DCDCB3",
+"Q 	c #DDDDB2",
+"R 	c #DCDCB1",
+"S 	c #727263",
+"T 	c #6A6A62",
+"U 	c #696960",
+"V 	c #2F2F2C",
+"W 	c #0B0B0B",
+"X 	c #3D3D39",
+"Y 	c #5B5B55",
+"Z 	c #5E5E57",
+"` 	c #747463",
+" .	c #C5C5A1",
+"..	c #C7C7A2",
+"+.	c #C8C8A4",
+"@.	c #CACAA5",
+"#.	c #CBCBA6",
+"$.	c #CCCCA6",
+"%.	c #CBCBA5",
+"&.	c #CACAA3",
+"*.	c #6F6F5F",
+"=.	c #5A5A53",
+"-.	c #585851",
+";.	c #121212",
+">.	c #181818",
+",.	c #252523",
+"'.	c #363631",
+").	c #383833",
+"!.	c #373732",
+"~.	c #3C3C36",
+"{.	c #3A3A34",
+"].	c #383832",
+"^.	c #35352F",
+"/.	c #31312C",
+"(.	c #1B1B19",
+"_.	c #111111",
+":.	c #101010",
+"<.	c #525252",
+"[.	c #131313",
+"}.	c #151515",
+"|.	c #191919",
+"1.	c #1A1A1A",
+"2.	c #171717",
+"3.	c #0F0F0F",
+"4.	c #1C1C1C",
+"5.	c #1D1D1D",
+"6.	c #1E1E1E",
+"7.	c #8F8F8F",
+"8.	c #5F5F5F",
+"9.	c #323232",
+"0.	c #272727",
+"a.	c #313131",
+"b.	c #1F1F1F",
+"c.	c #333333",
+"d.	c #3D3D3D",
+"e.	c #2C2C2C",
+"f.	c #383838",
+"g.	c #474747",
+"h.	c #404040",
+"i.	c #141414",
+"j.	c #444444",
+"k.	c #242424",
+"l.	c #5B5B5B",
+"m.	c #464646",
+"n.	c #5C5C5C",
+"o.	c #3E3E3E",
+"p.	c #717171",
+"q.	c #212121",
+"r.	c #353535",
+"s.	c #5A5A5A",
+"t.	c #6C6C6C",
+"u.	c #4A4A4A",
+"v.	c #202020",
+"w.	c #737373",
+"x.	c #5D5D5D",
+"y.	c #777777",
+"z.	c #161616",
+"A.	c #909090",
+"B.	c #7D7D7D",
+"C.	c #797979",
+"D.	c #818181",
+"E.	c #222222",
+"F.	c #7F7F7F",
+"G.	c #2A2A2A",
+"H.	c #979797",
+"I.	c #6B6B6B",
+"J.	c #6D6D6D",
+"K.	c #F9F9F9",
+"L.	c #7B7B7B",
+"M.	c #454545",
+"N.	c #727272",
+"O.	c #626262",
+"P.	c #1B1B1B",
+"Q.	c #7C7C7C",
+"R.	c #919191",
+"S.	c #808080",
+"T.	c #555555",
+"U.	c #686868",
+"V.	c #676767",
+"W.	c #7A7A7A",
+"X.	c #959595",
+"Y.	c #8E8E8E",
+"Z.	c #2E2E2E",
+"`.	c #FBFBFB",
+" +	c #656565",
+".+	c #585858",
+"++	c #616161",
+"@+	c #5E5E5E",
+"#+	c #6A6A6A",
+"$+	c #696969",
+"%+	c #6F6F6F",
+"&+	c #989898",
+"*+	c #2F2F2F",
+"=+	c #363636",
+"-+	c #757575",
+";+	c #8B8B8B",
+">+	c #282828",
+",+	c #6E6E6E",
+"'+	c #9A9A9A",
+")+	c #232323",
+"!+	c #787878",
+"~+	c #9B9B9B",
+"{+	c #707070",
+"]+	c #9C9C9C",
+"^+	c #303030",
+"/+	c #9D9D9D",
+"(+	c #A6A6A6",
+"_+	c #939393",
+":+	c #4F4F4F",
+"<+	c #8C8C8C",
+"[+	c #949494",
+"}+	c #999999",
+"|+	c #9E9E9E",
+"1+	c #747474",
+"2+	c #C9C9C9",
+"3+	c #666666",
+"4+	c #969696",
+"5+	c #9F9F9F",
+"6+	c #A0A0A0",
+"7+	c #D4D4D4",
+"8+	c #A3A3A3",
+"9+	c #767676",
+"0+	c #A1A1A1",
+"a+	c #A5A5A5",
+"b+	c #A8A8A8",
+"c+	c #A9A9A9",
+"d+	c #A7A7A7",
+"e+	c #B1B1B1",
+"f+	c #DBDBDB",
+"g+	c #FCFCFC",
+"h+	c #BBBBBB",
+"i+	c #B9B9B9",
+"j+	c #BEBEBE",
+"k+	c #C1C1C1",
+"l+	c #C4C4C4",
+"m+	c #CACACA",
+"n+	c #AAAAAA",
+"o+	c #BFBFBF",
+"p+	c #D6D6D6",
+"q+	c #B2B2B2",
+"r+	c #E5E5E5",
+"s+	c #E7E7E7",
+"t+	c #ACACAC",
+"u+	c #EDEDED",
+"v+	c #F0F0F0",
+"w+	c #F2F2F2",
+"x+	c #F3F3F3",
+"y+	c #B7B7B7",
+"z+	c #F4F4F4",
+"A+	c #F5F5F5",
+"B+	c #E6E6E6",
+"C+	c #D9D9D9",
+"D+	c #CECECE",
+"E+	c #EBEBEB",
+"F+	c #D3D3D3",
+"G+	c #636363",
+"H+	c #CBCBCB",
+"I+	c #565656",
+"J+	c #C3C3C3",
+"K+	c #AEAEAE",
+"L+	c #A2A2A2",
+"M+	c #B4B4B4",
+"N+	c #C6C6C6",
+"O+	c #C7C7C7",
+"P+	c #CCCCCC",
+"Q+	c #C2C2C2",
+"R+	c #E3E3E3",
+"S+	c #ABABAB",
+"T+	c #B5B5B5",
+"U+	c #BCBCBC",
+"V+	c #C5C5C5",
+"W+	c #CDCDCD",
+"X+	c #AFAFAF",
+"Y+	c #B3B3B3",
+"Z+	c #BABABA",
+"`+	c #CFCFCF",
+" @	c #D1D1D1",
+".@	c #D5D5D5",
+"+@	c #D2D2D2",
+"@@	c #D7D7D7",
+"#@	c #FDFDFD",
+"$@	c #BDBDBD",
+"%@	c #C0C0C0",
+"&@	c #C8C8C8",
+"*@	c #D8D8D8",
+"=@	c #DFDFDF",
+"-@	c #E2E2E2",
+";@	c #E9E9E9",
+">@	c #ECECEC",
+",@	c #EEEEEE",
+"'@	c #F6F6F6",
+")@	c #F7F7F7",
+"!@	c #DADADA",
+"~@	c #D0D0D0",
+"{@	c #DCDCDC",
+"]@	c #FEFEFE",
+"^@	c #DDDDDD",
+"/@	c #E0E0E0",
+"(@	c #E4E4E4",
+"_@	c #EAEAEA",
+":@	c #E8E8E8",
+"<@	c #F1F1F1",
+"[@	c #373737",
+"}@	c #393939",
+"|@	c #3A3A3A",
+"1@	c #3B3B3B",
+"2@	c #3C3C3C",
+"3@	c #3F3F3F",
+"4@	c #434343",
+"5@	c #494949",
+"6@	c #4D4D4D",
+"7@	c #545454",
+"8@	c #4B4B4B",
+"9@	c #FEFCFC",
+"0@	c #E3DCDC",
+"a@	c #D08585",
+"b@	c #CF8484",
+"c@	c #D38D8D",
+"d@	c #F7EAEA",
+"e@	c #EFEFEF",
+"f@	c #AD7575",
+"g@	c #AC2929",
+"h@	c #AD2929",
+"i@	c #BA5454",
+"j@	c #F1E4E4",
+"k@	c #F9F8F8",
+"l@	c #B0B0B0",
+"m@	c #B6B6B6",
+"n@	c #B54242",
+"o@	c #AB2424",
+"p@	c #AB2525",
+"q@	c #AE2D2D",
+"r@	c #B8B8B8",
+"s@	c #FFFEFE",
+"t@	c #D59292",
+"u@	c #AB2828",
+"v@	c #AB2727",
+"w@	c #C16060",
+"x@	c #E9DEDE",
+"y@	c #E5E1E1",
+"z@	c #E5E2E2",
+"A@	c #E6E2E2",
+"B@	c #CCB0B0",
+"C@	c #BF9090",
+"D@	c #C09191",
+"E@	c #D0BBBB",
+"F@	c #E1E1E1",
+"    . + @ # $ $ $ $ $ % & * * % $ = = - $ = = $ * % % % $ $ $ = - - ; - - ; > > > , ' ) !       ",
+"    ~ { ] ^ / / / / ( ( _ : < [ } | 1 2 3 4 5 6 7 7 8 5 9 0 0 a b c d e ^ f ( ( / / ] g h       ",
+"    ~ i / / / / / / ( f _ e j k l m n o p q r s t u v w x x y z m A B C ^ f ( / / / / _ D       ",
+"    ~ i / / / / / / ( f ^ C j g E F G H I J K L M N O P Q O R S T U V < : f ( / / / / _ D       ",
+"    ~ i / / / / / / ( f ^ C W g X Y Z `  ...+.@.#.$.$.$.$.%.&.*.=.-.} < : _ f ( / / / _ D       ",
+"    ~ i / / / / / ( f f : < j g ;.;.>.,.'.).!.'.~.).'.{.].^./.(._.:.j < e _ f ( / / ( _ D       ",
+"    ~ <.( / / / / / ( / f ^ ( e ] ( k _.[.}.k C |.[ j 1.|.|.>.: ] 2.f [ }./ 3.4.5.6.[.^ 7.      ",
+"    ~ 8._.f [.9.0.a.[./ b._./ 0.:.( c.d.e.f.[ g f.j _.g.d.h.@ e i.j.^ 4.j.f k.l.m.n.o.C 7.      ",
+"    ~ p.q._ r.p.s.t.k./ u.q./ n.v._ w.= x.y.|.|.y.z.6.A.B.C.$ :.1.D.j E.F.C G.H.I.H.J.g D       ",
+"    K.L.6.f M.N.' I.6./ <.5./ O.6.e y.- 8.L.P.|.Q.|.4.A.- N.7.}.3., :.;.D g i.H.w.R.& 1.D       ",
+"    . S.2.( T.N.' U.>./ s.|._ V.P.< W.; U.+ 4.|.& P.>.A.7.p.X.v.j , 5.< D b.e Y.& & A.Z.D       ",
+"    `.L._.(  +N..+++i._ @+z.e #+|.W B., $+D.6.|.= b.>.7.X.%+&+Z.C D.*+_ F.=+f L.h -+H.M.Y.      ",
+"    . w.k < J.N.' l._.< @+i.[ #+|.:.D.;+#+$ E.v., >+E.Y.&+,+'+h.)+L.j.2.!+) [ t.~+J.~+8.h       ",
+"    . C.6.b.p.{+n.s.|.i.++4.i.%+q.;.% D t., G.2.Y.9.i.R.~+,+]+T.^+L.@+}.C.$+k {+/+I./++ (+      ",
+"    `._+:+.+N.t.++y.%+n.B.y.s.% & n.<+Y.,+[+h O.}+H. +]+/+{+|+]+1+]+]+U.~+]+V.]+|+J./+}+2+      ",
+"    `.]+8.V.w.3+I.!+%+I.+ C.#+= $ #+Y.A.%+4+&+{+~+/+N.|+5+1+5+5+p.|+|+p.]+|+w.}+5+C.R.6+7+      ",
+"    `.]+@+I.w.8.w.!+U.w.F.-+p.- % %+7.R.p.H.'+-+/+5+-+6+6+1+6+6+1+|+5+C.4+5+* <+5+7.L.6+7+      ",
+"    `.8+U.9+y.8.W.Q.3+B.* w.L.<+- y.X.H.y.|+0+C.a+(+L.b+c+L.b+b+S.5+d+<+A.d+'+* (+8+% e+f+      ",
+"    g+h+% c+i+7.j+k+H.l+m+n+o+p+m+q+r+s+t+u+v+e+w+x+y+z+z+i+z+A+l+B+z+C+D+z+E+i+x+v+a+F+E+      ",
+"    `.5+G+1+-+n.!+W.O.Q.S.,+W.$ F.1+D D p._+4+9+'+'+C.~+~+C.}+H.L.7.[+; D.R.X.{+;+~+I.7.H+      ",
+"    . 7.' T.<.i <.T.I+' n.@+8.++ + +V.t.J.%+w.N.N.9+1+w.-+1+p.p.-+p.{+Q.,+J.D.t.t.$ -+Q.J+      ",
+"    `.K+> A.4+&+'+/+5+L+a+d+n+K+e+M+y+h+j+k+J+N+O+2+m+H+P+P+P+H+H+H+m+m+m+m+m+m+m+m+Q+k+R+      ",
+"    g+M+h [+4+&+~+/+5+L+a+b+S+K+q+T+i+U+o+Q+V+O+2+m+P+P+W+W+W+P+P+P+H+H+m+m+m+m+m+m+m+H+s+      ",
+"    g+M+h [+H.}+~+/+6+8+(+c+t+X+Y+y+Z+j+k+l+O+2+H+P+W+D+`+`+D+D+W+W+P+H+H+H+H+m+H+H+H+P+s+      ",
+"    g+y+H.H.H.}+]+5+0+a+b+S+X+Y+y+h+o+J+N+m+P+`+ @F+7+.@.@.@.@7+F+F++@+@+@ @ @ @ @+@@@C+u+      ",
+"    #@m+Y+y+Z+$@%@Q+V+&@H+D+ @.@*@f+=@-@B+;@>@,@v+w+x+z+A+'@'@)@~ ~ K.K.. . . `.`.g+'@A+.       ",
+"    #@!@H+~@p+C+{@=@-@B+;@>@v+z+)@`.#@]@                                                        ",
+"    #@m+Y+%@P+`++@7+@@!@^@/@(@s+_@,@w+A+)@K.K.. . . . . `.`.`.`.`.`.`.`.`.`.`.`.`.`.:@-@<@      ",
+"    . S.m.d.=+[@f.}@f.f.}@|@1@2@d.o.3@3@3@@ 4@m.5@6@<.T..+l.x.x.x.x.n.s..+I+7@<.6@8@{ n.T+      ",
+"    ~ 7@^ f / / / / / / / / / / / / / / ( f ^ < [ 3.[.z.|.P.5.6.6.5.P.>.}._.g j e _ ^ < 7.      ",
+"    ~ i / / / / / / / / / / / / / / / / / ( _ : < [ g _.[.}.2.2.2.z.i.;.:.k ] e _ f / _ D       ",
+"    ~ i / / / / / / / / / / / / / / / / / ( ( f ^ C j k g :._._._._.3.g W < : _ f ( / _ D       ",
+"    ~ i / / / / / / / / / / / / / / / / / / / ( f ^ : < j W [ [ [ [ W ] C ^ _ f ( / / _ D       ",
+"    ~ .+] ^ / / / / / / / / / / / / / / / / / / / / ( f f f _ _ _ _ f f ( ( / / / / j :.h       ",
+"    `.(+B.y.p.8.i p.p.9+9+9+9+9+9+9+9+9+9+9+9+9+9+L.L.L.L.L.L.L.L.L.Q.F.F.D.* * * * = ; 2+      ",
+"            ]@e+=@                                                                              ",
+"            '@|+#@            .             '@                9@                                ",
+"            B+t+    ]@!@'@  N+<+{@A+*@]@  F+D R+    s+_+4+t+0@a@b@a@a@a@a@a@a@a@c@d@            ",
+"            !@y+    >@D.T+e@D n+U+j+C.. `.S+a+k+  K.L+}+o+, f@g@g@g@g@g@g@g@g@h@i@j@k@k@]@      ",
+"            -@b+)@  W+h+[+{@l@~+~@6+D `.;@S+(+p+  !@m@]@  , n@o@p@p@p@p@p@p@p@q@, , , , ,       ",
+"            . D L+p+q+W.r@p+t.}+v+I.r@  (@# d+#@g+b+(@  s@t@u@v@v@v@v@v@v@v@u@w@x@y@z@A@k@      ",
+"              ,@X+; -+g.$ % N.S+A.t.X+O+R.%+J+`+d+l@]@    B@C@D@D@D@D@D@D@D@D@E@                ",
+"                  x+;@{@2+f+^@(+m+F@'+[+J+{@A.D.L+)@                                            ",
+"                                    K.)@    A+<@`.                                              ",
+"                                                                                                ",
+"                                                                                                ",
+"                                                                                                ",
+"                                                                                                "};
--- a/Plugins/Input/amidi-plug/amidi-plug.c	Mon Jul 10 04:42:53 2006 -0700
+++ b/Plugins/Input/amidi-plug/amidi-plug.c	Mon Jul 10 04:52:51 2006 -0700
@@ -30,20 +30,20 @@
 
 static gint amidiplug_is_our_file( gchar * filename )
 {
-#ifdef MIDIFILE_PROBE_MAGICBYTES
-    VFSFile * fp;
+#if defined(MIDIFILE_PROBE_MAGICBYTES)
+    FILE * fp;
     gchar magic_bytes[4];
 
-    fp = vfs_fopen( filename , "rb" );
+    fp = fopen( filename , "rb" );
 
-    if (fp == NULL)
-	return FALSE;
+    if ( fp == NULL )
+      return FALSE;
 
-    vfs_fread( magic_bytes , 1 , 4 , fp );
+    fread( magic_bytes , 1 , 4 , fp );
 
     if ( !strncmp( magic_bytes , "MThd" , 4 ) )
     {
-      vfs_fclose( fp );
+      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 );
+      fseek( fp , 4 , SEEK_CUR );
+      fread( magic_bytes , 1 , 4 , fp );
       if ( !strncmp( magic_bytes , "RMID" , 4 ) )
       {
-        vfs_fclose( fp );
+        fclose( fp );
         DEBUGMSG( "MIDI found, %s is a riff midi file\n" , filename );
         return TRUE;
       }
     }
-    vfs_fclose( fp );
+    fclose( fp );
 #else
     gchar * ext = strrchr( filename, '.' );
     /* check the filename extension */
@@ -78,40 +78,27 @@
 {
   g_log_set_handler(NULL , G_LOG_LEVEL_WARNING , g_log_default_handler , NULL);
   DEBUGMSG( "init, read configuration\n" );
-  /* read configuration */
-  i_configure_cfg_read();
+  /* read configuration for amidi-plug */
+  i_configure_cfg_ap_read();
   amidiplug_playing_status = AMIDIPLUG_STOP;
+  backend.gmodule = NULL;
+  /* load the backend selected by user */
+  i_backend_load( amidiplug_cfg_ap.ap_seq_backend );
 }
 
 
 static void amidiplug_cleanup( void )
 {
+  i_backend_unload(); /* unload currently loaded backend */
   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 );
-  }
+  /* display the nice config dialog */
+  DEBUGMSG( "opening config system\n" );
+  i_configure_gui();
 }
 
 
@@ -137,6 +124,8 @@
     amidiplug_playing_status = AMIDIPLUG_STOP;
     pthread_mutex_unlock( &amidiplug_playing_mutex );
     pthread_join( amidiplug_play_thread , NULL );
+    if ( backend.autonomous_audio == FALSE )
+      pthread_join( amidiplug_audio_thread , NULL );
     DEBUGMSG( "STOP activated (play thread joined)\n" );
   }
   else if ( amidiplug_playing_status == AMIDIPLUG_PAUSE )
@@ -150,10 +139,25 @@
     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) */
+
+  /* kill the sequencer (while it may have been already killed if coming
+     from pause, it's safe to do anyway since it checks for multiple calls) */
+  if ( backend.gmodule != NULL )
+    backend.seq_off();
+
+  /* call seq_stop */
+  if ( backend.gmodule != NULL )
+    backend.seq_stop();
+
+  /* close audio if current backend works with output plugin */
+  if (( backend.gmodule != NULL ) && ( backend.autonomous_audio == FALSE ))
+  {
+    DEBUGMSG( "STOP activated, closing audio output plugin\n" );
+    amidiplug_ip.output->buffer_free();
+    amidiplug_ip.output->buffer_free();
+    amidiplug_ip.output->close_audio();
+  }
+  /* free midi data (if it has not been freed yet) */
   i_midi_free( &midifile );
 }
 
@@ -171,22 +175,30 @@
     pthread_mutex_unlock( &amidiplug_playing_mutex );
 
     pthread_join( amidiplug_play_thread , NULL );
+    if ( backend.autonomous_audio == FALSE )
+      pthread_join( amidiplug_audio_thread , NULL );
     DEBUGMSG( "PAUSE activated (play thread joined)\n" , midifile.playing_tick );
 
+    if ( backend.autonomous_audio == FALSE )
+      amidiplug_ip.output->pause(paused);
+
     /* kill the sequencer */
-    i_seq_off();
+    backend.seq_off();
   }
   else
   {
     DEBUGMSG( "PAUSE deactivated, returning to tick %i\n" , midifile.playing_tick );
     /* revive the sequencer */
-    i_seq_on( 0 , NULL );
+    backend.seq_on();
     /* re-set initial tempo */
     i_midi_setget_tempo( &midifile );
-    i_seq_queue_set_tempo( midifile.current_tempo , midifile.ppq );
+    backend.seq_queue_tempo( midifile.current_tempo , midifile.ppq );
     /* get back to the previous state */
     amidiplug_skipto( midifile.playing_tick );
 
+    if ( backend.autonomous_audio == FALSE )
+      amidiplug_ip.output->pause(paused);
+
     pthread_mutex_lock( &amidiplug_playing_mutex );
     /* play play play! */
     DEBUGMSG( "PAUSE deactivated, starting play thread again\n" );
@@ -205,24 +217,30 @@
   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 );
+    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 );
+  if ( backend.autonomous_audio == FALSE )
+    pthread_join( amidiplug_audio_thread , NULL );
   DEBUGMSG( "SEEK requested (time %i), song paused\n" , time );
   /* kill the sequencer */
-  i_seq_off();
+  backend.seq_off();
   /* revive the sequencer */
-  i_seq_on( 0 , NULL );
+  backend.seq_on();
   /* re-set initial tempo */
   i_midi_setget_tempo( &midifile );
-  i_seq_queue_set_tempo( midifile.current_tempo , midifile.ppq );
+  backend.seq_queue_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 );
+
+  if ( backend.autonomous_audio == FALSE )
+    amidiplug_ip.output->flush(time * 1000);
+
   /* play play play! */
   DEBUGMSG( "SEEK done, starting play thread again\n" );
   pthread_create(&amidiplug_play_thread, NULL, amidiplug_play_loop, NULL);
@@ -231,52 +249,77 @@
 
 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 ))
+  if ( backend.autonomous_audio == FALSE )
   {
-    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);
+    pthread_mutex_lock( &amidiplug_playing_mutex );
+    if (( amidiplug_playing_status == AMIDIPLUG_PLAY ) ||
+        ( amidiplug_playing_status == AMIDIPLUG_PAUSE ) ||
+        (( amidiplug_playing_status == AMIDIPLUG_STOP ) && ( amidiplug_ip.output->buffer_playing() )))
+    {
+      pthread_mutex_unlock( &amidiplug_playing_mutex );
+      return amidiplug_ip.output->output_time();
+    }
+    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" );
+      xmms_remote_stop(0);
+      return -1;
+    }
   }
-  else if ( amidiplug_playing_status == AMIDIPLUG_STOP )
+  else
   {
-    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;
+    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_get_volume( gint * l , gint * r )
+static void amidiplug_get_volume( gint * l_p , gint * r_p )
 {
-  gchar mixer_card[10];
-  snprintf( mixer_card , 8 , "hw:%i" , amidiplug_cfg.mixer_card_id );
-  mixer_card[9] = '\0';
-  /* get volume */
-  i_seq_mixer_get_volume( l , r , mixer_card , amidiplug_cfg.mixer_control_name ,
-                          amidiplug_cfg.mixer_control_id );
+  if ( backend.autonomous_audio == TRUE )
+    backend.audio_volume_get( l_p , r_p );
+  else
+    amidiplug_ip.output->get_volume( l_p , r_p );
+  return;
 }
 
 
 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 );
+  if ( backend.autonomous_audio == TRUE )
+    backend.audio_volume_set( l , r );
+  else
+    amidiplug_ip.output->set_volume( l , r );
+  return;
 }
 
 
@@ -286,11 +329,9 @@
   *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 */
-
-  if ( amidiplug_cfg.length_precalc_enable )
+     but the file must be entirely parsed to calculate it; this could
+     lead to a bit of performance loss, so let the user decide here */
+  if ( amidiplug_cfg_ap.ap_opts_length_precalc )
   {
     /* let's calculate the midi length, using this nice helper function that
        will return 0 if a problem occurs and the length can't be calculated */
@@ -313,15 +354,38 @@
 static void amidiplug_play( gchar * filename )
 {
   gint port_count = 0;
+  gint au_samplerate = -1, au_bitdepth = -1, au_channels = -1;
+
+  if ( backend.gmodule == NULL )
+  {
+    g_warning( "No sequencer backend selected\n" );
+    i_message_gui( _("AMIDI-Plug - warning") ,
+                   _("No sequencer backend has been selected!\nPlease configure AMIDI-Plug before playing.") ,
+                   AMIDIPLUG_MESSAGE_WARN , NULL );
+    amidiplug_playing_status = AMIDIPLUG_ERR;
+    return;
+  }
+
+  /* get information about audio from backend, if available */
+  backend.audio_info_get( &au_channels , &au_bitdepth , &au_samplerate );
+  DEBUGMSG( "PLAY requested, audio details: channels -> %i , bitdepth -> %i , samplerate -> %i\n" ,
+            au_channels , au_bitdepth , au_samplerate );
+
+  if ( backend.autonomous_audio == FALSE )
+  {
+    DEBUGMSG( "PLAY requested, opening audio output plugin\n" );
+    amidiplug_ip.output->open_audio( FMT_S16_NE , au_samplerate , au_channels );
+  }
+
   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 , ':' );
+  /* get the number of selected ports */
+  port_count = backend.seq_get_port_count();
   if ( port_count < 1 )
   {
-    g_warning( "No ALSA ports selected\n" );
+    g_warning( "No ports selected\n" );
     amidiplug_playing_status = AMIDIPLUG_ERR;
     return;
   }
@@ -362,16 +426,21 @@
       if ( !i_midi_setget_tempo( &midifile ) )
         WARNANDBREAKANDPLAYERR( "%s: invalid values while setting ppq and tempo\n" , filename );
 
-      DEBUGMSG( "PLAY requested, sequencer init\n" );
+      DEBUGMSG( "PLAY requested, sequencer start\n" );
+      /* sequencer start */
+      if ( !backend.seq_start( filename ) )
+        WARNANDBREAKANDPLAYERR( "%s: problem with seq_start, play aborted\n" , filename );
+
+      DEBUGMSG( "PLAY requested, sequencer on\n" );
       /* sequencer on */
-      if ( !i_seq_on( 1 , amidiplug_cfg.seq_writable_ports ) )
-        WARNANDBREAKANDPLAYERR( "%s: ALSA problem, play aborted\n" , filename );
+      if ( !backend.seq_on() )
+        WARNANDBREAKANDPLAYERR( "%s: problem with seq_on, 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 ) )
+      if ( !backend.seq_queue_tempo( midifile.current_tempo , midifile.ppq ) )
       {
-        i_seq_off(); /* kill the sequencer */
+        backend.seq_off(); /* kill the sequencer */
         WARNANDBREAKANDPLAYERR( "%s: ALSA queue problem, play aborted\n" , filename );
       }
 
@@ -380,7 +449,10 @@
       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 );
+      amidiplug_ip.set_info( G_PATH_GET_BASENAME(filename) ,
+                             (gint)(midifile.length / 1000) ,
+                             au_bitdepth * au_samplerate * au_channels / 8 ,
+                             au_samplerate , au_channels );
 
       /* play play play! */
       DEBUGMSG( "PLAY requested, starting play thread\n" );
@@ -405,8 +477,7 @@
 
 void * amidiplug_play_loop( void * arg )
 {
-  snd_seq_event_t ev;
-  gint i, p, c;
+  gint i = 0;
   gboolean rewind = FALSE;
 
   pthread_mutex_lock( &amidiplug_playing_mutex );
@@ -428,14 +499,16 @@
     /* 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);
+    backend.seq_queue_start();
+  }
+
+  if ( backend.autonomous_audio == FALSE )
+  {
+    pthread_create(&amidiplug_audio_thread, NULL, amidiplug_audio_loop, 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;
+  backend.seq_event_init();
 
   DEBUGMSG( "PLAY thread, start the play loop\n" );
   for (;;)
@@ -471,124 +544,67 @@
 
     /* advance pointer to next event */
     event_track->current_event = event->next;
+    /* consider the midifile.skip_offset */
+    event->tick_real = event->tick - midifile.skip_offset;
 
-    /* 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)
+    switch (event->type)
     {
       case SND_SEQ_EVENT_NOTEON:
+        backend.seq_event_noteon( event );
+        break;
       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];
+        backend.seq_event_noteoff( event );
         break;
-      }
+      case SND_SEQ_EVENT_KEYPRESS:
+        backend.seq_event_keypress( event );
+        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];
+        backend.seq_event_controller( event );
         break;
-      }
       case SND_SEQ_EVENT_PGMCHANGE:
+        backend.seq_event_pgmchange( event );
+        break;
       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];
+        backend.seq_event_chanpress( event );
         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;
+        backend.seq_event_pitchbend( event );
         break;
-      }
       case SND_SEQ_EVENT_SYSEX:
-      {
-        snd_seq_ev_set_variable(&ev, event->data.length, event->sysex);
+        backend.seq_event_sysex( event );
         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;
+        backend.seq_event_tempo( event );
         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 );
+        DEBUGMSG( "PLAY thread, encountered invalid event type %i\n" , event->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);
-  }
-
-  /* time to shutdown playback! */
-  /* send "ALL SOUNDS OFF" to all channels on all ports */
-  ev.type = SND_SEQ_EVENT_CONTROLLER;
-  ev.time.tick = 0;
-  snd_seq_ev_set_fixed(&ev);
-  ev.data.control.param = MIDI_CTL_ALL_SOUNDS_OFF;
-  ev.data.control.value = 0;
-  for ( p = 0 ; p < sc.dest_port_num ; p++)
-  {
-    ev.queue = sc.queue;
-    ev.dest = sc.dest_port[p];
-
-    for ( c = 0 ; c < 16 ; c++ )
+    if ( backend.autonomous_audio == TRUE )
     {
-      ev.data.control.channel = c;
-      snd_seq_event_output(sc.seq, &ev);
-      snd_seq_drain_output(sc.seq);
+      /* these backends deal with audio production themselves (i.e. ALSA) */
+      backend.seq_output( NULL , NULL );
     }
   }
 
-  /* schedule queue stop at end of song */
-  snd_seq_ev_clear(&ev);
-  ev.queue = sc.queue;
-  ev.source.port = 0;
-  ev.flags = SND_SEQ_TIME_STAMP_TICK;
-
-  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); */
+  backend.seq_output_shut( midifile.max_tick , midifile.skip_offset );
 
   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 );
 
@@ -602,7 +618,6 @@
    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*/
@@ -614,12 +629,8 @@
     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);
+  backend.seq_event_init();
+  backend.seq_queue_start();
 
   DEBUGMSG( "SKIPTO request, starting skipto loop\n" );
   for (;;)
@@ -657,13 +668,10 @@
 
     /* advance pointer to next event */
     event_track->current_event = event->next;
+    /* set the time tick to 0 */
+    event->tick_real = 0;
 
-    /* output the event */
-    ev.type = event->type;
-    ev.time.tick = event->tick;
-    ev.dest = sc.dest_port[event->port];
-
-    switch (ev.type)
+    switch (event->type)
     {
       /* do nothing for these
       case SND_SEQ_EVENT_NOTEON:
@@ -673,65 +681,32 @@
         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);
+        backend.seq_event_controller( event );
         break;
-      }
       case SND_SEQ_EVENT_PGMCHANGE:
+        backend.seq_event_pgmchange( event );
+        break;
       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);
+        backend.seq_event_chanpress( event );
         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);
+        backend.seq_event_pitchbend( event );
         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);
+        backend.seq_event_sysex( event );
         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;
+        backend.seq_event_tempo( event );
         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;
-      }
+    }
+
+    if ( backend.autonomous_audio == TRUE )
+    {
+      /* these backends deal with audio production themselves (i.e. ALSA) */
+      backend.seq_output( NULL , NULL );
     }
   }
 
@@ -739,3 +714,28 @@
 
   return;
 }
+
+
+void * amidiplug_audio_loop( void * arg )
+{
+  gboolean going = 1;
+  gpointer buffer = NULL;
+  gint buffer_size = 0;
+  while ( going )
+  {
+    if ( backend.seq_output( &buffer , &buffer_size ) )
+    {
+      while( ( amidiplug_ip.output->buffer_free() < buffer_size ) && ( going == TRUE ) )
+        G_USLEEP(10000);
+      produce_audio( amidiplug_ip.output->written_time() ,
+                     FMT_S16_NE , 2 , buffer_size , buffer , &going );
+    }
+    pthread_mutex_lock( &amidiplug_playing_mutex );
+    if ( amidiplug_playing_status != AMIDIPLUG_PLAY )
+      going = FALSE;
+    pthread_mutex_unlock( &amidiplug_playing_mutex );
+  }
+  if ( buffer != NULL )
+    g_free( buffer );
+  pthread_exit(NULL);
+}
--- a/Plugins/Input/amidi-plug/amidi-plug.h	Mon Jul 10 04:42:53 2006 -0700
+++ b/Plugins/Input/amidi-plug/amidi-plug.h	Mon Jul 10 04:52:51 2006 -0700
@@ -28,11 +28,12 @@
 
 #include "i_common.h"
 #include "audacious/plugin.h"
+#include "audacious/output.h"
 #include "libaudacious/beepctrl.h"
 #include "libaudacious/vfs.h"
 #include <pthread.h>
+#include "i_backend.h"
 #include "i_configure.h"
-#include "i_seq.h"
 #include "i_midi.h"
 #include "i_fileinfo.h"
 #include "i_utils.h"
@@ -45,6 +46,7 @@
 
 
 static pthread_t amidiplug_play_thread;
+static pthread_t amidiplug_audio_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;
@@ -52,25 +54,18 @@
 gint amidiplug_playing_status = AMIDIPLUG_STOP;
 
 midifile_t midifile;
-sequencer_client_t sc =
+
+amidiplug_sequencer_backend_t backend;
+
+amidiplug_cfg_ap_t amidiplug_cfg_ap =
 {
-  NULL,		/* seq */
-  0,		/* client_port */
-  0,		/* queue */
-  NULL,		/* dest_port */
-  0		/* dest_port_num */
+  NULL,		/* ap_seq_backend */
+  0		/* ap_opts_length_precalc */
 };
 
-amidiplug_cfg_t amidiplug_cfg =
-{
-  NULL,		/* seq_writable_ports */
-  0,		/* mixer_card_id */
-  NULL,		/* mixer_control_name */
-  0,		/* mixer_control_id */
-  0		/* length_precalc_enable */
-};
 
 void * amidiplug_play_loop( void * );
+void * amidiplug_audio_loop( void * );
 void amidiplug_skipto( gint );
 static void amidiplug_init( void );
 static void amidiplug_cleanup( void );
@@ -112,7 +107,8 @@
   NULL,				/* set_info_text */
   amidiplug_get_song_info,	/* get_song_info */
   amidiplug_file_info_box,	/* file_info_box */
-  NULL				/* output */
+  NULL,				/* output */
+  NULL				/* get_song_tuple */
 };
 
 #endif /* !_I_AMIDIPLUG_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/backend-alsa/Makefile.in	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,15 @@
+include ../../../../mk/rules.mk
+include ../../../../mk/objective.mk
+
+noinst_HEADERS = b-alsa.h b-alsa-config.h backend-alsa-icon.xpm
+
+CFLAGS += -fPIC -DPIC $(GLIB_CFLAGS) $(ALSA_CFLAGS) -I../../../../intl -I../../../..
+
+libdir = $(AMIDIPLUGDATADIR)
+
+OBJECTIVE_LIBS = ap-alsa.so
+
+LIBADD = $(GLIB_LIBS) $(ALSA_LIBS) ../pcfg/libpcfg.a
+SOURCES = b-alsa.c
+
+OBJECTS = ${SOURCES:.c=.o}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/backend-alsa/b-alsa-config.h	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,35 @@
+/*
+*
+* 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 _B_ALSA_CONFIG_H
+#define _B_ALSA_CONFIG_H 1
+
+
+typedef struct
+{
+  gchar *	alsa_seq_wports;
+  gint		alsa_mixer_card_id;
+  gchar *	alsa_mixer_ctl_name;
+  gint		alsa_mixer_ctl_id;
+}
+amidiplug_cfg_alsa_t;
+
+
+#endif /* !_B_ALSA_CONFIG_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/backend-alsa/b-alsa.c	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,875 @@
+/*
+*
+* 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 "b-alsa.h"
+#include "b-alsa-config.h"
+
+/* sequencer instance */
+static sequencer_client_t sc;
+/* options */
+static amidiplug_cfg_alsa_t amidiplug_cfg_alsa;
+
+
+gint backend_info_get( gchar ** name , gchar ** longname , gchar ** desc , gint * ppos )
+{
+  if ( name != NULL )
+    *name = g_strdup( "alsa" );
+  if ( longname != NULL )
+    *longname = g_strdup( "ALSA Backend " AMIDIPLUG_VERSION );
+  if ( desc != NULL )
+    *desc = g_strdup( _("This backend sends MIDI events to a group of user-chosen "
+                        "ALSA sequencer ports. The ALSA sequencer interface is very "
+                        "versatile, it can provide ports for audio cards hardware "
+                        "synthesizers (i.e. emu10k1) but also for software synths, "
+                        "external devices, etc.\n"
+                        "This backend does not produce audio, MIDI events are handled "
+                        "directly from devices/programs behind the ALSA ports; in example, "
+                        "MIDI events sent to the hardware synth will be directly played.\n"
+                        "Backend written by Giacomo Lozito.") );
+  if ( ppos != NULL )
+    *ppos = 1; /* preferred position in backend list */
+  return 1;
+}
+
+
+gint backend_init( void )
+{
+  /* read configuration options */
+  i_cfg_read();
+
+  sc.seq = NULL;
+  sc.client_port = 0;
+  sc.queue = 0;
+  sc.dest_port = NULL;
+  sc.dest_port_num = 0;
+  sc.queue_tempo = NULL;
+  sc.is_start = FALSE;
+
+  return 1;
+}
+
+gint backend_cleanup( void )
+{
+  /* free configuration options */
+  i_cfg_free();
+
+  return 1;
+}
+
+
+gint sequencer_get_port_count( void )
+{
+  return i_util_str_count( amidiplug_cfg_alsa.alsa_seq_wports , ':' );
+}
+
+
+gint sequencer_start( gchar * midi_fname )
+{
+  sc.is_start = TRUE;
+  return 1; /* success */
+}
+
+
+gint sequencer_stop( void )
+{
+  return 1; /* success */
+}
+
+
+/* activate sequencer client */
+gint sequencer_on( void )
+{
+  gchar * wports_str = amidiplug_cfg_alsa.alsa_seq_wports;
+
+  if ( !i_seq_open() )
+  {
+    sc.seq = NULL;
+    return 0;
+  }
+
+  if ( !i_seq_port_create() )
+  {
+    i_seq_close();
+    sc.seq = NULL;
+    return 0;
+  }
+
+  if ( !i_seq_queue_create() )
+  {
+    i_seq_close();
+    sc.seq = NULL;
+    return 0;
+  }
+
+  if (( sc.is_start == TRUE ) && ( wports_str ))
+  {
+    sc.is_start = FALSE;
+    i_seq_port_wparse( wports_str );
+  }
+
+  if ( !i_seq_port_connect() )
+  {
+    i_seq_queue_free();
+    i_seq_close();
+    sc.seq = NULL;
+    return 0;
+  }
+
+  /* success */
+  return 1;
+}
+
+
+/* shutdown sequencer client */
+gint sequencer_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;
+}
+
+
+/* queue set tempo */
+gint sequencer_queue_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;
+}
+
+
+gint sequencer_queue_start( void )
+{
+  return snd_seq_start_queue( sc.seq , sc.queue , NULL );
+}
+
+
+gint sequencer_event_init( void )
+{
+  /* common settings for all our events */
+  snd_seq_ev_clear(&sc.ev);
+  sc.ev.queue = sc.queue;
+  sc.ev.source.port = 0;
+  sc.ev.flags = SND_SEQ_TIME_STAMP_TICK;
+  return 1;
+}
+
+
+gint sequencer_event_noteon( midievent_t * event )
+{
+  i_seq_event_common_init( event );
+  snd_seq_ev_set_fixed(&sc.ev);
+  sc.ev.data.note.channel = event->data.d[0];
+  sc.ev.data.note.note = event->data.d[1];
+  sc.ev.data.note.velocity = event->data.d[2];
+  return 1;
+}
+
+
+gint sequencer_event_noteoff( midievent_t * event )
+{
+  i_seq_event_common_init( event );
+  snd_seq_ev_set_fixed(&sc.ev);
+  sc.ev.data.note.channel = event->data.d[0];
+  sc.ev.data.note.note = event->data.d[1];
+  sc.ev.data.note.velocity = event->data.d[2];
+  return 1;
+}
+
+
+gint sequencer_event_keypress( midievent_t * event )
+{
+  i_seq_event_common_init( event );
+  snd_seq_ev_set_fixed(&sc.ev);
+  sc.ev.data.note.channel = event->data.d[0];
+  sc.ev.data.note.note = event->data.d[1];
+  sc.ev.data.note.velocity = event->data.d[2];
+  return 1;
+}
+
+
+gint sequencer_event_controller( midievent_t * event )
+{
+  i_seq_event_common_init( event );
+  snd_seq_ev_set_fixed(&sc.ev);
+  sc.ev.data.control.channel = event->data.d[0];
+  sc.ev.data.control.param = event->data.d[1];
+  sc.ev.data.control.value = event->data.d[2];
+  return 1;
+}
+
+
+gint sequencer_event_pgmchange( midievent_t * event )
+{
+  i_seq_event_common_init( event );
+  snd_seq_ev_set_fixed(&sc.ev);
+  sc.ev.data.control.channel = event->data.d[0];
+  sc.ev.data.control.value = event->data.d[1];
+  return 1;
+}
+
+
+gint sequencer_event_chanpress( midievent_t * event )
+{
+  i_seq_event_common_init( event );
+  snd_seq_ev_set_fixed(&sc.ev);
+  sc.ev.data.control.channel = event->data.d[0];
+  sc.ev.data.control.value = event->data.d[1];
+  return 1;
+}
+
+
+gint sequencer_event_pitchbend( midievent_t * event )
+{
+  i_seq_event_common_init( event );
+  snd_seq_ev_set_fixed(&sc.ev);
+  sc.ev.data.control.channel = event->data.d[0];
+  sc.ev.data.control.value = ((event->data.d[1]) | ((event->data.d[2]) << 7)) - 0x2000;
+  return 1;
+}
+
+
+gint sequencer_event_sysex( midievent_t * event )
+{
+  i_seq_event_common_init( event );
+  snd_seq_ev_set_variable(&sc.ev, event->data.length, event->sysex);
+  return 1;
+}
+
+
+gint sequencer_event_tempo( midievent_t * event )
+{
+  i_seq_event_common_init( event );
+  snd_seq_ev_set_fixed(&sc.ev);
+  sc.ev.dest.client = SND_SEQ_CLIENT_SYSTEM;
+  sc.ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER;
+  sc.ev.data.queue.queue = sc.queue;
+  sc.ev.data.queue.param.value = event->data.tempo;
+  return 1;
+}
+
+
+gint sequencer_event_other( midievent_t * event )
+{
+  /* unhandled */
+  return 1;
+}
+
+
+gint sequencer_output( gpointer * buffer , gint * len )
+{
+  snd_seq_event_output( sc.seq , &sc.ev );
+  snd_seq_drain_output( sc.seq );
+  snd_seq_sync_output_queue( sc.seq );
+  return 0;
+}
+
+
+gint sequencer_output_shut( guint max_tick , gint skip_offset )
+{
+  gint i = 0 , c = 0;
+  /* time to shutdown playback! */
+  /* send "ALL SOUNDS OFF" to all channels on all ports */
+  sc.ev.type = SND_SEQ_EVENT_CONTROLLER;
+  sc.ev.time.tick = 0;
+  snd_seq_ev_set_fixed(&sc.ev);
+  sc.ev.data.control.param = MIDI_CTL_ALL_SOUNDS_OFF;
+  sc.ev.data.control.value = 0;
+  for ( i = 0 ; i < sc.dest_port_num ; i++ )
+  {
+    sc.ev.queue = sc.queue;
+    sc.ev.dest = sc.dest_port[i];
+
+    for ( c = 0 ; c < 16 ; c++ )
+    {
+      sc.ev.data.control.channel = c;
+      snd_seq_event_output(sc.seq, &sc.ev);
+      snd_seq_drain_output(sc.seq);
+    }
+  }
+
+  /* schedule queue stop at end of song */
+  snd_seq_ev_clear(&sc.ev);
+  sc.ev.queue = sc.queue;
+  sc.ev.source.port = 0;
+  sc.ev.flags = SND_SEQ_TIME_STAMP_TICK;
+
+  snd_seq_ev_set_fixed(&sc.ev);
+  sc.ev.type = SND_SEQ_EVENT_STOP;
+  sc.ev.time.tick = max_tick - skip_offset;
+  sc.ev.dest.client = SND_SEQ_CLIENT_SYSTEM;
+  sc.ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER;
+  sc.ev.data.queue.queue = sc.queue;
+  snd_seq_event_output(sc.seq, &sc.ev);
+  snd_seq_drain_output(sc.seq);
+  /* snd_seq_sync_output_queue(sc.seq); */
+
+  return 1;
+}
+
+
+gint audio_volume_get( gint * left_volume , gint * right_volume )
+{
+  snd_mixer_t * mixer_h = NULL;
+  snd_mixer_elem_t * mixer_elem = NULL;
+  gchar mixer_card[10];
+  snprintf( mixer_card , 8 , "hw:%i" , amidiplug_cfg_alsa.alsa_mixer_card_id );
+  mixer_card[9] = '\0';
+
+  if ( snd_mixer_open( &mixer_h , 0 ) > -1 )
+    i_seq_mixer_find_selem( mixer_h , mixer_card ,
+                            amidiplug_cfg_alsa.alsa_mixer_ctl_name ,
+                            amidiplug_cfg_alsa.alsa_mixer_ctl_id ,
+                            &mixer_elem );
+  else
+    mixer_h = NULL;
+
+  if ( ( mixer_elem ) && ( snd_mixer_selem_has_playback_volume( mixer_elem ) ) )
+  {
+    glong pv_min , pv_max , pv_range;
+    glong lc, rc;
+
+    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 ) )
+      {
+        snd_mixer_selem_get_playback_volume( mixer_elem , SND_MIXER_SCHN_FRONT_LEFT , &lc );
+        /* convert the range to 0-100 (for the case that pv_range is not 0-100 already) */
+        *left_volume = (gint)(((lc - pv_min) * 100) / pv_range);
+        DEBUGMSG( "GET VOLUME requested, get left channel (%i)\n" , *left_volume );
+      }
+      if ( snd_mixer_selem_has_playback_channel( mixer_elem , SND_MIXER_SCHN_FRONT_RIGHT ) )
+      {
+        snd_mixer_selem_get_playback_volume( mixer_elem , SND_MIXER_SCHN_FRONT_RIGHT , &rc );
+        /* convert the range to 0-100 (for the case that pv_range is not 0-100 already) */
+        *right_volume = (gint)(((rc - pv_min) * 100) / pv_range);
+        DEBUGMSG( "GET VOLUME requested, get right channel (%i)\n" , *right_volume );
+      }
+    }
+  }
+
+  if ( mixer_h )
+    snd_mixer_close( mixer_h );
+  /* always return 1 here */
+  return 1;
+}
+
+
+gint audio_volume_set( gint left_volume , gint right_volume )
+{
+  snd_mixer_t * mixer_h = NULL;
+  snd_mixer_elem_t * mixer_elem = NULL;
+  gchar mixer_card[10];
+  snprintf( mixer_card , 8 , "hw:%i" , amidiplug_cfg_alsa.alsa_mixer_card_id );
+  mixer_card[9] = '\0';
+
+  if ( snd_mixer_open( &mixer_h , 0 ) > -1 )
+    i_seq_mixer_find_selem( mixer_h , mixer_card ,
+                            amidiplug_cfg_alsa.alsa_mixer_ctl_name ,
+                            amidiplug_cfg_alsa.alsa_mixer_ctl_id ,
+                            &mixer_elem );
+  else
+    mixer_h = NULL;
+
+  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)(0.01 * (gdouble)(left_volume * pv_range)) + 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)(0.01 * (gdouble)(right_volume * pv_range)) + pv_min) );
+      }
+    }
+  }
+
+  if ( mixer_h )
+    snd_mixer_close( mixer_h );
+  /* always return 1 here */
+  return 1;
+}
+
+
+gint audio_info_get( gint * channels , gint * bitdepth , gint * samplerate )
+{
+  /* not applicable for ALSA backend */
+  *channels = -1;
+  *bitdepth = -1;
+  *samplerate = -1;
+  return 0; /* not valid information */
+}
+
+
+gboolean audio_check_autonomous( void )
+{
+  return TRUE; /* ALSA deals directly with audio production */
+}
+
+
+
+/* ******************************************************************
+   *** EXTRA FUNCTIONS **********************************************
+   ****************************************************************** */
+
+
+/* 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 * sequencer_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 sequencer_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 * alsa_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 alsa_card_free_list( GSList * scards )
+{
+  GSList * start = scards;
+  while ( scards != NULL )
+  {
+    data_bucket_t * cardinfo = scards->data;
+    /* free the list of mixer controls for the sound card */
+    i_seq_mixctl_free_list( (GSList*)cardinfo->bpointer[0] );
+    g_free( (gpointer)cardinfo->bcharp[0] );
+    g_free( cardinfo );
+    scards = scards->next;
+  }
+  g_slist_free( start );
+  return;
+}
+
+
+
+/* ******************************************************************
+   *** INTERNALS ****************************************************
+   ****************************************************************** */
+
+
+/* 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 */
+}
+
+
+/* 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 */
+}
+
+
+gint i_seq_event_common_init( midievent_t * event )
+{
+  sc.ev.type = event->type;
+  sc.ev.time.tick = event->tick_real;
+  sc.ev.dest = sc.dest_port[event->port];
+  return 1;
+}
+
+
+/* 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_find_selem( snd_mixer_t * mixer_h , gchar * mixer_card ,
+                             gchar * mixer_control_name , gint mixer_control_id ,
+                             snd_mixer_elem_t ** mixer_elem )
+{
+  snd_mixer_selem_id_t * mixer_selem_id = NULL;
+  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_attach( mixer_h , mixer_card );
+  snd_mixer_selem_register( mixer_h , NULL , NULL);
+  snd_mixer_load( mixer_h );
+  /* assign the mixer element (can be NULL if there is no such element) */
+  *mixer_elem = snd_mixer_find_selem( mixer_h , mixer_selem_id );
+  /* always return 1 here */
+  return 1;
+}
+
+
+gchar * i_configure_read_seq_ports_default( void )
+{
+  FILE * fp = 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 option: do not set ports at all, let the user
+     select the right ones in the nice config window :) */
+  return g_strdup( "" );
+}
+
+
+/* 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_cfg_read( void )
+{
+  pcfg_t *cfgfile;
+  gchar * config_pathfilename = g_strjoin( "" , g_get_home_dir() , "/" ,
+                                           PLAYER_LOCALRCDIR , "/amidi-plug.conf" , NULL );
+  cfgfile = i_pcfg_new_from_file( config_pathfilename );
+
+  if ( !cfgfile )
+  {
+    /* alsa backend defaults */
+    amidiplug_cfg_alsa.alsa_seq_wports = i_configure_read_seq_ports_default();
+    amidiplug_cfg_alsa.alsa_mixer_card_id = 0;
+    amidiplug_cfg_alsa.alsa_mixer_ctl_name = g_strdup( "Synth" );
+    amidiplug_cfg_alsa.alsa_mixer_ctl_id = 0;
+  }
+  else
+  {
+    i_pcfg_read_string( cfgfile , "alsa" , "alsa_seq_wports" ,
+                        &amidiplug_cfg_alsa.alsa_seq_wports , NULL );
+    if ( amidiplug_cfg_alsa.alsa_seq_wports == NULL )
+      amidiplug_cfg_alsa.alsa_seq_wports = i_configure_read_seq_ports_default(); /* pick default values */
+
+    i_pcfg_read_integer( cfgfile , "alsa" , "alsa_mixer_card_id" ,
+                         &amidiplug_cfg_alsa.alsa_mixer_card_id , 0 );
+
+    i_pcfg_read_string( cfgfile , "alsa" , "alsa_mixer_ctl_name" ,
+                        &amidiplug_cfg_alsa.alsa_mixer_ctl_name , "Synth" );
+
+    i_pcfg_read_integer( cfgfile , "alsa" , "alsa_mixer_ctl_id" ,
+                         &amidiplug_cfg_alsa.alsa_mixer_ctl_id , 0 );
+
+    i_pcfg_free( cfgfile );
+  }
+
+  g_free( config_pathfilename );
+}
+
+
+void i_cfg_free( void )
+{
+  g_free( amidiplug_cfg_alsa.alsa_seq_wports );
+  g_free( amidiplug_cfg_alsa.alsa_mixer_ctl_name );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/backend-alsa/b-alsa.h	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,63 @@
+/*
+*
+* 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 _B_ALSA_H
+#define _B_ALSA_H 1
+
+#include <alsa/asoundlib.h>
+#include "../i_common.h"
+#include "../pcfg/i_pcfg.h"
+#include "../i_midievent.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;
+
+  snd_seq_event_t ev;
+
+  gboolean is_start;
+}
+sequencer_client_t;
+
+gint i_seq_open( void );
+gint i_seq_close( void );
+gint i_seq_queue_create( void );
+gint i_seq_queue_free( void );
+gint i_seq_port_create( void );
+gint i_seq_port_connect( void );
+gint i_seq_port_disconnect( void );
+gint i_seq_port_wparse( gchar * );
+gint i_seq_event_common_init( midievent_t * );
+GSList * i_seq_mixctl_get_list( gint );
+void i_seq_mixctl_free_list( GSList * );
+gint i_seq_mixer_find_selem( snd_mixer_t * , gchar * , gchar * , gint , snd_mixer_elem_t ** );
+void i_cfg_read( void );
+void i_cfg_free( void );
+gint i_util_str_count( gchar * , gchar );
+
+#endif /* !_B_ALSA_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/backend-alsa/backend-alsa-icon.xpm	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,444 @@
+/* XPM */
+static char * backend_alsa_icon_xpm[] = {
+"48 48 393 2",
+"  	c None",
+". 	c #FFFFFF",
+"+ 	c #F5F8F4",
+"@ 	c #E2EBE1",
+"# 	c #D6E3D5",
+"$ 	c #C5D5C3",
+"% 	c #ABBCAA",
+"& 	c #9BAB9A",
+"* 	c #92A190",
+"= 	c #8E9D8D",
+"- 	c #FAFBF9",
+"; 	c #EAF1E9",
+"> 	c #CAD9C8",
+", 	c #A7B7A6",
+"' 	c #747E73",
+") 	c #4B504B",
+"! 	c #383B39",
+"~ 	c #4A4C4A",
+"{ 	c #646764",
+"] 	c #787878",
+"^ 	c #818181",
+"/ 	c #FCFDFC",
+"( 	c #DDE7DC",
+"_ 	c #C0D1BE",
+": 	c #828E81",
+"< 	c #3B3F3B",
+"[ 	c #434544",
+"} 	c #8B8C8B",
+"| 	c #CBCCCA",
+"1 	c #F1F1EF",
+"2 	c #FEFEFC",
+"3 	c #EFF4EF",
+"4 	c #C8D8C6",
+"5 	c #303231",
+"6 	c #6A6B69",
+"7 	c #D2D3D0",
+"8 	c #FEFEFE",
+"9 	c #DCE7DB",
+"0 	c #A8B7A7",
+"a 	c #454945",
+"b 	c #5E5F5E",
+"c 	c #DADBD9",
+"d 	c #FDFDFB",
+"e 	c #F9FBF9",
+"f 	c #D8E4D7",
+"g 	c #8A9689",
+"h 	c #343635",
+"i 	c #AFB0AE",
+"j 	c #FBFBF9",
+"k 	c #737D72",
+"l 	c #454745",
+"m 	c #E5E6E3",
+"n 	c #666E66",
+"o 	c #5F605F",
+"p 	c #F3F3F1",
+"q 	c #F1F2F0",
+"r 	c #C5C8C4",
+"s 	c #A1A3A1",
+"t 	c #8A8D8A",
+"u 	c #9B9D9A",
+"v 	c #CFD1CF",
+"w 	c #FAFAF8",
+"x 	c #FCFCFB",
+"y 	c #D8D9D7",
+"z 	c #838683",
+"A 	c #535653",
+"B 	c #717371",
+"C 	c #949794",
+"D 	c #AAACA9",
+"E 	c #9A9E9A",
+"F 	c #676A67",
+"G 	c #979A97",
+"H 	c #FCFCFA",
+"I 	c #DADCD9",
+"J 	c #808380",
+"K 	c #676B67",
+"L 	c #B5B7B5",
+"M 	c #F7F8F6",
+"N 	c #AFB1AE",
+"O 	c #DEE0DD",
+"P 	c #F5F5F3",
+"Q 	c #A5A8A5",
+"R 	c #6D706C",
+"S 	c #BABBB9",
+"T 	c #F6F7F4",
+"U 	c #F0F1EF",
+"V 	c #E4E5E3",
+"W 	c #777A77",
+"X 	c #939693",
+"Y 	c #EFEFEE",
+"Z 	c #FBFBFA",
+"` 	c #E7EAE5",
+" .	c #B8B9B7",
+"..	c #515451",
+"+.	c #D0D1CF",
+"@.	c #DBDCD9",
+"#.	c #E4E6E2",
+"$.	c #ECECEA",
+"%.	c #C0C1BF",
+"&.	c #8E928E",
+"*.	c #737873",
+"=.	c #798079",
+"-.	c #838B84",
+";.	c #828C82",
+">.	c #929F92",
+",.	c #9DAB9D",
+"'.	c #A2B0A2",
+").	c #A0AEA0",
+"!.	c #9EAD9E",
+"~.	c #9CA99C",
+"{.	c #9EA99E",
+"].	c #9FA79E",
+"^.	c #A0A6A0",
+"/.	c #C8CBC7",
+"(.	c #EAEBE8",
+"_.	c #F9F9F7",
+":.	c #DDDEDC",
+"<.	c #767876",
+"[.	c #5F645F",
+"}.	c #8E9B8F",
+"|.	c #BBCDBB",
+"1.	c #D4E9D3",
+"2.	c #D9F0D8",
+"3.	c #D6ECD5",
+"4.	c #D4EAD3",
+"5.	c #D3EAD4",
+"6.	c #D0E7D1",
+"7.	c #D2E9D3",
+"8.	c #D2E9D4",
+"9.	c #D0E7D2",
+"0.	c #CAE0CB",
+"a.	c #CDE4CE",
+"b.	c #CFE6CF",
+"c.	c #CCE3CD",
+"d.	c #C6DAC7",
+"e.	c #B7CAB8",
+"f.	c #BECBBE",
+"g.	c #D7DBD6",
+"h.	c #F6F6F5",
+"i.	c #F5F6F3",
+"j.	c #828482",
+"k.	c #555B56",
+"l.	c #B0C1B0",
+"m.	c #D7EED8",
+"n.	c #D4EBD5",
+"o.	c #D4EBD4",
+"p.	c #D6ECD4",
+"q.	c #A6B6A4",
+"r.	c #4A504B",
+"s.	c #D4E9D2",
+"t.	c #515751",
+"u.	c #A4B4A5",
+"v.	c #D1E8D3",
+"w.	c #7B857B",
+"x.	c #1A1B1B",
+"y.	c #919E91",
+"z.	c #3F4340",
+"A.	c #ABBCAC",
+"B.	c #CBE2CC",
+"C.	c #CAE1CB",
+"D.	c #CCDDCB",
+"E.	c #E1E9E1",
+"F.	c #676967",
+"G.	c #8F9C8F",
+"H.	c #D2E8D3",
+"I.	c #93A192",
+"J.	c #323533",
+"K.	c #D2E6D0",
+"L.	c #444A44",
+"M.	c #9FAFA0",
+"N.	c #C8DCC9",
+"O.	c #3A3D3A",
+"P.	c #B5C6B5",
+"Q.	c #C8DDC8",
+"R.	c #2B2E2C",
+"S.	c #92A192",
+"T.	c #CBE1CC",
+"U.	c #C8DEC9",
+"V.	c #C8DCC7",
+"W.	c #D2E4D3",
+"X.	c #EDEFEB",
+"Y.	c #A1A3A0",
+"Z.	c #899489",
+"`.	c #808A80",
+" +	c #1F201F",
+".+	c #CCE0CA",
+"++	c #CAE0CC",
+"@+	c #B5C8B6",
+"#+	c #C2D7C3",
+"$+	c #1B1C1B",
+"%+	c #7C867C",
+"&+	c #C7D9C5",
+"*+	c #C2DAC4",
+"=+	c #C6DBC7",
+"-+	c #E4EBE3",
+";+	c #787C78",
+">+	c #D1E6D1",
+",+	c #CFE6D1",
+"'+	c #656C65",
+")+	c #0A0A0B",
+"!+	c #C5D9C3",
+"~+	c #666F67",
+"{+	c #757F75",
+"]+	c #BDD2BE",
+"^+	c #606861",
+"/+	c #C4DAC4",
+"(+	c #C5D8C3",
+"_+	c #ECEEEB",
+":+	c #A0A7A0",
+"<+	c #CEE5D0",
+"[+	c #D5EBD4",
+"}+	c #D4EBD3",
+"|+	c #515851",
+"1+	c #1C1E1D",
+"2+	c #B3C4B2",
+"3+	c #B5C7B6",
+"4+	c #323432",
+"5+	c #C2D8C3",
+"6+	c #B0C2B1",
+"7+	c #1B1C1C",
+"8+	c #4C514C",
+"9+	c #C9DFC9",
+"0+	c #C3DAC4",
+"a+	c #C3D6C1",
+"b+	c #CBD6CA",
+"c+	c #DEE2DD",
+"d+	c #D0E6D0",
+"e+	c #D2E7D0",
+"f+	c #424742",
+"g+	c #474A47",
+"h+	c #96A496",
+"i+	c #434944",
+"j+	c #D0E6D1",
+"k+	c #4F554F",
+"l+	c #909C90",
+"m+	c #9AA99B",
+"n+	c #424542",
+"o+	c #373B38",
+"p+	c #C6DAC6",
+"q+	c #C8DCC8",
+"r+	c #9EAA9D",
+"s+	c #E9EAE8",
+"t+	c #D8E8D9",
+"u+	c #CFE6D0",
+"v+	c #CDE2CE",
+"w+	c #313431",
+"x+	c #6D766D",
+"y+	c #7E897E",
+"z+	c #CEE5CF",
+"A+	c #859286",
+"B+	c #5D655E",
+"C+	c #869387",
+"D+	c #697269",
+"E+	c #252726",
+"F+	c #BED2BF",
+"G+	c #C7DBC7",
+"H+	c #C2D5C0",
+"I+	c #7A8179",
+"J+	c #D6D9D5",
+"K+	c #F0F3EF",
+"L+	c #D0E5D1",
+"M+	c #C4D8C5",
+"N+	c #2E312F",
+"O+	c #6F7870",
+"P+	c #636A64",
+"Q+	c #9AAB9B",
+"R+	c #4A514B",
+"S+	c #727C73",
+"T+	c #6C756D",
+"U+	c #222422",
+"V+	c #B5C8B5",
+"W+	c #C7DAC6",
+"X+	c #C5D9C5",
+"Y+	c #C3D8C2",
+"Z+	c #545854",
+"`+	c #ECEDEB",
+" @	c #EEF1ED",
+".@	c #D4E3D4",
+"+@	c #CCE2CD",
+"@@	c #BBD0BD",
+"#@	c #161717",
+"$@	c #262927",
+"%@	c #424843",
+"&@	c #9CAC9D",
+"*@	c #7F8B7F",
+"=@	c #616962",
+"-@	c #5D635D",
+";@	c #212322",
+">@	c #101111",
+",@	c #AABCAB",
+"'@	c #C2D8C2",
+")@	c #B1C1B0",
+"!@	c #595E59",
+"~@	c #A1A4A1",
+"{@	c #FBFCFA",
+"]@	c #E3EAE2",
+"^@	c #CBDACB",
+"/@	c #CBE1CB",
+"(@	c #AFC2B1",
+"_@	c #383C39",
+":@	c #ACBEAD",
+"<@	c #3C413D",
+"[@	c #3D423D",
+"}@	c #8E9B8E",
+"|@	c #3E413E",
+"1@	c #242625",
+"2@	c #A7B8A8",
+"3@	c #4A504A",
+"4@	c #97A698",
+"5@	c #4B504C",
+"6@	c #94A295",
+"7@	c #C7DBC6",
+"8@	c #C4D8C3",
+"9@	c #BFD2BE",
+"0@	c #8C978D",
+"a@	c #404341",
+"b@	c #A0A2A0",
+"c@	c #F5F5F4",
+"d@	c #D5D7D4",
+"e@	c #BBC6BB",
+"f@	c #BECDBE",
+"g@	c #BED1BE",
+"h@	c #B0C1AF",
+"i@	c #C7DCC8",
+"j@	c #AFC1B0",
+"k@	c #AFC0AF",
+"l@	c #A3B4A3",
+"m@	c #B4C6B4",
+"n@	c #BBCEBC",
+"o@	c #AEBFAF",
+"p@	c #C0D3C0",
+"q@	c #B8CBB8",
+"r@	c #B1BBB0",
+"s@	c #808780",
+"t@	c #555955",
+"u@	c #747674",
+"v@	c #E2E4E1",
+"w@	c #F5F6F4",
+"x@	c #DDDFDC",
+"y@	c #B8BDB7",
+"z@	c #A1AAA1",
+"A@	c #919991",
+"B@	c #9DAA9C",
+"C@	c #A3AFA2",
+"D@	c #A8B5A7",
+"E@	c #ACBCAC",
+"F@	c #AFBFAF",
+"G@	c #AFBEAF",
+"H@	c #ABBAAB",
+"I@	c #98A497",
+"J@	c #899688",
+"K@	c #7E877E",
+"L@	c #707770",
+"M@	c #676B66",
+"N@	c #AEB0AD",
+"O@	c #E7E8E5",
+"P@	c #F3F3F2",
+"Q@	c #E2E4E0",
+"R@	c #C8C9C7",
+"S@	c #B7BAB7",
+"T@	c #A4A8A3",
+"U@	c #636763",
+"V@	c #4D4F4D",
+"W@	c #999C98",
+"X@	c #A7ABA6",
+"Y@	c #B6B6B6",
+"Z@	c #CACBC9",
+"`@	c #E0E2DF",
+" #	c #F4F5F3",
+".#	c #7E827D",
+"+#	c #868886",
+"@#	c #ECEDEA",
+"##	c #E3E5E2",
+"$#	c #969B97",
+"%#	c #696C69",
+"&#	c #BFC1BE",
+"*#	c #F8F8F7",
+"=#	c #B5B9B4",
+"-#	c #909190",
+";#	c #E8E8E6",
+">#	c #C4C6C3",
+",#	c #7A7C7A",
+"'#	c #5A5D5A",
+")#	c #A6A7A5",
+"!#	c #EEEFED",
+"~#	c #A7ABA7",
+"{#	c #535753",
+"]#	c #515551",
+"^#	c #707370",
+"/#	c #C0C2BF",
+"(#	c #E8E9E7",
+"_#	c #EBECEA",
+":#	c #F4F5F2",
+". . . . . . . . . . . . . . . . + @ # $ % & * = = * & % $ # @ + . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . - ; > , ' ) ! ~ { ] ^ ^ ] { ~ ! ) ' , > ; - . . . . . . . . . . . . . ",
+". . . . . . . . . . . / ( _ : < [ } | 1 2 2 2 2 2 2 2 2 1 | } [ < : _ ( / . . . . . . . . . . . ",
+". . . . . . . . . . 3 4 : 5 6 7 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 7 6 5 : 4 3 . . . . . . . . . . ",
+". . . . . . . . 8 9 0 a b c d 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 d c b a 0 9 8 . . . . . . . . ",
+". . . . . . . e f g h i j 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 j i h g f e . . . . . . . ",
+". . . . . . e 4 k l m 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 m l k 4 e . . . . . . ",
+". . . . . e 4 n o 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 1 o n 4 e . . . . . ",
+". . . . 8 f k o p 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 p o k f 8 . . . . ",
+". . . . 9 g l 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 1 l g 9 . . . . ",
+". . . 3 0 h m 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 2 m h 0 3 . . . ",
+". . / 4 a i 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 q r s t u v w 2 2 2 2 2 2 2 i a 4 / . . ",
+". . ( : b j 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 x y z A B C D E F G H 2 2 2 2 2 2 j b : ( . . ",
+". - _ 5 c 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 d I J K L q d 2 2 2 M N O 2 2 2 2 2 2 2 c 5 _ - . ",
+". ; : 6 d 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 P Q R S T 2 2 2 2 2 2 2 w U 2 2 2 2 2 2 2 d 6 : ; . ",
+". > < 7 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 V W X Y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 7 < > . ",
+"+ , [ 2 2 2 2 2 2 2 2 2 2 2 2 2 Z p ` O  ...G +.@.#.p H 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 d $.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.2 2 2 2 2 2 2 2 2 2 2 2 2 } ' @ ",
+"# ) | 2 2 2 2 2 2 2 d :.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.2 2 2 2 2 2 2 2 2 2 2 | ) # ",
+"$ ! 1 2 2 2 2 2 2 i.j.k.l.m.n.o.p.p.q.r.s.t.u.v.w.x.y.0.z.A.B.0.C.D.E.d 2 2 2 2 2 2 2 2 2 1 ! $ ",
+"% ~ 2 2 2 2 2 2 P F.G.H.5.8.8.p.p.p.I.J.K.L.M.N.O.P.0.Q.R.S.T.U.U.U.V.W.X.2 2 2 2 2 2 2 2 2 ~ % ",
+"& { 2 2 2 2 2 2 Y.Z.5.6.8.8.8.p.p.p.`. +.+L.M.++< @+a.#+$+%+T.U.U.Q.&+*+=+-+2 2 2 2 2 2 2 2 { & ",
+"* ] 2 2 2 2 2 - ;+>+a.,+8.8.8.p.p.p.'+)+!+L.M.8.~+{+a.]+)+^+T.U.U.Q.&+*+/+(+_+2 2 2 2 2 2 2 ] * ",
+"= ^ 2 2 2 2 2 Z :+7.a.<+8.8.8.[+p.}+|+1+2+L.M.8.3+4+5+6+7+8+9+U.U.Q.&+*+0+a+b+H 2 2 2 2 2 2 ^ = ",
+"= ^ 2 2 2 2 2 2 c+d+a.a.v.8.8.8.[+e+f+g+h+i+M.8.j+k+l+m+n+o+p+U.U.q+&+*+0+a+r+s+2 2 2 2 2 2 ^ = ",
+"* ] 2 2 2 2 2 2 j t+a.a.u+8.8.8.8.v+w+x+y+i+M.8.z+A+B+C+D+E+F+U.U.G+&+*+0+H+I+J+2 2 2 2 2 2 ] * ",
+"& { 2 2 2 2 2 2 2 K+L+a.a.u+8.8.8.M+N+O+P+i+M.6.a.Q+R+S+T+U+V+U.U.W+X+*+Y+2+Z+`+2 2 2 2 2 2 { & ",
+"% ~ 2 2 2 2 2 2 2 2  @.@+@a.u+8.8.@@#@$@r.%@&@c.U.*@=@-@;@>@,@U.Q.&+/+'@)@!@~@d 2 2 2 2 2 2 ~ % ",
+"$ ! 1 2 2 2 2 2 2 2 2 {@]@^@/@z+6.(@_@:@<@[@<@}@|@1@2@3@4@5@6@U.7@8@9@0@a@b@d 2 2 2 2 2 2 1 ! $ ",
+"# ) | 2 2 2 2 2 2 2 2 2 2 c@d@e@f@g@h@i@j@k@l@F+m@n@T.o@p@k@q@9@r@s@t@u@v@2 2 2 2 2 2 2 2 | ) # ",
+"@ ' } 2 2 2 2 2 2 2 2 2 2 2 2 w@x@y@z@A@B@C@D@E@F@G@H@I@J@K@L@M@;+N@O@x 2 2 2 2 2 2 2 2 2 } ' @ ",
+"+ , [ 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 x P@Q@R@S@T@U@V@W@X@Y@Z@`@ #d 2 2 2 2 2 2 2 2 2 2 2 2 [ , + ",
+". > < 7 2 2 2 2 2 2 2 2 H 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 7 < > . ",
+". ; : 6 d 2 2 2 2 2 2 H v j 2 2 2 2 2 d ##$#%#&#*#2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 d 6 : ; . ",
+". - _ 5 c 2 2 2 2 2 2 2 =#-#`@c@c@;#>#,#'#)#!#2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 c 5 _ - . ",
+". . ( : b j 2 2 2 2 2 2 H ~#'#{#]#t@^#/#c@2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 j b : ( . . ",
+". . / 4 a i 2 2 2 2 2 2 2 2 P (#_#:#d 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 i a 4 / . . ",
+". . . 3 0 h m 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 2 m h 0 3 . . . ",
+". . . . 9 g l 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 1 l g 9 . . . . ",
+". . . . 8 f k o p 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 p o k f 8 . . . . ",
+". . . . . e 4 n o 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 1 o n 4 e . . . . . ",
+". . . . . . e 4 k l m 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 m l k 4 e . . . . . . ",
+". . . . . . . e f g h i j 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 j i h g f e . . . . . . . ",
+". . . . . . . . 8 9 0 a b c d 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 d c b a 0 9 8 . . . . . . . . ",
+". . . . . . . . . . 3 4 : 5 6 7 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 7 6 5 : 4 3 . . . . . . . . . . ",
+". . . . . . . . . . . / ( _ : < [ } | 1 2 2 2 2 2 2 2 2 1 | } [ < : _ ( / . . . . . . . . . . . ",
+". . . . . . . . . . . . . - ; > , ' ) ! ~ { ] ^ ^ ] { ~ ! ) ' , > ; - . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . + @ # $ % & * = = * & % $ # @ + . . . . . . . . . . . . . . . . "};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/backend-dummy/Makefile.in	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,15 @@
+include ../../../../mk/rules.mk
+include ../../../../mk/objective.mk
+
+noinst_HEADERS = b-dummy.h b-dummy-config.h backend-dummy-icon.xpm
+
+CFLAGS += -fPIC -DPIC $(GLIB_CFLAGS) -I../../../../intl -I../../../..
+
+libdir = $(AMIDIPLUGDATADIR)
+
+OBJECTIVE_LIBS = ap-dummy.so
+
+LIBADD = $(GLIB_LIBS) ../pcfg/libpcfg.a
+SOURCES = b-dummy.c
+
+OBJECTS = ${SOURCES:.c=.o}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/backend-dummy/b-dummy-config.h	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,36 @@
+/*
+*
+* 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 _B_DUMMY_CONFIG_H
+#define _B_DUMMY_CONFIG_H 1
+
+
+typedef struct
+{
+  gint		dumm_logger_enable;
+  gint		dumm_logger_lfstyle;
+  gint		dumm_playback_speed;
+  gchar *	dumm_logger_logfile;
+  gchar *	dumm_logger_logdir;
+}
+amidiplug_cfg_dumm_t;
+
+
+#endif /* !_B_DUMMY_CONFIG_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/backend-dummy/b-dummy.c	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,392 @@
+/*
+*
+* 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 "b-dummy.h"
+#include "b-dummy-config.h"
+
+/* dummy sequencer instance */
+static sequencer_client_t sc;
+/* options */
+static amidiplug_cfg_dumm_t amidiplug_cfg_dumm;
+
+
+gint backend_info_get( gchar ** name , gchar ** longname , gchar ** desc , gint * ppos )
+{
+  if ( name != NULL )
+    *name = g_strdup( "dummy" );
+  if ( longname != NULL )
+    *longname = g_strdup( "Dummy Backend " AMIDIPLUG_VERSION );
+  if ( desc != NULL )
+    *desc = g_strdup( _("This backend does not produce audio at all. It is mostly "
+                        "useful for analysis and testing purposes, as it can log "
+                        "all MIDI events to standard output, standard error or file.\n"
+                        "Backend written by Giacomo Lozito.") );
+  if ( ppos != NULL )
+    *ppos = 3; /* preferred position in backend list */
+  return 1;
+}
+
+
+gint backend_init( void )
+{
+  i_cfg_read(); /* read configuration options */
+
+  return 1;
+}
+
+
+gint backend_cleanup( void )
+{
+  i_cfg_free(); /* free configuration options */
+
+  return 1;
+}
+
+
+gint sequencer_get_port_count( void )
+{
+  return 1; /* always return a single port here */
+}
+
+
+gint sequencer_start( gchar * midi_fname )
+{
+  switch( amidiplug_cfg_dumm.dumm_logger_enable )
+  {
+    case 1:
+    {
+      sc.file = stdout; /* log to standard output */
+      break;
+    }
+    case 2:
+    {
+      sc.file = stderr; /* log to standard error */
+      break;
+    }
+    case 3:
+    {
+      switch ( amidiplug_cfg_dumm.dumm_logger_lfstyle )
+      {
+        case 0:
+        {
+          sc.file = fopen( amidiplug_cfg_dumm.dumm_logger_logfile , "w" );
+          break;
+        }
+        case 1:
+        {
+          sc.file = fopen( amidiplug_cfg_dumm.dumm_logger_logfile , "a" );
+          break;
+        }
+        case 2:
+        {
+          gchar *midi_basefname = G_PATH_GET_BASENAME( midi_fname );
+          gchar *logfile = g_strjoin( "" , amidiplug_cfg_dumm.dumm_logger_logdir ,
+                                      "/" , midi_basefname , ".log" , NULL );
+          sc.file = fopen( logfile , "w" );
+          g_free( logfile );
+          g_free( midi_basefname );
+          break;
+        }
+        default: /* shouldn't happen, let's handle this anyway */
+        {
+          sc.file = NULL;
+          break;
+        }
+      }
+      break;
+    }
+    case 0:
+    default:
+    {
+      sc.file = NULL;
+      break;
+    }
+  }
+
+  if (( sc.file == NULL ) && ( amidiplug_cfg_dumm.dumm_logger_enable != 0 ))
+  {
+    DEBUGMSG( "Unable to get a FILE pointer\n" );
+    return 0;
+  }
+  else
+    return 1; /* success */
+}
+
+
+gint sequencer_stop( void )
+{
+  if (( sc.file != NULL ) && ( amidiplug_cfg_dumm.dumm_logger_enable == 3 ))
+    fclose( sc.file );
+
+  return 1; /* success */
+}
+
+
+/* activate sequencer client */
+gint sequencer_on( void )
+{
+  sc.tick_offset = 0;
+  if ( amidiplug_cfg_dumm.dumm_playback_speed == 0 )
+    sc.timer_seq = g_timer_new(); /* create the sequencer timer */
+  return 1; /* success */
+}
+
+
+/* shutdown sequencer client */
+gint sequencer_off( void )
+{
+  if (( amidiplug_cfg_dumm.dumm_playback_speed == 0 ) && ( sc.timer_seq != NULL ))
+  {
+    g_timer_destroy( sc.timer_seq ); /* destroy the sequencer timer */
+    sc.timer_seq = NULL;
+  }
+  return 1; /* success */
+}
+
+
+/* queue set tempo */
+gint sequencer_queue_tempo( gint tempo , gint ppq )
+{
+  sc.ppq = ppq;
+  sc.usec_per_tick = (gdouble)tempo / (gdouble)ppq;
+  return 1;
+}
+
+
+gint sequencer_queue_start( void )
+{
+  if ( amidiplug_cfg_dumm.dumm_playback_speed == 0 )
+    g_timer_start( sc.timer_seq ); /* reset the sequencer timer */
+  return 1;
+}
+
+
+gint sequencer_event_init( void )
+{
+  /* common settings for all our events */
+  return 1;
+}
+
+
+gint sequencer_event_noteon( midievent_t * event )
+{
+  i_sleep( event->tick_real );
+  i_printf( sc.file , "NOTEON : ti %i : ch %i : no %i : ve %i\n" ,
+            event->tick , event->data.d[0] , event->data.d[1] , event->data.d[2] );
+  return 1;
+}
+
+
+gint sequencer_event_noteoff( midievent_t * event )
+{
+  i_sleep( event->tick_real );
+  i_printf( sc.file , "NOTEOFF : ti %i : ch %i : no %i : ve %i\n" ,
+            event->tick , event->data.d[0] , event->data.d[1] , event->data.d[2] );
+  return 1;
+}
+
+
+gint sequencer_event_keypress( midievent_t * event )
+{
+  i_sleep( event->tick_real );
+  i_printf( sc.file , "KEYPRESS : ti %i : ch %i : no %i : ve %i\n" ,
+            event->tick , event->data.d[0] , event->data.d[1] , event->data.d[2] );
+  return 1;
+}
+
+
+gint sequencer_event_controller( midievent_t * event )
+{
+  i_sleep( event->tick_real );
+  i_printf( sc.file , "CONTROLLER : ti %i : ch %i : pa %i : va %i\n" ,
+            event->tick , event->data.d[0] , event->data.d[1] , event->data.d[2] );
+  return 1;
+}
+
+
+gint sequencer_event_pgmchange( midievent_t * event )
+{
+  i_sleep( event->tick_real );
+  i_printf( sc.file , "PGMCHANGE : ti %i : ch %i : va %i\n" ,
+            event->tick , event->data.d[0] , event->data.d[1] );
+  return 1;
+}
+
+
+gint sequencer_event_chanpress( midievent_t * event )
+{
+  i_sleep( event->tick_real );
+  i_printf( sc.file , "CHANPRESS : ti %i : ch %i : va %i\n" ,
+            event->tick , event->data.d[0] , event->data.d[1] );
+  return 1;
+}
+
+
+gint sequencer_event_pitchbend( midievent_t * event )
+{
+  i_sleep( event->tick_real );
+  i_printf( sc.file , "PITCHBEND : ti %i : ch %i : va %i\n" ,
+            event->tick ,  event->data.d[0] ,
+            ((((event->data.d[2]) & 0x7f) << 7) | ((event->data.d[1]) & 0x7f)) );
+  return 1;
+}
+
+
+gint sequencer_event_sysex( midievent_t * event )
+{
+  i_sleep( event->tick_real );
+  i_printf( sc.file , "SYSEX : ti %i\n" ,
+            event->tick );
+  return 1;
+}
+
+
+gint sequencer_event_tempo( midievent_t * event )
+{
+  i_sleep( event->tick_real );
+  i_printf( sc.file , "TEMPOCHANGE : ti %i : va %i\n" ,
+            event->tick , event->data.tempo );
+  sc.usec_per_tick = (gdouble)event->data.tempo / (gdouble)sc.ppq;
+  if ( amidiplug_cfg_dumm.dumm_playback_speed == 0 )
+    g_timer_start( sc.timer_seq ); /* reset the sequencer timer */
+  sc.tick_offset = event->tick_real;
+  return 1;
+}
+
+
+gint sequencer_event_other( midievent_t * event )
+{
+  return 1;
+}
+
+
+gint sequencer_output( gpointer * buffer , gint * len )
+{
+  return 0;
+}
+
+
+gint sequencer_output_shut( guint max_tick , gint skip_offset )
+{
+  return 1;
+}
+
+
+/* unimplemented (useless for dummy backend) */
+gint audio_volume_get( gint * left_volume , gint * right_volume )
+{
+  return 0; 
+}
+gint audio_volume_set( gint left_volume , gint right_volume )
+{
+  return 0;
+}
+
+
+gint audio_info_get( gint * channels , gint * bitdepth , gint * samplerate )
+{
+  /* not applicable for dummy backend */
+  *channels = -1;
+  *bitdepth = -1;
+  *samplerate = -1;
+  return 0; /* not valid information */
+}
+
+
+gboolean audio_check_autonomous( void )
+{
+  return TRUE; /* Dummy deals itself with audio (well, it doesn't produce any at all :)) */
+}
+
+
+
+/* ******************************************************************
+   *** INTERNALS ****************************************************
+   ****************************************************************** */
+
+
+void i_sleep( guint tick )
+{
+  if ( amidiplug_cfg_dumm.dumm_playback_speed == 0 )
+  {
+    gdouble elapsed_tick_usecs = (gdouble)(tick - sc.tick_offset) * sc.usec_per_tick;
+    gdouble elapsed_seq_usecs = g_timer_elapsed( sc.timer_seq , NULL ) * 1000000;
+    if ( elapsed_seq_usecs < elapsed_tick_usecs )
+    {
+      G_USLEEP( elapsed_tick_usecs - elapsed_seq_usecs );
+    }
+  }
+}
+
+
+void i_printf( FILE * fp , const gchar * format , ... )
+{
+  va_list args;
+  va_start( args , format );
+  if ( fp != NULL )
+    G_VFPRINTF( fp , format , args );
+  va_end( args );
+}
+
+
+void i_cfg_read( void )
+{
+  pcfg_t *cfgfile;
+  gchar * def_logfile = g_strjoin( "" , g_get_home_dir() , "/amidi-plug.log" , NULL );
+  gchar * def_logdir = (gchar*)g_get_home_dir();
+  gchar * config_pathfilename = g_strjoin( "" , g_get_home_dir() , "/" ,
+                                           PLAYER_LOCALRCDIR , "/amidi-plug.conf" , NULL );
+  cfgfile = i_pcfg_new_from_file( config_pathfilename );
+
+  if ( !cfgfile )
+  {
+    /* fluidsynth backend defaults */
+    amidiplug_cfg_dumm.dumm_logger_enable = 0;
+    amidiplug_cfg_dumm.dumm_logger_lfstyle = 0;
+    amidiplug_cfg_dumm.dumm_playback_speed = 0;
+    amidiplug_cfg_dumm.dumm_logger_logfile = g_strdup( def_logfile );
+    amidiplug_cfg_dumm.dumm_logger_logdir = g_strdup( def_logdir );
+  }
+  else
+  {
+    i_pcfg_read_integer( cfgfile , "dumm" , "dumm_logger_enable" ,
+                         &amidiplug_cfg_dumm.dumm_logger_enable , 0 );
+    i_pcfg_read_integer( cfgfile , "dumm" , "dumm_logger_lfstyle" ,
+                         &amidiplug_cfg_dumm.dumm_logger_lfstyle , 0 );
+    i_pcfg_read_integer( cfgfile , "dumm" , "dumm_playback_speed" ,
+                         &amidiplug_cfg_dumm.dumm_playback_speed , 0 );
+    i_pcfg_read_string( cfgfile , "dumm" , "dumm_logger_logfile" ,
+                        &amidiplug_cfg_dumm.dumm_logger_logfile , def_logfile );
+    i_pcfg_read_string( cfgfile , "dumm" , "dumm_logger_logdir" ,
+                        &amidiplug_cfg_dumm.dumm_logger_logdir , def_logdir );
+
+    i_pcfg_free( cfgfile );
+  }
+
+  g_free( config_pathfilename );
+  g_free( def_logfile );
+}
+
+
+void i_cfg_free( void )
+{
+  g_free( amidiplug_cfg_dumm.dumm_logger_logfile );
+  g_free( amidiplug_cfg_dumm.dumm_logger_logdir );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/backend-dummy/b-dummy.h	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,49 @@
+/*
+*
+* 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 _B_DUMMY_H
+#define _B_DUMMY_H 1
+
+
+#include "../i_common.h"
+#include <glib/gprintf.h>
+#include "../pcfg/i_pcfg.h"
+#include "../i_midievent.h"
+
+
+typedef struct
+{
+  FILE * file;
+
+  gint ppq;
+  gdouble usec_per_tick;
+  guint tick_offset;
+
+  GTimer * timer_seq;
+}
+sequencer_client_t;
+
+
+void i_sleep( guint );
+void i_printf( FILE * , const gchar * , ... );
+void i_cfg_read( void );
+void i_cfg_free( void );
+
+#endif /* !_B_DUMMY_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/backend-dummy/backend-dummy-icon.xpm	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,852 @@
+/* XPM */
+static char * backend_dummy_icon_xpm[] = {
+"48 48 801 2",
+"  	c #FFFFFF",
+". 	c #D4D4D4",
+"+ 	c #BEBEBE",
+"@ 	c #DFDFDF",
+"# 	c #E7E7E7",
+"$ 	c #F4F4F4",
+"% 	c #7F7F7F",
+"& 	c #484848",
+"* 	c #AEAEAE",
+"= 	c #C0C0C0",
+"- 	c #EFEFEF",
+"; 	c #C1C1C1",
+"> 	c #FEFEFE",
+", 	c #7A7A7A",
+"' 	c #6E6E6E",
+") 	c #E2E2E2",
+"! 	c #9A9A9A",
+"~ 	c #767676",
+"{ 	c #D9D9D9",
+"] 	c #CBCBCB",
+"^ 	c #DDDDDD",
+"/ 	c #9C9C9C",
+"( 	c #B9B9B9",
+"_ 	c #D0D0D0",
+": 	c #BFBFBF",
+"< 	c #E4E4E4",
+"[ 	c #C2C2C2",
+"} 	c #E3E3E3",
+"| 	c #DCDCDC",
+"1 	c #F7F6F6",
+"2 	c #C8C7C7",
+"3 	c #ABAAAA",
+"4 	c #868585",
+"5 	c #686666",
+"6 	c #5C5B5B",
+"7 	c #595858",
+"8 	c #626161",
+"9 	c #737272",
+"0 	c #8D8C8C",
+"a 	c #A5A4A4",
+"b 	c #D5D5D5",
+"c 	c #A2A2A2",
+"d 	c #C6C6C6",
+"e 	c #D2D2D2",
+"f 	c #D8D8D8",
+"g 	c #AEADAD",
+"h 	c #8C8B8B",
+"i 	c #8A8989",
+"j 	c #828080",
+"k 	c #757373",
+"l 	c #787676",
+"m 	c #7B7A7A",
+"n 	c #727272",
+"o 	c #717070",
+"p 	c #676666",
+"q 	c #656464",
+"r 	c #9B9A9A",
+"s 	c #EAEAEA",
+"t 	c #C7C7C7",
+"u 	c #7C7C7C",
+"v 	c #E6E6E6",
+"w 	c #A6A5A5",
+"x 	c #9E9C9C",
+"y 	c #999898",
+"z 	c #908E8E",
+"A 	c #858484",
+"B 	c #767575",
+"C 	c #6E6C6E",
+"D 	c #6F6D70",
+"E 	c #6B6A6E",
+"F 	c #6B6A6F",
+"G 	c #6E6C70",
+"H 	c #767577",
+"I 	c #707070",
+"J 	c #5F5E5E",
+"K 	c #949393",
+"L 	c #F0F0F0",
+"M 	c #F1F1F1",
+"N 	c #ABABAB",
+"O 	c #454545",
+"P 	c #F6F6F6",
+"Q 	c #B0AFAF",
+"R 	c #969595",
+"S 	c #8E8D8D",
+"T 	c #807E80",
+"U 	c #817F80",
+"V 	c #84847B",
+"W 	c #838476",
+"X 	c #BEC0B1",
+"Y 	c #C7C8AE",
+"Z 	c #C7C8AB",
+"` 	c #BABBA2",
+" .	c #909182",
+"..	c #858676",
+"+.	c #69686A",
+"@.	c #6E6D71",
+"#.	c #C3C3C3",
+"$.	c #989898",
+"%.	c #E5E5E5",
+"&.	c #FCFCFC",
+"*.	c #878787",
+"=.	c #7B7B7B",
+"-.	c #929191",
+";.	c #929090",
+">.	c #8F8C8C",
+",.	c #868485",
+"'.	c #7E7D7B",
+").	c #9E9E96",
+"!.	c #C3C3B4",
+"~.	c #FDFDEC",
+"{.	c #FAFCE2",
+"].	c #F8F9D6",
+"^.	c #F4F6D1",
+"/.	c #F3F6CE",
+"(.	c #F3F5CA",
+"_.	c #F8FACC",
+":.	c #F8FACE",
+"<.	c #DFE0B5",
+"[.	c #BCBC9C",
+"}.	c #6D6C65",
+"|.	c #6B6A70",
+"1.	c #757474",
+"2.	c #7A7979",
+"3.	c #666464",
+"4.	c #A09F9F",
+"5.	c #E1E0E0",
+"6.	c #7A7878",
+"7.	c #848383",
+"8.	c #868484",
+"9.	c #848182",
+"0.	c #797778",
+"a.	c #9E9F9A",
+"b.	c #E0E1D7",
+"c.	c #FCFDE9",
+"d.	c #F8F9E0",
+"e.	c #F7F9DE",
+"f.	c #F6F8DB",
+"g.	c #F6F8D8",
+"h.	c #F5F7D4",
+"i.	c #F4F6D0",
+"j.	c #F4F6CC",
+"k.	c #F2F5C8",
+"l.	c #F2F4C5",
+"m.	c #F0F4C0",
+"n.	c #F2F6BE",
+"o.	c #F9FBC5",
+"p.	c #B7B793",
+"q.	c #676668",
+"r.	c #727072",
+"s.	c #6A6969",
+"t.	c #939292",
+"u.	c #E7E8E8",
+"v.	c #696767",
+"w.	c #747272",
+"x.	c #767474",
+"y.	c #A8A9A0",
+"z.	c #FEFEF3",
+"A.	c #FAFBE7",
+"B.	c #F9FAE6",
+"C.	c #F9FAE5",
+"D.	c #F8F9E2",
+"E.	c #F6F8D7",
+"F.	c #F5F7D3",
+"G.	c #F4F6CE",
+"H.	c #F3F6CA",
+"I.	c #F2F5C7",
+"J.	c #F1F4C2",
+"K.	c #F0F3BE",
+"L.	c #EFF2B9",
+"M.	c #F1F4B6",
+"N.	c #E1E3A8",
+"O.	c #6D6D67",
+"P.	c #A2A1A1",
+"Q.	c #C4C4C4",
+"R.	c #999999",
+"S.	c #6C6C6C",
+"T.	c #E8E8E8",
+"U.	c #777676",
+"V.	c #797878",
+"W.	c #727171",
+"X.	c #6C6B6B",
+"Y.	c #C2C2BD",
+"Z.	c #FEFEF6",
+"`.	c #FAFCED",
+" +	c #FBFBEC",
+".+	c #FAFBEA",
+"++	c #FAFBE8",
+"@+	c #F6F8DA",
+"#+	c #F6F7D6",
+"$+	c #F4F7D0",
+"%+	c #F2F4C4",
+"&+	c #F0F3BF",
+"*+	c #EFF3BA",
+"=+	c #EEF2B6",
+"-+	c #F0F4B2",
+";+	c #DEE0A2",
+">+	c #84837D",
+",+	c #C5C5C5",
+"'+	c #EBEBEB",
+")+	c #CCCCCC",
+"!+	c #898888",
+"~+	c #7C7B7B",
+"{+	c #6D6C6D",
+"]+	c #A8A7A0",
+"^+	c #FDFDF5",
+"/+	c #FCFCF0",
+"(+	c #FCFCF2",
+"_+	c #FCFCF1",
+":+	c #FBFCEF",
+"<+	c #FAFBEC",
+"[+	c #F6F8DC",
+"}+	c #F4F7D2",
+"|+	c #F2F5C9",
+"1+	c #F1F4C0",
+"2+	c #F0F2BB",
+"3+	c #EEF2B7",
+"4+	c #EEF1B2",
+"5+	c #ECF0AE",
+"6+	c #DEDF9D",
+"7+	c #6C6C66",
+"8+	c #727172",
+"9+	c #787878",
+"0+	c #6C6A6A",
+"a+	c #EDEDED",
+"b+	c #747474",
+"c+	c #6C6A6C",
+"d+	c #999894",
+"e+	c #FBFCF2",
+"f+	c #FCFDF4",
+"g+	c #FCFDF6",
+"h+	c #FDFDF6",
+"i+	c #FCFCF3",
+"j+	c #F8FAE2",
+"k+	c #F7F8DE",
+"l+	c #F6F8D9",
+"m+	c #F4F6CF",
+"n+	c #F2F5CA",
+"o+	c #F2F4C6",
+"p+	c #F0F4C1",
+"q+	c #F0F3BC",
+"r+	c #EEF2B8",
+"s+	c #EEF1B3",
+"t+	c #EDF0AE",
+"u+	c #EEF2AB",
+"v+	c #D8DA9C",
+"w+	c #626069",
+"x+	c #F2F2F2",
+"y+	c #B5B5B5",
+"z+	c #FDFDFD",
+"A+	c #B7B6B6",
+"B+	c #8A8888",
+"C+	c #7E7D7D",
+"D+	c #6A6968",
+"E+	c #FEFEF8",
+"F+	c #FDFEF8",
+"G+	c #FEFFFC",
+"H+	c #A6A6A8",
+"I+	c #A7A7A7",
+"J+	c #FBFCEA",
+"K+	c #F8FAE3",
+"L+	c #F9FAD0",
+"M+	c #E5E6BE",
+"N+	c #A6A598",
+"O+	c #AAA998",
+"P+	c #FAFCC2",
+"Q+	c #F0F4B4",
+"R+	c #ECF0AA",
+"S+	c #EEF2A6",
+"T+	c #A8A886",
+"U+	c #6F6D72",
+"V+	c #7E7C7C",
+"W+	c #404040",
+"X+	c #FAFAFA",
+"Y+	c #8E8E8E",
+"Z+	c #747373",
+"`+	c #6A696B",
+" @	c #BABAB6",
+".@	c #FBFCED",
+"+@	c #FCFCF4",
+"@@	c #FEFEFB",
+"#@	c #7F7F80",
+"$@	c #AEAEAF",
+"%@	c #D3D3D4",
+"&@	c #82827F",
+"*@	c #D2D3CD",
+"=@	c #F9FAE3",
+"-@	c #F5F7D5",
+";@	c #FAFAD6",
+">@	c #828185",
+",@	c #AAA9B0",
+"'@	c #D4D4D6",
+")@	c #84848B",
+"!@	c #D2D4A6",
+"~@	c #EAEEA4",
+"{@	c #F7FAAB",
+"]@	c #5D5C64",
+"^@	c #807F7F",
+"/@	c #929292",
+"(@	c #CFCFCF",
+"_@	c #F8F8F8",
+":@	c #CACACA",
+"<@	c #9A9999",
+"[@	c #6E6C6B",
+"}@	c #FEFEF5",
+"|@	c #FAFBE9",
+"1@	c #FBFCEE",
+"2@	c #D4D3D4",
+"3@	c #7E7E7C",
+"4@	c #FCFCEC",
+"5@	c #D4D4C2",
+"6@	c #ACACAF",
+"7@	c #808079",
+"8@	c #F4F7B2",
+"9@	c #EAEEA5",
+"0@	c #ECF1A1",
+"a@	c #A6A486",
+"b@	c #727173",
+"c@	c #A7A6A6",
+"d@	c #868686",
+"e@	c #787777",
+"f@	c #717071",
+"g@	c #959590",
+"h@	c #FCFCEB",
+"i@	c #FAFAE8",
+"j@	c #AAAAA8",
+"k@	c #D2D2C9",
+"l@	c #F7F9DC",
+"m@	c #FAFBD9",
+"n@	c #818084",
+"o@	c #ABABAD",
+"p@	c #D2D3A2",
+"q@	c #EBF0A9",
+"r@	c #E9EEA0",
+"s@	c #D6D890",
+"t@	c #64626E",
+"u@	c #838383",
+"v@	c #828181",
+"w@	c #CECECE",
+"x@	c #949494",
+"y@	c #6C6A6D",
+"z@	c #C3C3B9",
+"A@	c #F8FAE1",
+"B@	c #FCFDF5",
+"C@	c #A4A4A6",
+"D@	c #A2A29B",
+"E@	c #F7F8DA",
+"F@	c #FAFBDD",
+"G@	c #A6A5AB",
+"H@	c #A4A483",
+"I@	c #EBEFA8",
+"J@	c #EAEFA3",
+"K@	c #E9EE9F",
+"L@	c #F4F6A3",
+"M@	c #5F5E62",
+"N@	c #9F9E9E",
+"O@	c #888787",
+"P@	c #9E9E9E",
+"Q@	c #68676A",
+"R@	c #E2E2D2",
+"S@	c #F8F9DE",
+"T@	c #A2A2A4",
+"U@	c #9E9F96",
+"V@	c #FAFBDA",
+"W@	c #A2A2A9",
+"X@	c #A0A07E",
+"Y@	c #EBEFA7",
+"Z@	c #EAEEA2",
+"`@	c #E8EE9E",
+" #	c #F0F49C",
+".#	c #7F7F77",
+"+#	c #727070",
+"@#	c #6D6C6A",
+"##	c #FAFCE8",
+"$#	c #A2A298",
+"%#	c #F5F8D6",
+"&#	c #FAFAD9",
+"*#	c #A5A5AA",
+"=#	c #A4A481",
+"-#	c #EAEFA6",
+";#	c #EAEEA1",
+">#	c #E9ED9C",
+",#	c #E7EC96",
+"'#	c #999881",
+")#	c #585757",
+"!#	c #77766F",
+"~#	c #FAFBE2",
+"{#	c #FBFCE7",
+"]#	c #7F7F81",
+"^#	c #282828",
+"/#	c #686868",
+"(#	c #A9A9A1",
+"_#	c #D2D2C3",
+":#	c #F5F7D2",
+"<#	c #F9FAD1",
+"[#	c #80807F",
+"}#	c #AAAAA5",
+"|#	c #D2D29E",
+"1#	c #EAEFA4",
+"2#	c #E8ED9B",
+"3#	c #EAEF98",
+"4#	c #99987D",
+"5#	c #ACABAB",
+"6#	c #808075",
+"7#	c #DFDFC7",
+"8#	c #F6F8D6",
+"9#	c #D3D3C8",
+"0#	c #BBBBBB",
+"a#	c #1E1E1E",
+"b#	c #666667",
+"c#	c #7C7C72",
+"d#	c #FAFBDB",
+"e#	c #F3F5CC",
+"f#	c #D3D4B6",
+"g#	c #7E7E6B",
+"h#	c #F3F6AC",
+"i#	c #E9EE9E",
+"j#	c #E8ED9A",
+"k#	c #F2F69C",
+"l#	c #575849",
+"m#	c #636262",
+"n#	c #ECEBEB",
+"o#	c #7F7E7E",
+"p#	c #8B8A8A",
+"q#	c #61605C",
+"r#	c #DFE0C2",
+"s#	c #FAFCDF",
+"t#	c #7C7D73",
+"u#	c #B0AFAE",
+"v#	c #939394",
+"w#	c #CCCCC9",
+"x#	c #7F7F70",
+"y#	c #D2D2BC",
+"z#	c #F7FAC7",
+"A#	c #7E7E71",
+"B#	c #B0B0B0",
+"C#	c #CCCCCA",
+"D#	c #808179",
+"E#	c #D1D29D",
+"F#	c #EAEFA5",
+"G#	c #EAEEA0",
+"H#	c #E8ED9C",
+"I#	c #E8EC98",
+"J#	c #F1F597",
+"K#	c #898A74",
+"L#	c #888686",
+"M#	c #B1B1B1",
+"N#	c #88898C",
+"O#	c #ACADAF",
+"P#	c #A6A6A6",
+"Q#	c #878686",
+"R#	c #787877",
+"S#	c #B7B89D",
+"T#	c #F3F6CC",
+"U#	c #F4F7D1",
+"V#	c #F4F6D2",
+"W#	c #FAFADA",
+"X#	c #D2D2BF",
+"Y#	c #A2A292",
+"Z#	c #A5A592",
+"`#	c #FCFDE2",
+" $	c #F6F8CF",
+".$	c #F1F4C5",
+"+$	c #F6F8C0",
+"@$	c #D2D3A9",
+"#$	c #A3A482",
+"$$	c #A6A684",
+"%$	c #F8FAB7",
+"&$	c #EEF2A9",
+"*$	c #F2F59E",
+"=$	c #414148",
+"-$	c #7E7E7E",
+";$	c #FBFBFB",
+">$	c #666344",
+",$	c #696F76",
+"'$	c #E4E3E3",
+")$	c #BBBABA",
+"!$	c #A8A7A7",
+"~$	c #A5A49C",
+"{$	c #B2B29D",
+"]$	c #F5F8CA",
+"^$	c #F3F6CB",
+"/$	c #F4F6CD",
+"($	c #F1F4C1",
+"_$	c #EFF2BB",
+":$	c #EEF1B4",
+"<$	c #EDF1B0",
+"[$	c #ECF0AD",
+"}$	c #EBF0A8",
+"|$	c #E8EC99",
+"1$	c #E7EC94",
+"2$	c #F6F8AF",
+"3$	c #444445",
+"4$	c #A3A2A2",
+"5$	c #CDCDCD",
+"6$	c #B7B7B7",
+"7$	c #8C8B7A",
+"8$	c #61593A",
+"9$	c #B4B5B7",
+"0$	c #D0CFD6",
+"a$	c #F2F2B2",
+"b$	c #86866E",
+"c$	c #F8FACF",
+"d$	c #F2F4C7",
+"e$	c #F3F5C9",
+"f$	c #F2F5C6",
+"g$	c #F0F3BD",
+"h$	c #EFF2BA",
+"i$	c #EDF1B1",
+"j$	c #EBEFAA",
+"k$	c #E9ED9E",
+"l$	c #E6EB90",
+"m$	c #9F9E70",
+"n$	c #626263",
+"o$	c #5A5B61",
+"p$	c #CBB250",
+"q$	c #757A83",
+"r$	c #ACACAE",
+"s$	c #A1A09B",
+"t$	c #F8FE9A",
+"u$	c #65646D",
+"v$	c #DEDFB6",
+"w$	c #F1F4C3",
+"x$	c #F1F4C4",
+"y$	c #EFF3BC",
+"z$	c #EEF2B4",
+"A$	c #EBEFA6",
+"B$	c #E6EC94",
+"C$	c #EFF48E",
+"D$	c #5C5A6B",
+"E$	c #72727A",
+"F$	c #BCBCBC",
+"G$	c #948A57",
+"H$	c #5A5548",
+"I$	c #C8C8BB",
+"J$	c #FBFE9D",
+"K$	c #9D9C95",
+"L$	c #74755E",
+"M$	c #F6F9C2",
+"N$	c #F0F2BC",
+"O$	c #EFF2B8",
+"P$	c #EEF2B5",
+"Q$	c #EDF1B2",
+"R$	c #EAEEA3",
+"S$	c #E7EC98",
+"T$	c #E6EB8F",
+"U$	c #C4C691",
+"V$	c #88877C",
+"W$	c #D8D8B9",
+"X$	c #ACACAC",
+"Y$	c #7A8693",
+"Z$	c #887750",
+"`$	c #C0C38A",
+" %	c #A4A39C",
+".%	c #E0DFE2",
+"+%	c #91918E",
+"@%	c #D8DAAE",
+"#%	c #F1F5BB",
+"$%	c #DADDA4",
+"%%	c #EAEDAC",
+"&%	c #ECF0AC",
+"*%	c #ECEFA9",
+"=%	c #E7EC95",
+"-%	c #EAEF94",
+";%	c #E4E891",
+">%	c #83827E",
+",%	c #FAFCA8",
+"'%	c #F4F89C",
+")%	c #A2A1B6",
+"!%	c #6E717A",
+"~%	c #C0AC50",
+"{%	c #575C67",
+"]%	c #D2D2D4",
+"^%	c #EEEEEE",
+"/%	c #737466",
+"(%	c #DDE0AA",
+"_%	c #67684C",
+":%	c #727453",
+"<%	c #DADE9D",
+"[%	c #E6EB92",
+"}%	c #EEF292",
+"|%	c #373820",
+"1%	c #E6E6EA",
+"2%	c #CFD0C4",
+"3%	c #F3F6B1",
+"4%	c #EEF0AB",
+"5%	c #CECED5",
+"6%	c #C2C2C8",
+"7%	c #AAA982",
+"8%	c #9E925B",
+"9%	c #3B3730",
+"0%	c #9D9D9D",
+"a%	c #BBBABB",
+"b%	c #6A6C5C",
+"c%	c #F0F3B2",
+"d%	c #EDF0B0",
+"e%	c #ECF0B0",
+"f%	c #D9DC9D",
+"g%	c #EEF390",
+"h%	c #8C8C75",
+"i%	c #818085",
+"j%	c #9F9F9F",
+"k%	c #A0A0AE",
+"l%	c #FAFEAA",
+"m%	c #B2B2C2",
+"n%	c #D4D4C8",
+"o%	c #838368",
+"p%	c #686E76",
+"q%	c #6E6140",
+"r%	c #7F828C",
+"s%	c #797A68",
+"t%	c #DEDFA3",
+"u%	c #EFF3AE",
+"v%	c #ECF0AB",
+"w%	c #E9EE9D",
+"x%	c #E6EC92",
+"y%	c #F4F896",
+"z%	c #65664C",
+"A%	c #85858A",
+"B%	c #F1F1F3",
+"C%	c #DCDE94",
+"D%	c #E1E39F",
+"E%	c #E1E3BD",
+"F%	c #9D9C7F",
+"G%	c #BFC1C2",
+"H%	c #968E54",
+"I%	c #727988",
+"J%	c #50504E",
+"K%	c #D1D39D",
+"L%	c #F3F6AD",
+"M%	c #EAEFA7",
+"N%	c #E8ED99",
+"O%	c #E9EE90",
+"P%	c #F6FAA8",
+"Q%	c #4A4A44",
+"R%	c #909094",
+"S%	c #B6B6B6",
+"T%	c #BABABA",
+"U%	c #B7B7C0",
+"V%	c #F5F894",
+"W%	c #92919F",
+"X%	c #ACABB2",
+"Y%	c #EDEEB2",
+"Z%	c #B8B795",
+"`%	c #888876",
+" &	c #726949",
+".&	c #9C9C9E",
+"+&	c #88888C",
+"@&	c #60604F",
+"#&	c #D2D497",
+"$&	c #F4F6AB",
+"%&	c #EDF1A2",
+"&&	c #F0F495",
+"*&	c #F6F8AE",
+"=&	c #8C8C76",
+"-&	c #4C4C56",
+";&	c #C1C1C2",
+">&	c #CAC9D7",
+",&	c #F4F898",
+"'&	c #ACAAA0",
+")&	c #B8B7C5",
+"!&	c #F4F6A0",
+"~&	c #5A5D66",
+"{&	c #C79A29",
+"]&	c #565961",
+"^&	c #898989",
+"/&	c #BDBDBD",
+"(&	c #565660",
+"_&	c #50504D",
+":&	c #848366",
+"<&	c #A1A16C",
+"[&	c #F6F9B4",
+"}&	c #F2F5A2",
+"|&	c #F2F5A9",
+"1&	c #CBCD94",
+"2&	c #88885F",
+"3&	c #525250",
+"4&	c #6B6A76",
+"5&	c #8E8E90",
+"6&	c #B8B8B8",
+"7&	c #9696A4",
+"8&	c #F4F6A2",
+"9&	c #D2D1AE",
+"0&	c #BCBC99",
+"a&	c #9F9F92",
+"b&	c #787253",
+"c&	c #AFA99C",
+"d&	c #606061",
+"e&	c #DDDDE4",
+"f&	c #CACACC",
+"g&	c #BFBFC1",
+"h&	c #808087",
+"i&	c #808088",
+"j&	c #808086",
+"k&	c #A1A0B3",
+"l&	c #A3A3A3",
+"m&	c #B9B9C4",
+"n&	c #F5F79E",
+"o&	c #EDF0B2",
+"p&	c #ACACB8",
+"q&	c #C2C2AE",
+"r&	c #77796E",
+"s&	c #968261",
+"t&	c #88876C",
+"u&	c #B3B293",
+"v&	c #E3E2D6",
+"w&	c #B4B3B6",
+"x&	c #DADADA",
+"y&	c #ECECEC",
+"z&	c #C6C6A2",
+"A&	c #ECF0A1",
+"B&	c #EAECC6",
+"C&	c #C2C2C4",
+"D&	c #E8E9C4",
+"E&	c #EDF1A0",
+"F&	c #ECEFB1",
+"G&	c #E6E8C2",
+"H&	c #A0A09C",
+"I&	c #E9EBBD",
+"J&	c #FDFF9C",
+"K&	c #8E8C95",
+"L&	c #CFCE96",
+"M&	c #9E9DA9",
+"N&	c #DBDBDB",
+"O&	c #C9C9CB",
+"P&	c #B6B5C4",
+"Q&	c #F2F698",
+"R&	c #ECF0A2",
+"S&	c #B8B893",
+"T&	c #B4B4B4",
+"U&	c #E0E0E0",
+"V&	c #9796A7",
+"W&	c #F4F89F",
+"X&	c #ECF09F",
+"Y&	c #EEF29A",
+"Z&	c #A6A4CC",
+"`&	c #E4E4A8",
+" *	c #E8E8C1",
+".*	c #A1A0A8",
+"+*	c #B6B6B8",
+"@*	c #E1E3B0",
+"#*	c #EFF49A",
+"$*	c #F6FA9D",
+"%*	c #A1A0B1",
+"&*	c #E1E0E3",
+"**	c #BCBCB2",
+"=*	c #ECF09E",
+"-*	c #DFDFC4",
+";*	c #D8D8A0",
+">*	c #B2B28E",
+",*	c #A4A4A9",
+"'*	c #848490",
+")*	c #D0D1AB",
+"!*	c #F1F5AE",
+"~*	c #EAEE9B",
+"{*	c #9998A9",
+"]*	c #DCDCDF",
+"^*	c #B9B9BC",
+"/*	c #BEBEB5",
+"(*	c #F2F59F",
+"_*	c #EBEFA0",
+":*	c #F5FA96",
+"<*	c #EEF0A6",
+"[*	c #BCBBC1",
+"}*	c #8D8D8F",
+"|*	c #BFBEC3",
+"1*	c #AFAE8C",
+"2*	c #DFE0A6",
+"3*	c #DADDA2",
+"4*	c #EDF29C",
+"5*	c #BEBD9C",
+"6*	c #CECD9D",
+"7*	c #B8B8BC",
+"8*	c #D1D1D3",
+"9*	c #ACACA0",
+"0*	c #E4E6C0",
+"a*	c #E3E6BF",
+"b*	c #D4D4B0",
+"c*	c #ACABB7",
+"d*	c #F7F7F7",
+"e*	c #B1B09C",
+"f*	c #DEDDF2",
+"g*	c #89886A",
+"h*	c #FAFAB4",
+"i*	c #A6A4C2",
+"j*	c #F5F4B3",
+"k*	c #C2C2B4",
+"l*	c #B6B5BC",
+"m*	c #B3B3B3",
+"n*	c #A4A4A4",
+"o*	c #98989D",
+"p*	c #5A5A5C",
+"q*	c #6A6A6A",
+"r*	c #8D8D92",
+"s*	c #464648",
+"t*	c #9B9AA2",
+"u*	c #838371",
+"v*	c #86868F",
+"w*	c #7E7E87",
+"x*	c #868688",
+"y*	c #9B9B9B",
+"z*	c #D7D7D7",
+"                                                                                                ",
+"                                                                  . +           @ #             ",
+"            $ % & *                                             = - ; >         , ' )           ",
+"          ! ~ { > ]           ^ /                                     (         _ : <           ",
+"        > [     } }         [ |       1 2 3 4 5 6 7 8 9 0 a b                     c             ",
+"        > d     : e               f g h i j k 9 9 9 l m n o p q r s               :             ",
+"          t   ^ u v           | w x y z A B C D E F G H n 9 9 9 I J K L         b ' M           ",
+"        ] +   N O L       P Q y r R S T U V W X Y Z `  ...+.@.9 9 9 9 9 #.      $.I %.          ",
+"      &.*.=.    { <     # z -.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.9 1.2.3.4.      >             ",
+"        s L           5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.n 9 s.t.        > f       ",
+"                    u.v.w.x.k 9 y.z.A.B.C.D.e.f.E.F.G.H.I.J.K.L.M.N.O.r.9 9 s.P.    ) Q.        ",
+"    R.S.T.          =.U.V.W.X.Y.Z.`. +.+++C.D.e.@+#+$+j.k.%+&+*+=+-+;+>+r.9 n 1.,+              ",
+"    '+)+{         Q !+~+1.{+]+^+/+(+_+:+<+++C.d.[+g.}+G.|+l.1+2+3+4+5+6+7+8+n 9+0+$             ",
+"      +         a+b+!+W.c+d+Z.e+f+g+h+i+:+.+B.j+k+l+h.m+n+o+p+q+r+s+t+u+v+w+9 n ~ 3             ",
+"    x+y+z+      A+B+C+W.D+E+:+f+F+G+: H+I+E+J+K+e.l+h.i.L+M+N+O+P+Q+5+R+S+T+U+9 m V+P           ",
+"    d W+[     X+: Y+Z+`+ @.@:++@@@#@$@  %@&@*@=@e.@+-@;@>@,@  '@)@!@5+R+~@{@]@n ^@/@(@          ",
+"    _@!       :@<@B o [@}@|@1@i+2@N         3@4@k+l+h.5@6@        7@8@R+9@0@a@b@9+0 c@          ",
+"            2 W.d@e@f@g@h@i@<+h+#@          j@k@l@g.m@n@          o@p@q@~@r@s@t@1.u@v@S $       ",
+"          w@I <@x@m y@z@A@C.++B@C@            D@E@E.F@G@            H@I@J@K@L@M@b+4 N@j O@      ",
+"          P@u@! b+b+Q@R@S@D.C.i+T@            U@g.-@V@W@            X@Y@Z@`@ #.#1.+#*.R.7       ",
+"          P@2.^@Z+x.@###f.S@A@_+C@  X+L &.    $#%#}+&#*#  X+L &.    =#-#;#>#,#'#B 1.e@v@)#      ",
+"          P@9 Z+1.x.!#~#g.f.l@{#]#  { ^#/#  (#_#:#m+<#[#  { ^#/#  }#|#1#r@2#3#4#l 1.Z+Z+)#      ",
+"          5#n V+B 1.6#7#h.8#g.@+9#o@0#a#b#  c#d#m+e#k.f#6@0#a#b#  g#h#Z@i#j#k#l#V.Z+V.u m#      ",
+"          n#o#p#C+1.q#r#i.:#h.#+s#t#u#v#w#x#y#m+e#k.l.z#A#B#v#C#D#E#F#G#H#I#J#K#m B L#C+g       ",
+"        M#N#O#P#Q#W.R#S#T#G.i.U#V#W#X#Y#Z#`# $H.k..$J.K.+$@$#$$$%$&$Z@i#j#,#*$=$9 V.-$;$        ",
+"        I+>$,$'$)$!$~${$]$(.^$T#/$G.G./$T#H.k.I.%+($K._$r+:$<$[$}$1#G#H#|$1$2$3$4$c@5$          ",
+"        6$7$8$9$Q.0$a$b$c$l.d$k.k.k.e$k.I.f$%+J.m.g$h$3+:$i$[$j$-#Z@k$j#,#l$m$n$  (@            ",
+"        ] o$p$q$r$s$t$u$v$1+J.w$x$%+%+x$J.p+m.K.y$L.=+z$i$[$j$A$Z@K@2#I#B$C$D$E$  F$            ",
+"          , G$H$I$J$K$  L$M$K.K.&+&+&+K.K.q+N$h$O$P$Q$<$[$j$A$R$r@H#S$1$T$U$V$W$L . -           ",
+"          X$Y$Z$`$ %.%  +%@%#%L.*+h$h$h$L.r+=+P$$%$%%%&%*%A$R$r@H#|$=%-%;%>%,%'%)%L .           ",
+"          )+!%~%{%]%^%    /%(%M.P$=+=+P$z$s+4+<$_%:%<%I@F#Z@r@H#|$=%[%}%|%1%2%3%4%5%+           ",
+"          6%7%8%9%0%( y+y+a%b%P+c%d%d%d%e%5+5+&%f%I@Y@~@;#i#H#|$,#[%g%h%i%6$j%k%l%m%5$          ",
+"        - n%o%p%q%r%f       : s%t%u%&%v%v%R+q@I@A$1#Z@r@w%j#S$=%x%y%z%A%      B%C%D%,@          ",
+"        < E%F%G%H%I%S.y+y+y+y+0#J%K%L%M%-#A$~@R$Z@r@i#H#N%,#B$O%P%Q%R%S%y+y+y+T%U%V%W%          ",
+"        X%Y%Z%M#`% &.&L           +&@&#&$&%&r@i#>#H#j#I#1$&&*&=&-&;&            >&,&'&a+        ",
+"        )&!&Z%L ~&{&]&^&/&( y+y+y+S%F$(&_&:&<&[&L@}&|&1&2&3&4&5&6$6$6$6$6$6$6$6&7&8&9&=         ",
+"        )&!&0&5$a&b&c&d&e&f&                g&h&i&i&j&j&  ;$> z+z+z+z+z+z+z+z+> k&8&E%l&        ",
+"        m&n&o&p&q&r&s&t&u&v&w&| x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&y&z&A&B&6&        ",
+"        C&D&E&F&G&H&I&J&K&L&M&| x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&N&O&P&Q&R&S&T&        ",
+"        U&V&W&Z@Z@X&Y&Z&`& *.*| x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&{ f %.+*@*#*$*%*. -       ",
+"      > Q.&*** #Z@Z@=*-*;*>*,*| x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&( '*)*!*~*e%{*]*- .       ",
+"      . -   ^*/*(*Z@_*:*<*[*}*6$6$6$6$6$6$6$6$6$6$6$6$6$6$6$6$6$6$6$T%|*1*2*3*4*5*6*7*  F$      ",
+"      F$    &.8*9*0*a*b*c*f&d*z+z+z+z+z+z+z+z+z+z+z+z+z+z+z+z+z+z+z+> e*f*g*h*i*j*k*l*  Q.      ",
+"      F$  m*6&S%* l&n*o*p*q*0#y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+X$r*s*t*u*v*w*x*y*  F$      ",
+"    z*y&                                                                                #.      ",
+"    ( w@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./&e     ",
+"                                                                                                ",
+"                                                                                                "};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/backend-fluidsynth/Makefile.in	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,15 @@
+include ../../../../mk/rules.mk
+include ../../../../mk/objective.mk
+
+noinst_HEADERS = b-fluidsynth.h b-fluidsynth-config.h backend-fluidsynth-icon.xpm
+
+CFLAGS += -fPIC -DPIC $(GLIB_CFLAGS) $(FLUIDSYNTH_CFLAGS) -I../../../../intl -I../../../..
+
+libdir = $(AMIDIPLUGDATADIR)
+
+OBJECTIVE_LIBS = ap-fluidsynth.so
+
+LIBADD = -lm $(GLIB_LIBS) $(FLUIDSYNTH_LIBS) ../pcfg/libpcfg.a
+SOURCES = b-fluidsynth.c
+
+OBJECTS = ${SOURCES:.c=.o}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/backend-fluidsynth/b-fluidsynth-config.h	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,41 @@
+/*
+*
+* 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 _B_FLUIDSYNTH_CONFIG_H
+#define _B_FLUIDSYNTH_CONFIG_H 1
+
+
+typedef struct
+{
+  gchar *	fsyn_soundfont_file;
+  gint		fsyn_soundfont_load;
+  gint		fsyn_synth_samplerate;
+  gint		fsyn_synth_gain;
+  gint		fsyn_synth_poliphony;
+  gint		fsyn_synth_reverb;
+  gint		fsyn_synth_chorus;
+  gint		fsyn_buffer_size;
+  gint		fsyn_buffer_margin;
+  gint		fsyn_buffer_increment;
+}
+amidiplug_cfg_fsyn_t;
+
+
+#endif /* !_B_FLUIDSYNTH_CONFIG_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/backend-fluidsynth/b-fluidsynth.c	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,455 @@
+/*
+*
+* 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 "b-fluidsynth.h"
+#include "b-fluidsynth-config.h"
+
+/* sequencer instance */
+static sequencer_client_t sc;
+/* options */
+static amidiplug_cfg_fsyn_t amidiplug_cfg_fsyn;
+
+
+gint backend_info_get( gchar ** name , gchar ** longname , gchar ** desc , gint * ppos )
+{
+  if ( name != NULL )
+    *name = g_strdup( "fluidsynth" );
+  if ( longname != NULL )
+    *longname = g_strdup( "FluidSynth Backend " AMIDIPLUG_VERSION );
+  if ( desc != NULL )
+    *desc = g_strdup( _("This backend produces audio by sending MIDI events "
+                        "to FluidSynth, a real-time software synthesizer based "
+                        "on the SoundFont2 specification (www.fluidsynth.org).\n"
+                        "Produced audio can be manipulated via player effect "
+                        "plugins and is processed by chosen ouput plugin.\n"
+                        "Backend written by Giacomo Lozito.") );
+  if ( ppos != NULL )
+    *ppos = 2; /* preferred position in backend list */
+  return 1;
+}
+
+
+gint backend_init( void )
+{
+  /* read configuration options */
+  i_cfg_read();
+
+  sc.soundfont_id = -1;
+  sc.sample_rate = amidiplug_cfg_fsyn.fsyn_synth_samplerate;
+  sc.settings = new_fluid_settings();
+
+  fluid_settings_setnum( sc.settings , "synth.sample-rate" , amidiplug_cfg_fsyn.fsyn_synth_samplerate );
+  if ( amidiplug_cfg_fsyn.fsyn_synth_gain != -1 )
+    fluid_settings_setnum( sc.settings , "synth.gain" , (gdouble)amidiplug_cfg_fsyn.fsyn_synth_gain / 10 );
+  if ( amidiplug_cfg_fsyn.fsyn_synth_poliphony != -1 )
+    fluid_settings_setint( sc.settings , "synth.poliphony" , amidiplug_cfg_fsyn.fsyn_synth_poliphony );
+  if ( amidiplug_cfg_fsyn.fsyn_synth_reverb == 1 )
+    fluid_settings_setstr( sc.settings , "synth.reverb.active" , "yes" );
+  else if ( amidiplug_cfg_fsyn.fsyn_synth_reverb == 0 )
+    fluid_settings_setstr( sc.settings , "synth.reverb.active" , "no" );
+  if ( amidiplug_cfg_fsyn.fsyn_synth_chorus == 1 )
+    fluid_settings_setstr( sc.settings , "synth.chorus.active" , "yes" );
+  else if ( amidiplug_cfg_fsyn.fsyn_synth_chorus == 0 )
+    fluid_settings_setstr( sc.settings , "synth.chorus.active" , "no" );
+
+  sc.synth = new_fluid_synth( sc.settings );
+
+  /* soundfont loader, check if we should load soundfont on backend init */
+  if ( amidiplug_cfg_fsyn.fsyn_soundfont_load == 0 )
+    i_soundfont_load();
+
+  return 1;
+}
+
+
+gint backend_cleanup( void )
+{
+  if ( sc.soundfont_id != -1 )
+    fluid_synth_sfunload( sc.synth , sc.soundfont_id , 0 );
+  delete_fluid_synth( sc.synth );
+  delete_fluid_settings( sc.settings );
+
+  i_cfg_free(); /* free configuration options */
+
+  return 1;
+}
+
+
+gint sequencer_get_port_count( void )
+{
+  /* always return a single port here */
+  return 1;
+}
+
+
+gint sequencer_start( gchar * midi_fname )
+{
+  /* soundfont loader, check if we should load soundfont on first midifile play */
+  if (( amidiplug_cfg_fsyn.fsyn_soundfont_load == 1 ) && (sc.soundfont_id == -1 ))
+    i_soundfont_load();
+
+  return 1; /* success */
+}
+
+
+gint sequencer_stop( void )
+{
+  return 1; /* success */
+}
+
+
+/* activate sequencer client */
+gint sequencer_on( void )
+{
+  sc.last_sample_time = 0;
+  sc.tick_offset = 0;
+
+  sc.timer_seq = g_timer_new(); /* create the sequencer timer */
+  sc.timer_sample = g_timer_new(); /* create the sampler timer */
+
+  return 1; /* success */
+}
+
+
+/* shutdown sequencer client */
+gint sequencer_off( void )
+{
+  if ( sc.timer_seq != NULL )
+  {
+    g_timer_destroy( sc.timer_seq ); /* destroy the sequencer timer */
+    sc.timer_seq = NULL;
+  }
+  if ( sc.timer_sample != NULL )
+  {
+    g_timer_destroy( sc.timer_sample ); /* destroy the sampler timer */
+    sc.timer_sample = NULL;
+  }
+  return 1; /* success */
+}
+
+
+/* queue set tempo */
+gint sequencer_queue_tempo( gint tempo , gint ppq )
+{
+  sc.ppq = ppq;
+  /* sc.cur_tick_per_sec = (gdouble)( ppq * 1000000 ) / (gdouble)tempo; */
+  sc.cur_microsec_per_tick = (gdouble)tempo / (gdouble)ppq;
+  return 1;
+}
+
+
+gint sequencer_queue_start( void )
+{
+  g_timer_start( sc.timer_seq ); /* reset the sequencer timer */
+  g_timer_start( sc.timer_sample ); /* reset the sampler timer */
+  return 1;
+}
+
+
+gint sequencer_event_init( void )
+{
+  /* common settings for all our events */
+  return 1;
+}
+
+
+gint sequencer_event_noteon( midievent_t * event )
+{
+  i_sleep( event->tick_real );
+  fluid_synth_noteon( sc.synth ,
+                      event->data.d[0] ,
+                      event->data.d[1] ,
+                      event->data.d[2] );
+  return 1;
+}
+
+
+gint sequencer_event_noteoff( midievent_t * event )
+{
+  i_sleep( event->tick_real );
+  fluid_synth_noteoff( sc.synth ,
+                       event->data.d[0] ,
+                       event->data.d[1] );
+  return 1;
+}
+
+
+gint sequencer_event_keypress( midievent_t * event )
+{
+  /* KEY PRESSURE events are not handled by FluidSynth sequencer? */
+  DEBUGMSG( "KEYPRESS EVENT with FluidSynth backend (unhandled)\n" );
+  i_sleep( event->tick_real );
+  return 1;
+}
+
+
+gint sequencer_event_controller( midievent_t * event )
+{
+  i_sleep( event->tick_real );
+  fluid_synth_cc( sc.synth ,
+                  event->data.d[0] ,
+                  event->data.d[1] ,
+                  event->data.d[2] );
+  return 1;
+}
+
+
+gint sequencer_event_pgmchange( midievent_t * event )
+{
+  i_sleep( event->tick_real );
+  fluid_synth_program_change( sc.synth ,
+                              event->data.d[0] ,
+                              event->data.d[1] );
+  return 1;
+}
+
+
+gint sequencer_event_chanpress( midievent_t * event )
+{
+  /* CHANNEL PRESSURE events are not handled by FluidSynth sequencer? */
+  DEBUGMSG( "CHANPRESS EVENT with FluidSynth backend (unhandled)\n" );
+  i_sleep( event->tick_real );
+  return 1;
+}
+
+
+gint sequencer_event_pitchbend( midievent_t * event )
+{
+  gint pb_value = (((event->data.d[2]) & 0x7f) << 7) | ((event->data.d[1]) & 0x7f);
+  i_sleep( event->tick_real );
+  fluid_synth_pitch_bend( sc.synth ,
+                          event->data.d[0] ,
+                          pb_value );
+  return 1;
+}
+
+
+gint sequencer_event_sysex( midievent_t * event )
+{
+  DEBUGMSG( "SYSEX EVENT with FluidSynth backend (unhandled)\n" );
+  i_sleep( event->tick_real );
+  return 1;
+}
+
+
+gint sequencer_event_tempo( midievent_t * event )
+{
+  i_sleep( event->tick_real );
+  /* sc.cur_tick_per_sec = (gdouble)( sc.ppq * 1000000 ) / (gdouble)event->data.tempo; */
+  sc.cur_microsec_per_tick = (gdouble)event->data.tempo / (gdouble)sc.ppq;
+  g_timer_start( sc.timer_seq ); /* reset the sequencer timer */
+  sc.tick_offset = event->tick_real;
+  return 1;
+}
+
+
+gint sequencer_event_other( midievent_t * event )
+{
+  /* unhandled */
+  i_sleep( event->tick_real );
+  return 1;
+}
+
+
+gint sequencer_output( gpointer * buffer , gint * len )
+{
+  gdouble current_time = g_timer_elapsed( sc.timer_sample , NULL );
+  if (( current_time > 0.000500 ) && 
+      ( (current_time - sc.last_sample_time) * 1000000 >=
+        ((gdouble)amidiplug_cfg_fsyn.fsyn_buffer_size * 1000000 / sc.sample_rate) ))
+  {
+    sc.last_sample_time = g_timer_elapsed( sc.timer_sample , NULL ) - 0.000500;
+    /* number of samples to get = buffer size + incremental margin */
+    /* g_print( "buf increment: %i\n" , amidiplug_cfg_fsyn.fsyn_buffer_margin +
+             ((gint)sc.last_sample_time / amidiplug_cfg_fsyn.fsyn_buffer_increment) ); */
+    *len = (amidiplug_cfg_fsyn.fsyn_buffer_size + amidiplug_cfg_fsyn.fsyn_buffer_margin +
+           ((gint)sc.last_sample_time / amidiplug_cfg_fsyn.fsyn_buffer_increment) );
+    *buffer = g_realloc( *buffer , *len * 4 );
+    fluid_synth_write_s16( sc.synth , *len , *buffer , 0 , 2 , *buffer , 1 , 2 );
+    *len = *len * 4; /* return the real buffer size in bytes */
+    return 1;
+  }
+  else
+  {
+    G_USLEEP( 500 );
+    return 0;
+  }
+}
+
+
+gint sequencer_output_shut( guint max_tick , gint skip_offset )
+{
+  fluid_synth_system_reset( sc.synth ); /* all notes off and channels reset */
+  return 1;
+}
+
+
+/* unimplemented, for autonomous audio == FALSE volume is set by the
+   output plugin mixer controls and is not handled by input plugins */
+gint audio_volume_get( gint * left_volume , gint * right_volume )
+{
+  return 0; 
+}
+gint audio_volume_set( gint left_volume , gint right_volume )
+{
+  return 0;
+}
+
+
+gint audio_info_get( gint * channels , gint * bitdepth , gint * samplerate )
+{
+  *channels = 2;
+  *bitdepth = 16; /* always 16 bit, we use fluid_synth_write_s16() */
+  *samplerate = amidiplug_cfg_fsyn.fsyn_synth_samplerate;
+  return 1; /* valid information */
+}
+
+
+gboolean audio_check_autonomous( void )
+{
+  return FALSE; /* FluidSynth gives produced audio back to player */
+}
+
+
+
+/* ******************************************************************
+   *** INTERNALS ****************************************************
+   ****************************************************************** */
+
+
+void i_sleep( guint tick )
+{
+  gdouble elapsed_tick_usecs = (gdouble)(tick - sc.tick_offset) * sc.cur_microsec_per_tick;
+  gdouble elapsed_seq_usecs = g_timer_elapsed( sc.timer_seq , NULL ) * 1000000;
+  if ( elapsed_seq_usecs < elapsed_tick_usecs )
+  {
+    G_USLEEP( elapsed_tick_usecs - elapsed_seq_usecs );
+  }
+}
+
+
+void i_soundfont_load( void )
+{
+  if ( strcmp( amidiplug_cfg_fsyn.fsyn_soundfont_file , "" ) )
+  {
+    DEBUGMSG( "loading soundfont %s\n" , amidiplug_cfg_fsyn.fsyn_soundfont_file );
+    sc.soundfont_id = fluid_synth_sfload( sc.synth , amidiplug_cfg_fsyn.fsyn_soundfont_file , 0 );
+    if ( sc.soundfont_id == -1 )
+      g_warning( "unable to load SoundFont file %s\n" , amidiplug_cfg_fsyn.fsyn_soundfont_file );
+#ifdef DEBUG
+    else
+      DEBUGMSG( "soundfont %s successfully loaded\n" , amidiplug_cfg_fsyn.fsyn_soundfont_file );
+#endif
+  }
+  else
+  {
+    g_warning( "FluidSynth backend was selected, but no SoundFont has been specified\n" );
+    sc.soundfont_id = -1;
+  }
+}
+
+
+gboolean i_bounds_check( gint value , gint min , gint max )
+{
+  if (( value >= min ) && ( value <= max ))
+    return TRUE;
+  else
+    return FALSE;
+}
+
+
+void i_cfg_read( void )
+{
+  pcfg_t *cfgfile;
+  gchar * config_pathfilename = g_strjoin( "" , g_get_home_dir() , "/" ,
+                                           PLAYER_LOCALRCDIR , "/amidi-plug.conf" , NULL );
+  cfgfile = i_pcfg_new_from_file( config_pathfilename );
+
+  if ( !cfgfile )
+  {
+    /* fluidsynth backend defaults */
+    amidiplug_cfg_fsyn.fsyn_soundfont_file = g_strdup( "" );
+    amidiplug_cfg_fsyn.fsyn_soundfont_load = 1;
+    amidiplug_cfg_fsyn.fsyn_synth_samplerate = 44100;
+    amidiplug_cfg_fsyn.fsyn_synth_gain = -1;
+    amidiplug_cfg_fsyn.fsyn_synth_poliphony = -1;
+    amidiplug_cfg_fsyn.fsyn_synth_reverb = -1;
+    amidiplug_cfg_fsyn.fsyn_synth_chorus = -1;
+    amidiplug_cfg_fsyn.fsyn_buffer_size = 512;
+    amidiplug_cfg_fsyn.fsyn_buffer_margin = 10;
+    amidiplug_cfg_fsyn.fsyn_buffer_increment = 18;
+  }
+  else
+  {
+    i_pcfg_read_string( cfgfile , "fsyn" , "fsyn_soundfont_file" ,
+                        &amidiplug_cfg_fsyn.fsyn_soundfont_file , "" );
+
+    i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_soundfont_load" ,
+                         &amidiplug_cfg_fsyn.fsyn_soundfont_load , 1 );
+
+    i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_synth_samplerate" ,
+                         &amidiplug_cfg_fsyn.fsyn_synth_samplerate , 44100 );
+    if ( !i_bounds_check( amidiplug_cfg_fsyn.fsyn_synth_samplerate , 22050 , 96000 ) )
+      amidiplug_cfg_fsyn.fsyn_synth_samplerate = 44100;
+
+    i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_synth_gain" ,
+                         &amidiplug_cfg_fsyn.fsyn_synth_gain , -1 );
+    if (( amidiplug_cfg_fsyn.fsyn_synth_gain != -1 ) &&
+        ( !i_bounds_check( amidiplug_cfg_fsyn.fsyn_synth_gain , 0 , 100 ) ))
+      amidiplug_cfg_fsyn.fsyn_synth_gain = -1;
+
+    i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_synth_poliphony" ,
+                         &amidiplug_cfg_fsyn.fsyn_synth_poliphony , -1 );
+    if (( amidiplug_cfg_fsyn.fsyn_synth_poliphony != -1 ) &&
+        ( !i_bounds_check( amidiplug_cfg_fsyn.fsyn_synth_poliphony , 0 , 100 ) ))
+      amidiplug_cfg_fsyn.fsyn_synth_poliphony = -1;
+
+    i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_synth_reverb" ,
+                         &amidiplug_cfg_fsyn.fsyn_synth_reverb , -1 );
+
+    i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_synth_chorus" ,
+                         &amidiplug_cfg_fsyn.fsyn_synth_chorus , -1 );
+
+    i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_buffer_size" ,
+                         &amidiplug_cfg_fsyn.fsyn_buffer_size , 512 );
+    if ( !i_bounds_check( amidiplug_cfg_fsyn.fsyn_buffer_size , 100 , 99999 ) )
+      amidiplug_cfg_fsyn.fsyn_buffer_size = 512;
+
+    i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_buffer_margin" ,
+                         &amidiplug_cfg_fsyn.fsyn_buffer_margin , 15 );
+    if ( !i_bounds_check( amidiplug_cfg_fsyn.fsyn_buffer_margin , 0 , 100 ) )
+      amidiplug_cfg_fsyn.fsyn_buffer_margin = 15;
+
+    i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_buffer_increment" ,
+                         &amidiplug_cfg_fsyn.fsyn_buffer_increment , 18 );
+    if ( !i_bounds_check( amidiplug_cfg_fsyn.fsyn_buffer_increment , 6 , 1000 ) )
+      amidiplug_cfg_fsyn.fsyn_buffer_increment = 18;
+
+    i_pcfg_free( cfgfile );
+  }
+
+  g_free( config_pathfilename );
+}
+
+
+void i_cfg_free( void )
+{
+  g_free( amidiplug_cfg_fsyn.fsyn_soundfont_file );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/backend-fluidsynth/b-fluidsynth.h	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,56 @@
+/*
+*
+* 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 _B_FLUIDSYNTH_H
+#define _B_FLUIDSYNTH_H 1
+
+#include <fluidsynth.h>
+#include <math.h>
+#include "../i_common.h"
+#include "../pcfg/i_pcfg.h"
+#include "../i_midievent.h"
+
+
+typedef struct
+{
+  fluid_settings_t * settings;
+  fluid_synth_t * synth;
+
+  gint soundfont_id;
+
+  gint ppq;
+  gdouble cur_microsec_per_tick;
+  guint tick_offset;
+
+  GTimer * timer_seq;
+  GTimer * timer_sample;
+
+  guint sample_rate;
+  gdouble last_sample_time;
+}
+sequencer_client_t;
+
+
+void i_sleep( guint );
+void i_soundfont_load( void );
+void i_cfg_read( void );
+void i_cfg_free( void );
+
+#endif /* !_B_FLUIDSYNTH_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/backend-fluidsynth/backend-fluidsynth-icon.xpm	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,1408 @@
+/* XPM */
+static char * backend_fluidsynth_icon_xpm[] = {
+"48 48 1357 2",
+"  	c None",
+". 	c #11002D",
+"+ 	c #11002E",
+"@ 	c #160830",
+"# 	c #12022E",
+"$ 	c #251F3E",
+"% 	c #2C2B44",
+"& 	c #170B32",
+"* 	c #10002D",
+"= 	c #160730",
+"- 	c #211A3A",
+"; 	c #10002C",
+"> 	c #241839",
+", 	c #1A0E33",
+"' 	c #170930",
+") 	c #11012D",
+"! 	c #11022D",
+"~ 	c #14052F",
+"{ 	c #160931",
+"] 	c #2A233E",
+"^ 	c #16092F",
+"/ 	c #332A41",
+"( 	c #11012C",
+"_ 	c #1A0D31",
+": 	c #211534",
+"< 	c #271F41",
+"[ 	c #211838",
+"} 	c #12032D",
+"| 	c #363343",
+"1 	c #14062E",
+"2 	c #10012C",
+"3 	c #10002B",
+"4 	c #221A37",
+"5 	c #2F253D",
+"6 	c #1F1333",
+"7 	c #1B1036",
+"8 	c #1D1434",
+"9 	c #170C2F",
+"0 	c #12032C",
+"a 	c #170B2F",
+"b 	c #13072D",
+"c 	c #10002A",
+"d 	c #16072E",
+"e 	c #231437",
+"f 	c #28193C",
+"g 	c #2F2140",
+"h 	c #352841",
+"i 	c #14052D",
+"j 	c #231537",
+"k 	c #12022B",
+"l 	c #14052E",
+"m 	c #251A3A",
+"n 	c #231438",
+"o 	c #2E2040",
+"p 	c #13042D",
+"q 	c #1E1033",
+"r 	c #1B0C32",
+"s 	c #17092F",
+"t 	c #888277",
+"u 	c #928C7F",
+"v 	c #969083",
+"w 	c #9B9587",
+"x 	c #5B5258",
+"y 	c #706868",
+"z 	c #5E565B",
+"A 	c #14052C",
+"B 	c #0F002A",
+"C 	c #11012B",
+"D 	c #3E3249",
+"E 	c #787070",
+"F 	c #1B0B31",
+"G 	c #989187",
+"H 	c #CDCAA9",
+"I 	c #493D50",
+"J 	c #170C30",
+"K 	c #392F42",
+"L 	c #7B746F",
+"M 	c #2A1E3A",
+"N 	c #10012A",
+"O 	c #1C0E31",
+"P 	c #E2E3B0",
+"Q 	c #EDEEBA",
+"R 	c #F4F5BF",
+"S 	c #F9F9C3",
+"T 	c #6E6862",
+"U 	c #B9B498",
+"V 	c #847E72",
+"W 	c #14062C",
+"X 	c #281A3B",
+"Y 	c #10012B",
+"Z 	c #5F5560",
+"` 	c #C0BCA3",
+" .	c #534958",
+"..	c #FBFBCA",
+"+.	c #FFFFCB",
+"@.	c #CBC8A6",
+"#.	c #11022B",
+"$.	c #14082E",
+"%.	c #201C39",
+"&.	c #3D3244",
+"*.	c #C1BF99",
+"=.	c #453B4B",
+"-.	c #2C2140",
+";.	c #1F1531",
+">.	c #17092E",
+",.	c #E3E3B1",
+"'.	c #F1F1BC",
+").	c #F8F8C2",
+"!.	c #FDFDC6",
+"~.	c #716C65",
+"{.	c #B6B298",
+"].	c #8B8677",
+"^.	c #2D203D",
+"/.	c #8B837C",
+"(.	c #16082F",
+"_.	c #5E5461",
+":.	c #C0BCA5",
+"<.	c #A49F8F",
+"[.	c #FFFFCD",
+"}.	c #FDFDC8",
+"|.	c #10022B",
+"1.	c #403645",
+"2.	c #C4C39B",
+"3.	c #433849",
+"4.	c #0F0029",
+"5.	c #291D3D",
+"6.	c #221A32",
+"7.	c #13052C",
+"8.	c #E2E2B2",
+"9.	c #E2E1B3",
+"0.	c #DEDCB2",
+"a.	c #E0DEB5",
+"b.	c #5A5258",
+"c.	c #AFAB95",
+"d.	c #8E897A",
+"e.	c #15062C",
+"f.	c #2A2344",
+"g.	c #14062D",
+"h.	c #645B5F",
+"i.	c #D1CFA8",
+"j.	c #5D5360",
+"k.	c #C0BCA4",
+"l.	c #100129",
+"m.	c #DCDAB5",
+"n.	c #E4E3B9",
+"o.	c #BEBA9E",
+"p.	c #FCFCC8",
+"q.	c #1E1032",
+"r.	c #443B48",
+"s.	c #C6C69D",
+"t.	c #3C3244",
+"u.	c #12052B",
+"v.	c #12042A",
+"w.	c #767167",
+"x.	c #231635",
+"y.	c #1F1133",
+"z.	c #15072D",
+"A.	c #A9A394",
+"B.	c #918C7E",
+"C.	c #15072C",
+"D.	c #292641",
+"E.	c #11032B",
+"F.	c #6B6264",
+"G.	c #DBDAAD",
+"H.	c #100229",
+"I.	c #5C525F",
+"J.	c #F5F5C7",
+"K.	c #5F565E",
+"L.	c #180A2F",
+"M.	c #C2BFA0",
+"N.	c #1D0F32",
+"O.	c #11022A",
+"P.	c #1B0E30",
+"Q.	c #483F4A",
+"R.	c #C8C89E",
+"S.	c #362A41",
+"T.	c #261E38",
+"U.	c #0F0028",
+"V.	c #110229",
+"W.	c #E1E1B1",
+"X.	c #726D65",
+"Y.	c #13052A",
+"Z.	c #190C2F",
+"`.	c #A59F94",
+" +	c #948F82",
+".+	c #16082B",
+"++	c #4A3F4F",
+"@+	c #BDBA9B",
+"#+	c #281B3B",
+"$+	c #13042B",
+"%+	c #5C525E",
+"&+	c #C0BDA5",
+"*+	c #231536",
+"=+	c #FAFACB",
+"-+	c #544A56",
+";+	c #1C0E30",
+">+	c #1F1135",
+",+	c #544956",
+"'+	c #2E223D",
+")+	c #4C424C",
+"!+	c #CACA9F",
+"~+	c #33273E",
+"{+	c #1B1131",
+"]+	c #0F0128",
+"^+	c #DEDDB1",
+"/+	c #767068",
+"(+	c #120429",
+"_+	c #AAA99C",
+":+	c #999488",
+"<+	c #17092C",
+"[+	c #352A40",
+"}+	c #C1BDA5",
+"|+	c #2B1E3B",
+"1+	c #F4F4C7",
+"2+	c #13052B",
+"3+	c #12032A",
+"4+	c #756A6F",
+"5+	c #584D58",
+"6+	c #50464F",
+"7+	c #CCCCA0",
+"8+	c #2F233B",
+"9+	c #11032A",
+"0+	c #322A4B",
+"a+	c #1F1532",
+"b+	c #DDDCB1",
+"c+	c #78726B",
+"d+	c #110429",
+"e+	c #0E0028",
+"f+	c #AFAFA3",
+"g+	c #9D998F",
+"h+	c #170A2C",
+"i+	c #100128",
+"j+	c #100228",
+"k+	c #17082D",
+"l+	c #605661",
+"m+	c #FCFCCC",
+"n+	c #1E1031",
+"o+	c #180C2D",
+"p+	c #160A2C",
+"q+	c #110329",
+"r+	c #231636",
+"s+	c #7F7577",
+"t+	c #716967",
+"u+	c #534A52",
+"v+	c #CECEA2",
+"w+	c #30253D",
+"x+	c #11052A",
+"y+	c #0E0027",
+"z+	c #231934",
+"A+	c #DAD9B1",
+"B+	c #7B766F",
+"C+	c #120529",
+"D+	c #959094",
+"E+	c #A19D97",
+"F+	c #170B2C",
+"G+	c #281B3C",
+"H+	c #261A38",
+"I+	c #201235",
+"J+	c #2C1E3E",
+"K+	c #291C3B",
+"L+	c #10032A",
+"M+	c #0E012B",
+"N+	c #190C31",
+"O+	c #392A4A",
+"P+	c #786E75",
+"Q+	c #C2BFA6",
+"R+	c #190D30",
+"S+	c #3E3348",
+"T+	c #0E0129",
+"U+	c #1C1333",
+"V+	c #261C39",
+"W+	c #241637",
+"X+	c #3B2D49",
+"Y+	c #2A1C3D",
+"Z+	c #372947",
+"`+	c #2A1D3D",
+" @	c #3E2F4E",
+".@	c #1A0C2F",
+"+@	c #41354B",
+"@@	c #9A9386",
+"#@	c #8E887C",
+"$@	c #352842",
+"%@	c #574E55",
+"&@	c #CFCFA2",
+"*@	c #54475C",
+"=@	c #251738",
+"-@	c #D2D0B0",
+";@	c #807C7B",
+">@	c #170B2D",
+",@	c #12052A",
+"'@	c #8F8996",
+")@	c #A4A3A9",
+"!@	c #231939",
+"~@	c #9E9797",
+"{@	c #2B2647",
+"]@	c #0E022F",
+"^@	c #7D767D",
+"/@	c #4E4A66",
+"(@	c #332E5B",
+"_@	c #8C868A",
+":@	c #110E50",
+"<@	c #0E0C4F",
+"[@	c #655E6E",
+"}@	c #DAD7BA",
+"|@	c #C7C3AB",
+"1@	c #C4C4B0",
+"2@	c #100F50",
+"3@	c #F0F0C6",
+"4@	c #888381",
+"5@	c #0E0C4E",
+"6@	c #0D0D4F",
+"7@	c #37345F",
+"8@	c #928D84",
+"9@	c #0E0B4E",
+"0@	c #0F0A49",
+"a@	c #766C72",
+"b@	c #7E7777",
+"c@	c #7C777B",
+"d@	c #786D73",
+"e@	c #A8A28F",
+"f@	c #9E9A84",
+"g@	c #100329",
+"h@	c #5C505F",
+"i@	c #C2BF9E",
+"j@	c #B9B698",
+"k@	c #958E81",
+"l@	c #65626C",
+"m@	c #D0D0A4",
+"n@	c #6E646B",
+"o@	c #A3A085",
+"p@	c #3B3241",
+"q@	c #0E0026",
+"r@	c #CCC9B1",
+"s@	c #AAA798",
+"t@	c #4D4157",
+"u@	c #423552",
+"v@	c #3F3450",
+"w@	c #8F8DA5",
+"x@	c #A6A6B1",
+"y@	c #292553",
+"z@	c #F7F7E2",
+"A@	c #2F2E5A",
+"B@	c #0E0C52",
+"C@	c #C1C0BC",
+"D@	c #6C6C83",
+"E@	c #494874",
+"F@	c #D6D6C2",
+"G@	c #101055",
+"H@	c #181758",
+"I@	c #E0DEBF",
+"J@	c #FFFFD5",
+"K@	c #FFFFD3",
+"L@	c #C7C6B5",
+"M@	c #100E60",
+"N@	c #D0D0BA",
+"O@	c #231D50",
+"P@	c #0E0E57",
+"Q@	c #353568",
+"R@	c #F7F7C4",
+"S@	c #151354",
+"T@	c #B3AD97",
+"U@	c #9F9F96",
+"V@	c #AFAF9E",
+"W@	c #BEBA9D",
+"X@	c #EFEFBA",
+"Y@	c #403A57",
+"Z@	c #746970",
+"`@	c #E1E1B0",
+" #	c #DDDDAC",
+".#	c #6C6B72",
+"+#	c #D1D1A4",
+"@#	c #A9A58C",
+"##	c #C5C599",
+"$#	c #83806C",
+"%#	c #C7C4B2",
+"&#	c #F3F3E4",
+"*#	c #E0DEE1",
+"=#	c #DDDBE0",
+"-#	c #8C8B99",
+";#	c #8C8BA9",
+">#	c #ABABB6",
+",#	c #26245D",
+"'#	c #F7F7EB",
+")#	c #31315F",
+"!#	c #0E0C53",
+"~#	c #BBBBBC",
+"{#	c #6F6F8B",
+"]#	c #464775",
+"^#	c #DADAC6",
+"/#	c #141265",
+"(#	c #45437D",
+"_#	c #FEFED5",
+":#	c #C8C8BE",
+"<#	c #141583",
+"[#	c #9393AF",
+"}#	c #FFFFCE",
+"|#	c #767079",
+"1#	c #131379",
+"2#	c #1E1E74",
+"3#	c #FAFAC6",
+"4#	c #333368",
+"5#	c #1F1C56",
+"6#	c #CDCAA7",
+"7#	c #7B7B85",
+"8#	c #B1B19F",
+"9#	c #EBEBB9",
+"0#	c #E5E6B5",
+"a#	c #F0F0BB",
+"b#	c #6F6E7E",
+"c#	c #958F85",
+"d#	c #E6E7B3",
+"e#	c #DBDCAB",
+"f#	c #6F6E74",
+"g#	c #D1D2A4",
+"h#	c #C8C79D",
+"i#	c #BFBF96",
+"j#	c #A2A27F",
+"k#	c #120528",
+"l#	c #C0BDB5",
+"m#	c #FFFFFB",
+"n#	c #FFFFFF",
+"o#	c #9F9FAB",
+"p#	c #8787A5",
+"q#	c #B0B0BD",
+"r#	c #21205C",
+"s#	c #F6F6F4",
+"t#	c #343467",
+"u#	c #0D0D54",
+"v#	c #B7B7BC",
+"w#	c #737397",
+"x#	c #474584",
+"y#	c #DDDDCA",
+"z#	c #161676",
+"A#	c #8080A3",
+"B#	c #F9F9D4",
+"C#	c #6F70A6",
+"D#	c #A8A8BC",
+"E#	c #C9C9C5",
+"F#	c #191AA2",
+"G#	c #5252AF",
+"H#	c #FEFECE",
+"I#	c #DDDBB5",
+"J#	c #242189",
+"K#	c #19199C",
+"L#	c #E4E4C1",
+"M#	c #575890",
+"N#	c #2D2866",
+"O#	c #E7E6B7",
+"P#	c #535374",
+"Q#	c #B4B4A6",
+"R#	c #EBEBBA",
+"S#	c #313162",
+"T#	c #CACAAB",
+"U#	c #8B8B8C",
+"V#	c #747381",
+"W#	c #D7D7AD",
+"X#	c #A9A894",
+"Y#	c #828281",
+"Z#	c #6C6C77",
+"`#	c #D3D3A5",
+" $	c #898473",
+".$	c #67656F",
+"+$	c #ACAC86",
+"@$	c #201430",
+"#$	c #0E0432",
+"$$	c #B7B6C0",
+"%$	c #9D9DAC",
+"&$	c #7D7CA0",
+"*$	c #B4B4C2",
+"=$	c #21215C",
+"-$	c #F6F6F8",
+";$	c #36366C",
+">$	c #100F64",
+",$	c #B6B5C3",
+"'$	c #76769C",
+")$	c #444387",
+"!$	c #E0E0CE",
+"~$	c #181882",
+"{$	c #AAABB9",
+"]$	c #BCBCC5",
+"^$	c #1A1A9F",
+"/$	c #5F5FB3",
+"($	c #CACAC8",
+"_$	c #1C1CB2",
+":$	c #2020B6",
+"<$	c #D3D4CA",
+"[$	c #FEFECC",
+"}$	c #66639D",
+"|$	c #C3C3BE",
+"1$	c #7A7AAB",
+"2$	c #403A73",
+"3$	c #F8F8C1",
+"4$	c #323270",
+"5$	c #B8B8AD",
+"6$	c #A8A89A",
+"7$	c #0E0E54",
+"8$	c #9A9A94",
+"9$	c #9D9D94",
+"0$	c #4B4B73",
+"a$	c #C5C6A5",
+"b$	c #5C5A74",
+"c$	c #0F0C53",
+"d$	c #6A6979",
+"e$	c #D2D3A4",
+"f$	c #392F3F",
+"g$	c #484561",
+"h$	c #A9A988",
+"i$	c #2B2037",
+"j$	c #0F0B4F",
+"k$	c #B2B1C5",
+"l$	c #D0D0D4",
+"m$	c #9191B0",
+"n$	c #8C8CB2",
+"o$	c #54548A",
+"p$	c #75759E",
+"q$	c #B7B7C6",
+"r$	c #21215D",
+"s$	c #F4F4F7",
+"t$	c #3A3976",
+"u$	c #12106B",
+"v$	c #B4B4C3",
+"w$	c #7979A1",
+"x$	c #41428F",
+"y$	c #E1E1D1",
+"z$	c #1A1A8A",
+"A$	c #C6C6C6",
+"B$	c #8383BE",
+"C$	c #1C1CB1",
+"D$	c #5F5FBE",
+"E$	c #CACACC",
+"F$	c #1E1EC1",
+"G$	c #1F1FC6",
+"H$	c #7373CD",
+"I$	c #B0AEAE",
+"J$	c #1E1FC1",
+"K$	c #A3A3C3",
+"L$	c #9B9BB8",
+"M$	c #5E5A88",
+"N$	c #F2F2C1",
+"O$	c #1D1E7F",
+"P$	c #BBBCB4",
+"Q$	c #727382",
+"R$	c #0D0D55",
+"S$	c #89888D",
+"T$	c #A5A598",
+"U$	c #45456E",
+"V$	c #C5C5A4",
+"W$	c #555472",
+"X$	c #0E0C54",
+"Y$	c #6D6C7B",
+"Z$	c #CACA9E",
+"`$	c #130628",
+" %	c #47455A",
+".%	c #A5A589",
+"+%	c #2F2439",
+"@%	c #110E60",
+"#%	c #ACACC7",
+"$%	c #A9A9B0",
+"%%	c #201F69",
+"&%	c #11116E",
+"*%	c #111270",
+"=%	c #7374A9",
+"-%	c #BABAC9",
+";%	c #212161",
+">%	c #F2F2F6",
+",%	c #3F3E7C",
+"'%	c #121171",
+")%	c #B1B1C4",
+"!%	c #7B7CA8",
+"~%	c #3D3D92",
+"{%	c #E4E4D3",
+"]%	c #1C1C96",
+"^%	c #D8D8CE",
+"/%	c #6363BD",
+"(%	c #1E1EBD",
+"_%	c #5F5FC8",
+":%	c #CDCDCE",
+"<%	c #2121CF",
+"[%	c #2222D7",
+"}%	c #2A29DB",
+"|%	c #E0E0CF",
+"1%	c #E2E2C1",
+"2%	c #2222D2",
+"3%	c #8485CD",
+"4%	c #BCBDC2",
+"5%	c #8282AE",
+"6%	c #D6D6BE",
+"7%	c #1A1B93",
+"8%	c #BFBFB9",
+"9%	c #6D6D85",
+"0%	c #0E0D55",
+"a%	c #87878F",
+"b%	c #A6A699",
+"c%	c #3F3F6B",
+"d%	c #C6C6A5",
+"e%	c #4E4F70",
+"f%	c #706F7C",
+"g%	c #C2C29C",
+"h%	c #0E0534",
+"i%	c #4A4759",
+"j%	c #A9A98A",
+"k%	c #2E2439",
+"l%	c #110F67",
+"m%	c #A4A4C5",
+"n%	c #AEADB5",
+"o%	c #21216C",
+"p%	c #111271",
+"q%	c #121273",
+"r%	c #6F70AA",
+"s%	c #C0BFCC",
+"t%	c #22216D",
+"u%	c #EFEFF4",
+"v%	c #434381",
+"w%	c #121375",
+"x%	c #AEAFC6",
+"y%	c #8080AD",
+"z%	c #3C3D96",
+"A%	c #E5E5D4",
+"B%	c #1E1E9F",
+"C%	c #E3E3D1",
+"D%	c #5151BD",
+"E%	c #1F1FC2",
+"F%	c #5E5ECD",
+"G%	c #CECED1",
+"H%	c #2322D9",
+"I%	c #2424E0",
+"J%	c #2424DF",
+"K%	c #8888D5",
+"L%	c #3333DE",
+"M%	c #6464D2",
+"N%	c #DFDFC8",
+"O%	c #A5A5C1",
+"P%	c #B3B4BD",
+"Q%	c #1D1EA4",
+"R%	c #C1C1BB",
+"S%	c #68688F",
+"T%	c #100F60",
+"U%	c #888890",
+"V%	c #A5A698",
+"W%	c #3A3A68",
+"X%	c #4D4D77",
+"Y%	c #11116B",
+"Z%	c #757581",
+"`%	c #BEBE9C",
+" &	c #4C4A60",
+".&	c #AFAF8E",
+"+&	c #2C2237",
+"@&	c #9E9DC3",
+"#&	c #B1B1B9",
+"$&	c #23246E",
+"%&	c #121274",
+"&&	c #6869A7",
+"*&	c #C4C3CF",
+"=&	c #201F6E",
+"-&	c #EBEBF2",
+";&	c #464685",
+">&	c #13137A",
+",&	c #AAAAC6",
+"'&	c #8585B1",
+")&	c #3B3B97",
+"!&	c #E7E7D6",
+"~&	c #1F1FA3",
+"{&	c #E7E7D3",
+"]&	c #4D4DC0",
+"^&	c #1F1FC5",
+"/&	c #5D5DD0",
+"(&	c #D0D0D1",
+"_&	c #2323DB",
+":&	c #2424E2",
+"<&	c #2424E3",
+"[&	c #4343DE",
+"}&	c #4343E2",
+"|&	c #4545D9",
+"1&	c #F9F9C6",
+"2&	c #D7D7B5",
+"3&	c #9293BF",
+"4&	c #1F20B2",
+"5&	c #C3C4BE",
+"6&	c #676792",
+"7&	c #12116D",
+"8&	c #868691",
+"9&	c #A3A397",
+"0&	c #363666",
+"a&	c #C7C8A5",
+"b&	c #4C4C83",
+"c&	c #111272",
+"d&	c #787884",
+"e&	c #BABA9B",
+"f&	c #11106A",
+"g&	c #4E4D6A",
+"h&	c #B4B491",
+"i&	c #291F35",
+"j&	c #12116F",
+"k&	c #9999C0",
+"l&	c #B5B5BC",
+"m&	c #262670",
+"n&	c #121376",
+"o&	c #121377",
+"p&	c #5E5FA3",
+"q&	c #BDBDD1",
+"r&	c #1F1F78",
+"s&	c #E8E8F0",
+"t&	c #494988",
+"u&	c #13147C",
+"v&	c #A4A4C7",
+"w&	c #8787B3",
+"x&	c #3A3A99",
+"y&	c #E8E8D7",
+"z&	c #201FA5",
+"A&	c #DFDFD3",
+"B&	c #5353BE",
+"C&	c #2020C9",
+"D&	c #5D5DD2",
+"E&	c #D2D2D2",
+"F&	c #2424DB",
+"G&	c #2727DE",
+"H&	c #2525E6",
+"I&	c #2829E7",
+"J&	c #F0F0CE",
+"K&	c #5252E2",
+"L&	c #2D2DE2",
+"M&	c #F8F8C8",
+"N&	c #F4F4BE",
+"O&	c #7172C3",
+"P&	c #2022BA",
+"Q&	c #C5C5BE",
+"R&	c #656595",
+"S&	c #131271",
+"T&	c #75748F",
+"U&	c #A0A095",
+"V&	c #34346A",
+"W&	c #C9CAA5",
+"X&	c #474883",
+"Y&	c #121374",
+"Z&	c #7C7C84",
+"`&	c #B4B49A",
+" *	c #515174",
+".*	c #B7B793",
+"+*	c #251A32",
+"@*	c #121271",
+"#*	c #9191BC",
+"$*	c #BBBBC1",
+"%*	c #272770",
+"&*	c #4B4B99",
+"**	c #8586C4",
+"=*	c #2C2C85",
+"-*	c #E5E5EE",
+";*	c #4E4E8A",
+">*	c #13147D",
+",*	c #A2A2C7",
+"'*	c #8A8AB5",
+")*	c #373798",
+"!*	c #E9E9D7",
+"~*	c #2020A7",
+"{*	c #D6D6D1",
+"]*	c #6E6CAF",
+"^*	c #2120CC",
+"/*	c #5E5DD4",
+"(*	c #D3D3D2",
+"_*	c #2929DC",
+":*	c #3332CB",
+"<*	c #2525EA",
+"[*	c #2727EC",
+"}*	c #5F5FE2",
+"|*	c #2526E9",
+"1*	c #E0E0CC",
+"2*	c #FEFFC6",
+"3*	c #4F50C9",
+"4*	c #2223BE",
+"5*	c #C7C7BF",
+"6*	c #646497",
+"7*	c #131172",
+"8*	c #444487",
+"9*	c #90909A",
+"0*	c #343477",
+"a*	c #CBCBA6",
+"b*	c #414281",
+"c*	c #7F7F86",
+"d*	c #ACAD98",
+"e*	c #121270",
+"f*	c #545378",
+"g*	c #B8B893",
+"h*	c #211631",
+"i*	c #8989B9",
+"j*	c #BFBFC5",
+"k*	c #282970",
+"l*	c #121272",
+"m*	c #2E2E85",
+"n*	c #6162AD",
+"o*	c #3C3C91",
+"p*	c #DCDCE9",
+"q*	c #65648D",
+"r*	c #15157E",
+"s*	c #9F9FC6",
+"t*	c #8C8CB7",
+"u*	c #363698",
+"v*	c #ECECD8",
+"w*	c #2121A9",
+"x*	c #C5C5CF",
+"y*	c #94929D",
+"z*	c #2727CC",
+"A*	c #5C5CD5",
+"B*	c #3636DE",
+"C*	c #5E5BA0",
+"D*	c #2626EB",
+"E*	c #312EDA",
+"F*	c #DDDDC8",
+"G*	c #5D5EE5",
+"H*	c #2526EC",
+"I*	c #C1C1D1",
+"J*	c #FCFDC6",
+"K*	c #3132CE",
+"L*	c #2223C1",
+"M*	c #C8C9BF",
+"N*	c #616195",
+"O*	c #131170",
+"P*	c #242376",
+"Q*	c #51518C",
+"R*	c #302F73",
+"S*	c #CDCDA7",
+"T*	c #414180",
+"U*	c #2B2B78",
+"V*	c #848489",
+"W*	c #A8A897",
+"X*	c #565679",
+"Y*	c #201847",
+"Z*	c #8484B6",
+"`*	c #C3C3C9",
+" =	c #2B2B70",
+".=	c #131270",
+"+=	c #1A1A7A",
+"@=	c #191979",
+"#=	c #23237D",
+"$=	c #BFBFDB",
+"%=	c #737194",
+"&=	c #2F2972",
+"*=	c #B3B2C8",
+"==	c #8E8EB9",
+"-=	c #323297",
+";=	c #EEEED8",
+">=	c #2222A9",
+",=	c #ACACCA",
+"'=	c #ADA89B",
+")=	c #5D578D",
+"!=	c #6A6ABE",
+"~=	c #D0D0C0",
+"{=	c #2A2888",
+"]=	c #A39E95",
+"^=	c #362F99",
+"/=	c #463C89",
+"(=	c #EEEEC7",
+"_=	c #5353E8",
+":=	c #2526ED",
+"<=	c #ACACD3",
+"[=	c #EAEAC9",
+"}=	c #2123D0",
+"|=	c #2324C1",
+"1=	c #CACBBF",
+"2=	c #474793",
+"3=	c #12106D",
+"4=	c #1E1D72",
+"5=	c #252472",
+"6=	c #2C2B6D",
+"7=	c #8B8A89",
+"8=	c #787683",
+"9=	c #8C8C8B",
+"0=	c #A4A495",
+"a=	c #59597B",
+"b=	c #B8B892",
+"c=	c #1E1C6A",
+"d=	c #7E7FB3",
+"e=	c #C8C8CE",
+"f=	c #2C2D6F",
+"g=	c #191877",
+"h=	c #1A1B7D",
+"i=	c #151578",
+"j=	c #24257E",
+"k=	c #7B7CB7",
+"l=	c #9993A3",
+"m=	c #534768",
+"n=	c #E4E3E6",
+"o=	c #9090B9",
+"p=	c #302F97",
+"q=	c #F0F0D9",
+"r=	c #2323A6",
+"s=	c #8787C4",
+"t=	c #D9D7BC",
+"u=	c #625C83",
+"v=	c #8080B2",
+"w=	c #D0D0BF",
+"x=	c #272578",
+"y=	c #C7C7C4",
+"z=	c #615464",
+"A=	c #7B7176",
+"B=	c #FDFDCC",
+"C=	c #3939E8",
+"D=	c #2627EA",
+"E=	c #9FA0D3",
+"F=	c #C9C9CC",
+"G=	c #2022CF",
+"H=	c #2A2BC6",
+"I=	c #B0B2CB",
+"J=	c #27288A",
+"K=	c #1F1D72",
+"L=	c #1A186C",
+"M=	c #27276A",
+"N=	c #C7C7A4",
+"O=	c #8A8379",
+"P=	c #847D78",
+"Q=	c #94938B",
+"R=	c #9E9E94",
+"S=	c #5C5C7D",
+"T=	c #B6B691",
+"U=	c #191871",
+"V=	c #7576AE",
+"W=	c #CECED3",
+"X=	c #2D2D6D",
+"Y=	c #12116E",
+"Z=	c #1C1D7D",
+"`=	c #181980",
+" -	c #16167A",
+".-	c #2C2D82",
+"+-	c #3E4090",
+"@-	c #CCC9D6",
+"#-	c #9C97AD",
+"$-	c #FDFDFC",
+"%-	c #9494BA",
+"&-	c #2B2B95",
+"*-	c #F2F2DA",
+"=-	c #2322A1",
+"--	c #5555BA",
+";-	c #F9F9D8",
+">-	c #8282C0",
+",-	c #7C7DBE",
+"'-	c #9798AC",
+")-	c #1A1979",
+"!-	c #474797",
+"~-	c #BFBEB9",
+"{-	c #ECEBC1",
+"]-	c #ECECCF",
+"^-	c #2627E5",
+"/-	c #2929E4",
+"(-	c #B2B2CF",
+"_-	c #A9A9CE",
+":-	c #2021CE",
+"<-	c #3132C8",
+"[-	c #7577CC",
+"}-	c #262782",
+"|-	c #1F1E73",
+"1-	c #1D1D6F",
+"2-	c #23236C",
+"3-	c #B3B39C",
+"4-	c #B8B595",
+"5-	c #B7B595",
+"6-	c #92918A",
+"7-	c #979792",
+"8-	c #5F5F7F",
+"9-	c #B4B490",
+"0-	c #171772",
+"a-	c #D2D2D7",
+"b-	c #2D2D6C",
+"c-	c #181972",
+"d-	c #1A1B80",
+"e-	c #171982",
+"f-	c #18187E",
+"g-	c #292A80",
+"h-	c #1F1F75",
+"i-	c #B5B5D6",
+"j-	c #E5E5ED",
+"k-	c #9696BB",
+"l-	c #292894",
+"m-	c #22229E",
+"n-	c #2322AD",
+"o-	c #A2A3C9",
+"p-	c #2C2DA4",
+"q-	c #1B1C97",
+"r-	c #161789",
+"s-	c #14147D",
+"t-	c #5D5D9D",
+"u-	c #F8F8CD",
+"v-	c #B7B7D4",
+"w-	c #2324E0",
+"x-	c #3030DD",
+"y-	c #CCCCCB",
+"z-	c #8788D0",
+"A-	c #1F21CB",
+"B-	c #2829BD",
+"C-	c #3B3DB0",
+"D-	c #212179",
+"E-	c #212075",
+"F-	c #1D1C71",
+"G-	c #24256F",
+"H-	c #7E7E89",
+"I-	c #DADAA9",
+"J-	c #CECFA3",
+"K-	c #8E8E8A",
+"L-	c #939390",
+"M-	c #5F5E80",
+"N-	c #B1B28F",
+"O-	c #151572",
+"P-	c #6767A4",
+"Q-	c #CFCFD7",
+"R-	c #1E1E6D",
+"S-	c #1E1E79",
+"T-	c #191B82",
+"U-	c #161885",
+"V-	c #151682",
+"W-	c #151577",
+"X-	c #11116A",
+"Y-	c #6A6BA7",
+"Z-	c #E6E6F0",
+"`-	c #9797C3",
+" ;	c #9090BB",
+".;	c #272692",
+"+;	c #1E1E9A",
+"@;	c #1A1AA3",
+"#;	c #2223A3",
+"$;	c #1A1BA9",
+"%;	c #1A1BAB",
+"&;	c #181899",
+"*;	c #16178F",
+"=;	c #151686",
+"-;	c #191A7B",
+";;	c #C1C2BB",
+">;	c #5B5CD0",
+",;	c #2223D9",
+"';	c #393AD7",
+");	c #E5E6CA",
+"!;	c #6364D0",
+"~;	c #1F20C6",
+"{;	c #1C1DAF",
+"];	c #222399",
+"^;	c #29297F",
+"/;	c #141270",
+"(;	c #202077",
+"_;	c #1D1E73",
+":;	c #232471",
+"<;	c #30316E",
+"[;	c #C9C9A3",
+"};	c #B0B099",
+"|;	c #6C6B83",
+"1;	c #8C8C8E",
+"2;	c #121275",
+"3;	c #3F3F7D",
+"4;	c #A9A98D",
+"5;	c #131373",
+"6;	c #131274",
+"7;	c #26257D",
+"8;	c #424188",
+"9;	c #212275",
+"0;	c #232481",
+"a;	c #1A1C85",
+"b;	c #141687",
+"c;	c #141686",
+"d;	c #14147E",
+"e;	c #2D2E7F",
+"f;	c #525298",
+"g;	c #31318C",
+"h;	c #343492",
+"i;	c #1A1A8D",
+"j;	c #4D4DA0",
+"k;	c #191995",
+"l;	c #1C1DAD",
+"m;	c #1C1DB5",
+"n;	c #1D1EBD",
+"o;	c #1B1CB0",
+"p;	c #18199B",
+"q;	c #16178E",
+"r;	c #383993",
+"s;	c #1F21BF",
+"t;	c #2021CB",
+"u;	c #4849D1",
+"v;	c #F8F8C9",
+"w;	c #4142CB",
+"x;	c #1E1FC0",
+"y;	c #1A1CAB",
+"z;	c #272891",
+"A;	c #272679",
+"B;	c #181875",
+"C;	c #191975",
+"D;	c #1F2075",
+"E;	c #19196C",
+"F;	c #161563",
+"G;	c #5A5A7B",
+"H;	c #313073",
+"I;	c #242372",
+"J;	c #313179",
+"K;	c #131276",
+"L;	c #1A1B79",
+"M;	c #3B3C7D",
+"N;	c #131273",
+"O;	c #131171",
+"P;	c #161670",
+"Q;	c #2C2D80",
+"R;	c #1E1F83",
+"S;	c #181A87",
+"T;	c #15178B",
+"U;	c #15178C",
+"V;	c #242576",
+"W;	c #131375",
+"X;	c #151584",
+"Y;	c #16168A",
+"Z;	c #16168E",
+"`;	c #171791",
+" >	c #171895",
+".>	c #1D1FBB",
+"+>	c #1E1FC3",
+"@>	c #2021CC",
+"#>	c #151688",
+"$>	c #16177D",
+"%>	c #1A1CAA",
+"&>	c #1C1EB8",
+"*>	c #6263C9",
+"=>	c #F5F5C9",
+"->	c #2527C2",
+";>	c #1D1EBB",
+">>	c #201F7D",
+",>	c #24247B",
+"'>	c #191978",
+")>	c #1D1E76",
+"!>	c #14146C",
+"~>	c #111163",
+"{>	c #202069",
+"]>	c #111069",
+"^>	c #141477",
+"/>	c #141475",
+"(>	c #121170",
+"_>	c #1C1C73",
+":>	c #1F207D",
+"<>	c #151689",
+"[>	c #15178D",
+"}>	c #161790",
+"|>	c #141582",
+"1>	c #16168C",
+"2>	c #16178D",
+"3>	c #191A9C",
+"4>	c #1F20C4",
+"5>	c #2122D3",
+"6>	c #19199B",
+"7>	c #16168D",
+"8>	c #14147B",
+"9>	c #161890",
+"0>	c #191BA5",
+"a>	c #8585C6",
+"b>	c #D9DAC7",
+"c>	c #1D1EB9",
+"d>	c #1D1EAF",
+"e>	c #15137A",
+"f>	c #1A1977",
+"g>	c #17167A",
+"h>	c #131377",
+"i>	c #181975",
+"j>	c #191A71",
+"k>	c #1A1B6B",
+"l>	c #21216A",
+"m>	c #111168",
+"n>	c #141476",
+"o>	c #161576",
+"p>	c #151571",
+"q>	c #14137C",
+"r>	c #161791",
+"s>	c #161892",
+"t>	c #161893",
+"u>	c #15178F",
+"v>	c #17177F",
+"w>	c #131378",
+"x>	c #141580",
+"y>	c #151587",
+"z>	c #15168A",
+"A>	c #1B1DA7",
+"B>	c #2324DE",
+"C>	c #2223DB",
+"D>	c #1C1DB4",
+"E>	c #19199E",
+"F>	c #141480",
+"G>	c #18198F",
+"H>	c #A7A7C8",
+"I>	c #B7B7C1",
+"J>	c #24249F",
+"K>	c #262685",
+"L>	c #1B1B7B",
+"M>	c #14137B",
+"N>	c #13137B",
+"O>	c #141574",
+"P>	c #1A1B73",
+"Q>	c #1C1D6E",
+"R>	c #1F206B",
+"S>	c #171769",
+"T>	c #121069",
+"U>	c #141375",
+"V>	c #1A1B78",
+"W>	c #171777",
+"X>	c #141481",
+"Y>	c #171999",
+"Z>	c #171897",
+"`>	c #171894",
+" ,	c #161891",
+".,	c #171880",
+"+,	c #171885",
+"@,	c #151687",
+"#,	c #1D1FB1",
+"$,	c #2123D6",
+"%,	c #2324E1",
+"&,	c #2324DD",
+"*,	c #1D1DB7",
+"=,	c #1A19A0",
+"-,	c #171794",
+";,	c #151585",
+">,	c #1C1C82",
+",,	c #7272AE",
+"',	c #494996",
+"),	c #1A197C",
+"!,	c #16157C",
+"~,	c #15147E",
+"{,	c #14147F",
+"],	c #13147E",
+"^,	c #121479",
+"/,	c #151677",
+"(,	c #191B75",
+"_,	c #1C1D71",
+":,	c #1E1F6C",
+"<,	c #1A1A78",
+"[,	c #191977",
+"},	c #131275",
+"|,	c #18199D",
+"1,	c #181A9F",
+"2,	c #17199A",
+"3,	c #171998",
+"4,	c #171997",
+"5,	c #161895",
+"6,	c #16178C",
+"7,	c #171786",
+"8,	c #191983",
+"9,	c #2223A9",
+"0,	c #2425D4",
+"a,	c #2324DF",
+"b,	c #2121D0",
+"c,	c #1D1EBA",
+"d,	c #1A1A97",
+"e,	c #181889",
+"f,	c #1F1F7D",
+"g,	c #191779",
+"h,	c #1B1A7F",
+"i,	c #161680",
+"j,	c #131581",
+"k,	c #13157F",
+"l,	c #141679",
+"m,	c #161775",
+"n,	c #191B72",
+"o,	c #20216E",
+"p,	c #19196E",
+"q,	c #131272",
+"r,	c #16168B",
+"s,	c #181898",
+"t,	c #181AA0",
+"u,	c #191BA4",
+"v,	c #18199C",
+"w,	c #161685",
+"x,	c #1C1B85",
+"y,	c #1F1F8B",
+"z,	c #1C1C99",
+"A,	c #1F20A8",
+"B,	c #2222AA",
+"C,	c #1C1C8E",
+"D,	c #1F1F87",
+"E,	c #1C1B81",
+"F,	c #1C1B84",
+"G,	c #171782",
+"H,	c #141688",
+"I,	c #141685",
+"J,	c #13147A",
+"K,	c #161772",
+"L,	c #15166C",
+"M,	c #18186B",
+"N,	c #18186D",
+"O,	c #181977",
+"P,	c #1C1C79",
+"Q,	c #191BA7",
+"R,	c #181A9E",
+"S,	c #15178E",
+"T,	c #17188D",
+"U,	c #191B8E",
+"V,	c #16178B",
+"W,	c #17188C",
+"X,	c #16188C",
+"Y,	c #15168B",
+"Z,	c #141584",
+"`,	c #131580",
+" '	c #151673",
+".'	c #17196F",
+"+'	c #15156B",
+"@'	c #12116B",
+"#'	c #151575",
+"$'	c #181877",
+"%'	c #1D1D7A",
+"&'	c #171792",
+"*'	c #191AA0",
+"='	c #1A1BA7",
+"-'	c #1A1CAD",
+";'	c #1A1CAC",
+">'	c #191AA1",
+",'	c #181AA1",
+"''	c #181A9D",
+")'	c #17199B",
+"!'	c #161996",
+"~'	c #141585",
+"{'	c #131374",
+"]'	c #171871",
+"^'	c #18196E",
+"/'	c #17176E",
+"('	c #141370",
+"_'	c #141373",
+":'	c #181878",
+"<'	c #1D1E7A",
+"['	c #141482",
+"}'	c #171793",
+"|'	c #1B1CAE",
+"1'	c #1B1DB0",
+"2'	c #1B1CAD",
+"3'	c #1A1BA8",
+"4'	c #191AA5",
+"5'	c #191AA3",
+"6'	c #171996",
+"7'	c #171896",
+"8'	c #13147F",
+"9'	c #13147B",
+"0'	c #171970",
+"a'	c #181970",
+"b'	c #181873",
+"c'	c #171775",
+"d'	c #161677",
+"e'	c #171778",
+"f'	c #151583",
+"g'	c #1B1DB1",
+"h'	c #1B1DB2",
+"i'	c #1B1DB3",
+"j'	c #1C1DB3",
+"k'	c #191BA6",
+"l'	c #191AA4",
+"m'	c #18199A",
+"n'	c #171898",
+"o'	c #171874",
+"p'	c #171776",
+"q'	c #171677",
+"r'	c #1E1E7A",
+"s'	c #1B1DB4",
+"t'	c #1B1CAF",
+"u'	c #1A1BAA",
+"v'	c #18199E",
+"w'	c #181999",
+"x'	c #171893",
+"y'	c #141581",
+"z'	c #121379",
+"A'	c #151573",
+"B'	c #181A74",
+"C'	c #171875",
+"D'	c #171678",
+". . + + + + + + + + + + + + + + + + + + + + + + + + + + + + @ + # + + $ + + + + + + + + + + . . ",
+". . . . . . . . + + + + + + + + + + + + + + + + + + + + + + + + % + + & + + + + . . . . . . . . ",
+"* * * * . . . . . . . . . . . = . . + + + + + + + + + + + + . . - . . . . . . . . . . * * * * * ",
+"; ; ; ; * * * * * * * * * * . > . . . . . . . . . . . . . . . . . * , * * * * * * * ' * ; ; ; ; ",
+"; ; ; ; ; ; ; ; ; ; ; ) * * * ! * * * * * * ~ { * * * * * * * * * * ] * ; ; ; ; ^ ; / ; ; ; ; ; ",
+"; ; ( _ ; ; ; : ; ; ; < ! ; ; ; ; ; ; ; ; ; , [ ; ; ; ; ; ; ; ; ; ; } ; ; ; ; ; | ; 1 ; 2 ; ; ; ",
+"3 3 4 5 3 ; ; 6 ; ; ; 7 2 ; ; ; ; ; ; ; ; ; ( ! ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ^ ; ; 3 8 3 3 3 ",
+"3 3 9 0 3 3 3 3 3 3 3 3 3 3 3 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 3 3 3 3 3 3 3 3 3 3 3 3 a 3 3 3 ",
+"3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 b 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 ",
+"c d e f g h i j k 3 3 3 3 3 3 3 3 3 3 3 l m 3 3 n o p 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 q r c c c c ",
+"s t u v w x y z A B c c c c c C c c c c D E c F G H I c c c 0 J c c c c c B B B B B K L M B N B ",
+"O P Q R S T U V W B B B B B B X Y B B B Z ` B  ...+.@.#.B B $.%.B B B B B B B B B B &.*.=.B -.;.",
+">.,.'.).!.~.{.].W B B B B B ^./.(.B B B _.:.B <.[.+.}.q B B B |.B B B B B B B B B B 1.2.3.4.5.6.",
+"7.8.9.0.a.b.c.d.e.4.4.f.g.4.h.i.W 4.4.4.j.k.l.m.n.o.p.q.4.4.4.4.4.4.4.4.4.4.4.4.4.4.r.s.t.4.u.4.",
+"v.8.w.x.y.z.A.B.C.4.4.D.E.4.F.G.H.l.4.4.I.k.>.J.K.L.M.N.4.4.4.4.4.4.4.4.4.4.O.P.l.4.Q.R.S.4.T.U.",
+"V.W.X.Y.U.Z.`. +.+U.U.H.U.4.++@+4.#+$+4.%+&+*+=+q.4.-+;+4.4.4.4.4.4.4.U.U.U.>+,+'+U.)+!+~+U.{+U.",
+"]+^+/+(+U.U._+:+<+U.U.U.U.U.v.[+U.N.V.U.%+}+|+1+V.U.2+3+U.U.U.U.U.U.U.U.U.U.l.4+5+U.6+7+8+9+0+U.",
+"a+b+c+d+e+U.f+g+h+i+j+U.]+j+U.U.U.U.U.k+l+}+|+m+n+U.o+p+j+U.U.q+j+q+]+>.U.U.r+s+t+i+u+v+w+i+x+y+",
+"z+A+B+C+y+y+D+E+F+G+H+y+I+J+j+K+L+M+N+O+P+Q+R+=+S+T+U+V+W+y+y+X+Y+Z+`+ @.@y++@@@#@$@%@&@*@=@y+y+",
+"y+-@;@>@,@,@'@)@!@~@{@]@^@/@(@_@:@<@[@}@|@1@2@3@4@5@6@7@8@9@0@a@b@c@d@e@f@g@h@i@j@k@l@m@n@o@p@y+",
+"q@r@s@t@u@v@w@x@y@z@A@B@C@D@E@F@G@H@I@J@K@L@M@N@m.O@P@Q@R@H@S@T@U@V@W@'.X@Y@Z@`@,. #.#+#@###$#q@",
+"q@%#&#*#=#-#;#>#,#'#)#!#~#{#]#^#/#(#_#J@K@:#<#[#}#|#1#2#3#4#5#6#7#8#9#0#a#b#c#d#P e#f#g#h#i#j#k#",
+"q@l#m#n#n#o#p#q#r#s#t#u#v#w#x#y#z#A#B#C#D#E#F#G#H#I#J#K#L#M#N#O#P#Q#R#S#T#U#V#W#X#Y#Z#`# $.$+$@$",
+"#$$$n#n#n#%$&$*$=$-$;$>$,$'$)$!$~${$]$^$/$($_$:$<$[$}$_$|$1$2$3$4$5$6$7$8$9$0$a$b$c$d$e$f$g$h$i$",
+"j$k$l$m$n$o$p$q$r$s$t$u$v$w$x$y$z$A$B$C$D$E$F$G$H$[.I$J$K$L$M$N$O$P$Q$R$S$T$U$V$W$X$Y$Z$`$ %.%+%",
+"@%#%$%%%&%*%=%-%;%>%,%'%)%!%~%{%]%^%/%(%_%:%<%[%}%|%1%2%3%4%5%6%7%8%9%0%a%b%c%d%e%0%f%g%h%i%j%k%",
+"l%m%n%o%p%q%r%s%t%u%v%w%x%y%z%A%B%C%D%E%F%G%H%I%J%K%[$L%M%N%O%P%Q%R%S%T%U%V%W%d%X%Y%Z%`%M@ &.&+&",
+"u$@&#&$&%&w%&&*&=&-&;&>&,&'&)&!&~&{&]&^&/&(&_&:&<&[&m+}&|&1&2&3&4&5&6&7&8&9&0&a&b&c&d&e&f&g&h&i&",
+"j&k&l&m&n&o&p&q&r&s&t&u&v&w&x&y&z&A&B&C&D&E&F&G&H&I&J&K&L&M&N&O&P&Q&R&S&T&U&V&W&X&Y&Z&`&7& *.*+*",
+"@*#*$*%*o&n&&***=*-*;*>*,*'*)*!*~*{*]*^*/*(*_*:*<*[*!$}*|*1*2*3*4*5*6*7*8*9*0*a*b*w%c*d*e*f*g*h*",
+"q%i*j*k*n&l*m*n*o*p*q*r*s*t*u*v*w*x*y*z*A*(*B*C*D*E*F*G*H*I*J*K*L*M*N*O*P*Q*R*S*T*U*V*W*l*X*g*Y*",
+"%&Z*`* =w%.=+=@=#=$=%=&=*===-=;=>=,='=)=!=~={=]=^=/=(=_=:=<=[=}=|=1=2=3=4=5=6=a*7=8=9=0=q%a=b=c=",
+"w%d=e=f='%g=h=i=j=k=l=m=n=o=p=q=r=s=t=u=v=w=x=y=z=A=B=C=D=E=F=G=H=I=J=j&K=L=M=N=O=P=Q=R=%&S=T=U=",
+"w%V=W=X=Y=Z=`= -.-+-@-#-$-%-&-*-=---;->-,-'-)-!-~-{-]-^-/-(-_-:-<-[-}-3=|-1-2-3-4-5-6-7-%&8-9-0-",
+"w%r%a-b-c-d-e-f-g-h-i-n#j-k-l-*-m-n-o-p-q-r-<#s-t-u-v-w-x-y-z-A-B-C-D-3=E-F-G-H-I-J-K-L-%&M-N-O-",
+"w%P-Q-R-S-T-U-V-W-X-Y-Z-`- ;.;;=+;@;#;$;%;&;*;=;-;;;>;,;';);!;~;{;];^;/;(;_;:;<;[;};|;1;2;3;4;5;",
+"6;7;8;9;0;a;b;c;d;&%e;f;g;h;i;j;k;&;l;m;n;o;p;q;V-r;s;t;u;v;w;x;y;z;A;B;C;D;E;F;G;H;I;J;K;L;M;%&",
+"N;O;P;Q;R;S;T;U;c;1#V;W;s-X;Y;Z;`; >.>+>@>x;$; >#>$>%>&>*>=>->;>F#>>,>'>6;)>!>~>{>]>3=l*6;^>L;/>",
+"7*(>_>:>X;<>[>}>[>b;+=5;>&|><>1>2>3>4>5>[%~;C$6>7>8>9>0>a>b>c>d>e>f>g>h>2;i>j>k>l>m>u$(>6;n>L;o>",
+"O;e*p>q>1>r>}>s>t>u><>v>w>x>y>z><>A>@>B>C>C&D>E>`;F>>*G>H>I>J>K>L>M>N>>&o&O>P>Q>R>S>T>(>N;U>V>W>",
+"O;@*q%X>`;Y>Z>`> > > ,[>|>.,+,c;@,#,$,%,&,@>*,=,-,;,h>>,,,',),!,~,{,],u&^,/,(,_,:,:,T>j&N;U><,[,",
+"l*l*},y> >|,1,2,3,Y>4,5, ,6,7,F>8,9,0,a,B>b,c,@;d,e,f,g,h,i,X>|><#|>j,k,u&l,m,n,Q>o,p,j&q,U>'>V>",
+"q%l*1#r,s,t,u,F#v,p;v,2,4,5,u>[>w,x,y,z,A,B,s,C,D,E,F,G,;,=;b;H,b;c;I,|>],J,w%K,L,M,N,Y=7*/>O,P,",
+"%&q%d;}>v,u,Q,$;0>1,R,R,v,v,Y>4,5,s>}>S,T,U,z>V,W,X,U;Y,U;T;U;T;z><>b;Z,`,u&o& '.'+'@'j&N;#'$'%'",
+"2;q%F>&'*'='%>-';'0>>'F#,','t,'')'3,!'5,t>s>s> ,s>s>s>s>s> ,}>q;[>T;<>~'|>],1#{']'^'/'('_'z#:'<'",
+"w%N;['}'>'y;|'o;1'2'$;3'4'5'F#1,1,v,p;2,Y>3,3,4,4,6'4,7'7' >`>r>*;2>z>@,<#8'9'n& '0'a'b'c'd'e'<'",
+"},},f'}'>';'g'h'i'j'1'2'y;k'l'F#F#t,*'1,R,R,''v,v,m'p;Y>3,n'7'`>r>q;Y,#>Z,x>u&o&5;c-c-o'p'q'e'r'",
+"6;K;X;}'>';'i's'm;&>D>|'t'u'0>u,0>l'4'l'5'5'>','1,R,v'v,m'w'Z> >x'}>6,<>;,y'>*z'w%A'B'C'p'q'D'%'"};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_backend.c	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,174 @@
+/*
+*
+* 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_backend.h"
+
+
+gboolean i_str_has_pref_and_suff( const gchar *str , gchar *pref , gchar *suff )
+{
+  if ( (g_str_has_prefix( str , pref )) &&
+       (g_str_has_suffix( str , suff )) )
+    return TRUE;
+  else
+    return FALSE;
+}
+
+GSList * i_backend_list_lookup( void )
+{
+  GDir * backend_directory;
+  GSList * backend_list = NULL;
+
+  backend_directory = g_dir_open( AMIDIPLUGDATADIR , 0 , NULL );
+  if ( backend_directory != NULL )
+  {
+    const gchar * backend_directory_entry = g_dir_read_name( backend_directory );
+    while ( backend_directory_entry != NULL )
+    {
+      /* simple filename checking */
+      if ( i_str_has_pref_and_suff( backend_directory_entry , "ap-" , ".so" ) == TRUE )
+      {
+        GModule * module;
+        gchar * (*getapmoduleinfo)( gchar ** , gchar ** , gchar ** , gint * );
+        gchar * module_pathfilename = g_strjoin( "" , AMIDIPLUGDATADIR , "/" ,
+                                                 backend_directory_entry , NULL );
+        /* seems to be a backend for amidi-plug , try to load it */
+        module = g_module_open( module_pathfilename , 0 );
+        if ( module == NULL )
+          g_warning( "Error loading module %s - %s\n" , module_pathfilename , g_module_error() );
+        else
+        {
+          /* try to get the module name */
+          if ( g_module_symbol( module , "backend_info_get" , (gpointer*)&getapmoduleinfo ) )
+          {
+            /* module name found, ok! add its name and filename to the list */
+            amidiplug_sequencer_backend_name_t * mn = g_malloc(sizeof(amidiplug_sequencer_backend_name_t));
+            /* name and desc dinamically allocated */
+            getapmoduleinfo( &mn->name , &mn->longname , &mn->desc , &mn->ppos );
+            mn->filename = g_strdup(module_pathfilename); /* dinamically allocated */
+            DEBUGMSG( "Backend found and added in list, filename: %s and lname: %s\n" ,
+                      mn->filename, mn->longname );
+            backend_list = g_slist_append( backend_list , mn );
+          }
+          else
+          {
+            /* module name not found, this is not a backend for amidi-plug */
+            g_warning( "File %s is not a backend for amidi-plug!\n" , module_pathfilename );
+          }
+          g_module_close( module );
+        }
+      }
+      backend_directory_entry = g_dir_read_name( backend_directory );
+    }
+    g_dir_close( backend_directory );
+  }
+  else
+    g_warning( "Unable to open the backend directory %s\n" , AMIDIPLUGDATADIR );
+
+  return backend_list;
+}
+
+
+void i_backend_list_free( GSList * backend_list )
+{
+  while ( backend_list != NULL )
+  {
+    amidiplug_sequencer_backend_name_t * mn = backend_list->data;
+    g_free( mn->desc );
+    g_free( mn->name );
+    g_free( mn->longname );
+    g_free( mn->filename );
+    g_free( mn );
+    backend_list = backend_list->next;
+  }
+  return;
+}
+
+
+gint i_backend_load( gchar * module_name )
+{
+  gchar * module_pathfilename = g_strjoin( "" , AMIDIPLUGDATADIR , "/ap-" , module_name , ".so" , NULL );
+  DEBUGMSG( "loading backend '%s'\n" , module_pathfilename );
+  backend.gmodule = g_module_open( module_pathfilename , 0 );
+
+  if ( backend.gmodule != NULL )
+  {
+    gchar * (*getapmoduleinfo)( gchar ** , gchar ** , gchar ** , gint * );
+    gboolean (*checkautonomousaudio)( void );
+    g_module_symbol( backend.gmodule , "backend_init" , (gpointer *)&backend.init );
+    g_module_symbol( backend.gmodule , "backend_cleanup" , (gpointer *)&backend.cleanup );
+    g_module_symbol( backend.gmodule , "audio_info_get" , (gpointer*)&backend.audio_info_get );
+    g_module_symbol( backend.gmodule , "audio_volume_get" , (gpointer *)&backend.audio_volume_get );
+    g_module_symbol( backend.gmodule , "audio_volume_set" , (gpointer *)&backend.audio_volume_set );
+    g_module_symbol( backend.gmodule , "sequencer_start" , (gpointer *)&backend.seq_start );
+    g_module_symbol( backend.gmodule , "sequencer_stop" , (gpointer *)&backend.seq_stop );
+    g_module_symbol( backend.gmodule , "sequencer_on" , (gpointer *)&backend.seq_on );
+    g_module_symbol( backend.gmodule , "sequencer_off" , (gpointer *)&backend.seq_off );
+    g_module_symbol( backend.gmodule , "sequencer_queue_tempo" , (gpointer *)&backend.seq_queue_tempo );
+    g_module_symbol( backend.gmodule , "sequencer_queue_start" , (gpointer *)&backend.seq_queue_start );
+    g_module_symbol( backend.gmodule , "sequencer_event_init" , (gpointer *)&backend.seq_event_init );
+    g_module_symbol( backend.gmodule , "sequencer_event_noteon" , (gpointer *)&backend.seq_event_noteon );
+    g_module_symbol( backend.gmodule , "sequencer_event_noteoff" , (gpointer *)&backend.seq_event_noteoff );
+    g_module_symbol( backend.gmodule , "sequencer_event_keypress" , (gpointer *)&backend.seq_event_keypress );
+    g_module_symbol( backend.gmodule , "sequencer_event_controller" , (gpointer *)&backend.seq_event_controller );
+    g_module_symbol( backend.gmodule , "sequencer_event_pgmchange" , (gpointer *)&backend.seq_event_pgmchange );
+    g_module_symbol( backend.gmodule , "sequencer_event_chanpress" , (gpointer *)&backend.seq_event_chanpress );
+    g_module_symbol( backend.gmodule , "sequencer_event_pitchbend" , (gpointer *)&backend.seq_event_pitchbend );
+    g_module_symbol( backend.gmodule , "sequencer_event_sysex" , (gpointer *)&backend.seq_event_sysex );
+    g_module_symbol( backend.gmodule , "sequencer_event_tempo" , (gpointer *)&backend.seq_event_tempo );
+    g_module_symbol( backend.gmodule , "sequencer_event_other" , (gpointer *)&backend.seq_event_other );
+    g_module_symbol( backend.gmodule , "sequencer_output" , (gpointer *)&backend.seq_output );
+    g_module_symbol( backend.gmodule , "sequencer_output_shut" , (gpointer *)&backend.seq_output_shut );
+    g_module_symbol( backend.gmodule , "sequencer_get_port_count" , (gpointer *)&backend.seq_get_port_count );
+    g_module_symbol( backend.gmodule , "backend_info_get" , (gpointer*)&getapmoduleinfo );
+    g_module_symbol( backend.gmodule , "audio_check_autonomous" , (gpointer*)&checkautonomousaudio );
+    getapmoduleinfo( &backend.name , NULL , NULL , NULL );
+    backend.autonomous_audio = checkautonomousaudio();
+    DEBUGMSG( "backend %s (name '%s') successfully loaded\n" , module_pathfilename , backend.name );
+    backend.init();
+    g_free( module_pathfilename );
+    return 1;
+  }
+  else
+  {
+    g_warning( "unable to load backend '%s'\n" , module_pathfilename );
+    g_free( module_pathfilename );
+    return 0;
+  }
+}
+
+
+gint i_backend_unload( void )
+{
+  if ( backend.gmodule != NULL )
+  {
+    DEBUGMSG( "unloading backend '%s'\n" , backend.name );
+    backend.cleanup();
+    g_module_close( backend.gmodule );
+    DEBUGMSG( "backend '%s' unloaded\n" , backend.name );
+    g_free( backend.name );
+    backend.gmodule = NULL;
+    return 1;
+  }
+  else
+  {
+    g_warning( "attempting to unload backend, but no backend is loaded\n" );
+    return 0;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_backend.h	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,82 @@
+/*
+*
+* 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_BACKEND_H
+#define _I_BACKEND_H 1
+
+#include <gmodule.h>
+#include "i_midievent.h"
+#include "i_common.h"
+
+
+typedef struct
+{
+  gchar * desc;
+  gchar * filename;
+  gchar * longname;
+  gchar * name;
+  gint ppos;
+}
+amidiplug_sequencer_backend_name_t;
+
+
+typedef struct
+{
+  gint id;
+  GModule * gmodule;
+  gchar * name;
+  gint (*init)( void );
+  gint (*cleanup)( void );
+  gint (*audio_info_get)( gint * , gint * , gint * );
+  gint (*audio_volume_get)( gint * , gint * );
+  gint (*audio_volume_set)( gint , gint );
+  gint (*seq_start)( gchar * );
+  gint (*seq_stop)( void );
+  gint (*seq_on)( void );
+  gint (*seq_off)( void );
+  gint (*seq_queue_tempo)( gint , gint );
+  gint (*seq_queue_start)( void );
+  gint (*seq_event_init)( void );
+  gint (*seq_event_noteon)( midievent_t * );
+  gint (*seq_event_noteoff)( midievent_t * );
+  gint (*seq_event_keypress)( midievent_t * );
+  gint (*seq_event_controller)( midievent_t * );
+  gint (*seq_event_pgmchange)( midievent_t * );
+  gint (*seq_event_chanpress)( midievent_t * );
+  gint (*seq_event_pitchbend)( midievent_t * );
+  gint (*seq_event_sysex)( midievent_t * );
+  gint (*seq_event_tempo)( midievent_t * );
+  gint (*seq_event_other)( midievent_t * );
+  gint (*seq_output)( gpointer * , gint * );
+  gint (*seq_output_shut)( guint , gint );
+  gint (*seq_get_port_count)( void );
+  gboolean autonomous_audio;
+}
+amidiplug_sequencer_backend_t;
+
+extern amidiplug_sequencer_backend_t backend;
+
+
+GSList * i_backend_list_lookup( void );
+void i_backend_list_free( GSList * );
+gint i_backend_load( gchar * );
+gint i_backend_unload( void );
+
+#endif /* !_I_BACKEND_H */
--- a/Plugins/Input/amidi-plug/i_common.h	Mon Jul 10 04:42:53 2006 -0700
+++ b/Plugins/Input/amidi-plug/i_common.h	Mon Jul 10 04:52:51 2006 -0700
@@ -21,7 +21,6 @@
 #ifndef _I_COMMON_H
 #define _I_COMMON_H 1
 
-
 #include "config.h"
 #include <stdio.h>
 #include <stdlib.h>
@@ -44,10 +43,14 @@
 #endif /* DEBUG */
 
 
-#define AMIDIPLUG_VERSION "0.2+"
+#define AMIDIPLUG_VERSION "0.5"
 #define PLAYER_NAME "Audacious"
+#define PLAYER_LOCALRCDIR ".audacious"
 #define G_PATH_GET_BASENAME(x) g_path_get_basename(x)
 #define G_STRING_PRINTF(...) g_string_printf(__VA_ARGS__)
+#define G_USLEEP(x) g_usleep(x)
+#define G_VFPRINTF(x,y,z) g_vfprintf(x,y,z)
+
 
 /* multi-purpose data bucket */
 typedef struct
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_configure-alsa.c	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,555 @@
+/*
+*
+* 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-alsa.h"
+#include "backend-alsa/b-alsa-config.h"
+#include "backend-alsa/backend-alsa-icon.xpm"
+
+
+enum
+{
+  LISTPORT_TOGGLE_COLUMN = 0,
+  LISTPORT_PORTNUM_COLUMN,
+  LISTPORT_CLIENTNAME_COLUMN,
+  LISTPORT_PORTNAME_COLUMN,
+  LISTPORT_POINTER_COLUMN,
+  LISTPORT_N_COLUMNS
+};
+
+enum
+{
+  LISTCARD_NAME_COLUMN = 0,
+  LISTCARD_ID_COLUMN,
+  LISTCARD_MIXERPTR_COLUMN,
+  LISTCARD_N_COLUMNS
+};
+
+enum
+{
+  LISTMIXER_NAME_COLUMN = 0,
+  LISTMIXER_ID_COLUMN,
+  LISTMIXER_N_COLUMNS
+};
+
+
+void i_configure_ev_portlv_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);
+}
+
+
+gboolean i_configure_ev_mixctlcmb_inspect( GtkTreeModel * store , GtkTreePath * path,
+                                           GtkTreeIter * iter , gpointer mixctl_cmb )
+{
+  gint ctl_id;
+  gchar * ctl_name;
+  amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa;
+  gtk_tree_model_get( GTK_TREE_MODEL(store) , iter ,
+                      LISTMIXER_ID_COLUMN , &ctl_id ,
+                      LISTMIXER_NAME_COLUMN , &ctl_name , -1 );
+  if (( !strcmp( ctl_name , alsacfg->alsa_mixer_ctl_name ) ) &&
+      ( ctl_id == alsacfg->alsa_mixer_ctl_id ))
+  {
+    /* this is the selected control in the mixer control combobox */
+    gtk_combo_box_set_active_iter( GTK_COMBO_BOX(mixctl_cmb) , iter );
+    return TRUE;
+  }
+  g_free( ctl_name );
+  return FALSE;
+}
+
+
+void i_configure_ev_cardcmb_changed( GtkWidget * card_cmb , gpointer mixctl_cmb )
+{
+  GtkTreeIter iter;
+  if( gtk_combo_box_get_active_iter( GTK_COMBO_BOX(card_cmb) , &iter ) )
+  {
+    amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa;
+    gpointer mixctl_store;
+    gint card_id;
+    GtkTreeModel * store = gtk_combo_box_get_model( GTK_COMBO_BOX(card_cmb) );
+    gtk_tree_model_get( GTK_TREE_MODEL(store) , &iter ,
+                        LISTCARD_ID_COLUMN , &card_id ,
+                        LISTCARD_MIXERPTR_COLUMN , &mixctl_store , -1 );
+    gtk_combo_box_set_model( GTK_COMBO_BOX(mixctl_cmb) , GTK_TREE_MODEL(mixctl_store) );
+
+    /* check if the selected card is the one contained in configuration */
+    if ( card_id == alsacfg->alsa_mixer_card_id )
+    {
+      /* search for the selected mixer control in combo box */
+      gtk_tree_model_foreach( GTK_TREE_MODEL(mixctl_store) ,
+                              i_configure_ev_mixctlcmb_inspect , mixctl_cmb );
+    }
+  }
+}
+
+
+gboolean i_configure_ev_portlv_inspecttoggle( 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 );
+  if ( toggled ) /* check if the row points to an enabled port */
+  {
+    /* 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_portlv_commit( gpointer port_lv )
+{
+  amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa;
+  GtkTreeModel * store;
+  GString *wp = g_string_new( "" );
+  /* get the model of the port listview */
+  store = gtk_tree_view_get_model( GTK_TREE_VIEW(port_lv) );
+  /* after going through this foreach, wp contains a comma-separated list of selected ports */
+  gtk_tree_model_foreach( store , i_configure_ev_portlv_inspecttoggle , wp );
+  g_free( alsacfg->alsa_seq_wports ); /* free previous */
+  alsacfg->alsa_seq_wports = g_strdup( wp->str ); /* set with new */
+  g_string_free( wp , TRUE ); /* not needed anymore */
+  return;
+}
+
+void i_configure_ev_cardcmb_commit( gpointer card_cmb )
+{
+  GtkTreeModel * store;
+  GtkTreeIter iter;
+  store = gtk_combo_box_get_model( GTK_COMBO_BOX(card_cmb) );
+  /* get the selected item */
+  if ( gtk_combo_box_get_active_iter( GTK_COMBO_BOX(card_cmb) , &iter ) )
+  {
+    amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa;
+    /* update amidiplug_cfg.alsa_mixer_card_id */
+    gtk_tree_model_get( GTK_TREE_MODEL(store) , &iter ,
+                        LISTCARD_ID_COLUMN ,
+                        &alsacfg->alsa_mixer_card_id , -1 );
+  }
+  return;
+}
+
+void i_configure_ev_mixctlcmb_commit( gpointer mixctl_cmb )
+{
+  GtkTreeModel * store;
+  GtkTreeIter iter;
+  store = gtk_combo_box_get_model( GTK_COMBO_BOX(mixctl_cmb) );
+  /* get the selected item */
+  if ( gtk_combo_box_get_active_iter( GTK_COMBO_BOX(mixctl_cmb) , &iter ) )
+  {
+    amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa;
+    g_free( alsacfg->alsa_mixer_ctl_name ); /* free previous */
+    /* update amidiplug_cfg.alsa_mixer_card_id */
+    gtk_tree_model_get( GTK_TREE_MODEL(store) , &iter ,
+                        LISTMIXER_NAME_COLUMN ,
+                        &alsacfg->alsa_mixer_ctl_name ,
+                        LISTMIXER_ID_COLUMN ,
+                        &alsacfg->alsa_mixer_ctl_id , -1 );
+  }
+  return;
+}
+
+
+void i_configure_gui_ctlcmb_datafunc( GtkCellLayout *cell_layout , GtkCellRenderer *cr ,
+                                      GtkTreeModel *store , GtkTreeIter *iter , gpointer p )
+{
+  gchar *ctl_display, *ctl_name;
+  gint ctl_id;
+  gtk_tree_model_get( store , iter ,
+                      LISTMIXER_NAME_COLUMN , &ctl_name ,
+                      LISTMIXER_ID_COLUMN , &ctl_id , -1 );
+  if ( ctl_id == 0 )
+    ctl_display = g_strdup_printf( "%s" , ctl_name );
+  else
+    ctl_display = g_strdup_printf( "%s (%i)" , ctl_name , ctl_id );
+  g_object_set( G_OBJECT(cr) , "text" , ctl_display , NULL );
+  g_free( ctl_display );
+  g_free( ctl_name );
+}
+
+
+void i_configure_gui_tab_alsa( GtkWidget * alsa_page_alignment ,
+                               gpointer backend_list_p ,
+                               gpointer commit_button )
+{
+  GtkWidget *alsa_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 alsa_module_ok = FALSE;
+  gchar * alsa_module_pathfilename;
+
+  alsa_page_vbox = gtk_vbox_new( FALSE , 0 );
+
+  title_widget = i_configure_gui_draw_title( _("ALSA BACKEND CONFIGURATION") );
+  gtk_box_pack_start( GTK_BOX(alsa_page_vbox) , title_widget , FALSE , FALSE , 2 );
+
+  content_vbox = gtk_vbox_new( TRUE , 2 );
+
+  /* check if the ALSA module is available */
+  while ( backend_list != NULL )
+  {
+    amidiplug_sequencer_backend_name_t * mn = backend_list->data;
+    if ( !strcmp( mn->name , "alsa" ) )
+    {
+      alsa_module_ok = TRUE;
+      alsa_module_pathfilename = mn->filename;
+      break;
+    }
+    backend_list = backend_list->next;
+  }
+
+  if ( alsa_module_ok )
+  {
+    GtkListStore *port_store, *mixer_card_store;
+    GtkWidget *port_lv, *port_lv_sw, *port_lv_frame;
+    GtkCellRenderer *port_lv_toggle_rndr, *port_lv_text_rndr;
+    GtkTreeViewColumn *port_lv_toggle_col, *port_lv_portnum_col;
+    GtkTreeViewColumn *port_lv_clientname_col, *port_lv_portname_col;
+    GtkTreeSelection *port_lv_sel;
+    GtkTreeIter iter;
+    GtkWidget *mixer_table, *mixer_frame;
+    GtkCellRenderer *mixer_card_cmb_text_rndr, *mixer_ctl_cmb_text_rndr;
+    GtkWidget *mixer_card_cmb_evbox, *mixer_card_cmb, *mixer_card_label;
+    GtkWidget *mixer_ctl_cmb_evbox, *mixer_ctl_cmb, *mixer_ctl_label;
+    GtkTooltips *tips;
+
+    amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa;
+
+    gchar **portstring_from_cfg = NULL;
+
+    GModule * alsa_module;
+    GSList *wports = NULL, *wports_h = NULL, *scards = NULL, *scards_h = NULL;
+    GSList * (*get_port_list)( void );
+    void (*free_port_list)( GSList * );
+    GSList * (*get_card_list)( void );
+    void (*free_card_list)( GSList * );
+
+    if ( strlen( alsacfg->alsa_seq_wports ) > 0 )
+      portstring_from_cfg = g_strsplit( alsacfg->alsa_seq_wports , "," , 0 );
+
+    tips = gtk_tooltips_new();
+    g_object_set_data_full( G_OBJECT(alsa_page_alignment) , "tt" , tips , g_object_unref );
+
+    /* it's legit to assume that this can't fail,
+       since the module is present in the backend_list */
+    alsa_module = g_module_open( alsa_module_pathfilename , 0 );
+    g_module_symbol( alsa_module , "sequencer_port_get_list" , (gpointer*)&get_port_list );
+    g_module_symbol( alsa_module , "sequencer_port_free_list" , (gpointer*)&free_port_list );
+    g_module_symbol( alsa_module , "alsa_card_get_list" , (gpointer*)&get_card_list );
+    g_module_symbol( alsa_module , "alsa_card_free_list" , (gpointer*)&free_card_list );
+    /* get an updated list of writable ALSA MIDI ports and ALSA-enabled sound cards*/
+    wports = get_port_list(); wports_h = wports;
+    scards = get_card_list(); scards_h = scards;
+
+    /* ALSA MIDI PORT LISTVIEW */
+    port_store = gtk_list_store_new( LISTPORT_N_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_STRING ,
+                                     G_TYPE_STRING , G_TYPE_STRING , G_TYPE_POINTER );
+    while ( wports != NULL )
+    {
+      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_store , &iter );
+      /* in the existing configuration there may be previously selected ports */
+      if ( portstring_from_cfg != NULL )
+      {
+        gint i = 0;
+        /* 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_store , &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;
+    }
+    g_strfreev( portstring_from_cfg ); /* not needed anymore */
+    port_lv = gtk_tree_view_new_with_model( GTK_TREE_MODEL(port_store) );
+    gtk_tree_view_set_rules_hint( GTK_TREE_VIEW(port_lv), TRUE );
+    g_object_unref( port_store );
+    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_portlv_changetoggle) , port_store );
+    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_NONE );
+    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_ALWAYS );
+    port_lv_frame = gtk_frame_new( _("ALSA output ports") );
+    gtk_container_add( GTK_CONTAINER(port_lv_sw) , port_lv );
+    gtk_container_add( GTK_CONTAINER(port_lv_frame) , port_lv_sw );
+    gtk_box_pack_start( GTK_BOX(content_vbox) , port_lv_frame , TRUE , TRUE , 0 );
+    g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_portlv_commit) , port_lv );
+
+    /* MIXER CARD/CONTROL COMBOBOXES */
+    mixer_card_store = gtk_list_store_new( LISTCARD_N_COLUMNS , G_TYPE_STRING , G_TYPE_INT , G_TYPE_POINTER );
+    mixer_card_cmb = gtk_combo_box_new_with_model( GTK_TREE_MODEL(mixer_card_store) ); /* soundcard combo box */
+    mixer_ctl_cmb = gtk_combo_box_new(); /* mixer control combo box */
+    g_signal_connect( mixer_card_cmb , "changed" , G_CALLBACK(i_configure_ev_cardcmb_changed) , mixer_ctl_cmb );
+    while ( scards != NULL )
+    {
+      GtkListStore *mixer_ctl_store;
+      GtkTreeIter itermix;
+      data_bucket_t * cardinfo = (data_bucket_t *)scards->data;
+      GSList *mixctl_list = cardinfo->bpointer[0];
+      mixer_ctl_store = gtk_list_store_new( LISTMIXER_N_COLUMNS , G_TYPE_STRING , G_TYPE_INT );
+      while ( mixctl_list != NULL )
+      {
+        data_bucket_t * mixctlinfo = (data_bucket_t *)mixctl_list->data;
+        gtk_list_store_append( mixer_ctl_store , &itermix );
+        gtk_list_store_set( mixer_ctl_store , &itermix ,
+                            LISTMIXER_NAME_COLUMN , mixctlinfo->bcharp[0] ,
+                            LISTMIXER_ID_COLUMN , mixctlinfo->bint[0] , -1 );
+        mixctl_list = mixctl_list->next; /* on with next mixer control */
+      }
+      gtk_list_store_append( mixer_card_store , &iter );
+      gtk_list_store_set( mixer_card_store , &iter ,
+                          LISTCARD_NAME_COLUMN , cardinfo->bcharp[0] ,
+                          LISTCARD_ID_COLUMN , cardinfo->bint[0] ,
+                          LISTCARD_MIXERPTR_COLUMN , mixer_ctl_store , -1 );
+      /* check if this corresponds to the value previously selected by user */
+      if ( cardinfo->bint[0] == alsacfg->alsa_mixer_card_id )
+        gtk_combo_box_set_active_iter( GTK_COMBO_BOX(mixer_card_cmb) , &iter );
+      scards = scards->next; /* on with next card */
+    }
+    g_object_unref( mixer_card_store ); /* free a reference, no longer needed */
+    /* 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" , LISTCARD_NAME_COLUMN );
+    mixer_ctl_cmb_text_rndr = gtk_cell_renderer_text_new();
+    gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(mixer_ctl_cmb) , mixer_ctl_cmb_text_rndr , TRUE );
+    gtk_cell_layout_set_cell_data_func( GTK_CELL_LAYOUT(mixer_ctl_cmb) , mixer_ctl_cmb_text_rndr ,
+                                        i_configure_gui_ctlcmb_datafunc , NULL , NULL );
+    /* 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_ctl_cmb_evbox = gtk_event_box_new();
+    gtk_container_add( GTK_CONTAINER(mixer_ctl_cmb_evbox) , mixer_ctl_cmb );
+    mixer_card_label = gtk_label_new( _("Soundcard: ") );
+    gtk_misc_set_alignment( GTK_MISC(mixer_card_label) , 0 , 0.5 );
+    mixer_ctl_label = gtk_label_new( _("Mixer control: ") );
+    gtk_misc_set_alignment( GTK_MISC(mixer_ctl_label) , 0 , 0.5 );
+    mixer_table = gtk_table_new( 3 , 2 , FALSE );
+    gtk_container_set_border_width( GTK_CONTAINER(mixer_table), 4 );
+    gtk_table_attach( GTK_TABLE(mixer_table) , mixer_card_label , 0 , 1 , 0 , 1 ,
+                      GTK_FILL , 0 , 1 , 2 );
+    gtk_table_attach( GTK_TABLE(mixer_table) , mixer_card_cmb_evbox , 1 , 2 , 0 , 1 ,
+                      GTK_EXPAND | GTK_FILL , 0 , 1 , 2 );
+    gtk_table_attach( GTK_TABLE(mixer_table) , mixer_ctl_label , 0 , 1 , 1 , 2 ,
+                      GTK_FILL , 0 , 1 , 2 );
+    gtk_table_attach( GTK_TABLE(mixer_table) , mixer_ctl_cmb_evbox , 1 , 2 , 1 , 2 ,
+                      GTK_EXPAND | GTK_FILL , 0 , 1 , 2 );
+    mixer_frame = gtk_frame_new( _("Mixer settings") );
+    gtk_container_add( GTK_CONTAINER(mixer_frame) , mixer_table );
+    gtk_box_pack_start( GTK_BOX(content_vbox) , mixer_frame , TRUE , TRUE , 0 );
+    g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_cardcmb_commit) , mixer_card_cmb );
+    g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_mixctlcmb_commit) , mixer_ctl_cmb );
+
+    free_card_list( scards_h );
+    free_port_list( wports_h );
+    g_module_close( alsa_module );
+
+    gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , port_lv ,
+                        _("* Select ALSA output ports *\n"
+                        "MIDI events will be sent to the ports selected here. In example, if your "
+                        "audio card provides a hardware synth and you want to play MIDI with it, "
+                        "you'll probably want to select the wavetable synthesizer ports.") , "" );
+    gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , mixer_card_cmb_evbox ,
+                        _("* Select ALSA mixer card *\n"
+                        "The ALSA backend outputs directly through ALSA, it doesn't use effect "
+                        "and ouput plugins from the player. During playback, the player volume"
+                        "slider will manipulate the mixer control you select here. "
+                        "If you're using wavetable synthesizer ports, you'll probably want to "
+                        "select the Synth control here.") , "" );
+    gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , mixer_ctl_cmb_evbox ,
+                        _("* Select ALSA mixer control *\n"
+                        "The ALSA backend outputs directly through ALSA, it doesn't use effect "
+                        "and ouput plugins from the player. During playback, the player volume "
+                        "slider will manipulate the mixer control you select here. "
+                        "If you're using wavetable synthesizer ports, you'll probably want to "
+                        "select the Synth control here.") , "" );
+  }
+  else
+  {
+    /* display "not available" information */
+    GtkWidget * info_label;
+    info_label = gtk_label_new( _("ALSA Backend not loaded or not available") );
+    gtk_box_pack_start( GTK_BOX(alsa_page_vbox) , info_label , FALSE , FALSE , 2 );
+  }
+
+  gtk_box_pack_start( GTK_BOX(alsa_page_vbox) , content_vbox , TRUE , TRUE , 2 );
+  gtk_container_add( GTK_CONTAINER(alsa_page_alignment) , alsa_page_vbox );
+}
+
+
+void i_configure_gui_tablabel_alsa( GtkWidget * alsa_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_alsa_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\">ALSA\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(alsa_page_alignment) , pagelabel_vbox );
+  gtk_widget_show_all( alsa_page_alignment );
+  return;
+}
+
+
+gchar * i_configure_read_seq_ports_default( void )
+{
+  FILE * fp = 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 option: do not set ports at all, let the user
+     select the right ones in the nice config window :) */
+  return g_strdup( "" );
+}
+
+
+
+void i_configure_cfg_alsa_alloc( void )
+{
+  amidiplug_cfg_alsa_t * alsacfg = g_malloc(sizeof(amidiplug_cfg_alsa_t));
+  amidiplug_cfg_backend->alsa = alsacfg;
+}
+
+
+void i_configure_cfg_alsa_free( void )
+{
+  amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa;
+  g_free( alsacfg->alsa_seq_wports );
+  g_free( alsacfg->alsa_mixer_ctl_name );
+  g_free( amidiplug_cfg_backend->alsa );
+}
+
+
+void i_configure_cfg_alsa_read( pcfg_t * cfgfile )
+{
+  amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa;
+
+  if (!cfgfile)
+  {
+    /* alsa backend defaults */
+    alsacfg->alsa_seq_wports = i_configure_read_seq_ports_default();
+    alsacfg->alsa_mixer_card_id = 0;
+    alsacfg->alsa_mixer_ctl_name = g_strdup( "Synth" );
+    alsacfg->alsa_mixer_ctl_id = 0;
+  }
+  else
+  {
+    i_pcfg_read_string( cfgfile , "alsa" , "alsa_seq_wports" , &alsacfg->alsa_seq_wports , NULL );
+    if ( alsacfg->alsa_seq_wports == NULL )
+      alsacfg->alsa_seq_wports = i_configure_read_seq_ports_default(); /* pick default values */
+    i_pcfg_read_integer( cfgfile , "alsa" , "alsa_mixer_card_id" , &alsacfg->alsa_mixer_card_id , 0 );
+    i_pcfg_read_string( cfgfile , "alsa" , "alsa_mixer_ctl_name" , &alsacfg->alsa_mixer_ctl_name , "Synth" );
+    i_pcfg_read_integer( cfgfile , "alsa" , "alsa_mixer_ctl_id" , &alsacfg->alsa_mixer_ctl_id , 0 );
+  }
+}
+
+
+void i_configure_cfg_alsa_save( pcfg_t * cfgfile )
+{
+  amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa;
+
+  i_pcfg_write_string( cfgfile , "alsa" , "alsa_seq_wports" , alsacfg->alsa_seq_wports );
+  i_pcfg_write_integer( cfgfile , "alsa" , "alsa_mixer_card_id" , alsacfg->alsa_mixer_card_id );
+  i_pcfg_write_string( cfgfile , "alsa" , "alsa_mixer_ctl_name" , alsacfg->alsa_mixer_ctl_name );
+  i_pcfg_write_integer( cfgfile , "alsa" , "alsa_mixer_ctl_id" , alsacfg->alsa_mixer_ctl_id );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_configure-alsa.h	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,36 @@
+/*
+*
+* 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_ALSA_H
+#define _I_CONFIGURE_ALSA_H 1
+
+#include "i_configure_private.h"
+
+
+extern amidiplug_cfg_backend_t * amidiplug_cfg_backend;
+
+void i_configure_gui_tab_alsa( GtkWidget * , gpointer , gpointer );
+void i_configure_gui_tablabel_alsa( GtkWidget * , gpointer , gpointer );
+void i_configure_cfg_alsa_alloc( void );
+void i_configure_cfg_alsa_free( void );
+void i_configure_cfg_alsa_read( pcfg_t * );
+void i_configure_cfg_alsa_save( pcfg_t * );
+
+#endif /* !_I_CONFIGURE_ALSA_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_configure-ap.c	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,279 @@
+/*
+*
+* 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-ap.h"
+#include "amidi-plug-icon.xpm"
+
+
+enum
+{
+  LISTBACKEND_NAME_COLUMN = 0,
+  LISTBACKEND_LONGNAME_COLUMN,
+  LISTBACKEND_DESC_COLUMN,
+  LISTBACKEND_FILENAME_COLUMN,
+  LISTBACKEND_PPOS_COLUMN,
+  LISTBACKEND_N_COLUMNS
+};
+
+
+void i_configure_ev_backendlv_info( gpointer backend_lv )
+{
+  GtkTreeModel * store;
+  GtkTreeIter iter;
+  GtkTreeSelection *sel = gtk_tree_view_get_selection( GTK_TREE_VIEW(backend_lv) );
+  /* get the selected item */
+  if ( gtk_tree_selection_get_selected( sel , &store , &iter ) )
+  {
+    GtkWidget *bidialog;
+    GdkGeometry bi_hints;
+    GtkWidget *title_label, *title_frame;
+    GtkWidget *filename_entry, *filename_frame;
+    GtkWidget *description_label, *description_frame;
+    GtkWidget *parent_window = gtk_widget_get_toplevel( backend_lv );
+    gchar *longname_title, *longname, *filename, *description;
+    gtk_tree_model_get( GTK_TREE_MODEL(store) , &iter ,
+                        LISTBACKEND_LONGNAME_COLUMN , &longname ,
+                        LISTBACKEND_DESC_COLUMN , &description ,
+                        LISTBACKEND_FILENAME_COLUMN , &filename , -1 );
+    bidialog = gtk_dialog_new_with_buttons( _("AMIDI-Plug - backend information") ,
+                                            GTK_WINDOW(parent_window) ,
+                                            GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL ,
+                                            GTK_STOCK_OK , GTK_RESPONSE_NONE , NULL );
+    bi_hints.min_width = 360; bi_hints.min_height = -1;
+    gtk_window_set_geometry_hints( GTK_WINDOW(bidialog) , GTK_WIDGET(bidialog) ,
+                                   &bi_hints , GDK_HINT_MIN_SIZE );
+
+    longname_title = g_markup_printf_escaped( "<span size=\"larger\" weight=\"bold\" >%s</span>" , longname );
+    title_frame = gtk_frame_new( NULL );
+    title_label = gtk_label_new( "" );
+    gtk_label_set_markup( GTK_LABEL(title_label) , longname_title );
+    g_free( longname_title ); g_free( longname );
+    gtk_container_add( GTK_CONTAINER(title_frame) , title_label );
+    gtk_box_pack_start( GTK_BOX(GTK_DIALOG(bidialog)->vbox) , title_frame , FALSE , FALSE , 0 );
+
+    filename_frame = gtk_frame_new( NULL );
+    filename_entry = gtk_entry_new();
+    gtk_entry_set_text( GTK_ENTRY(filename_entry) , filename );
+    gtk_entry_set_alignment( GTK_ENTRY(filename_entry) , 0.5 );
+    gtk_editable_set_editable( GTK_EDITABLE(filename_entry) , FALSE );
+    gtk_entry_set_has_frame( GTK_ENTRY(filename_entry) , FALSE );
+    g_free( filename );
+    gtk_container_add( GTK_CONTAINER(filename_frame) , filename_entry );
+    gtk_box_pack_start( GTK_BOX(GTK_DIALOG(bidialog)->vbox) , filename_frame , FALSE , FALSE , 0 );
+
+    description_frame = gtk_frame_new( NULL );
+    description_label = gtk_label_new( description );
+    gtk_misc_set_padding( GTK_MISC(description_label) , 4 , 4 );
+    gtk_label_set_line_wrap( GTK_LABEL(description_label) , TRUE );
+    g_free( description );
+    gtk_container_add( GTK_CONTAINER(description_frame) , description_label );
+    gtk_box_pack_start( GTK_BOX(GTK_DIALOG(bidialog)->vbox) , description_frame , TRUE , TRUE , 0 );
+
+    gtk_widget_show_all( bidialog );
+    gtk_window_set_focus( GTK_WINDOW(bidialog) , NULL );
+    gtk_dialog_run( GTK_DIALOG(bidialog) );
+    gtk_widget_destroy( bidialog );
+  }
+  return;
+}
+
+
+void i_configure_ev_backendlv_commit( gpointer backend_lv )
+{
+  GtkTreeModel * store;
+  GtkTreeIter iter;
+  GtkTreeSelection *sel = gtk_tree_view_get_selection( GTK_TREE_VIEW(backend_lv) );
+  /* get the selected item */
+  if ( gtk_tree_selection_get_selected( sel , &store , &iter ) )
+  {
+    g_free( amidiplug_cfg_ap.ap_seq_backend ); /* free previous */
+    /* update amidiplug_cfg_ap.ap_seq_backend */
+    gtk_tree_model_get( GTK_TREE_MODEL(store) , &iter ,
+                        LISTBACKEND_NAME_COLUMN , &amidiplug_cfg_ap.ap_seq_backend , -1 );
+  }
+  return;
+}
+
+
+void i_configure_ev_settings_commit( gpointer settings_vbox )
+{
+  GtkWidget * settings_precalc_checkbt = g_object_get_data( G_OBJECT(settings_vbox) ,
+                                                            "ap_opts_length_precalc" );
+  if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(settings_precalc_checkbt) ) )
+    amidiplug_cfg_ap.ap_opts_length_precalc = 1;
+  else
+    amidiplug_cfg_ap.ap_opts_length_precalc = 0;
+  return;
+}
+
+
+gint i_configure_backendlist_sortf( GtkTreeModel * model , GtkTreeIter * a ,
+                                    GtkTreeIter * b , gpointer data )
+{
+  gint v_a = 0, v_b = 0;
+  gtk_tree_model_get( model , a , LISTBACKEND_PPOS_COLUMN , &v_a , -1 );
+  gtk_tree_model_get( model , b , LISTBACKEND_PPOS_COLUMN , &v_b , -1 );
+  return (v_a - v_b);
+}
+
+
+void i_configure_gui_tab_ap( GtkWidget * ap_page_alignment ,
+                               gpointer backend_list_p ,
+                               gpointer commit_button )
+{
+  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, *settings_precalc_checkbt;
+  GtkWidget *backend_lv_frame, *backend_lv, *backend_lv_sw;
+  GtkWidget *backend_lv_hbox, *backend_lv_vbbox, *backend_lv_infobt;
+  GtkListStore *backend_store;
+  GtkCellRenderer *backend_lv_text_rndr;
+  GtkTreeViewColumn *backend_lv_name_col;
+  GtkTreeIter backend_lv_iter_selected;
+  GtkTreeSelection *backend_lv_sel;
+  GtkTreeIter iter;
+  GtkTooltips *tips;
+  GSList * backend_list = backend_list_p;
+
+  tips = gtk_tooltips_new();
+  g_object_set_data_full( G_OBJECT(ap_page_alignment) , "tt" , tips , g_object_unref );
+
+  ap_page_vbox = gtk_vbox_new( FALSE , 0 );
+
+  title_widget = i_configure_gui_draw_title( _("AMIDI-PLUG PREFERENCES") );
+  gtk_box_pack_start( GTK_BOX(ap_page_vbox) , title_widget , FALSE , FALSE , 2 );
+
+  content_vbox = gtk_vbox_new( TRUE , 2 );
+
+  backend_store = gtk_list_store_new( LISTBACKEND_N_COLUMNS , G_TYPE_STRING , G_TYPE_STRING ,
+                                      G_TYPE_STRING , G_TYPE_STRING , G_TYPE_INT );
+  gtk_tree_sortable_set_default_sort_func( GTK_TREE_SORTABLE(backend_store) ,
+                                           i_configure_backendlist_sortf , NULL , NULL );
+  gtk_tree_sortable_set_sort_column_id( GTK_TREE_SORTABLE(backend_store) ,
+                                        GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID ,
+                                        GTK_SORT_ASCENDING );
+  while ( backend_list != NULL )
+  {
+    amidiplug_sequencer_backend_name_t * mn = backend_list->data;
+    gtk_list_store_append( backend_store , &iter );
+    gtk_list_store_set ( backend_store, &iter,
+                         LISTBACKEND_NAME_COLUMN , mn->name ,
+                         LISTBACKEND_LONGNAME_COLUMN , mn->longname ,
+                         LISTBACKEND_DESC_COLUMN , mn->desc ,
+                         LISTBACKEND_FILENAME_COLUMN , mn->filename ,
+                         LISTBACKEND_PPOS_COLUMN , mn->ppos , -1 );
+    if ( !strcmp( mn->name , amidiplug_cfg_ap.ap_seq_backend ) )
+      backend_lv_iter_selected = iter;
+    backend_list = backend_list->next;
+  }
+
+  backend_lv_frame = gtk_frame_new( _("Backend selection") );
+  backend_lv = gtk_tree_view_new_with_model( GTK_TREE_MODEL(backend_store) );
+  g_object_unref( backend_store );
+  backend_lv_text_rndr = gtk_cell_renderer_text_new();
+  backend_lv_name_col = gtk_tree_view_column_new_with_attributes( _("Available backends") ,
+                                                                  backend_lv_text_rndr ,
+                                                                  "text" , 1 , NULL );
+  gtk_tree_view_append_column( GTK_TREE_VIEW(backend_lv), backend_lv_name_col );
+
+  backend_lv_sel = gtk_tree_view_get_selection( GTK_TREE_VIEW(backend_lv) );
+  gtk_tree_selection_set_mode( GTK_TREE_SELECTION(backend_lv_sel) , GTK_SELECTION_BROWSE );
+  gtk_tree_selection_select_iter( GTK_TREE_SELECTION(backend_lv_sel) , &backend_lv_iter_selected );
+
+  backend_lv_sw = gtk_scrolled_window_new( NULL , NULL );
+  gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(backend_lv_sw) ,
+                                  GTK_POLICY_NEVER , GTK_POLICY_ALWAYS );
+  gtk_container_add( GTK_CONTAINER(backend_lv_sw) , backend_lv );
+  g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" ,
+                            G_CALLBACK(i_configure_ev_backendlv_commit) , backend_lv );
+
+  backend_lv_hbox = gtk_hbox_new( FALSE , 0 );
+  gtk_box_pack_start( GTK_BOX(backend_lv_hbox) , backend_lv_sw , TRUE , TRUE , 0 );
+  backend_lv_vbbox = gtk_vbox_new( FALSE , 2 );
+  gtk_box_pack_start( GTK_BOX(backend_lv_hbox) , backend_lv_vbbox , FALSE , FALSE , 3 );
+  backend_lv_infobt = gtk_button_new();
+  gtk_button_set_image( GTK_BUTTON(backend_lv_infobt) ,
+                          gtk_image_new_from_stock( GTK_STOCK_DIALOG_INFO , GTK_ICON_SIZE_BUTTON ) );
+  g_signal_connect_swapped( G_OBJECT(backend_lv_infobt) , "clicked" ,
+                            G_CALLBACK(i_configure_ev_backendlv_info) , backend_lv );
+  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( _("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 );
+  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_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" ,
+                            G_CALLBACK(i_configure_ev_settings_commit) , settings_vbox );
+
+  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(ap_page_vbox) , content_vbox , TRUE , TRUE , 2 );
+  gtk_container_add( GTK_CONTAINER(ap_page_alignment) , ap_page_vbox );
+
+  gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , backend_lv ,
+                        _("* Backend selection *\n"
+                        "AMIDI-Plug works with backends, in a modular fashion; here you should "
+                        "select your backend; that is, the way MIDI events are going to be handled "
+                        "and played.\nIf you have a hardware synthesizer on your audio card, and ALSA "
+                        "supports it, you'll want to use the ALSA backend. It can also be "
+                        "used with anything that provides an interface to the ALSA sequencer, including "
+                        "software synths or external devices.\nIf you want to rely on a software "
+                        "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 ,
+                        _("* 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 "
+                        "when the MIDI file is being played. In example, MIDI length "
+                        "will be calculated straight after adding MIDI files in a playlist. "
+                        "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.") , "" );
+}
+
+
+void i_configure_gui_tablabel_ap( GtkWidget * ap_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 **)amidi_plug_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\">AMIDI\nPlug</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(ap_page_alignment) , pagelabel_vbox );
+  gtk_widget_show_all( ap_page_alignment );
+  return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_configure-ap.h	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,33 @@
+/*
+*
+* 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_AP_H
+#define _I_CONFIGURE_AP_H 1
+
+#include "i_configure.h"
+#include "i_configure_private.h"
+
+
+extern amidiplug_cfg_ap_t amidiplug_cfg_ap;
+
+void i_configure_gui_tab_ap( GtkWidget * , gpointer , gpointer );
+void i_configure_gui_tablabel_ap( GtkWidget * , gpointer , gpointer );
+
+#endif /* !_I_CONFIGURE_AP_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_configure-dummy.c	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,410 @@
+/*
+*
+* 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-dummy.h"
+#include "backend-dummy/b-dummy-config.h"
+#include "backend-dummy/backend-dummy-icon.xpm"
+
+
+void i_configure_ev_logfile_toggle( GtkToggleButton *diflogfiles_radiobt , gpointer logfile_table )
+{
+  GList * tc_list = gtk_container_get_children( GTK_CONTAINER(logfile_table) );
+  if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(diflogfiles_radiobt) ) )
+  {
+    gtk_widget_set_sensitive( g_list_nth_data(tc_list,0) , TRUE ); /* dir bbutton */
+    gtk_widget_set_sensitive( g_list_nth_data(tc_list,1) , TRUE ); /* dir entry */
+    gtk_widget_set_sensitive( g_list_nth_data(tc_list,2) , TRUE ); /* dir label */
+    gtk_widget_set_sensitive( g_list_nth_data(tc_list,4) , FALSE ); /* file bbutton */
+    gtk_widget_set_sensitive( g_list_nth_data(tc_list,5) , FALSE ); /* file entry */
+    gtk_widget_set_sensitive( g_list_nth_data(tc_list,6) , FALSE ); /* file label */
+  }
+  else
+  {
+    gtk_widget_set_sensitive( g_list_nth_data(tc_list,0) , FALSE ); /* dir bbutton */
+    gtk_widget_set_sensitive( g_list_nth_data(tc_list,1) , FALSE ); /* dir entry */
+    gtk_widget_set_sensitive( g_list_nth_data(tc_list,2) , FALSE ); /* dir label */
+    gtk_widget_set_sensitive( g_list_nth_data(tc_list,4) , TRUE ); /* file bbutton */
+    gtk_widget_set_sensitive( g_list_nth_data(tc_list,5) , TRUE ); /* file entry */
+    gtk_widget_set_sensitive( g_list_nth_data(tc_list,6) , TRUE ); /* file label */
+  }
+}
+
+
+void i_configure_ev_enablelog_toggle( GtkToggleButton *logwithfile_radiobt , gpointer logfile_table )
+{
+  if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(logwithfile_radiobt) ) )
+  {
+    gtk_widget_set_sensitive( GTK_WIDGET(logfile_table) , TRUE );
+    i_configure_ev_logfile_toggle( g_object_get_data(G_OBJECT(logfile_table),"lfstyle-opt2") , logfile_table );
+  }
+  else
+  {
+    gtk_widget_set_sensitive( GTK_WIDGET(logfile_table) , FALSE );
+  }
+}
+
+
+void i_configure_ev_enablelog_commit( gpointer enablelog_radiobt )
+{
+  amidiplug_cfg_dumm_t * dummcfg = amidiplug_cfg_backend->dumm;
+  GSList *group = gtk_radio_button_get_group( GTK_RADIO_BUTTON(enablelog_radiobt) );
+  while ( group != NULL )
+  {
+    if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(group->data) ) )
+    {
+      dummcfg->dumm_logger_enable = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(group->data),"val"));
+      group = NULL; /* do not iterate further */
+    }
+    else
+      group = group->next;
+  }
+}
+
+void i_configure_ev_lfstyle_commit( gpointer lfstyle_radiobt )
+{
+  amidiplug_cfg_dumm_t * dummcfg = amidiplug_cfg_backend->dumm;
+  GSList *group = gtk_radio_button_get_group( GTK_RADIO_BUTTON(lfstyle_radiobt) );
+  while ( group != NULL )
+  {
+    if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(group->data) ) )
+    {
+      dummcfg->dumm_logger_lfstyle = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(group->data),"val"));
+      group = NULL; /* do not iterate further */
+    }
+    else
+      group = group->next;
+  }
+}
+
+
+void i_configure_ev_plspeed_commit( gpointer plspeed_normal_radiobt )
+{
+  amidiplug_cfg_dumm_t * dummcfg = amidiplug_cfg_backend->dumm;
+  if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(plspeed_normal_radiobt) ) )
+    dummcfg->dumm_playback_speed = 0;
+  else
+    dummcfg->dumm_playback_speed = 1;
+}
+
+
+void i_configure_ev_logfname_commit( gpointer logfname_entry )
+{
+  amidiplug_cfg_dumm_t * dummcfg = amidiplug_cfg_backend->dumm;
+  g_free( dummcfg->dumm_logger_logfile ); /* free previous */
+  dummcfg->dumm_logger_logfile = g_strdup( gtk_entry_get_text(GTK_ENTRY(logfname_entry)) );
+}
+
+
+void i_configure_ev_logdir_commit( gpointer logdir_entry )
+{
+  amidiplug_cfg_dumm_t * dummcfg = amidiplug_cfg_backend->dumm;
+  g_free( dummcfg->dumm_logger_logdir ); /* free previous */
+  dummcfg->dumm_logger_logdir = g_strdup( gtk_entry_get_text(GTK_ENTRY(logdir_entry)) );
+}
+
+
+void i_configure_gui_tab_dumm( GtkWidget * dumm_page_alignment ,
+                               gpointer backend_list_p ,
+                               gpointer commit_button )
+{
+  GtkWidget *dumm_page_vbox;
+  GtkWidget *title_widget;
+  GtkWidget *content_vbox;
+  GSList * backend_list = backend_list_p;
+  gboolean dumm_module_ok = FALSE;
+  gchar * dumm_module_pathfilename;
+
+  dumm_page_vbox = gtk_vbox_new( FALSE , 0 );
+
+  title_widget = i_configure_gui_draw_title( _("DUMMY BACKEND CONFIGURATION") );
+  gtk_box_pack_start( GTK_BOX(dumm_page_vbox) , title_widget , FALSE , FALSE , 2 );
+
+  content_vbox = gtk_vbox_new( FALSE , 2 );
+
+  /* check if the dummy module is available */
+  while ( backend_list != NULL )
+  {
+    amidiplug_sequencer_backend_name_t * mn = backend_list->data;
+    if ( !strcmp( mn->name , "dummy" ) )
+    {
+      dumm_module_ok = TRUE;
+      dumm_module_pathfilename = mn->filename;
+      break;
+    }
+    backend_list = backend_list->next;
+  }
+
+  if ( dumm_module_ok )
+  {
+    GtkWidget *midilogger_frame, *midilogger_vbox;
+    GtkWidget *midilogger_enablelog_vbox, *midilogger_enablelog_option[4];
+    GtkWidget *midilogger_logfile_frame, *midilogger_logfile_table, *midilogger_logfile_option[3];
+    GtkWidget *midilogger_logfile_logdir_labelalign, *midilogger_logfile_logdir_label;
+    GtkWidget *midilogger_logfile_logdir_entry, *midilogger_logfile_logdir_bbutton;
+    GtkWidget *midilogger_logfile_logfname_labelalign, *midilogger_logfile_logfname_label;
+    GtkWidget *midilogger_logfile_logfname_entry, *midilogger_logfile_logfname_bbutton;
+    GtkWidget *plspeed_frame, *plspeed_vbox, *plspeed_option[2];
+    GtkTooltips *tips;
+
+    amidiplug_cfg_dumm_t * dummcfg = amidiplug_cfg_backend->dumm;
+
+    tips = gtk_tooltips_new();
+    g_object_set_data_full( G_OBJECT(dumm_page_alignment) , "tt" , tips , g_object_unref );
+
+    /* midilogger settings */
+    midilogger_frame = gtk_frame_new( _("MIDI logger settings") );
+    midilogger_vbox = gtk_vbox_new( FALSE , 4 );
+    gtk_container_set_border_width( GTK_CONTAINER(midilogger_vbox), 4 );
+    gtk_container_add( GTK_CONTAINER(midilogger_frame) , midilogger_vbox );
+
+    /* midilogger settings - enable/disable */
+    midilogger_enablelog_vbox = gtk_vbox_new( FALSE , 0 );
+    midilogger_enablelog_option[0] = gtk_radio_button_new_with_label( NULL ,
+                                       _("Do not log anything") );
+    g_object_set_data( G_OBJECT(midilogger_enablelog_option[0]) , "val" , GINT_TO_POINTER(0) );
+    midilogger_enablelog_option[1] = gtk_radio_button_new_with_label_from_widget(
+                                       GTK_RADIO_BUTTON(midilogger_enablelog_option[0]) ,
+                                       _("Log MIDI events to standard output") );
+    g_object_set_data( G_OBJECT(midilogger_enablelog_option[1]) , "val" , GINT_TO_POINTER(1) );
+    midilogger_enablelog_option[2] = gtk_radio_button_new_with_label_from_widget(
+                                       GTK_RADIO_BUTTON(midilogger_enablelog_option[0]) ,
+                                       _("Log MIDI events to standard error") );
+    g_object_set_data( G_OBJECT(midilogger_enablelog_option[2]) , "val" , GINT_TO_POINTER(2) );
+    midilogger_enablelog_option[3] = gtk_radio_button_new_with_label_from_widget(
+                                       GTK_RADIO_BUTTON(midilogger_enablelog_option[0]) ,
+                                       _("Log MIDI events to file") );
+    g_object_set_data( G_OBJECT(midilogger_enablelog_option[3]) , "val" , GINT_TO_POINTER(3) );
+    gtk_box_pack_start( GTK_BOX(midilogger_enablelog_vbox) , midilogger_enablelog_option[0] , FALSE , FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(midilogger_enablelog_vbox) , midilogger_enablelog_option[1] , FALSE , FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(midilogger_enablelog_vbox) , midilogger_enablelog_option[2] , FALSE , FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(midilogger_enablelog_vbox) , midilogger_enablelog_option[3] , FALSE , FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(midilogger_vbox) , midilogger_enablelog_vbox , FALSE , FALSE , 0 );
+
+    /* midilogger settings - logfile options */
+    midilogger_logfile_frame = gtk_frame_new( _("Logfile settings") );
+    midilogger_logfile_table = gtk_table_new( 5 , 3 , FALSE );
+    gtk_table_set_col_spacings( GTK_TABLE(midilogger_logfile_table) , 2 );
+    gtk_container_set_border_width( GTK_CONTAINER(midilogger_logfile_table), 4 );
+    gtk_container_add( GTK_CONTAINER(midilogger_logfile_frame) , midilogger_logfile_table );
+    gtk_box_pack_start( GTK_BOX(midilogger_vbox) , midilogger_logfile_frame , FALSE , FALSE , 0 );
+    midilogger_logfile_option[0] = gtk_radio_button_new_with_label( NULL ,
+                                     _("Use a single file to log everything (rewrite)") );
+    g_object_set_data( G_OBJECT(midilogger_logfile_option[0]) , "val" , GINT_TO_POINTER(0) );
+    midilogger_logfile_option[1] = gtk_radio_button_new_with_label_from_widget(
+                                     GTK_RADIO_BUTTON(midilogger_logfile_option[0]) ,
+                                     _("Use a single file to log everything (append)") );
+    g_object_set_data( G_OBJECT(midilogger_logfile_option[1]) , "val" , GINT_TO_POINTER(1) );
+    midilogger_logfile_option[2] = gtk_radio_button_new_with_label_from_widget(
+                                     GTK_RADIO_BUTTON(midilogger_logfile_option[0]) ,
+                                     _("Use a different logfile for each MIDI file") );
+    g_object_set_data( G_OBJECT(midilogger_logfile_option[2]) , "val" , GINT_TO_POINTER(2) );
+    g_object_set_data( G_OBJECT(midilogger_logfile_table) , "lfstyle-opt2" , midilogger_logfile_option[2] );
+    /* midilogger settings - logfile options - dir entry box */
+    midilogger_logfile_logdir_labelalign = gtk_alignment_new( 0.5 , 0.5 , 1 , 1 );
+    gtk_alignment_set_padding( GTK_ALIGNMENT(midilogger_logfile_logdir_labelalign) , 0 , 0 , 15 , 0 );
+    midilogger_logfile_logdir_label = gtk_label_new( _("\302\273 Log dir:") );
+    gtk_container_add( GTK_CONTAINER(midilogger_logfile_logdir_labelalign) , midilogger_logfile_logdir_label );
+    midilogger_logfile_logdir_entry = gtk_entry_new();
+    gtk_entry_set_text( GTK_ENTRY(midilogger_logfile_logdir_entry) , dummcfg->dumm_logger_logdir );
+    g_object_set_data( G_OBJECT(midilogger_logfile_logdir_entry) , "fc-act",
+                       GINT_TO_POINTER(GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) );
+    midilogger_logfile_logdir_bbutton = gtk_button_new_with_label( _("browse") );
+    g_signal_connect_swapped( G_OBJECT(midilogger_logfile_logdir_bbutton) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_browse_for_entry) , midilogger_logfile_logdir_entry );
+    /* midilogger settings - logfile options - file entry box */
+    midilogger_logfile_logfname_labelalign = gtk_alignment_new( 0.5 , 0.5 , 1 , 1 );
+    gtk_alignment_set_padding( GTK_ALIGNMENT(midilogger_logfile_logfname_labelalign) , 0 , 0 , 15 , 0 );
+    midilogger_logfile_logfname_label = gtk_label_new( _("\302\273 Log file:") );
+    gtk_container_add( GTK_CONTAINER(midilogger_logfile_logfname_labelalign) , midilogger_logfile_logfname_label );
+    midilogger_logfile_logfname_entry = gtk_entry_new();
+    gtk_entry_set_text( GTK_ENTRY(midilogger_logfile_logfname_entry) , dummcfg->dumm_logger_logfile );
+    g_object_set_data( G_OBJECT(midilogger_logfile_logfname_entry) , "fc-act",
+                       GINT_TO_POINTER(GTK_FILE_CHOOSER_ACTION_OPEN) );
+    midilogger_logfile_logfname_bbutton = gtk_button_new_with_label( _("browse") );
+    g_signal_connect_swapped( G_OBJECT(midilogger_logfile_logfname_bbutton) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_browse_for_entry) , midilogger_logfile_logfname_entry );
+    /* midilogger settings - logfile options - pack everything in table */
+    gtk_table_attach( GTK_TABLE(midilogger_logfile_table) , midilogger_logfile_option[0] ,
+                      0 , 3 , 0 , 1 , GTK_EXPAND | GTK_FILL , 0 , 0 , 0 );
+    gtk_table_attach( GTK_TABLE(midilogger_logfile_table) , midilogger_logfile_option[1] ,
+                      0 , 3 , 1 , 2 , GTK_EXPAND | GTK_FILL , 0 , 0 , 0 );
+    gtk_table_attach( GTK_TABLE(midilogger_logfile_table) , midilogger_logfile_logfname_labelalign ,
+                      0 , 1 , 2 , 3 , GTK_FILL , 0 , 0 , 0 );
+    gtk_table_attach( GTK_TABLE(midilogger_logfile_table) , midilogger_logfile_logfname_entry ,
+                      1 , 2 , 2 , 3 , GTK_EXPAND | GTK_FILL , 0 , 0 , 0 );
+    gtk_table_attach( GTK_TABLE(midilogger_logfile_table) , midilogger_logfile_logfname_bbutton ,
+                      2 , 3 , 2 , 3 , GTK_FILL , 0 , 0 , 0 );
+    gtk_table_attach( GTK_TABLE(midilogger_logfile_table) , midilogger_logfile_option[2] ,
+                      0 , 3 , 3 , 4 , GTK_EXPAND | GTK_FILL , 0 , 0 , 0 );
+    gtk_table_attach( GTK_TABLE(midilogger_logfile_table) , midilogger_logfile_logdir_labelalign ,
+                      0 , 1 , 4 , 5 , GTK_FILL , 0 , 0 , 0 );
+    gtk_table_attach( GTK_TABLE(midilogger_logfile_table) , midilogger_logfile_logdir_entry ,
+                      1 , 2 , 4 , 5 , GTK_EXPAND | GTK_FILL , 0 , 0 , 0 );
+    gtk_table_attach( GTK_TABLE(midilogger_logfile_table) , midilogger_logfile_logdir_bbutton ,
+                      2 , 3 , 4 , 5 , GTK_FILL , 0 , 0 , 0 );
+
+    gtk_box_pack_start( GTK_BOX(content_vbox) , midilogger_frame , FALSE , FALSE , 0 );
+
+    /* playback speed settings */
+    plspeed_frame = gtk_frame_new( _("Playback speed") );
+    plspeed_vbox = gtk_vbox_new( FALSE , 2 );
+    gtk_container_set_border_width( GTK_CONTAINER(plspeed_vbox), 4 );
+    gtk_container_add( GTK_CONTAINER(plspeed_frame) , plspeed_vbox );
+    plspeed_option[0] = gtk_radio_button_new_with_label( NULL ,
+                          _("Play at normal speed") );
+    plspeed_option[1] = gtk_radio_button_new_with_label_from_widget(
+                          GTK_RADIO_BUTTON(plspeed_option[0]) ,
+                          _("Play as fast as possible") );
+    gtk_box_pack_start( GTK_BOX(plspeed_vbox) , plspeed_option[0] , FALSE , FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(plspeed_vbox) , plspeed_option[1] , FALSE , FALSE , 0 );
+
+    gtk_box_pack_start( GTK_BOX(content_vbox) , plspeed_frame , FALSE , FALSE , 0 );
+
+    /* set values */
+    /* we check this before connecting signals, it would be a useless work to
+       set/unset widget sensitivity at this time; in fact everything in the table is
+       going to lose sensitivity anyway, until i_configure_ev_enablelog_toggle is called */
+    switch ( dummcfg->dumm_logger_lfstyle )
+    {
+      case 1: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(midilogger_logfile_option[1]) , TRUE ); break;
+      case 2: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(midilogger_logfile_option[2]) , TRUE ); break;
+      case 0:
+      default: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(midilogger_logfile_option[0]) , TRUE ); break;
+    }
+    gtk_widget_set_sensitive( GTK_WIDGET(midilogger_logfile_table) , FALSE );
+    g_signal_connect( G_OBJECT(midilogger_enablelog_option[3]) , "toggled" ,
+                      G_CALLBACK(i_configure_ev_enablelog_toggle) , midilogger_logfile_table );
+    g_signal_connect( G_OBJECT(midilogger_logfile_option[2]) , "toggled" ,
+                      G_CALLBACK(i_configure_ev_logfile_toggle) , midilogger_logfile_table );
+    switch ( dummcfg->dumm_logger_enable )
+    {
+      case 1: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(midilogger_enablelog_option[1]) , TRUE ); break;
+      case 2: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(midilogger_enablelog_option[2]) , TRUE ); break;
+      case 3: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(midilogger_enablelog_option[3]) , TRUE ); break;
+      case 0:
+      default: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(midilogger_enablelog_option[0]) , TRUE ); break;
+    }
+    switch ( dummcfg->dumm_playback_speed )
+    {
+      case 1: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(plspeed_option[1]) , TRUE ); break;
+      case 0:
+      default: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(plspeed_option[0]) , TRUE ); break;
+    }
+
+    /* commit events */
+    g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_enablelog_commit) , midilogger_enablelog_option[0] );
+    g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_lfstyle_commit) , midilogger_logfile_option[0] );
+    g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_plspeed_commit) , plspeed_option[0] );
+    g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_logfname_commit) , midilogger_logfile_logfname_entry );
+    g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_logdir_commit) , midilogger_logfile_logdir_entry );
+
+  }
+  else
+  {
+    /* display "not available" information */
+    GtkWidget * info_label;
+    info_label = gtk_label_new( _("Dummy Backend not loaded or not available") );
+    gtk_box_pack_start( GTK_BOX(dumm_page_vbox) , info_label , FALSE , FALSE , 2 );
+  }
+
+  gtk_box_pack_start( GTK_BOX(dumm_page_vbox) , content_vbox , TRUE , TRUE , 2 );
+  gtk_container_add( GTK_CONTAINER(dumm_page_alignment) , dumm_page_vbox );
+}
+
+
+void i_configure_gui_tablabel_dumm( GtkWidget * dumm_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_dummy_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\">Dummy\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(dumm_page_alignment) , pagelabel_vbox );
+  gtk_widget_show_all( dumm_page_alignment );
+  return;
+}
+
+
+void i_configure_cfg_dumm_alloc( void )
+{
+  amidiplug_cfg_dumm_t * dummcfg = g_malloc(sizeof(amidiplug_cfg_dumm_t));
+  amidiplug_cfg_backend->dumm = dummcfg;
+}
+
+
+void i_configure_cfg_dumm_free( void )
+{
+  amidiplug_cfg_dumm_t * dummcfg = amidiplug_cfg_backend->dumm;
+  g_free( dummcfg->dumm_logger_logfile );
+  g_free( dummcfg->dumm_logger_logdir );
+}
+
+
+void i_configure_cfg_dumm_read( pcfg_t * cfgfile )
+{
+  amidiplug_cfg_dumm_t * dummcfg = amidiplug_cfg_backend->dumm;
+  gchar * def_logfile = g_strjoin( "" , g_get_home_dir() , "/amidi-plug.log" , NULL );
+  gchar * def_logdir = (gchar*)g_get_home_dir();
+
+  if (!cfgfile)
+  {
+    /* fluidsynth backend defaults */
+    dummcfg->dumm_logger_enable = 0;
+    dummcfg->dumm_logger_lfstyle = 0;
+    dummcfg->dumm_playback_speed = 0;
+    dummcfg->dumm_logger_logfile = g_strdup( def_logfile );
+    dummcfg->dumm_logger_logdir = g_strdup( def_logdir );
+  }
+  else
+  {
+    i_pcfg_read_integer( cfgfile , "dumm" , "dumm_logger_enable" , &dummcfg->dumm_logger_enable , 0 );
+    i_pcfg_read_integer( cfgfile , "dumm" , "dumm_logger_lfstyle" , &dummcfg->dumm_logger_lfstyle , 0 );
+    i_pcfg_read_integer( cfgfile , "dumm" , "dumm_playback_speed" , &dummcfg->dumm_playback_speed , 0 );
+    i_pcfg_read_string( cfgfile , "dumm" , "dumm_logger_logfile" , &dummcfg->dumm_logger_logfile , def_logfile );
+    i_pcfg_read_string( cfgfile , "dumm" , "dumm_logger_logdir" , &dummcfg->dumm_logger_logdir , def_logdir );
+  }
+
+  g_free( def_logfile );
+}
+
+
+void i_configure_cfg_dumm_save( pcfg_t * cfgfile )
+{
+  amidiplug_cfg_dumm_t * dummcfg = amidiplug_cfg_backend->dumm;
+
+  i_pcfg_write_integer( cfgfile , "dumm" , "dumm_logger_enable" , dummcfg->dumm_logger_enable );
+  i_pcfg_write_integer( cfgfile , "dumm" , "dumm_logger_lfstyle" , dummcfg->dumm_logger_lfstyle );
+  i_pcfg_write_integer( cfgfile , "dumm" , "dumm_playback_speed" , dummcfg->dumm_playback_speed );
+  i_pcfg_write_string( cfgfile , "dumm" , "dumm_logger_logfile" , dummcfg->dumm_logger_logfile );
+  i_pcfg_write_string( cfgfile , "dumm" , "dumm_logger_logdir" , dummcfg->dumm_logger_logdir );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_configure-dummy.h	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,36 @@
+/*
+*
+* 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_DUMMY_H
+#define _I_CONFIGURE_DUMMY_H 1
+
+#include "i_configure_private.h"
+
+
+extern amidiplug_cfg_backend_t * amidiplug_cfg_backend;
+
+void i_configure_gui_tab_dumm( GtkWidget * , gpointer , gpointer );
+void i_configure_gui_tablabel_dumm( GtkWidget * , gpointer , gpointer );
+void i_configure_cfg_dumm_alloc( void );
+void i_configure_cfg_dumm_free( void );
+void i_configure_cfg_dumm_read( pcfg_t * );
+void i_configure_cfg_dumm_save( pcfg_t * );
+
+#endif /* !_I_CONFIGURE_DUMMY_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_configure-fluidsynth.c	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,843 @@
+/*
+*
+* 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-fluidsynth.h"
+#include "backend-fluidsynth/b-fluidsynth-config.h"
+#include "backend-fluidsynth/backend-fluidsynth-icon.xpm"
+
+
+void i_configure_ev_toggle_default( GtkToggleButton *togglebutton , gpointer hbox )
+{
+  if ( gtk_toggle_button_get_active( togglebutton ) )
+    gtk_widget_set_sensitive( GTK_WIDGET(hbox) , FALSE );
+  else
+    gtk_widget_set_sensitive( GTK_WIDGET(hbox) , TRUE );
+}
+
+
+void i_configure_ev_buffertuner_valuechanged( GtkRange *buffertuner_range )
+{
+  gint bufsize_val, bufmarginsize_val;
+  gint i = (gint)gtk_range_get_value( GTK_RANGE(buffertuner_range) );
+  GtkWidget *bufsize_spin = g_object_get_data( G_OBJECT(buffertuner_range) , "bufsize_spin" );
+  GtkWidget *bufmarginsize_spin = g_object_get_data( G_OBJECT(buffertuner_range) , "bufmarginsize_spin" );
+
+  if ( i < 33 )
+  {
+    bufsize_val = 256 + (i * 16); /* linear growth of 16i - bufsize_val <= 768 */
+    if ( i > 16 )
+      bufmarginsize_val = 15 + ((i - 15) / 2); /* linear growth of i/2 */
+    else
+      bufmarginsize_val = 15; /* do not go below 10 even when bufsize < 512 */
+  }
+  else if ( i < 42 )
+  {
+    bufsize_val = 768 + ((i - 33) * 32); /* linear growth of 32i - bufsize_val <= 1024 */
+    bufmarginsize_val = 15 + ( (i - 16) / 2 ); /* linear growth of i/2 */
+  }
+  else
+  {
+    bufsize_val = 1024 + ( 32 << (i - 42) ); /* exponential growth - bufsize_val > 1024 */
+    bufmarginsize_val = 15 + ( (i - 16) / 2 ); /* linear growth of i/2 */
+  }
+
+  gtk_spin_button_set_value( GTK_SPIN_BUTTON(bufsize_spin) , bufsize_val );
+  gtk_spin_button_set_value( GTK_SPIN_BUTTON(bufmarginsize_spin) , bufmarginsize_val );
+}
+
+
+void i_configure_ev_sffile_commit( gpointer sffile_entry )
+{
+  amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn;
+  g_free( fsyncfg->fsyn_soundfont_file ); /* free previous */
+  fsyncfg->fsyn_soundfont_file = g_strdup( gtk_entry_get_text(GTK_ENTRY(sffile_entry)) );
+}
+
+
+void i_configure_ev_sfload_commit( gpointer sfload_radiobt )
+{
+  amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn;
+  GSList *group = gtk_radio_button_get_group( GTK_RADIO_BUTTON(sfload_radiobt) );
+  while ( group != NULL )
+  {
+    if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(group->data) ) )
+      fsyncfg->fsyn_soundfont_load = GPOINTER_TO_INT(g_object_get_data( G_OBJECT(group->data) , "val" ));
+    group = group->next;
+  }
+}
+
+
+void i_configure_ev_sygain_commit( gpointer gain_spinbt )
+{
+  amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn;
+  if ( GTK_WIDGET_IS_SENSITIVE(GTK_WIDGET(gain_spinbt)) )
+    fsyncfg->fsyn_synth_gain = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(gain_spinbt)) * 10);
+  else
+    fsyncfg->fsyn_synth_gain = -1;
+}
+
+
+void i_configure_ev_sypoly_commit( gpointer poly_spinbt )
+{
+  amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn;
+  if ( GTK_WIDGET_IS_SENSITIVE(GTK_WIDGET(poly_spinbt)) )
+    fsyncfg->fsyn_synth_poliphony = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(poly_spinbt)));
+  else
+    fsyncfg->fsyn_synth_poliphony = -1;
+}
+
+
+void i_configure_ev_syreverb_commit( gpointer reverb_yes_radiobt )
+{
+  amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn;
+  if ( GTK_WIDGET_IS_SENSITIVE(GTK_WIDGET(reverb_yes_radiobt)) )
+  {
+    if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(reverb_yes_radiobt) ) )
+      fsyncfg->fsyn_synth_reverb = 1;
+    else
+      fsyncfg->fsyn_synth_reverb = 0;
+  }
+  else
+    fsyncfg->fsyn_synth_reverb = -1;
+}
+
+
+void i_configure_ev_sychorus_commit( gpointer chorus_yes_radiobt )
+{
+  amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn;
+  if ( GTK_WIDGET_IS_SENSITIVE(GTK_WIDGET(chorus_yes_radiobt)) )
+  {
+    if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(chorus_yes_radiobt) ) )
+      fsyncfg->fsyn_synth_chorus = 1;
+    else
+      fsyncfg->fsyn_synth_chorus = 0;
+  }
+  else
+    fsyncfg->fsyn_synth_chorus = -1;
+}
+
+
+void i_configure_ev_sysamplerate_togglecustom( GtkToggleButton *custom_radiobt , gpointer custom_entry )
+{
+  if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(custom_radiobt) ) )
+    gtk_widget_set_sensitive( GTK_WIDGET(custom_entry) , TRUE );
+  else
+    gtk_widget_set_sensitive( GTK_WIDGET(custom_entry) , FALSE );
+}
+
+
+void i_configure_ev_sysamplerate_commit( gpointer samplerate_custom_radiobt )
+{
+  amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn;
+  if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(samplerate_custom_radiobt)) )
+  {
+    GtkWidget *customentry = g_object_get_data( G_OBJECT(samplerate_custom_radiobt) , "customentry" );
+    gint customvalue = strtol( gtk_entry_get_text(GTK_ENTRY(customentry)) , NULL , 10 );
+    if (( customvalue > 22050 ) && ( customvalue < 96000 ))
+      fsyncfg->fsyn_synth_samplerate = customvalue;
+    else
+      fsyncfg->fsyn_synth_samplerate = 44100;
+  }
+  else
+  {
+    GSList *group = gtk_radio_button_get_group( GTK_RADIO_BUTTON(samplerate_custom_radiobt) );
+    while ( group != NULL )
+    {
+      if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(group->data) ) )
+        fsyncfg->fsyn_synth_samplerate = GPOINTER_TO_INT(g_object_get_data( G_OBJECT(group->data) , "val" ));
+      group = group->next;
+    }
+  }
+}
+
+
+void i_configure_ev_bufsize_commit( gpointer bufsize_spinbt )
+{
+  amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn;
+  fsyncfg->fsyn_buffer_size = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(bufsize_spinbt)));
+}
+
+
+void i_configure_ev_bufmarginsize_commit( gpointer marginsize_spinbt )
+{
+  amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn;
+  fsyncfg->fsyn_buffer_margin = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(marginsize_spinbt)));
+}
+
+
+void i_configure_ev_bufmargininc_commit( gpointer margininc_spinbt )
+{
+  amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn;
+  fsyncfg->fsyn_buffer_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(margininc_spinbt)));
+}
+
+
+void i_configure_buffertuner_setvalue( GtkWidget * buftuner_hscale , gint bufsize )
+{
+  gint scale_value = 0;
+  if ( bufsize <= 768 )
+  {
+    scale_value = ( bufsize - 256 ) / 16;
+  }
+  else if ( bufsize <= 1024 )
+  {
+    scale_value = ( bufsize + 288 ) / 32;
+  }
+  else
+  {
+    gint tcount = 0, tval = bufsize - 1024;
+    tval = tval >> 1;
+    while ( tval > 0 )
+    {
+      tval = tval >> 1;
+      tcount++;
+    }
+    scale_value = 37 + tcount;
+  }
+  if ( scale_value < 0 )
+    scale_value = 0;
+  else if ( scale_value > 53 )
+    scale_value = 53;
+  gtk_range_set_value( GTK_RANGE(buftuner_hscale) , scale_value );
+}
+
+
+void i_configure_ev_buffertuner_default( gpointer buffertuner_hscale )
+{
+  GtkWidget *bufsize_spin = g_object_get_data( G_OBJECT(buffertuner_hscale) , "bufsize_spin" );
+  GtkWidget *bufmarginsize_spin = g_object_get_data( G_OBJECT(buffertuner_hscale) , "bufmarginsize_spin" );
+  GtkWidget *bufmargininc_spin = g_object_get_data( G_OBJECT(buffertuner_hscale) , "bufmargininc_spin" );
+  i_configure_buffertuner_setvalue( GTK_WIDGET(buffertuner_hscale) , 512 );
+  gtk_spin_button_set_value( GTK_SPIN_BUTTON(bufsize_spin) , 512 );
+  gtk_spin_button_set_value( GTK_SPIN_BUTTON(bufmarginsize_spin) , 15 );
+  gtk_spin_button_set_value( GTK_SPIN_BUTTON(bufmargininc_spin) , 18 );
+}
+
+
+void i_configure_gui_tab_fsyn( GtkWidget * fsyn_page_alignment ,
+                               gpointer backend_list_p ,
+                               gpointer commit_button )
+{
+  GtkWidget *fsyn_page_vbox;
+  GtkWidget *title_widget;
+  GtkWidget *content_vbox; /* this vbox will contain the various frames for config sections */
+  GSList * backend_list = backend_list_p;
+  gboolean fsyn_module_ok = FALSE;
+  gchar * fsyn_module_pathfilename;
+
+  fsyn_page_vbox = gtk_vbox_new( FALSE , 0 );
+
+  title_widget = i_configure_gui_draw_title( _("FLUIDSYNTH BACKEND CONFIGURATION") );
+  gtk_box_pack_start( GTK_BOX(fsyn_page_vbox) , title_widget , FALSE , FALSE , 2 );
+
+  content_vbox = gtk_vbox_new( FALSE , 2 );
+
+  /* check if the FluidSynth module is available */
+  while ( backend_list != NULL )
+  {
+    amidiplug_sequencer_backend_name_t * mn = backend_list->data;
+    if ( !strcmp( mn->name , "fluidsynth" ) )
+    {
+      fsyn_module_ok = TRUE;
+      fsyn_module_pathfilename = mn->filename;
+      break;
+    }
+    backend_list = backend_list->next;
+  }
+
+  if ( fsyn_module_ok )
+  {
+    GtkWidget *soundfont_frame, *soundfont_vbox;
+    GtkWidget *soundfont_file_label, *soundfont_file_entry, *soundfont_file_bbutton, *soundfont_file_hbox;
+    GtkWidget *soundfont_load_hsep, *soundfont_load_vbox, *soundfont_load_option[2];
+    GtkWidget *synth_frame, *synth_hbox, *synth_leftcol_vbox, *synth_rightcol_vbox;
+    GtkWidget *synth_samplerate_frame, *synth_samplerate_vbox, *synth_samplerate_option[4];
+    GtkWidget *synth_samplerate_optionhbox, *synth_samplerate_optionentry, *synth_samplerate_optionlabel;
+    GtkWidget *synth_gain_frame, *synth_gain_hbox, *synth_gain_value_hbox;
+    GtkWidget *synth_gain_value_label, *synth_gain_value_spin, *synth_gain_defcheckbt;
+    GtkWidget *synth_poly_frame, *synth_poly_hbox, *synth_poly_value_hbox;
+    GtkWidget *synth_poly_value_label, *synth_poly_value_spin, *synth_poly_defcheckbt;
+    GtkWidget *synth_reverb_frame, *synth_reverb_hbox, *synth_reverb_value_hbox;
+    GtkWidget *synth_reverb_value_option[2], *synth_reverb_defcheckbt;
+    GtkWidget *synth_chorus_frame, *synth_chorus_hbox, *synth_chorus_value_hbox;
+    GtkWidget *synth_chorus_value_option[2], *synth_chorus_defcheckbt;
+    GtkWidget *buffer_frame, *buffer_table , *buffer_vsep[4];
+    GtkWidget *buffer_tuner_label, *buffer_tuner_hscale;
+    GtkWidget *buffer_tuner_defbt, *buffer_tuner_defbt_label;
+    GtkWidget *buffer_bufsize_label, *buffer_bufsize_spin;
+    GtkWidget *buffer_marginsize_label, *buffer_marginsize_spin;
+    GtkWidget *buffer_margininc_label, *buffer_margininc_spin;
+    GtkTooltips *tips;
+
+    amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn;
+
+    tips = gtk_tooltips_new();
+    g_object_set_data_full( G_OBJECT(fsyn_page_alignment) , "tt" , tips , g_object_unref );
+
+    /* soundfont settings */
+    soundfont_frame = gtk_frame_new( _("SoundFont settings") );
+    soundfont_vbox = gtk_vbox_new( FALSE , 2 );
+    gtk_container_set_border_width( GTK_CONTAINER(soundfont_vbox), 4 );
+    gtk_container_add( GTK_CONTAINER(soundfont_frame) , soundfont_vbox );
+    /* soundfont settings - file */
+    soundfont_file_hbox = gtk_hbox_new( FALSE , 2 );
+    soundfont_file_label = gtk_label_new( _("SoundFont filename:") );
+    soundfont_file_entry = gtk_entry_new();
+    g_object_set_data( G_OBJECT(soundfont_file_entry) , "fc-act" ,
+                       GINT_TO_POINTER(GTK_FILE_CHOOSER_ACTION_OPEN) );
+    gtk_entry_set_text( GTK_ENTRY(soundfont_file_entry) , fsyncfg->fsyn_soundfont_file );
+    soundfont_file_bbutton = gtk_button_new_with_label( _("browse") );
+    g_signal_connect_swapped( G_OBJECT(soundfont_file_bbutton) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_browse_for_entry) , soundfont_file_entry );
+    gtk_box_pack_start( GTK_BOX(soundfont_file_hbox) , soundfont_file_label , FALSE , FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(soundfont_file_hbox) , soundfont_file_entry , TRUE , TRUE , 0 );
+    gtk_box_pack_start( GTK_BOX(soundfont_file_hbox) , soundfont_file_bbutton , FALSE , FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(soundfont_vbox) , soundfont_file_hbox , FALSE , FALSE , 0 );
+    /* soundfont settings - load */
+    soundfont_load_hsep = gtk_hseparator_new();
+    soundfont_load_vbox = gtk_vbox_new( FALSE , 0 );
+    soundfont_load_option[0] = gtk_radio_button_new_with_label( NULL ,
+                                 _("Load SoundFont on player start") );
+    g_object_set_data( G_OBJECT(soundfont_load_option[0]) , "val" , GINT_TO_POINTER(0) );
+    soundfont_load_option[1] = gtk_radio_button_new_with_label_from_widget(
+                                 GTK_RADIO_BUTTON(soundfont_load_option[0]) ,
+                                 _("Load SoundFont on first midifile play") );
+    g_object_set_data( G_OBJECT(soundfont_load_option[1]) , "val" , GINT_TO_POINTER(1) );
+    if ( fsyncfg->fsyn_soundfont_load == 0 )
+      gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(soundfont_load_option[0]) , TRUE );
+    else
+      gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(soundfont_load_option[1]) , TRUE );
+    gtk_box_pack_start( GTK_BOX(soundfont_load_vbox) , soundfont_load_option[0] , FALSE , FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(soundfont_load_vbox) , soundfont_load_option[1] , FALSE , FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(soundfont_vbox) , soundfont_load_hsep , FALSE , FALSE , 3 );
+    gtk_box_pack_start( GTK_BOX(soundfont_vbox) , soundfont_load_vbox , FALSE , FALSE , 0 );
+
+    gtk_box_pack_start( GTK_BOX(content_vbox) , soundfont_frame , FALSE , FALSE , 0 );
+
+    /* synth settings */
+    synth_frame = gtk_frame_new( _("Synthesizer settings") );
+    synth_hbox = gtk_hbox_new( FALSE , 4 );
+    gtk_container_set_border_width( GTK_CONTAINER(synth_hbox), 4 );
+    gtk_container_add( GTK_CONTAINER(synth_frame) , synth_hbox );
+    synth_leftcol_vbox = gtk_vbox_new( TRUE , 0 );
+    synth_rightcol_vbox = gtk_vbox_new( FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(synth_hbox) , synth_leftcol_vbox , TRUE , TRUE , 0 );
+    gtk_box_pack_start( GTK_BOX(synth_hbox) , synth_rightcol_vbox , FALSE , FALSE , 0 );
+    /* synth settings - gain */
+    synth_gain_frame = gtk_frame_new( _("gain") );
+    gtk_frame_set_label_align( GTK_FRAME(synth_gain_frame) , 0.5 , 0.5 );
+    gtk_box_pack_start( GTK_BOX(synth_leftcol_vbox) , synth_gain_frame , TRUE , TRUE , 0 );
+    synth_gain_hbox = gtk_hbox_new( TRUE , 2 );
+    gtk_container_set_border_width( GTK_CONTAINER(synth_gain_hbox), 2 );
+    gtk_container_add( GTK_CONTAINER(synth_gain_frame) , synth_gain_hbox );
+    synth_gain_defcheckbt = gtk_check_button_new_with_label( _("use default") );
+    gtk_box_pack_start( GTK_BOX(synth_gain_hbox) , synth_gain_defcheckbt , FALSE , FALSE , 0 );
+    synth_gain_value_hbox = gtk_hbox_new( FALSE , 4 );
+    synth_gain_value_label = gtk_label_new( _("value:") );
+    synth_gain_value_spin = gtk_spin_button_new_with_range( 0.0 , 10.0 , 0.1 );
+    gtk_spin_button_set_value( GTK_SPIN_BUTTON(synth_gain_value_spin) , 0.2 );
+    g_signal_connect( G_OBJECT(synth_gain_defcheckbt) , "toggled" ,
+                      G_CALLBACK(i_configure_ev_toggle_default) , synth_gain_value_hbox );
+    if ( fsyncfg->fsyn_synth_gain < 0 )
+    {
+      gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_gain_defcheckbt) , TRUE );
+    }
+    else
+    {
+      gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_gain_defcheckbt) , FALSE );
+      gtk_spin_button_set_value( GTK_SPIN_BUTTON(synth_gain_value_spin) ,
+                                 (gdouble)fsyncfg->fsyn_synth_gain / 10 );
+    }
+    gtk_box_pack_start( GTK_BOX(synth_gain_hbox) , synth_gain_value_hbox , FALSE , FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(synth_gain_value_hbox) , synth_gain_value_label , FALSE , FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(synth_gain_value_hbox) , synth_gain_value_spin , FALSE , FALSE , 0 );
+    /* synth settings - poliphony */
+    synth_poly_frame = gtk_frame_new( _("poliphony") );
+    gtk_frame_set_label_align( GTK_FRAME(synth_poly_frame) , 0.5 , 0.5 );
+    gtk_box_pack_start( GTK_BOX(synth_leftcol_vbox) , synth_poly_frame , TRUE , TRUE , 0 );
+    synth_poly_hbox = gtk_hbox_new( TRUE , 2 );
+    gtk_container_set_border_width( GTK_CONTAINER(synth_poly_hbox), 2 );
+    gtk_container_add( GTK_CONTAINER(synth_poly_frame) , synth_poly_hbox );
+    synth_poly_defcheckbt = gtk_check_button_new_with_label( _("use default") );
+    gtk_box_pack_start( GTK_BOX(synth_poly_hbox) , synth_poly_defcheckbt , FALSE , FALSE , 0 );
+    synth_poly_value_hbox = gtk_hbox_new( FALSE , 4 );
+    synth_poly_value_label = gtk_label_new( _("value:") );
+    synth_poly_value_spin = gtk_spin_button_new_with_range( 16 , 4096 , 1 );
+    gtk_spin_button_set_value( GTK_SPIN_BUTTON(synth_poly_value_spin) , 256 );
+    g_signal_connect( G_OBJECT(synth_poly_defcheckbt) , "toggled" ,
+                      G_CALLBACK(i_configure_ev_toggle_default) , synth_poly_value_hbox );
+    if ( fsyncfg->fsyn_synth_poliphony < 0 )
+    {
+      gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_poly_defcheckbt) , TRUE );
+    }
+    else
+    {
+      gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_poly_defcheckbt) , FALSE );
+      gtk_spin_button_set_value( GTK_SPIN_BUTTON(synth_poly_value_spin) ,
+                                 (gdouble)fsyncfg->fsyn_synth_poliphony );
+    }
+    gtk_box_pack_start( GTK_BOX(synth_poly_hbox) , synth_poly_value_hbox , FALSE , FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(synth_poly_value_hbox) , synth_poly_value_label , FALSE , FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(synth_poly_value_hbox) , synth_poly_value_spin , FALSE , FALSE , 0 );
+    /* synth settings - reverb */
+    synth_reverb_frame = gtk_frame_new( _("reverb") );
+    gtk_frame_set_label_align( GTK_FRAME(synth_reverb_frame) , 0.5 , 0.5 );
+    gtk_box_pack_start( GTK_BOX(synth_leftcol_vbox) , synth_reverb_frame , TRUE , TRUE , 0 );
+    synth_reverb_hbox = gtk_hbox_new( TRUE , 2 );
+    gtk_container_set_border_width( GTK_CONTAINER(synth_reverb_hbox), 2 );
+    gtk_container_add( GTK_CONTAINER(synth_reverb_frame) , synth_reverb_hbox );
+    synth_reverb_defcheckbt = gtk_check_button_new_with_label( _("use default") );
+    gtk_box_pack_start( GTK_BOX(synth_reverb_hbox) , synth_reverb_defcheckbt , FALSE , FALSE , 0 );
+    synth_reverb_value_hbox = gtk_hbox_new( TRUE , 4 );
+    synth_reverb_value_option[0] = gtk_radio_button_new_with_label( NULL , _("yes") );
+    synth_reverb_value_option[1] = gtk_radio_button_new_with_label_from_widget(
+                                     GTK_RADIO_BUTTON(synth_reverb_value_option[0]) , _("no") );
+    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_reverb_value_option[0]) , TRUE );
+    g_signal_connect( G_OBJECT(synth_reverb_defcheckbt) , "toggled" ,
+                      G_CALLBACK(i_configure_ev_toggle_default) , synth_reverb_value_hbox );
+    if ( fsyncfg->fsyn_synth_reverb < 0 )
+    {
+      gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_reverb_defcheckbt) , TRUE );
+    }
+    else
+    {
+      gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_reverb_defcheckbt) , FALSE );
+      if ( fsyncfg->fsyn_synth_reverb == 0 )
+        gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_reverb_value_option[1]) , TRUE );
+      else
+        gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_reverb_value_option[0]) , TRUE );
+    }
+    gtk_box_pack_start( GTK_BOX(synth_reverb_hbox) , synth_reverb_value_hbox , FALSE , FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(synth_reverb_value_hbox) , synth_reverb_value_option[0] , FALSE , FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(synth_reverb_value_hbox) , synth_reverb_value_option[1] , FALSE , FALSE , 0 );
+    /* synth settings - chorus */
+    synth_chorus_frame = gtk_frame_new( _("chorus") );
+    gtk_frame_set_label_align( GTK_FRAME(synth_chorus_frame) , 0.5 , 0.5 );
+    gtk_box_pack_start( GTK_BOX(synth_leftcol_vbox) , synth_chorus_frame , TRUE , TRUE , 0 );
+    synth_chorus_hbox = gtk_hbox_new( TRUE , 2 );
+    gtk_container_set_border_width( GTK_CONTAINER(synth_chorus_hbox), 2 );
+    gtk_container_add( GTK_CONTAINER(synth_chorus_frame) , synth_chorus_hbox );
+    synth_chorus_defcheckbt = gtk_check_button_new_with_label( _("use default") );
+    gtk_box_pack_start( GTK_BOX(synth_chorus_hbox) , synth_chorus_defcheckbt , FALSE , FALSE , 0 );
+    synth_chorus_value_hbox = gtk_hbox_new( TRUE , 4 );
+    synth_chorus_value_option[0] = gtk_radio_button_new_with_label( NULL , _("yes") );
+    synth_chorus_value_option[1] = gtk_radio_button_new_with_label_from_widget(
+                                     GTK_RADIO_BUTTON(synth_chorus_value_option[0]) , _("no") );
+    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_chorus_value_option[0]) , TRUE );
+    g_signal_connect( G_OBJECT(synth_chorus_defcheckbt) , "toggled" ,
+                      G_CALLBACK(i_configure_ev_toggle_default) , synth_chorus_value_hbox );
+    if ( fsyncfg->fsyn_synth_chorus < 0 )
+    {
+      gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_chorus_defcheckbt) , TRUE );
+    }
+    else
+    {
+      gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_chorus_defcheckbt) , FALSE );
+      if ( fsyncfg->fsyn_synth_chorus == 0 )
+        gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_chorus_value_option[1]) , TRUE );
+      else
+        gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_chorus_value_option[0]) , TRUE );
+    }
+    gtk_box_pack_start( GTK_BOX(synth_chorus_hbox) , synth_chorus_value_hbox , FALSE , FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(synth_chorus_value_hbox) , synth_chorus_value_option[0] , FALSE , FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(synth_chorus_value_hbox) , synth_chorus_value_option[1] , FALSE , FALSE , 0 );
+    /* synth settings - samplerate */
+    synth_samplerate_frame = gtk_frame_new( _("sample rate") );
+    gtk_frame_set_label_align( GTK_FRAME(synth_samplerate_frame) , 0.5 , 0.5 );
+    synth_samplerate_vbox = gtk_vbox_new( TRUE , 0 );
+    gtk_container_set_border_width( GTK_CONTAINER(synth_samplerate_vbox), 6 );
+    gtk_container_add( GTK_CONTAINER(synth_samplerate_frame) , synth_samplerate_vbox );
+    gtk_box_pack_start( GTK_BOX(synth_rightcol_vbox) , synth_samplerate_frame , FALSE , FALSE , 0 );
+    synth_samplerate_option[0] = gtk_radio_button_new_with_label( NULL , "22050 Hz " );
+    g_object_set_data( G_OBJECT(synth_samplerate_option[0]) , "val" , GINT_TO_POINTER(22050) );
+    synth_samplerate_option[1] = gtk_radio_button_new_with_label_from_widget(
+                                   GTK_RADIO_BUTTON(synth_samplerate_option[0]) , "44100 Hz " );
+    g_object_set_data( G_OBJECT(synth_samplerate_option[1]) , "val" , GINT_TO_POINTER(44100) );
+    synth_samplerate_option[2] = gtk_radio_button_new_with_label_from_widget(
+                                   GTK_RADIO_BUTTON(synth_samplerate_option[0]) , "96000 Hz " );
+    g_object_set_data( G_OBJECT(synth_samplerate_option[2]) , "val" , GINT_TO_POINTER(96000) );
+    synth_samplerate_option[3] = gtk_radio_button_new_with_label_from_widget(
+                                   GTK_RADIO_BUTTON(synth_samplerate_option[0]) , _("custom ") );
+    synth_samplerate_optionhbox = gtk_hbox_new( FALSE , 4 );
+    synth_samplerate_optionentry = gtk_entry_new();
+    gtk_widget_set_sensitive( GTK_WIDGET(synth_samplerate_optionentry) , FALSE );
+    gtk_entry_set_width_chars( GTK_ENTRY(synth_samplerate_optionentry) , 8 );
+    gtk_entry_set_max_length( GTK_ENTRY(synth_samplerate_optionentry) , 5 );
+    g_object_set_data( G_OBJECT(synth_samplerate_option[3]) , "customentry" , synth_samplerate_optionentry );
+    g_signal_connect( G_OBJECT(synth_samplerate_option[3]) , "toggled" ,
+                      G_CALLBACK(i_configure_ev_sysamplerate_togglecustom) , synth_samplerate_optionentry );
+    synth_samplerate_optionlabel = gtk_label_new( "Hz " );
+    gtk_box_pack_start( GTK_BOX(synth_samplerate_optionhbox) , synth_samplerate_optionentry , TRUE , TRUE , 0 );
+    gtk_box_pack_start( GTK_BOX(synth_samplerate_optionhbox) , synth_samplerate_optionlabel , FALSE , FALSE , 0 );
+    switch ( fsyncfg->fsyn_synth_samplerate )
+    {
+      case 22050:
+        gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_samplerate_option[0]) , TRUE );
+        break;
+      case 44100:
+        gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_samplerate_option[1]) , TRUE );
+        break;
+      case 96000:
+        gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_samplerate_option[2]) , TRUE );
+        break;
+      default:
+        if (( fsyncfg->fsyn_synth_samplerate > 22050 ) && ( fsyncfg->fsyn_synth_samplerate < 96000 ))
+        {
+          gchar *samplerate_value = g_strdup_printf( "%i" , fsyncfg->fsyn_synth_samplerate );
+          gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_samplerate_option[3]) , TRUE );
+          gtk_entry_set_text( GTK_ENTRY(synth_samplerate_optionentry) , samplerate_value );
+          g_free( samplerate_value );
+        }
+        else
+          gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_samplerate_option[1]) , TRUE );
+    }
+    gtk_box_pack_start( GTK_BOX(synth_samplerate_vbox) , synth_samplerate_option[0] , FALSE , FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(synth_samplerate_vbox) , synth_samplerate_option[1] , FALSE , FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(synth_samplerate_vbox) , synth_samplerate_option[2] , FALSE , FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(synth_samplerate_vbox) , synth_samplerate_option[3] , FALSE , FALSE , 0 );
+    gtk_box_pack_start( GTK_BOX(synth_samplerate_vbox) , synth_samplerate_optionhbox , FALSE , FALSE , 0 );
+
+    gtk_box_pack_start( GTK_BOX(content_vbox) , synth_frame , TRUE , TRUE , 0 );
+
+    /* buffer settings */
+    buffer_frame = gtk_frame_new( _("Buffer settings") );
+    buffer_table = gtk_table_new( 2 , 9 , FALSE );
+    gtk_table_set_col_spacings( GTK_TABLE(buffer_table) , 2 );
+    gtk_container_set_border_width( GTK_CONTAINER(buffer_table), 4 );
+    gtk_container_add( GTK_CONTAINER(buffer_frame) , buffer_table );
+    /* buffer settings - slider */
+    buffer_tuner_defbt = gtk_button_new();
+    buffer_tuner_defbt_label = gtk_label_new( "" );
+    gtk_label_set_markup( GTK_LABEL(buffer_tuner_defbt_label) ,
+                          _("<span size=\"smaller\">def</span>") );
+    gtk_container_add( GTK_CONTAINER(buffer_tuner_defbt) , buffer_tuner_defbt_label );
+    gtk_table_attach( GTK_TABLE(buffer_table) , buffer_tuner_defbt , 0 , 1 , 0 , 2 ,
+                      0 , GTK_FILL , 2 , 0 );
+    buffer_vsep[0] = gtk_vseparator_new();
+    gtk_table_attach( GTK_TABLE(buffer_table) , buffer_vsep[0] , 1 , 2 , 0 , 2 ,
+                      0 , GTK_FILL , 0 , 0 );
+    buffer_tuner_label = gtk_label_new( "" );
+    gtk_label_set_markup( GTK_LABEL(buffer_tuner_label) ,
+                          _("<span size=\"smaller\">handy buffer tuner</span>") );
+    buffer_tuner_hscale = gtk_hscale_new_with_range( 0 , 53 , 1 );
+    gtk_scale_set_draw_value( GTK_SCALE(buffer_tuner_hscale) , FALSE );
+    i_configure_buffertuner_setvalue( buffer_tuner_hscale , fsyncfg->fsyn_buffer_size );
+    gtk_table_attach( GTK_TABLE(buffer_table) , buffer_tuner_label , 2 , 3 , 0 , 1 ,
+                      GTK_EXPAND | GTK_FILL , GTK_EXPAND | GTK_FILL , 0 , 0 );
+    gtk_table_attach( GTK_TABLE(buffer_table) , buffer_tuner_hscale , 2 , 3 , 1 , 2 ,
+                      GTK_EXPAND | GTK_FILL , GTK_EXPAND | GTK_FILL , 0 , 0 );
+    buffer_vsep[1] = gtk_vseparator_new();
+    gtk_table_attach( GTK_TABLE(buffer_table) , buffer_vsep[1] , 3 , 4 , 0 , 2 ,
+                      0 , GTK_FILL , 0 , 0 );
+    /* buffer settings - size */
+    buffer_bufsize_label = gtk_label_new( "" );
+    gtk_label_set_markup( GTK_LABEL(buffer_bufsize_label) ,
+                          _("<span size=\"smaller\">size</span>") );
+    buffer_bufsize_spin = gtk_spin_button_new_with_range( 100 , 99999 , 20 );
+    gtk_spin_button_set_value( GTK_SPIN_BUTTON(buffer_bufsize_spin) ,
+                               (gdouble)fsyncfg->fsyn_buffer_size );
+    gtk_table_attach( GTK_TABLE(buffer_table) , buffer_bufsize_label , 4 , 5 , 0 , 1 ,
+                      GTK_FILL , 0 , 1 , 1 );
+    gtk_table_attach( GTK_TABLE(buffer_table) , buffer_bufsize_spin , 4 , 5 , 1 , 2 ,
+                      0 , 0 , 1 , 1 );
+    buffer_vsep[2] = gtk_vseparator_new();
+    gtk_table_attach( GTK_TABLE(buffer_table) , buffer_vsep[2] , 5 , 6 , 0 , 2 ,
+                      0 , GTK_FILL , 0 , 0 );
+    /* buffer settings - margin */
+    buffer_marginsize_label = gtk_label_new( "" );
+    gtk_label_set_markup( GTK_LABEL(buffer_marginsize_label) ,
+                          _("<span size=\"smaller\">margin</span>") );
+    buffer_marginsize_spin = gtk_spin_button_new_with_range( 0 , 100 , 1 );
+    gtk_spin_button_set_value( GTK_SPIN_BUTTON(buffer_marginsize_spin) ,
+                               (gdouble)fsyncfg->fsyn_buffer_margin );
+    gtk_table_attach( GTK_TABLE(buffer_table) , buffer_marginsize_label , 6 , 7 , 0 , 1 ,
+                      GTK_FILL , 0 , 1 , 1 );
+    gtk_table_attach( GTK_TABLE(buffer_table) , buffer_marginsize_spin , 6 , 7 , 1 , 2 ,
+                      0 , 0 , 1 , 1 );
+    buffer_vsep[3] = gtk_vseparator_new();
+    gtk_table_attach( GTK_TABLE(buffer_table) , buffer_vsep[3] , 7 , 8 , 0 , 2 ,
+                      0 , GTK_FILL , 0 , 0 );
+    /* buffer settings - increment */
+    buffer_margininc_label = gtk_label_new( "" );
+    gtk_label_set_markup( GTK_LABEL(buffer_margininc_label) ,
+                          _("<span size=\"smaller\">increment</span>") );
+    buffer_margininc_spin = gtk_spin_button_new_with_range( 6 , 1000 , 1 );
+    gtk_spin_button_set_value( GTK_SPIN_BUTTON(buffer_margininc_spin) ,
+                               (gdouble)fsyncfg->fsyn_buffer_increment );
+    gtk_table_attach( GTK_TABLE(buffer_table) , buffer_margininc_label , 8 , 9 , 0 , 1 ,
+                      GTK_FILL , 0 , 1 , 1 );
+    gtk_table_attach( GTK_TABLE(buffer_table) , buffer_margininc_spin , 8 , 9 , 1 , 2 ,
+                      0 , 0 , 1 , 1 );
+
+    g_object_set_data( G_OBJECT(buffer_tuner_hscale) , "bufsize_spin" , buffer_bufsize_spin );
+    g_object_set_data( G_OBJECT(buffer_tuner_hscale) , "bufmarginsize_spin" , buffer_marginsize_spin );
+    g_object_set_data( G_OBJECT(buffer_tuner_hscale) , "bufmargininc_spin" , buffer_margininc_spin );
+    g_signal_connect_swapped( G_OBJECT(buffer_tuner_defbt) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_buffertuner_default) , buffer_tuner_hscale );
+    g_signal_connect( G_OBJECT(buffer_tuner_hscale) , "value-changed" ,
+                      G_CALLBACK(i_configure_ev_buffertuner_valuechanged) , NULL );
+
+    gtk_box_pack_start( GTK_BOX(content_vbox) , buffer_frame , FALSE , FALSE , 0 );
+
+    /* commit events */
+    g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_sffile_commit) , soundfont_file_entry );
+    g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_sfload_commit) , soundfont_load_option[0] );
+    g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_sygain_commit) , synth_gain_value_spin );
+    g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_sypoly_commit) , synth_poly_value_spin );
+    g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_syreverb_commit) , synth_reverb_value_option[0] );
+    g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_sychorus_commit) , synth_chorus_value_option[0] );
+    g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_sysamplerate_commit) , synth_samplerate_option[3] );
+    g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_bufsize_commit) , buffer_bufsize_spin );
+    g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_bufmarginsize_commit) , buffer_marginsize_spin );
+    g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" ,
+                              G_CALLBACK(i_configure_ev_bufmargininc_commit) , buffer_margininc_spin );
+
+    gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , soundfont_file_entry ,
+                          _("* Select SoundFont *\n"
+                          "In order to play MIDI with FluidSynth, you need to specify a "
+                          "valid SoundFont file here (use absolute paths).") , "" );
+    gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , soundfont_load_option[0] ,
+                          _("* Load SoundFont on player start *\n"
+                          "Depending on your system speed, SoundFont loading in FluidSynth will "
+                          "require up to a few seconds. This is a one-time task (the soundfont "
+                          "will stay loaded until it is changed or the backend is unloaded) that "
+                          "can be done at player start, or before the first MIDI file is played "
+                          "(the latter is a better choice if you don't use your player to listen "
+                          "MIDI files only).") , "" );
+    gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , soundfont_load_option[1] ,
+                          _("* Load SoundFont on first midifile play *\n"
+                          "Depending on your system speed, SoundFont loading in FluidSynth will "
+                          "require up to a few seconds. This is a one-time task (the soundfont "
+                          "will stay loaded until it is changed or the backend is unloaded) that "
+                          "can be done at player start, or before the first MIDI file is played "
+                          "(the latter is a better choice if you don't use your player to listen "
+                          "MIDI files only).") , "" );
+    gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , synth_gain_value_spin ,
+                          _("* Synthesizer gain *\n"
+                          "From FluidSynth docs: the gain is applied to the final or master output "
+                          "of the synthesizer; it is set to a low value by default to avoid the "
+                          "saturation of the output when random MIDI files are played.") , "" );
+    gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , synth_poly_value_spin ,
+                          _("* Synthesizer polyphony *\n"
+                          "From FluidSynth docs: the polyphony defines how many voices can be played "
+                          "in parallel; the number of voices is not necessarily equivalent to the "
+                          "number of notes played simultaneously; indeed, when a note is struck on a "
+                          "specific MIDI channel, the preset on that channel may create several voices, "
+                          "for example, one for the left audio channel and one for the right audio "
+                          "channels; the number of voices activated depends on the number of instrument "
+                          "zones that fall in the correspond to the velocity and key of the played "
+                          "note.") , "" );
+    gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , synth_reverb_value_option[0] ,
+                          _("* Synthesizer reverb *\n"
+                          "From FluidSynth docs: when set to \"yes\" the reverb effects module is "
+                          "activated; note that when the reverb module is active, the amount of "
+                          "signal sent to the reverb module depends on the \"reverb send\" generator "
+                          "defined in the SoundFont.") , "" );
+    gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , synth_reverb_value_option[1] ,
+                          _("* Synthesizer reverb *\n"
+                          "From FluidSynth docs: when set to \"yes\" the reverb effects module is "
+                          "activated; note that when the reverb module is active, the amount of "
+                          "signal sent to the reverb module depends on the \"reverb send\" generator "
+                          "defined in the SoundFont.") , "" );
+    gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , synth_chorus_value_option[0] ,
+                          _("* Synthesizer chorus *\n"
+                          "From FluidSynth docs: when set to \"yes\" the chorus effects module is "
+                          "activated; note that when the chorus module is active, the amount of "
+                          "signal sent to the chorus module depends on the \"chorus send\" generator "
+                          "defined in the SoundFont.") , "" );
+    gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , synth_chorus_value_option[1] ,
+                          _("* Synthesizer chorus *\n"
+                          "From FluidSynth docs: when set to \"yes\" the chorus effects module is "
+                          "activated; note that when the chorus module is active, the amount of "
+                          "signal sent to the chorus module depends on the \"chorus send\" generator "
+                          "defined in the SoundFont.") , "" );
+    gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , synth_samplerate_option[0] ,
+                          _("* Synthesizer samplerate *\n"
+                          "The sample rate of the audio generated by the synthesizer. You can also specify "
+                          "a custom value in the interval 22050Hz-96000Hz.\n"
+                          "NOTE: the default buffer parameters are tuned for 44100Hz; changing the sample "
+                          "rate may require buffer params tuning to obtain good sound quality.") , "" );
+    gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , synth_samplerate_option[1] ,
+                          _("* Synthesizer samplerate *\n"
+                          "The sample rate of the audio generated by the synthesizer. You can also specify "
+                          "a custom value in the interval 22050Hz-96000Hz.\n"
+                          "NOTE: the default buffer parameters are tuned for 44100Hz; changing the sample "
+                          "rate may require buffer params tuning to obtain good sound quality.") , "" );
+    gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , synth_samplerate_option[2] ,
+                          _("* Synthesizer samplerate *\n"
+                          "The sample rate of the audio generated by the synthesizer. You can also specify "
+                          "a custom value in the interval 22050Hz-96000Hz.\n"
+                          "NOTE: the default buffer parameters are tuned for 44100Hz; changing the sample "
+                          "rate may require buffer params tuning to obtain good sound quality.") , "" );
+    gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , synth_samplerate_option[3] ,
+                          _("* Synthesizer samplerate *\n"
+                          "The sample rate of the audio generated by the synthesizer. You can also specify "
+                          "a custom value in the interval 22050Hz-96000Hz.\n"
+                          "NOTE: the default buffer parameters are tuned for 44100Hz; changing the sample "
+                          "rate may require buffer params tuning to obtain good sound quality.") , "" );
+    gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , buffer_tuner_defbt ,
+                          _("* FluidSynth backend buffer *\n"
+                          "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.") , "" );
+    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\" "
+                          "before resorting to manual editing of buffer parameters.\n"
+                          "However, if you want to fine-tune something and want to know what you're doing, "
+                          "you can understand how these parameters work by reading the backend code "
+                          "(b-fluidsynth.c). In short words, every amount of time "
+                          "(proportional to buffer_SIZE and sample rate), right before gathering samples, "
+                          "the buffer is resized as follows:\n"
+                          "buffer_SIZE + buffer_MARGIN + extramargin\nwhere extramargin is a value "
+                          "computed as number_of_seconds_of_playback / margin_INCREMENT .") , "" );
+    gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , buffer_marginsize_spin ,
+                          _("* FluidSynth backend buffer *\n"
+                          "It is a good idea to make buffer adjustments with the \"handy buffer tuner\" "
+                          "before resorting to manual editing of buffer parameters.\n"
+                          "However, if you want to fine-tune something and want to know what you're doing, "
+                          "you can understand how these parameters work by reading the backend code "
+                          "(b-fluidsynth.c). In short words, every amount of time "
+                          "(proportional to buffer_SIZE and sample rate), right before gathering samples, "
+                          "the buffer is resized as follows:\n"
+                          "buffer_SIZE + buffer_MARGIN + extramargin\nwhere extramargin is a value "
+                          "computed as number_of_seconds_of_playback / margin_INCREMENT .") , "" );
+    gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , buffer_margininc_spin ,
+                          _("* FluidSynth backend buffer *\n"
+                          "It is a good idea to make buffer adjustments with the \"handy buffer tuner\" "
+                          "before resorting to manual editing of buffer parameters.\n"
+                          "However, if you want to fine-tune something and want to know what you're doing, "
+                          "you can understand how these parameters work by reading the backend code "
+                          "(b-fluidsynth.c). In short words, every amount of time "
+                          "(proportional to buffer_SIZE and sample rate), right before gathering samples, "
+                          "the buffer is resized as follows:\n"
+                          "buffer_SIZE + buffer_MARGIN + extramargin\nwhere extramargin is a value "
+                          "computed as number_of_seconds_of_playback / margin_INCREMENT .") , "" );
+  }
+  else
+  {
+    /* display "not available" information */
+    GtkWidget * info_label;
+    info_label = gtk_label_new( _("FluidSynth Backend not loaded or not available") );
+    gtk_box_pack_start( GTK_BOX(fsyn_page_vbox) , info_label , FALSE , FALSE , 2 );
+  }
+
+  gtk_box_pack_start( GTK_BOX(fsyn_page_vbox) , content_vbox , TRUE , TRUE , 2 );
+  gtk_container_add( GTK_CONTAINER(fsyn_page_alignment) , fsyn_page_vbox );
+}
+
+
+void i_configure_gui_tablabel_fsyn( GtkWidget * fsyn_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_fluidsynth_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\">FluidSynth\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(fsyn_page_alignment) , pagelabel_vbox );
+  gtk_widget_show_all( fsyn_page_alignment );
+  return;
+}
+
+
+void i_configure_cfg_fsyn_alloc( void )
+{
+  amidiplug_cfg_fsyn_t * fsyncfg = g_malloc(sizeof(amidiplug_cfg_fsyn_t));
+  amidiplug_cfg_backend->fsyn = fsyncfg;
+}
+
+
+void i_configure_cfg_fsyn_free( void )
+{
+  amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn;
+  g_free( fsyncfg->fsyn_soundfont_file );
+}
+
+
+void i_configure_cfg_fsyn_read( pcfg_t * cfgfile )
+{
+  amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn;
+
+  if (!cfgfile)
+  {
+    /* fluidsynth backend defaults */
+    fsyncfg->fsyn_soundfont_file = g_strdup( "" );
+    fsyncfg->fsyn_soundfont_load = 1;
+    fsyncfg->fsyn_synth_samplerate = 44100;
+    fsyncfg->fsyn_synth_gain = -1;
+    fsyncfg->fsyn_synth_poliphony = -1;
+    fsyncfg->fsyn_synth_reverb = -1;
+    fsyncfg->fsyn_synth_chorus = -1;
+    fsyncfg->fsyn_buffer_size = 512;
+    fsyncfg->fsyn_buffer_margin = 10;
+    fsyncfg->fsyn_buffer_increment = 18;
+  }
+  else
+  {
+    i_pcfg_read_string( cfgfile , "fsyn" , "fsyn_soundfont_file" , &fsyncfg->fsyn_soundfont_file , "" );
+    i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_soundfont_load" , &fsyncfg->fsyn_soundfont_load , 1 );
+    i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_synth_samplerate" , &fsyncfg->fsyn_synth_samplerate , 44100 );
+    i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_synth_gain" , &fsyncfg->fsyn_synth_gain , -1 );
+    i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_synth_poliphony" , &fsyncfg->fsyn_synth_poliphony , -1 );
+    i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_synth_reverb" , &fsyncfg->fsyn_synth_reverb , -1 );
+    i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_synth_chorus" , &fsyncfg->fsyn_synth_chorus , -1 );
+    i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_buffer_size" , &fsyncfg->fsyn_buffer_size , 512 );
+    i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_buffer_margin" , &fsyncfg->fsyn_buffer_margin , 15 );
+    i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_buffer_increment" , &fsyncfg->fsyn_buffer_increment , 18 );
+  }
+}
+
+
+void i_configure_cfg_fsyn_save( pcfg_t * cfgfile )
+{
+  amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn;
+
+  i_pcfg_write_string( cfgfile , "fsyn" , "fsyn_soundfont_file" , fsyncfg->fsyn_soundfont_file );
+  i_pcfg_write_integer( cfgfile , "fsyn" , "fsyn_soundfont_load" , fsyncfg->fsyn_soundfont_load );
+  i_pcfg_write_integer( cfgfile , "fsyn" , "fsyn_synth_samplerate" , fsyncfg->fsyn_synth_samplerate );
+  i_pcfg_write_integer( cfgfile , "fsyn" , "fsyn_synth_gain" , fsyncfg->fsyn_synth_gain );
+  i_pcfg_write_integer( cfgfile , "fsyn" , "fsyn_synth_poliphony" , fsyncfg->fsyn_synth_poliphony );
+  i_pcfg_write_integer( cfgfile , "fsyn" , "fsyn_synth_reverb" , fsyncfg->fsyn_synth_reverb );
+  i_pcfg_write_integer( cfgfile , "fsyn" , "fsyn_synth_chorus" , fsyncfg->fsyn_synth_chorus );
+  i_pcfg_write_integer( cfgfile , "fsyn" , "fsyn_buffer_size" , fsyncfg->fsyn_buffer_size );
+  i_pcfg_write_integer( cfgfile , "fsyn" , "fsyn_buffer_margin" , fsyncfg->fsyn_buffer_margin );
+  i_pcfg_write_integer( cfgfile , "fsyn" , "fsyn_buffer_increment" , fsyncfg->fsyn_buffer_increment );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_configure-fluidsynth.h	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,36 @@
+/*
+*
+* 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_FLUIDSYNTH_H
+#define _I_CONFIGURE_FLUIDSYNTH_H 1
+
+#include "i_configure_private.h"
+
+
+extern amidiplug_cfg_backend_t * amidiplug_cfg_backend;
+
+void i_configure_gui_tab_fsyn( GtkWidget * , gpointer , gpointer );
+void i_configure_gui_tablabel_fsyn( GtkWidget * , gpointer , gpointer );
+void i_configure_cfg_fsyn_alloc( void );
+void i_configure_cfg_fsyn_free( void );
+void i_configure_cfg_fsyn_read( pcfg_t * );
+void i_configure_cfg_fsyn_save( pcfg_t * );
+
+#endif /* !_I_CONFIGURE_FLUIDSYNTH_H */
--- a/Plugins/Input/amidi-plug/i_configure.c	Mon Jul 10 04:42:53 2006 -0700
+++ b/Plugins/Input/amidi-plug/i_configure.c	Mon Jul 10 04:52:51 2006 -0700
@@ -20,189 +20,158 @@
 
 
 #include "i_configure.h"
+#include "i_configure_private.h"
+#include "i_backend.h"
+#include "i_configure-ap.h"
+#include "i_configure-alsa.h"
+#include "i_configure-fluidsynth.h"
+#include "i_configure-dummy.h"
+#include "i_utils.h"
+#include "libaudacious/beepctrl.h"
 
-/* internals */
-void i_configure_upd_portlist( void );
-void i_configure_upd_mixercardlist( void );
-gchar * i_configure_read_seq_ports_default( void );
-gboolean i_configure_ev_checktoggle( GtkTreeModel * , GtkTreePath * , GtkTreeIter * , gpointer );
-void i_configure_ev_changetoggle( GtkCellRendererToggle * , gchar * , gpointer );
+
+amidiplug_cfg_backend_t * amidiplug_cfg_backend;
+
+
+void i_configure_ev_bcancel( gpointer );
+void i_configure_ev_bok( gpointer );
+void i_configure_cfg_backend_alloc( void );
+void i_configure_cfg_backend_free( void );
+void i_configure_cfg_backend_save( void );
+void i_configure_cfg_backend_read( void );
+void i_configure_cfg_ap_save( void );
+void i_configure_cfg_ap_read( void );
+
+
+GtkWidget * i_configure_gui_draw_title( gchar * title_string )
+{
+  GtkWidget *title_label, *title_evbox, *title_frame;
+  GtkStyle * style = gtk_widget_get_default_style();
+  GdkColor title_fgcol = style->fg[GTK_STATE_SELECTED];
+  GdkColor title_bgcol = style->bg[GTK_STATE_SELECTED];
+  title_label = gtk_label_new( title_string );
+  title_evbox = gtk_event_box_new();
+  title_frame = gtk_frame_new( NULL );
+  gtk_frame_set_shadow_type( GTK_FRAME(title_frame) , GTK_SHADOW_OUT );
+  gtk_container_add( GTK_CONTAINER(title_evbox) , title_label );
+  gtk_container_set_border_width( GTK_CONTAINER(title_evbox) , 5 );
+  gtk_container_add( GTK_CONTAINER(title_frame) , title_evbox );
+  gtk_widget_modify_fg( GTK_WIDGET(title_label) , GTK_STATE_NORMAL , &title_fgcol );
+  gtk_widget_modify_bg( GTK_WIDGET(title_evbox) , GTK_STATE_NORMAL , &title_bgcol );
+  return title_frame;
+}
 
 
-void i_configure_gui( GSList * wports , GSList * scards )
+void i_configure_ev_browse_for_entry( GtkWidget * target_entry )
 {
-  GtkWidget *configwin_vbox;
-  GtkWidget *port_lv, *port_lv_sw, *port_frame;
-  GtkWidget *mixer_card_cmb_evbox, *mixer_card_cmb, *mixer_vbox, *mixer_frame;
-  GtkWidget *advanced_precalc_checkbt, *advanced_vbox, *advanced_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 );
+  GtkWidget *parent_window = gtk_widget_get_toplevel( target_entry );
+  GtkFileChooserAction act = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(target_entry),"fc-act"));
+  if ( GTK_WIDGET_TOPLEVEL(parent_window) )
+  {
+    GtkWidget *browse_dialog = gtk_file_chooser_dialog_new( _("AMIDI-Plug - select file") ,
+                                                            GTK_WINDOW(parent_window) , act ,
+                                                            GTK_STOCK_CANCEL , GTK_RESPONSE_CANCEL ,
+                                                            GTK_STOCK_OPEN , GTK_RESPONSE_ACCEPT , NULL );
+    if ( strcmp( gtk_entry_get_text(GTK_ENTRY(target_entry)) , "" ) )
+      gtk_file_chooser_set_filename( GTK_FILE_CHOOSER(browse_dialog) ,
+                                     gtk_entry_get_text(GTK_ENTRY(target_entry)) );
+    if ( gtk_dialog_run(GTK_DIALOG(browse_dialog)) == GTK_RESPONSE_ACCEPT )
+    {
+      gchar *filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(browse_dialog) );
+      gtk_entry_set_text( GTK_ENTRY(target_entry) , filename );
+      DEBUGMSG( "selected file: %s\n" , filename );
+      g_free( filename );
+    }
+    gtk_widget_destroy( browse_dialog );
+  }
+}
 
-  /* 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 );
+
+void i_configure_gui( void )
+{
+  static GtkWidget *configwin = NULL;
+  GdkGeometry cw_hints;
+  GtkWidget *configwin_vbox;
+  GtkWidget *hseparator, *hbuttonbox, *button_ok, *button_cancel;
+
+  GtkWidget *configwin_notebook;
 
-    /* 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;
-      }
-    }
+  GtkWidget *ap_page_alignment, *ap_pagelabel_alignment; /* amidi-plug */
+  GtkWidget *alsa_page_alignment, *alsa_pagelabel_alignment; /* alsa */
+  GtkWidget *dumm_page_alignment, *dumm_pagelabel_alignment; /* dummy */
+  GtkWidget *fsyn_page_alignment, *fsyn_pagelabel_alignment; /* fluidsynth */
 
-    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 );
+  GSList *backend_list = NULL, *backend_list_h = NULL;
 
-    g_string_free( portstring , TRUE );
-    /* on with next */
-    wports = wports->next;
+  if ( configwin != NULL )
+  {
+    DEBUGMSG( "config window is already open!\n" );
+    return;
   }
 
-  /* this string array is not needed anymore */
-  g_strfreev( portstring_from_cfg );
+  /* get configuration information for backends */
+  i_configure_cfg_backend_alloc();
+  i_configure_cfg_backend_read();
 
-  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 );
+  configwin = gtk_window_new( GTK_WINDOW_TOPLEVEL );
+  gtk_window_set_type_hint( GTK_WINDOW(configwin), GDK_WINDOW_TYPE_HINT_DIALOG );
+  gtk_window_set_title( GTK_WINDOW(configwin), _("AMIDI-Plug - configuration") );
+  gtk_container_set_border_width( GTK_CONTAINER(configwin), 10 );
+  g_signal_connect( G_OBJECT(configwin) , "destroy" ,
+                    G_CALLBACK(gtk_widget_destroyed) , &configwin );
+  button_ok = gtk_button_new_from_stock( GTK_STOCK_OK );
+  cw_hints.min_width = 480; cw_hints.min_height = -1;
+  gtk_window_set_geometry_hints( GTK_WINDOW(configwin) , GTK_WIDGET(configwin) ,
+                                 &cw_hints , GDK_HINT_MIN_SIZE );
 
-  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 );
+  configwin_vbox = gtk_vbox_new( FALSE , 0 );
+  gtk_container_add( GTK_CONTAINER(configwin) , configwin_vbox );
 
-  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") );
+  configwin_notebook = gtk_notebook_new();
+  gtk_notebook_set_tab_pos( GTK_NOTEBOOK(configwin_notebook) , GTK_POS_LEFT );
+  gtk_box_pack_start( GTK_BOX(configwin_vbox) , configwin_notebook , TRUE , TRUE , 2 );
 
-  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 , 2 );
+  /* GET A LIST OF BACKENDS */
+  backend_list = i_backend_list_lookup(); /* get a list of available backends */;
+  backend_list_h = backend_list;
 
-  /**********************/
-  /*** 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 );
+  /* AMIDI-PLUG PREFERENCES TAB */
+  ap_pagelabel_alignment = gtk_alignment_new( 0.5 , 0.5 , 1 , 1 );
+  ap_page_alignment = gtk_alignment_new( 0.5 , 0.5 , 1 , 1 );
+  gtk_alignment_set_padding( GTK_ALIGNMENT(ap_page_alignment) , 3 , 3 , 8 , 3 );
+  i_configure_gui_tab_ap( ap_page_alignment , backend_list , button_ok );
+  i_configure_gui_tablabel_ap( ap_pagelabel_alignment , backend_list , button_ok );
+  gtk_notebook_append_page( GTK_NOTEBOOK(configwin_notebook) ,
+                            ap_page_alignment , ap_pagelabel_alignment );
+
+  /* ALSA BACKEND CONFIGURATION TAB */
+  alsa_pagelabel_alignment = gtk_alignment_new( 0.5 , 0.5 , 1 , 1 );
+  alsa_page_alignment = gtk_alignment_new( 0.5 , 0.5 , 1 , 1 );
+  gtk_alignment_set_padding( GTK_ALIGNMENT(alsa_page_alignment) , 3 , 3 , 8 , 3 );
+  i_configure_gui_tab_alsa( alsa_page_alignment , backend_list , button_ok );
+  i_configure_gui_tablabel_alsa( alsa_pagelabel_alignment , backend_list , button_ok );
+  gtk_notebook_append_page( GTK_NOTEBOOK(configwin_notebook) ,
+                            alsa_page_alignment , alsa_pagelabel_alignment );
 
-  /* 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 , 2 );
+  /* FLUIDSYNTH BACKEND CONFIGURATION TAB */
+  fsyn_pagelabel_alignment = gtk_alignment_new( 0.5 , 0.5 , 1 , 1 );
+  fsyn_page_alignment = gtk_alignment_new( 0.5 , 0.5 , 1 , 1 );
+  gtk_alignment_set_padding( GTK_ALIGNMENT(fsyn_page_alignment) , 3 , 3 , 8 , 3 );
+  i_configure_gui_tab_fsyn( fsyn_page_alignment , backend_list , button_ok );
+  i_configure_gui_tablabel_fsyn( fsyn_pagelabel_alignment , backend_list , button_ok );
+  gtk_notebook_append_page( GTK_NOTEBOOK(configwin_notebook) ,
+                            fsyn_page_alignment , fsyn_pagelabel_alignment );
 
-  /*************************/
-  /*** ADVANCED SETTINGS ***/
-  advanced_vbox = gtk_vbox_new( FALSE , 0 );
-  gtk_container_set_border_width( GTK_CONTAINER(advanced_vbox) , 5 );
-  
-  advanced_precalc_checkbt = gtk_check_button_new_with_label( _("pre-calculate length of MIDI files in playlist") );
-  amidiplug_gui_prefs.precalc_checkbt = advanced_precalc_checkbt;
-  if ( amidiplug_cfg.length_precalc_enable )
-    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(advanced_precalc_checkbt) , TRUE );
-  gtk_box_pack_start( GTK_BOX(advanced_vbox) , advanced_precalc_checkbt , TRUE , TRUE , 0 );
+  /* DUMMY BACKEND CONFIGURATION TAB */
+  dumm_pagelabel_alignment = gtk_alignment_new( 0.5 , 0.5 , 1 , 1 );
+  dumm_page_alignment = gtk_alignment_new( 0.5 , 0.5 , 1 , 1 );
+  gtk_alignment_set_padding( GTK_ALIGNMENT(dumm_page_alignment) , 3 , 3 , 8 , 3 );
+  i_configure_gui_tab_dumm( dumm_page_alignment , backend_list , button_ok );
+  i_configure_gui_tablabel_dumm( dumm_pagelabel_alignment , backend_list , button_ok );
+  gtk_notebook_append_page( GTK_NOTEBOOK(configwin_notebook) ,
+                            dumm_page_alignment , dumm_pagelabel_alignment );
 
-  advanced_frame = gtk_frame_new( _("Advanced settings") );
-  gtk_container_add( GTK_CONTAINER(advanced_frame) , advanced_vbox );
-  gtk_box_pack_start( GTK_BOX(configwin_vbox) , advanced_frame , TRUE , TRUE , 2 );
-
+  i_backend_list_free( backend_list_h ); /* done, free the list of available backends */
 
   /* horizontal separator and buttons */
   hseparator = gtk_hseparator_new();
@@ -210,238 +179,174 @@
   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 );
+  g_signal_connect_swapped( G_OBJECT(button_cancel) , "clicked" ,
+                            G_CALLBACK(i_configure_ev_bcancel) , configwin );
   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 );
+  /* button_ok = gtk_button_new_from_stock( GTK_STOCK_OK ); created above */
+  g_signal_connect_swapped( G_OBJECT(button_ok) , "clicked" ,
+                            G_CALLBACK(i_configure_ev_bok) , configwin );
   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_tooltips_set_tip( GTK_TOOLTIPS(amidiplug_gui_prefs.config_tips) , advanced_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 "
-                        "when the the MIDI file is being played. In example, MIDI length "
-                        "will be calculated straight after adding MIDI files in a playlist. "
-                        "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_widget_show_all( amidiplug_gui_prefs.config_win );
+  gtk_widget_show_all( configwin );
 }
 
 
-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 )
+void i_configure_ev_bcancel( gpointer configwin )
 {
-  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;
+  i_configure_cfg_backend_free();
+  gtk_widget_destroy(GTK_WIDGET(configwin));
 }
 
 
-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 )
+void i_configure_ev_bok( gpointer configwin )
 {
-  /* 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();
-  
-  /* update amidiplug_cfg.length_precalc_enable using
-     the check control in the advanced settings frame */
-  if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(amidiplug_gui_prefs.precalc_checkbt) ) )
-    amidiplug_cfg.length_precalc_enable = 1;
-  else
-    amidiplug_cfg.length_precalc_enable = 0;
-
-  /* save settings */
-  i_configure_cfg_save();
-
-  gtk_widget_destroy(amidiplug_gui_prefs.config_win);
-}
-
-
-gchar * i_configure_read_seq_ports_default( void )
-{
-  FILE * fp = NULL;
-  /* first try, get seq ports from proc on card0 */
-  fp = fopen( "/proc/asound/card0/wavetableD1" , "rb" );
-  if ( fp )
+  if ( xmms_remote_is_playing(0) || xmms_remote_is_paused(0) )
   {
-    gchar buffer[100];
-    while ( !feof( fp ) )
+    /* we can't change settings while a song is being played */
+    static GtkWidget * configwin_warnmsg = NULL;
+    if ( configwin_warnmsg != NULL )
     {
-      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] );
-      }
+      gdk_window_raise( configwin_warnmsg->window );
     }
-    fclose( fp );
-  }
-
-  /* second option: do not set ports at all, let the user
-     select the right ones in the nice preferences dialog :) */
-  return g_strdup( "" );
-}
-
-
-void i_configure_cfg_read( void )
-{
-  ConfigDb *cfgfile;
-  cfgfile = bmp_cfg_db_open();
-
-  if (!cfgfile)
-  {
-    /* use defaults */
-    amidiplug_cfg.seq_writable_ports = i_configure_read_seq_ports_default();
-    amidiplug_cfg.mixer_card_id = 0;
-    amidiplug_cfg.mixer_control_name = g_strdup( "Synth" );
-    amidiplug_cfg.mixer_control_id = 0;
-    amidiplug_cfg.length_precalc_enable = 0;
+    else
+    {
+      configwin_warnmsg = (GtkWidget*)i_message_gui( _("AMIDI-Plug message") ,
+                                        _("Please stop the player before changing AMIDI-Plug settings.") ,
+                                        AMIDIPLUG_MESSAGE_WARN , configwin );
+      g_signal_connect( G_OBJECT(configwin_warnmsg) , "destroy" ,
+                        G_CALLBACK(gtk_widget_destroyed) , &configwin_warnmsg );
+      gtk_widget_show_all( configwin_warnmsg );
+    }
   }
   else
   {
-    if ( !bmp_cfg_db_get_string( cfgfile , "amidi-plug" , "writable_ports" , &amidiplug_cfg.seq_writable_ports ) )
-      amidiplug_cfg.seq_writable_ports = i_configure_read_seq_ports_default(); /* default value */
-
-    if ( !bmp_cfg_db_get_int( cfgfile , "amidi-plug" , "mixer_card_id" , &amidiplug_cfg.mixer_card_id ) )
-      amidiplug_cfg.mixer_card_id = 0; /* default value */
+    DEBUGMSG( "saving configuration...\n" );
+    i_configure_cfg_ap_save(); /* save amidiplug settings */
+    i_configure_cfg_backend_save(); /* save backend settings */
+    i_configure_cfg_backend_free(); /* free backend settings */
+    DEBUGMSG( "configuration saved\n" );
 
-    if ( !bmp_cfg_db_get_string( cfgfile , "amidi-plug" , "mixer_control_name" , &amidiplug_cfg.mixer_control_name ) )
-      amidiplug_cfg.mixer_control_name = g_strdup( "Synth" ); /* default value */
+    /* check if a different backend has been selected */
+    if ( strcmp( amidiplug_cfg_ap.ap_seq_backend , backend.name ) )
+    {
+      DEBUGMSG( "a new backend has been selected, unloading previous and loading the new one\n" );
+      i_backend_unload(); /* unload previous backend */
+      i_backend_load( amidiplug_cfg_ap.ap_seq_backend ); /* load new backend */
+    }
+    else /* same backend, just reload updated configuration */
+    {
+      DEBUGMSG( "the selected backend is already loaded, so just perform backend cleanup and reinit\n" );
+      backend.cleanup();
+      backend.init();
+    }
 
-    if ( !bmp_cfg_db_get_int( cfgfile , "amidi-plug" , "mixer_control_id" , &amidiplug_cfg.mixer_control_id ) )
-      amidiplug_cfg.mixer_control_id = 0; /* default value */
-
-    if ( !bmp_cfg_db_get_int( cfgfile , "amidi-plug" , "length_precalc_enable" , &amidiplug_cfg.length_precalc_enable ) )
-      amidiplug_cfg.length_precalc_enable = 0; /* default value */
-
-    bmp_cfg_db_close(cfgfile);
+    gtk_widget_destroy(GTK_WIDGET(configwin));
   }
 }
 
 
-void i_configure_cfg_save( void )
+void i_configure_cfg_backend_alloc( void )
+{
+  amidiplug_cfg_backend = g_malloc(sizeof(amidiplug_cfg_backend));
+
+  i_configure_cfg_alsa_alloc(); /* alloc alsa backend configuration */
+  i_configure_cfg_fsyn_alloc(); /* alloc fluidsynth backend configuration */
+  i_configure_cfg_dumm_alloc(); /* alloc dummy backend configuration */
+}
+
+
+void i_configure_cfg_backend_free( void )
+{
+  i_configure_cfg_alsa_free(); /* free alsa backend configuration */
+  i_configure_cfg_fsyn_free(); /* free fluidsynth backend configuration */
+  i_configure_cfg_dumm_free(); /* free dummy backend configuration */
+
+  g_free( amidiplug_cfg_backend );
+}
+
+
+void i_configure_cfg_backend_read( void )
 {
-  ConfigDb *cfgfile;
-  cfgfile = bmp_cfg_db_open();
+  pcfg_t *cfgfile;
+
+  gchar * config_pathfilename = g_strjoin( "" , g_get_home_dir() , "/" ,
+                                           PLAYER_LOCALRCDIR , "/amidi-plug.conf" , NULL );
+  cfgfile = i_pcfg_new_from_file( config_pathfilename );
+
+  i_configure_cfg_alsa_read( cfgfile ); /* get alsa backend configuration */
+  i_configure_cfg_fsyn_read( cfgfile ); /* get fluidsynth backend configuration */
+  i_configure_cfg_dumm_read( cfgfile ); /* get dummy backend configuration */
+
+  if ( cfgfile != NULL )
+    i_pcfg_free(cfgfile);
+
+  g_free( config_pathfilename );
+}
+
+
+void i_configure_cfg_backend_save( void )
+{
+  pcfg_t *cfgfile;
+  gchar * config_pathfilename = g_strjoin( "" , g_get_home_dir() , "/" ,
+                                           PLAYER_LOCALRCDIR , "/amidi-plug.conf" , NULL );
+  cfgfile = i_pcfg_new_from_file( config_pathfilename );
+
+  if (!cfgfile)
+    cfgfile = i_pcfg_new();
 
-  bmp_cfg_db_set_string( cfgfile , "amidi-plug" , "writable_ports" , amidiplug_cfg.seq_writable_ports );
-  bmp_cfg_db_set_int( cfgfile , "amidi-plug" , "mixer_card_id" , amidiplug_cfg.mixer_card_id );
-  bmp_cfg_db_set_string( cfgfile , "amidi-plug" , "mixer_control_name" , amidiplug_cfg.mixer_control_name );
-  bmp_cfg_db_set_int( cfgfile , "amidi-plug" , "mixer_control_id" , amidiplug_cfg.mixer_control_id );
-  bmp_cfg_db_set_int( cfgfile , "amidi-plug" , "length_precalc_enable" , amidiplug_cfg.length_precalc_enable );
+  i_configure_cfg_alsa_save( cfgfile ); /* save alsa backend configuration */
+  i_configure_cfg_fsyn_save( cfgfile ); /* save fluidsynth backend configuration */
+  i_configure_cfg_dumm_save( cfgfile ); /* save dummy backend configuration */
+
+  i_pcfg_write_to_file( cfgfile , config_pathfilename );
+  i_pcfg_free( cfgfile );
+  g_free( config_pathfilename );
+}
+
+
+/* read only the amidi-plug part of configuration */
+void i_configure_cfg_ap_read( void )
+{
+  pcfg_t *cfgfile;
+  gchar * config_pathfilename = g_strjoin( "" , g_get_home_dir() , "/" ,
+                                           PLAYER_LOCALRCDIR , "/amidi-plug.conf" , NULL );
+  cfgfile = i_pcfg_new_from_file( config_pathfilename );
 
-  bmp_cfg_db_close(cfgfile);
+  if (!cfgfile)
+  {
+    /* amidi-plug defaults */
+    amidiplug_cfg_ap.ap_seq_backend = g_strdup( "alsa" );
+    amidiplug_cfg_ap.ap_opts_length_precalc = 0;
+  }
+  else
+  {
+    i_pcfg_read_string( cfgfile , "general" , "ap_seq_backend" ,
+                        &amidiplug_cfg_ap.ap_seq_backend , "alsa" );
+    i_pcfg_read_integer( cfgfile , "general" , "ap_opts_length_precalc" ,
+                         &amidiplug_cfg_ap.ap_opts_length_precalc , 0 );
+    i_pcfg_free( cfgfile );
+  }
+
+  g_free( config_pathfilename );
 }
+
+
+void i_configure_cfg_ap_save( void )
+{
+  pcfg_t *cfgfile;
+  gchar * config_pathfilename = g_strjoin( "" , g_get_home_dir() , "/" ,
+                                           PLAYER_LOCALRCDIR , "/amidi-plug.conf" , NULL );
+  cfgfile = i_pcfg_new_from_file( config_pathfilename );
+
+  if (!cfgfile)
+    cfgfile = i_pcfg_new();
+
+  /* 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_length_precalc" , amidiplug_cfg_ap.ap_opts_length_precalc );
+
+  i_pcfg_write_to_file( cfgfile , config_pathfilename );
+  i_pcfg_free( cfgfile );
+  g_free( config_pathfilename );
+}
--- a/Plugins/Input/amidi-plug/i_configure.h	Mon Jul 10 04:42:53 2006 -0700
+++ b/Plugins/Input/amidi-plug/i_configure.h	Mon Jul 10 04:52:51 2006 -0700
@@ -22,59 +22,22 @@
 #define _I_CONFIGURE_H 1
 
 #include "i_common.h"
-#include <gtk/gtk.h>
-#include "libaudacious/configdb.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;
-  gint length_precalc_enable;
+  gchar *	ap_seq_backend;
+  gint		ap_opts_length_precalc;
 }
-amidiplug_cfg_t;
+amidiplug_cfg_ap_t;
 
-extern amidiplug_cfg_t amidiplug_cfg;
 
-typedef struct
-{
-  GtkWidget * config_win;
-  GtkWidget * port_treeview;
-  GtkWidget * mixercard_combo;
-  GtkWidget * precalc_checkbt;
-  GtkTooltips * config_tips;
-}
-amidiplug_gui_prefs_t;
+extern amidiplug_cfg_ap_t amidiplug_cfg_ap;
+
 
-static amidiplug_gui_prefs_t amidiplug_gui_prefs = { NULL , 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( void );
+void i_configure_gui( void );
+void i_configure_cfg_ap_read( void );
+void i_configure_cfg_ap_save( void );
 
 
 #endif /* !_I_CONFIGURE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_configure_private.h	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,42 @@
+/*
+*
+* 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_PRIVATE_H
+#define _I_CONFIGURE_PRIVATE_H 1
+
+#include "i_common.h"
+#include "i_backend.h"
+#include "pcfg/i_pcfg.h"
+#include <gtk/gtk.h>
+
+
+typedef struct
+{
+  gpointer alsa; /* advanced linux sound architecture */
+  gpointer fsyn; /* fluidsynth */
+  gpointer dumm; /* dummy */
+}
+amidiplug_cfg_backend_t;
+
+
+GtkWidget * i_configure_gui_draw_title( gchar * );
+void i_configure_ev_browse_for_entry( GtkWidget * );
+
+#endif /* !_I_CONFIGURE_PRIVATE_H */
--- a/Plugins/Input/amidi-plug/i_fileinfo.c	Mon Jul 10 04:42:53 2006 -0700
+++ b/Plugins/Input/amidi-plug/i_fileinfo.c	Mon Jul 10 04:52:51 2006 -0700
@@ -19,26 +19,24 @@
 */
 
 
+#include <gtk/gtk.h>
 #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 };
-
 
 void i_fileinfo_ev_destroy( GtkWidget * win , gpointer mf )
 {
   i_midi_free( (midifile_t *)mf );
   g_free( mf );
-  amidiplug_gui_fileinfo.fileinfo_win = NULL;
 }
 
 
-void i_fileinfo_ev_close( void )
+void i_fileinfo_ev_close( GtkWidget * button , gpointer fileinfowin )
 {
-  gtk_widget_destroy( amidiplug_gui_fileinfo.fileinfo_win );
+  gtk_widget_destroy( GTK_WIDGET(fileinfowin) );
 }
 
 
@@ -63,6 +61,7 @@
 
 void i_fileinfo_gui( gchar * filename )
 {
+  static GtkWidget *fileinfowin = NULL;
   GtkWidget *fileinfowin_vbox;
   GtkWidget *title_hbox , *title_icon_image , *title_name_f_label , *title_name_v_entry;
   GtkWidget *info_frame , *info_table;
@@ -73,11 +72,13 @@
   GString *value_gstring;
   gchar *title , *filename_utf8;
   gint bpm = 0, wavg_bpm = 0;
-  midifile_t * mf = g_malloc(sizeof(midifile_t));
+  midifile_t *mf;
 
-  if ( amidiplug_gui_fileinfo.fileinfo_win )
+  if ( fileinfowin )
     return;
 
+  mf = g_malloc(sizeof(midifile_t));
+
   /****************** midifile parser ******************/
   if ( !i_midi_parse_from_filename( filename , mf ) )
     return;
@@ -86,16 +87,16 @@
   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) , mf );
-  gtk_container_set_border_width( GTK_CONTAINER(amidiplug_gui_fileinfo.fileinfo_win), 10 );
+  fileinfowin = gtk_window_new( GTK_WINDOW_TOPLEVEL );
+  gtk_window_set_type_hint( GTK_WINDOW(fileinfowin), GDK_WINDOW_TYPE_HINT_DIALOG );
+  gtk_window_set_resizable( GTK_WINDOW(fileinfowin) , FALSE );
+  gtk_window_set_position( GTK_WINDOW(fileinfowin) , GTK_WIN_POS_CENTER );
+  g_signal_connect( G_OBJECT(fileinfowin) , "destroy" , G_CALLBACK(i_fileinfo_ev_destroy) , mf );
+  g_signal_connect( G_OBJECT(fileinfowin) , "destroy" , G_CALLBACK(gtk_widget_destroyed) , &fileinfowin );
+  gtk_container_set_border_width( GTK_CONTAINER(fileinfowin), 10 );
 
   fileinfowin_vbox = gtk_vbox_new( FALSE , 10 );
-  gtk_container_add( GTK_CONTAINER(amidiplug_gui_fileinfo.fileinfo_win) , fileinfowin_vbox );
+  gtk_container_add( GTK_CONTAINER(fileinfowin) , fileinfowin_vbox );
 
   /* pango attributes */
   pangoattrlist = pango_attr_list_new();
@@ -165,7 +166,7 @@
   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 );
+  g_signal_connect( G_OBJECT(footer_bclose) , "clicked" , G_CALLBACK(i_fileinfo_ev_close) , fileinfowin );
   gtk_container_add( GTK_CONTAINER(footer_hbbox) , footer_bclose );
   gtk_box_pack_start( GTK_BOX(fileinfowin_vbox) , footer_hbbox , FALSE , FALSE , 0 );
 
@@ -185,7 +186,7 @@
     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);
+  gtk_window_set_title( GTK_WINDOW(fileinfowin) , title);
   g_free(title);
   /* set the text for the filename header too */
   gtk_entry_set_text( GTK_ENTRY(title_name_v_entry) , filename_utf8 );
@@ -193,5 +194,5 @@
   g_free(filename_utf8);
 
   gtk_widget_grab_focus( GTK_WIDGET(footer_bclose) );
-  gtk_widget_show_all( amidiplug_gui_fileinfo.fileinfo_win );
+  gtk_widget_show_all( fileinfowin );
 }
--- a/Plugins/Input/amidi-plug/i_fileinfo.h	Mon Jul 10 04:42:53 2006 -0700
+++ b/Plugins/Input/amidi-plug/i_fileinfo.h	Mon Jul 10 04:52:51 2006 -0700
@@ -22,16 +22,8 @@
 #define _I_FILEINFO_H 1
 
 #include "i_common.h"
-#include <gtk/gtk.h>
-#include "libaudacious/util.h"
 
 
-typedef struct
-{
-  GtkWidget * fileinfo_win;
-}
-amidiplug_gui_fileinfo_t;
-
 void i_fileinfo_gui( gchar * );
 
 
--- a/Plugins/Input/amidi-plug/i_midi.h	Mon Jul 10 04:42:53 2006 -0700
+++ b/Plugins/Input/amidi-plug/i_midi.h	Mon Jul 10 04:52:51 2006 -0700
@@ -22,36 +22,202 @@
 #define _I_MIDI_H 1
 
 #include "i_common.h"
-#include <alsa/asoundlib.h>
+#include "i_midievent.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
+
+/* sequencer event type, got from ALSA header alsa/seq_event.h */
+enum snd_seq_event_type {
+  /* system status; event data type = #snd_seq_result_t */
+  SND_SEQ_EVENT_SYSTEM = 0,
+  /* returned result status; event data type = #snd_seq_result_t */
+  SND_SEQ_EVENT_RESULT,
+
+  /* note on and off with duration; event data type = #snd_seq_ev_note_t */
+  SND_SEQ_EVENT_NOTE = 5,
+  /* note on; event data type = #snd_seq_ev_note_t */
+  SND_SEQ_EVENT_NOTEON,
+  /* note off; event data type = #snd_seq_ev_note_t */
+  SND_SEQ_EVENT_NOTEOFF,
+  /* key pressure change (aftertouch); event data type = #snd_seq_ev_note_t */
+  SND_SEQ_EVENT_KEYPRESS,
+
+  /* controller; event data type = #snd_seq_ev_ctrl_t */
+  SND_SEQ_EVENT_CONTROLLER = 10,
+  /* program change; event data type = #snd_seq_ev_ctrl_t */
+  SND_SEQ_EVENT_PGMCHANGE,
+  /* channel pressure; event data type = #snd_seq_ev_ctrl_t */
+  SND_SEQ_EVENT_CHANPRESS,
+  /* pitchwheel; event data type = #snd_seq_ev_ctrl_t; data is from -8192 to 8191) */
+  SND_SEQ_EVENT_PITCHBEND,
+  /* 14 bit controller value; event data type = #snd_seq_ev_ctrl_t */
+  SND_SEQ_EVENT_CONTROL14,
+  /* 14 bit NRPN;  event data type = #snd_seq_ev_ctrl_t */
+  SND_SEQ_EVENT_NONREGPARAM,
+  /* 14 bit RPN; event data type = #snd_seq_ev_ctrl_t */
+  SND_SEQ_EVENT_REGPARAM,
+
+  /* SPP with LSB and MSB values; event data type = #snd_seq_ev_ctrl_t */
+  SND_SEQ_EVENT_SONGPOS = 20,
+  /* Song Select with song ID number; event data type = #snd_seq_ev_ctrl_t */
+  SND_SEQ_EVENT_SONGSEL,
+  /* midi time code quarter frame; event data type = #snd_seq_ev_ctrl_t */
+  SND_SEQ_EVENT_QFRAME,
+  /* SMF Time Signature event; event data type = #snd_seq_ev_ctrl_t */
+  SND_SEQ_EVENT_TIMESIGN,
+  /* SMF Key Signature event; event data type = #snd_seq_ev_ctrl_t */
+  SND_SEQ_EVENT_KEYSIGN,
 
+  /* MIDI Real Time Start message; event data type = #snd_seq_ev_queue_control_t */
+  SND_SEQ_EVENT_START = 30,
+  /* MIDI Real Time Continue message; event data type = #snd_seq_ev_queue_control_t */
+  SND_SEQ_EVENT_CONTINUE,
+  /* MIDI Real Time Stop message; event data type = #snd_seq_ev_queue_control_t */
+  SND_SEQ_EVENT_STOP,
+  /* Set tick queue position; event data type = #snd_seq_ev_queue_control_t */
+  SND_SEQ_EVENT_SETPOS_TICK,
+  /* Set real-time queue position; event data type = #snd_seq_ev_queue_control_t */
+  SND_SEQ_EVENT_SETPOS_TIME,
+  /* (SMF) Tempo event; event data type = #snd_seq_ev_queue_control_t */
+  SND_SEQ_EVENT_TEMPO,
+  /* MIDI Real Time Clock message; event data type = #snd_seq_ev_queue_control_t */
+  SND_SEQ_EVENT_CLOCK,
+  /* MIDI Real Time Tick message; event data type = #snd_seq_ev_queue_control_t */
+  SND_SEQ_EVENT_TICK,
+  /* Queue timer skew; event data type = #snd_seq_ev_queue_control_t */
+  SND_SEQ_EVENT_QUEUE_SKEW,
+  /* Sync position changed; event data type = #snd_seq_ev_queue_control_t */
+  SND_SEQ_EVENT_SYNC_POS,
+
+  /* Tune request; event data type = none */
+  SND_SEQ_EVENT_TUNE_REQUEST = 40,
+  /* Reset to power-on state; event data type = none */
+  SND_SEQ_EVENT_RESET,
+  /* Active sensing event; event data type = none */
+  SND_SEQ_EVENT_SENSING,
+
+  /* Echo-back event; event data type = any type */
+  SND_SEQ_EVENT_ECHO = 50,
+  /* OSS emulation raw event; event data type = any type */
+  SND_SEQ_EVENT_OSS,
+
+  /* New client has connected; event data type = #snd_seq_addr_t */
+  SND_SEQ_EVENT_CLIENT_START = 60,
+  /* Client has left the system; event data type = #snd_seq_addr_t */
+  SND_SEQ_EVENT_CLIENT_EXIT,
+  /* Client status/info has changed; event data type = #snd_seq_addr_t */
+  SND_SEQ_EVENT_CLIENT_CHANGE,
+  /* New port was created; event data type = #snd_seq_addr_t */
+  SND_SEQ_EVENT_PORT_START,
+  /* Port was deleted from system; event data type = #snd_seq_addr_t */
+  SND_SEQ_EVENT_PORT_EXIT,
+  /* Port status/info has changed; event data type = #snd_seq_addr_t */
+  SND_SEQ_EVENT_PORT_CHANGE,
+
+  /* Ports connected; event data type = #snd_seq_connect_t */
+  SND_SEQ_EVENT_PORT_SUBSCRIBED,
+  /* Ports disconnected; event data type = #snd_seq_connect_t */
+  SND_SEQ_EVENT_PORT_UNSUBSCRIBED,
 
-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];
+  /* Sample select; event data type = #snd_seq_ev_sample_control_t */
+  SND_SEQ_EVENT_SAMPLE = 70,
+  /* Sample cluster select; event data type = #snd_seq_ev_sample_control_t */
+  SND_SEQ_EVENT_SAMPLE_CLUSTER,
+  /* voice start */
+  SND_SEQ_EVENT_SAMPLE_START,
+  /* voice stop */
+  SND_SEQ_EVENT_SAMPLE_STOP,
+  /* playback frequency */
+  SND_SEQ_EVENT_SAMPLE_FREQ,
+  /* volume and balance */
+  SND_SEQ_EVENT_SAMPLE_VOLUME,
+  /* sample loop */
+  SND_SEQ_EVENT_SAMPLE_LOOP,
+  /* sample position */
+  SND_SEQ_EVENT_SAMPLE_POSITION,
+  /* private (hardware dependent) event */
+  SND_SEQ_EVENT_SAMPLE_PRIVATE1,
+
+  /* user-defined event; event data type = any (fixed size) */
+  SND_SEQ_EVENT_USR0 = 90,
+  /* user-defined event; event data type = any (fixed size) */
+  SND_SEQ_EVENT_USR1,
+  /* user-defined event; event data type = any (fixed size) */
+  SND_SEQ_EVENT_USR2,
+  /* user-defined event; event data type = any (fixed size) */
+  SND_SEQ_EVENT_USR3,
+  /* user-defined event; event data type = any (fixed size) */
+  SND_SEQ_EVENT_USR4,
+  /* user-defined event; event data type = any (fixed size) */
+  SND_SEQ_EVENT_USR5,
+  /* user-defined event; event data type = any (fixed size) */
+  SND_SEQ_EVENT_USR6,
+  /* user-defined event; event data type = any (fixed size) */
+  SND_SEQ_EVENT_USR7,
+  /* user-defined event; event data type = any (fixed size) */
+  SND_SEQ_EVENT_USR8,
+  /* user-defined event; event data type = any (fixed size) */
+  SND_SEQ_EVENT_USR9,
+
+  /* begin of instrument management */
+  SND_SEQ_EVENT_INSTR_BEGIN = 100,
+  /* end of instrument management */
+  SND_SEQ_EVENT_INSTR_END,
+  /* query instrument interface info */
+  SND_SEQ_EVENT_INSTR_INFO,
+  /* result of instrument interface info */
+  SND_SEQ_EVENT_INSTR_INFO_RESULT,
+  /* query instrument format info */
+  SND_SEQ_EVENT_INSTR_FINFO,
+  /* result of instrument format info */
+  SND_SEQ_EVENT_INSTR_FINFO_RESULT,
+  /* reset instrument instrument memory */
+  SND_SEQ_EVENT_INSTR_RESET,
+  /* get instrument interface status */
+  SND_SEQ_EVENT_INSTR_STATUS,
+  /* result of instrument interface status */
+  SND_SEQ_EVENT_INSTR_STATUS_RESULT,
+  /* put an instrument to port */
+  SND_SEQ_EVENT_INSTR_PUT,
+  /* get an instrument from port */
+  SND_SEQ_EVENT_INSTR_GET,
+  /* result of instrument query */
+  SND_SEQ_EVENT_INSTR_GET_RESULT,
+  /* free instrument(s) */
+  SND_SEQ_EVENT_INSTR_FREE,
+ /* get instrument list */
+  SND_SEQ_EVENT_INSTR_LIST,
+  /* result of instrument list */
+  SND_SEQ_EVENT_INSTR_LIST_RESULT,
+  /* set cluster parameters */
+  SND_SEQ_EVENT_INSTR_CLUSTER,
+  /* get cluster parameters */
+  SND_SEQ_EVENT_INSTR_CLUSTER_GET,
+  /* result of cluster parameters */
+  SND_SEQ_EVENT_INSTR_CLUSTER_RESULT,
+  /* instrument change */
+  SND_SEQ_EVENT_INSTR_CHANGE,
+
+  /* system exclusive data (variable length);  event data type = #snd_seq_ev_ext_t */
+  SND_SEQ_EVENT_SYSEX = 130,
+  /* error event;  event data type = #snd_seq_ev_ext_t */
+  SND_SEQ_EVENT_BOUNCE,
+  /* reserved for user apps;  event data type = #snd_seq_ev_ext_t */
+  SND_SEQ_EVENT_USR_VAR0 = 135,
+  /* reserved for user apps; event data type = #snd_seq_ev_ext_t */
+  SND_SEQ_EVENT_USR_VAR1,
+  /* reserved for user apps; event data type = #snd_seq_ev_ext_t */
+  SND_SEQ_EVENT_USR_VAR2,
+  /* reserved for user apps; event data type = #snd_seq_ev_ext_t */
+  SND_SEQ_EVENT_USR_VAR3,
+  /* reserved for user apps; event data type = #snd_seq_ev_ext_t */
+  SND_SEQ_EVENT_USR_VAR4,
+
+  /* NOP; ignored in any case */
+  SND_SEQ_EVENT_NONE = 255
 };
 
-typedef struct midievent_stru midievent_t;
 
 typedef struct
 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/i_midievent.h	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,40 @@
+/*
+*
+* 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_MIDIEVENT_H
+#define _I_MIDIEVENT_H 1
+
+struct midievent_stru {
+  struct midievent_stru * next;		/* linked list */
+  guchar type;				/* SND_SEQ_EVENT_xxx */
+  guchar port;				/* port index */
+  guint tick;
+  guint tick_real;			/* tick with custom offset */
+  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;
+
+#endif /* !_I_MIDIEVENT_H */
--- a/Plugins/Input/amidi-plug/i_seq.c	Mon Jul 10 04:42:53 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,493 +0,0 @@
-/*
-*
-* 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() )
-  {
-    sc.seq = NULL;
-    return 0;
-  }
-
-  if ( !i_seq_port_create() )
-  {
-    i_seq_close();
-    sc.seq = NULL;
-    return 0;
-  }
-
-  if ( !i_seq_queue_create() )
-  {
-    i_seq_close();
-    sc.seq = NULL;
-    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();
-    sc.seq = NULL;
-    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_find_selem( snd_mixer_t * mixer_h , gchar * mixer_card ,
-                             gchar * mixer_control_name , gint mixer_control_id ,
-                             snd_mixer_elem_t ** mixer_elem )
-{
-  snd_mixer_selem_id_t * mixer_selem_id = NULL;
-
-  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_attach( mixer_h , mixer_card );
-  snd_mixer_selem_register( mixer_h , NULL , NULL);
-  snd_mixer_load( mixer_h );
-
-  /* assign the mixer element (can be NULL if there is no such element) */
-  *mixer_elem = snd_mixer_find_selem( mixer_h , mixer_selem_id );
-
-  /* always return 1 here */
-  return 1;
-}
-
-
-gint i_seq_mixer_get_volume( gint * left_volume , gint * right_volume ,
-                            gchar * mixer_card , gchar * mixer_control_name , gint mixer_control_id )
-{
-  snd_mixer_t * mixer_h = NULL;
-  snd_mixer_elem_t * mixer_elem = NULL;
-
-  if ( snd_mixer_open( &mixer_h , 0 ) > -1 )
-    i_seq_mixer_find_selem( mixer_h , mixer_card , mixer_control_name , mixer_control_id , &mixer_elem );
-  else
-    mixer_h = NULL;
-
-  if ( ( mixer_elem ) && ( snd_mixer_selem_has_playback_volume( mixer_elem ) ) )
-  {
-    glong pv_min , pv_max , pv_range;
-    glong lc, rc;
-
-    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 ) )
-      {
-        snd_mixer_selem_get_playback_volume( mixer_elem , SND_MIXER_SCHN_FRONT_LEFT , &lc );
-        /* convert the range to 0-100 (for the case that pv_range is not 0-100 already) */
-        *left_volume = (gint)(((lc - pv_min) * 100) / pv_range);
-        DEBUGMSG( "GET VOLUME requested, get left channel (%i)\n" , *left_volume );
-      }
-      if ( snd_mixer_selem_has_playback_channel( mixer_elem , SND_MIXER_SCHN_FRONT_RIGHT ) )
-      {
-        snd_mixer_selem_get_playback_volume( mixer_elem , SND_MIXER_SCHN_FRONT_RIGHT , &rc );
-        /* convert the range to 0-100 (for the case that pv_range is not 0-100 already) */
-        *right_volume = (gint)(((rc - pv_min) * 100) / pv_range);
-        DEBUGMSG( "GET VOLUME requested, get right channel (%i)\n" , *right_volume );
-      }
-    }
-  }
-
-  if ( mixer_h )
-    snd_mixer_close( mixer_h );
-
-  /* for now, always return 1 here */
-  return 1;
-}
-
-
-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 = NULL;
-  snd_mixer_elem_t * mixer_elem = NULL;
-
-  if ( snd_mixer_open( &mixer_h , 0 ) > -1 )
-    i_seq_mixer_find_selem( mixer_h , mixer_card , mixer_control_name , mixer_control_id , &mixer_elem );
-  else
-    mixer_h = NULL;
-
-  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)(0.01 * (gdouble)(left_volume * pv_range)) + 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)(0.01 * (gdouble)(right_volume * pv_range)) + pv_min) );
-      }
-    }
-  }
-
-  if ( mixer_h )
-    snd_mixer_close( mixer_h );
-
-  /* for now, always return 1 here */
-  return 1;
-}
--- a/Plugins/Input/amidi-plug/i_seq.h	Mon Jul 10 04:42:53 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
-*
-* 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_get_volume( gint * , gint * , gchar * , gchar * , 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 */
--- a/Plugins/Input/amidi-plug/i_utils.c	Mon Jul 10 04:42:53 2006 -0700
+++ b/Plugins/Input/amidi-plug/i_utils.c	Mon Jul 10 04:52:51 2006 -0700
@@ -20,31 +20,13 @@
 
 
 #include "i_utils.h"
+#include <gtk/gtk.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 )
 {
+  static GtkWidget * aboutwin = NULL;
   GtkWidget *logoandinfo_vbox , *aboutwin_vbox;
   GtkWidget *logo_image , *logo_frame;
   GtkWidget *info_frame , *info_scrolledwin , *info_textview;
@@ -52,21 +34,20 @@
   GtkTextBuffer *info_textbuffer;
   GdkPixbuf *logo_pixbuf;
 
-  if ( amidiplug_gui_about.about_win )
+  if ( aboutwin != NULL )
     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 = gtk_window_new( GTK_WINDOW_TOPLEVEL );
+  gtk_window_set_type_hint( GTK_WINDOW(aboutwin), GDK_WINDOW_TYPE_HINT_DIALOG );
+  gtk_window_set_title( GTK_WINDOW(aboutwin), "AMIDI-Plug - about" );
+  gtk_window_set_resizable( GTK_WINDOW(aboutwin) , FALSE );
+  gtk_container_set_border_width( GTK_CONTAINER(aboutwin), 10 );
+  g_signal_connect( G_OBJECT(aboutwin) , "destroy" , G_CALLBACK(gtk_widget_destroyed) , &aboutwin );
 
   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 );
+  gtk_container_add( GTK_CONTAINER(aboutwin) , aboutwin_vbox );
 
   logo_pixbuf = gdk_pixbuf_new_from_xpm_data( (const gchar **)amidiplug_xpm_logo );
   logo_image = gtk_image_new_from_pixbuf( logo_pixbuf );
@@ -84,8 +65,8 @@
   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"
+                            "\nAMIDI-Plug " VERSION
+                            "\nmodular MIDI music player\n"
                             "http://www.develia.org/projects.php?p=amidiplug\n\n"
                             "written by Giacomo Lozito\n"
                             "< james@develia.org >\n\n\n"
@@ -117,21 +98,38 @@
   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 );
+  g_signal_connect_swapped( G_OBJECT(button_ok) , "clicked" , G_CALLBACK(gtk_widget_destroy) , aboutwin );
   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 );
+  gtk_widget_show_all( aboutwin );
 }
 
 
-void i_about_ev_destroy( void )
+gpointer i_message_gui( gchar * title , gchar * message ,
+                        gint type , gpointer parent_win )
 {
-  amidiplug_gui_about.about_win = NULL;
-}
+  GtkWidget *win;
+  GtkMessageType mtype = GTK_MESSAGE_INFO;
 
+  switch ( type )
+  {
+    case AMIDIPLUG_MESSAGE_INFO:
+      mtype = GTK_MESSAGE_INFO; break;
+    case AMIDIPLUG_MESSAGE_WARN:
+      mtype = GTK_MESSAGE_WARNING; break;
+    case AMIDIPLUG_MESSAGE_ERR:
+      mtype = GTK_MESSAGE_ERROR; break;
+  }
 
-void i_about_ev_bok( void )
-{
-  gtk_widget_destroy(amidiplug_gui_about.about_win);
+  if ( parent_win != NULL )
+    win = gtk_message_dialog_new( GTK_WINDOW(parent_win) , GTK_DIALOG_DESTROY_WITH_PARENT ,
+                                  mtype , GTK_BUTTONS_OK , message );
+  else
+    win = gtk_message_dialog_new( NULL , 0 , mtype , GTK_BUTTONS_OK , message );
+
+  gtk_window_set_title( GTK_WINDOW(win) , title );
+  g_signal_connect_swapped( G_OBJECT(win) , "response" , G_CALLBACK(gtk_widget_destroy) , win );
+
+  return win;
 }
--- a/Plugins/Input/amidi-plug/i_utils.h	Mon Jul 10 04:42:53 2006 -0700
+++ b/Plugins/Input/amidi-plug/i_utils.h	Mon Jul 10 04:52:51 2006 -0700
@@ -22,17 +22,13 @@
 #define _I_UTILS_H 1
 
 #include "i_common.h"
-#include <gtk/gtk.h>
+
+#define AMIDIPLUG_MESSAGE_INFO	0
+#define AMIDIPLUG_MESSAGE_WARN	1
+#define AMIDIPLUG_MESSAGE_ERR	2
 
 
-typedef struct
-{
-  GtkWidget * about_win;
-}
-amidiplug_gui_about_t;
-
 void i_about_gui( void );
-gint i_util_str_count( gchar * , gchar );
-
+gpointer i_message_gui( gchar * , gchar * , gint , gpointer );
 
 #endif /* !_I_UTILS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/pcfg/Makefile.in	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,12 @@
+include ../../../../mk/rules.mk
+include ../../../../mk/objective.mk
+
+noinst_HEADERS = i_pcfg.h
+
+CFLAGS += -fPIC -DPIC $(GLIB_CFLAGS) -I../../../../intl -I../../../..
+
+OBJECTIVE_LIBS_NOINST = libpcfg.a
+
+SOURCES = i_pcfg.c
+
+OBJECTS = ${SOURCES:.c=.o}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/pcfg/i_pcfg.c	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,158 @@
+/*
+*
+* 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_pcfg.h"
+
+
+pcfg_t * i_pcfg_new( void )
+{
+  pcfg_t * configfile = g_key_file_new();
+  return configfile;
+}
+
+
+pcfg_t * i_pcfg_new_from_file( gchar * pathfilename )
+{
+  pcfg_t * configfile = g_key_file_new();
+  if ( g_key_file_load_from_file( configfile , pathfilename , G_KEY_FILE_NONE , NULL ) == FALSE )
+  {
+    g_key_file_free( configfile );
+    configfile = NULL;
+  }
+  return configfile;
+}
+
+
+void i_pcfg_free( pcfg_t * configfile )
+{
+  g_key_file_free( configfile );
+  return;
+}
+
+
+gboolean i_pcfg_write_to_file( pcfg_t * configfile , gchar * pathfilename )
+{
+  GError * error = NULL;
+  gchar *configfile_string = g_key_file_to_data( configfile , NULL , &error );
+  if ( error != NULL )
+  {
+    g_clear_error( &error );
+    return FALSE;
+  }
+  else
+  {
+    if ( g_file_set_contents( pathfilename , configfile_string , -1 , NULL ) == FALSE )
+    {
+      g_free( configfile_string );
+      return FALSE;
+    }
+    else
+    {
+      g_free( configfile_string );
+      return TRUE;
+    }
+  }
+}
+
+
+gboolean i_pcfg_read_string( pcfg_t * configfile ,
+                             const gchar * group ,
+                             const gchar * key ,
+                             gchar ** value ,
+                             gchar * default_value )
+{
+  GError * error = NULL;
+  *value = g_key_file_get_string( configfile , group , key , &error );
+  if ( error != NULL )
+  {
+    if ( default_value != NULL )
+      *value = g_strdup( default_value );
+    g_clear_error( &error );
+    return FALSE;
+  }
+  return TRUE;
+}
+
+
+gboolean i_pcfg_read_integer( pcfg_t * configfile ,
+                              const gchar * group ,
+                              const gchar * key ,
+                              gint * value ,
+                              gint default_value )
+{
+  GError * error = NULL;
+  *value = g_key_file_get_integer( configfile , group , key , &error );
+  if ( error != NULL )
+  {
+    *value = default_value;
+    g_clear_error( &error );
+    return FALSE;
+  }
+  return TRUE;
+}
+
+
+gboolean i_pcfg_read_boolean( pcfg_t * configfile ,
+                              const gchar * group ,
+                              const gchar * key ,
+                              gboolean * value ,
+                              gboolean default_value )
+{
+  GError * error = NULL;
+  *value = g_key_file_get_boolean( configfile , group , key , &error );
+  if ( error != NULL )
+  {
+    *value = default_value;
+    g_clear_error( &error );
+    return FALSE;
+  }
+  return TRUE;
+}
+
+
+gboolean i_pcfg_write_string( pcfg_t * configfile ,
+                              const gchar * group ,
+                              const gchar * key ,
+                              gchar * value )
+{
+  g_key_file_set_string( configfile , group , key , value );
+  return TRUE;
+}
+
+
+gboolean i_pcfg_write_integer( pcfg_t * configfile ,
+                               const gchar * group ,
+                               const gchar * key ,
+                               gint value )
+{
+  g_key_file_set_integer( configfile , group , key , value );
+  return TRUE;
+}
+
+
+gboolean i_pcfg_write_boolean( pcfg_t * configfile ,
+                               const gchar * group ,
+                               const gchar * key ,
+                               gboolean value )
+{
+  g_key_file_set_boolean( configfile , group , key , value );
+  return TRUE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/amidi-plug/pcfg/i_pcfg.h	Mon Jul 10 04:52:51 2006 -0700
@@ -0,0 +1,39 @@
+/*
+*
+* 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_PCFG_H
+#define _I_PCFG_H 1
+
+#include <glib.h>
+
+typedef void pcfg_t;
+
+pcfg_t * i_pcfg_new( void );
+pcfg_t * i_pcfg_new_from_file( gchar * );
+void i_pcfg_free( pcfg_t * );
+gboolean i_pcfg_write_to_file( pcfg_t * , gchar * );
+gboolean i_pcfg_read_string( pcfg_t * , const gchar * , const gchar * , gchar ** , gchar * );
+gboolean i_pcfg_read_integer( pcfg_t * , const gchar * , const gchar * , gint * , gint );
+gboolean i_pcfg_read_boolean( pcfg_t * , const gchar * , const gchar * , gboolean * , gboolean );
+gboolean i_pcfg_write_string( pcfg_t * , const gchar * , const gchar * , gchar * );
+gboolean i_pcfg_write_integer( pcfg_t * , const gchar * , const gchar * , gint );
+gboolean i_pcfg_write_boolean( pcfg_t * , const gchar * , const gchar * , gboolean );
+
+#endif /* !_I_PCFG_H */
--- a/configure.ac	Mon Jul 10 04:42:53 2006 -0700
+++ b/configure.ac	Mon Jul 10 04:52:51 2006 -0700
@@ -584,7 +584,8 @@
 	OUTPUT_PLUGINS="$OUTPUT_PLUGINS alsa"
 fi
 
-dnl *** amidi-plug (note: should appear somewhere after the alsa ouput plugin check)
+
+dnl *** amidi-plug (note: to avoid checking twice ALSA, this should appear somewhere after the alsa ouput plugin check)
 
 AC_ARG_ENABLE(amidiplug,
     [  --disable-amidiplug     disable amidi-plug input plugin (default=check) ],
@@ -592,33 +593,124 @@
     [enable_amidiplug=check]
 )
 
+AC_ARG_ENABLE(amidiplug-alsa,
+    [  --disable-amidiplug-alsa    disable amidi-plug ALSA backend (default=enabled) ],
+    [enable_amidiplug_alsa=$enableval],
+    [enable_amidiplug_alsa=auto]
+)
+
+AC_ARG_ENABLE(amidiplug-flsyn,
+    [  --disable-amidiplug-flsyn   disable amidi-plug FluidSynth backend (default=enabled) ],
+    [enable_amidiplug_fluidsynth=$enableval],
+    [enable_amidiplug_fluidsynth=auto]
+)
+
+AC_ARG_ENABLE(amidiplug-dummy,
+    [  --disable-amidiplug-dummy   disable amidi-plug dummy backend (default=enabled) ],
+    [enable_amidiplug_dummy=$enableval],
+    [enable_amidiplug_dummy=auto]
+)
+
+
 if test "x$enable_amidiplug" = "xno"; then
   AC_MSG_RESULT([*** amidi-plug disabled per user request ***])
   enable_amidiplug=no
 else
+  if test "x$enable_amidiplug_alsa" != "xauto"; then
+    enable_amidiplug=yes
+  elif test "x$enable_amidiplug_fluidsynth" != "xauto"; then
+    enable_amidiplug=yes
+  elif test "x$enable_amidiplug_dummy" != "xauto"; then
+    enable_amidiplug=yes
+  fi
+fi
+
+if test "x$enable_amidiplug" = "xcheck"; then
   if test "x$alsalib_available" = "xcheck"; then
     PKG_CHECK_MODULES(ALSA, [alsa >= 1.0],
       [alsalib_available=yes],[alsalib_available=no])
   fi
   if test "x$alsalib_available" = "xyes"; then
-    if test "x$enable_amidiplug" = "xcheck"; then
-        AM_PATH_AMIDIPLUG(enable_amidiplug=yes, enable_amidiplug=no)
-        if test "x$enable_amidiplug" = "xyes"; then
-          ap_disable_timidity=yes
-        fi
+    AM_PATH_AMIDIPLUG_HWSYNTH(ap_have_hwsynth=yes, ap_have_hwsynth=no)
+    if test "x$ap_have_hwsynth" = "xyes"; then
+      enable_amidiplug=yes
+      ap_disable_timidity=yes
     else
-      enable_amidiplug=yes
+      PKG_CHECK_MODULES(FLUIDSYNTH, [fluidsynth >= 1.0.6],
+        [fluidsynth_available=yes],[fluidsynth_available=no])
+      if test "x$fluidsynth_available" = "xyes"; then
+        enable_amidiplug=yes
+        ap_disable_timidity=yes
+      else
+        enable_amidiplug=no
+        AC_MSG_WARN([*** Neither an ALSA-supported hardware synth or FluidSynth software synth (>= 1.0.6) have been found (even if ALSA was detected), so amidi-plug won't be compiled unless you explicitly request it with --enable-amidiplug ***])
+      fi
     fi
   else
-    AC_MSG_WARN([*** ALSA not found, amidi-plug won't be compiled ***])
-    enable_amidiplug=no
+    PKG_CHECK_MODULES(FLUIDSYNTH, [fluidsynth >= 1.0.6],
+      [fluidsynth_available=yes],[fluidsynth_available=no])
+    if test "x$fluidsynth_available" = "xyes"; then
+      enable_amidiplug=yes
+      ap_disable_timidity=yes
+    else
+      enable_amidiplug=no
+      AC_MSG_WARN([*** Neither ALSA or FluidSynth software synth (>= 1.0.6) have been found, so amidi-plug won't be compiled unless you explicitly request it with --enable-amidiplug ***])
+    fi
   fi
 fi
 
-if test "$enable_amidiplug" = "yes"; then
-	INPUT_PLUGINS="$INPUT_PLUGINS amidi-plug"
+if test "x$enable_amidiplug" = "xyes"; then
+  INPUT_PLUGINS="$INPUT_PLUGINS amidi-plug"
+  PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.6.0],,)
+  PKG_CHECK_MODULES(GMODULE, [gmodule-2.0 >= 2.6.0],,)
+  AMIDIPLUGDATADIR=${datadir}/amidi-plug/audacious
+  AC_SUBST(AMIDIPLUGDATADIR)
+  if test "x$enable_amidiplug_alsa" = "xauto" -o "x$enable_amidiplug_alsa" = "xyes"; then
+    if test "x$alsalib_available" = "xcheck"; then
+      PKG_CHECK_MODULES(ALSA, [alsa >= 1.0],
+        [alsalib_available=yes],[alsalib_available=no])
+    fi
+    if test "x$alsalib_available" = "xyes"; then
+      AMIDIPLUG_BACKENDS="$AMIDIPLUG_BACKENDS backend-alsa"
+      enable_amidiplug_alsa=yes
+    else
+      if test "x$enable_amidiplug_alsa" = "xyes"; then
+        AC_MSG_ERROR([Cannot find ALSA development files (ver >= 1.0), but compilation of AMIDI-Plug ALSA backend has been explicitly requested; please install ALSA dev files and run configure again])
+        enable_amidiplug_alsa=no
+      else
+        enable_amidiplug_alsa=no
+      fi
+    fi
+  fi
+  if test "x$enable_amidiplug_fluidsynth" = "xauto" -o "x$enable_amidiplug_fluidsynth" = "xyes"; then
+    if test "x$fluidsynth_available" != "xyes" -a "x$fluidsynth_available" != "xno"; then
+      PKG_CHECK_MODULES(FLUIDSYNTH, [fluidsynth >= 1.0.6],
+        [fluidsynth_available=yes],[fluidsynth_available=no])
+    fi
+    if test "x$fluidsynth_available" = "xyes"; then
+      AMIDIPLUG_BACKENDS="$AMIDIPLUG_BACKENDS backend-fluidsynth"
+      enable_amidiplug_fluidsynth=yes
+    else
+      if test "x$enable_amidiplug_fluidsynth" = "xyes"; then
+        AC_MSG_ERROR([Cannot find FluidSynth development files (ver >= 1.0.6), but compilation of AMIDI-Plug FluidSynth backend has been explicitly requested; please install FluidSynth dev files and run configure again])
+        enable_amidiplug_fluidsynth=no
+      else
+        enable_amidiplug_fluidsynth=no
+      fi
+    fi
+  fi
+  if test "x$enable_amidiplug_dummy" = "xauto" -o "x$enable_amidiplug_dummy" = "xyes"; then
+    AMIDIPLUG_BACKENDS="$AMIDIPLUG_BACKENDS backend-dummy"
+    enable_amidiplug_dummy=yes
+  fi
+  AC_SUBST(AMIDIPLUG_BACKENDS)
 fi
 
+if test "x$enable_amidiplug" = "xyes"; then
+  INPUT_PLUGINS="$INPUT_PLUGINS amidi-plug"
+fi
+
+
 dnl *** TiMidity input plugin (note: should appear somewhere after the amidi-plug check)
 
 AC_ARG_ENABLE(timidity,
@@ -890,6 +982,10 @@
 	Plugins/Input/adplug/Makefile
 	Plugins/Input/adplug/core/Makefile
 	Plugins/Input/amidi-plug/Makefile
+	Plugins/Input/amidi-plug/pcfg/Makefile
+	Plugins/Input/amidi-plug/backend-alsa/Makefile
+	Plugins/Input/amidi-plug/backend-fluidsynth/Makefile
+	Plugins/Input/amidi-plug/backend-dummy/Makefile
         Plugins/Visualization/Makefile
         Plugins/Visualization/blur_scope/Makefile
 	Plugins/General/Makefile
@@ -950,7 +1046,10 @@
 echo "  Windows Media Audio (wma):              $enable_wma"
 echo "  .mpc playback (musepack):               $enable_musepack"
 echo "  Module decoder (modplug):               $have_modplug"
-echo "  MIDI hw synth via ALSA (amidi-plug):    $enable_amidiplug"
+echo "  MIDI modular plugin (amidi-plug):       $enable_amidiplug"
+echo "    -> ALSA backend:                      $enable_amidiplug_alsa"
+echo "    -> FluidSynth backend:                $enable_amidiplug_fluidsynth"
+echo "    -> dummy backend:                     $enable_amidiplug_dummy"
 echo "  MIDI to WAVE converter (timidity):      $enable_timidity"
 echo "  CD Digital Audio (cdda):                yes"
 echo "  Microsoft WAV (wav):                    yes"
@@ -1000,9 +1099,9 @@
 fi
 
 if test "x$ap_disable_timidity" = "xyes" && test "x$enable_timidity" = "xno"; then
-    echo "Note: an ALSA-supported hardware midi synth was detected in configuration;"
-    echo "in order to use it, the amidi-plug (MIDI through ALSA) input plugin"
-    echo "will be compiled in place of timidity. If you wish to compile timidity"
+    echo "Note: an ALSA-supported hardware midi synth or a FluidSynth software synth"
+    echo "was detected in configuration; in order to use it, the amidi-plug input"
+    echo "plugin will be compiled in place of timidity. If you wish to compile timidity"
     echo "anyway, simply use --enable-timidity in configuration."
     echo ""
 fi
--- a/m4/amidi-plug.m4	Mon Jul 10 04:42:53 2006 -0700
+++ b/m4/amidi-plug.m4	Mon Jul 10 04:52:51 2006 -0700
@@ -1,9 +1,9 @@
 # Checks for amidi-plug
 
-dnl AM_PATH_AMIDIPLUG([ACTION-IF-FOUND , ACTION-IF-NOT-FOUND])
-dnl Test for AMIDI-Plug and ALSA-supported hardware synth
+dnl AM_PATH_AMIDIPLUG_HWSYNTH([ACTION-IF-FOUND , ACTION-IF-NOT-FOUND])
+dnl Test for ALSA-supported hardware synth
 dnl
-AC_DEFUN([AM_PATH_AMIDIPLUG],
+AC_DEFUN([AM_PATH_AMIDIPLUG_HWSYNTH],
 [
 
 AMIDIPLUG_EVERYTHINGOK="yes"
--- a/mk/rules.mk.in	Mon Jul 10 04:42:53 2006 -0700
+++ b/mk/rules.mk.in	Mon Jul 10 04:52:51 2006 -0700
@@ -62,6 +62,7 @@
 ALSA_LIBS ?= @ALSA_LIBS@
 AMDEP_FALSE ?= @AMDEP_FALSE@
 AMDEP_TRUE ?= @AMDEP_TRUE@
+AMIDIPLUGDATADIR ?= @AMIDIPLUGDATADIR@
 AMTAR ?= @AMTAR@
 AR ?= @AR@
 ARCH_DEFINES ?= @ARCH_DEFINES@
@@ -122,12 +123,18 @@
 ESD_CFLAGS ?= @ESD_CFLAGS@
 ESD_LIBS ?= @ESD_LIBS@
 EXEEXT ?= @EXEEXT@
+FLUIDSYNTH_CFLAGS ?= @FLUIDSYNTH_CFLAGS@
+FLUIDSYNTH_LIBS ?= @FLUIDSYNTH_LIBS@
 GCONF_CFLAGS ?= @GCONF_CFLAGS@
 GCONF_LIBS ?= @GCONF_LIBS@
 GENCAT ?= @GENCAT@
 GENERAL_PLUGINS ?= @GENERAL_PLUGINS@
 GENERAL_PLUGIN_DIR ?= @GENERAL_PLUGIN_DIR@
 GLIBC21 ?= @GLIBC21@
+GLIB_CFLAGS ?= @GLIB_CFLAGS@
+GLIB_LIBS ?= @GLIB_LIBS@
+GMODULE_CFLAGS ?= @GMODULE_CFLAGS@
+GMODULE_LIBS ?= @GMODULE_LIBS@
 GMSGFMT ?= @GMSGFMT@
 GNOMEVFS_CFLAGS ?= @GNOMEVFS_CFLAGS@
 GNOMEVFS_LIBS ?= @GNOMEVFS_LIBS@