changeset 269:1b82a9932b60 trunk

[svn] Import sid plugin. Ported from XMMS by giacomo.
author chainsaw
date Thu, 08 Dec 2005 15:12:12 -0800
parents 1368faba73c9
children c7efd92ee0e8
files Plugins/Input/Makefile.am Plugins/Input/sid/Makefile.am Plugins/Input/sid/config.h.in Plugins/Input/sid/xmms-sid-logo.xpm Plugins/Input/sid/xmms-sid.c Plugins/Input/sid/xmms-sid.h Plugins/Input/sid/xs_about.c Plugins/Input/sid/xs_config.c Plugins/Input/sid/xs_config.h Plugins/Input/sid/xs_fileinfo.c Plugins/Input/sid/xs_fileinfo.h Plugins/Input/sid/xs_filter.c Plugins/Input/sid/xs_filter.h Plugins/Input/sid/xs_genui.c Plugins/Input/sid/xs_genui.h Plugins/Input/sid/xs_glade.c Plugins/Input/sid/xs_glade.h Plugins/Input/sid/xs_init.c Plugins/Input/sid/xs_interface.c Plugins/Input/sid/xs_interface.h Plugins/Input/sid/xs_length.c Plugins/Input/sid/xs_length.h Plugins/Input/sid/xs_md5.c Plugins/Input/sid/xs_md5.h Plugins/Input/sid/xs_sidplay.h Plugins/Input/sid/xs_sidplay1.cc Plugins/Input/sid/xs_sidplay1.h Plugins/Input/sid/xs_sidplay2.cc Plugins/Input/sid/xs_sidplay2.h Plugins/Input/sid/xs_stil.c Plugins/Input/sid/xs_stil.h Plugins/Input/sid/xs_support.c Plugins/Input/sid/xs_support.h Plugins/Input/sid/xs_title.c Plugins/Input/sid/xs_title.h configure.ac
diffstat 36 files changed, 8633 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/Plugins/Input/Makefile.am	Thu Dec 08 13:29:31 2005 -0800
+++ b/Plugins/Input/Makefile.am	Thu Dec 08 15:12:12 2005 -0800
@@ -1,2 +1,2 @@
-ALL_PLUGINS = mpg123 aac mikmod vorbis tonegen cdaudio wav flac console wma
+ALL_PLUGINS = mpg123 aac mikmod vorbis tonegen cdaudio sid wav flac console wma
 SUBDIRS = $(INPUT_PLUGINS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/Makefile.am	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,42 @@
+if HAVE_SIDPLAY
+
+lib_LTLIBRARIES = libsid.la
+
+endif
+
+###
+### Source targets
+###
+EXTRA_DIST = xmms-sid-logo.xpm
+
+# Generals
+AM_CFLAGS   = -D_REENTRANT $(PLUGIN_CFLAGS) @SIDPLAY1_INCLUDES@ @SIDPLAY2_INCLUDES@ @BUILDERS_INCLUDES@
+AM_CXXFLAGS = $(AM_CFLAGS)
+
+# Generated libraries
+
+libdir = $(plugindir)/$(INPUT_PLUGIN_DIR)
+
+libsid_la_LDFLAGS = $(PLUGIN_LDFLAGS) @BUILDERS_LDFLAGS@
+libsid_la_LIBADD  = @SIDPLAY1_LDADD@ @SIDPLAY2_LDADD@ @RESID_LDADD@ @HARDSID_LDADD@
+libsid_la_SOURCES =	\
+	xs_init.c			\
+	xs_about.c			\
+	xs_support.c	xs_support.h	\
+	xs_config.c	xs_config.h	\
+	xs_md5.c	xs_md5.h	\
+	xs_length.c	xs_length.h	\
+	xs_genui.c	xs_genui.h	\
+	xs_glade.c	xs_glade.h	\
+	xs_interface.c	xs_interface.h	\
+	xs_stil.c	xs_stil.h	\
+	xs_title.c	xs_title.h	\
+	xs_fileinfo.c	xs_fileinfo.h	\
+	xs_filter.c	xs_filter.h	\
+	xs_sidplay.h			\
+	xs_sidplay1.cc	xs_sidplay1.h	\
+	xs_sidplay2.cc	xs_sidplay2.h	\
+	xmms-sid.c	xmms-sid.h
+
+INCLUDES = $(GTK_CFLAGS) -I$(top_builddir)/intl -I$(top_srcdir)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/config.h.in	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,131 @@
+/* src/config.h.in.  Generated from configure.in by autoheader.  */
+
+/* If this macro is defined, a BMP plugin will be built instead of XMMS one.
+   */
+#undef BUILD_FOR_BMP
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define if you have HardSID with libSIDPlay 2 */
+#undef HAVE_HARDSID_BUILDER
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+   to 0 otherwise. */
+#undef HAVE_MALLOC
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* Define if you have reSID with libSIDPlay 2 */
+#undef HAVE_RESID_BUILDER
+
+/* Define if you have and want to use libSIDPlay 1 */
+#undef HAVE_SIDPLAY1
+
+/* Define if you have and want to use libSIDPlay 2 */
+#undef HAVE_SIDPLAY2
+
+/* Define if you have XMMS patched with the songpos patch. */
+#undef HAVE_SONG_POSITION
+
+/* Define to 1 if `stat' has the bug that it succeeds when given the
+   zero-length file name argument. */
+#undef HAVE_STAT_EMPTY_STRING_BUG
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#undef HAVE_STDBOOL_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define if you have XMMS version 1.2.5 or later and you want XMMS-SID to
+   support some extra features. */
+#undef HAVE_XMMSEXTRA
+
+/* Define to 1 if the system has the type `_Bool'. */
+#undef HAVE__BOOL
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+   slash. */
+#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 if your processor stores words with the most significant byte
+   first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to rpl_malloc if the replacement function should be used. */
+#undef malloc
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to empty if the keyword `volatile' does not work. Warning: valid
+   code using `volatile' can become incorrect without. Disable with care. */
+#undef volatile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xmms-sid-logo.xpm	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,188 @@
+/* XPM */
+static char * xmms_sid_logo_xpm[] = {
+"249 120 65 1",
+" 	c None",
+".	c #0B0A0B",
+"+	c #B9A962",
+"@	c #517764",
+"#	c #32301B",
+"$	c #3F6957",
+"%	c #3A5E4D",
+"&	c #305243",
+"*	c #B9C0C1",
+"=	c #2D433A",
+"-	c #978A59",
+";	c #222523",
+">	c #CBD1D1",
+",	c #6D764E",
+"'	c #4E5D3D",
+")	c #4B4629",
+"!	c #586845",
+"~	c #747762",
+"{	c #151615",
+"]	c #465131",
+"^	c #898D64",
+"/	c #D7DEDE",
+"(	c #3E4028",
+"_	c #9A9A92",
+":	c #2E3722",
+"<	c #404A4C",
+"[	c #868276",
+"}	c #363F41",
+"|	c #4F6B5B",
+"1	c #4B5E55",
+"2	c #575233",
+"3	c #E2EAEB",
+"4	c #3F464A",
+"5	c #3A3821",
+"6	c #7A8684",
+"7	c #666A52",
+"8	c #382818",
+"9	c #535352",
+"0	c #6A6053",
+"a	c #494848",
+"b	c #798282",
+"c	c #37393C",
+"d	c #A09867",
+"e	c #424146",
+"f	c #1F1D1C",
+"g	c #70777D",
+"h	c #858F8C",
+"i	c #2F3133",
+"j	c #817D4F",
+"k	c #2B2824",
+"l	c #FBFDFD",
+"m	c #B59D50",
+"n	c #756C60",
+"o	c #3B3F42",
+"p	c #635E3B",
+"q	c #A8ADA9",
+"r	c #5A5E5F",
+"s	c #7B7C81",
+"t	c #31373A",
+"u	c #6F6A43",
+"v	c #455150",
+"w	c #3C414B",
+"x	c #656B6F",
+"y	c #181B18",
+"z	c #101010",
+"$%%%%%%%,j,!j^,7j^u%&&v!---j---j,]&v%&&7jp]&&&&%'7jp&&'u----p]&&&&&=&=&]7~0<&v&<=<]r,j,r]v&vvvjdmmmmmmmmd-'',-~!||$1,^[|%%$$$@6@||~dm+mmmmm+mm-'%!jd7%%1![d,1%$|~^d,%%%![d,$%%1,d[!%%|j^[!$$|,d^,|@$@^d,!|$@@ddu1$@@@@$$$$@,_^@@$$@jdd'jd-7jd-7jdj!jdj7jd",
+"%$%$&%%$bd,],du'jd]}&&&u------m-u(=&&=<7^!&&&&&&&,dp=&=p-m--'==%%%&&&&=&'u-['$%|1|&('j-j<1@|1'~mm-m-m--mm-)],d0(=&&%7+^|$|@@1$$%%!~+mmmmmm+++mj(<%^q,|%%|^d,1|$@^dd,v$@@^dp%1%%,m-'%&$bm^|%%@^qd'&%$@-d,%%$$6^d!$$@@$$$$@@$@d-@@$$%,+-]~m-!dd-'bm~)bd,'~^",
+"$@@$&$$$@^7!^dp]j-2=&&%,d--m----j]%%%%&--]=%$%&&]7^p&&&]jm-j'&&==&&<&&===]0-,]<&v%%<=]u^^7==vv!jmmmmmmmmmj]'jdu'&%%@,dj'$%&%%%%%$@,+mmm+mmmdmm^!|7^m71@h@jm!&=%$,d+6'$$@^q!%$@@^*-p|$$jdj%%$|jdd,@$%@^d,!$$$,dd,@@$%$@@@@$$j+-'%$$@6d-],d-p~ddp,d-p^+,]j-",
+"$$%%@@$%@d^7^d!'jd']&%!um---m---j]&&&'@d!&&&=====!d'%&='ummp]&&%%%==&&&===]p-~}<%=:=<]p,d^'<%v]pj-mmmmmmm,((7dp%$%%%,d^&&&&%%$1%&]7mmmmmmmmm+m-']@q+'&%@,^d!%$@@6qmj|$&'^dp&%%$d+d!@%%bm[]%$%,md6@@$@^+,$$$@^q+!$$$$$@@@@|,_+d@@@@@6+d'j+-ujm-'jdj,~d~!j^",
+"$@$$$$$|,^!]jd7'jd,%%%%,mmm--mm-j'%%1~+j!%&%%$$|@j^]&&$!,--2)%&&v%v%1%&&1%9]u-b1v&%|g@']7^d71<<]pjmmmmmm-up,[d7]%$,~__d@6@6@|%%1|!,dmmmmm++md+j'!^_^!'%&!^d7|@$!j_^b1||@^d@!@@~^d,%%@,^h~|$@@ddj,%%%b,j|]%$@^^jx$$@@6@$%%|s^^jp$$%$,_j2~m^p~m-pjmj'j+[]j^",
+"@$$$$$@@,^u%^d,@bb!7&vpuujujujju7r!11g799v%%%v%&]!,2'11'2n79<1=<&1|''r1x|11v9'9v11@g9v<<aa99v&v9)22]p22))(v<'9e<vv%'|1'x|r<w4a4ew=4v(5))55::::tcwoe2v1v<voi:tt:==((}::i::;}wc:iky#(:tti;iiii:;;;;;ik:;ikii:i;;;it===ii;i:i;;ffiki:k;yf:0d-!~dj'~m-pjdj],^",
+"$%$%%@@$,^u]^^p]=:}ow<<c5()5(555oocwc}w444ew4wct}ocwo}}4=}:tecc4}}to}tcwcccotttt}4cctcoo5ci5}}=:to5:::5c}ctttt}=}cct:ttcittiitiito4}cccccct}tc}tcooecccic4}=tti}:}i:=ttt}::tiiitc}ecciii:=t}tii:ccct=ti}t}}=i;ccctcii;t=4=}tiitikcc:ii}u+d9jm[p6d-'jd['j^",
+"%%$$$@$%,^u'jdp]<4cto44vaeaae44waoiit4v<ww}ewew}<ci}}(4=}=}wve44oiitc}ww}cta<<oo4ti}w4weccooctct;;t}oo=ticvv<<<i;ic}}tc=tt<ww44;;tc44cwci<v<v<iyi}oocoiie9vv9w;;49t}t}ii99vv<iyktt}wot;<vvvv};;:t}cct;ivvae4;yitcttt;;4vv<}=;;:i;;i;;kaxdd'bd-]jm-@^mj!~^",
+"@g@@%%%%j^,!-d2)=4t{z{f;;;;;i<9vvef.zy;y;{y;}awa<;..zyyyyy;iv<<4ez..yy{zzz;o<w<9i.z{{{{{{{tveociz..z{yy{.y}444=;..z{{{z.zi<4wwi{.zyikz{.{e<=wt;..zzzzz..kwewck{z{zzzz{.zicict;zzzzzzz..;}owtk{z.zy;zz.zktcciy{zzzz....y;ii;y{..yhv...{kpdd'jd^!^dj'j_j!j[",
+"$1%%1$|@j^u'-d7v};;{zyyyfyfz{kii;yfz;;;;;;yy;ikiyy;y;iitct{y;;;f{yit4<woac{f;;:tz;kta99av#;k;ff{zw<<v9v91;zfyfy.{9999rrrvzfyf{z.t1rsbxrgvz{{zzz{rggxxr9xiz{zz{.{9rxrr99x{zzz...ixrrxxr1r.zzzz.zxg@|gxrxr{{{yz.ixr1xggx9{.zz..zs>/*b6bb95dd'jd^',d-!^d^7,[",
+"$$$|$|@@,d!2^d!14w/l333//3q9yzz..gll3333ll6=.{z.{>ll3l33l3ryzzz.v3l3lll3l*;yz{y;63lllllll_{y{{{;*llllllll<z{{{zv>llllllll.y{{yys3lllllll>.yyyyi_llllllllg.ffyytqllllllllt{;;;y|3llllllll;yfffiqllllllll>zy;;ix3llllllllg{;;yv*llllllll/9dd!jdj',dj],d^!,-",
+"||@@!%%$,^!'^^||<hllllllllh!4yi;y>llllllll'1y;;{wllllllll3]c;;;z_llllllll>wyk;ii/llllllll_zfk;;c3llllllllwykk;{g3llllllll.k;;;{qllllllll/.iik;;>llllllllh{;iky=/llllllll4y;k;{blllllllllt;kkiw>llllllll3;i;;tv3llllllll*{i;;v_3lllllllls[-!,d^!jd-]jd-pu[",
+"$$1%$|%%,^,@^^)=&/llllllllr;;fky<llllllll3z;{;;{6llllllll/.y;kk{*llllllll,.fk;;y3llllllllrz;8;;4lllllllll;y;iiz6lllllllll.ikii{qllllllll*.iii;;>llllllllxyti;yt3lllllllle;itkzv>l33lllllikiki{hllllllll/iti;y.>llllllllqyii;.:3lllllllls-^'!+^',^^!j^^!,^",
+"$$$$$@$@~^!]6jv$%*llllllllz.{yiyv3lllllll/.z{;i;6llllllll*.{fi;{*lllllllli.yi;ii3llllllllf.;kky<llllllll3zyikk.hllllllll/.;iik{qllllllll_.ikk;y*lllllllliyikiyiqlllllllly;iikz=>l33>>3l3yiii;.xllllllllq{kk;z]lllllllllxyi;yzv3lllllll3<jj'!-j]!d-'!-j]u[",
+"@@@@$$$@,^!'^^!|&1/llllll3{.yy;y=>lllllll>.zyyyzgllllllll_.{{f;.qllllllll;.y;;yi3llllllllzzfiizvllllllll3.{;;;.6llllllll>.;;;;{_llllllllh.k;;y;*llllllll;;;;kyyg3llllll*;i;i;fkqlllll/3/{;kk;.hllllllllqz;kk.x3llllllllg{;f;zv/lllllllgk7~!,^-',-j',dj]~j",
+"1%$%%%%$,^@,^^r11v>l3l3ll3{.zy;;k_lllllll*.{{yy{xllllllllq.{{;yzqllllllll;.yy;{;lllllllll{zffyzvllllllll3.{y;y._llllllll>.y;;yzqllllllllxzyfff;>llllllllty;;;;y7lllllllqy;;;y{zhlllllll3ff;;;._llllllll*z;;;.;>llllllll6{;y{.]/lllllllr}v']'j-2'-^2,-^]jj",
+"$@@@$@$@b^'','5ttv>33333/qfy;yyy{h///////n..z{{yv*//////><.y{yyzh///////qyy;;;;=*/>>/>/>,zfkttir*>>>>>>q,itc}tib*qqqqqq69;tiii;6q__qqqh9c}wtciwhqq*q__h!ktttiitrh_____7t;iiwcit,h^h^__69itittig____q__g<ictct=hq_h^_hh1ttww4or~^__qq_6v4a]],jj)'jj5'^j(!j",
+"@$$@@@@$j^p%g6hhq_66hbs[6h_hh_qq_hhh[6[^6_q*qqqq_6b6ss~~g6hqq_q_bggg7~~gb_qqqq_6xx~~~7xg6_qqqq_hg~sn~s~gh_qqqqq_[6hh^[[6qq****qqh[s[~7b_qqqqqq_6g77x~gbh__q_q_hbg0rrrrg6hh666bgrrv9<4wvrrgg@x1v44}4www4<1rx|r1=}(4ec449x|rrrr9veooc}ov91rrv7-j]!-j],jj),j",
+"$$$$$$$%@^!|&4=&=}4}w}}}4t=w<wt=wwttiiitttititiiitkitickiit;ttiy;;f;k;;f;yyy;y;;;;fy;k;;k;f;;;;;;;k;fk;;;;;y;;;f;;kfk;;fy;y;;;;k;iikiikiii;ittiittt}i;;i;;i;;;tiiiktci;k;iiiittiitiittctiikiikioitit}tciccitcwe<cceccewccwww4eaw44<<cecwwee2--]u--'u-j27j",
+"$$%$$%%$,j11&w<vv<wvvvvvvrvvvvv<v<a<v<vv<<ww<<<vvvwea4eew<4<w4w4wwww<4<4w44w4<<<9a<w<4ww4w444vv<<aaav<<<<w4<4<<va9vaaavvvv9rr99rrvv91911v919vvv9v1vvv1|v1%vv9ra1r1rr1r1rv1<v9vvv9vvvv1vvvv9vrr9v991r9999rr119r1v9v9arrvvvvvv9<vv<<<v99<eew})jj(],-)'--)pj",
+"@@@h@@@$@d!%<=<ww4w4ww4v4=4<v4444eee4wvvv4v<<ww4w4wwoowecwwwt}t}tw<ecwccwtww<4wcecw}}eaeaewww}wwaeceaowww<w<<4w<wwvwwwww<v<w444<<444<4w4v4wa4wvvawwa4w4<w4v<w4ww4<4w444<44<<44w44}v4<vv44<44<w4v<<<<<<vw44<4w444ww<eww4<<vea4ea<v<<wwwewww42j-)pjj]pjj2p~",
+"@$$@$%%$@^11&ww<444<ww<ww<<<<4<<w<a<<444444<<wwweoww4wccww}w}t}wwwccwcc4w<wweeweo4wc44wwww4wwwwwweaew44<44aaw4<a<wava<44<4<9<4<<<4vv44<<<a44a9<a<<a444<4<4w<<4<<<ww4www<v<<<4<4e4a<vv<<4v44<<4w44<aa444w<aa9wa<<<a<<4w<4<4w444wwwww<v4w}}}t)u-]]jj5)jj5pj",
+"$$$$%&$@6^'&v&www<<<aav<w<<<4<w4wwwe<<v4&<<44w4wa<4w4wowwwww}tw}c}w4w}tcwwwwwecoec}cweccwwwcww4wweeeee<eea4<4a<aaw9aa4<4<wwwww44<<4v<<a<<4w4wwwawwaa<vww44va<weav<<<<4ww4<wweaaaaaaww4<w4<vva<a4<wwav<vaeeeee4e<444a44<<w<<<444<44w4w4w4}co)uj)]j-]pj-)'j",
+"$$@@@@@@,61&<www4<4<wwww4<w<4w444wwvwwwww44<wwww4c}ww}cowct}wwcw}}t}ccc}}c}wceeocwececwwccwwww444waawwww44ww4<4wa<ww4aa4aa44vv<<4a<44w<4w4ww4a<aww444<4wwww<a4<44ew}ww44ewe<e4wa4waww44www44v<e4<9v<4ww4aaee44<av<v44w44<4v<<4v9awaeww4wwoc)uj)]jjp7j-22~",
+"$@$$@$$%$j!1%v<444<v4aa<ww<w<44<<awv4w<v44wwww<ww44}w4wwwwwwcwctcw}tcwwcwwwoooceoweeeoewcw44<ee<4ww44wwwwwwaaawa9vv<<wwaa<<<4wwww4w<4<wv444<<<aww<ww4e4v<vwcww4eoccw}cccw<e<weweeweewe<<444<4aaweaeewa44ewew4<<ww4w444<49944<44<wwwew<4}4wc)j-2p,j2p~j)pn",
+"$@$$$$&$,^v&<4ww44<<4av<<<aw494w4a4=w<44w4ewwowww=4w}wwccwwtiwwcc}ctccwwcw}ceeccccwccwccwwcowcw444wwwww44wa4waweww4<<wwvv<<44w444ww44www4444wwww<aewa<4aww4wwaewewwww4wwee49a4w4we<aaa44wwww4wav4aaa<4ewa4ew444ww444<4w4<4wew4aw}ww<vewwewe)0jpp,^()u-)2~",
+"@$$$$$%$,^'v<4w4www4<wav<<awwweaaaa44<<vw4<4www}w}}eowoecocwwcwwcc}w4ecccwcctoowccoott}}w}cw4ewwvwoee4wwwwweaaewwwww<<4www4w444<<44<<4awwwewwwewawea4aw4w44w44woeowwwweeccoww4eccwewwwa<wwwcww44<vwew<wweew4www4<4wwww<<<w<v4www4<w}4wwwwao20j)2uj]2u-52u",
+"$%%$%$$$@^1%<w4a4aae9w<<4wwae4444wwww44wew4oocetctcecccccweeotc}ccccwccwecotcoocwcccicccwoooeotoowcww4ww4w44w4aeww44www<4<w44ww<ww444awe4wee<aewe4ee44www<w}w4ccecccccow4}owwewwwweww4www<4wwww<wwowwwwe4<4awcceee<ww44<w444ww44w4<w4e=4<4c)uj))ujppuj)2n",
+"$%$@$%$$@j11<vvaa<4ww<a<<4<994<v<ww4a<a44wccowoccaewot}ccwcccceo}cwwcwccccw}coo}ooowcw}w}itcowocow}}}w44<4a4eowawawwww<wwvw4w4<<wwwwwwwe4eweewewa<ewewwwc4wcttwoooctcctcittcwoewww<wwwwwwaw}www<ewwwccc}www<4wcww}w4www4wwwwww4<ww44oe<w=wo)0j22jj2]uj22u",
+"$$@$$$$$,61%&4ww<wwww<<w4v444e44weewww<wwww}occoeccccccccotcc}cctcccwwwcccxxx9ctocrxxxcaxxr|r4wwc<rxxxxrcwxxrxxwwwwwxggxxrww<xxxxxrrr4wwe444warxxxgxxxvcwxxxvcwxxrxrxxxr4ct}ww<wwwwww44www4w<w44weewww444w44wwewww<44<4ewew<<ewwa<aweew44w()uj2]uj]2j-p2u",
+"$$$$%$%&|,'v&4<44ww4w<ww<va94444<wwcw4eww}}cwcccoewctco}oewwowcewwooo44w4ovg6gwitagbhr}rgsxgg9}4orssgb6riagggggrtwwaggggsrwwgggssggggxawwwwwwgggssbssggwcxgx9teggggxgggsg9t}}t444w4awwwwwwwwwowo}wwwwwec}weww4wwcwwwwww4<aw444aww<a4wweeweo)pj)(pj)2uj2)u",
+"$$$$$$@@,b1&&w44w44<wwwwwwa4a4eowwwe<w}wwwow}}ccccccco}c}c}ccw}ttccccwcccc=x6grtixghhwirgggggxt}i1ggxs6rw9sbssggwiirggsbgrt<gsbgxrxh6s9wwwwwvgssgxxx6bsv}gbb9icss[[6bs6s~g4}}}eowewwwew4we}wwwow4a<ww4w}owwee4ecwwww44w4w<w4ww4v<<v4w4}ww}5)pj))uj])p-p2u",
+"%%$$$%$$@j|1&<ww<<44<waa4<weaaew4wcwwct4wwweoawoowwtccot}}occccwccwww4}ccccv6sg}wgs6acc9ssxs6bewcgsbgbbrtvssggsgecwxshghbxtrsbs<4wassgvwowwc9bs6eww<gbsvtgbbrcwsh69aavrsgsvcceeewecwoow}oc}ctcceeeawwewco4wwe4wcww}w44www4ww<wwww}owooc}44o)0jp5uj2)uj2ep",
+"$$$%%&%%!,v&w&wwww4awa<w<9r94eww<44w4<4wwoo(ecctcctocct}}}teccco}c}wceowecccx6grxs6xwcc9s6rx6gvcvbbxxssrta6bsrgs9t4gbsr6sgtrsss9wwwwawwcoccw96bb9wwc}wwwtggbxcvbssaeaeag6s9toowccoecoowwwoo}weewcccweocwe4owwww}www}}cwwwwww4e4w44wwwwv<44c5pj2)uj2'uj))p",
+"$$$@$$$$@,]&44w=wwv<aw<4<<<www4www4}=t}<weoow4oowwcww}coctcww}ic}ccwwoeewwciessgs[bwocc9g6xrs6xcrssrxgsrt9hssa6gri9ssxrbsgt9hbsgxxxrrawcwctt4bsggxxrr9wctgbg|i9ssbeceeegbs9ceo}}ccoceow}ooctcwew}cc4}coeeeeeawww4wcwwww4a4wwwwww4aaeaav4w}}(pu2)pj)2p-220",
+"$$$$$$%$,~9%w44www<wwwaw44444aaowcw4}}}woeccecceccowctcicceccct}oooot}coccettx6sggxwcocrsbxe6srwgsscxbsrt9gggwgsgwxss99gsxcwg6sssggggxwcwwcwwghsggggggx4txssrca6ssoctowg6sxotcwow}4oo}wcowecwwwww44ww44e444woow4ww<ww=wwwwww<4(4<44o44}w=4()0u25pj22p-2(p",
+"$$%&%%$$,,]v==w4ww<ww4aww4<<<4awwwcwcwooooecoetooco}owceocccoccccecoowccoooivgb6sbb9cct9sbxwx[brggxcxs6rw<sbscrsg9xbgwxbsxicwrxgsss6sg99xxg9wwrxggbssgsrixbsxw9ssswcoeenbsrccctcec=}otooccccococcwecceotcowoo}w4}w<4444}cwcwew4<4o4ww444www(2j2)pj2(pj))p",
+"$@$$@@@$,~v&&<<=<4<44www<4wwww}}ww4w4}oooeewoc}tcctcccccc}}cceccccccc}ciceccxgbxxggxctcrggxc9sgxgsrcxsb9irgggcasgxgsxc9ggxcwwaaw<49gbsxrsgs9c4avawa<xssxtggbrt<gsscccicggs9ccctco}occctceeccow4wwwoooectowwcco}we4woww44wcooeee4owww4<4awoe5pn2)pj2)pj2ep",
+"@&%&%%&&!j&<&wwwwwvwwww4www}ttc}}ttw}tccce4o4oecocccccotct=4}ctc}ccwwoeecci9gss4v6h6r}t9gggcwsbs6sacgs6rt<bbh<4xggss9txssxcvgggcccwxgbx1gggv9ggxwcwwrsbxtgghxiv6bsciitrgsb4cccoeeoccweocccecc}=}}}cccccoow}o4w}}cectow<<4eweaeowoewow<<aoecepj)52n2(pjp5p",
+"@$%$$$$$@^[1w<ww<4wwaa<ww4<44<wccw4otcc}c}tooe4ecowccccittcicttccecccocecotggbxwtxggxci9ggxcwxgssgccgbbxcvbbxwcrggssairssxi<sgsrrrxxbgrwwwww<gggrr9rgssxtgggxt4sgxxxgxggbgictotooc}tcceccccttcc}ciccoccccwo4ww}4}wwaowcoavaeeeowo4wwa44weee52n2)pj2]un2(p",
+",^@$$$$%&!jj4w4}tww<<wwwwwwwwwww}cccc}t}cttcoccoccocccwcc=ccccctteciccccc}1g66wttvsggrt9sgxcc96ssrwwg6brtvs6gwtvsgsxwixgsxiwssggxxgg6swcwwwcwssggsgsshs9tgsbr}vhhggxggsg6xie4ec}}ooccccccc}w}}ccccooow}}cocico4=w4}wwwc4ccecwa9<w444www4oo55pnp)pn2k]n2(p",
+"$@@$&&&&%&'rv44w44wwwww4ww<www}wc}}owowtcwooc}ccoccwccccc}cctcc}wcccccc}cwxggrtcttgbsswrs6xcwasshvttgg6rivg6swtwg669twrshxccvggs6hbsg9wttcitc<xsss6[[grcwghhxtvbgbshh6sg0eitti}ccc}cceeec}c}tccooecoct}cw4aoo4wo}w4wo<<eoawo}ov<4}<4}ww<a9e820252u2(2np:'",
+"%',^%&&%$%%%www4ww<<44w4444w4w}wtc}o}w}=c}}tc}ccwttwt}ccccctwccccwcccwcw}wtttwcctwwwwwwwwwwciwwe4wwww44wwtwwawwwtwwwwiwwwwcwcww<wwewwccccccctweaweeaw44}t<<4www44aeaeewaawcc}}}cticccecccoocc}ccccicccooooe5ceoowe4(oooeocoowoavo<<w}4ea449e)u2)2jp('jp#]",
+"%$%,@@%$%%1%=w<<<4ww44ww}w44wwwwww<}}}woowcc}w}ccwtccwcccccttcccwcwcco}cctcwcwwcwwe4wwcwwwwwcww<wcwtwwwwwwwwwtttwwwwwwwwwwccccwwwwwwcitcciccccwcwwwwwcctttwtwitwowececcctttccccc}}ccccwcittcccccowwcoccc}}}}eocce4c=cocoo}}44}4}}}<www4ww<45)u252u2]2up52",
+"%$%$,j%&&&&&wwww44w}=wwwwtw}wcw4}}}cw}o}wwcwwowoc}itcccwwt}wwwwcccwwww}}ttwcwcwttcwcwwwcwcccwwwwctttcwwwccicwcwcwicccwwccttttccccccccccctcctcctcccccwww}}twctccwccccccitccccwowtcwwcceoeeececcccwoocoeco}}}ocowwo4owweeeoccw}wwwww<44444w4}(2up52up)2jp]0",
+"%%&&%!,$&&%&<vwwww4www444ww4<4oww4<w}ocoocceow<cewweewcewwwcccocccccccctwwiccccccwwcctccccccitttttwcicicccwwwcccwwcccitcttwcciciicccctctccttctwcwcw}ccccccwwwcccitcccicioocw}t49v<cccicciiicitccccco5oe4occc(oo}oco}o}cc4wwcccoww<v<4=}owee520p52n25],p52",
+"&&%&&%,,%&&%titw4w=}ww44wwt}4oo4cw<}}cioeooiikiiccewtitwc}}tticcccc4vv4cttiwcwccwccwctticcccccwtwtttiwewccciwctiicccccctwttticccccccccctcwcwccccwwcc}tcwcwwcwtcwccctticciccowwxbhhhbr<tccccecct}eeec5k;;;;itee44e}owew}}=w4wwwc4r1vvv<<4oea()u252uu(2~25]",
+"%&%%%%'7,1&&;{y;t4vwww4w4444<eewwwcwoowee#{y{{{{ffktcwctcctwwwcarshhhsxwwccccccccccwtwwceccicwctwtttwiwicccwcwwwceiicwwtttitccwiciiccttttcccccctttcttcwicccccocctcccccicccic}}gbgggshs4wwocce5o4}ck{{y{{{{{y;cct}owwooowc}}wwcwcw4=4<4wow=e520p52u2#2u05]",
+"@&&&&&&%u,&=yyyyyiwwwcwwwwwe<eooo}cwwee4k{{ffffffff;iwcccti}w}ws6gxgggg}cwttctcccwtcwcwwccciccctcccwiccccwcciwwwccciiicitttcctciccciiitctticcccicctcctiiwcwccotitctccctcccwcwwxgggggbhhrcccccttcwif{f;;ffffffkt}wo4we4oww}}}4=w}cw4weaeo}}}5)up52np#a,n5]",
+"*@&&&&&&!!s%i;f{yytw<<4<w}ooweewwwoowww;yf;;;;kfkfffkiw}ccww}r6hbgggggxwwccwwcwcctwc}wccwcccoewwcwicicwcwcccccccctcw9rr94citicccicw4<<wwtwccccctwwtwtitwcciccccccciitticiiitc<xggbbggxgx4occtccckyy;;yf;;f;f;;kt}}ccw<wwocwww}cw4994ccw}w}c)2n05)np(]pp5]",
+"*q%%%$&%%%u,t;fyf{;i<wwww}woocowwccc}<iy;;f;;f;ff;k;k;t}itccwxgxxgggggx4cctiiccttititcttcttccticccwcttccccttttttcaxxxxrxx9ccticierxxxrxx<twctitic}ttcccticccceoiccttctexxssbgg66gxgb@gxsx4ccit}i;ff;ffy;;f;;;f;icooooo}}}}wwwwweaa4w4wcooeeepup52u25]u05]",
+"q*$$$%%&&&vvif;;;ffiww4w4wwww4w4eow}oi;f;fyfff;f;ff;;kiwtwt<xgxx@ggxxbbgggggxxwcwwccccwcttcwcccwtccctiwiicwwccwtwxgbggssgxwcitccxgsgxxggxccccccccwcwcticcwcccccoo}wttivsgxgx@gxwt}1xggggg9cccco;ffffffffyyyyffy;cwwccocw}cwww4ww4w=}}v9wwwc8)p25202#(p,:)",
+"qq$%&&&&&&&&tk;;;ffkww4cww4}cc}ooccwaiy;;ff;;f;f;ff;;;iwc}tvgggggx%wtwxgxxxxgxaccttccwictctccwiotittccicicciiciiwggg4<agsxwccctcxggwtwxggctcttcccitcccwitccciitttc}ciitaxggxxx|<ccc<ggxgg1c}cctfffffff;;;y;;y;;;t}ooc}www}c}ccwwww4<w<vw}cc#)pp5)up5(uu(]",
+"*q]%&&&&&&%%i;ikf;f;icw}w444wwwooowww;ffffffkfffff;ff;;iwtwvgxxgx4cwt4rxrxxgxactwcccecctwttwwctcttwcweeaxxacirrr<gbxwwtxgxvtcweessgwkwshswcttcwctccctccictcccwocc}cttcctvgxrxgracwwt|gggsxwow}if;ff;;yy;;;;y;y;;i}cc}www}w4wewww=tw}w}}e4ec8)p05)up(]0j8)",
+"q^&'&&&&&&&&i;;;;;;;itw}}=}t}oowwwo4oy;ff;;f;{fffffff;;iwcwrgggg|wtwcvrxxxxgvwcccctccwccww}cttc}}ttwcccess9itggr<bgxtttrbgvtwcccrsxxvrx60tittttcciccitttttcciotticttcccc4r|xxgr4cwccrxxg6xw}cck{f;;yyyyy;;;y;;;;;4ctc}c}wwwcwc}w}}w}wwwwwwe5)pp5)up(]pu5)",
+"^=]@@&=&&&&=i;;;;;;;;}4w}w=}w}c}wctct{f;ffffff;fff;f;f;ktw<x6@xxrtwc}w1gxxrrwcwcwccccccccttctttt}ccccccwssgiwssvvbgrtitrb6vcccic9xsggssgattwtttcccttitccecccccctoeectttcrxxxggx4wcwtxx@ggxwc}ckf;yyffyyyyf;yy;f;kcoewcccccowww}}ciwccww}ccc8)pp)2up:)u-()",
+"v=gh$::&&&%&t;i;ki;;itww4w=ww4}ww44}cf;;;ff;ff;fff;f;fkt}tw|ggrxr}cwtvxgxgxxrwctctww}tcctttccttt}ttwccctrggi9gxwwggritivbbvcccccxggw<<ggxctccctitcttiticciccoccitceiicw1sgxgxgx4wctwxxggb1wwocif;yf;fyf;fyfff;y;i}tccwwwow}ow}w4wccwwo}w}tc#5225)pp:(p7#)",
+"]@$&==&&&%&&t;;i;k;;;}ww}woo44}4}}<wc;ffff;f;;fy;ffff;;t}w4vgxgxxwtww4|gxxxgs9ctcccwciitttccwcc}twcccwww<ss<xsxi<sgxtik|gbaiicwwggrccirsswctticciiitticecccwcwcoootttirgbgggggxwitc9gggbs9wccciyf;;;fyyyfy;fff;icwto44w<tcctc}}ecweeewcwcwa8)pp))up#5pu:)",
+"@h&=&&&&&=&&;;iiik;;tw}twwww4w}}}wwwoif;;fffffffffffk;;ttwwrbgxggrctiwxggxxxgg9twwiiccciiwcwcccccctiiiictgsrrgriwssg9w9xgbwc99twgggwitrggeciiiiccitctttiicccicicociiikvxbbgggbgxrrs6bggg|wiitcifffyyy;yy;fy;;;fk1<cc}oweowo}}}cwccewwwceecwi)p2()uu5(pn5)",
+"@%&$&&&==&&1tfikk;f;wwwww}}}c}w}}4}w}i;ffk;ffffff;;;f;twtttwrggggsgrrxgbgggb6gvitttcccccccicccctcwcciwcwtxbxssacwxgggxxgsgwwxsawxgsxrxgsgoitttttccitccccccccccooocicctwttt}}wvssssggggbb1wcccctkfffy;f;yy;;fy;;}aceoo}o}w}w44}44wccctcwwwwe55pp5)pp()pn()",
+"$&&==&=$@$$gtii;k;;icww44w4wwww}w=wowct;;;;;;;;f;ff;;;wtw}twvbgggggssggvwtw}tt}twwticecciicccccitciccctctrhbshactcxssssxxwcashawwxgbgggn9citcccciiiitcccictitwciititccww}t}tt}rxsgxggggrwtcicccc;f;;yf;;ff;;ff;tooeccoo}w}t}}wccc}wwwwccwwee)p055pp:(pn5(",
+"==&&$@%$%t|_i;;k;;itweect}w4wcw}}ow}}w}k;;;;;;fff;k;;tttitt}wrgggxxgggr}twt}}wct}tccctctwwc}cccwccttcttitw9wewtctww<99wwwwcc9<titt4wecaectctiiiiiiiiiiiiccctictcccciiitttittiwxgxggggbr4tcccccttiyyy;fyfffy;;;i}tooccicccitcccc}4oo4}t}ttce85pu)ppp#(pu8(",
+"&:&&&$&&=&*3;f;;;iw4vweecwcw4wcw}<eo}w}i;ff;ff;;ff;ic<wwtww}t<1bggggxxxwitttitttciiiic}tt}twcctttittciitttwwccwctwcwwwwctittcwiiwtwcccccwtitiiiiicccccticc}tcc}cciicitiittittwxgggb6x9wttticocctti;y;f;;;ff;;twwctooccicwcccw}cwww}w}}w}wcci5pu()u0()pj()",
+"h===&===&ql>k;;kicewwoooe}wtwww}}cwwwwwwwi;;;;kf;tccwccwt}wwwtwvxbbgggrww4ttccccwcecw4cttcttwwticwwwwtwwtcwccwwtttctcwwitww4cwttttwcwiccccccccccccccictcctittwtiiccctitititttwvxgxxvwwcttiitccc}}ciif;ffyff;t4w}ceccecw}cwc44cctt}c}t}wcoeee52p85pp#(2u()",
+"_@&&%&&=h//_;itcaecwtcwoec}c}}=4<wwtcw}wciti;itiiitwttttttt}tttwtvrxxxvctwtwittccccco}tttttcttwtccccttittwtcccttictttttwttccwttttccccccwcctcttcciiiiicccitictctciiiiiictctttttttiiictttttcccctcicttikkiikkiwo}}}wwwwoccocwwwcwcwccc}cwweocc55pp))p05(pu:<",
+"h_&&%&=$>3qgww<www<9woecw}wwww}w4wcc}tww4wtww<v44w}twwttwtttwcwwwttiwtctcwtittc}coccicoowcwwitctiicwtitttccwccwcwwcwticciicccittccccociiccttcitccccciccccccctoccctiitiicwtittcictiitiiiccitewcctttticcwewawct}cwtwt}c}ccccic}}owee<4wcoeeocc5pp()pp:(2,5(",
+"qq]%%&=@/>_xcwwwww<9wwtc}www}}w}t}wcwc}wcwwwwwwwwtwwwttttt}twtcttttttitiicccccttcciiicccccitctttiiiccccwttctitccccctctttiiicccccctcciiitctiicititcccccccttttcccciiiciiiicittciiciititiiitiiiiiiwccccwctciccwoccccccccctcwecctcw}wwwwccccccct52p()p0#()u#(",
+">q&%%&&_/*_xccwtt}w=twwwwc}=t4}}}ccwwwwtcwtt}wwctwctwtwtttttwctwitcitiiitcctciitcttitcwccoitciciiictwttiicttitwccccictttiictccciitctittiwccecccciiciiiciititcccttttcccticiccwiciiciictciiicoccc}ciiciccwwccocweccccccec}ccottctccccwwctwwoct(2p)5p055pj((",
+">qwv&=$q>q_gtwwcwwwwttwtccowt}twwwccww4wccccwwcccwtw}}ttwtttttcctttictttiiitciiticcictcccccccitciciiictiicicttccccciciciciiiitciitttcicit}tcciciciccitccc}cticttccttitctiiiiiiiiicciciciiciciccttiicoccctcc}cowotccccct}}ccccc}}}ttw}}ccwwc#52p850u((2j((",
+">b=%&&6q*q_hcwwwctwww}w44ccc}icwcctctwcwcccccccct}c}t}ttwwtwcitciiccttcccctictcccciiiciicciicctccccciiccccccicciccciccctccccticcccccttiiccccoiciciiiiiiciciitcttcictiikiicciiiiicccccccececiciiicwceoccttoccccw}c}wtwccooowo}cccc}}}ccw}}ctk520552p552u5(",
+"hi%@=%hq*q__iwcwwcw}}weeeceewcew}cwwt}wcccwcwwwcwtwtt}twcciticcctcictwiikk;iiccccikiiikiiicciiitkkiiicccccikkiitccccittcwiitiiiccccticciiikkiiiciiikkikikiiiiiikikikiiiikkiiiciitiiiccici8iicttttiicicccceiccciciow}}ccwcccc}cc}ctcw}}ww}tti5p2852p##2u5(",
+"=<66&@bh__*qiwcwccctwaeewwccowwwww}ctt}cicwc}wwwttttictttctctwittwtttiie9rxr9ekii1r11rrxrccct41r9r9accciii4r1r4ctiiwctttiiiiixritiittiiw1r9rraiitwxrxrrrrrioiw9vr9r9wtiiwrrxr9rvtccicccccciiocciiticccccceccccowowctcccww}c}cowtcc}coo}}}}t#(p0552u58)u((",
+"16@&1_[[h**gtcwcw}}}c}cccwccew}}wwwwwtcwcwwwwctct}tctwtttcwiittccctwtirrxgxgxxvii1gsxxxxx4tt4gxggxxx<ccii9rrggwitcwttwttwickag4ictiitc<rxxggxx9ki4gxrxxxxxiccrxxxxxrriiirx0xxxxxwicctiiticcccctiicccceceoctc}occccctcwctc}cwcwe}wccccccccwct5)p552u552u)(",
+"6b==n-jjjrc<iwccwcwt}cwcw}}cwccwwwctwwwwoccwttwcwtctttwittcttwcttttctixxxv4rggxiixsxw4wv4ttirggr49xxriitrgxsbg4tcitcicwitiii|xiiiccicixssv9agsgii<ggaeeeaeii4xgx<axnxciwxxxrrxsx9kccwccccitcccoocottciccccccoccttwiiicicicowcccwtt}}}woowwc5)2p55pp5)2u((",
+"%==1jj02)<&v}}oeecwcw}4wct}cw4}}}}tcwccwowwt}}w}wwcceicttcwttciititccwgbrtctvr9tixsrtwwciktigsgtitghgiirggrrssviciiticwcttiv6<icccicctxgxkikgggit4gbicwiciii9ggwkiasgak<ggaciensxkicccccciitccocciicccecetcicicccwwct}cwccccw}c}}cwtccccwwti520)52p5#2n((",
+"&=p-j25:====tctcccwtwwwtww=w4tt4w}wwwwcccccitt}cccccwccwcwtitcittkictwgg4t4ccw;t;xgrrrxraii;rsgw}wxbrii<gri4gx<iiitkitccit;gxiitttikiirgg<w4xsxktvgxrrr|1wiiaggaccrsgwiagswiiixsgkcctccciiicwcicccccccccocicicccc}cciwctt}wwwwwctwc}wt}cwoo58)p552p##2u55",
+"=%-u55======wwcttt4}=w}c}t44=4ww}wwwwwwcwt}t=}tccwwwccicwcwtwccctttciwggxxrxxrciigsgxgssg<it}xgxxxbgw;ii4ti4gsvcccttcttctivbwiiitiiic;c0gxxxxg}iiv6gggs6x1iti9xgxrxg9ikasgiikingnkcciiiictcttctc}}cticittccciccttcc<reiccctcctttc}tcttc}wcti5)p#52p#:)u(5",
+"9du8(&$&==tttwwct}tc}}t}w=w}4}}t=}}wwwwcwcwtwwwwccw}twtcwcwttccciticicggbxxggxrkixr9ww4ssrfiwsgxxxbg<ttttitagsvicctiicctitgritttcicwckagggxrggw;iarrvt<xxxcitrxxrrgsrtk9sniccixsgiticoctctcttctc}ctc}oooccccwcttc}ccocccccttwwwtwcw}t}}cccc552p)(20(}2n(5",
+"~p(]='&&=&@xcwwwwwcwwwccw}t}}t=cwwwwwcwttwtttcwccwtttcctcciwwcccittcicsg9iiwggrkitictwtssxftxgrtiivgxiiciitwgsriwciitctii4xwiiittiiwicxgxtctxggtiiiiicivggc;axgeiiwxx4;<ggciiigg0kicciciccttttcit}t}cocctttiwctwttcicccccocctttt}t}ccc}cctii#2p5(2p5:2u)5",
+"p(======4nnvtcw4t}ccwww4wt}wwwwcwcccc}ctcw}}wwwwctccwwwtwwcttccwccttiwgxv;;ixgritaww;iigggiwgg9ii;9xxtitiiiwgs4iccwctcittrriiittiitwitxgriikrxxic4<wtii9sgwirssikicxgrkesgekiixgrktiiictitcttttitcti}ccocwitttccccooccccicwccct=t=}w}c}c}cc##2u552u5:20)(",
+"(===&:=$-u5e}=w}t}twc4wc}tt}wwwtccwwcwcctwww4ceoeccccctccttcticccicctcgsx<wrbb1k}rxrw4agsrkcgsx<w4g6gwt}tttwgsvitciicttt<g4ttccccitiitxgg4aaxgsic9xx9twrggcivsx9ww9ggvkwgn099rgg9ititittiiiccc}}tt}cttccittttccccccctcciiccticttt}ttciccttci8)p552p5:)p((",
+"=====:[+2:}=}wctwcwcw444w}ww=}t}44aeewtcwwcwwecowcctticctiicciiwcoctttvbbgxxgg4ii1bgxgxsgaccrggxrgbsritttitwbbvkcceccttirxcttttttttiiirbgxxg6[xiiwsgxrxgs9iiwssgxxgggwiixggggxgxcicitctt}tccttittctccitiiiiicccccittciccicwwwctt}ttwccttott##2p5:22(#)u5#",
+"=&==&^,(::==}cocwtwwwwc}cwwwwwww<wwwewwccwowcccccctwctcci}iwcciccccccitvrxrrrwiittvxrxr9eciiw9rrrxr9titttttwxxacicccccc4g<twticttittttcarrrr0acitt<1rxrrvwttiwvrvrvvtitcia9rr99wiitiittttiit}titctiic}tiititcticwcctcccicwttccwt}}}t}twccctt#)2552p#5)p(#",
+"&&='du5==&=4}ccttwwwwcttw}wcw}cww}}w}wwctccwcccww}cwwttc}tcccccciccccciicciic}tcttwtccccccitccciitccitcwttttcccieciicccxrcioitccc}twctctccitcecctttitctttiititiiititiiiiiiiitittikticciiiiiccccc}tcitttccticcctccwcctcccitttttct}}t}iiccc}ci#)p]22p5:2u(5",
+"==^^':===&===4}}tcccw}t}}w}cewwctc}ctc}ccwweccttcciict}wwcctccicicccttttttttttwctittitciciccittttttttttcwctitticicicciwrwttcictcc}itttiicciicctcociitwcticttttttkiiiiiiiiiiitttiitiiiiiicct}c}tiicttcttccciciitwcwccocctcccwccwctct}wwcctcti#)p5()p:#(0)5",
+"]^^]:=========}tcwewwwwwttcwcw}}wwt}=4wwcceoowc}ccctctitwccicccccttttittcttcctttcctttccccccttttittctccctttcttcccccccctitttctcc}ctiwttcttcccccticcccitcctctwtcttwtciiiiiccttttiiiiciitciiiicct}tcwtccctcttiicccittcccctictttc}ccttwtccwccccci5)p5#]05#)p55",
+"j0(:&=&=&=&v}}wwcwcccct}w}wv9v<=t4}w}ttwoeeccoc}cccttcitcwceccccttcttiiticttcttcwtictcccccttctitititttwitcwticcccctitciiititttcttcctitttccccicccctctttttctccwtittiicctiiiiiiiiiciccccc}coitcictiiiicccccctccccwiiiccccttt}}t}twtittcccctccti#(25#)p(:(p#5",
+"'===&&====g9ct<}4wcwcc}}wwww<4v<4w}}}w4cecoooccwtctctctctcccceoccttctcccwwcwwctwitccccccccwccwttcwcwtccwccccwccccwwwcwcwccwwwc}}ctcccwcciccccctttttttcttcctttcttctcttiitiiiiticitiiit}}ccicttcikiitccocittwci}ticiccitttt}titttciicttctitct##(2(()p5k)p(5",
+"==&==&==$^jacctttcewwwwwtwwwww<vvw}w}}}ccowooowcctttwwcticceccwiitictttwititttitt}cccccwctccwctcwwtttcwwttwwwccctcwcwccccwcccct}}=tcttcicocccctctittttwicwctwwttttcctiiicwitttciiitiiiccccocccecoctciiitctc}tc}tciccccwtttcitccwcwcctt}tittki(p55)p:#(0)5",
+"=======xdn)cc}tccewwwt4<w44w}w4wwcwcw}}aecw4}ccccitctcittcctcwcccccwcctiiicttitttccccitttiitwcww}wcccwccwcccccwwcccctwtc}cccctttttttt}ctcciciictcitctitttiiiiitticiiiiiiiiittittkiitiiiccecccccccccttwcctttittccccctitttttcccitctttcttttttik#)p5#)p:#)p(:",
+"=&%&=&^j)#:4t=wccocww}wwccccw<4w}wtcwcw4ocww}cccciicw}cciitwtiicccittcctttccttttttittcttcwccttt}ttcctceccccociccccccctcc}cwo}ctttt}=ittiiiicicoctccciiiiiiitttccciitciiiiwiiciittctccccicccctcctcctwccc}tttttttcccitctiittcctitcitcittttt}ti#)p5#)p(;(u)5",
+"&&&=@-,(===<}}}wowwww}}cww44w44wwwww<4w}}}wctccwwwwwttctwcwwccewccowwc}cc}tttt}=w}wcccwcwcwwwcwwctwwoowcwwcewcwwwccwwww}tctccttttw}tt}ctcicwccccccwcccttiitwwcwwcwitciciiccccccctcwccccceo}ctccccticcwctccwc}c}}ticctctctttttcccciccitctttci55p5#)u:#)u]#",
+"=:&jj](]====tt}tcc}ttttwtwtcctctcttcc=ttcttcwcctwcitccciittcciccccticcttiiitctttttccticwccticcitccccccccccwcicoicitctwtt}iiittttctccctcwiicctitctciiiitttiiiiiiiiiiiiiiiiiciiicittcctiticiitititiiitiiiitictiitiitiiiiiiiitiicctciicititiiti#(p(#)p5#)p)k",
+"&$dj]=&&&==}itiitiit}tiitiitcttcccwtiiiitttiiiik;kkkiikkikkkk;k;;;kk;;;ki;;;;;;;;;k;i;ii;kkikkkkk;ikkkk;kki;;k;;;;;k;k;;;kk;;;;;;;;;;;;;;f;;;;;;kf;fk;k;;;;fk;;;ik;;;kfk;fk;f;kk;;;;;;;ff;;k;;f;;y;;;;;;;;;;;;ff;ff;;i;;;;;;;ik;;kkk;;;f;;;k#(25#)2:;(2(#",
+",^]:=======;;;;;;y;y;f;;;;f;;;;;;;f;yy;y;;yfy{{f{yyyfff{{{{{{{{{{{{{{{{{{{{{{y{y{{z{zzz{{{{{{{{{{{y{y{{{y{yy{{{{{{yy{{yy{{{{{zz{{{z{{{{{{{{{{{{zf{{{{{{{fff{{{y{z{{{z{{{{{{f{{{{{{y{{{{yy{{{{{{zz{{{{{{{z{{{{{{z{{z{{{{{{f{z{y{{{{z.{z{{{y;;t)p(:)p5#5p)5",
+"u]=&&&=&&==;z{{zz{{{{zz{z{y{{zzzz{{zzzz{z{z{{{{{{{z{zzz{zz{.{{{{{{z{{{{{{{{{{zz{{{{z{{{{{{{z{{{{zz{{{{{y{{{{z{{{z{zzz{zz{{z{{{{{z{{{{z{{{{z{zz{zz{{{{z{{zz{{z{zz{z{{{z{zzzzzzzzz{{{{zzz{zzzzzzzzzz{zz{{{{zzzz{z{{{y{{yz{zzzz{{{{y{{f{y{zzz{;#52#k)p(#)2)#",
+"<=&====&=&&=yy{{yf;kk;kff{{z{zz{{;;k;;;;fz.zz..z{i;kkik;fzzzzzz.f;k;ff;;{zzzzzz{f;k;;;;f{z{zzzz{;kkk;f;f{z.zz.z{f;;;;;;f{zzzzzzz{;;ff8kffzzzzzzzfkfk;;ff{zzzzzzzf;;kkkf{zz{..z.{kkfkfkkf{{zz{.z{fkk;f;kff{{{{zz{;;;;fff{z{zzzzz{;fffff;zzzy;i(258)p(5)p)5",
+"=&&&==&=&&&=;{zz{fcikkiif{.z.zz.{iii#iiifzzz.z.zfiki8iicf..zz.zzkiikk8ik{...zz.zkiikkki;..zzzz.zk8ci8ikf..z.zz.{ki8i8k8fzzzzzz.{f8ffi888fzz{{..zkikkkcifz..z.z.{ik;kfkkfzz..zz.{iicceii8fzzzzz.{keciieck{z{{zz.{cic8ieif.zzzz.{fc5e5ceiy.z;:k(2(8)p:k(0)#",
+"===&=&====&%=;yz;a00n0n0ez.z...y4~n~n0n0e....z.fannn0000i...z..fan0nn~n0f......fnn00099ef.....zfnn0n0n0ef..z..zk9000n00af.zzz..fe0000009f..z.zzf9000009cyz..z..f9nr0009i.zz....f000u00098.zzz..;900n00098..zz.zf0000009ez.zz..fin000n~0#{;))k(p(5)25i(2)#",
+"=:;:====&&=&&=;zf9sn0n00cz.z..zye02092p2i...z..{e0r00009c.z....{e009p200f....zzfr99000p9f...{z.f00900009f.zzzzz89000000akzz.z..fe00009098..z{zzfe2990099fz.zz.zf9000009e{zzzzz.f0p200009i.z..z.820000009;.zz..zf00000000zzzzz.{8nnnnn~05z8));525k)p(:)2)5",
+"=&q333*@=&&&%%=ir_[[-[[n){zzz..f9nsnjnnn)..z...f9sn~n~~0)..z...frs~s~snnf.zz..zfnnsnnjn0f......fsn[nsnjn8......f0ns~sjs08.z.zz{k0ssjsns08......k0[jnsnn~k....z.knnsssssn8z..zz{k~s~~[s[nc..zzzzknjs[n[nn8..zzz{esj[[[[s0{zzz{{fe-[-h-__h;52)#(2)#)p:;(225",
+"%q/qqqq*%=&&===4_*___d_mnifz{z.;n_-_-dh-x..zz..k0_-h--_-r...zzz8n-[_-_d_a.zz..zf[_d_-h-_e.z.{zzk-_d_d__he...zz.i[d_-_d_-9..z.z.8~_-_dd_[9.zzz.z8[__d-h-[a.zz.z.k[__-_-_ha{.z...k[_-d_-_-9...z{.5[_dd_-_hw.zzzzzc-_d_-___k.zz{{{e___q_qq*r#))#52(k)p:;52)#",
+"6>*qq***q==&===&_qq_____nfz{{z.;0__-____~..zz..f0_______0.{....is_______a..zz.zf[_-_____a.z....f[q_____q2.zz...i[q_____h0..z.zzig____-__r.....zk[__-____r..zz.zfhq______az..z..f[______[a.z.zz.isd-_-h-he.zz{.z8__-__-_[i..{{{z5__-_h__-ck228(2);)0(k(2)#",
+"h>qh__q>q!<&&&=cx[[[[--[p{z{{{zf9[[[s[-[r.....zfr_[-[[[[9.....zfn_[[[[[[o.z..z.f0[--[--[e.z.zzzfn_[h[[^ba..zzz.ks-[[[[[sa..z...8n-s-[[-[a.zzz.zfn_[[[[[[e..zz..8s-[[[[[se.zzzz.k~[[s[s6sezzzzz.knsss[[[so.z{zzz8n[ssss[gkzz{{{z8sgs~gnnx#8)5k52(8)p(:)2)5",
+"h*qq>*>>q!<$&==tw0nnnxn02{z{{zzfwnn0nnn09{zzzzzfennnnnnnaz.zzzzf9snsgnn~c..z.zz{9nngnns~e...zz{frnng~n~na..zz{.;9nnnnnn0c.zzz{zk9n0nnnnne..zz.{f9n0n0nnne.zzz.z{0000n0n0i.zzzz.;070000nri.z.zz.kr0000909f.zzzz{ir0090099fz.{{{ftp2r9rr9ak52)k#)(k(258(225",
+"6q__**>>h<=&&=ttie999a2aakfzz{z{8aaaaa92ef{....{ir990992afz..zz{i99999r9efz.{zzzc99r0r00c{..z.z{ar0r090pczzzz..fc090929ac..z.z.fe2922a2a8..zzz.ze2a22aaakzzzzz.faaaaa)ae;.zz.z.kae9aaaac;.zzz.{ieaee9aeof.zzz{fee)aaeeec{z{zz{kaeee5c5ikf#))k(2(#(p(k5)):",
+"gh__*>>/6:<v===t;fkf88888kf{z{z{zf{8f8f888{.z{z{{fff;f8fffzzz{z{{f888k8kf{.zzz{zfki8iiki;{{zzz{zkki8kkkkfz.{z{zz{ff88fff{zz{{zz{{888888{zzzz{zzz{fffffffzzzzzzz{f{f8ff8fzzzzzz.z{fkfk;{{z.zzzzzfffffffffz.zz.zz{{f{{{{zzzzzzzz{{{{ffff{ff#))#5)(#)2)::]):",
+"b__q>>>*1=&&====;ff.z{{zzz...zz{zz...zzf;y{zzz.zz..zz.z.z..zzzzzzzz{{.{z...zzzz.zz.....z.zzzzzz.{zz.{zzzz.z.z.zz....zzz..zz.zz....z...z.z.{zzz......zzzzzz{zzz....{zzz.z.zzzzz..z.zz....zzzzzz...zzzz{zz.{zzz...z.z.zzz{z{{z......z{{{zf##2)k52)5(p(:52]#",
+"g___*q_g:=%%====kf{{zz..z.z{zzzzz.zzz..z...z{{z.z....z..zz.{zzzz........zz.z{zzz.......z..z.zz{z..z.z.zz.zzzzzzz...z.zz..z{zzzz..z......zz{zzzz..zzz.....zzzzz..{8fzzz..zz{zzz........z.zzz{z{{.zz....z{z{z{{..........z{{{{z.....z.zzyy;#))##2(#(p5;:))5",
+"bhhh_h,==%@%===ik{ff{zzzz..zfzz{z..zz.zz...z{{{{......zzz.z{z{z{z.........{{{{{....z.z....{{{{fz...z.z{..z{{{{{z..zzz.z..{{{{f{.zzzzz.z.z{{{f{zz..zz....zfzf{zzzzz{{{...z{{{y{zzz..zz.z.{{{z{zzzzffz{zzz{{{{z{zz..{.{.z{{{{{{{.zz.{{ff;ff#));:2)#)p(;(22#",
+"h_h_*6t:$6$&=&==iktkffff{yf{f{ff{{f{{z{{{{f{{{{f{{{{fz{z{{{fff{{{y{f{{{z{{f{fff{f{{f{{{z{{f{fff{ffz{{{f{{{yy{{f{{{{f{{{{{{ff{f{{z{{{{{zz{f{f{{{{fzz{{{{z{fzf{{{{z{{ffff{{f{{{ff{{z{f{{{{{{{{{{f{{f{{{z{{{z{f{{{{y{{{{ff{{{{{{ff{ffffffff;#));#225(2(;:)2#",
+"x[_*q1%hh@===%=tikik;kffffffffffffkfffffyfffffffffffff{y{{f{ff;ffyfffffffffffff{ffff;fff{ffffffffff{ff{{yyyf{f{ff{{{{ff{{fzff{{f{fffff{{{ff{{{fz{f{ff{f{{{{{{{ffffzf{fff{{{f{z{{{{{{y{{f{{{{{z{{z{{ff{{{{zffff{ff{f{{{ffffff{{f{{f{ff;;f;5)(#5225)25#5)2#",
+"rnjnax_@&=====:;;i;iii;kk;k;fffff;fff;fyyyffffff;fffy;fffyfffyyyyyyfyy{{{ffffff{ff{f{f{f{{{yyyyfy;f{{fyf{{;fffffff{f{{ff{f{{{fff{{{z{ff{fz{f8fff{z{{{zf{{ffffffffffffffffffffff{{{{{{{{f{f{{{{{{{{{{{zffkeecikff;592e8ffk;f;fffff;;ii;ifi))#k:)25)25#()p:",
+"2jup&@&=:==&&&&==&&===:tic888k;;;;ffyyyyy{y{{fffkfy{{yy{yfy{{{{yz{{{{{yyy{y{{{yy{{{{ffk8ff{{{z{yzz{{{yy{{{8f88f8ffk8fff{{{{zz{{{z{{{{fffz{{{f88ff{z{zz{{zfffz{{{{{{f888f88f8f8ff{{y{{{{ff{{f{{{{{y{ff{fkecik;fyf5eike48;fyy{;ff;;;ik;i#22(k;;#2p5)p):=))#",
+"p-25::;===:;:;=&==&&:=;::58888;y;y;y;yyyy;yy;yf888ff{{y{{y{y{yyyy{{{{{yyyyy{y{{{yyy{{y;8ff{zzz{{{z{{zzyzzy88f8ff8f8ff8{z{{{{z{zzf{{{ff{z{zzzfff{888ffzzzzzffzzz{{{{f8f88888888ff{{zz{{fff{{{{{{;;fy{y{f:({zz{{{;akzz;e(;{y{y5929]p2))2225:;;#:))#5p5;:)2#",
+"0n(=====:%q//>@&===:=:=:))8585;yy;yyy;;;yy;yyff;8888;y{yyy{{{{{{{{yyyy{{yyy{{{y{{;yyyyk8f{{yyyy{y{{{zy{{{{kff88f8f8f8f8f{{{{{{fz{f{z{{{{{{{{z88eaeee5cf{{{;f{{{{{zff88f888f88888{{{{{;f{{{{{{k#eeci;{{;epr9'}kk(rky;k((yfy;59a)a0njn2))#;;::#522852(#5()#",
+"up):=:==@33>*q>h========2)5)855;;;;;;;yyy;;yyyy;#8888kf{yyyy{{{{yyyyy{{yyyyyyyyyyy{{yy#k{yyy{y{zz{{yz{yy{{yf8f8888f8f8ff{z{{zzzz{zzzz{{{zzzzzf5555e5e)5fz{kf{z{{{{f888888888888f{{{{8;{{{{{fkaa29a2a#y;<n~0rr]5)9kzy5aa{yy52e8iee)n-0)5;;;;:;:))5(p(k5)]#",
+"p):====%*>g@g_*q&==:=;y#2858885;yy;yyyyy{yyy{{{{85588##yy{yyz{z{{{zyyyy;yyyyyyyyyyyy{y;kyzy{{z{{z.{z{y{{yzzz.{88f8f88888f.z{{zzz{{{{{{{{{{{f{f88eee85ee8{fkkz{{z{{f8888888888888{{{;8fzzz{z;5ea22009(y#arkzfipcerkf85e2yy;9[hn22000j0#;;;::;#52(#52(k:))5",
+"p2==:=&@3qrn_q6q@:=@666,u2)))855;:;y;;;;;:;;:::#())8888#;y{;==}=:;{yyyyyyyyyyy;yyyy{{{;kyyyy:|xx'!1f{{yyy#0np22))22)222020rxr9r9;{yz{{{cs[snef8a)))iic5c{fk;zz{y{{f8888888888888{ff8fyz{yyz#9)ea0002ey;(ri.z5aicr888k#v{fknq>*0[__0nak:::;:::))#5)2(;:)]5",
+"p(====%h*_b6_q>*6&*3/>*+-----jj6,666h66@@6@@,b~s~nn0255]&:;:9x,71=yyyyyyyyyyyyyyyyyyyy;k;yy;<77r9(;y{{y{y;ea9a2022)a2a2a2r99aaekf{{{{{f;5(9vif8e2ai8i5e#fyk;{y{{y{88588888888888ffk8fyy{{{;e2e)a92r2e;;5a0n7pekc)5k;;ki;#(j_/>neea94:;;:::;(2(#:#))5:()):"};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xmms-sid.c	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,1005 @@
+/*
+   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
+
+   Main source file
+
+   Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org>
+   (C) Copyright 1999-2005 Tecnic Software productions (TNSP)
+
+   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 "xmms-sid.h"
+#include "xs_support.h"
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <stdarg.h>
+
+#include <audacious/plugin.h>
+#include <libaudacious/util.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include "xs_config.h"
+#include "xs_length.h"
+#include "xs_stil.h"
+#include "xs_filter.h"
+#include "xs_fileinfo.h"
+#include "xs_interface.h"
+#include "xs_glade.h"
+
+/*
+ * Include player engines
+ */
+#ifdef HAVE_SIDPLAY1
+#include "xs_sidplay1.h"
+#endif
+#ifdef HAVE_SIDPLAY2
+#include "xs_sidplay2.h"
+#endif
+
+
+/*
+ * List of players and links to their functions
+ */
+t_xs_player xs_playerlist[] = {
+#ifdef HAVE_SIDPLAY1
+	{XS_ENG_SIDPLAY1,
+	 xs_sidplay1_isourfile,
+	 xs_sidplay1_init, xs_sidplay1_close,
+	 xs_sidplay1_initsong, xs_sidplay1_fillbuffer,
+	 xs_sidplay1_loadsid, xs_sidplay1_deletesid,
+	 xs_sidplay1_getsidinfo
+	},
+#endif
+#ifdef HAVE_SIDPLAY2
+	{XS_ENG_SIDPLAY2,
+	 xs_sidplay2_isourfile,
+	 xs_sidplay2_init, xs_sidplay2_close,
+	 xs_sidplay2_initsong, xs_sidplay2_fillbuffer,
+	 xs_sidplay2_loadsid, xs_sidplay2_deletesid,
+	 xs_sidplay2_getsidinfo
+	},
+#endif
+};
+
+const gint xs_nplayerlist = (sizeof(xs_playerlist) / sizeof(t_xs_player));
+
+
+/*
+ * Global variables
+ */
+t_xs_status xs_status;
+XS_MUTEX(xs_status);
+static pthread_t xs_decode_thread;
+
+static GtkWidget *xs_subctrl = NULL;
+static GtkObject *xs_subctrl_adj = NULL;
+XS_MUTEX(xs_subctrl);
+
+void xs_subctrl_close(void);
+void xs_subctrl_update(void);
+
+
+/*
+ * Error messages
+ */
+void XSERR(const char *fmt, ...)
+{
+	va_list ap;
+	fprintf(stderr, "XMMS-SID: ");
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+}
+
+#ifndef DEBUG_NP
+void XSDEBUG(const char *fmt, ...)
+{
+#ifdef DEBUG
+	va_list ap;
+	fprintf(stderr, "XSDEBUG: ");
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+#endif
+}
+#endif
+
+/*
+ * Initialization functions
+ */
+void xs_reinit(void)
+{
+	gint iPlayer;
+	gboolean isInitialized;
+
+	/* Stop playing, if we are */
+	XS_MUTEX_LOCK(xs_status);
+	if (xs_status.isPlaying) {
+		XS_MUTEX_UNLOCK(xs_status);
+		xs_stop();
+	} else {
+		XS_MUTEX_UNLOCK(xs_status);
+	}
+
+	/* Initialize status and sanitize configuration */
+	xs_memset(&xs_status, 0, sizeof(xs_status));
+
+	if (xs_cfg.audioFrequency < 8000)
+		xs_cfg.audioFrequency = 8000;
+
+	if (xs_cfg.oversampleFactor < XS_MIN_OVERSAMPLE)
+		xs_cfg.oversampleFactor = XS_MIN_OVERSAMPLE;
+	else if (xs_cfg.oversampleFactor > XS_MAX_OVERSAMPLE)
+		xs_cfg.oversampleFactor = XS_MAX_OVERSAMPLE;
+
+	if (xs_cfg.audioChannels != XS_CHN_MONO)
+		xs_cfg.oversampleEnable = FALSE;
+
+	xs_status.audioFrequency = xs_cfg.audioFrequency;
+	xs_status.audioBitsPerSample = xs_cfg.audioBitsPerSample;
+	xs_status.audioChannels = xs_cfg.audioChannels;
+	xs_status.audioFormat = -1;
+	xs_status.oversampleEnable = xs_cfg.oversampleEnable;
+	xs_status.oversampleFactor = xs_cfg.oversampleFactor;
+
+	/* Try to initialize emulator engine */
+	XSDEBUG("initializing emulator engine #%i...\n", xs_cfg.playerEngine);
+
+	iPlayer = 0;
+	isInitialized = FALSE;
+	while ((iPlayer < xs_nplayerlist) && !isInitialized) {
+		if (xs_playerlist[iPlayer].plrIdent == xs_cfg.playerEngine) {
+			if (xs_playerlist[iPlayer].plrInit(&xs_status)) {
+				isInitialized = TRUE;
+				xs_status.sidPlayer = (t_xs_player *) & xs_playerlist[iPlayer];
+			}
+		}
+		iPlayer++;
+	}
+
+	XSDEBUG("init#1: %s, %i\n", (isInitialized) ? "OK" : "FAILED", iPlayer);
+
+	iPlayer = 0;
+	while ((iPlayer < xs_nplayerlist) && !isInitialized) {
+		if (xs_playerlist[iPlayer].plrInit(&xs_status)) {
+			isInitialized = TRUE;
+			xs_status.sidPlayer = (t_xs_player *) & xs_playerlist[iPlayer];
+			xs_cfg.playerEngine = xs_playerlist[iPlayer].plrIdent;
+		} else
+			iPlayer++;
+	}
+
+	XSDEBUG("init#2: %s, %i\n", (isInitialized) ? "OK" : "FAILED", iPlayer);
+
+	/* Get settings back, in case the chosen emulator backend changed them */
+	xs_cfg.audioFrequency = xs_status.audioFrequency;
+	xs_cfg.audioBitsPerSample = xs_status.audioBitsPerSample;
+	xs_cfg.audioChannels = xs_status.audioChannels;
+	xs_cfg.oversampleEnable = xs_status.oversampleEnable;
+
+	/* Initialize song-length database */
+	xs_songlen_close();
+	if (xs_cfg.songlenDBEnable && (xs_songlen_init() != 0)) {
+		XSERR("Error initializing song-length database!\n");
+	}
+
+	/* Initialize STIL database */
+	xs_stil_close();
+	if (xs_cfg.stilDBEnable && (xs_stil_init() != 0)) {
+		XSERR("Error initializing STIL database!\n");
+	}
+}
+
+
+/*
+ * Initialize XMMS-SID
+ */
+void xs_init(void)
+{
+	XSDEBUG("xs_init()\n");
+
+	/* Initialize and get configuration */
+	xs_memset(&xs_cfg, 0, sizeof(xs_cfg));
+	xs_init_configuration();
+	xs_read_configuration();
+
+	/* Initialize subsystems */
+	xs_reinit();
+
+	XSDEBUG("OK\n");
+}
+
+
+/*
+ * Shut down XMMS-SID
+ */
+void xs_close(void)
+{
+	XSDEBUG("xs_close(): shutting down...\n");
+
+	/* Stop playing, free structures */
+	xs_stop();
+
+	xs_tuneinfo_free(xs_status.tuneInfo);
+	xs_status.tuneInfo = NULL;
+	xs_status.sidPlayer->plrDeleteSID(&xs_status);
+	xs_status.sidPlayer->plrClose(&xs_status);
+
+	xs_songlen_close();
+	xs_stil_close();
+
+	XSDEBUG("shutdown finished.\n");
+}
+
+
+/*
+ * Check whether the given file is handled by this plugin
+ */
+gint xs_is_our_file(gchar * pcFilename)
+{
+	gchar *pcExt;
+	assert(xs_status.sidPlayer);
+
+	/* Check the filename */
+	if (pcFilename == NULL)
+		return FALSE;
+
+	/* Try to detect via detection routine, if required */
+	if (xs_cfg.detectMagic && xs_status.sidPlayer->plrIsOurFile(pcFilename))
+		return TRUE;
+
+	/* Detect just by checking filename extension */
+	pcExt = xs_strrchr(pcFilename, '.');
+	if (pcExt) {
+		pcExt++;
+		switch (xs_cfg.playerEngine) {
+		case XS_ENG_SIDPLAY1:
+		case XS_ENG_SIDPLAY2:
+			if (!g_strcasecmp(pcExt, "psid"))
+				return TRUE;
+			if (!g_strcasecmp(pcExt, "sid"))
+				return TRUE;
+			if (!g_strcasecmp(pcExt, "dat"))
+				return TRUE;
+			if (!g_strcasecmp(pcExt, "inf"))
+				return TRUE;
+			if (!g_strcasecmp(pcExt, "info"))
+				return TRUE;
+			break;
+		}
+	}
+
+	return FALSE;
+}
+
+
+/*
+ * Main playing thread loop
+ */
+void *xs_playthread(void *argPointer)
+{
+	t_xs_status myStatus;
+	t_xs_tuneinfo *myTune;
+	gboolean audioOpen = FALSE, doPlay = FALSE, isFound = FALSE;
+	gboolean playedTune[XS_STIL_MAXENTRY + 1];
+	gint audioGot, songLength, i;
+	gchar *audioBuffer = NULL, *oversampleBuffer = NULL;
+
+	(void) argPointer;
+
+	/* Initialize */
+	XSDEBUG("entering player thread\n");
+	XS_MUTEX_LOCK(xs_status);
+	memcpy(&myStatus, &xs_status, sizeof(t_xs_status));
+	myTune = xs_status.tuneInfo;
+	XS_MUTEX_UNLOCK(xs_status);
+
+	xs_memset(&playedTune, 0, sizeof(playedTune));
+
+	/* Allocate audio buffer */
+	audioBuffer = (gchar *) g_malloc(XS_AUDIOBUF_SIZE);
+	if (audioBuffer == NULL) {
+		XSERR("Couldn't allocate memory for audio data buffer!\n");
+		goto xs_err_exit;
+	}
+
+	if (myStatus.oversampleEnable) {
+		oversampleBuffer = (gchar *) g_malloc(XS_AUDIOBUF_SIZE * myStatus.oversampleFactor);
+		if (oversampleBuffer == NULL) {
+			XSERR("Couldn't allocate memory for audio oversampling buffer!\n");
+			goto xs_err_exit;
+		}
+	}
+
+	/*
+	 * Main player loop: while not stopped, loop here - play subtunes
+	 */
+	audioOpen = FALSE;
+	doPlay = TRUE;
+	while (xs_status.isPlaying && doPlay) {
+		/* Automatic sub-tune change logic */
+		XS_MUTEX_LOCK(xs_cfg);
+		XS_MUTEX_LOCK(xs_status);
+		assert(xs_status.currSong >= 1);
+		assert(xs_status.currSong <= XS_STIL_MAXENTRY);
+		myStatus.isPlaying = TRUE;
+
+		if (xs_cfg.subAutoEnable && (myStatus.currSong == xs_status.currSong)) {
+			/* Check if currently selected sub-tune has been played already */
+			if (playedTune[myStatus.currSong]) {
+				/* Find a tune that has not been played */
+				XSDEBUG("tune #%i already played, finding next match ...\n", myStatus.currSong);
+				isFound = FALSE;
+				i = 0;
+				while (!isFound && (++i <= myTune->nsubTunes)) {
+					if (xs_cfg.subAutoMinOnly) {
+						/* A tune with minimum length must be found */
+						if (!playedTune[i]
+						    && myTune->subTunes[i].tuneLength >= xs_cfg.subAutoMinTime)
+							isFound = TRUE;
+					} else {
+						/* Any unplayed tune is okay */
+						if (!playedTune[i])
+							isFound = TRUE;
+					}
+				}
+
+				if (isFound) {
+					/* Set the new sub-tune */
+					XSDEBUG("found #%i\n", i);
+					xs_status.currSong = i;
+				} else
+					/* This is the end */
+					doPlay = FALSE;
+
+				XS_MUTEX_UNLOCK(xs_status);
+				XS_MUTEX_UNLOCK(xs_cfg);
+				continue;	/* This is ugly, but ... */
+			}
+		}
+
+		/* Tell that we are initializing, update sub-tune controls */
+		myStatus.currSong = xs_status.currSong;
+		playedTune[myStatus.currSong] = TRUE;
+		XS_MUTEX_UNLOCK(xs_status);
+		XS_MUTEX_UNLOCK(xs_cfg);
+
+		XSDEBUG("subtune #%i selected, initializing...\n", myStatus.currSong);
+
+		GDK_THREADS_ENTER();
+		xs_subctrl_update();
+		GDK_THREADS_LEAVE();
+
+		/* Check minimum playtime */
+		songLength = myTune->subTunes[myStatus.currSong - 1].tuneLength;
+		if (xs_cfg.playMinTimeEnable && (songLength >= 0)) {
+			if (songLength < xs_cfg.playMinTime)
+				songLength = xs_cfg.playMinTime;
+		}
+
+		/* Initialize song */
+		if (!myStatus.sidPlayer->plrInitSong(&myStatus)) {
+			XSERR("Couldn't initialize SID-tune '%s' (sub-tune #%i)!\n",
+			      myTune->sidFilename, myStatus.currSong);
+			goto xs_err_exit;
+		}
+
+
+		/* Open the audio output */
+		if (!xs_plugin_ip.output->
+		    open_audio(myStatus.audioFormat, myStatus.audioFrequency, myStatus.audioChannels)) {
+			XSERR("Couldn't open XMMS audio output (fmt=%x, freq=%i, nchan=%i)!\n", myStatus.audioFormat,
+			      myStatus.audioFrequency, myStatus.audioChannels);
+
+			XS_MUTEX_LOCK(xs_status);
+			xs_status.isError = TRUE;
+			XS_MUTEX_UNLOCK(xs_status);
+			goto xs_err_exit;
+		}
+
+		audioOpen = TRUE;
+
+		/* Set song information for current subtune */
+		xs_plugin_ip.set_info(myTune->subTunes[myStatus.currSong - 1].tuneTitle,
+				      (songLength > 0) ? (songLength * 1000) : -1,
+				      (myTune->subTunes[myStatus.currSong - 1].tuneSpeed >
+				       0) ? (myTune->subTunes[myStatus.currSong - 1].tuneSpeed * 1000) : -1,
+				      myStatus.audioFrequency, myStatus.audioChannels);
+
+
+		XSDEBUG("playing\n");
+
+		/*
+		 * Play the subtune
+		 */
+		while (xs_status.isPlaying && myStatus.isPlaying && (xs_status.currSong == myStatus.currSong)) {
+			/* Render audio data */
+			if (myStatus.oversampleEnable) {
+				/* Perform oversampled rendering */
+				audioGot = myStatus.sidPlayer->plrFillBuffer(&myStatus,
+									     oversampleBuffer,
+									     (XS_AUDIOBUF_SIZE *
+									      myStatus.oversampleFactor));
+
+				audioGot /= myStatus.oversampleFactor;
+
+				/* Execute rate-conversion with filtering */
+				if (xs_filter_rateconv(audioBuffer, oversampleBuffer,
+						       myStatus.audioFormat, myStatus.oversampleFactor, audioGot) < 0) {
+					XSERR("Oversampling rate-conversion pass failed.\n");
+					XS_MUTEX_LOCK(xs_status);
+					xs_status.isError = TRUE;
+					XS_MUTEX_UNLOCK(xs_status);
+					goto xs_err_exit;
+				}
+			} else
+				audioGot = myStatus.sidPlayer->plrFillBuffer(&myStatus, audioBuffer, XS_AUDIOBUF_SIZE);
+
+			/* I <3 visualice/haujobb */
+			xs_plugin_ip.add_vis_pcm(xs_plugin_ip.output->written_time(),
+						 myStatus.audioFormat, myStatus.audioChannels, audioGot, audioBuffer);
+
+			/* Wait a little */
+			while (xs_status.isPlaying &&
+			       (xs_status.currSong == myStatus.currSong) &&
+			       (xs_plugin_ip.output->buffer_free() < audioGot))
+				xmms_usleep(500);
+
+			/* Output audio */
+			if (xs_status.isPlaying && (xs_status.currSong == myStatus.currSong))
+				xs_plugin_ip.output->write_audio(audioBuffer, audioGot);
+
+			/* Check if we have played enough */
+			if (xs_cfg.playMaxTimeEnable) {
+				if (xs_cfg.playMaxTimeUnknown) {
+					if ((songLength < 0) &&
+					    (xs_plugin_ip.output->output_time() >= (xs_cfg.playMaxTime * 1000)))
+						myStatus.isPlaying = FALSE;
+				} else {
+					if (xs_plugin_ip.output->output_time() >= (xs_cfg.playMaxTime * 1000))
+						myStatus.isPlaying = FALSE;
+				}
+			}
+
+			if (songLength >= 0) {
+				if (xs_plugin_ip.output->output_time() >= (songLength * 1000))
+					myStatus.isPlaying = FALSE;
+			}
+		}
+
+		XSDEBUG("subtune ended/stopped\n");
+
+		/* Close audio output plugin */
+		if (audioOpen) {
+			XSDEBUG("close audio #1\n");
+			xs_plugin_ip.output->close_audio();
+			audioOpen = FALSE;
+		}
+
+		/* Now determine if we continue by selecting other subtune or something */
+		if (!myStatus.isPlaying && !xs_cfg.subAutoEnable)
+			doPlay = FALSE;
+	}
+
+      xs_err_exit:
+	/* Close audio output plugin */
+	if (audioOpen) {
+		XSDEBUG("close audio #2\n");
+		xs_plugin_ip.output->close_audio();
+	}
+
+	g_free(audioBuffer);
+	g_free(oversampleBuffer);
+
+	/* Set playing status to false (stopped), thus when
+	 * XMMS next calls xs_get_time(), it can return appropriate
+	 * value "not playing" status and XMMS knows to move to
+	 * next entry in the playlist .. or whatever it wishes.
+	 */
+	XS_MUTEX_LOCK(xs_status);
+	xs_status.isPlaying = FALSE;
+	XS_MUTEX_UNLOCK(xs_status);
+
+	/* Exit the playing thread */
+	XSDEBUG("exiting thread, bye.\n");
+	pthread_exit(NULL);
+}
+
+
+/*
+ * Start playing the given file
+ * Here we load the tune and initialize the playing thread.
+ * Usually you would also initialize the output-plugin, but
+ * this is XMMS-SID and we do it on the player thread instead.
+ */
+void xs_play_file(gchar * pcFilename)
+{
+	assert(xs_status.sidPlayer);
+
+	XSDEBUG("play '%s'\n", pcFilename);
+
+	/* Get tune information */
+	if ((xs_status.tuneInfo = xs_status.sidPlayer->plrGetSIDInfo(pcFilename)) == NULL)
+		return;
+
+	/* Initialize the tune */
+	if (!xs_status.sidPlayer->plrLoadSID(&xs_status, pcFilename)) {
+		xs_tuneinfo_free(xs_status.tuneInfo);
+		xs_status.tuneInfo = NULL;
+		return;
+	}
+
+	XSDEBUG("load ok\n");
+
+	/* Set general status information */
+	xs_status.isPlaying = TRUE;
+	xs_status.isError = FALSE;
+	xs_status.currSong = xs_status.tuneInfo->startTune;
+
+	/* Start the playing thread! */
+	if (pthread_create(&xs_decode_thread, NULL, xs_playthread, NULL) < 0) {
+		XSERR("Couldn't start playing thread!\n");
+		xs_tuneinfo_free(xs_status.tuneInfo);
+		xs_status.tuneInfo = NULL;
+		xs_status.sidPlayer->plrDeleteSID(&xs_status);
+	}
+
+	/* Okay, here the playing thread has started up and we
+	 * return from here to XMMS. Rest is up to XMMS's GUI
+	 * and playing thread.
+	 */
+	XSDEBUG("systems should be up?\n");
+}
+
+
+/*
+ * Stop playing
+ * Here we set the playing status to stop and wait for playing
+ * thread to shut down. In any "correctly" done plugin, this is
+ * also the function where you close the output-plugin, but since
+ * XMMS-SID has special behaviour (audio opened/closed in the
+ * playing thread), we don't do that here.
+ *
+ * Finally tune and other memory allocations are free'd.
+ */
+void xs_stop(void)
+{
+	XSDEBUG("STOP_REQ\n");
+
+	/* Close the sub-tune control window, if any */
+	xs_subctrl_close();
+
+	/* Lock xs_status and stop playing thread */
+	XS_MUTEX_LOCK(xs_status);
+	if (xs_status.isPlaying) {
+		/* Stop playing */
+		XSDEBUG("stopping...\n");
+		xs_status.isPlaying = FALSE;
+		XS_MUTEX_UNLOCK(xs_status);
+		pthread_join(xs_decode_thread, NULL);
+	} else {
+		XS_MUTEX_UNLOCK(xs_status);
+	}
+
+	/* Status is now stopped, update the sub-tune
+	 * controller in fileinfo window (if open)
+	 */
+	xs_fileinfo_update();
+
+	/* Free tune information */
+	xs_status.sidPlayer->plrDeleteSID(&xs_status);
+	xs_tuneinfo_free(xs_status.tuneInfo);
+	xs_status.tuneInfo = NULL;
+}
+
+
+/*
+ * Pause/unpause the playing
+ */
+void xs_pause(short pauseState)
+{
+	XS_MUTEX_LOCK(xs_status);
+	/* FIXME FIX ME todo: pause should disable sub-tune controls */
+	XS_MUTEX_UNLOCK(xs_status);
+
+	xs_subctrl_close();
+	xs_fileinfo_update();
+	xs_plugin_ip.output->pause(pauseState);
+}
+
+
+/*
+ * Pop-up subtune selector
+ */
+void xs_subctrl_setsong(void)
+{
+	gint n;
+
+	XS_MUTEX_LOCK(xs_status);
+	XS_MUTEX_LOCK(xs_subctrl);
+
+	if (xs_status.tuneInfo && xs_status.isPlaying) {
+		n = (gint) GTK_ADJUSTMENT(xs_subctrl_adj)->value;
+		if ((n >= 1) && (n <= xs_status.tuneInfo->nsubTunes))
+			xs_status.currSong = n;
+	}
+
+	XS_MUTEX_UNLOCK(xs_subctrl);
+	XS_MUTEX_UNLOCK(xs_status);
+}
+
+
+void xs_subctrl_prevsong(void)
+{
+	XS_MUTEX_LOCK(xs_status);
+
+	if (xs_status.tuneInfo && xs_status.isPlaying) {
+		if (xs_status.currSong > 1)
+			xs_status.currSong--;
+	}
+
+	XS_MUTEX_UNLOCK(xs_status);
+
+	xs_subctrl_update();
+}
+
+
+void xs_subctrl_nextsong(void)
+{
+	XS_MUTEX_LOCK(xs_status);
+
+	if (xs_status.tuneInfo && xs_status.isPlaying) {
+		if (xs_status.currSong < xs_status.tuneInfo->nsubTunes)
+			xs_status.currSong++;
+	}
+
+	XS_MUTEX_UNLOCK(xs_status);
+
+	xs_subctrl_update();
+}
+
+
+void xs_subctrl_update(void)
+{
+	GtkAdjustment *tmpAdj;
+
+	XS_MUTEX_LOCK(xs_status);
+	XS_MUTEX_LOCK(xs_subctrl);
+
+	/* Check if control window exists, we are currently playing and have a tune */
+	if (xs_subctrl) {
+		if (xs_status.tuneInfo && xs_status.isPlaying) {
+			tmpAdj = GTK_ADJUSTMENT(xs_subctrl_adj);
+
+			tmpAdj->value = xs_status.currSong;
+			tmpAdj->lower = 1;
+			tmpAdj->upper = xs_status.tuneInfo->nsubTunes;
+			XS_MUTEX_UNLOCK(xs_status);
+			XS_MUTEX_UNLOCK(xs_subctrl);
+			gtk_adjustment_value_changed(tmpAdj);
+		} else {
+			XS_MUTEX_UNLOCK(xs_status);
+			XS_MUTEX_UNLOCK(xs_subctrl);
+			xs_subctrl_close();
+		}
+	} else {
+		XS_MUTEX_UNLOCK(xs_subctrl);
+		XS_MUTEX_UNLOCK(xs_status);
+	}
+
+	xs_fileinfo_update();
+}
+
+
+void xs_subctrl_close(void)
+{
+	XS_MUTEX_LOCK(xs_subctrl);
+
+	if (xs_subctrl) {
+		gtk_widget_destroy(xs_subctrl);
+		xs_subctrl = NULL;
+	}
+
+	XS_MUTEX_UNLOCK(xs_subctrl);
+}
+
+
+gboolean xs_subctrl_keypress(GtkWidget * win, GdkEventKey * ev)
+{
+	(void) win;
+
+	if (ev->keyval == GDK_Escape)
+		xs_subctrl_close();
+
+	return FALSE;
+}
+
+
+void xs_subctrl_open(void)
+{
+	GtkWidget *frame25, *hbox15, *subctrl_prev, *subctrl_current, *subctrl_next;
+
+	XS_MUTEX_LOCK(xs_subctrl);
+	if (!xs_status.tuneInfo || !xs_status.isPlaying || xs_subctrl || (xs_status.tuneInfo->nsubTunes <= 1)) {
+		XS_MUTEX_UNLOCK(xs_subctrl);
+		return;
+	}
+
+	/* Create the pop-up window */
+	xs_subctrl = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+	gtk_window_set_type_hint (GTK_WINDOW(xs_subctrl), GDK_WINDOW_TYPE_HINT_DIALOG);
+	gtk_widget_set_name(xs_subctrl, "xs_subctrl");
+	gtk_object_set_data(GTK_OBJECT(xs_subctrl), "xs_subctrl", xs_subctrl);
+
+	gtk_window_set_title(GTK_WINDOW(xs_subctrl), "Subtune Control");
+	gtk_window_set_position(GTK_WINDOW(xs_subctrl), GTK_WIN_POS_MOUSE);
+	gtk_container_set_border_width(GTK_CONTAINER(xs_subctrl), 0);
+	gtk_window_set_policy(GTK_WINDOW(xs_subctrl), FALSE, FALSE, FALSE);
+
+	gtk_signal_connect(GTK_OBJECT(xs_subctrl), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &xs_subctrl);
+
+	gtk_signal_connect(GTK_OBJECT(xs_subctrl), "focus_out_event", GTK_SIGNAL_FUNC(xs_subctrl_close), NULL);
+
+	gtk_widget_realize(xs_subctrl);
+	gdk_window_set_decorations(xs_subctrl->window, (GdkWMDecoration) 0);
+
+
+	/* Create the control widgets */
+	frame25 = gtk_frame_new(NULL);
+	gtk_container_add(GTK_CONTAINER(xs_subctrl), frame25);
+	gtk_container_set_border_width(GTK_CONTAINER(frame25), 2);
+	gtk_frame_set_shadow_type(GTK_FRAME(frame25), GTK_SHADOW_OUT);
+
+	hbox15 = gtk_hbox_new(FALSE, 4);
+	gtk_container_add(GTK_CONTAINER(frame25), hbox15);
+
+	subctrl_prev = gtk_button_new_with_label(" < ");
+	gtk_widget_set_name(subctrl_prev, "subctrl_prev");
+	gtk_box_pack_start(GTK_BOX(hbox15), subctrl_prev, FALSE, FALSE, 0);
+
+	xs_subctrl_adj = gtk_adjustment_new(xs_status.currSong, 1, xs_status.tuneInfo->nsubTunes, 1, 1, 0);
+	gtk_signal_connect(GTK_OBJECT(xs_subctrl_adj), "value_changed", GTK_SIGNAL_FUNC(xs_subctrl_setsong), NULL);
+
+	subctrl_current = gtk_hscale_new(GTK_ADJUSTMENT(xs_subctrl_adj));
+	gtk_widget_set_name(subctrl_current, "subctrl_current");
+	gtk_box_pack_start(GTK_BOX(hbox15), subctrl_current, FALSE, TRUE, 0);
+	gtk_scale_set_digits(GTK_SCALE(subctrl_current), 0);
+	gtk_range_set_update_policy(GTK_RANGE(subctrl_current), GTK_UPDATE_DELAYED);
+	gtk_widget_grab_focus(subctrl_current);
+
+	subctrl_next = gtk_button_new_with_label(" > ");
+	gtk_widget_set_name(subctrl_next, "subctrl_next");
+	gtk_box_pack_start(GTK_BOX(hbox15), subctrl_next, FALSE, FALSE, 0);
+
+	gtk_signal_connect(GTK_OBJECT(subctrl_prev), "clicked", GTK_SIGNAL_FUNC(xs_subctrl_prevsong), NULL);
+
+	gtk_signal_connect(GTK_OBJECT(subctrl_next), "clicked", GTK_SIGNAL_FUNC(xs_subctrl_nextsong), NULL);
+
+	gtk_signal_connect(GTK_OBJECT(xs_subctrl), "key_press_event", GTK_SIGNAL_FUNC(xs_subctrl_keypress), NULL);
+
+	gtk_widget_show_all(xs_subctrl);
+
+	XS_MUTEX_UNLOCK(xs_subctrl);
+}
+
+
+/*
+ * Set the time-seek position
+ * The playing thread will do the "seeking", which means sub-tune
+ * changing in XMMS-SID's case. iTime argument is time in seconds,
+ * in contrast to milliseconds used in other occasions.
+ *
+ * This function is called whenever position slider is clicked or
+ * other method of seeking is used (keyboard, etc.)
+ */
+void xs_seek(gint iTime)
+{
+	/* Check status */
+	XS_MUTEX_LOCK(xs_status);
+	if (!xs_status.tuneInfo || !xs_status.isPlaying) {
+		XS_MUTEX_UNLOCK(xs_status);
+		return;
+	}
+
+	/* Act according to settings */
+	switch (xs_cfg.subsongControl) {
+	case XS_SSC_SEEK:
+		if (iTime < xs_status.lastTime) {
+			if (xs_status.currSong > 1)
+				xs_status.currSong--;
+		} else if (iTime > xs_status.lastTime) {
+			if (xs_status.currSong < xs_status.tuneInfo->nsubTunes)
+				xs_status.currSong++;
+		}
+		break;
+
+	case XS_SSC_POPUP:
+		xs_subctrl_open();
+		break;
+
+		/* If we have song-position patch, check settings */
+#ifdef HAVE_SONG_POSITION
+	case XS_SSC_PATCH:
+		if ((iTime > 0) && (iTime <= xs_status.tuneInfo->nsubTunes))
+			xs_status.currSong = iTime;
+		break;
+#endif
+	}
+
+	XS_MUTEX_UNLOCK(xs_status);
+}
+
+
+/*
+ * Return the playing "position/time"
+ * Determine current position/time in song. Used by XMMS to update
+ * the song clock and position slider and MOST importantly to determine
+ * END OF SONG! Return value of -2 means error, XMMS opens an audio
+ * error dialog. -1 means end of song (if one was playing currently).
+ */
+gint xs_get_time(void)
+{
+	/* If errorflag is set, return -2 to signal it to XMMS's idle callback */
+	XS_MUTEX_LOCK(xs_status);
+	if (xs_status.isError) {
+		XS_MUTEX_UNLOCK(xs_status);
+		return -2;
+	}
+
+	/* If there is no tune, return -1 */
+	if (!xs_status.tuneInfo) {
+		XS_MUTEX_UNLOCK(xs_status);
+		return -1;
+	}
+
+	/* If tune has ended, return -1 */
+	if (!xs_status.isPlaying) {
+		XS_MUTEX_UNLOCK(xs_status);
+		return -1;
+	}
+
+	/* Let's see what we do */
+	switch (xs_cfg.subsongControl) {
+	case XS_SSC_SEEK:
+		xs_status.lastTime = (xs_plugin_ip.output->output_time() / 1000);
+		break;
+
+#ifdef HAVE_SONG_POSITION
+	case XS_SSC_PATCH:
+		set_song_position(xs_status.currSong, 1, xs_status.tuneInfo->nsubTunes);
+		break;
+#endif
+	}
+
+	XS_MUTEX_UNLOCK(xs_status);
+
+	/* Return output time reported by audio output plugin */
+	return xs_plugin_ip.output->output_time();
+}
+
+
+/*
+ * Return song information
+ * This function is called by XMMS when initially loading the playlist.
+ * Subsequent changes to information are made by the player thread,
+ * which uses xs_plugin_ip.set_info();
+ */
+void xs_get_song_info(gchar * songFilename, gchar ** songTitle, gint * songLength)
+{
+	t_xs_tuneinfo *pInfo;
+	gint tmpInt;
+
+	/* Get tune information from emulation engine */
+	pInfo = xs_status.sidPlayer->plrGetSIDInfo(songFilename);
+	if (!pInfo)
+		return;
+
+	/* Get sub-tune information, if available */
+	if ((pInfo->startTune > 0) && (pInfo->startTune <= pInfo->nsubTunes)) {
+		(*songTitle) = g_strdup(pInfo->subTunes[pInfo->startTune - 1].tuneTitle);
+
+		tmpInt = pInfo->subTunes[pInfo->startTune - 1].tuneLength;
+		if (tmpInt < 0)
+			(*songLength) = -1;
+		else
+			(*songLength) = (tmpInt * 1000);
+	}
+
+	/* Free tune information */
+	xs_tuneinfo_free(pInfo);
+}
+
+
+/* Allocate a new tune information structure
+ */
+t_xs_tuneinfo *xs_tuneinfo_new(gchar * pcFilename, gint nsubTunes, gint startTune,
+			       gchar * sidName, gchar * sidComposer, gchar * sidCopyright,
+			       gint loadAddr, gint initAddr, gint playAddr, gint dataFileLen)
+{
+	t_xs_tuneinfo *pResult;
+
+	/* Allocate structure */
+	pResult = (t_xs_tuneinfo *) g_malloc0(sizeof(t_xs_tuneinfo));
+	if (!pResult) {
+		XSERR("Could not allocate memory for t_xs_tuneinfo ('%s')\n", pcFilename);
+		return NULL;
+	}
+
+	pResult->sidFilename = g_strdup(pcFilename);
+	if (!pResult->sidFilename) {
+		XSERR("Could not allocate sidFilename ('%s')\n", pcFilename);
+		g_free(pResult);
+		return NULL;
+	}
+
+	/* Allocate space for subtune information */
+	if (nsubTunes > 0) {
+		pResult->subTunes = g_malloc0(sizeof(t_xs_subtuneinfo) * nsubTunes);
+		if (!pResult->subTunes) {
+			XSERR("Could not allocate memory for t_xs_subtuneinfo ('%s', %i)\n", pcFilename, nsubTunes);
+
+			g_free(pResult->sidFilename);
+			g_free(pResult);
+			return NULL;
+		}
+	}
+
+	/* The following allocations don't matter if they fail */
+	pResult->sidName = g_strdup(sidName);
+	pResult->sidComposer = g_strdup(sidComposer);
+	pResult->sidCopyright = g_strdup(sidCopyright);
+
+	pResult->nsubTunes = nsubTunes;
+	pResult->startTune = startTune;
+
+	pResult->loadAddr = loadAddr;
+	pResult->initAddr = initAddr;
+	pResult->playAddr = playAddr;
+	pResult->dataFileLen = dataFileLen;
+
+	return pResult;
+}
+
+
+/* Free given tune information structure
+ */
+void xs_tuneinfo_free(t_xs_tuneinfo * pTune)
+{
+	gint i;
+	if (!pTune)
+		return;
+
+	for (i = 0; i < pTune->nsubTunes; i++) {
+		g_free(pTune->subTunes[i].tuneTitle);
+		pTune->subTunes[i].tuneTitle = NULL;
+	}
+
+	g_free(pTune->subTunes);
+	pTune->nsubTunes = 0;
+	g_free(pTune->sidFilename);
+	pTune->sidFilename = NULL;
+	g_free(pTune->sidName);
+	pTune->sidName = NULL;
+	g_free(pTune->sidComposer);
+	pTune->sidComposer = NULL;
+	g_free(pTune->sidCopyright);
+	pTune->sidCopyright = NULL;
+	g_free(pTune);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xmms-sid.h	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,229 @@
+/*  
+   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
+
+   Main header file
+
+   Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org>
+   (C) Copyright 1999-2005 Tecnic Software productions (TNSP)
+
+   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 _XMMS_SID_H
+#define _XMMS_SID_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_ASSERT_H
+#include <assert.h>
+#else
+#define assert(x) /* stub */
+#endif
+
+#include <glib.h>
+#include <pthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "audacious/plugin.h"
+
+/*
+ * Some constants and defines
+ */
+/* #define to enable spurious debugging messages for development
+ * purposes. Output goes to stderr. See also DEBUG_NP below.
+ */
+#define DEBUG
+
+/* Define to ISO C99 macro for debugging instead of varargs function.
+ * This provides more useful information, but is incompatible with
+ * older standards. If #undef'd, a varargs function is used instead.
+ */
+#define DEBUG_NP
+
+/* Define to enable non-portable thread and mutex debugging code.
+ * You need to #define DEBUG also to make this useful.
+ * (Works probably with GNU/Linux pthreads implementation only)
+ */
+#undef XS_MUTEX_DEBUG
+
+/* HardSID-support is not working and is untested, thus we disable it here.
+ */
+#undef HAVE_HARDSID_BUILDER
+
+/* Size for some small buffers (always static variables) */
+#define XS_BUF_SIZE		(1024)
+
+/* If defined, some dynamically allocated temp. buffers are used.
+ * Static (#undef) might give slight performance gain,
+ * but fails on systems with limited stack space. */
+#define XS_BUF_DYNAMIC
+
+/* Size of audio buffer. If you are experiencing lots of audio
+ * "underruns" or clicks/gaps in output, try increasing this value.
+ * Do notice, however, that it also affects the update frequency of
+ * XMMS's visualization plugins... 
+ */
+#define XS_AUDIOBUF_SIZE	(2*1024)
+
+/* Size of data buffer used for SID-tune MD5 hash calculation.
+ * If this is too small, the computed hash will be incorrect.
+ * Largest SID files I've seen are ~70kB. */
+#define XS_SIDBUF_SIZE		(80*1024)
+
+
+/* libSIDPlay1 default filter values (copied from libsidplay1's headers) */
+#define XS_SIDPLAY1_FS		(400.0f)
+#define XS_SIDPLAY1_FM		(60.0f)
+#define XS_SIDPLAY1_FT		(0.05f)
+
+
+#define XS_BIN_BAILOUT		(32)	/* Binary search bailout treshold */
+
+#define XS_STIL_MAXENTRY	(128)	/* Max number of sub-songs in STIL/SLDB node */
+
+
+#define XS_CONFIG_IDENT		"XMMS-SID"	/* Configuration file identifier */
+#define XS_CONFIG_FILE		"/.bmp/xmms-sid"	/* Use this configfile if autocyrpe fails */
+
+#define XS_MIN_OVERSAMPLE	(2)		/* Minimum oversampling factor */
+#define XS_MAX_OVERSAMPLE	(8)		/* Maximum oversampling factor */
+
+
+/* Macros for mutexes and threads. These exist to be able to
+ * easily change from pthreads to glib threads, etc, if necessary.
+ */
+#define XS_MPP(M)	M ## _mutex
+#if XS_MUTEX_DEBUG
+#define XS_MUTEX(M)		pthread_mutex_t	XS_MPP(M) = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; int M ## _qq;
+#define XS_MUTEX_H(M)		extern pthread_mutex_t XS_MPP(M); extern int M ## _qq
+#define XS_MUTEX_LOCK(M)	{ M ## _qq = pthread_mutex_lock(&XS_MPP(M)); if (M ## _qq) XSDEBUG("XS_MUTEX_LOCK(" #M ") == %i\n", M ## _qq); }
+#define XS_MUTEX_UNLOCK(M)	{ M ## _qq = pthread_mutex_unlock(&XS_MPP(M)); if (M ## _qq) XSDEBUG("XS_MUTEX_UNLOCK(" #M ") == %i\n", M ## _qq); }
+#else
+#define XS_MUTEX(M)		pthread_mutex_t	XS_MPP(M) = PTHREAD_MUTEX_INITIALIZER
+#define XS_MUTEX_H(M)		extern pthread_mutex_t XS_MPP(M)
+#define XS_MUTEX_LOCK(M)	pthread_mutex_lock(&XS_MPP(M))
+#define XS_MUTEX_UNLOCK(M)	pthread_mutex_unlock(&XS_MPP(M))
+#endif
+
+/* Shorthands for linked lists
+ */
+#define LPREV	(pNode->pPrev)
+#define LTHIS	(pNode)
+#define LNEXT	(pNode->pNext)
+
+
+/* Plugin-wide typedefs
+ */
+typedef struct {
+	gint		tuneSpeed;
+	gint		tuneLength;
+	gchar		*tuneTitle;
+} t_xs_subtuneinfo;
+
+
+typedef struct {
+	gchar		*sidFilename,
+			*sidName,
+			*sidComposer,
+			*sidCopyright;
+	gint		loadAddr,
+			initAddr,
+			playAddr,
+			dataFileLen;
+	gint		nsubTunes, startTune;
+	t_xs_subtuneinfo	*subTunes;
+} t_xs_tuneinfo;
+
+
+struct t_xs_status;
+
+typedef struct {
+	gint		plrIdent;
+	gboolean	(*plrIsOurFile)(gchar *);
+	gboolean	(*plrInit)(struct t_xs_status *);
+	void		(*plrClose)(struct t_xs_status *);
+	gboolean	(*plrInitSong)(struct t_xs_status *);
+	guint		(*plrFillBuffer)(struct t_xs_status *, gchar *, guint);
+	gboolean	(*plrLoadSID)(struct t_xs_status *, gchar *);
+	void		(*plrDeleteSID)(struct t_xs_status *);
+	t_xs_tuneinfo*	(*plrGetSIDInfo)(gchar *);
+} t_xs_player;
+
+
+typedef struct t_xs_status {
+	gint		audioFrequency,		/* Audio settings */
+			audioChannels,
+			audioBitsPerSample,
+			oversampleFactor;	/* Factor of oversampling */
+	AFormat		audioFormat;
+	gboolean	oversampleEnable;	/* TRUE after sidEngine initialization,
+						if xs_cfg.oversampleEnable == TRUE and
+						emulation backend supports oversampling.
+						*/
+	void		*sidEngine;		/* SID-emulation internal engine data */
+	t_xs_player	*sidPlayer;		/* Selected player engine */
+	gboolean	isError, isPlaying;
+	gint		currSong,		/* Current sub-tune */
+			lastTime;
+	t_xs_tuneinfo	*tuneInfo;
+} t_xs_status;
+
+
+/* Global variables
+ */
+extern InputPlugin	xs_plugin_ip;
+
+extern t_xs_status	xs_status;
+XS_MUTEX_H(xs_status);
+
+
+
+/* Plugin function prototypes
+ */
+void	xs_init(void);
+void	xs_reinit(void);
+void	xs_close(void);
+gint	xs_is_our_file(gchar *);
+void	xs_play_file(gchar *);
+void	xs_stop(void);
+void	xs_pause(short);
+void	xs_seek(gint);
+gint	xs_get_time(void);
+void	xs_get_song_info(gchar *, gchar **, gint *);
+void	xs_about(void);
+
+t_xs_tuneinfo *xs_tuneinfo_new(gchar *, gint, gint, gchar *, gchar *, gchar *, gint, gint, gint, gint);
+void	xs_tuneinfo_free(t_xs_tuneinfo *);
+
+void	XSERR(const char *, ...);
+
+#ifndef DEBUG_NP
+void	XSDEBUG(const char *, ...);
+#else
+#ifdef DEBUG
+#define XSDEBUG(...) { fprintf(stderr, "XS[%s:%s:%d]: ", __FILE__, __FUNCTION__, (int) __LINE__); fprintf(stderr, __VA_ARGS__); }
+#else
+#define XSDEBUG(...) /* stub */
+#endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _XMMS_SID_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_about.c	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,171 @@
+/*  
+   xmms-sid - SIDPlay input plugin for X MultiMedia System (XMMS)
+
+   Aboutbox dialog
+   
+   Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org>
+   (C) Copyright 1999-2005 Tecnic Software productions (TNSP)
+
+   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 "xmms-sid.h"
+#include <gtk/gtk.h>
+#include "xmms-sid-logo.xpm"
+
+
+static GtkWidget *xs_aboutwin = NULL;
+
+
+gint xs_about_ok(void)
+{
+	gtk_widget_destroy(xs_aboutwin);
+	xs_aboutwin = NULL;
+	return 0;
+}
+
+
+/*
+ * Execute the about dialog
+ */
+void xs_about(void)
+{
+	GtkWidget *about_vbox1;
+	GtkWidget *about_frame;
+	GtkWidget *about_logo;
+	GdkPixmap *about_logo_pixmap = NULL, *about_logo_mask = NULL;
+	GtkWidget *about_scrwin;
+	GtkWidget *about_text;
+	GtkWidget *alignment6;
+	GtkWidget *about_close;
+
+	/* Check if there already is an open about window */
+	if (xs_aboutwin != NULL) {
+		gdk_window_raise(xs_aboutwin->window);
+		return;
+	}
+
+	/* No, create one ... */
+	xs_aboutwin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+	gtk_window_set_type_hint (GTK_WINDOW(xs_aboutwin), GDK_WINDOW_TYPE_HINT_DIALOG);
+	gtk_widget_set_name(xs_aboutwin, "xs_aboutwin");
+	gtk_object_set_data(GTK_OBJECT(xs_aboutwin), "xs_aboutwin", xs_aboutwin);
+	gtk_window_set_title(GTK_WINDOW(xs_aboutwin), "About " PACKAGE_STRING);
+	gtk_window_set_default_size(GTK_WINDOW(xs_aboutwin), 300, -1);
+
+	about_vbox1 = gtk_vbox_new(FALSE, 0);
+	gtk_widget_set_name(about_vbox1, "about_vbox1");
+	gtk_widget_ref(about_vbox1);
+	gtk_object_set_data_full(GTK_OBJECT(xs_aboutwin), "about_vbox1", about_vbox1,
+				 (GtkDestroyNotify) gtk_widget_unref);
+	gtk_widget_show(about_vbox1);
+	gtk_container_add(GTK_CONTAINER(xs_aboutwin), about_vbox1);
+
+	about_frame = gtk_frame_new(NULL);
+	gtk_widget_set_name(about_frame, "about_frame");
+	gtk_widget_ref(about_frame);
+	gtk_object_set_data_full(GTK_OBJECT(xs_aboutwin), "about_frame", about_frame,
+				 (GtkDestroyNotify) gtk_widget_unref);
+	gtk_widget_show(about_frame);
+	gtk_box_pack_start(GTK_BOX(about_vbox1), about_frame, FALSE, FALSE, 0);
+	gtk_container_set_border_width(GTK_CONTAINER(about_frame), 4);
+
+	gtk_frame_set_shadow_type(GTK_FRAME(about_frame), GTK_SHADOW_OUT);
+
+	/* Create the Gdk data for logo pixmap */
+	gtk_widget_realize(xs_aboutwin);
+	about_logo_pixmap = gdk_pixmap_create_from_xpm_d(xs_aboutwin->window,
+							 &about_logo_mask, NULL, (gchar **) xmms_sid_logo_xpm);
+
+	about_logo = gtk_pixmap_new(about_logo_pixmap, about_logo_mask);
+
+	/* Create logo widget */
+	gtk_widget_set_name(about_logo, "about_logo");
+	gtk_widget_ref(about_logo);
+	gtk_object_set_data_full(GTK_OBJECT(xs_aboutwin), "about_logo", about_logo,
+				 (GtkDestroyNotify) gtk_widget_unref);
+	gtk_widget_show(about_logo);
+	gtk_container_add(GTK_CONTAINER(about_frame), about_logo);
+	gtk_misc_set_padding(GTK_MISC(about_logo), 0, 6);
+
+	about_scrwin = gtk_scrolled_window_new(NULL, NULL);
+	gtk_widget_set_name(about_scrwin, "about_scrwin");
+	gtk_widget_ref(about_scrwin);
+	gtk_object_set_data_full(GTK_OBJECT(xs_aboutwin), "about_scrwin", about_scrwin,
+				 (GtkDestroyNotify) gtk_widget_unref);
+	gtk_widget_show(about_scrwin);
+	gtk_box_pack_start(GTK_BOX(about_vbox1), about_scrwin, TRUE, TRUE, 0);
+	gtk_container_set_border_width(GTK_CONTAINER(about_scrwin), 8);
+	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(about_scrwin), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
+
+	about_text = gtk_text_view_new();
+	gtk_widget_set_name(about_text, "about_text");
+	gtk_widget_ref(about_text);
+	gtk_object_set_data_full(GTK_OBJECT(xs_aboutwin), "about_text", about_text,
+				 (GtkDestroyNotify) gtk_widget_unref);
+	gtk_widget_show(about_text);
+	gtk_container_add(GTK_CONTAINER(about_scrwin), about_text);
+	gtk_widget_set_usize(about_text, -2, 100);
+	gtk_text_buffer_set_text( GTK_TEXT_BUFFER(gtk_text_view_get_buffer(GTK_TEXT_VIEW(about_text))), g_locale_to_utf8(
+			"\n"
+			"(C) Copyright 1999-2005\n"
+			"\tTecnic Software productions (TNSP)\n"
+			"\n" "Programming and design\n" "\tMatti 'ccr' Hämäläinen\n" "\n"
+#ifdef HAVE_SIDPLAY1
+			"libSIDPlay1 created by\n" "\tMichael Schwendt\n" "\n"
+#endif
+#ifdef HAVE_SIDPLAY2
+			"libSIDPlay2 and reSID created by\n"
+			"\tSimon White, Dag Lem,\n" "\tMichael Schwendt and rest.\n" "\n"
+#endif
+			"BMP-SID and Audacious port written by\n"
+			"\tGiacomo Lozito from develia.org\n"
+			"\n"
+			"Original XMMS-SID (v0.4) by\n" "\tWillem Monsuwe\n" "\n"
+			"Greetings fly out to ...\n"
+			"\tEveryone at #Linux.Fi, #Fireball,\n"
+			"\t#TNSP and #c-64 of IRCNet, #xmms\n"
+			"\tof Freenode.net.\n"
+			"\n"
+			"\tDekadence, PWP, Byterapers,\n"
+			"\tmfx, Unique, Fairlight, iSO,\n"
+			"\tWrath Designs, Padua, Extend,\n"
+			"\tPHn, Creators, Cosine, tAAt,\n" "\tViruz, Crest and Skalaria.\n" "\n"
+			"Special thanks\n"
+			"\tGerfried 'Alfie' Fuchs\n"
+			"\tAndreas 'mrsid' Varga\n" "\tAll the betatesters.\n" "\tAll the users!\n",
+			-1, NULL, NULL, NULL), -1);
+
+	alignment6 = gtk_alignment_new(0.5, 0.5, 0.18, 1);
+	gtk_widget_set_name(alignment6, "alignment6");
+	gtk_widget_ref(alignment6);
+	gtk_object_set_data_full(GTK_OBJECT(xs_aboutwin), "alignment6", alignment6,
+				 (GtkDestroyNotify) gtk_widget_unref);
+	gtk_widget_show(alignment6);
+	gtk_box_pack_start(GTK_BOX(about_vbox1), alignment6, FALSE, TRUE, 0);
+	gtk_container_set_border_width(GTK_CONTAINER(alignment6), 8);
+
+	about_close = gtk_button_new_with_label("Close");
+	gtk_widget_set_name(about_close, "about_close");
+	gtk_widget_ref(about_close);
+	gtk_object_set_data_full(GTK_OBJECT(xs_aboutwin), "about_close", about_close,
+				 (GtkDestroyNotify) gtk_widget_unref);
+	gtk_widget_show(about_close);
+	gtk_container_add(GTK_CONTAINER(alignment6), about_close);
+	GTK_WIDGET_SET_FLAGS(about_close, GTK_CAN_DEFAULT);
+
+	gtk_signal_connect(GTK_OBJECT(about_close), "clicked", GTK_SIGNAL_FUNC(xs_about_ok), NULL);
+
+	gtk_widget_show(xs_aboutwin);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_config.c	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,923 @@
+/*  
+   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
+
+   Configuration dialog
+   
+   Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org>
+   (C) Copyright 1999-2005 Tecnic Software productions (TNSP)
+   
+   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 "xs_config.h"
+#include "libaudacious/configfile.h"
+#include <stdio.h>
+#include "xs_glade.h"
+#include "xs_interface.h"
+#include "xs_support.h"
+
+/*
+ * Global widgets
+ */
+static GtkWidget *xs_configwin = NULL,
+	*xs_sldb_fileselector = NULL,
+	*xs_stil_fileselector = NULL,
+	*xs_hvsc_pathselector = NULL;
+
+#define LUW(x)	lookup_widget(xs_configwin, x)
+
+
+/*
+ * Configuration specific stuff
+ */
+XS_MUTEX(xs_cfg);
+struct t_xs_cfg xs_cfg;
+
+t_xs_cfg_item xs_cfgtable[] = {
+{ CTYPE_INT,	&xs_cfg.audioBitsPerSample,	"audioBitsPerSample" },
+{ CTYPE_INT,	&xs_cfg.audioChannels,		"audioChannels" },
+{ CTYPE_INT,	&xs_cfg.audioFrequency,		"audioFrequency" },
+
+{ CTYPE_BOOL,	&xs_cfg.mos8580,		"mos8580" },
+{ CTYPE_BOOL,	&xs_cfg.forceModel,		"forceModel" },
+{ CTYPE_BOOL,	&xs_cfg.emulateFilters,		"emulateFilters" },
+{ CTYPE_FLOAT,	&xs_cfg.filterFs,		"filterFs" },
+{ CTYPE_FLOAT,	&xs_cfg.filterFm,		"filterFm" },
+{ CTYPE_FLOAT,	&xs_cfg.filterFt,		"filterFt" },
+{ CTYPE_INT,	&xs_cfg.memoryMode,		"memoryMode" },
+{ CTYPE_INT,	&xs_cfg.clockSpeed,		"clockSpeed" },
+{ CTYPE_BOOL,	&xs_cfg.forceSpeed,		"forceSpeed" },
+
+{ CTYPE_INT,	&xs_cfg.playerEngine,		"playerEngine" },
+
+{ CTYPE_INT,	&xs_cfg.sid2Builder,		"sid2Builder" },
+{ CTYPE_INT,	&xs_cfg.sid2OptLevel,		"sid2OptLevel" },
+
+{ CTYPE_BOOL,	&xs_cfg.oversampleEnable,	"oversampleEnable" },
+{ CTYPE_INT,	&xs_cfg.oversampleFactor,	"oversampleFactor" },
+
+{ CTYPE_BOOL,	&xs_cfg.playMaxTimeEnable,	"playMaxTimeEnable" },
+{ CTYPE_BOOL,	&xs_cfg.playMaxTimeUnknown,	"playMaxTimeUnknown" },
+{ CTYPE_INT,	&xs_cfg.playMaxTime,		"playMaxTime" },
+{ CTYPE_BOOL,	&xs_cfg.playMinTimeEnable,	"playMinTimeEnable" },
+{ CTYPE_INT,	&xs_cfg.playMinTime,		"playMinTime" },
+{ CTYPE_BOOL,	&xs_cfg.songlenDBEnable,	"songlenDBEnable" },
+{ CTYPE_STR,	&xs_cfg.songlenDBPath,		"songlenDBPath" },
+
+{ CTYPE_BOOL,	&xs_cfg.stilDBEnable,		"stilDBEnable" },
+{ CTYPE_STR,	&xs_cfg.stilDBPath,		"stilDBPath" },
+{ CTYPE_STR,	&xs_cfg.hvscPath,		"hvscPath" },
+
+{ CTYPE_INT,	&xs_cfg.subsongControl,		"subsongControl" },
+{ CTYPE_BOOL,	&xs_cfg.detectMagic,		"detectMagic" },
+
+{ CTYPE_BOOL,	&xs_cfg.titleOverride,		"titleOverride" },
+{ CTYPE_STR,	&xs_cfg.titleFormat,		"titleFormat" },
+
+{ CTYPE_BOOL,	&xs_cfg.subAutoEnable,		"subAutoEnable" },
+{ CTYPE_BOOL,	&xs_cfg.subAutoMinOnly,		"subAutoMinOnly" },
+{ CTYPE_INT,	&xs_cfg.subAutoMinTime,		"subAutoMinTime" },
+};
+
+static const gint xs_cfgtable_max = (sizeof(xs_cfgtable) / sizeof(t_xs_cfg_item));
+
+
+t_xs_wid_item xs_widtable[] = {
+{ WTYPE_BGROUP,	CTYPE_INT,	"cfg_res_16bit",	&xs_cfg.audioBitsPerSample,	XS_RES_16BIT },
+{ WTYPE_BGROUP,	CTYPE_INT,	"cfg_res_8bit",		&xs_cfg.audioBitsPerSample,	XS_RES_8BIT },
+{ WTYPE_BGROUP,	CTYPE_INT,	"cfg_chn_mono",		&xs_cfg.audioChannels,		XS_CHN_MONO },
+{ WTYPE_BGROUP,	CTYPE_INT,	"cfg_chn_stereo",	&xs_cfg.audioChannels,		XS_CHN_STEREO },
+{ WTYPE_BGROUP,	CTYPE_INT,	"cfg_chn_autopan",	&xs_cfg.audioChannels,		XS_CHN_AUTOPAN },
+{ WTYPE_SPIN,	CTYPE_INT,	"cfg_samplerate",	&xs_cfg.audioFrequency,		0 },
+{ WTYPE_BUTTON,	CTYPE_BOOL,	"cfg_oversample",	&xs_cfg.oversampleEnable,	0 },
+{ WTYPE_SPIN,	CTYPE_INT,	"cfg_oversample_factor",&xs_cfg.oversampleFactor,	0 },
+
+{ WTYPE_BGROUP,	CTYPE_INT,	"cfg_emu_sidplay1",	&xs_cfg.playerEngine,		XS_ENG_SIDPLAY1 },
+{ WTYPE_BGROUP,	CTYPE_INT,	"cfg_emu_sidplay2",	&xs_cfg.playerEngine,		XS_ENG_SIDPLAY2 },
+{ WTYPE_BGROUP,	CTYPE_INT,	"cfg_emu_mem_real",	&xs_cfg.memoryMode,		XS_MPU_REAL },
+{ WTYPE_BGROUP,	CTYPE_INT,	"cfg_emu_mem_banksw",	&xs_cfg.memoryMode,		XS_MPU_BANK_SWITCHING },
+{ WTYPE_BGROUP,	CTYPE_INT,	"cfg_emu_mem_transrom",	&xs_cfg.memoryMode,		XS_MPU_TRANSPARENT_ROM },
+{ WTYPE_BGROUP,	CTYPE_INT,	"cfg_emu_mem_playsid",	&xs_cfg.memoryMode,		XS_MPU_PLAYSID_ENVIRONMENT },
+
+{ WTYPE_BUTTON,	CTYPE_BOOL,	"cfg_emu_mos8580",	&xs_cfg.mos8580,		0 },
+{ WTYPE_BUTTON,	CTYPE_BOOL,	"cfg_emu_sid_force",	&xs_cfg.forceModel,		0 },
+{ WTYPE_BGROUP,	CTYPE_INT,	"cfg_emu_clock_ntsc",	&xs_cfg.clockSpeed,		XS_CLOCK_NTSC },
+{ WTYPE_BGROUP,	CTYPE_INT,	"cfg_emu_clock_pal",	&xs_cfg.clockSpeed,		XS_CLOCK_PAL },
+{ WTYPE_BUTTON,	CTYPE_BOOL,	"cfg_emu_clock_force",	&xs_cfg.forceSpeed,		0 },
+{ WTYPE_BUTTON,	CTYPE_BOOL,	"cfg_emu_sidplay2_opt",	&xs_cfg.sid2OptLevel,		0 },
+
+{ WTYPE_BGROUP,	CTYPE_INT,	"cfg_emu_sidplay2_resid",&xs_cfg.sid2Builder,		XS_BLD_RESID },
+{ WTYPE_BGROUP,	CTYPE_INT,	"cfg_emu_sidplay2_hardsid",&xs_cfg.sid2Builder,		XS_BLD_HARDSID },
+
+{ WTYPE_BUTTON,	CTYPE_BOOL,	"cfg_emu_filters",	&xs_cfg.emulateFilters,		0 },
+{ WTYPE_SCALE,	CTYPE_FLOAT,	"cfg_emu_filt_fs",	&xs_cfg.filterFs,		0 },
+{ WTYPE_SCALE,	CTYPE_FLOAT,	"cfg_emu_filt_fm",	&xs_cfg.filterFm,		0 },
+{ WTYPE_SCALE,	CTYPE_FLOAT,	"cfg_emu_filt_ft",	&xs_cfg.filterFt,		0 },
+
+{ WTYPE_BUTTON,	CTYPE_BOOL,	"cfg_maxtime_enable",	&xs_cfg.playMaxTimeEnable,	0 },
+{ WTYPE_BUTTON,	CTYPE_BOOL,	"cfg_maxtime_unknown",	&xs_cfg.playMaxTimeUnknown,	0 },
+{ WTYPE_SPIN,	CTYPE_INT,	"cfg_maxtime",		&xs_cfg.playMaxTime,		0 },
+{ WTYPE_BUTTON,	CTYPE_BOOL,	"cfg_mintime_enable",	&xs_cfg.playMinTimeEnable,	0 },
+{ WTYPE_SPIN,	CTYPE_INT,	"cfg_mintime",		&xs_cfg.playMinTime,		0 },
+{ WTYPE_BUTTON,	CTYPE_BOOL,	"cfg_sld_enable",	&xs_cfg.songlenDBEnable,	0 },
+{ WTYPE_TEXT,	CTYPE_STR,	"cfg_sld_dbpath",	&xs_cfg.songlenDBPath,		0 },
+
+{ WTYPE_BUTTON,	CTYPE_BOOL,	"cfg_stil_enable",	&xs_cfg.stilDBEnable,		0 },
+{ WTYPE_TEXT,	CTYPE_STR,	"cfg_stil_dbpath",	&xs_cfg.stilDBPath,		0 },
+{ WTYPE_TEXT,	CTYPE_STR,	"cfg_hvsc_path",	&xs_cfg.hvscPath,		0 },
+
+{ WTYPE_BGROUP,	CTYPE_INT,	"cfg_subctrl_none",	&xs_cfg.subsongControl,		XS_SSC_NONE },
+{ WTYPE_BGROUP,	CTYPE_INT,	"cfg_subctrl_seek",	&xs_cfg.subsongControl,		XS_SSC_SEEK },
+{ WTYPE_BGROUP,	CTYPE_INT,	"cfg_subctrl_popup",	&xs_cfg.subsongControl,		XS_SSC_POPUP },
+{ WTYPE_BGROUP,	CTYPE_INT,	"cfg_subctrl_patch",	&xs_cfg.subsongControl,		XS_SSC_PATCH },
+
+{ WTYPE_BUTTON,	CTYPE_BOOL,	"cfg_detectmagic",	&xs_cfg.detectMagic,		0 },
+
+{ WTYPE_BUTTON,	CTYPE_BOOL,	"cfg_ftitle_override",	&xs_cfg.titleOverride,		0 },
+{ WTYPE_TEXT,	CTYPE_STR,	"cfg_ftitle_format",	&xs_cfg.titleFormat,		0 },
+
+{ WTYPE_BUTTON,	CTYPE_BOOL,	"cfg_subauto_enable",	&xs_cfg.subAutoEnable,		0 },
+{ WTYPE_BUTTON,	CTYPE_BOOL,	"cfg_subauto_min_only",	&xs_cfg.subAutoMinOnly,		0 },
+{ WTYPE_SPIN,	CTYPE_INT,	"cfg_subauto_mintime",	&xs_cfg.subAutoMinTime,		0 },
+};
+
+static const gint xs_widtable_max = (sizeof(xs_widtable) / sizeof(t_xs_wid_item));
+
+
+/*
+ * Reset/initialize the configuration
+ */
+void xs_init_configuration(void)
+{
+	/* Lock configuration mutex */
+	XSDEBUG("initializing configuration ...\n");
+	XS_MUTEX_LOCK(xs_cfg);
+
+	/* Initialize values with sensible defaults */
+	xs_cfg.audioBitsPerSample = XS_RES_16BIT;
+	xs_cfg.audioChannels = XS_CHN_MONO;
+	xs_cfg.audioFrequency = 44100;
+
+	xs_cfg.mos8580 = FALSE;
+	xs_cfg.forceModel = FALSE;
+
+	xs_cfg.emulateFilters = TRUE;
+	xs_cfg.filterFs = XS_SIDPLAY1_FS;
+	xs_cfg.filterFm = XS_SIDPLAY1_FM;
+	xs_cfg.filterFt = XS_SIDPLAY1_FT;
+
+#ifdef HAVE_SIDPLAY2
+	xs_cfg.playerEngine = XS_ENG_SIDPLAY2;
+	xs_cfg.memoryMode = XS_MPU_REAL;
+#else
+#ifdef HAVE_SIDPLAY1
+	xs_cfg.playerEngine = XS_ENG_SIDPLAY1;
+	xs_cfg.memoryMode = XS_MPU_BANK_SWITCHING;
+#else
+#error This should not happen! No emulator engines configured in!
+#endif
+#endif
+
+	xs_cfg.clockSpeed = XS_CLOCK_PAL;
+	xs_cfg.forceSpeed = FALSE;
+
+	xs_cfg.sid2OptLevel = FALSE;
+#ifdef HAVE_RESID_BUILDER
+	xs_cfg.sid2Builder = XS_BLD_RESID;
+#else
+#ifdef HAVE_HARDSID_BUILDER
+	xs_cfg.sid2Builder = XS_BLD_HARDSID;
+#else
+#ifdef HAVE_SIDPLAY2
+#error This should not happen! No supported SIDPlay2 builders configured in!
+#endif
+#endif
+#endif
+
+	xs_cfg.oversampleEnable = FALSE;
+	xs_cfg.oversampleFactor = XS_MIN_OVERSAMPLE;
+
+	xs_cfg.playMaxTimeEnable = FALSE;
+	xs_cfg.playMaxTimeUnknown = FALSE;
+	xs_cfg.playMaxTime = 150;
+
+	xs_cfg.playMinTimeEnable = FALSE;
+	xs_cfg.playMinTime = 15;
+
+	xs_cfg.songlenDBEnable = FALSE;
+	xs_pstrcpy(&xs_cfg.songlenDBPath, "~/C64Music/Songlengths.txt");
+
+	xs_cfg.stilDBEnable = FALSE;
+	xs_pstrcpy(&xs_cfg.stilDBPath, "~/C64Music/DOCUMENTS/STIL.txt");
+	xs_pstrcpy(&xs_cfg.hvscPath, "~/C64Music");
+
+#ifdef HAVE_SONG_POSITION
+	xs_cfg.subsongControl = XS_SSC_PATCH;
+#else
+	xs_cfg.subsongControl = XS_SSC_POPUP;
+#endif
+
+	xs_cfg.detectMagic = FALSE;
+
+#ifdef HAVE_XMMSEXTRA
+	xs_cfg.titleOverride = FALSE;
+#else
+	xs_cfg.titleOverride = TRUE;
+#endif
+	xs_pstrcpy(&xs_cfg.titleFormat, "%p - %t (%c) [%n/%N][%m]");
+
+
+	xs_cfg.subAutoEnable = FALSE;
+	xs_cfg.subAutoMinOnly = TRUE;
+	xs_cfg.subAutoMinTime = 15;
+
+
+	/* Unlock the configuration */
+	XS_MUTEX_UNLOCK(xs_cfg);
+}
+
+
+/*
+ * Get the configuration (from file or default)
+ */
+void xs_read_configuration(void)
+{
+#ifdef HAVE_NODEFAULTCFG
+	gchar *cfgFilename;
+#endif
+	gchar *tmpStr;
+	ConfigFile *cfgFile;
+	gint i;
+
+	/* Try to open the XMMS configuration file  */
+	XS_MUTEX_LOCK(xs_cfg);
+	XSDEBUG("loading from config-file ...\n");
+
+#ifdef HAVE_NODEFAULTCFG
+	cfgFilename = g_strconcat(g_get_home_dir(), XS_CONFIG_FILE, NULL);
+	cfgFile = xmms_cfg_open_file(cfgFilename);
+	g_free(cfgFilename);
+#else
+	cfgFile = xmms_cfg_open_default_file();
+#endif
+
+	if (cfgFile == NULL) {
+		XSDEBUG("could not open configuration file, trying to write defaults...\n");
+		xs_write_configuration();
+		return;
+	}
+
+	/* Read the new settings from XMMS configuration file */
+	for (i = 0; i < xs_cfgtable_max; i++) {
+		switch (xs_cfgtable[i].itemType) {
+		case CTYPE_INT:
+			xmms_cfg_read_int(cfgFile, XS_CONFIG_IDENT, xs_cfgtable[i].itemName,
+					  (gint *) xs_cfgtable[i].itemData);
+			break;
+
+		case CTYPE_BOOL:
+			xmms_cfg_read_boolean(cfgFile, XS_CONFIG_IDENT, xs_cfgtable[i].itemName,
+					      (gboolean *) xs_cfgtable[i].itemData);
+			break;
+
+		case CTYPE_FLOAT:
+			xmms_cfg_read_float(cfgFile, XS_CONFIG_IDENT, xs_cfgtable[i].itemName,
+					    (gfloat *) xs_cfgtable[i].itemData);
+			break;
+
+		case CTYPE_STR:
+			if (xmms_cfg_read_string
+			    (cfgFile, XS_CONFIG_IDENT, xs_cfgtable[i].itemName, (gchar **) & tmpStr)) {
+				/* Read was successfull */
+				xs_pstrcpy((gchar **) xs_cfgtable[i].itemData, tmpStr);
+				g_free(tmpStr);
+			}
+			break;
+
+		default:
+			XSERR
+			    ("Internal: Unsupported setting type found while reading configuration file. Please report to author!\n");
+			break;
+		}
+	}
+
+
+	/* Free the config file */
+	xmms_cfg_free(cfgFile);
+
+	XS_MUTEX_UNLOCK(xs_cfg);
+	XSDEBUG("OK\n");
+}
+
+
+
+/*
+ * Write the current configuration
+ */
+gint xs_write_configuration(void)
+{
+#ifdef HAVE_NODEFAULTCFG
+	gchar *cfgFilename;
+#endif
+	ConfigFile *cfgFile;
+	gint i;
+
+	XSDEBUG("writing configuration ...\n");
+	XS_MUTEX_LOCK(xs_cfg);
+
+	/* Try to open the XMMS configuration file  */
+#ifdef HAVE_NODEFAULTCFG
+	cfgFilename = g_strconcat(g_get_home_dir(), XS_CONFIG_FILE, NULL);
+	cfgFile = xmms_cfg_open_file(cfgFilename);
+#else
+	cfgFile = xmms_cfg_open_default_file();
+#endif
+
+	if (!cfgFile)
+		cfgFile = xmms_cfg_new();
+
+	/* Write the new settings to XMMS configuration file */
+	for (i = 0; i < xs_cfgtable_max; i++) {
+		switch (xs_cfgtable[i].itemType) {
+		case CTYPE_INT:
+			xmms_cfg_write_int(cfgFile, XS_CONFIG_IDENT, xs_cfgtable[i].itemName,
+					   *(gint *) xs_cfgtable[i].itemData);
+			break;
+
+		case CTYPE_BOOL:
+			xmms_cfg_write_boolean(cfgFile, XS_CONFIG_IDENT, xs_cfgtable[i].itemName,
+					       *(gboolean *) xs_cfgtable[i].itemData);
+			break;
+
+		case CTYPE_FLOAT:
+			xmms_cfg_write_float(cfgFile, XS_CONFIG_IDENT, xs_cfgtable[i].itemName,
+					     *(gfloat *) xs_cfgtable[i].itemData);
+			break;
+
+		case CTYPE_STR:
+			xmms_cfg_write_string(cfgFile, XS_CONFIG_IDENT, xs_cfgtable[i].itemName,
+					      *(gchar **) xs_cfgtable[i].itemData);
+			break;
+
+		default:
+			XSERR
+			    ("Internal: Unsupported setting type found while writing configuration file. Please report to author!\n");
+			break;
+		}
+	}
+
+	/* Flush the file */
+#ifdef HAVE_NODEFAULTCFG
+	xmms_cfg_write_file(cfgFile, cfgFilename);
+	g_free(cfgFilename);
+#else
+	xmms_cfg_write_default_file(cfgFile);
+#endif
+
+	/* Free the memory areas */
+	xmms_cfg_free(cfgFile);
+
+	XS_MUTEX_UNLOCK(xs_cfg);
+
+	return 0;
+}
+
+
+/*
+ * Configuration panel was canceled
+ */
+void xs_cfg_cancel(void)
+{
+	gtk_widget_destroy(xs_configwin);
+	xs_configwin = NULL;
+}
+
+
+/*
+ * Configuration was accepted (OK), save the settings
+ */
+void xs_cfg_ok(void)
+{
+	gint i;
+	gfloat tmpValue;
+
+	XSDEBUG("get data from widgets to config...\n");
+
+	for (i = 0; i < xs_widtable_max; i++) {
+		switch (xs_widtable[i].widType) {
+		case WTYPE_BGROUP:
+			/* Check if toggle-button is active */
+			if (GTK_TOGGLE_BUTTON(LUW(xs_widtable[i].widName))->active) {
+				/* Yes, set the constant value */
+				*((gint *) xs_widtable[i].itemData) = xs_widtable[i].itemSet;
+			}
+			break;
+
+		case WTYPE_SPIN:
+		case WTYPE_SCALE:
+			/* Get the value */
+			switch (xs_widtable[i].widType) {
+			case WTYPE_SPIN:
+				tmpValue =
+				    gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(LUW(xs_widtable[i].widName)))->value;
+				break;
+
+			case WTYPE_SCALE:
+				tmpValue = gtk_range_get_adjustment(GTK_RANGE(LUW(xs_widtable[i].widName)))->value;
+				break;
+
+			default:
+				tmpValue = -1;
+			}
+
+			/* Set the value */
+			switch (xs_widtable[i].itemType) {
+			case CTYPE_INT:
+				*((gint *) xs_widtable[i].itemData) = (gint) tmpValue;
+				break;
+
+			case CTYPE_FLOAT:
+				*((gfloat *) xs_widtable[i].itemData) = tmpValue;
+				break;
+			}
+			break;
+
+		case WTYPE_BUTTON:
+			/* Check if toggle-button is active */
+			*((gboolean *) xs_widtable[i].itemData) =
+			    (GTK_TOGGLE_BUTTON(LUW(xs_widtable[i].widName))->active);
+			break;
+
+		case WTYPE_TEXT:
+			/* Get text from text-widget */
+			xs_pstrcpy((gchar **) xs_widtable[i].itemData,
+				   gtk_entry_get_text(GTK_ENTRY(LUW(xs_widtable[i].widName)))
+			    );
+			break;
+		}
+	}
+
+	/* Close window */
+	gtk_widget_destroy(xs_configwin);
+	xs_configwin = NULL;
+
+	/* Write settings */
+	xs_write_configuration();
+
+	/* Re-initialize */
+	xs_reinit();
+}
+
+
+/*
+ * Reset filter settings to defaults
+ */
+void xs_cfg_filter_reset(GtkButton * button, gpointer user_data)
+{
+	(void) button;
+	(void) user_data;
+
+	gtk_adjustment_set_value(gtk_range_get_adjustment(GTK_RANGE(LUW("cfg_emu_filt_fs"))), XS_SIDPLAY1_FS);
+	gtk_adjustment_set_value(gtk_range_get_adjustment(GTK_RANGE(LUW("cfg_emu_filt_fm"))), XS_SIDPLAY1_FM);
+	gtk_adjustment_set_value(gtk_range_get_adjustment(GTK_RANGE(LUW("cfg_emu_filt_ft"))), XS_SIDPLAY1_FT);
+}
+
+
+
+
+/*
+ * HVSC songlength-database file selector response-functions
+ */
+void xs_cfg_sld_dbbrowse(GtkButton * button, gpointer user_data)
+{
+	(void) button;
+	(void) user_data;
+
+	if (xs_sldb_fileselector != NULL) {
+		gdk_window_raise(xs_sldb_fileselector->window);
+		return;
+	}
+
+	xs_sldb_fileselector = create_xs_sldbfileselector();
+	XS_MUTEX_LOCK(xs_cfg);
+	gtk_file_selection_set_filename(GTK_FILE_SELECTION(xs_sldb_fileselector), xs_cfg.songlenDBPath);
+	XS_MUTEX_UNLOCK(xs_cfg);
+	gtk_widget_show(xs_sldb_fileselector);
+}
+
+
+void xs_cfg_sldb_fs_ok(void)
+{
+	/* Selection was accepted! */
+	gtk_entry_set_text(GTK_ENTRY(LUW("cfg_sld_dbpath")),
+			   gtk_file_selection_get_filename(GTK_FILE_SELECTION(xs_sldb_fileselector)));
+
+	/* Close file selector window */
+	gtk_widget_destroy(xs_sldb_fileselector);
+	xs_sldb_fileselector = NULL;
+}
+
+
+void xs_cfg_sldb_fs_cancel(void)
+{
+	/* Close file selector window */
+	gtk_widget_destroy(xs_sldb_fileselector);
+	xs_sldb_fileselector = NULL;
+}
+
+
+/*
+ * STIL-database file selector response-functions
+ */
+void xs_cfg_stil_browse(GtkButton * button, gpointer user_data)
+{
+	(void) button;
+	(void) user_data;
+
+	if (xs_stil_fileselector != NULL) {
+		gdk_window_raise(xs_stil_fileselector->window);
+		return;
+	}
+
+	xs_stil_fileselector = create_xs_stilfileselector();
+	XS_MUTEX_LOCK(xs_cfg);
+	gtk_file_selection_set_filename(GTK_FILE_SELECTION(xs_stil_fileselector), xs_cfg.stilDBPath);
+	XS_MUTEX_UNLOCK(xs_cfg);
+	gtk_widget_show(xs_stil_fileselector);
+}
+
+
+void xs_cfg_stil_fs_ok(void)
+{
+	/* Selection was accepted! */
+	gtk_entry_set_text(GTK_ENTRY(LUW("cfg_stil_dbpath")),
+			   gtk_file_selection_get_filename(GTK_FILE_SELECTION(xs_stil_fileselector)));
+
+	/* Close file selector window */
+	gtk_widget_destroy(xs_stil_fileselector);
+	xs_stil_fileselector = NULL;
+}
+
+
+void xs_cfg_stil_fs_cancel(void)
+{
+	/* Close file selector window */
+	gtk_widget_destroy(xs_stil_fileselector);
+	xs_stil_fileselector = NULL;
+}
+
+
+/*
+ * HVSC location selector response-functions
+ */
+void xs_cfg_hvsc_browse(GtkButton * button, gpointer user_data)
+{
+	(void) button;
+	(void) user_data;
+
+	if (xs_hvsc_pathselector != NULL) {
+		gdk_window_raise(xs_hvsc_pathselector->window);
+		return;
+	}
+
+	xs_hvsc_pathselector = create_xs_hvscpathselector();
+	XS_MUTEX_LOCK(xs_cfg);
+	gtk_file_selection_set_filename(GTK_FILE_SELECTION(xs_hvsc_pathselector), xs_cfg.hvscPath);
+	XS_MUTEX_UNLOCK(xs_cfg);
+	gtk_widget_show(xs_hvsc_pathselector);
+}
+
+
+void xs_cfg_hvsc_fs_ok(void)
+{
+	/* Selection was accepted! */
+	gtk_entry_set_text(GTK_ENTRY(LUW("cfg_hvsc_path")),
+			   gtk_file_selection_get_filename(GTK_FILE_SELECTION(xs_hvsc_pathselector)));
+
+	/* Close file selector window */
+	gtk_widget_destroy(xs_hvsc_pathselector);
+	xs_hvsc_pathselector = NULL;
+}
+
+
+void xs_cfg_hvsc_fs_cancel(void)
+{
+	/* Close file selector window */
+	gtk_widget_destroy(xs_hvsc_pathselector);
+	xs_hvsc_pathselector = NULL;
+}
+
+
+/*
+ * Selection toggle handlers
+ */
+void xs_cfg_emu_filters_toggled(GtkToggleButton * togglebutton, gpointer user_data)
+{
+	gboolean isActive = GTK_TOGGLE_BUTTON(togglebutton)->active;
+
+	(void) user_data;
+
+	gtk_widget_set_sensitive(LUW("cfg_filters_notebook"), isActive);
+}
+
+
+void xs_cfg_ftitle_override_toggled(GtkToggleButton * togglebutton, gpointer user_data)
+{
+	gboolean isActive = GTK_TOGGLE_BUTTON(togglebutton)->active;
+
+	(void) user_data;
+
+	gtk_widget_set_sensitive(LUW("cfg_ftitle_format"), isActive);
+	gtk_widget_set_sensitive(LUW("cfg_ftitle_desc1"), isActive);
+	gtk_widget_set_sensitive(LUW("cfg_ftitle_desc2"), isActive);
+}
+
+
+void xs_cfg_emu_sidplay1_toggled(GtkToggleButton * togglebutton, gpointer user_data)
+{
+	(void) togglebutton;
+	(void) user_data;
+}
+
+
+void xs_cfg_emu_sidplay2_toggled(GtkToggleButton * togglebutton, gpointer user_data)
+{
+	gboolean isActive = GTK_TOGGLE_BUTTON(togglebutton)->active;
+
+	(void) user_data;
+
+	gtk_widget_set_sensitive(LUW("cfg_emu_mem_real"), isActive);
+
+	gtk_widget_set_sensitive(LUW("cfg_sidplay2_grp"), isActive);
+	gtk_widget_set_sensitive(LUW("cfg_emu_sidplay2_opt"), isActive);
+
+	gtk_widget_set_sensitive(LUW("cfg_chn_autopan"), !isActive);
+
+#ifdef HAVE_RESID_BUILDER
+	gtk_widget_set_sensitive(LUW("cfg_emu_sidplay2_resid"), isActive);
+#else
+	gtk_widget_set_sensitive(LUW("cfg_emu_sidplay2_resid"), FALSE);
+#endif
+
+#ifdef HAVE_HARDSID_BUILDER
+	gtk_widget_set_sensitive(LUW("cfg_emu_sidplay2_hardsid"), isActive);
+#else
+	gtk_widget_set_sensitive(LUW("cfg_emu_sidplay2_hardsid"), FALSE);
+#endif
+}
+
+
+void xs_cfg_oversample_toggled(GtkToggleButton * togglebutton, gpointer user_data)
+{
+	gboolean isActive = GTK_TOGGLE_BUTTON(togglebutton)->active;
+
+	(void) user_data;
+
+	gtk_widget_set_sensitive(LUW("cfg_oversample_factor"), isActive);
+	gtk_widget_set_sensitive(LUW("cfg_oversample_label1"), isActive);
+	gtk_widget_set_sensitive(LUW("cfg_oversample_label2"), isActive);
+}
+
+
+void xs_cfg_mintime_enable_toggled(GtkToggleButton * togglebutton, gpointer user_data)
+{
+	gboolean isActive = GTK_TOGGLE_BUTTON(togglebutton)->active;
+
+	(void) user_data;
+
+	gtk_widget_set_sensitive(LUW("cfg_mintime"), isActive);
+	gtk_widget_set_sensitive(LUW("cfg_mintime_label1"), isActive);
+	gtk_widget_set_sensitive(LUW("cfg_mintime_label2"), isActive);
+}
+
+
+void xs_cfg_maxtime_enable_toggled(GtkToggleButton * togglebutton, gpointer user_data)
+{
+	gboolean isActive = GTK_TOGGLE_BUTTON(LUW("cfg_maxtime_enable"))->active;
+
+	(void) togglebutton;
+	(void) user_data;
+
+	gtk_widget_set_sensitive(LUW("cfg_maxtime_unknown"), isActive);
+	gtk_widget_set_sensitive(LUW("cfg_maxtime"), isActive);
+	gtk_widget_set_sensitive(LUW("cfg_maxtime_label1"), isActive);
+	gtk_widget_set_sensitive(LUW("cfg_maxtime_label2"), isActive);
+}
+
+
+void xs_cfg_sld_enable_toggled(GtkToggleButton * togglebutton, gpointer user_data)
+{
+	gboolean isActive = GTK_TOGGLE_BUTTON(togglebutton)->active;
+
+	(void) user_data;
+
+	gtk_widget_set_sensitive(LUW("cfg_sld_dbpath"), isActive);
+	gtk_widget_set_sensitive(LUW("cfg_sld_dbbrowse"), isActive);
+	gtk_widget_set_sensitive(LUW("cfg_sld_label1"), isActive);
+}
+
+
+void xs_cfg_stil_enable_toggled(GtkToggleButton * togglebutton, gpointer user_data)
+{
+	gboolean isActive = GTK_TOGGLE_BUTTON(togglebutton)->active;
+
+	(void) user_data;
+
+	gtk_widget_set_sensitive(LUW("cfg_stil_dbpath"), isActive);
+	gtk_widget_set_sensitive(LUW("cfg_stil_browse"), isActive);
+	gtk_widget_set_sensitive(LUW("cfg_stil_label1"), isActive);
+
+	gtk_widget_set_sensitive(LUW("cfg_hvsc_path"), isActive);
+	gtk_widget_set_sensitive(LUW("cfg_hvsc_browse"), isActive);
+	gtk_widget_set_sensitive(LUW("cfg_hvsc_label1"), isActive);
+}
+
+
+void xs_cfg_subauto_enable_toggled(GtkToggleButton * togglebutton, gpointer user_data)
+{
+	gboolean isActive = GTK_TOGGLE_BUTTON(togglebutton)->active;
+
+	(void) user_data;
+
+	gtk_widget_set_sensitive(LUW("cfg_subauto_min_only"), isActive);
+	gtk_widget_set_sensitive(LUW("cfg_subauto_mintime"), isActive);
+}
+
+
+void xs_cfg_subauto_min_only_toggled(GtkToggleButton * togglebutton, gpointer user_data)
+{
+	gboolean isActive = GTK_TOGGLE_BUTTON(togglebutton)->active &&
+		GTK_TOGGLE_BUTTON(LUW("cfg_subauto_enable"))->active;
+
+	(void) user_data;
+
+	gtk_widget_set_sensitive(LUW("cfg_subauto_mintime"), isActive);
+}
+
+
+void xs_cfg_mintime_changed(GtkEditable * editable, gpointer user_data)
+{
+	gint tmpValue;
+	GtkAdjustment *tmpAdj;
+
+	(void) user_data;
+
+	tmpAdj = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(LUW("cfg_maxtime")));
+
+	tmpValue = (gint) gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(editable))->value;
+
+	if (tmpValue > tmpAdj->value)
+		gtk_adjustment_set_value(tmpAdj, tmpValue);
+}
+
+
+void xs_cfg_maxtime_changed(GtkEditable * editable, gpointer user_data)
+{
+	gint tmpValue;
+	GtkAdjustment *tmpAdj;
+
+	(void) user_data;
+
+	tmpAdj = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(LUW("cfg_mintime")));
+
+	tmpValue = (gint) gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(editable))->value;
+
+	if (tmpValue < tmpAdj->value)
+		gtk_adjustment_set_value(tmpAdj, tmpValue);
+}
+
+
+void xs_cfg_filter2_reset(GtkButton * button, gpointer user_data)
+{
+	(void) button; (void) user_data;
+}
+
+/*
+ * Execute the configuration panel
+ */
+void xs_configure(void)
+{
+	gint i;
+	gfloat tmpValue;
+
+	/* Check if the window already exists */
+	if (xs_configwin != NULL) {
+		gdk_window_raise(xs_configwin->window);
+		return;
+	}
+
+	/* Create the window */
+	xs_configwin = create_xs_configwin();
+
+	/* Get lock on configuration */
+	XS_MUTEX_LOCK(xs_cfg);
+
+	/* Based on available optional parts, gray out options */
+#ifndef HAVE_SIDPLAY1
+	gtk_widget_set_sensitive(LUW("cfg_emu_sidplay1"), FALSE);
+	gtk_widget_set_sensitive(LUW("cfg_box_sidplay1"), FALSE);
+#endif
+
+#ifndef HAVE_SIDPLAY2
+	gtk_widget_set_sensitive(LUW("cfg_emu_sidplay2"), FALSE);
+	gtk_widget_set_sensitive(LUW("cfg_box_sidplay2"), FALSE);
+#endif
+
+#ifndef HAVE_XMMSEXTRA
+	gtk_widget_set_sensitive(LUW("cfg_ftitle_override"), FALSE);
+	xs_cfg.titleOverride = TRUE;
+#endif
+
+#ifndef HAVE_SONG_POSITION
+	gtk_widget_set_sensitive(LUW("cfg_subctrl_patch"), FALSE);
+#endif
+
+	/* Update the widget sensitivities */
+	xs_cfg_emu_filters_toggled((GtkToggleButton *) LUW("cfg_emu_filters"), NULL);
+	xs_cfg_ftitle_override_toggled((GtkToggleButton *) LUW("cfg_ftitle_override"), NULL);
+	xs_cfg_emu_sidplay1_toggled((GtkToggleButton *) LUW("cfg_emu_sidplay1"), NULL);
+	xs_cfg_emu_sidplay2_toggled((GtkToggleButton *) LUW("cfg_emu_sidplay2"), NULL);
+	xs_cfg_oversample_toggled((GtkToggleButton *) LUW("cfg_oversample"), NULL);
+	xs_cfg_mintime_enable_toggled((GtkToggleButton *) LUW("cfg_mintime_enable"), NULL);
+	xs_cfg_maxtime_enable_toggled((GtkToggleButton *) LUW("cfg_maxtime_enable"), NULL);
+	xs_cfg_sld_enable_toggled((GtkToggleButton *) LUW("cfg_sld_enable"), NULL);
+	xs_cfg_stil_enable_toggled((GtkToggleButton *) LUW("cfg_stil_enable"), NULL);
+	xs_cfg_subauto_enable_toggled((GtkToggleButton *) LUW("cfg_subauto_enable"), NULL);
+	xs_cfg_subauto_min_only_toggled((GtkToggleButton *) LUW("cfg_subauto_min_only"), NULL);
+
+
+	/* Set current data to widgets */
+	for (i = 0; i < xs_widtable_max; i++) {
+		switch (xs_widtable[i].widType) {
+		case WTYPE_BGROUP:
+			/* Check if current value matches the given one */
+			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(LUW(xs_widtable[i].widName)),
+						     (*((gint *) xs_widtable[i].itemData) == xs_widtable[i].itemSet)
+			    );
+			break;
+
+
+		case WTYPE_SPIN:
+		case WTYPE_SCALE:
+			/* Get the value */
+			switch (xs_widtable[i].itemType) {
+			case CTYPE_INT:
+				tmpValue = (gfloat) * ((gint *) xs_widtable[i].itemData);
+				break;
+
+			case CTYPE_FLOAT:
+				tmpValue = *((gfloat *) xs_widtable[i].itemData);
+				break;
+
+			default:
+				tmpValue = -1;
+			}
+
+			/* Set the value */
+			switch (xs_widtable[i].widType) {
+			case WTYPE_SPIN:
+				gtk_adjustment_set_value(gtk_spin_button_get_adjustment
+							 (GTK_SPIN_BUTTON(LUW(xs_widtable[i].widName))), tmpValue);
+				break;
+
+			case WTYPE_SCALE:
+				gtk_adjustment_set_value(gtk_range_get_adjustment
+							 (GTK_RANGE(LUW(xs_widtable[i].widName))), tmpValue);
+				break;
+			}
+			break;
+
+		case WTYPE_BUTTON:
+			/* Set toggle-button */
+			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(LUW(xs_widtable[i].widName)),
+						     *((gboolean *) xs_widtable[i].itemData)
+			    );
+			break;
+
+		case WTYPE_TEXT:
+			/* Set text to text-widget */
+			if (*(gchar **) xs_widtable[i].itemData != NULL) {
+				gtk_entry_set_text(GTK_ENTRY(LUW(xs_widtable[i].widName)),
+						   *(gchar **) xs_widtable[i].itemData);
+			}
+			break;
+		}
+	}
+
+	/* Release the configuration */
+	XS_MUTEX_UNLOCK(xs_cfg);
+
+	/* Show the widget */
+	gtk_widget_show(xs_configwin);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_config.h	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,167 @@
+#ifndef XS_CONFIG_H
+#define XS_CONFIG_H
+
+#include "xmms-sid.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Configuration structure
+ */
+enum XS_EMUENGINE {
+	XS_ENG_SIDPLAY1 = 1,
+	XS_ENG_SIDPLAY2
+};
+
+
+enum XS_BUILDER {
+	XS_BLD_RESID = 1,
+	XS_BLD_HARDSID
+};
+
+enum XS_RESOLUTION {
+	XS_RES_8BIT = 8,
+	XS_RES_16BIT = 16
+};
+
+enum XS_CHANNELS {
+	XS_CHN_MONO = 1,
+	XS_CHN_STEREO = 2,
+	XS_CHN_AUTOPAN = 3
+};
+
+
+enum XS_CLOCK {
+	XS_CLOCK_PAL = 1,
+	XS_CLOCK_NTSC
+};
+
+
+enum XS_MPU {
+	XS_MPU_BANK_SWITCHING = 1,
+	XS_MPU_TRANSPARENT_ROM,
+	XS_MPU_PLAYSID_ENVIRONMENT,
+	XS_MPU_REAL
+};
+
+
+enum XS_SSC {
+	XS_SSC_NONE = 1,
+	XS_SSC_POPUP,
+	XS_SSC_PATCH,
+	XS_SSC_SEEK
+};
+
+
+enum XS_SIDMODEL {
+	XS_SIDMODEL_UNKNOWN = 0,
+	XS_SIDMODEL_6581,
+	XS_SIDMODEL_8580
+};
+
+
+extern struct t_xs_cfg {
+	/* General audio settings */
+	gint		audioBitsPerSample;
+	gint		audioChannels;
+	gint		audioFrequency;
+
+	/* General libSIDPlay settings */
+	gboolean	mos8580;		/* TRUE = 8580, FALSE = 6581 */
+	gboolean	forceModel;
+	gboolean	emulateFilters;
+	gfloat		filterFs;
+	gfloat		filterFm;
+	gfloat		filterFt;
+	gint		memoryMode;		/* See XS_MPU-constants */
+	gint		clockSpeed;		/* PAL (50Hz) or NTSC (60Hz) */
+	gboolean	forceSpeed;		/* TRUE = force to given clockspeed */
+
+	gint		playerEngine;		/* Selected player engine */
+
+	gboolean	sid2OptLevel;		/* SIDPlay2 emulation optimization */
+	gint		sid2Builder;		/* SIDPlay2 "builder" aka SID-emu */
+
+	gboolean	oversampleEnable;
+	gint		oversampleFactor;	/* Factor of oversampling */
+
+	/* Playing settings */
+	gboolean	playMaxTimeEnable,
+			playMaxTimeUnknown;	/* Use max-time only when song-length is unknown */
+	gint		playMaxTime;		/* MAX playtime in seconds */
+
+	gboolean	playMinTimeEnable;
+	gint		playMinTime;		/* MIN playtime in seconds */
+
+	gboolean	songlenDBEnable;
+	gchar		*songlenDBPath;		/* Path to Songlengths.txt */
+
+
+	/* Miscellaneous settings */
+	gboolean	stilDBEnable;
+	gchar		*stilDBPath;		/* Path to STIL.txt */
+	gchar		*hvscPath;		/* Path-prefix for HVSC */
+
+	gint		subsongControl;
+	gboolean	detectMagic;
+
+	gboolean	titleOverride;		/* TRUE if XMMS titles are overriden */
+	gchar		*titleFormat;
+
+	gboolean	subAutoEnable,
+			subAutoMinOnly;
+	gint		subAutoMinTime;
+} xs_cfg;
+
+XS_MUTEX_H(xs_cfg);
+
+/*
+ * Configuration-file
+ */
+enum {
+	CTYPE_INT = 1,
+	CTYPE_FLOAT,
+	CTYPE_STR,
+	CTYPE_BOOL
+};
+
+enum {
+	WTYPE_BGROUP = 1,
+	WTYPE_SPIN,
+	WTYPE_SCALE,
+	WTYPE_BUTTON,
+	WTYPE_TEXT
+};
+
+
+typedef struct {
+	gint	itemType;	/* Type of item (CTYPE_*) */
+	void	*itemData;	/* Pointer to variable */
+	gchar	*itemName;	/* Name of configuration item */
+} t_xs_cfg_item;
+
+
+typedef struct {
+	gint	widType;
+	gint	itemType;
+	gchar	*widName;
+	void	*itemData;
+	gint	itemSet;
+} t_xs_wid_item;
+
+
+/*
+ * Functions
+ */
+void	xs_init_configuration(void);
+void	xs_configure(void);
+void	xs_read_configuration(void);
+gint	xs_write_configuration(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* XS_CONFIG_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_fileinfo.c	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,252 @@
+/*
+   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
+
+   File information window
+
+   Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org>
+   (C) Copyright 1999-2005 Tecnic Software productions (TNSP)
+
+   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 <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include "xs_fileinfo.h"
+#include "xs_support.h"
+#include "xs_stil.h"
+#include "xs_config.h"
+#include "xs_interface.h"
+#include "xs_glade.h"
+
+static GtkWidget *xs_fileinfowin = NULL;
+static t_xs_stil_node *xs_fileinfostil = NULL;
+XS_MUTEX(xs_fileinfowin);
+
+#define LUW(x)	lookup_widget(xs_fileinfowin, x)
+
+
+void xs_fileinfo_update(void)
+{
+	gboolean isEnabled;
+	GtkAdjustment *tmpAdj;
+
+	XS_MUTEX_LOCK(xs_status);
+	XS_MUTEX_LOCK(xs_fileinfowin);
+
+	/* Check if control window exists, we are currently playing and have a tune */
+	if (xs_fileinfowin) {
+		if (xs_status.tuneInfo && xs_status.isPlaying && (xs_status.tuneInfo->nsubTunes > 1)) {
+			tmpAdj = gtk_range_get_adjustment(GTK_RANGE(LUW("fileinfo_subctrl_adj")));
+
+			tmpAdj->value = xs_status.currSong;
+			tmpAdj->lower = 1;
+			tmpAdj->upper = xs_status.tuneInfo->nsubTunes;
+			XS_MUTEX_UNLOCK(xs_status);
+			XS_MUTEX_UNLOCK(xs_fileinfowin);
+			gtk_adjustment_value_changed(tmpAdj);
+			XS_MUTEX_LOCK(xs_status);
+			XS_MUTEX_LOCK(xs_fileinfowin);
+			isEnabled = TRUE;
+		} else
+			isEnabled = FALSE;
+
+		/* Enable or disable subtune-control in fileinfo window */
+		gtk_widget_set_sensitive(LUW("fileinfo_subctrl_prev"), isEnabled);
+		gtk_widget_set_sensitive(LUW("fileinfo_subctrl_adj"), isEnabled);
+		gtk_widget_set_sensitive(LUW("fileinfo_subctrl_next"), isEnabled);
+	}
+
+	XS_MUTEX_UNLOCK(xs_status);
+	XS_MUTEX_UNLOCK(xs_fileinfowin);
+}
+
+
+void xs_fileinfo_setsong(void)
+{
+	gint n;
+
+	XS_MUTEX_LOCK(xs_status);
+	XS_MUTEX_LOCK(xs_fileinfowin);
+
+	if (xs_status.tuneInfo && xs_status.isPlaying) {
+		n = (gint) gtk_range_get_adjustment(GTK_RANGE(LUW("fileinfo_subctrl_adj")))->value;
+		if ((n >= 1) && (n <= xs_status.tuneInfo->nsubTunes))
+			xs_status.currSong = n;
+	}
+
+	XS_MUTEX_UNLOCK(xs_fileinfowin);
+	XS_MUTEX_UNLOCK(xs_status);
+}
+
+
+void xs_fileinfo_ok(void)
+{
+	XS_MUTEX_LOCK(xs_fileinfowin);
+	if (xs_fileinfowin) {
+		gtk_widget_destroy(xs_fileinfowin);
+		xs_fileinfowin = NULL;
+	}
+	XS_MUTEX_UNLOCK(xs_fileinfowin);
+}
+
+
+gboolean xs_fileinfo_delete(GtkWidget * widget, GdkEvent * event, gpointer user_data)
+{
+	(void) widget;
+	(void) event;
+	(void) user_data;
+
+	XSDEBUG("delete_event\n");
+	xs_fileinfo_ok();
+	return FALSE;
+}
+
+
+
+void xs_fileinfo_subtune(GtkWidget * widget, void *data)
+{
+	t_xs_stil_subnode *tmpNode;
+	GtkWidget *tmpItem, *tmpText;
+	gint tmpIndex;
+	gchar *subName, *subAuthor;
+
+	(void) widget;
+	(void) data;
+
+	/* Freeze text-widget and delete the old text */
+	tmpText = LUW("fileinfo_sub_info");
+
+	if (xs_fileinfostil) {
+		/* Get subtune number */
+		tmpItem = gtk_menu_get_active(GTK_MENU(data));
+		tmpIndex = g_list_index(GTK_MENU_SHELL(data)->children, tmpItem);
+
+		/* Get subtune information */
+		tmpNode = &xs_fileinfostil->subTunes[tmpIndex];
+		subName = tmpNode->pName;
+		subAuthor = tmpNode->pAuthor;
+
+		/* Put in the new text, if available */
+		if (tmpNode->pInfo) {
+			gsize pInfo_utf8_size;
+			gchar *pInfo_utf8 = g_locale_to_utf8( tmpNode->pInfo , strlen(tmpNode->pInfo) , NULL , &pInfo_utf8_size , NULL );
+			gtk_text_buffer_set_text( GTK_TEXT_BUFFER(gtk_text_view_get_buffer(GTK_TEXT_VIEW(tmpText))),
+			  pInfo_utf8, pInfo_utf8_size);
+		}
+	} else {
+		/* We don't have any information */
+		subName = NULL;
+		subAuthor = NULL;
+	}
+
+	/* Get and set subtune information */
+	gtk_entry_set_text(GTK_ENTRY(LUW("fileinfo_sub_name")), subName ? g_locale_to_utf8(subName,strlen(subName),NULL,NULL,NULL) : "");
+	gtk_entry_set_text(GTK_ENTRY(LUW("fileinfo_sub_author")), subAuthor ? g_locale_to_utf8(subAuthor,strlen(subAuthor),NULL,NULL,NULL) : "");
+}
+
+
+void xs_fileinfo(gchar * pcFilename)
+{
+	GtkWidget *tmpMenuItem, *tmpMenu, *tmpOptionMenu;
+	t_xs_tuneinfo *tmpInfo;
+	t_xs_stil_subnode *tmpNode;
+	gchar tmpStr[64];
+	gint n;
+
+	/* Current implementation leaves old fileinfo window untouched if
+	 * no information can be found for the new file. Hmm...
+	 */
+
+	/* Get new tune information */
+	XS_MUTEX_LOCK(xs_fileinfowin);
+	XS_MUTEX_LOCK(xs_status);
+	if ((tmpInfo = xs_status.sidPlayer->plrGetSIDInfo(pcFilename)) == NULL) {
+		XS_MUTEX_UNLOCK(xs_fileinfowin);
+		XS_MUTEX_UNLOCK(xs_status);
+		return;
+	}
+	XS_MUTEX_UNLOCK(xs_status);
+
+	xs_fileinfostil = xs_stil_get(pcFilename);
+
+	/* Check if there already is an open fileinfo window */
+	if (xs_fileinfowin) {
+		/* Raise old window */
+		gdk_window_raise(xs_fileinfowin->window);
+
+		/* Delete items */
+		tmpOptionMenu = LUW("fileinfo_sub_tune");
+		gtk_widget_destroy(GTK_OPTION_MENU(tmpOptionMenu)->menu);
+		GTK_OPTION_MENU(tmpOptionMenu)->menu = gtk_menu_new();
+	} else {
+		/* If not, create a new one */
+		xs_fileinfowin = create_xs_fileinfowin();
+
+		/* Connect additional signals */
+		gtk_signal_connect(GTK_OBJECT(gtk_range_get_adjustment(GTK_RANGE(LUW("fileinfo_subctrl_adj")))),
+				   "value_changed", GTK_SIGNAL_FUNC(xs_fileinfo_setsong), NULL);
+	}
+
+
+	/* Set the generic song information */
+	gtk_entry_set_text(GTK_ENTRY(LUW("fileinfo_filename")), g_locale_to_utf8(pcFilename,strlen(pcFilename),NULL,NULL,NULL) );
+	gtk_entry_set_text(GTK_ENTRY(LUW("fileinfo_songname")), g_locale_to_utf8(tmpInfo->sidName,strlen(tmpInfo->sidName),NULL,NULL,NULL) );
+	gtk_entry_set_text(GTK_ENTRY(LUW("fileinfo_composer")), g_locale_to_utf8(tmpInfo->sidComposer,strlen(tmpInfo->sidComposer),NULL,NULL,NULL) );
+	gtk_entry_set_text(GTK_ENTRY(LUW("fileinfo_copyright")), g_locale_to_utf8(tmpInfo->sidCopyright,strlen(tmpInfo->sidCopyright),NULL,NULL,NULL) );
+
+	/* Main tune - the pseudo tune */
+	tmpOptionMenu = LUW("fileinfo_sub_tune");
+	tmpMenu = GTK_OPTION_MENU(tmpOptionMenu)->menu;
+
+	tmpMenuItem = gtk_menu_item_new_with_label("General info");
+	gtk_widget_show(tmpMenuItem);
+	gtk_menu_append(GTK_MENU(tmpMenu), tmpMenuItem);
+	gtk_signal_connect(GTK_OBJECT(tmpMenuItem), "activate", GTK_SIGNAL_FUNC(xs_fileinfo_subtune), tmpMenu);
+
+	/* Other menu items */
+	for (n = 1; n <= tmpInfo->nsubTunes; n++) {
+		if (xs_fileinfostil) {
+			snprintf(tmpStr, sizeof(tmpStr), "Tune #%i: ", n);
+			tmpNode = &xs_fileinfostil->subTunes[n];
+			if (tmpNode->pName)
+				xs_pnstrcat(tmpStr, sizeof(tmpStr), tmpNode->pName);
+			else if (tmpNode->pInfo)
+				xs_pnstrcat(tmpStr, sizeof(tmpStr), tmpNode->pInfo);
+			else
+				xs_pnstrcat(tmpStr, sizeof(tmpStr), "---");
+		} else {
+			snprintf(tmpStr, sizeof(tmpStr), "Tune #%i", n);
+		}
+
+		tmpMenuItem = gtk_menu_item_new_with_label(tmpStr);
+		gtk_widget_show(tmpMenuItem);
+		gtk_menu_append(GTK_MENU(tmpMenu), tmpMenuItem);
+
+		gtk_signal_connect(GTK_OBJECT(tmpMenuItem), "activate", GTK_SIGNAL_FUNC(xs_fileinfo_subtune), tmpMenu);
+	}
+
+	/* Set the subtune information */
+	xs_fileinfo_subtune(NULL, tmpMenu);
+
+	/* Free temporary tuneinfo */
+	xs_tuneinfo_free(tmpInfo);
+
+	/* Show the window */
+	gtk_widget_show(xs_fileinfowin);
+
+	XS_MUTEX_UNLOCK(xs_fileinfowin);
+
+	xs_fileinfo_update();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_fileinfo.h	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,16 @@
+#ifndef XS_FILEINFO_H
+#define XS_FILEINFO_H
+
+#include "xmms-sid.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void	xs_fileinfo_update(void);
+void	xs_fileinfo(gchar *);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* XS_FILEINFO_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_filter.c	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,84 @@
+/*  
+   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
+
+   Audio rate-conversion filter
+   
+   Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org>
+   (C) Copyright 1999-2005 Tecnic Software productions (TNSP)
+
+   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 "xs_filter.h"
+
+/* Let's do some preprocessor magic :) */
+#define XS_FVAR(T, P, K) g ## K ## int ## P *sp_ ## T ## P , *dp_ ## T ## P
+
+#define XS_FILTER1(T, P, K, Q)							\
+	dataSize /= sizeof(g ## K ## int ## P); 				\
+	sp_ ## T ## P = (g ## K ## int ## P *) srcBuf;				\
+	dp_ ## T ## P = (g ## K ## int ## P *) destBuf;				\
+	while (dataSize-- > 0) {						\
+		for (tmp = 0, i = 0; i < oversampleFactor; i++)			\
+			tmp += (gint32) ((gint ## P) (*(sp_ ## T ## P ++) Q));	\
+		xs_filter_mbn = (tmp + xs_filter_mbn) / (oversampleFactor + 1);	\
+		*(dp_ ## T ## P ++) = ((g ## K ## int ## P) xs_filter_mbn) Q ;	\
+		}
+
+
+static gint32 xs_filter_mbn = 0;
+
+
+gint xs_filter_rateconv(void *destBuf, void *srcBuf, const AFormat audioFormat, const gint oversampleFactor,
+			const gint bufSize)
+{
+	static gint32 tmp;
+	XS_FVAR(s, 8,);
+	XS_FVAR(u, 8, u);
+	XS_FVAR(s, 16,);
+	XS_FVAR(u, 16, u);
+	gint i;
+	gint dataSize = bufSize;
+
+	if (dataSize <= 0)
+		return dataSize;
+
+	switch (audioFormat) {
+	case FMT_U8:
+		XS_FILTER1(u, 8, u, ^0x80)
+		    break;
+
+	case FMT_S8:
+		XS_FILTER1(s, 8,,)
+		    break;
+
+
+	case FMT_U16_BE:
+	case FMT_U16_LE:
+	case FMT_U16_NE:
+		XS_FILTER1(u, 16, u, ^0x8000)
+		    break;
+
+	case FMT_S16_BE:
+	case FMT_S16_LE:
+	case FMT_S16_NE:
+		XS_FILTER1(s, 16,,)
+		    break;
+
+	default:
+		return -1;
+	}
+
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_filter.h	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,21 @@
+#ifndef XS_FILTER_H
+#define XS_FILTER_H
+
+#include "xmms-sid.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+typedef struct {
+} t_xs_filter;
+
+void	xs_filter_init(t_xs_filter *);
+*/
+gint	xs_filter_rateconv(void *, void *, const AFormat, const gint, const gint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* XS_FILTER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_genui.c	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,26 @@
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+
+#include "xs_genui.h"
+#include "xs_interface.h"
+#include "xs_glade.h"
+
+void xs_cfg_samplerate_menu_clicked(GtkButton * button, gpointer user_data)
+{
+	(void) button; (void) user_data;
+}
+
+
+void xs_cfg_filter_sync_clicked(GtkButton * button, gpointer user_data)
+{
+	(void) button; (void) user_data;
+}
+
+
+void xs_cfg_filter2_sync_clicked(GtkButton * button, gpointer user_data)
+{
+	(void) button; (void) user_data;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_genui.h	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,135 @@
+#include <gtk/gtk.h>
+
+
+void
+xs_cfg_samplerate_menu_clicked         (GtkButton       *button,
+                                        gpointer         user_data);
+
+void
+xs_cfg_oversample_toggled              (GtkToggleButton *togglebutton,
+                                        gpointer         user_data);
+
+void
+xs_cfg_emu_sidplay1_toggled            (GtkToggleButton *togglebutton,
+                                        gpointer         user_data);
+
+void
+xs_cfg_emu_sidplay2_toggled            (GtkToggleButton *togglebutton,
+                                        gpointer         user_data);
+
+void
+xs_cfg_emu_filters_toggled             (GtkToggleButton *togglebutton,
+                                        gpointer         user_data);
+
+void
+xs_cfg_filter_reset                    (GtkButton       *button,
+                                        gpointer         user_data);
+
+void
+xs_cfg_filter_sync_clicked             (GtkButton       *button,
+                                        gpointer         user_data);
+
+void
+xs_cfg_filter2_reset                   (GtkButton       *button,
+                                        gpointer         user_data);
+
+void
+xs_cfg_filter2_sync_clicked            (GtkButton       *button,
+                                        gpointer         user_data);
+
+void
+xs_cfg_mintime_enable_toggled          (GtkToggleButton *togglebutton,
+                                        gpointer         user_data);
+
+void
+xs_cfg_mintime_changed                 (GtkEditable     *editable,
+                                        gpointer         user_data);
+
+void
+xs_cfg_maxtime_enable_toggled          (GtkToggleButton *togglebutton,
+                                        gpointer         user_data);
+
+void
+xs_cfg_maxtime_changed                 (GtkEditable     *editable,
+                                        gpointer         user_data);
+
+void
+xs_cfg_sld_enable_toggled              (GtkToggleButton *togglebutton,
+                                        gpointer         user_data);
+
+void
+xs_cfg_sld_dbbrowse                    (GtkButton       *button,
+                                        gpointer         user_data);
+
+void
+xs_cfg_stil_enable_toggled             (GtkToggleButton *togglebutton,
+                                        gpointer         user_data);
+
+void
+xs_cfg_stil_browse                     (GtkButton       *button,
+                                        gpointer         user_data);
+
+void
+xs_cfg_hvsc_browse                     (GtkButton       *button,
+                                        gpointer         user_data);
+
+void
+xs_cfg_ftitle_override_toggled         (GtkToggleButton *togglebutton,
+                                        gpointer         user_data);
+
+void
+xs_cfg_subauto_enable_toggled          (GtkToggleButton *togglebutton,
+                                        gpointer         user_data);
+
+void
+xs_cfg_subauto_min_only_toggled        (GtkToggleButton *togglebutton,
+                                        gpointer         user_data);
+
+void
+xs_cfg_ok                              (GtkButton       *button,
+                                        gpointer         user_data);
+
+void
+xs_cfg_cancel                          (GtkButton       *button,
+                                        gpointer         user_data);
+
+gboolean
+xs_fileinfo_delete                     (GtkWidget       *widget,
+                                        GdkEvent        *event,
+                                        gpointer         user_data);
+
+void
+xs_subctrl_prevsong                    (GtkButton       *button,
+                                        gpointer         user_data);
+
+void
+xs_subctrl_nextsong                    (GtkButton       *button,
+                                        gpointer         user_data);
+
+void
+xs_fileinfo_ok                         (GtkButton       *button,
+                                        gpointer         user_data);
+
+void
+xs_cfg_sldb_fs_ok                      (GtkButton       *button,
+                                        gpointer         user_data);
+
+void
+xs_cfg_sldb_fs_cancel                  (GtkButton       *button,
+                                        gpointer         user_data);
+
+void
+xs_cfg_stil_fs_ok                      (GtkButton       *button,
+                                        gpointer         user_data);
+
+void
+xs_cfg_stil_fs_cancel                  (GtkButton       *button,
+                                        gpointer         user_data);
+
+void
+xs_cfg_hvsc_fs_ok                      (GtkButton       *button,
+                                        gpointer         user_data);
+
+void
+xs_cfg_hvsc_fs_cancel                  (GtkButton       *button,
+                                        gpointer         user_data);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_glade.c	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,162 @@
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+#include "xs_glade.h"
+
+/* This is an internally used function to check if a pixmap file exists. */
+static gchar* check_file_exists        (const gchar     *directory,
+                                        const gchar     *filename);
+
+/* This is an internally used function to create pixmaps. */
+static GtkWidget* create_dummy_pixmap  (GtkWidget       *widget);
+
+GtkWidget*
+lookup_widget                          (GtkWidget       *widget,
+                                        const gchar     *widget_name)
+{
+  GtkWidget *parent, *found_widget;
+
+  for (;;)
+    {
+      if (GTK_IS_MENU (widget))
+        parent = gtk_menu_get_attach_widget (GTK_MENU (widget));
+      else
+        parent = widget->parent;
+      if (parent == NULL)
+        break;
+      widget = parent;
+    }
+
+  found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget),
+                                                   widget_name);
+  if (!found_widget)
+    g_warning ("Widget not found: %s", widget_name);
+  return found_widget;
+}
+
+/* This is a dummy pixmap we use when a pixmap can't be found. */
+static char *dummy_pixmap_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"1 1 1 1",
+"  c None",
+/* pixels */
+" "
+};
+
+/* This is an internally used function to create pixmaps. */
+static GtkWidget*
+create_dummy_pixmap                    (GtkWidget       *widget)
+{
+  GdkColormap *colormap;
+  GdkPixmap *gdkpixmap;
+  GdkBitmap *mask;
+  GtkWidget *pixmap;
+
+  colormap = gtk_widget_get_colormap (widget);
+  gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask,
+                                                     NULL, dummy_pixmap_xpm);
+  if (gdkpixmap == NULL)
+    g_error ("Couldn't create replacement pixmap.");
+  pixmap = gtk_pixmap_new (gdkpixmap, mask);
+  gdk_pixmap_unref (gdkpixmap);
+  gdk_bitmap_unref (mask);
+  return pixmap;
+}
+
+static GList *pixmaps_directories = NULL;
+
+/* Use this function to set the directory containing installed pixmaps. */
+void
+add_pixmap_directory                   (const gchar     *directory)
+{
+  pixmaps_directories = g_list_prepend (pixmaps_directories,
+                                        g_strdup (directory));
+}
+
+/* This is an internally used function to create pixmaps. */
+GtkWidget*
+create_pixmap                          (GtkWidget       *widget,
+                                        const gchar     *filename)
+{
+  gchar *found_filename = NULL;
+  GdkColormap *colormap;
+  GdkPixmap *gdkpixmap;
+  GdkBitmap *mask;
+  GtkWidget *pixmap;
+  GList *elem;
+
+  if (!filename || !filename[0])
+      return create_dummy_pixmap (widget);
+
+  /* We first try any pixmaps directories set by the application. */
+  elem = pixmaps_directories;
+  while (elem)
+    {
+      found_filename = check_file_exists ((gchar*)elem->data, filename);
+      if (found_filename)
+        break;
+      elem = elem->next;
+    }
+
+  /* If we haven't found the pixmap, try the source directory. */
+  if (!found_filename)
+    {
+      found_filename = check_file_exists ("../pixmaps", filename);
+    }
+
+  if (!found_filename)
+    {
+      g_warning ("Couldn't find pixmap file: %s", filename);
+      return create_dummy_pixmap (widget);
+    }
+
+  colormap = gtk_widget_get_colormap (widget);
+  gdkpixmap = gdk_pixmap_colormap_create_from_xpm (NULL, colormap, &mask,
+                                                   NULL, found_filename);
+  if (gdkpixmap == NULL)
+    {
+      g_warning ("Error loading pixmap file: %s", found_filename);
+      g_free (found_filename);
+      return create_dummy_pixmap (widget);
+    }
+  g_free (found_filename);
+  pixmap = gtk_pixmap_new (gdkpixmap, mask);
+  gdk_pixmap_unref (gdkpixmap);
+  gdk_bitmap_unref (mask);
+  return pixmap;
+}
+
+/* This is an internally used function to check if a pixmap file exists. */
+static gchar*
+check_file_exists                      (const gchar     *directory,
+                                        const gchar     *filename)
+{
+  gchar *full_filename;
+  struct stat s;
+  gint status;
+
+  full_filename = (gchar*) g_malloc (strlen (directory) + 1
+                                     + strlen (filename) + 1);
+  strcpy (full_filename, directory);
+  strcat (full_filename, G_DIR_SEPARATOR_S);
+  strcat (full_filename, filename);
+
+  status = stat (full_filename, &s);
+  if (status == 0 && S_ISREG (s.st_mode))
+    return full_filename;
+  g_free (full_filename);
+  return NULL;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_glade.h	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,38 @@
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+
+/*
+ * Public Functions.
+ */
+
+/*
+ * This function returns a widget in a component created by Glade.
+ * Call it with the toplevel widget in the component (i.e. a window/dialog),
+ * or alternatively any widget in the component, and the name of the widget
+ * you want returned.
+ */
+GtkWidget*  lookup_widget              (GtkWidget       *widget,
+                                        const gchar     *widget_name);
+
+/* get_widget() is deprecated. Use lookup_widget instead. */
+#define get_widget lookup_widget
+
+/* Use this function to set the directory containing installed pixmaps. */
+void        add_pixmap_directory       (const gchar     *directory);
+
+
+/*
+ * Private Functions.
+ */
+
+/* This is used to create the pixmaps in the interface. */
+GtkWidget*  create_pixmap              (GtkWidget       *widget,
+                                        const gchar     *filename);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_init.c	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,62 @@
+/*  
+   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
+
+   Plugin initialization point
+   
+   Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org>
+   (C) Copyright 1999-2005 Tecnic Software productions (TNSP)
+
+   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 "xmms-sid.h"
+#include "xs_config.h"
+#include "xs_fileinfo.h"
+
+InputPlugin xs_plugin_ip = {
+	NULL,			/* FILLED BY XMMS */
+	NULL,			/* FILLED BY XMMS */
+	"SID Tune Plugin",	/* Plugin description */
+	xs_init,		/* Initialization */
+	xs_about,		/* Show aboutbox */
+	xs_configure,		/* Show/edit configuration */
+	xs_is_our_file,		/* Check file */
+	NULL,			/* Scan directory */
+	xs_play_file,		/* Play given file */
+	xs_stop,		/* Stop playing */
+	xs_pause,		/* Pause playing */
+	xs_seek,		/* Seek time */
+	NULL,			/* Set equalizer */
+	xs_get_time,		/* Get playing time */
+	NULL,			/* Get volume */
+	NULL,			/* Set volume */
+	xs_close,		/* Cleanup */
+	NULL,			/* OBSOLETE! */
+	NULL,			/* Send data to Visualization plugin */
+	NULL, NULL,		/* FILLED BY XMMS */
+	xs_get_song_info,	/* Get song title and length */
+	xs_fileinfo,		/* Show file-information dialog */
+	NULL			/* FILLED BY XMMS */
+};
+
+
+
+/*
+ * Return plugin information
+ */
+InputPlugin *get_iplugin_info(void)
+{
+	return &xs_plugin_ip;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_interface.c	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,2073 @@
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include "xs_genui.h"
+#include "xs_interface.h"
+#include "xs_glade.h"
+
+GtkWidget*
+create_xs_configwin (void)
+{
+  GtkWidget *xs_configwin;
+  GtkWidget *vbox1;
+  GtkWidget *cfg_notebook;
+  GtkWidget *vbox6;
+  GtkWidget *hbox2;
+  GtkWidget *frame4;
+  GtkWidget *vbox9;
+  GSList *resolution_group = NULL;
+  GtkWidget *cfg_res_8bit;
+  GtkWidget *cfg_res_16bit;
+  GtkWidget *frame5;
+  GtkWidget *vbox10;
+  GSList *channels_group = NULL;
+  GtkWidget *cfg_chn_mono;
+  GtkWidget *cfg_chn_stereo;
+  GtkWidget *cfg_chn_autopan;
+  GtkWidget *frame8;
+  GtkWidget *hbox4;
+  GtkWidget *cfg_samplerate_menu;
+  GtkWidget *cfg_samplerate_menu_menu;
+  GtkWidget *glade_menuitem;
+  GtkWidget *label8;
+  GtkWidget *vseparator1;
+  GtkObject *cfg_samplerate_adj;
+  GtkWidget *cfg_samplerate;
+  GtkWidget *label54;
+  GtkWidget *cfg_oversample_grp;
+  GtkWidget *vbox27;
+  GtkWidget *cfg_oversample;
+  GtkWidget *hbox16;
+  GtkWidget *cfg_oversample_label1;
+  GtkObject *cfg_oversample_factor_adj;
+  GtkWidget *cfg_oversample_factor;
+  GtkWidget *cfg_oversample_label2;
+  GtkWidget *label1;
+  GtkWidget *vbox2;
+  GtkWidget *frame26;
+  GtkWidget *vbox26;
+  GSList *emulator_group = NULL;
+  GtkWidget *cfg_emu_sidplay1;
+  GtkWidget *cfg_emu_sidplay2;
+  GtkWidget *frame1;
+  GtkWidget *vbox5;
+  GSList *memorymode_group = NULL;
+  GtkWidget *cfg_emu_mem_real;
+  GtkWidget *cfg_emu_mem_banksw;
+  GtkWidget *cfg_emu_mem_transrom;
+  GtkWidget *cfg_emu_mem_playsid;
+  GtkWidget *label2;
+  GtkWidget *vbox29;
+  GtkWidget *hbox1;
+  GtkWidget *frame2;
+  GtkWidget *vbox4;
+  GtkWidget *cfg_emu_clock_force;
+  GSList *speed_group = NULL;
+  GtkWidget *cfg_emu_clock_pal;
+  GtkWidget *cfg_emu_clock_ntsc;
+  GtkWidget *frame3;
+  GtkWidget *vbox3;
+  GtkWidget *cfg_emu_sid_force;
+  GSList *waveforms_group = NULL;
+  GtkWidget *cfg_emu_mos6581;
+  GtkWidget *cfg_emu_mos8580;
+  GtkWidget *cfg_sidplay2_grp;
+  GtkWidget *vbox30;
+  GtkWidget *cfg_emu_sidplay2_opt;
+  GSList *emutype_group = NULL;
+  GtkWidget *cfg_emu_sidplay2_resid;
+  GtkWidget *cfg_emu_sidplay2_hardsid;
+  GtkWidget *label48;
+  GtkWidget *vbox25;
+  GtkWidget *cfg_emu_filters;
+  GtkWidget *cfg_filters_notebook;
+  GtkWidget *cfg_box_sidplay1;
+  GtkWidget *cfg_frm_fs;
+  GtkWidget *cfg_emu_filt_fs;
+  GtkWidget *cfg_frm_fm;
+  GtkWidget *cfg_emu_filt_fm;
+  GtkWidget *cfg_frm_ft;
+  GtkWidget *cfg_emu_filt_ft;
+  GtkWidget *vbox17;
+  GtkWidget *cfg_filter_reset;
+  GtkWidget *cfg_filter_sync;
+  GtkWidget *label55;
+  GtkWidget *cfg_box_sidplay2;
+  GtkWidget *vbox36;
+  GtkWidget *cfg_filter2_reset;
+  GtkWidget *cfg_filter2_sync;
+  GtkWidget *label56;
+  GtkWidget *label24;
+  GtkWidget *vbox20;
+  GtkWidget *frame29;
+  GtkWidget *vbox32;
+  GtkWidget *cfg_mintime_enable;
+  GtkWidget *hbox18;
+  GtkWidget *cfg_mintime_label1;
+  GtkObject *cfg_mintime_adj;
+  GtkWidget *cfg_mintime;
+  GtkWidget *cfg_mintime_label2;
+  GtkWidget *frame21;
+  GtkWidget *vbox21;
+  GtkWidget *cfg_maxtime_enable;
+  GtkWidget *cfg_maxtime_unknown;
+  GtkWidget *hbox14;
+  GtkWidget *cfg_maxtime_label1;
+  GtkObject *cfg_maxtime_adj;
+  GtkWidget *cfg_maxtime;
+  GtkWidget *cfg_maxtime_label2;
+  GtkWidget *frame18;
+  GtkWidget *vbox18;
+  GtkWidget *cfg_sld_enable;
+  GtkWidget *hbox13;
+  GtkWidget *cfg_sld_label1;
+  GtkWidget *cfg_sld_dbpath;
+  GtkWidget *cfg_sld_dbbrowse;
+  GtkWidget *label26;
+  GtkWidget *vbox33;
+  GtkWidget *frame7;
+  GtkWidget *vbox8;
+  GtkWidget *cfg_stil_enable;
+  GtkWidget *hbox3;
+  GtkWidget *cfg_stil_label1;
+  GtkWidget *alignment2;
+  GtkWidget *cfg_stil_dbpath;
+  GtkWidget *alignment1;
+  GtkWidget *cfg_stil_browse;
+  GtkWidget *hbox17;
+  GtkWidget *cfg_hvsc_label1;
+  GtkWidget *alignment6;
+  GtkWidget *cfg_hvsc_path;
+  GtkWidget *alignment7;
+  GtkWidget *cfg_hvsc_browse;
+  GtkWidget *frame16;
+  GtkWidget *vbox16;
+  GtkWidget *cfg_ftitle_override;
+  GtkWidget *cfg_ftitle_format;
+  GtkWidget *hbox9;
+  GtkWidget *cfg_ftitle_desc1;
+  GtkWidget *cfg_ftitle_desc2;
+  GtkWidget *label23;
+  GtkWidget *vbox19;
+  GtkWidget *frame28;
+  GtkWidget *vbox31;
+  GSList *subtune_group = NULL;
+  GtkWidget *cfg_subctrl_none;
+  GtkWidget *cfg_subctrl_seek;
+  GtkWidget *cfg_subctrl_popup;
+  GtkWidget *cfg_subctrl_patch;
+  GtkWidget *frame31;
+  GtkWidget *vbox35;
+  GtkWidget *cfg_subauto_enable;
+  GtkWidget *cfg_subauto_min_only;
+  GtkWidget *hbox20;
+  GtkWidget *label52;
+  GtkObject *cfg_subauto_mintime_adj;
+  GtkWidget *cfg_subauto_mintime;
+  GtkWidget *label53;
+  GtkWidget *frame22;
+  GtkWidget *vbox22;
+  GtkWidget *cfg_detectmagic;
+  GtkWidget *label3;
+  GtkWidget *hbuttonbox1;
+  GtkWidget *cfg_ok;
+  GtkWidget *cfg_cancel;
+  GtkTooltips *tooltips;
+
+  tooltips = gtk_tooltips_new ();
+
+  xs_configwin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_type_hint (GTK_WINDOW(xs_configwin), GDK_WINDOW_TYPE_HINT_DIALOG);
+  gtk_widget_set_name (xs_configwin, "xs_configwin");
+  gtk_object_set_data (GTK_OBJECT (xs_configwin), "xs_configwin", xs_configwin);
+  gtk_window_set_title (GTK_WINDOW (xs_configwin), "XMMS-SID configuration");
+  gtk_window_set_policy (GTK_WINDOW (xs_configwin), FALSE, FALSE, FALSE);
+
+  vbox1 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_set_name (vbox1, "vbox1");
+  gtk_widget_ref (vbox1);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox1", vbox1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox1);
+  gtk_container_add (GTK_CONTAINER (xs_configwin), vbox1);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox1), 8);
+
+  cfg_notebook = gtk_notebook_new ();
+  gtk_widget_set_name (cfg_notebook, "cfg_notebook");
+  gtk_widget_ref (cfg_notebook);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_notebook", cfg_notebook,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_notebook);
+  gtk_box_pack_start (GTK_BOX (vbox1), cfg_notebook, TRUE, TRUE, 0);
+  gtk_notebook_set_show_border (GTK_NOTEBOOK (cfg_notebook), FALSE);
+
+  vbox6 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_set_name (vbox6, "vbox6");
+  gtk_widget_ref (vbox6);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox6", vbox6,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox6);
+  gtk_container_add (GTK_CONTAINER (cfg_notebook), vbox6);
+
+  hbox2 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_set_name (hbox2, "hbox2");
+  gtk_widget_ref (hbox2);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "hbox2", hbox2,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (hbox2);
+  gtk_box_pack_start (GTK_BOX (vbox6), hbox2, FALSE, TRUE, 0);
+
+  frame4 = gtk_frame_new ("Resolution:");
+  gtk_widget_set_name (frame4, "frame4");
+  gtk_widget_ref (frame4);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "frame4", frame4,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (frame4);
+  gtk_box_pack_start (GTK_BOX (hbox2), frame4, TRUE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (frame4), 4);
+
+  vbox9 = gtk_vbox_new (FALSE, 2);
+  gtk_widget_set_name (vbox9, "vbox9");
+  gtk_widget_ref (vbox9);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox9", vbox9,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox9);
+  gtk_container_add (GTK_CONTAINER (frame4), vbox9);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox9), 2);
+
+  cfg_res_8bit = gtk_radio_button_new_with_label (resolution_group, "8-bit");
+  resolution_group = gtk_radio_button_group (GTK_RADIO_BUTTON (cfg_res_8bit));
+  gtk_widget_set_name (cfg_res_8bit, "cfg_res_8bit");
+  gtk_widget_ref (cfg_res_8bit);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_res_8bit", cfg_res_8bit,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_res_8bit);
+  gtk_box_pack_start (GTK_BOX (vbox9), cfg_res_8bit, FALSE, FALSE, 0);
+
+  cfg_res_16bit = gtk_radio_button_new_with_label (resolution_group, "16-bit");
+  resolution_group = gtk_radio_button_group (GTK_RADIO_BUTTON (cfg_res_16bit));
+  gtk_widget_set_name (cfg_res_16bit, "cfg_res_16bit");
+  gtk_widget_ref (cfg_res_16bit);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_res_16bit", cfg_res_16bit,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_res_16bit);
+  gtk_box_pack_start (GTK_BOX (vbox9), cfg_res_16bit, FALSE, FALSE, 0);
+
+  frame5 = gtk_frame_new ("Channels:");
+  gtk_widget_set_name (frame5, "frame5");
+  gtk_widget_ref (frame5);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "frame5", frame5,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (frame5);
+  gtk_box_pack_start (GTK_BOX (hbox2), frame5, TRUE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (frame5), 4);
+
+  vbox10 = gtk_vbox_new (FALSE, 2);
+  gtk_widget_set_name (vbox10, "vbox10");
+  gtk_widget_ref (vbox10);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox10", vbox10,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox10);
+  gtk_container_add (GTK_CONTAINER (frame5), vbox10);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox10), 2);
+
+  cfg_chn_mono = gtk_radio_button_new_with_label (channels_group, "Mono");
+  channels_group = gtk_radio_button_group (GTK_RADIO_BUTTON (cfg_chn_mono));
+  gtk_widget_set_name (cfg_chn_mono, "cfg_chn_mono");
+  gtk_widget_ref (cfg_chn_mono);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_chn_mono", cfg_chn_mono,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_chn_mono);
+  gtk_box_pack_start (GTK_BOX (vbox10), cfg_chn_mono, FALSE, FALSE, 0);
+
+  cfg_chn_stereo = gtk_radio_button_new_with_label (channels_group, "Stereo");
+  channels_group = gtk_radio_button_group (GTK_RADIO_BUTTON (cfg_chn_stereo));
+  gtk_widget_set_name (cfg_chn_stereo, "cfg_chn_stereo");
+  gtk_widget_ref (cfg_chn_stereo);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_chn_stereo", cfg_chn_stereo,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_chn_stereo);
+  gtk_box_pack_start (GTK_BOX (vbox10), cfg_chn_stereo, FALSE, FALSE, 0);
+
+  cfg_chn_autopan = gtk_radio_button_new_with_label (channels_group, "Autopanning");
+  channels_group = gtk_radio_button_group (GTK_RADIO_BUTTON (cfg_chn_autopan));
+  gtk_widget_set_name (cfg_chn_autopan, "cfg_chn_autopan");
+  gtk_widget_ref (cfg_chn_autopan);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_chn_autopan", cfg_chn_autopan,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_chn_autopan);
+  gtk_box_pack_start (GTK_BOX (vbox10), cfg_chn_autopan, FALSE, FALSE, 0);
+
+  frame8 = gtk_frame_new ("Samplerate:");
+  gtk_widget_set_name (frame8, "frame8");
+  gtk_widget_ref (frame8);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "frame8", frame8,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (frame8);
+  gtk_box_pack_start (GTK_BOX (vbox6), frame8, FALSE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (frame8), 4);
+
+  hbox4 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_set_name (hbox4, "hbox4");
+  gtk_widget_ref (hbox4);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "hbox4", hbox4,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (hbox4);
+  gtk_container_add (GTK_CONTAINER (frame8), hbox4);
+  gtk_container_set_border_width (GTK_CONTAINER (hbox4), 4);
+
+  cfg_samplerate_menu = gtk_option_menu_new ();
+  gtk_widget_set_name (cfg_samplerate_menu, "cfg_samplerate_menu");
+  gtk_widget_ref (cfg_samplerate_menu);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_samplerate_menu", cfg_samplerate_menu,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_samplerate_menu);
+  gtk_box_pack_start (GTK_BOX (hbox4), cfg_samplerate_menu, FALSE, FALSE, 0);
+  cfg_samplerate_menu_menu = gtk_menu_new ();
+  glade_menuitem = gtk_menu_item_new_with_label ("8000");
+  gtk_widget_show (glade_menuitem);
+  gtk_menu_append (GTK_MENU (cfg_samplerate_menu_menu), glade_menuitem);
+  glade_menuitem = gtk_menu_item_new_with_label ("11025");
+  gtk_widget_show (glade_menuitem);
+  gtk_menu_append (GTK_MENU (cfg_samplerate_menu_menu), glade_menuitem);
+  glade_menuitem = gtk_menu_item_new_with_label ("22050");
+  gtk_widget_show (glade_menuitem);
+  gtk_menu_append (GTK_MENU (cfg_samplerate_menu_menu), glade_menuitem);
+  glade_menuitem = gtk_menu_item_new_with_label ("44100");
+  gtk_widget_show (glade_menuitem);
+  gtk_menu_append (GTK_MENU (cfg_samplerate_menu_menu), glade_menuitem);
+  glade_menuitem = gtk_menu_item_new_with_label ("48000");
+  gtk_widget_show (glade_menuitem);
+  gtk_menu_append (GTK_MENU (cfg_samplerate_menu_menu), glade_menuitem);
+  glade_menuitem = gtk_menu_item_new_with_label ("64000");
+  gtk_widget_show (glade_menuitem);
+  gtk_menu_append (GTK_MENU (cfg_samplerate_menu_menu), glade_menuitem);
+  glade_menuitem = gtk_menu_item_new_with_label ("96000");
+  gtk_widget_show (glade_menuitem);
+  gtk_menu_append (GTK_MENU (cfg_samplerate_menu_menu), glade_menuitem);
+  gtk_option_menu_set_menu (GTK_OPTION_MENU (cfg_samplerate_menu), cfg_samplerate_menu_menu);
+  gtk_option_menu_set_history (GTK_OPTION_MENU (cfg_samplerate_menu), 3);
+
+  label8 = gtk_label_new ("Hz");
+  gtk_widget_set_name (label8, "label8");
+  gtk_widget_ref (label8);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "label8", label8,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label8);
+  gtk_box_pack_start (GTK_BOX (hbox4), label8, FALSE, TRUE, 4);
+
+  vseparator1 = gtk_vseparator_new ();
+  gtk_widget_set_name (vseparator1, "vseparator1");
+  gtk_widget_ref (vseparator1);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vseparator1", vseparator1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vseparator1);
+  gtk_box_pack_start (GTK_BOX (hbox4), vseparator1, TRUE, TRUE, 0);
+
+  cfg_samplerate_adj = gtk_adjustment_new (44100, 8000, 128000, 1, 10, 10);
+  cfg_samplerate = gtk_spin_button_new (GTK_ADJUSTMENT (cfg_samplerate_adj), 8000, 0);
+  gtk_widget_set_name (cfg_samplerate, "cfg_samplerate");
+  gtk_widget_ref (cfg_samplerate);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_samplerate", cfg_samplerate,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_samplerate);
+  gtk_box_pack_start (GTK_BOX (hbox4), cfg_samplerate, TRUE, TRUE, 0);
+  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (cfg_samplerate), TRUE);
+
+  label54 = gtk_label_new ("Hz");
+  gtk_widget_set_name (label54, "label54");
+  gtk_widget_ref (label54);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "label54", label54,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label54);
+  gtk_box_pack_start (GTK_BOX (hbox4), label54, FALSE, TRUE, 0);
+
+  cfg_oversample_grp = gtk_frame_new ("Oversampling:");
+  gtk_widget_set_name (cfg_oversample_grp, "cfg_oversample_grp");
+  gtk_widget_ref (cfg_oversample_grp);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_oversample_grp", cfg_oversample_grp,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_oversample_grp);
+  gtk_box_pack_start (GTK_BOX (vbox6), cfg_oversample_grp, FALSE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (cfg_oversample_grp), 4);
+
+  vbox27 = gtk_vbox_new (FALSE, 2);
+  gtk_widget_set_name (vbox27, "vbox27");
+  gtk_widget_ref (vbox27);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox27", vbox27,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox27);
+  gtk_container_add (GTK_CONTAINER (cfg_oversample_grp), vbox27);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox27), 2);
+
+  cfg_oversample = gtk_check_button_new_with_label ("Use oversampling");
+  gtk_widget_set_name (cfg_oversample, "cfg_oversample");
+  gtk_widget_ref (cfg_oversample);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_oversample", cfg_oversample,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_oversample);
+  gtk_box_pack_start (GTK_BOX (vbox27), cfg_oversample, FALSE, FALSE, 0);
+
+  hbox16 = gtk_hbox_new (FALSE, 4);
+  gtk_widget_set_name (hbox16, "hbox16");
+  gtk_widget_ref (hbox16);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "hbox16", hbox16,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (hbox16);
+  gtk_box_pack_start (GTK_BOX (vbox27), hbox16, FALSE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (hbox16), 2);
+
+  cfg_oversample_label1 = gtk_label_new ("Factor:");
+  gtk_widget_set_name (cfg_oversample_label1, "cfg_oversample_label1");
+  gtk_widget_ref (cfg_oversample_label1);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_oversample_label1", cfg_oversample_label1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_oversample_label1);
+  gtk_box_pack_start (GTK_BOX (hbox16), cfg_oversample_label1, FALSE, FALSE, 0);
+
+  cfg_oversample_factor_adj = gtk_adjustment_new (2, 2, 8, 1, 1, 1);
+  cfg_oversample_factor = gtk_spin_button_new (GTK_ADJUSTMENT (cfg_oversample_factor_adj), 1, 0);
+  gtk_widget_set_name (cfg_oversample_factor, "cfg_oversample_factor");
+  gtk_widget_ref (cfg_oversample_factor);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_oversample_factor", cfg_oversample_factor,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_oversample_factor);
+  gtk_box_pack_start (GTK_BOX (hbox16), cfg_oversample_factor, FALSE, TRUE, 0);
+
+  cfg_oversample_label2 = gtk_label_new ("Large factors require more CPU-power");
+  gtk_widget_set_name (cfg_oversample_label2, "cfg_oversample_label2");
+  gtk_widget_ref (cfg_oversample_label2);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_oversample_label2", cfg_oversample_label2,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_oversample_label2);
+  gtk_box_pack_start (GTK_BOX (hbox16), cfg_oversample_label2, FALSE, FALSE, 0);
+
+  label1 = gtk_label_new ("Audio");
+  gtk_widget_set_name (label1, "label1");
+  gtk_widget_ref (label1);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "label1", label1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label1);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (cfg_notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (cfg_notebook), 0), label1);
+
+  vbox2 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_set_name (vbox2, "vbox2");
+  gtk_widget_ref (vbox2);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox2", vbox2,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox2);
+  gtk_container_add (GTK_CONTAINER (cfg_notebook), vbox2);
+
+  frame26 = gtk_frame_new ("Emulation library selection: ");
+  gtk_widget_set_name (frame26, "frame26");
+  gtk_widget_ref (frame26);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "frame26", frame26,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (frame26);
+  gtk_box_pack_start (GTK_BOX (vbox2), frame26, FALSE, FALSE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (frame26), 4);
+
+  vbox26 = gtk_vbox_new (FALSE, 2);
+  gtk_widget_set_name (vbox26, "vbox26");
+  gtk_widget_ref (vbox26);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox26", vbox26,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox26);
+  gtk_container_add (GTK_CONTAINER (frame26), vbox26);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox26), 2);
+
+  cfg_emu_sidplay1 = gtk_radio_button_new_with_label (emulator_group, "SIDPlay 1 (frame-based)");
+  emulator_group = gtk_radio_button_group (GTK_RADIO_BUTTON (cfg_emu_sidplay1));
+  gtk_widget_set_name (cfg_emu_sidplay1, "cfg_emu_sidplay1");
+  gtk_widget_ref (cfg_emu_sidplay1);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_emu_sidplay1", cfg_emu_sidplay1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_emu_sidplay1);
+  gtk_box_pack_start (GTK_BOX (vbox26), cfg_emu_sidplay1, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_emu_sidplay1, "Use libSIDPlay 1.x emulation, faster but not so accurate. Good in most cases, though.", NULL);
+
+  cfg_emu_sidplay2 = gtk_radio_button_new_with_label (emulator_group, "SIDPlay 2 (cycle-based)");
+  emulator_group = gtk_radio_button_group (GTK_RADIO_BUTTON (cfg_emu_sidplay2));
+  gtk_widget_set_name (cfg_emu_sidplay2, "cfg_emu_sidplay2");
+  gtk_widget_ref (cfg_emu_sidplay2);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_emu_sidplay2", cfg_emu_sidplay2,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_emu_sidplay2);
+  gtk_box_pack_start (GTK_BOX (vbox26), cfg_emu_sidplay2, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_emu_sidplay2, "Use libSIDPlay 2.x emulation, which requires powerful CPU due to more exact emulation.", NULL);
+
+  frame1 = gtk_frame_new ("Memory mode:");
+  gtk_widget_set_name (frame1, "frame1");
+  gtk_widget_ref (frame1);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "frame1", frame1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (frame1);
+  gtk_box_pack_start (GTK_BOX (vbox2), frame1, FALSE, FALSE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (frame1), 4);
+
+  vbox5 = gtk_vbox_new (FALSE, 2);
+  gtk_widget_set_name (vbox5, "vbox5");
+  gtk_widget_ref (vbox5);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox5", vbox5,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox5);
+  gtk_container_add (GTK_CONTAINER (frame1), vbox5);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox5), 2);
+
+  cfg_emu_mem_real = gtk_radio_button_new_with_label (memorymode_group, "Real C64 (SIDPlay 2 only)");
+  memorymode_group = gtk_radio_button_group (GTK_RADIO_BUTTON (cfg_emu_mem_real));
+  gtk_widget_set_name (cfg_emu_mem_real, "cfg_emu_mem_real");
+  gtk_widget_ref (cfg_emu_mem_real);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_emu_mem_real", cfg_emu_mem_real,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_emu_mem_real);
+  gtk_box_pack_start (GTK_BOX (vbox5), cfg_emu_mem_real, FALSE, FALSE, 0);
+
+  cfg_emu_mem_banksw = gtk_radio_button_new_with_label (memorymode_group, "Bank switching");
+  memorymode_group = gtk_radio_button_group (GTK_RADIO_BUTTON (cfg_emu_mem_banksw));
+  gtk_widget_set_name (cfg_emu_mem_banksw, "cfg_emu_mem_banksw");
+  gtk_widget_ref (cfg_emu_mem_banksw);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_emu_mem_banksw", cfg_emu_mem_banksw,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_emu_mem_banksw);
+  gtk_box_pack_start (GTK_BOX (vbox5), cfg_emu_mem_banksw, FALSE, FALSE, 0);
+
+  cfg_emu_mem_transrom = gtk_radio_button_new_with_label (memorymode_group, "Transparent ROM");
+  memorymode_group = gtk_radio_button_group (GTK_RADIO_BUTTON (cfg_emu_mem_transrom));
+  gtk_widget_set_name (cfg_emu_mem_transrom, "cfg_emu_mem_transrom");
+  gtk_widget_ref (cfg_emu_mem_transrom);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_emu_mem_transrom", cfg_emu_mem_transrom,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_emu_mem_transrom);
+  gtk_box_pack_start (GTK_BOX (vbox5), cfg_emu_mem_transrom, FALSE, FALSE, 0);
+
+  cfg_emu_mem_playsid = gtk_radio_button_new_with_label (memorymode_group, "PlaySID environment");
+  memorymode_group = gtk_radio_button_group (GTK_RADIO_BUTTON (cfg_emu_mem_playsid));
+  gtk_widget_set_name (cfg_emu_mem_playsid, "cfg_emu_mem_playsid");
+  gtk_widget_ref (cfg_emu_mem_playsid);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_emu_mem_playsid", cfg_emu_mem_playsid,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_emu_mem_playsid);
+  gtk_box_pack_start (GTK_BOX (vbox5), cfg_emu_mem_playsid, FALSE, FALSE, 0);
+
+  label2 = gtk_label_new ("Emu#1");
+  gtk_widget_set_name (label2, "label2");
+  gtk_widget_ref (label2);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "label2", label2,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label2);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (cfg_notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (cfg_notebook), 1), label2);
+
+  vbox29 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_set_name (vbox29, "vbox29");
+  gtk_widget_ref (vbox29);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox29", vbox29,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox29);
+  gtk_container_add (GTK_CONTAINER (cfg_notebook), vbox29);
+
+  hbox1 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_set_name (hbox1, "hbox1");
+  gtk_widget_ref (hbox1);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "hbox1", hbox1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (hbox1);
+  gtk_box_pack_start (GTK_BOX (vbox29), hbox1, FALSE, TRUE, 0);
+
+  frame2 = gtk_frame_new ("Clock speed:");
+  gtk_widget_set_name (frame2, "frame2");
+  gtk_widget_ref (frame2);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "frame2", frame2,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (frame2);
+  gtk_box_pack_start (GTK_BOX (hbox1), frame2, TRUE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (frame2), 4);
+
+  vbox4 = gtk_vbox_new (FALSE, 2);
+  gtk_widget_set_name (vbox4, "vbox4");
+  gtk_widget_ref (vbox4);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox4", vbox4,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox4);
+  gtk_container_add (GTK_CONTAINER (frame2), vbox4);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox4), 2);
+
+  cfg_emu_clock_force = gtk_check_button_new_with_label ("Force speed");
+  gtk_widget_set_name (cfg_emu_clock_force, "cfg_emu_clock_force");
+  gtk_widget_ref (cfg_emu_clock_force);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_emu_clock_force", cfg_emu_clock_force,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_emu_clock_force);
+  gtk_box_pack_start (GTK_BOX (vbox4), cfg_emu_clock_force, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_emu_clock_force, "If enabled, this option \"forces\" the emulation engine to use the selected clock speed/frequency. Otherwise the speed is determined from played file itself.", NULL);
+
+  cfg_emu_clock_pal = gtk_radio_button_new_with_label (speed_group, "PAL (50 Hz)");
+  speed_group = gtk_radio_button_group (GTK_RADIO_BUTTON (cfg_emu_clock_pal));
+  gtk_widget_set_name (cfg_emu_clock_pal, "cfg_emu_clock_pal");
+  gtk_widget_ref (cfg_emu_clock_pal);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_emu_clock_pal", cfg_emu_clock_pal,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_emu_clock_pal);
+  gtk_box_pack_start (GTK_BOX (vbox4), cfg_emu_clock_pal, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_emu_clock_pal, "PAL is the european TV standard, which uses 50Hz vertical refresh frequency. Largest % of SID-tunes have been made for PAL computers.", NULL);
+
+  cfg_emu_clock_ntsc = gtk_radio_button_new_with_label (speed_group, "NTSC (60 Hz)");
+  speed_group = gtk_radio_button_group (GTK_RADIO_BUTTON (cfg_emu_clock_ntsc));
+  gtk_widget_set_name (cfg_emu_clock_ntsc, "cfg_emu_clock_ntsc");
+  gtk_widget_ref (cfg_emu_clock_ntsc);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_emu_clock_ntsc", cfg_emu_clock_ntsc,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_emu_clock_ntsc);
+  gtk_box_pack_start (GTK_BOX (vbox4), cfg_emu_clock_ntsc, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_emu_clock_ntsc, "NTSC is the TV standard with 60Hz vertical refresh rate (and other features that differ from PAL). It is mainly used in United States, Japan and certain other countries.", NULL);
+
+  frame3 = gtk_frame_new ("SID model: ");
+  gtk_widget_set_name (frame3, "frame3");
+  gtk_widget_ref (frame3);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "frame3", frame3,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (frame3);
+  gtk_box_pack_start (GTK_BOX (hbox1), frame3, TRUE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (frame3), 4);
+
+  vbox3 = gtk_vbox_new (FALSE, 2);
+  gtk_widget_set_name (vbox3, "vbox3");
+  gtk_widget_ref (vbox3);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox3", vbox3,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox3);
+  gtk_container_add (GTK_CONTAINER (frame3), vbox3);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox3), 2);
+
+  cfg_emu_sid_force = gtk_check_button_new_with_label ("Force model");
+  gtk_widget_set_name (cfg_emu_sid_force, "cfg_emu_sid_force");
+  gtk_widget_ref (cfg_emu_sid_force);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_emu_sid_force", cfg_emu_sid_force,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_emu_sid_force);
+  gtk_box_pack_start (GTK_BOX (vbox3), cfg_emu_sid_force, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_emu_sid_force, "If enabled, this option \"forces\" the emulation engine to use the selected SID-chip model. Otherwise the preferred SID model is determined from the file (if PSIDv2NG type) or if not available, this setting is used.", NULL);
+
+  cfg_emu_mos6581 = gtk_radio_button_new_with_label (waveforms_group, "MOS 6581");
+  waveforms_group = gtk_radio_button_group (GTK_RADIO_BUTTON (cfg_emu_mos6581));
+  gtk_widget_set_name (cfg_emu_mos6581, "cfg_emu_mos6581");
+  gtk_widget_ref (cfg_emu_mos6581);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_emu_mos6581", cfg_emu_mos6581,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_emu_mos6581);
+  gtk_box_pack_start (GTK_BOX (vbox3), cfg_emu_mos6581, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_emu_mos6581, "MOS/CSG 6581 is the earlier major version of SID chip. It differs from 8580 in few ways, having much fuller filter (which, due to design error, is never same between two different SID-chips) and has the \"volume adjustment bug\", which enables playing of digital samples.", NULL);
+
+  cfg_emu_mos8580 = gtk_radio_button_new_with_label (waveforms_group, "MOS 8580");
+  waveforms_group = gtk_radio_button_group (GTK_RADIO_BUTTON (cfg_emu_mos8580));
+  gtk_widget_set_name (cfg_emu_mos8580, "cfg_emu_mos8580");
+  gtk_widget_ref (cfg_emu_mos8580);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_emu_mos8580", cfg_emu_mos8580,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_emu_mos8580);
+  gtk_box_pack_start (GTK_BOX (vbox3), cfg_emu_mos8580, FALSE, FALSE, 0);
+
+  cfg_sidplay2_grp = gtk_frame_new ("SIDPlay 2 options: ");
+  gtk_widget_set_name (cfg_sidplay2_grp, "cfg_sidplay2_grp");
+  gtk_widget_ref (cfg_sidplay2_grp);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_sidplay2_grp", cfg_sidplay2_grp,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_sidplay2_grp);
+  gtk_box_pack_start (GTK_BOX (vbox29), cfg_sidplay2_grp, FALSE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (cfg_sidplay2_grp), 4);
+
+  vbox30 = gtk_vbox_new (FALSE, 2);
+  gtk_widget_set_name (vbox30, "vbox30");
+  gtk_widget_ref (vbox30);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox30", vbox30,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox30);
+  gtk_container_add (GTK_CONTAINER (cfg_sidplay2_grp), vbox30);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox30), 2);
+
+  cfg_emu_sidplay2_opt = gtk_check_button_new_with_label ("Optimization mode (faster, inaccurate)");
+  gtk_widget_set_name (cfg_emu_sidplay2_opt, "cfg_emu_sidplay2_opt");
+  gtk_widget_ref (cfg_emu_sidplay2_opt);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_emu_sidplay2_opt", cfg_emu_sidplay2_opt,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_emu_sidplay2_opt);
+  gtk_box_pack_start (GTK_BOX (vbox30), cfg_emu_sidplay2_opt, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_emu_sidplay2_opt, "This setting can be used to enable libSIDPlay2's \"optimization mode\", which in downgrades the emulation from cycle-exact to something similar to frame-exact. The result is lower CPU usage, but worse accuracy.", NULL);
+
+  cfg_emu_sidplay2_resid = gtk_radio_button_new_with_label (emutype_group, "reSID-emulation");
+  emutype_group = gtk_radio_button_group (GTK_RADIO_BUTTON (cfg_emu_sidplay2_resid));
+  gtk_widget_set_name (cfg_emu_sidplay2_resid, "cfg_emu_sidplay2_resid");
+  gtk_widget_ref (cfg_emu_sidplay2_resid);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_emu_sidplay2_resid", cfg_emu_sidplay2_resid,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_emu_sidplay2_resid);
+  gtk_box_pack_start (GTK_BOX (vbox30), cfg_emu_sidplay2_resid, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_emu_sidplay2_resid, "reSID is the software SID-chip simulator based on SID reverse-engineering, created by Dag Lem. It is probably the closest thing to real SID available as software-only emulation.", NULL);
+
+  cfg_emu_sidplay2_hardsid = gtk_radio_button_new_with_label (emutype_group, "HardSID");
+  emutype_group = gtk_radio_button_group (GTK_RADIO_BUTTON (cfg_emu_sidplay2_hardsid));
+  gtk_widget_set_name (cfg_emu_sidplay2_hardsid, "cfg_emu_sidplay2_hardsid");
+  gtk_widget_ref (cfg_emu_sidplay2_hardsid);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_emu_sidplay2_hardsid", cfg_emu_sidplay2_hardsid,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_emu_sidplay2_hardsid);
+  gtk_box_pack_start (GTK_BOX (vbox30), cfg_emu_sidplay2_hardsid, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_emu_sidplay2_hardsid, "HardSID is a EISA/PCI card for PC-compatibles, which can be fitted with a real SID-chip. Software can be used to control the HardSID and combined with software emulation of rest of C64 via libSIDPlay2 HardSID can be used to achieve \"near 100%\" similarity to real C64. For more information, see http://www.hardsid.com/", NULL);
+
+  label48 = gtk_label_new ("Emu#2");
+  gtk_widget_set_name (label48, "label48");
+  gtk_widget_ref (label48);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "label48", label48,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label48);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (cfg_notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (cfg_notebook), 2), label48);
+
+  vbox25 = gtk_vbox_new (FALSE, 2);
+  gtk_widget_set_name (vbox25, "vbox25");
+  gtk_widget_ref (vbox25);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox25", vbox25,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox25);
+  gtk_container_add (GTK_CONTAINER (cfg_notebook), vbox25);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox25), 4);
+
+  cfg_emu_filters = gtk_check_button_new_with_label ("Emulate filters");
+  gtk_widget_set_name (cfg_emu_filters, "cfg_emu_filters");
+  gtk_widget_ref (cfg_emu_filters);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_emu_filters", cfg_emu_filters,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_emu_filters);
+  gtk_box_pack_start (GTK_BOX (vbox25), cfg_emu_filters, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_emu_filters, "This option enables emulation of SID filter. The filter is an essential part of SID's sound capacity, but accurate emulation of it may require quite much CPU power. However, if filter emulation is disabled, tunes won't sound authentic at all if they utilize the filter.", NULL);
+
+  cfg_filters_notebook = gtk_notebook_new ();
+  gtk_widget_set_name (cfg_filters_notebook, "cfg_filters_notebook");
+  gtk_widget_ref (cfg_filters_notebook);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_filters_notebook", cfg_filters_notebook,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_filters_notebook);
+  gtk_box_pack_start (GTK_BOX (vbox25), cfg_filters_notebook, TRUE, TRUE, 0);
+
+  cfg_box_sidplay1 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_set_name (cfg_box_sidplay1, "cfg_box_sidplay1");
+  gtk_widget_ref (cfg_box_sidplay1);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_box_sidplay1", cfg_box_sidplay1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_box_sidplay1);
+  gtk_container_add (GTK_CONTAINER (cfg_filters_notebook), cfg_box_sidplay1);
+  gtk_container_set_border_width (GTK_CONTAINER (cfg_box_sidplay1), 4);
+
+  cfg_frm_fs = gtk_frame_new ("FS");
+  gtk_widget_set_name (cfg_frm_fs, "cfg_frm_fs");
+  gtk_widget_ref (cfg_frm_fs);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_frm_fs", cfg_frm_fs,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_frm_fs);
+  gtk_box_pack_start (GTK_BOX (cfg_box_sidplay1), cfg_frm_fs, FALSE, TRUE, 0);
+  gtk_widget_set_usize (cfg_frm_fs, 45, -2);
+  gtk_container_set_border_width (GTK_CONTAINER (cfg_frm_fs), 2);
+
+  cfg_emu_filt_fs = gtk_vscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 1000, 1, 100, 0)));
+  gtk_widget_set_name (cfg_emu_filt_fs, "cfg_emu_filt_fs");
+  gtk_widget_ref (cfg_emu_filt_fs);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_emu_filt_fs", cfg_emu_filt_fs,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_emu_filt_fs);
+  gtk_container_add (GTK_CONTAINER (cfg_frm_fs), cfg_emu_filt_fs);
+  gtk_scale_set_digits (GTK_SCALE (cfg_emu_filt_fs), 2);
+
+  cfg_frm_fm = gtk_frame_new ("FM");
+  gtk_widget_set_name (cfg_frm_fm, "cfg_frm_fm");
+  gtk_widget_ref (cfg_frm_fm);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_frm_fm", cfg_frm_fm,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_frm_fm);
+  gtk_box_pack_start (GTK_BOX (cfg_box_sidplay1), cfg_frm_fm, FALSE, TRUE, 0);
+  gtk_widget_set_usize (cfg_frm_fm, 45, -2);
+  gtk_container_set_border_width (GTK_CONTAINER (cfg_frm_fm), 2);
+
+  cfg_emu_filt_fm = gtk_vscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 100, 1, 10, 0)));
+  gtk_widget_set_name (cfg_emu_filt_fm, "cfg_emu_filt_fm");
+  gtk_widget_ref (cfg_emu_filt_fm);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_emu_filt_fm", cfg_emu_filt_fm,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_emu_filt_fm);
+  gtk_container_add (GTK_CONTAINER (cfg_frm_fm), cfg_emu_filt_fm);
+  gtk_scale_set_digits (GTK_SCALE (cfg_emu_filt_fm), 2);
+
+  cfg_frm_ft = gtk_frame_new ("FT");
+  gtk_widget_set_name (cfg_frm_ft, "cfg_frm_ft");
+  gtk_widget_ref (cfg_frm_ft);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_frm_ft", cfg_frm_ft,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_frm_ft);
+  gtk_box_pack_start (GTK_BOX (cfg_box_sidplay1), cfg_frm_ft, FALSE, TRUE, 0);
+  gtk_widget_set_usize (cfg_frm_ft, 45, -2);
+  gtk_container_set_border_width (GTK_CONTAINER (cfg_frm_ft), 2);
+
+  cfg_emu_filt_ft = gtk_vscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 1, 0.01, 0.1, 0)));
+  gtk_widget_set_name (cfg_emu_filt_ft, "cfg_emu_filt_ft");
+  gtk_widget_ref (cfg_emu_filt_ft);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_emu_filt_ft", cfg_emu_filt_ft,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_emu_filt_ft);
+  gtk_container_add (GTK_CONTAINER (cfg_frm_ft), cfg_emu_filt_ft);
+  gtk_scale_set_digits (GTK_SCALE (cfg_emu_filt_ft), 2);
+
+  vbox17 = gtk_vbox_new (FALSE, 8);
+  gtk_widget_set_name (vbox17, "vbox17");
+  gtk_widget_ref (vbox17);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox17", vbox17,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox17);
+  gtk_box_pack_start (GTK_BOX (cfg_box_sidplay1), vbox17, TRUE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox17), 4);
+
+  cfg_filter_reset = gtk_button_new_with_label ("Reset values");
+  gtk_widget_set_name (cfg_filter_reset, "cfg_filter_reset");
+  gtk_widget_ref (cfg_filter_reset);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_filter_reset", cfg_filter_reset,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_filter_reset);
+  gtk_box_pack_start (GTK_BOX (vbox17), cfg_filter_reset, FALSE, FALSE, 0);
+
+  cfg_filter_sync = gtk_button_new_with_label ("Synchronize from\nSIDPlay2");
+  gtk_widget_set_name (cfg_filter_sync, "cfg_filter_sync");
+  gtk_widget_ref (cfg_filter_sync);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_filter_sync", cfg_filter_sync,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_filter_sync);
+  gtk_box_pack_start (GTK_BOX (vbox17), cfg_filter_sync, FALSE, FALSE, 0);
+
+  label55 = gtk_label_new ("SIDPlay1");
+  gtk_widget_set_name (label55, "label55");
+  gtk_widget_ref (label55);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "label55", label55,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label55);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (cfg_filters_notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (cfg_filters_notebook), 0), label55);
+
+  cfg_box_sidplay2 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_set_name (cfg_box_sidplay2, "cfg_box_sidplay2");
+  gtk_widget_ref (cfg_box_sidplay2);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_box_sidplay2", cfg_box_sidplay2,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_box_sidplay2);
+  gtk_container_add (GTK_CONTAINER (cfg_filters_notebook), cfg_box_sidplay2);
+  gtk_container_set_border_width (GTK_CONTAINER (cfg_box_sidplay2), 4);
+
+  vbox36 = gtk_vbox_new (FALSE, 8);
+  gtk_widget_set_name (vbox36, "vbox36");
+  gtk_widget_ref (vbox36);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox36", vbox36,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox36);
+  gtk_box_pack_start (GTK_BOX (cfg_box_sidplay2), vbox36, FALSE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox36), 4);
+
+  cfg_filter2_reset = gtk_button_new_with_label ("Reset values");
+  gtk_widget_set_name (cfg_filter2_reset, "cfg_filter2_reset");
+  gtk_widget_ref (cfg_filter2_reset);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_filter2_reset", cfg_filter2_reset,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_filter2_reset);
+  gtk_box_pack_start (GTK_BOX (vbox36), cfg_filter2_reset, FALSE, FALSE, 0);
+
+  cfg_filter2_sync = gtk_button_new_with_label ("Synchronize from\nSIDPlay1");
+  gtk_widget_set_name (cfg_filter2_sync, "cfg_filter2_sync");
+  gtk_widget_ref (cfg_filter2_sync);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_filter2_sync", cfg_filter2_sync,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_filter2_sync);
+  gtk_box_pack_start (GTK_BOX (vbox36), cfg_filter2_sync, FALSE, FALSE, 0);
+
+  label56 = gtk_label_new ("SIDPlay2");
+  gtk_widget_set_name (label56, "label56");
+  gtk_widget_ref (label56);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "label56", label56,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label56);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (cfg_filters_notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (cfg_filters_notebook), 1), label56);
+
+  label24 = gtk_label_new ("Filters");
+  gtk_widget_set_name (label24, "label24");
+  gtk_widget_ref (label24);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "label24", label24,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label24);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (cfg_notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (cfg_notebook), 3), label24);
+
+  vbox20 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_set_name (vbox20, "vbox20");
+  gtk_widget_ref (vbox20);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox20", vbox20,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox20);
+  gtk_container_add (GTK_CONTAINER (cfg_notebook), vbox20);
+
+  frame29 = gtk_frame_new ("Minimum playtime: ");
+  gtk_widget_set_name (frame29, "frame29");
+  gtk_widget_ref (frame29);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "frame29", frame29,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (frame29);
+  gtk_box_pack_start (GTK_BOX (vbox20), frame29, FALSE, FALSE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (frame29), 4);
+
+  vbox32 = gtk_vbox_new (FALSE, 2);
+  gtk_widget_set_name (vbox32, "vbox32");
+  gtk_widget_ref (vbox32);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox32", vbox32,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox32);
+  gtk_container_add (GTK_CONTAINER (frame29), vbox32);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox32), 2);
+
+  cfg_mintime_enable = gtk_check_button_new_with_label ("Play at least for specified time");
+  gtk_widget_set_name (cfg_mintime_enable, "cfg_mintime_enable");
+  gtk_widget_ref (cfg_mintime_enable);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_mintime_enable", cfg_mintime_enable,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_mintime_enable);
+  gtk_box_pack_start (GTK_BOX (vbox32), cfg_mintime_enable, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_mintime_enable, "If enabled, the tune is played at least for the specified time, adding silence to the end if necessary.", NULL);
+
+  hbox18 = gtk_hbox_new (FALSE, 2);
+  gtk_widget_set_name (hbox18, "hbox18");
+  gtk_widget_ref (hbox18);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "hbox18", hbox18,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (hbox18);
+  gtk_box_pack_start (GTK_BOX (vbox32), hbox18, FALSE, TRUE, 2);
+
+  cfg_mintime_label1 = gtk_label_new ("Playtime: ");
+  gtk_widget_set_name (cfg_mintime_label1, "cfg_mintime_label1");
+  gtk_widget_ref (cfg_mintime_label1);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_mintime_label1", cfg_mintime_label1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_mintime_label1);
+  gtk_box_pack_start (GTK_BOX (hbox18), cfg_mintime_label1, FALSE, FALSE, 0);
+  gtk_misc_set_alignment (GTK_MISC (cfg_mintime_label1), 0, 0.5);
+
+  cfg_mintime_adj = gtk_adjustment_new (15, 1, 32767, 1, 60, 60);
+  cfg_mintime = gtk_spin_button_new (GTK_ADJUSTMENT (cfg_mintime_adj), 1, 0);
+  gtk_widget_set_name (cfg_mintime, "cfg_mintime");
+  gtk_widget_ref (cfg_mintime);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_mintime", cfg_mintime,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_mintime);
+  gtk_box_pack_start (GTK_BOX (hbox18), cfg_mintime, FALSE, TRUE, 0);
+
+  cfg_mintime_label2 = gtk_label_new ("seconds");
+  gtk_widget_set_name (cfg_mintime_label2, "cfg_mintime_label2");
+  gtk_widget_ref (cfg_mintime_label2);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_mintime_label2", cfg_mintime_label2,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_mintime_label2);
+  gtk_box_pack_start (GTK_BOX (hbox18), cfg_mintime_label2, FALSE, FALSE, 0);
+  gtk_misc_set_alignment (GTK_MISC (cfg_mintime_label2), 0, 0.5);
+
+  frame21 = gtk_frame_new ("Maximum playtime: ");
+  gtk_widget_set_name (frame21, "frame21");
+  gtk_widget_ref (frame21);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "frame21", frame21,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (frame21);
+  gtk_box_pack_start (GTK_BOX (vbox20), frame21, FALSE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (frame21), 4);
+
+  vbox21 = gtk_vbox_new (FALSE, 2);
+  gtk_widget_set_name (vbox21, "vbox21");
+  gtk_widget_ref (vbox21);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox21", vbox21,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox21);
+  gtk_container_add (GTK_CONTAINER (frame21), vbox21);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox21), 2);
+
+  cfg_maxtime_enable = gtk_check_button_new_with_label ("Play for specified time maximum");
+  gtk_widget_set_name (cfg_maxtime_enable, "cfg_maxtime_enable");
+  gtk_widget_ref (cfg_maxtime_enable);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_maxtime_enable", cfg_maxtime_enable,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_maxtime_enable);
+  gtk_box_pack_start (GTK_BOX (vbox21), cfg_maxtime_enable, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_maxtime_enable, "If enabled, tune is played until specified duration is reached (aka maximum playtime).", NULL);
+
+  cfg_maxtime_unknown = gtk_check_button_new_with_label ("Only when song length is unknown");
+  gtk_widget_set_name (cfg_maxtime_unknown, "cfg_maxtime_unknown");
+  gtk_widget_ref (cfg_maxtime_unknown);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_maxtime_unknown", cfg_maxtime_unknown,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_maxtime_unknown);
+  gtk_box_pack_start (GTK_BOX (vbox21), cfg_maxtime_unknown, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_maxtime_unknown, "If enabled, the maximum playtime is applied only if song/tune length is not known.", NULL);
+
+  hbox14 = gtk_hbox_new (FALSE, 2);
+  gtk_widget_set_name (hbox14, "hbox14");
+  gtk_widget_ref (hbox14);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "hbox14", hbox14,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (hbox14);
+  gtk_box_pack_start (GTK_BOX (vbox21), hbox14, FALSE, TRUE, 2);
+
+  cfg_maxtime_label1 = gtk_label_new ("Playtime: ");
+  gtk_widget_set_name (cfg_maxtime_label1, "cfg_maxtime_label1");
+  gtk_widget_ref (cfg_maxtime_label1);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_maxtime_label1", cfg_maxtime_label1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_maxtime_label1);
+  gtk_box_pack_start (GTK_BOX (hbox14), cfg_maxtime_label1, FALSE, FALSE, 0);
+  gtk_misc_set_alignment (GTK_MISC (cfg_maxtime_label1), 0, 0.5);
+
+  cfg_maxtime_adj = gtk_adjustment_new (150, 1, 32767, 1, 60, 60);
+  cfg_maxtime = gtk_spin_button_new (GTK_ADJUSTMENT (cfg_maxtime_adj), 1, 0);
+  gtk_widget_set_name (cfg_maxtime, "cfg_maxtime");
+  gtk_widget_ref (cfg_maxtime);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_maxtime", cfg_maxtime,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_maxtime);
+  gtk_box_pack_start (GTK_BOX (hbox14), cfg_maxtime, FALSE, TRUE, 0);
+
+  cfg_maxtime_label2 = gtk_label_new ("seconds");
+  gtk_widget_set_name (cfg_maxtime_label2, "cfg_maxtime_label2");
+  gtk_widget_ref (cfg_maxtime_label2);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_maxtime_label2", cfg_maxtime_label2,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_maxtime_label2);
+  gtk_box_pack_start (GTK_BOX (hbox14), cfg_maxtime_label2, FALSE, FALSE, 0);
+  gtk_misc_set_alignment (GTK_MISC (cfg_maxtime_label2), 0, 0.5);
+
+  frame18 = gtk_frame_new ("Song length database: ");
+  gtk_widget_set_name (frame18, "frame18");
+  gtk_widget_ref (frame18);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "frame18", frame18,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (frame18);
+  gtk_box_pack_start (GTK_BOX (vbox20), frame18, FALSE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (frame18), 4);
+
+  vbox18 = gtk_vbox_new (FALSE, 2);
+  gtk_widget_set_name (vbox18, "vbox18");
+  gtk_widget_ref (vbox18);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox18", vbox18,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox18);
+  gtk_container_add (GTK_CONTAINER (frame18), vbox18);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox18), 2);
+
+  cfg_sld_enable = gtk_check_button_new_with_label ("Use XSIDPLAY-compatible database");
+  gtk_widget_set_name (cfg_sld_enable, "cfg_sld_enable");
+  gtk_widget_ref (cfg_sld_enable);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_sld_enable", cfg_sld_enable,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_sld_enable);
+  gtk_box_pack_start (GTK_BOX (vbox18), cfg_sld_enable, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_sld_enable, "This option enables using of XSIDPLAY compatible song length database. (Refer to XMMS-SID documentation for more information)", NULL);
+
+  hbox13 = gtk_hbox_new (FALSE, 4);
+  gtk_widget_set_name (hbox13, "hbox13");
+  gtk_widget_ref (hbox13);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "hbox13", hbox13,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (hbox13);
+  gtk_box_pack_start (GTK_BOX (vbox18), hbox13, FALSE, TRUE, 0);
+
+  cfg_sld_label1 = gtk_label_new ("DB-file: ");
+  gtk_widget_set_name (cfg_sld_label1, "cfg_sld_label1");
+  gtk_widget_ref (cfg_sld_label1);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_sld_label1", cfg_sld_label1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_sld_label1);
+  gtk_box_pack_start (GTK_BOX (hbox13), cfg_sld_label1, FALSE, TRUE, 0);
+
+  cfg_sld_dbpath = gtk_entry_new ();
+  gtk_widget_set_name (cfg_sld_dbpath, "cfg_sld_dbpath");
+  gtk_widget_ref (cfg_sld_dbpath);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_sld_dbpath", cfg_sld_dbpath,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_sld_dbpath);
+  gtk_box_pack_start (GTK_BOX (hbox13), cfg_sld_dbpath, TRUE, TRUE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_sld_dbpath, "Database path and filename", NULL);
+
+  cfg_sld_dbbrowse = gtk_button_new_with_label ("Browse");
+  gtk_widget_set_name (cfg_sld_dbbrowse, "cfg_sld_dbbrowse");
+  gtk_widget_ref (cfg_sld_dbbrowse);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_sld_dbbrowse", cfg_sld_dbbrowse,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_sld_dbbrowse);
+  gtk_box_pack_start (GTK_BOX (hbox13), cfg_sld_dbbrowse, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_sld_dbbrowse, "Browse for song length-database file", NULL);
+
+  label26 = gtk_label_new ("Songlength");
+  gtk_widget_set_name (label26, "label26");
+  gtk_widget_ref (label26);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "label26", label26,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label26);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (cfg_notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (cfg_notebook), 4), label26);
+
+  vbox33 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_set_name (vbox33, "vbox33");
+  gtk_widget_ref (vbox33);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox33", vbox33,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox33);
+  gtk_container_add (GTK_CONTAINER (cfg_notebook), vbox33);
+
+  frame7 = gtk_frame_new ("SID Tune Information List (STIL) database: ");
+  gtk_widget_set_name (frame7, "frame7");
+  gtk_widget_ref (frame7);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "frame7", frame7,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (frame7);
+  gtk_box_pack_start (GTK_BOX (vbox33), frame7, FALSE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (frame7), 4);
+
+  vbox8 = gtk_vbox_new (FALSE, 2);
+  gtk_widget_set_name (vbox8, "vbox8");
+  gtk_widget_ref (vbox8);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox8", vbox8,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox8);
+  gtk_container_add (GTK_CONTAINER (frame7), vbox8);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox8), 2);
+
+  cfg_stil_enable = gtk_check_button_new_with_label ("Use STIL database");
+  gtk_widget_set_name (cfg_stil_enable, "cfg_stil_enable");
+  gtk_widget_ref (cfg_stil_enable);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_stil_enable", cfg_stil_enable,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_stil_enable);
+  gtk_box_pack_start (GTK_BOX (vbox8), cfg_stil_enable, TRUE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_stil_enable, "If this option is enabled (and the database & HVSC settings below are correctly set), XMMS-SID will use and display additional information from STIL database when HVSC SIDs are played.", NULL);
+
+  hbox3 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_set_name (hbox3, "hbox3");
+  gtk_widget_ref (hbox3);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "hbox3", hbox3,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (hbox3);
+  gtk_box_pack_start (GTK_BOX (vbox8), hbox3, TRUE, TRUE, 0);
+
+  cfg_stil_label1 = gtk_label_new ("STIL file:");
+  gtk_widget_set_name (cfg_stil_label1, "cfg_stil_label1");
+  gtk_widget_ref (cfg_stil_label1);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_stil_label1", cfg_stil_label1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_stil_label1);
+  gtk_box_pack_start (GTK_BOX (hbox3), cfg_stil_label1, FALSE, FALSE, 0);
+  gtk_misc_set_padding (GTK_MISC (cfg_stil_label1), 4, 0);
+
+  alignment2 = gtk_alignment_new (0.5, 0.5, 1, 1);
+  gtk_widget_set_name (alignment2, "alignment2");
+  gtk_widget_ref (alignment2);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "alignment2", alignment2,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (alignment2);
+  gtk_box_pack_start (GTK_BOX (hbox3), alignment2, TRUE, TRUE, 4);
+
+  cfg_stil_dbpath = gtk_entry_new ();
+  gtk_widget_set_name (cfg_stil_dbpath, "cfg_stil_dbpath");
+  gtk_widget_ref (cfg_stil_dbpath);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_stil_dbpath", cfg_stil_dbpath,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_stil_dbpath);
+  gtk_container_add (GTK_CONTAINER (alignment2), cfg_stil_dbpath);
+  gtk_tooltips_set_tip (tooltips, cfg_stil_dbpath, "Path and filename of STIL database file (STIL.txt), usually found from HVSC's DOCUMENTS-subdirectory.", NULL);
+
+  alignment1 = gtk_alignment_new (0.5, 0.5, 1, 0.300001);
+  gtk_widget_set_name (alignment1, "alignment1");
+  gtk_widget_ref (alignment1);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "alignment1", alignment1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (alignment1);
+  gtk_box_pack_end (GTK_BOX (hbox3), alignment1, FALSE, FALSE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (alignment1), 4);
+
+  cfg_stil_browse = gtk_button_new_with_label ("Browse");
+  gtk_widget_set_name (cfg_stil_browse, "cfg_stil_browse");
+  gtk_widget_ref (cfg_stil_browse);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_stil_browse", cfg_stil_browse,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_stil_browse);
+  gtk_container_add (GTK_CONTAINER (alignment1), cfg_stil_browse);
+  gtk_tooltips_set_tip (tooltips, cfg_stil_browse, "Browse for STIL-database file", NULL);
+
+  hbox17 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_set_name (hbox17, "hbox17");
+  gtk_widget_ref (hbox17);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "hbox17", hbox17,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (hbox17);
+  gtk_box_pack_start (GTK_BOX (vbox8), hbox17, TRUE, TRUE, 0);
+
+  cfg_hvsc_label1 = gtk_label_new ("HVSC path:");
+  gtk_widget_set_name (cfg_hvsc_label1, "cfg_hvsc_label1");
+  gtk_widget_ref (cfg_hvsc_label1);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_hvsc_label1", cfg_hvsc_label1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_hvsc_label1);
+  gtk_box_pack_start (GTK_BOX (hbox17), cfg_hvsc_label1, FALSE, FALSE, 0);
+  gtk_misc_set_padding (GTK_MISC (cfg_hvsc_label1), 4, 0);
+
+  alignment6 = gtk_alignment_new (0.5, 0.5, 1, 1);
+  gtk_widget_set_name (alignment6, "alignment6");
+  gtk_widget_ref (alignment6);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "alignment6", alignment6,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (alignment6);
+  gtk_box_pack_start (GTK_BOX (hbox17), alignment6, TRUE, TRUE, 4);
+
+  cfg_hvsc_path = gtk_entry_new ();
+  gtk_widget_set_name (cfg_hvsc_path, "cfg_hvsc_path");
+  gtk_widget_ref (cfg_hvsc_path);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_hvsc_path", cfg_hvsc_path,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_hvsc_path);
+  gtk_container_add (GTK_CONTAINER (alignment6), cfg_hvsc_path);
+  gtk_tooltips_set_tip (tooltips, cfg_hvsc_path, "Path to base-directory of your High Voltage SID Collection (HVSC), for example /media/C64Music/", NULL);
+
+  alignment7 = gtk_alignment_new (0.5, 0.5, 1, 0.300001);
+  gtk_widget_set_name (alignment7, "alignment7");
+  gtk_widget_ref (alignment7);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "alignment7", alignment7,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (alignment7);
+  gtk_box_pack_end (GTK_BOX (hbox17), alignment7, FALSE, FALSE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (alignment7), 4);
+
+  cfg_hvsc_browse = gtk_button_new_with_label ("Browse");
+  gtk_widget_set_name (cfg_hvsc_browse, "cfg_hvsc_browse");
+  gtk_widget_ref (cfg_hvsc_browse);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_hvsc_browse", cfg_hvsc_browse,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_hvsc_browse);
+  gtk_container_add (GTK_CONTAINER (alignment7), cfg_hvsc_browse);
+  gtk_tooltips_set_tip (tooltips, cfg_hvsc_browse, "Browse for HVSC path", NULL);
+
+  frame16 = gtk_frame_new ("Song name/title format: ");
+  gtk_widget_set_name (frame16, "frame16");
+  gtk_widget_ref (frame16);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "frame16", frame16,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (frame16);
+  gtk_box_pack_start (GTK_BOX (vbox33), frame16, FALSE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (frame16), 4);
+
+  vbox16 = gtk_vbox_new (FALSE, 2);
+  gtk_widget_set_name (vbox16, "vbox16");
+  gtk_widget_ref (vbox16);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox16", vbox16,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox16);
+  gtk_container_add (GTK_CONTAINER (frame16), vbox16);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox16), 2);
+
+  cfg_ftitle_override = gtk_check_button_new_with_label ("Override generic XMMS titles");
+  gtk_widget_set_name (cfg_ftitle_override, "cfg_ftitle_override");
+  gtk_widget_ref (cfg_ftitle_override);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_ftitle_override", cfg_ftitle_override,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_ftitle_override);
+  gtk_box_pack_start (GTK_BOX (vbox16), cfg_ftitle_override, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_ftitle_override, "XMMS v1.2.5 and later support generic titlestring formatting (see XMMS preferences). This option can be enabled to override those generic titles with XMMS-SID specific ones. Formatting mnemonics are explained briefly below.", NULL);
+
+  cfg_ftitle_format = gtk_entry_new ();
+  gtk_widget_set_name (cfg_ftitle_format, "cfg_ftitle_format");
+  gtk_widget_ref (cfg_ftitle_format);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_ftitle_format", cfg_ftitle_format,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_ftitle_format);
+  gtk_box_pack_start (GTK_BOX (vbox16), cfg_ftitle_format, FALSE, FALSE, 2);
+
+  hbox9 = gtk_hbox_new (TRUE, 0);
+  gtk_widget_set_name (hbox9, "hbox9");
+  gtk_widget_ref (hbox9);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "hbox9", hbox9,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (hbox9);
+  gtk_box_pack_start (GTK_BOX (vbox16), hbox9, FALSE, FALSE, 2);
+
+  cfg_ftitle_desc1 = gtk_label_new ("%p - Performer/composer\n%t - Song name (title)\n%c - Copyright\n%s - File type\n%m - SID model");
+  gtk_widget_set_name (cfg_ftitle_desc1, "cfg_ftitle_desc1");
+  gtk_widget_ref (cfg_ftitle_desc1);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_ftitle_desc1", cfg_ftitle_desc1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_ftitle_desc1);
+  gtk_box_pack_start (GTK_BOX (hbox9), cfg_ftitle_desc1, FALSE, FALSE, 0);
+  gtk_label_set_justify (GTK_LABEL (cfg_ftitle_desc1), GTK_JUSTIFY_LEFT);
+  gtk_misc_set_alignment (GTK_MISC (cfg_ftitle_desc1), 0.04, 0.5);
+
+  cfg_ftitle_desc2 = gtk_label_new ("%n - Subtune\n%N - Number of subtunes\n%f - Filename\n%F - File path\n%e - File extension");
+  gtk_widget_set_name (cfg_ftitle_desc2, "cfg_ftitle_desc2");
+  gtk_widget_ref (cfg_ftitle_desc2);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_ftitle_desc2", cfg_ftitle_desc2,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_ftitle_desc2);
+  gtk_box_pack_start (GTK_BOX (hbox9), cfg_ftitle_desc2, FALSE, FALSE, 0);
+  gtk_label_set_justify (GTK_LABEL (cfg_ftitle_desc2), GTK_JUSTIFY_LEFT);
+  gtk_misc_set_alignment (GTK_MISC (cfg_ftitle_desc2), 0.04, 0.5);
+
+  label23 = gtk_label_new ("Title");
+  gtk_widget_set_name (label23, "label23");
+  gtk_widget_ref (label23);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "label23", label23,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label23);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (cfg_notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (cfg_notebook), 5), label23);
+
+  vbox19 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_set_name (vbox19, "vbox19");
+  gtk_widget_ref (vbox19);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox19", vbox19,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox19);
+  gtk_container_add (GTK_CONTAINER (cfg_notebook), vbox19);
+
+  frame28 = gtk_frame_new ("Sub-tune control: ");
+  gtk_widget_set_name (frame28, "frame28");
+  gtk_widget_ref (frame28);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "frame28", frame28,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (frame28);
+  gtk_box_pack_start (GTK_BOX (vbox19), frame28, FALSE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (frame28), 4);
+
+  vbox31 = gtk_vbox_new (FALSE, 2);
+  gtk_widget_set_name (vbox31, "vbox31");
+  gtk_widget_ref (vbox31);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox31", vbox31,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox31);
+  gtk_container_add (GTK_CONTAINER (frame28), vbox31);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox31), 2);
+
+  cfg_subctrl_none = gtk_radio_button_new_with_label (subtune_group, "Disabled");
+  subtune_group = gtk_radio_button_group (GTK_RADIO_BUTTON (cfg_subctrl_none));
+  gtk_widget_set_name (cfg_subctrl_none, "cfg_subctrl_none");
+  gtk_widget_ref (cfg_subctrl_none);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_subctrl_none", cfg_subctrl_none,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_subctrl_none);
+  gtk_box_pack_start (GTK_BOX (vbox31), cfg_subctrl_none, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_subctrl_none, "No sub-tune control.", NULL);
+
+  cfg_subctrl_seek = gtk_radio_button_new_with_label (subtune_group, "Seek back/forward changes sub-tune");
+  subtune_group = gtk_radio_button_group (GTK_RADIO_BUTTON (cfg_subctrl_seek));
+  gtk_widget_set_name (cfg_subctrl_seek, "cfg_subctrl_seek");
+  gtk_widget_ref (cfg_subctrl_seek);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_subctrl_seek", cfg_subctrl_seek,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_subctrl_seek);
+  gtk_box_pack_start (GTK_BOX (vbox31), cfg_subctrl_seek, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_subctrl_seek, "Seeking backwards/forwards selects previous/next sub-tune, similar to selector used in XMMS-SidPlay.", NULL);
+
+  cfg_subctrl_popup = gtk_radio_button_new_with_label (subtune_group, "Pop-up via seekbar (UADE-style)");
+  subtune_group = gtk_radio_button_group (GTK_RADIO_BUTTON (cfg_subctrl_popup));
+  gtk_widget_set_name (cfg_subctrl_popup, "cfg_subctrl_popup");
+  gtk_widget_ref (cfg_subctrl_popup);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_subctrl_popup", cfg_subctrl_popup,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_subctrl_popup);
+  gtk_box_pack_start (GTK_BOX (vbox31), cfg_subctrl_popup, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_subctrl_popup, "By pressing the seekbar a sub-tune control window pops up, in style of UADE (Unix Amiga Delitracker Emulator)", NULL);
+
+  cfg_subctrl_patch = gtk_radio_button_new_with_label (subtune_group, "Song-position patch");
+  subtune_group = gtk_radio_button_group (GTK_RADIO_BUTTON (cfg_subctrl_patch));
+  gtk_widget_set_name (cfg_subctrl_patch, "cfg_subctrl_patch");
+  gtk_widget_ref (cfg_subctrl_patch);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_subctrl_patch", cfg_subctrl_patch,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_subctrl_patch);
+  gtk_box_pack_start (GTK_BOX (vbox31), cfg_subctrl_patch, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_subctrl_patch, "Seekbar works as a sub-tune selector (Best option if you have patched your XMMS with the song-position patch.)", NULL);
+
+  frame31 = gtk_frame_new ("Automatic sub-tune changes: ");
+  gtk_widget_set_name (frame31, "frame31");
+  gtk_widget_ref (frame31);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "frame31", frame31,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (frame31);
+  gtk_box_pack_start (GTK_BOX (vbox19), frame31, FALSE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (frame31), 4);
+
+  vbox35 = gtk_vbox_new (FALSE, 2);
+  gtk_widget_set_name (vbox35, "vbox35");
+  gtk_widget_ref (vbox35);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox35", vbox35,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox35);
+  gtk_container_add (GTK_CONTAINER (frame31), vbox35);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox35), 2);
+
+  cfg_subauto_enable = gtk_check_button_new_with_label ("Go through all sub-tunes in file");
+  gtk_widget_set_name (cfg_subauto_enable, "cfg_subauto_enable");
+  gtk_widget_ref (cfg_subauto_enable);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_subauto_enable", cfg_subauto_enable,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_subauto_enable);
+  gtk_box_pack_start (GTK_BOX (vbox35), cfg_subauto_enable, FALSE, FALSE, 0);
+
+  cfg_subauto_min_only = gtk_check_button_new_with_label ("Only tunes with specified minimum length ");
+  gtk_widget_set_name (cfg_subauto_min_only, "cfg_subauto_min_only");
+  gtk_widget_ref (cfg_subauto_min_only);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_subauto_min_only", cfg_subauto_min_only,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_subauto_min_only);
+  gtk_box_pack_start (GTK_BOX (vbox35), cfg_subauto_min_only, FALSE, FALSE, 0);
+
+  hbox20 = gtk_hbox_new (FALSE, 2);
+  gtk_widget_set_name (hbox20, "hbox20");
+  gtk_widget_ref (hbox20);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "hbox20", hbox20,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (hbox20);
+  gtk_box_pack_start (GTK_BOX (vbox35), hbox20, TRUE, TRUE, 0);
+
+  label52 = gtk_label_new ("Playtime: ");
+  gtk_widget_set_name (label52, "label52");
+  gtk_widget_ref (label52);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "label52", label52,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label52);
+  gtk_box_pack_start (GTK_BOX (hbox20), label52, FALSE, FALSE, 0);
+  gtk_misc_set_alignment (GTK_MISC (label52), 0, 0.5);
+
+  cfg_subauto_mintime_adj = gtk_adjustment_new (15, 1, 32767, 1, 60, 60);
+  cfg_subauto_mintime = gtk_spin_button_new (GTK_ADJUSTMENT (cfg_subauto_mintime_adj), 1, 0);
+  gtk_widget_set_name (cfg_subauto_mintime, "cfg_subauto_mintime");
+  gtk_widget_ref (cfg_subauto_mintime);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_subauto_mintime", cfg_subauto_mintime,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_subauto_mintime);
+  gtk_box_pack_start (GTK_BOX (hbox20), cfg_subauto_mintime, FALSE, TRUE, 0);
+
+  label53 = gtk_label_new ("seconds");
+  gtk_widget_set_name (label53, "label53");
+  gtk_widget_ref (label53);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "label53", label53,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label53);
+  gtk_box_pack_start (GTK_BOX (hbox20), label53, FALSE, FALSE, 0);
+  gtk_misc_set_alignment (GTK_MISC (label53), 0, 0.5);
+
+  frame22 = gtk_frame_new ("Miscellaneous options: ");
+  gtk_widget_set_name (frame22, "frame22");
+  gtk_widget_ref (frame22);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "frame22", frame22,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (frame22);
+  gtk_box_pack_start (GTK_BOX (vbox19), frame22, FALSE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (frame22), 4);
+
+  vbox22 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_set_name (vbox22, "vbox22");
+  gtk_widget_ref (vbox22);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "vbox22", vbox22,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox22);
+  gtk_container_add (GTK_CONTAINER (frame22), vbox22);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox22), 2);
+
+  cfg_detectmagic = gtk_check_button_new_with_label ("Detect file by contents (slower)");
+  gtk_widget_set_name (cfg_detectmagic, "cfg_detectmagic");
+  gtk_widget_ref (cfg_detectmagic);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_detectmagic", cfg_detectmagic,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_detectmagic);
+  gtk_box_pack_start (GTK_BOX (vbox22), cfg_detectmagic, FALSE, FALSE, 0);
+  gtk_tooltips_set_tip (tooltips, cfg_detectmagic, "Determine if file is a SID-tune by checking the file contents. If NOT selected, filetype is determined by checking filename extension (.sid, .dat, ...)", NULL);
+
+  label3 = gtk_label_new ("Misc");
+  gtk_widget_set_name (label3, "label3");
+  gtk_widget_ref (label3);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "label3", label3,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label3);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (cfg_notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (cfg_notebook), 6), label3);
+
+  hbuttonbox1 = gtk_hbutton_box_new ();
+  gtk_widget_set_name (hbuttonbox1, "hbuttonbox1");
+  gtk_widget_ref (hbuttonbox1);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "hbuttonbox1", hbuttonbox1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (hbuttonbox1);
+  gtk_box_pack_end (GTK_BOX (vbox1), hbuttonbox1, FALSE, FALSE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (hbuttonbox1), 4);
+  gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox1), GTK_BUTTONBOX_END);
+  gtk_button_box_set_child_size (GTK_BUTTON_BOX (hbuttonbox1), 85, 30);
+
+  cfg_ok = gtk_button_new_with_label ("OK");
+  gtk_widget_set_name (cfg_ok, "cfg_ok");
+  gtk_widget_ref (cfg_ok);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_ok", cfg_ok,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_ok);
+  gtk_container_add (GTK_CONTAINER (hbuttonbox1), cfg_ok);
+  GTK_WIDGET_SET_FLAGS (cfg_ok, GTK_CAN_DEFAULT);
+  gtk_tooltips_set_tip (tooltips, cfg_ok, "Accept and update changes", NULL);
+
+  cfg_cancel = gtk_button_new_with_label ("Cancel");
+  gtk_widget_set_name (cfg_cancel, "cfg_cancel");
+  gtk_widget_ref (cfg_cancel);
+  gtk_object_set_data_full (GTK_OBJECT (xs_configwin), "cfg_cancel", cfg_cancel,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (cfg_cancel);
+  gtk_container_add (GTK_CONTAINER (hbuttonbox1), cfg_cancel);
+  GTK_WIDGET_SET_FLAGS (cfg_cancel, GTK_CAN_DEFAULT);
+  gtk_tooltips_set_tip (tooltips, cfg_cancel, "Cancel any changes", NULL);
+
+  gtk_signal_connect (GTK_OBJECT (cfg_samplerate_menu), "clicked",
+                      GTK_SIGNAL_FUNC (xs_cfg_samplerate_menu_clicked),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_oversample), "toggled",
+                      GTK_SIGNAL_FUNC (xs_cfg_oversample_toggled),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_emu_sidplay1), "toggled",
+                      GTK_SIGNAL_FUNC (xs_cfg_emu_sidplay1_toggled),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_emu_sidplay2), "toggled",
+                      GTK_SIGNAL_FUNC (xs_cfg_emu_sidplay2_toggled),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_emu_filters), "toggled",
+                      GTK_SIGNAL_FUNC (xs_cfg_emu_filters_toggled),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_filter_reset), "clicked",
+                      GTK_SIGNAL_FUNC (xs_cfg_filter_reset),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_filter_sync), "clicked",
+                      GTK_SIGNAL_FUNC (xs_cfg_filter_sync_clicked),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_filter2_reset), "clicked",
+                      GTK_SIGNAL_FUNC (xs_cfg_filter2_reset),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_filter2_sync), "clicked",
+                      GTK_SIGNAL_FUNC (xs_cfg_filter2_sync_clicked),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_mintime_enable), "toggled",
+                      GTK_SIGNAL_FUNC (xs_cfg_mintime_enable_toggled),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_mintime), "changed",
+                      GTK_SIGNAL_FUNC (xs_cfg_mintime_changed),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_maxtime_enable), "toggled",
+                      GTK_SIGNAL_FUNC (xs_cfg_maxtime_enable_toggled),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_maxtime), "changed",
+                      GTK_SIGNAL_FUNC (xs_cfg_maxtime_changed),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_sld_enable), "toggled",
+                      GTK_SIGNAL_FUNC (xs_cfg_sld_enable_toggled),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_sld_dbbrowse), "clicked",
+                      GTK_SIGNAL_FUNC (xs_cfg_sld_dbbrowse),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_stil_enable), "toggled",
+                      GTK_SIGNAL_FUNC (xs_cfg_stil_enable_toggled),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_stil_browse), "clicked",
+                      GTK_SIGNAL_FUNC (xs_cfg_stil_browse),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_hvsc_browse), "clicked",
+                      GTK_SIGNAL_FUNC (xs_cfg_hvsc_browse),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_ftitle_override), "toggled",
+                      GTK_SIGNAL_FUNC (xs_cfg_ftitle_override_toggled),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_subauto_enable), "toggled",
+                      GTK_SIGNAL_FUNC (xs_cfg_subauto_enable_toggled),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_subauto_min_only), "toggled",
+                      GTK_SIGNAL_FUNC (xs_cfg_subauto_min_only_toggled),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_ok), "clicked",
+                      GTK_SIGNAL_FUNC (xs_cfg_ok),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cfg_cancel), "clicked",
+                      GTK_SIGNAL_FUNC (xs_cfg_cancel),
+                      NULL);
+
+  gtk_object_set_data (GTK_OBJECT (xs_configwin), "tooltips", tooltips);
+
+  return xs_configwin;
+}
+
+GtkWidget*
+create_xs_fileinfowin (void)
+{
+  GtkWidget *xs_fileinfowin;
+  GtkWidget *vbox14;
+  GtkWidget *alignment8;
+  GtkWidget *frame30;
+  GtkWidget *hbox19;
+  GtkWidget *fileinfo_subctrl_prev;
+  GtkWidget *fileinfo_subctrl_adj;
+  GtkWidget *fileinfo_subctrl_next;
+  GtkWidget *frame14;
+  GtkWidget *table1;
+  GtkWidget *label16;
+  GtkWidget *label17;
+  GtkWidget *label18;
+  GtkWidget *label19;
+  GtkWidget *fileinfo_filename;
+  GtkWidget *fileinfo_songname;
+  GtkWidget *fileinfo_composer;
+  GtkWidget *fileinfo_copyright;
+  GtkWidget *frame15;
+  GtkWidget *vbox15;
+  GtkWidget *fileinfo_sub_tune;
+  GtkWidget *fileinfo_sub_tune_menu;
+  GtkWidget *table2;
+  GtkWidget *label41;
+  GtkWidget *fileinfo_sub_author;
+  GtkWidget *label50;
+  GtkWidget *fileinfo_sub_name;
+  GtkWidget *label51;
+  GtkWidget *entry1;
+  GtkWidget *scrolledwindow2;
+  GtkWidget *fileinfo_sub_info;
+  GtkWidget *button2;
+
+  xs_fileinfowin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_type_hint (GTK_WINDOW(xs_fileinfowin), GDK_WINDOW_TYPE_HINT_DIALOG);
+  gtk_widget_set_name (xs_fileinfowin, "xs_fileinfowin");
+  gtk_object_set_data (GTK_OBJECT (xs_fileinfowin), "xs_fileinfowin", xs_fileinfowin);
+  gtk_widget_set_usize (xs_fileinfowin, 400, -2);
+  gtk_window_set_title (GTK_WINDOW (xs_fileinfowin), "XMMS-SID Fileinfo");
+  gtk_window_set_position (GTK_WINDOW (xs_fileinfowin), GTK_WIN_POS_MOUSE);
+
+  vbox14 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_set_name (vbox14, "vbox14");
+  gtk_widget_ref (vbox14);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "vbox14", vbox14,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox14);
+  gtk_container_add (GTK_CONTAINER (xs_fileinfowin), vbox14);
+
+  alignment8 = gtk_alignment_new (0.5, 0.5, 0.1, 1);
+  gtk_widget_set_name (alignment8, "alignment8");
+  gtk_widget_ref (alignment8);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "alignment8", alignment8,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (alignment8);
+  gtk_box_pack_start (GTK_BOX (vbox14), alignment8, FALSE, FALSE, 0);
+
+  frame30 = gtk_frame_new (NULL);
+  gtk_widget_set_name (frame30, "frame30");
+  gtk_widget_ref (frame30);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "frame30", frame30,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (frame30);
+  gtk_container_add (GTK_CONTAINER (alignment8), frame30);
+  gtk_container_set_border_width (GTK_CONTAINER (frame30), 2);
+  gtk_frame_set_shadow_type (GTK_FRAME (frame30), GTK_SHADOW_OUT);
+
+  hbox19 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_set_name (hbox19, "hbox19");
+  gtk_widget_ref (hbox19);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "hbox19", hbox19,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (hbox19);
+  gtk_container_add (GTK_CONTAINER (frame30), hbox19);
+  gtk_container_set_border_width (GTK_CONTAINER (hbox19), 4);
+
+  fileinfo_subctrl_prev = gtk_button_new_with_label (" < ");
+  gtk_widget_set_name (fileinfo_subctrl_prev, "fileinfo_subctrl_prev");
+  gtk_widget_ref (fileinfo_subctrl_prev);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "fileinfo_subctrl_prev", fileinfo_subctrl_prev,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (fileinfo_subctrl_prev);
+  gtk_box_pack_start (GTK_BOX (hbox19), fileinfo_subctrl_prev, FALSE, FALSE, 0);
+
+  fileinfo_subctrl_adj = gtk_hscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 0, 0, 0, 0)));
+  gtk_widget_set_name (fileinfo_subctrl_adj, "fileinfo_subctrl_adj");
+  gtk_widget_ref (fileinfo_subctrl_adj);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "fileinfo_subctrl_adj", fileinfo_subctrl_adj,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (fileinfo_subctrl_adj);
+  gtk_box_pack_start (GTK_BOX (hbox19), fileinfo_subctrl_adj, TRUE, TRUE, 0);
+  gtk_scale_set_digits (GTK_SCALE (fileinfo_subctrl_adj), 0);
+  gtk_range_set_update_policy (GTK_RANGE (fileinfo_subctrl_adj), GTK_UPDATE_DELAYED);
+
+  fileinfo_subctrl_next = gtk_button_new_with_label (" > ");
+  gtk_widget_set_name (fileinfo_subctrl_next, "fileinfo_subctrl_next");
+  gtk_widget_ref (fileinfo_subctrl_next);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "fileinfo_subctrl_next", fileinfo_subctrl_next,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (fileinfo_subctrl_next);
+  gtk_box_pack_start (GTK_BOX (hbox19), fileinfo_subctrl_next, FALSE, FALSE, 0);
+
+  frame14 = gtk_frame_new ("Song Information:");
+  gtk_widget_set_name (frame14, "frame14");
+  gtk_widget_ref (frame14);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "frame14", frame14,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (frame14);
+  gtk_box_pack_start (GTK_BOX (vbox14), frame14, FALSE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (frame14), 4);
+
+  table1 = gtk_table_new (4, 2, FALSE);
+  gtk_widget_set_name (table1, "table1");
+  gtk_widget_ref (table1);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "table1", table1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (table1);
+  gtk_container_add (GTK_CONTAINER (frame14), table1);
+  gtk_container_set_border_width (GTK_CONTAINER (table1), 4);
+  gtk_table_set_row_spacings (GTK_TABLE (table1), 2);
+  gtk_table_set_col_spacings (GTK_TABLE (table1), 4);
+
+  label16 = gtk_label_new ("Filename:");
+  gtk_widget_set_name (label16, "label16");
+  gtk_widget_ref (label16);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "label16", label16,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label16);
+  gtk_table_attach (GTK_TABLE (table1), label16, 0, 1, 0, 1,
+                    (GtkAttachOptions) (0),
+                    (GtkAttachOptions) (0), 0, 0);
+
+  label17 = gtk_label_new ("Songname:");
+  gtk_widget_set_name (label17, "label17");
+  gtk_widget_ref (label17);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "label17", label17,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label17);
+  gtk_table_attach (GTK_TABLE (table1), label17, 0, 1, 1, 2,
+                    (GtkAttachOptions) (0),
+                    (GtkAttachOptions) (0), 0, 0);
+
+  label18 = gtk_label_new ("Composer:");
+  gtk_widget_set_name (label18, "label18");
+  gtk_widget_ref (label18);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "label18", label18,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label18);
+  gtk_table_attach (GTK_TABLE (table1), label18, 0, 1, 2, 3,
+                    (GtkAttachOptions) (0),
+                    (GtkAttachOptions) (0), 0, 0);
+
+  label19 = gtk_label_new ("Copyright:");
+  gtk_widget_set_name (label19, "label19");
+  gtk_widget_ref (label19);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "label19", label19,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label19);
+  gtk_table_attach (GTK_TABLE (table1), label19, 0, 1, 3, 4,
+                    (GtkAttachOptions) (0),
+                    (GtkAttachOptions) (0), 0, 0);
+
+  fileinfo_filename = gtk_entry_new ();
+  gtk_widget_set_name (fileinfo_filename, "fileinfo_filename");
+  gtk_widget_ref (fileinfo_filename);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "fileinfo_filename", fileinfo_filename,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (fileinfo_filename);
+  gtk_table_attach (GTK_TABLE (table1), fileinfo_filename, 1, 2, 0, 1,
+                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+  gtk_entry_set_editable (GTK_ENTRY (fileinfo_filename), FALSE);
+
+  fileinfo_songname = gtk_entry_new ();
+  gtk_widget_set_name (fileinfo_songname, "fileinfo_songname");
+  gtk_widget_ref (fileinfo_songname);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "fileinfo_songname", fileinfo_songname,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (fileinfo_songname);
+  gtk_table_attach (GTK_TABLE (table1), fileinfo_songname, 1, 2, 1, 2,
+                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+  gtk_entry_set_editable (GTK_ENTRY (fileinfo_songname), FALSE);
+
+  fileinfo_composer = gtk_entry_new ();
+  gtk_widget_set_name (fileinfo_composer, "fileinfo_composer");
+  gtk_widget_ref (fileinfo_composer);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "fileinfo_composer", fileinfo_composer,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (fileinfo_composer);
+  gtk_table_attach (GTK_TABLE (table1), fileinfo_composer, 1, 2, 2, 3,
+                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+  gtk_entry_set_editable (GTK_ENTRY (fileinfo_composer), FALSE);
+
+  fileinfo_copyright = gtk_entry_new ();
+  gtk_widget_set_name (fileinfo_copyright, "fileinfo_copyright");
+  gtk_widget_ref (fileinfo_copyright);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "fileinfo_copyright", fileinfo_copyright,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (fileinfo_copyright);
+  gtk_table_attach (GTK_TABLE (table1), fileinfo_copyright, 1, 2, 3, 4,
+                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+  gtk_entry_set_editable (GTK_ENTRY (fileinfo_copyright), FALSE);
+
+  frame15 = gtk_frame_new ("Sub-tune Information:");
+  gtk_widget_set_name (frame15, "frame15");
+  gtk_widget_ref (frame15);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "frame15", frame15,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (frame15);
+  gtk_box_pack_start (GTK_BOX (vbox14), frame15, TRUE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (frame15), 4);
+
+  vbox15 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_set_name (vbox15, "vbox15");
+  gtk_widget_ref (vbox15);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "vbox15", vbox15,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox15);
+  gtk_container_add (GTK_CONTAINER (frame15), vbox15);
+
+  fileinfo_sub_tune = gtk_option_menu_new ();
+  gtk_widget_set_name (fileinfo_sub_tune, "fileinfo_sub_tune");
+  gtk_widget_ref (fileinfo_sub_tune);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "fileinfo_sub_tune", fileinfo_sub_tune,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (fileinfo_sub_tune);
+  gtk_box_pack_start (GTK_BOX (vbox15), fileinfo_sub_tune, FALSE, FALSE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (fileinfo_sub_tune), 4);
+  fileinfo_sub_tune_menu = gtk_menu_new ();
+  gtk_option_menu_set_menu (GTK_OPTION_MENU (fileinfo_sub_tune), fileinfo_sub_tune_menu);
+
+  table2 = gtk_table_new (3, 2, FALSE);
+  gtk_widget_set_name (table2, "table2");
+  gtk_widget_ref (table2);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "table2", table2,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (table2);
+  gtk_box_pack_start (GTK_BOX (vbox15), table2, FALSE, FALSE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (table2), 4);
+  gtk_table_set_row_spacings (GTK_TABLE (table2), 2);
+  gtk_table_set_col_spacings (GTK_TABLE (table2), 4);
+
+  label41 = gtk_label_new ("Author:");
+  gtk_widget_set_name (label41, "label41");
+  gtk_widget_ref (label41);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "label41", label41,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label41);
+  gtk_table_attach (GTK_TABLE (table2), label41, 0, 1, 1, 2,
+                    (GtkAttachOptions) (GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+
+  fileinfo_sub_author = gtk_entry_new ();
+  gtk_widget_set_name (fileinfo_sub_author, "fileinfo_sub_author");
+  gtk_widget_ref (fileinfo_sub_author);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "fileinfo_sub_author", fileinfo_sub_author,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (fileinfo_sub_author);
+  gtk_table_attach (GTK_TABLE (table2), fileinfo_sub_author, 1, 2, 1, 2,
+                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+  gtk_entry_set_editable (GTK_ENTRY (fileinfo_sub_author), FALSE);
+
+  label50 = gtk_label_new ("Name:");
+  gtk_widget_set_name (label50, "label50");
+  gtk_widget_ref (label50);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "label50", label50,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label50);
+  gtk_table_attach (GTK_TABLE (table2), label50, 0, 1, 0, 1,
+                    (GtkAttachOptions) (GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+
+  fileinfo_sub_name = gtk_entry_new ();
+  gtk_widget_set_name (fileinfo_sub_name, "fileinfo_sub_name");
+  gtk_widget_ref (fileinfo_sub_name);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "fileinfo_sub_name", fileinfo_sub_name,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (fileinfo_sub_name);
+  gtk_table_attach (GTK_TABLE (table2), fileinfo_sub_name, 1, 2, 0, 1,
+                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+  gtk_entry_set_editable (GTK_ENTRY (fileinfo_sub_name), FALSE);
+
+  label51 = gtk_label_new ("Duration:");
+  gtk_widget_set_name (label51, "label51");
+  gtk_widget_ref (label51);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "label51", label51,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label51);
+  gtk_table_attach (GTK_TABLE (table2), label51, 0, 1, 2, 3,
+                    (GtkAttachOptions) (GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+  gtk_misc_set_alignment (GTK_MISC (label51), 0, 0.5);
+
+  entry1 = gtk_entry_new ();
+  gtk_widget_set_name (entry1, "entry1");
+  gtk_widget_ref (entry1);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "entry1", entry1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (entry1);
+  gtk_table_attach (GTK_TABLE (table2), entry1, 1, 2, 2, 3,
+                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+  gtk_entry_set_editable (GTK_ENTRY (entry1), FALSE);
+
+  scrolledwindow2 = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_set_name (scrolledwindow2, "scrolledwindow2");
+  gtk_widget_ref (scrolledwindow2);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "scrolledwindow2", scrolledwindow2,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (scrolledwindow2);
+  gtk_box_pack_start (GTK_BOX (vbox15), scrolledwindow2, TRUE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (scrolledwindow2), 4);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow2), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+
+  fileinfo_sub_info = gtk_text_view_new ();
+  gtk_widget_set_name (fileinfo_sub_info, "fileinfo_sub_info");
+  gtk_widget_ref (fileinfo_sub_info);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "fileinfo_sub_info", fileinfo_sub_info,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (fileinfo_sub_info);
+  gtk_container_add (GTK_CONTAINER (scrolledwindow2), fileinfo_sub_info);
+
+  button2 = gtk_button_new_with_label ("Close");
+  gtk_widget_set_name (button2, "button2");
+  gtk_widget_ref (button2);
+  gtk_object_set_data_full (GTK_OBJECT (xs_fileinfowin), "button2", button2,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (button2);
+  gtk_box_pack_start (GTK_BOX (vbox14), button2, FALSE, FALSE, 0);
+  GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT);
+
+  gtk_signal_connect (GTK_OBJECT (xs_fileinfowin), "delete_event",
+                      GTK_SIGNAL_FUNC (xs_fileinfo_delete),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (fileinfo_subctrl_prev), "clicked",
+                      GTK_SIGNAL_FUNC (xs_subctrl_prevsong),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (fileinfo_subctrl_next), "clicked",
+                      GTK_SIGNAL_FUNC (xs_subctrl_nextsong),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (button2), "clicked",
+                      GTK_SIGNAL_FUNC (xs_fileinfo_ok),
+                      NULL);
+
+  gtk_widget_grab_focus (button2);
+  gtk_widget_grab_default (button2);
+  return xs_fileinfowin;
+}
+
+GtkWidget*
+create_xs_sldbfileselector (void)
+{
+  GtkWidget *xs_sldbfileselector;
+  GtkWidget *ok_button2;
+  GtkWidget *cancel_button2;
+
+  xs_sldbfileselector = gtk_file_selection_new ("Select HVSC song length database");
+  gtk_widget_set_name (xs_sldbfileselector, "xs_sldbfileselector");
+  gtk_object_set_data (GTK_OBJECT (xs_sldbfileselector), "xs_sldbfileselector", xs_sldbfileselector);
+  gtk_container_set_border_width (GTK_CONTAINER (xs_sldbfileselector), 10);
+  gtk_window_set_modal (GTK_WINDOW (xs_sldbfileselector), TRUE);
+  gtk_file_selection_hide_fileop_buttons (GTK_FILE_SELECTION (xs_sldbfileselector));
+
+  ok_button2 = GTK_FILE_SELECTION (xs_sldbfileselector)->ok_button;
+  gtk_widget_set_name (ok_button2, "ok_button2");
+  gtk_object_set_data (GTK_OBJECT (xs_sldbfileselector), "ok_button2", ok_button2);
+  gtk_widget_show (ok_button2);
+  GTK_WIDGET_SET_FLAGS (ok_button2, GTK_CAN_DEFAULT);
+
+  cancel_button2 = GTK_FILE_SELECTION (xs_sldbfileselector)->cancel_button;
+  gtk_widget_set_name (cancel_button2, "cancel_button2");
+  gtk_object_set_data (GTK_OBJECT (xs_sldbfileselector), "cancel_button2", cancel_button2);
+  gtk_widget_show (cancel_button2);
+  GTK_WIDGET_SET_FLAGS (cancel_button2, GTK_CAN_DEFAULT);
+
+  gtk_signal_connect (GTK_OBJECT (ok_button2), "clicked",
+                      GTK_SIGNAL_FUNC (xs_cfg_sldb_fs_ok),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cancel_button2), "clicked",
+                      GTK_SIGNAL_FUNC (xs_cfg_sldb_fs_cancel),
+                      NULL);
+
+  return xs_sldbfileselector;
+}
+
+GtkWidget*
+create_xs_stilfileselector (void)
+{
+  GtkWidget *xs_stilfileselector;
+  GtkWidget *ok_button3;
+  GtkWidget *cancel_button3;
+
+  xs_stilfileselector = gtk_file_selection_new ("Select STIL-database ");
+  gtk_widget_set_name (xs_stilfileselector, "xs_stilfileselector");
+  gtk_object_set_data (GTK_OBJECT (xs_stilfileselector), "xs_stilfileselector", xs_stilfileselector);
+  gtk_container_set_border_width (GTK_CONTAINER (xs_stilfileselector), 10);
+  gtk_window_set_modal (GTK_WINDOW (xs_stilfileselector), TRUE);
+  gtk_file_selection_hide_fileop_buttons (GTK_FILE_SELECTION (xs_stilfileselector));
+
+  ok_button3 = GTK_FILE_SELECTION (xs_stilfileselector)->ok_button;
+  gtk_widget_set_name (ok_button3, "ok_button3");
+  gtk_object_set_data (GTK_OBJECT (xs_stilfileselector), "ok_button3", ok_button3);
+  gtk_widget_show (ok_button3);
+  GTK_WIDGET_SET_FLAGS (ok_button3, GTK_CAN_DEFAULT);
+
+  cancel_button3 = GTK_FILE_SELECTION (xs_stilfileselector)->cancel_button;
+  gtk_widget_set_name (cancel_button3, "cancel_button3");
+  gtk_object_set_data (GTK_OBJECT (xs_stilfileselector), "cancel_button3", cancel_button3);
+  gtk_widget_show (cancel_button3);
+  GTK_WIDGET_SET_FLAGS (cancel_button3, GTK_CAN_DEFAULT);
+
+  gtk_signal_connect (GTK_OBJECT (ok_button3), "clicked",
+                      GTK_SIGNAL_FUNC (xs_cfg_stil_fs_ok),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cancel_button3), "clicked",
+                      GTK_SIGNAL_FUNC (xs_cfg_stil_fs_cancel),
+                      NULL);
+
+  return xs_stilfileselector;
+}
+
+GtkWidget*
+create_xs_hvscpathselector (void)
+{
+  GtkWidget *xs_hvscpathselector;
+  GtkWidget *ok_button4;
+  GtkWidget *cancel_button4;
+
+  xs_hvscpathselector = gtk_file_selection_new ("Select HVSC location prefix");
+  gtk_widget_set_name (xs_hvscpathselector, "xs_hvscpathselector");
+  gtk_object_set_data (GTK_OBJECT (xs_hvscpathselector), "xs_hvscpathselector", xs_hvscpathselector);
+  gtk_container_set_border_width (GTK_CONTAINER (xs_hvscpathselector), 10);
+  gtk_window_set_modal (GTK_WINDOW (xs_hvscpathselector), TRUE);
+  gtk_file_selection_hide_fileop_buttons (GTK_FILE_SELECTION (xs_hvscpathselector));
+
+  ok_button4 = GTK_FILE_SELECTION (xs_hvscpathselector)->ok_button;
+  gtk_widget_set_name (ok_button4, "ok_button4");
+  gtk_object_set_data (GTK_OBJECT (xs_hvscpathselector), "ok_button4", ok_button4);
+  gtk_widget_show (ok_button4);
+  GTK_WIDGET_SET_FLAGS (ok_button4, GTK_CAN_DEFAULT);
+
+  cancel_button4 = GTK_FILE_SELECTION (xs_hvscpathselector)->cancel_button;
+  gtk_widget_set_name (cancel_button4, "cancel_button4");
+  gtk_object_set_data (GTK_OBJECT (xs_hvscpathselector), "cancel_button4", cancel_button4);
+  gtk_widget_show (cancel_button4);
+  GTK_WIDGET_SET_FLAGS (cancel_button4, GTK_CAN_DEFAULT);
+
+  gtk_signal_connect (GTK_OBJECT (ok_button4), "clicked",
+                      GTK_SIGNAL_FUNC (xs_cfg_hvsc_fs_ok),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (cancel_button4), "clicked",
+                      GTK_SIGNAL_FUNC (xs_cfg_hvsc_fs_cancel),
+                      NULL);
+
+  return xs_hvscpathselector;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_interface.h	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,9 @@
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+GtkWidget* create_xs_configwin (void);
+GtkWidget* create_xs_fileinfowin (void);
+GtkWidget* create_xs_sldbfileselector (void);
+GtkWidget* create_xs_stilfileselector (void);
+GtkWidget* create_xs_hvscpathselector (void);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_length.c	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,603 @@
+/*  
+   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
+
+   Get song length from SLDB for PSID/RSID files
+   
+   Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org>
+   (C) Copyright 1999-2005 Tecnic Software productions (TNSP)
+
+   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 "xs_length.h"
+#include "xs_support.h"
+#include "xs_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+
+/* Database handling functions
+ */
+static t_xs_sldb_node *xs_sldb_node_new(void)
+{
+	t_xs_sldb_node *pResult;
+
+	/* Allocate memory for new node */
+	pResult = (t_xs_sldb_node *) g_malloc0(sizeof(t_xs_sldb_node));
+	if (!pResult)
+		return NULL;
+
+	return pResult;
+}
+
+
+static void xs_sldb_node_free(t_xs_sldb_node * pNode)
+{
+	if (pNode) {
+		/* Nothing much to do here ... */
+		g_free(pNode);
+	}
+}
+
+
+/* Insert given node to db linked list
+ */
+static void xs_sldb_node_insert(t_xs_sldb * db, t_xs_sldb_node * pNode)
+{
+	assert(db);
+
+	if (db->pNodes) {
+		/* The first node's pPrev points to last node */
+		LPREV = db->pNodes->pPrev;	/* New node's prev = Previous last node */
+		db->pNodes->pPrev->pNext = pNode;	/* Previous last node's next = New node */
+		db->pNodes->pPrev = pNode;	/* New last node = New node */
+		LNEXT = NULL;	/* But next is NULL! */
+	} else {
+		db->pNodes = pNode;	/* First node ... */
+		LPREV = pNode;	/* ... it's also last */
+		LNEXT = NULL;	/* But next is NULL! */
+	}
+}
+
+
+/* Parses a time-entry in SLDB format
+ */
+static gint32 xs_sldb_gettime(gchar * pcStr, size_t * piPos)
+{
+	gint32 iResult, iTemp;
+
+	/* Check if it starts with a digit */
+	if (isdigit(pcStr[*piPos])) {
+		/* Get minutes-field */
+		iResult = 0;
+		while (isdigit(pcStr[*piPos]))
+			iResult = (iResult * 10) + (pcStr[(*piPos)++] - '0');
+
+		iResult *= 60;
+
+		/* Check the field separator char */
+		if (pcStr[*piPos] == ':') {
+			/* Get seconds-field */
+			(*piPos)++;
+			iTemp = 0;
+			while (isdigit(pcStr[*piPos]))
+				iTemp = (iTemp * 10) + (pcStr[(*piPos)++] - '0');
+
+			iResult += iTemp;
+		} else
+			iResult = -2;
+	} else
+		iResult = -1;
+
+	/* Ignore and skip the possible attributes */
+	while (pcStr[*piPos] && !isspace(pcStr[*piPos]))
+		(*piPos)++;
+
+	return iResult;
+}
+
+
+/* Read database to memory
+ */
+gint xs_sldb_read(t_xs_sldb * db, gchar * dbFilename)
+{
+	FILE *inFile;
+	gchar inLine[XS_BUF_SIZE];
+	size_t lineNum, linePos;
+	gboolean iOK;
+	t_xs_sldb_node *tmpNode;
+	assert(db);
+
+	/* Try to open the file */
+	if ((inFile = fopen(dbFilename, "ra")) == NULL) {
+		XSERR("Could not open SongLengthDB '%s'\n", dbFilename);
+		return -1;
+	}
+
+	/* Read and parse the data */
+	lineNum = 0;
+
+	while (!feof(inFile)) {
+		fgets(inLine, XS_BUF_SIZE, inFile);
+		inLine[XS_BUF_SIZE - 1] = 0;
+		lineNum++;
+
+		/* Check if it is datafield */
+		if (isxdigit(inLine[0])) {
+			/* Check the length of the hash */
+			linePos = 0;
+			while (isxdigit(inLine[linePos]))
+				linePos++;
+
+			if (linePos != XS_MD5HASH_LENGTH_CH) {
+				XSERR("Invalid hash in SongLengthDB file '%s' line #%d!\n", dbFilename, lineNum);
+			} else {
+				/* Allocate new node */
+				if ((tmpNode = xs_sldb_node_new()) == NULL) {
+					XSERR("Error allocating new node. Fatal error.\n");
+					exit(5);
+				}
+
+				/* Get hash value */
+#if (XS_MD5HASH_LENGTH != 16)
+#error Mismatch in hashcode length. Fix here.
+#endif
+				sscanf(&inLine[0], "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
+				       (guint *) & (tmpNode->md5Hash[0]), (guint *) & (tmpNode->md5Hash[1]),
+				       (guint *) & (tmpNode->md5Hash[2]), (guint *) & (tmpNode->md5Hash[3]),
+				       (guint *) & (tmpNode->md5Hash[4]), (guint *) & (tmpNode->md5Hash[5]),
+				       (guint *) & (tmpNode->md5Hash[6]), (guint *) & (tmpNode->md5Hash[7]),
+				       (guint *) & (tmpNode->md5Hash[8]), (guint *) & (tmpNode->md5Hash[9]),
+				       (guint *) & (tmpNode->md5Hash[10]), (guint *) & (tmpNode->md5Hash[11]),
+				       (guint *) & (tmpNode->md5Hash[12]), (guint *) & (tmpNode->md5Hash[13]),
+				       (guint *) & (tmpNode->md5Hash[14]), (guint *) & (tmpNode->md5Hash[15]));
+
+				/* Get playtimes */
+				if (inLine[linePos] != 0) {
+					if (inLine[linePos] != '=') {
+						XSERR("'=' expected in SongLengthDB file '%s' line #%d, column #%d\n",
+						      dbFilename, lineNum, linePos);
+
+						xs_sldb_node_free(tmpNode);
+					} else {
+						/* First playtime is after '=' */
+						linePos++;
+						iOK = TRUE;
+
+						while ((linePos < strlen(inLine)) && iOK) {
+							xs_findnext(inLine, &linePos);
+
+							if (tmpNode->nLengths < XS_STIL_MAXENTRY) {
+								tmpNode->sLengths[tmpNode->nLengths] =
+								    xs_sldb_gettime(inLine, &linePos);
+								tmpNode->nLengths++;
+							} else
+								iOK = FALSE;
+						}
+
+						/* Add an node to db in memory */
+						if (iOK)
+							xs_sldb_node_insert(db, tmpNode);
+						else
+							xs_sldb_node_free(tmpNode);
+					}
+				}
+			}
+		} else if ((inLine[0] != ';') && (inLine[0] != '[')) {
+			XSERR("Invalid line in SongLengthDB file '%s' line #%d\n", dbFilename, lineNum);
+		}
+
+	}			/* while */
+
+	/* Close the file */
+	fclose(inFile);
+
+	return 0;
+}
+
+
+/* Compare two given MD5-hashes.
+ * Return: 0 if equal
+ *         negative if testHash1 < testHash2
+ *         positive if testHash1 > testHash2
+ */
+static gint xs_sldb_cmphash(t_xs_md5hash testHash1, t_xs_md5hash testHash2)
+{
+	register gint i, res = 0;
+
+	/* Compute difference of hashes */
+	for (i = 0; (i < XS_MD5HASH_LENGTH) && (!res); i++)
+		res = (testHash1[i] - testHash2[i]);
+
+	return res;
+}
+
+
+/* Get node from db index via binary search
+ */
+static t_xs_sldb_node *xs_sldb_get_node(t_xs_sldb * db, t_xs_md5hash pHash)
+{
+	gint iStartNode, iEndNode, iQNode, r, i;
+	gboolean iFound;
+	t_xs_sldb_node *pResult;
+
+	/* Check the database pointers */
+	if (!db || !db->pNodes || !db->ppIndex)
+		return NULL;
+
+	/* Look-up via index using binary search */
+	pResult = NULL;
+	iStartNode = 0;
+	iEndNode = (db->n - 1);
+	iQNode = (iEndNode / 2);
+	iFound = FALSE;
+
+	while ((!iFound) && ((iEndNode - iStartNode) > XS_BIN_BAILOUT)) {
+		r = xs_sldb_cmphash(pHash, db->ppIndex[iQNode]->md5Hash);
+		if (r < 0) {
+			/* Hash was in the <- LEFT side */
+			iEndNode = iQNode;
+			iQNode = iStartNode + ((iEndNode - iStartNode) / 2);
+		} else if (r > 0) {
+			/* Hash was in the RIGHT -> side */
+			iStartNode = iQNode;
+			iQNode = iStartNode + ((iEndNode - iStartNode) / 2);
+		} else
+			iFound = TRUE;
+	}
+
+	/* If not found already */
+	if (!iFound) {
+		/* Search the are linearly */
+		iFound = FALSE;
+		i = iStartNode;
+		while ((i <= iEndNode) && (!iFound)) {
+			if (xs_sldb_cmphash(pHash, db->ppIndex[i]->md5Hash) == 0)
+				iFound = TRUE;
+			else
+				i++;
+		}
+
+		/* Check the result */
+		if (iFound)
+			pResult = db->ppIndex[i];
+
+	} else {
+		/* Found via binary search */
+		pResult = db->ppIndex[iQNode];
+	}
+
+	return pResult;
+}
+
+
+/* Compare two nodes
+ */
+static gint xs_sldb_cmp(const void *pNode1, const void *pNode2)
+{
+	/* We assume here that we never ever get NULL-pointers or similar */
+	return xs_sldb_cmphash((*(t_xs_sldb_node **) pNode1)->md5Hash, (*(t_xs_sldb_node **) pNode2)->md5Hash);
+}
+
+
+/* (Re)create index
+ */
+gint xs_sldb_index(t_xs_sldb * db)
+{
+	t_xs_sldb_node *pCurr;
+	gint i;
+	assert(db);
+
+	/* Free old index */
+	if (db->ppIndex) {
+		g_free(db->ppIndex);
+		db->ppIndex = NULL;
+	}
+
+	/* Get size of db */
+	pCurr = db->pNodes;
+	db->n = 0;
+	while (pCurr) {
+		db->n++;
+		pCurr = pCurr->pNext;
+	}
+
+	/* Check number of nodes */
+	if (db->n > 0) {
+		/* Allocate memory for index-table */
+		db->ppIndex = (t_xs_sldb_node **) g_malloc(sizeof(t_xs_sldb_node *) * db->n);
+		if (!db->ppIndex)
+			return -1;
+
+		/* Get node-pointers to table */
+		i = 0;
+		pCurr = db->pNodes;
+		while (pCurr && (i < db->n)) {
+			db->ppIndex[i++] = pCurr;
+			pCurr = pCurr->pNext;
+		}
+
+		/* Sort the indexes */
+		qsort(db->ppIndex, db->n, sizeof(t_xs_sldb_node *), xs_sldb_cmp);
+	}
+
+	return 0;
+}
+
+
+/* Free a given song-length database
+ */
+void xs_sldb_free(t_xs_sldb * db)
+{
+	t_xs_sldb_node *pCurr, *pNext;
+
+	if (!db)
+		return;
+
+	/* Free the memory allocated for nodes */
+	pCurr = db->pNodes;
+	while (pCurr) {
+		pNext = pCurr->pNext;
+		xs_sldb_node_free(pCurr);
+		pCurr = pNext;
+	}
+
+	db->pNodes = NULL;
+
+	/* Free memory allocated for index */
+	if (db->ppIndex) {
+		g_free(db->ppIndex);
+		db->ppIndex = NULL;
+	}
+
+	/* Free structure */
+	db->n = 0;
+	g_free(db);
+}
+
+
+/* Compute md5hash of given SID-file
+ */
+typedef struct
+{
+	gchar magicID[4];	/* "PSID" / "RSID" magic identifier */
+	guint16 version,	/* Version number */
+	 dataOffset,		/* Start of actual c64 data in file */
+	 loadAddress,		/* Loading address */
+	 initAddress,		/* Initialization address */
+	 playAddress,		/* Play one frame */
+	 nSongs,		/* Number of subsongs */
+	 startSong;		/* Default starting song */
+	guint32 speed;		/* Speed */
+	gchar sidName[32];	/* Descriptive text-fields, ASCIIZ */
+	gchar sidAuthor[32];
+	gchar sidCopyright[32];
+} t_xs_psidv1_header;
+
+
+typedef struct
+{
+	guint16 flags;		/* Flags */
+	guint8 startPage, pageLength;
+	guint16 reserved;
+} t_xs_psidv2_header;
+
+
+static gint xs_get_sid_hash(gchar * pcFilename, t_xs_md5hash hash)
+{
+	FILE *inFile;
+	t_xs_md5state inState;
+	t_xs_psidv1_header psidH;
+	t_xs_psidv2_header psidH2;
+#ifdef XS_BUF_DYNAMIC
+	guint8 *songData;
+#else
+	guint8 songData[XS_SIDBUF_SIZE];
+#endif
+	guint8 ib8[2], i8;
+	gint iIndex, iRes;
+
+	/* Try to open the file */
+	if ((inFile = fopen(pcFilename, "rb")) == NULL)
+		return -1;
+
+	/* Read PSID header in */
+	xs_rd_str(inFile, psidH.magicID, sizeof(psidH.magicID));
+	if ((psidH.magicID[0] != 'P' && psidH.magicID[0] != 'R') ||
+	    (psidH.magicID[1] != 'S') || (psidH.magicID[2] != 'I') || (psidH.magicID[3] != 'D')) {
+		fclose(inFile);
+		return -2;
+	}
+
+	psidH.version = xs_rd_be16(inFile);
+	psidH.dataOffset = xs_rd_be16(inFile);
+	psidH.loadAddress = xs_rd_be16(inFile);
+	psidH.initAddress = xs_rd_be16(inFile);
+	psidH.playAddress = xs_rd_be16(inFile);
+	psidH.nSongs = xs_rd_be16(inFile);
+	psidH.startSong = xs_rd_be16(inFile);
+	psidH.speed = xs_rd_be32(inFile);
+
+	xs_rd_str(inFile, psidH.sidName, sizeof(psidH.sidName));
+	xs_rd_str(inFile, psidH.sidAuthor, sizeof(psidH.sidAuthor));
+	xs_rd_str(inFile, psidH.sidCopyright, sizeof(psidH.sidCopyright));
+
+	/* Check if we need to load PSIDv2NG header ... */
+	if (psidH.version == 2) {
+		/* Yes, we need to */
+		psidH2.flags = xs_rd_be16(inFile);
+		psidH2.startPage = fgetc(inFile);
+		psidH2.pageLength = fgetc(inFile);
+		psidH2.reserved = xs_rd_be16(inFile);
+	}
+#ifdef XS_BUF_DYNAMIC
+	/* Allocate buffer */
+	songData = (guint8 *) g_malloc(XS_SIDBUF_SIZE * sizeof(guint8));
+	if (!songData) {
+		fclose(inFile);
+		return -3;
+	}
+#endif
+
+	/* Read data to buffer */
+	iRes = fread(songData, sizeof(guint8), XS_SIDBUF_SIZE, inFile);
+	fclose(inFile);
+
+	/* Initialize and start MD5-hash calculation */
+	xs_md5_init(&inState);
+	if (psidH.loadAddress == 0) {
+		/* Strip load address (2 first bytes) */
+		xs_md5_append(&inState, &songData[2], iRes - 2);
+	} else {
+		/* Append "as is" */
+		xs_md5_append(&inState, songData, iRes);
+	}
+
+
+#ifdef XS_BUF_DYNAMIC
+	/* Free buffer */
+	g_free(songData);
+#endif
+
+	/* Append header data to hash */
+#define XSADDHASH(QDATAB) { ib8[0] = (QDATAB & 0xff); ib8[1] = (QDATAB >> 8); xs_md5_append(&inState, (guint8 *) &ib8, sizeof(ib8)); }
+
+	XSADDHASH(psidH.initAddress)
+	    XSADDHASH(psidH.playAddress)
+	    XSADDHASH(psidH.nSongs)
+#undef XSADDHASH
+	    /* Append song speed data to hash */
+	    i8 = 0;
+	for (iIndex = 0; (iIndex < psidH.nSongs) && (iIndex < 32); iIndex++) {
+		i8 = (psidH.speed & (1 << iIndex)) ? 60 : 0;
+		xs_md5_append(&inState, &i8, sizeof(i8));
+	}
+
+	/* Rest of songs (more than 32) */
+	for (iIndex = 32; iIndex < psidH.nSongs; iIndex++) {
+		xs_md5_append(&inState, &i8, sizeof(i8));
+	}
+
+
+	/* PSIDv2NG specific */
+	if (psidH.version == 2) {
+		/* SEE SIDPLAY HEADERS FOR INFO */
+		i8 = (psidH2.flags >> 2) & 3;
+		if (i8 == 2)
+			xs_md5_append(&inState, &i8, sizeof(i8));
+	}
+
+	/* Calculate the hash */
+	xs_md5_finish(&inState, hash);
+
+	return 0;
+}
+
+
+/* Get song lengths
+ */
+t_xs_sldb_node *xs_sldb_get(t_xs_sldb * db, gchar * pcFilename)
+{
+	t_xs_sldb_node *pResult;
+	t_xs_md5hash dbHash;
+
+	/* Get the hash and then look up from db */
+	if (xs_get_sid_hash(pcFilename, dbHash) == 0)
+		pResult = xs_sldb_get_node(db, dbHash);
+	else
+		pResult = NULL;
+
+	return pResult;
+}
+
+
+/*
+ * These should be moved out of this module some day ...
+ */
+static t_xs_sldb *xs_sldb_db = NULL;
+XS_MUTEX(xs_sldb_db);
+
+gint xs_songlen_init(void)
+{
+	XS_MUTEX_LOCK(xs_cfg);
+
+	if (!xs_cfg.songlenDBPath) {
+		XS_MUTEX_UNLOCK(xs_cfg);
+		return -1;
+	}
+
+	XS_MUTEX_LOCK(xs_sldb_db);
+
+	/* Check if already initialized */
+	if (xs_sldb_db)
+		xs_sldb_free(xs_sldb_db);
+
+	/* Allocate database */
+	xs_sldb_db = (t_xs_sldb *) g_malloc0(sizeof(t_xs_sldb));
+	if (!xs_sldb_db) {
+		XS_MUTEX_UNLOCK(xs_cfg);
+		XS_MUTEX_UNLOCK(xs_sldb_db);
+		return -2;
+	}
+
+	/* Read the database */
+	if (xs_sldb_read(xs_sldb_db, xs_cfg.songlenDBPath) != 0) {
+		xs_sldb_free(xs_sldb_db);
+		xs_sldb_db = NULL;
+		XS_MUTEX_UNLOCK(xs_cfg);
+		XS_MUTEX_UNLOCK(xs_sldb_db);
+		return -3;
+	}
+
+	/* Create index */
+	if (xs_sldb_index(xs_sldb_db) != 0) {
+		xs_sldb_free(xs_sldb_db);
+		xs_sldb_db = NULL;
+		XS_MUTEX_UNLOCK(xs_cfg);
+		XS_MUTEX_UNLOCK(xs_sldb_db);
+		return -4;
+	}
+
+	XS_MUTEX_UNLOCK(xs_cfg);
+	XS_MUTEX_UNLOCK(xs_sldb_db);
+	return 0;
+}
+
+
+void xs_songlen_close(void)
+{
+	XS_MUTEX_LOCK(xs_sldb_db);
+	xs_sldb_free(xs_sldb_db);
+	xs_sldb_db = NULL;
+	XS_MUTEX_UNLOCK(xs_sldb_db);
+}
+
+
+t_xs_sldb_node *xs_songlen_get(gchar * pcFilename)
+{
+	t_xs_sldb_node *pResult;
+
+	XS_MUTEX_LOCK(xs_sldb_db);
+
+	if (xs_cfg.songlenDBEnable && xs_sldb_db)
+		pResult = xs_sldb_get(xs_sldb_db, pcFilename);
+	else
+		pResult = NULL;
+
+	XS_MUTEX_UNLOCK(xs_sldb_db);
+
+	return pResult;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_length.h	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,46 @@
+#ifndef XS_LENGTH_H
+#define XS_LENGTH_H
+
+#include "xmms-sid.h"
+#include "xs_md5.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Defines and typedefs
+ */
+typedef struct _t_xs_sldb_node {
+	t_xs_md5hash	md5Hash;	/* 128-bit MD5 hash-digest */
+	gint		nLengths;	/* Number of lengths */
+	gint32		sLengths[XS_STIL_MAXENTRY+1];
+					/* Lengths in seconds */
+
+	struct _t_xs_sldb_node *pPrev, *pNext;
+} t_xs_sldb_node;
+
+typedef struct {
+	t_xs_sldb_node	*pNodes,
+			**ppIndex;
+	gint		n;
+} t_xs_sldb;
+
+
+/*
+ * Functions
+ */
+gint			xs_sldb_read(t_xs_sldb *, gchar *);
+gint			xs_sldb_index(t_xs_sldb *);
+void			xs_sldb_free(t_xs_sldb *);
+t_xs_sldb_node *	xs_sldb_get(t_xs_sldb *, gchar *);
+
+
+gint			xs_songlen_init(void);
+void			xs_songlen_close(void);
+t_xs_sldb_node *	xs_songlen_get(gchar *);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* XS_LENGTH_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_md5.c	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,333 @@
+/*
+  Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  L. Peter Deutsch
+  ghost@aladdin.com
+
+
+  Independent implementation of MD5 (RFC 1321).
+
+  This code implements the MD5 Algorithm defined in RFC 1321.
+  It is derived directly from the text of the RFC and not from the
+  reference implementation.
+
+  The original and principal author of md5.c is L. Peter Deutsch
+  <ghost@aladdin.com>.  Other authors are noted in the change history
+  that follows (in reverse chronological order):
+
+  2002-08-25 ccr Edited for integration in XMMS-SID. Removed unnecessary stuff.
+  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+  1999-05-03 lpd Original version.
+ */
+/* Include config.h here, because we don't include xmms-sid.h */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#include "xs_md5.h"
+
+#define T1 0xd76aa478
+#define T2 0xe8c7b756
+#define T3 0x242070db
+#define T4 0xc1bdceee
+#define T5 0xf57c0faf
+#define T6 0x4787c62a
+#define T7 0xa8304613
+#define T8 0xfd469501
+#define T9 0x698098d8
+#define T10 0x8b44f7af
+#define T11 0xffff5bb1
+#define T12 0x895cd7be
+#define T13 0x6b901122
+#define T14 0xfd987193
+#define T15 0xa679438e
+#define T16 0x49b40821
+#define T17 0xf61e2562
+#define T18 0xc040b340
+#define T19 0x265e5a51
+#define T20 0xe9b6c7aa
+#define T21 0xd62f105d
+#define T22 0x02441453
+#define T23 0xd8a1e681
+#define T24 0xe7d3fbc8
+#define T25 0x21e1cde6
+#define T26 0xc33707d6
+#define T27 0xf4d50d87
+#define T28 0x455a14ed
+#define T29 0xa9e3e905
+#define T30 0xfcefa3f8
+#define T31 0x676f02d9
+#define T32 0x8d2a4c8a
+#define T33 0xfffa3942
+#define T34 0x8771f681
+#define T35 0x6d9d6122
+#define T36 0xfde5380c
+#define T37 0xa4beea44
+#define T38 0x4bdecfa9
+#define T39 0xf6bb4b60
+#define T40 0xbebfbc70
+#define T41 0x289b7ec6
+#define T42 0xeaa127fa
+#define T43 0xd4ef3085
+#define T44 0x04881d05
+#define T45 0xd9d4d039
+#define T46 0xe6db99e5
+#define T47 0x1fa27cf8
+#define T48 0xc4ac5665
+#define T49 0xf4292244
+#define T50 0x432aff97
+#define T51 0xab9423a7
+#define T52 0xfc93a039
+#define T53 0x655b59c3
+#define T54 0x8f0ccc92
+#define T55 0xffeff47d
+#define T56 0x85845dd1
+#define T57 0x6fa87e4f
+#define T58 0xfe2ce6e0
+#define T59 0xa3014314
+#define T60 0x4e0811a1
+#define T61 0xf7537e82
+#define T62 0xbd3af235
+#define T63 0x2ad7d2bb
+#define T64 0xeb86d391
+
+
+static void xs_md5_process(t_xs_md5state * pms, const guint8 * data)
+{
+	guint32 a = pms->abcd[0], b = pms->abcd[1], c = pms->abcd[2], d = pms->abcd[3];
+	guint32 t;
+	guint32 X[16];
+	const guint8 *xp = data;
+	gint i;
+
+	for (i = 0; i < 16; ++i, xp += 4)
+		X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+
+
+	/*
+	 * Round 1. Let [abcd k s i] denote the operation
+	 * a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s).
+	 */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + F(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+
+	/* Do the following 16 operations. */
+	SET(a, b, c, d, 0, 7, T1);
+	SET(d, a, b, c, 1, 12, T2);
+	SET(c, d, a, b, 2, 17, T3);
+	SET(b, c, d, a, 3, 22, T4);
+	SET(a, b, c, d, 4, 7, T5);
+	SET(d, a, b, c, 5, 12, T6);
+	SET(c, d, a, b, 6, 17, T7);
+	SET(b, c, d, a, 7, 22, T8);
+	SET(a, b, c, d, 8, 7, T9);
+	SET(d, a, b, c, 9, 12, T10);
+	SET(c, d, a, b, 10, 17, T11);
+	SET(b, c, d, a, 11, 22, T12);
+	SET(a, b, c, d, 12, 7, T13);
+	SET(d, a, b, c, 13, 12, T14);
+	SET(c, d, a, b, 14, 17, T15);
+	SET(b, c, d, a, 15, 22, T16);
+
+#undef SET
+
+	/*
+	 * Round 2. Let [abcd k s i] denote the operation
+	 * a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s).
+	 */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + G(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+
+	/* Do the following 16 operations. */
+	SET(a, b, c, d, 1, 5, T17);
+	SET(d, a, b, c, 6, 9, T18);
+	SET(c, d, a, b, 11, 14, T19);
+	SET(b, c, d, a, 0, 20, T20);
+	SET(a, b, c, d, 5, 5, T21);
+	SET(d, a, b, c, 10, 9, T22);
+	SET(c, d, a, b, 15, 14, T23);
+	SET(b, c, d, a, 4, 20, T24);
+	SET(a, b, c, d, 9, 5, T25);
+	SET(d, a, b, c, 14, 9, T26);
+	SET(c, d, a, b, 3, 14, T27);
+	SET(b, c, d, a, 8, 20, T28);
+	SET(a, b, c, d, 13, 5, T29);
+	SET(d, a, b, c, 2, 9, T30);
+	SET(c, d, a, b, 7, 14, T31);
+	SET(b, c, d, a, 12, 20, T32);
+
+#undef SET
+
+	/*
+	 * Round 3. Let [abcd k s t] denote the operation
+	 * a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s).
+	 */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + H(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+
+	/* Do the following 16 operations. */
+	SET(a, b, c, d, 5, 4, T33);
+	SET(d, a, b, c, 8, 11, T34);
+	SET(c, d, a, b, 11, 16, T35);
+	SET(b, c, d, a, 14, 23, T36);
+	SET(a, b, c, d, 1, 4, T37);
+	SET(d, a, b, c, 4, 11, T38);
+	SET(c, d, a, b, 7, 16, T39);
+	SET(b, c, d, a, 10, 23, T40);
+	SET(a, b, c, d, 13, 4, T41);
+	SET(d, a, b, c, 0, 11, T42);
+	SET(c, d, a, b, 3, 16, T43);
+	SET(b, c, d, a, 6, 23, T44);
+	SET(a, b, c, d, 9, 4, T45);
+	SET(d, a, b, c, 12, 11, T46);
+	SET(c, d, a, b, 15, 16, T47);
+	SET(b, c, d, a, 2, 23, T48);
+
+#undef SET
+
+	/*
+	 * Round 4. Let [abcd k s t] denote the operation
+	 * a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s).
+	 */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + I(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+
+	/* Do the following 16 operations. */
+	SET(a, b, c, d, 0, 6, T49);
+	SET(d, a, b, c, 7, 10, T50);
+	SET(c, d, a, b, 14, 15, T51);
+	SET(b, c, d, a, 5, 21, T52);
+	SET(a, b, c, d, 12, 6, T53);
+	SET(d, a, b, c, 3, 10, T54);
+	SET(c, d, a, b, 10, 15, T55);
+	SET(b, c, d, a, 1, 21, T56);
+	SET(a, b, c, d, 8, 6, T57);
+	SET(d, a, b, c, 15, 10, T58);
+	SET(c, d, a, b, 6, 15, T59);
+	SET(b, c, d, a, 13, 21, T60);
+	SET(a, b, c, d, 4, 6, T61);
+	SET(d, a, b, c, 11, 10, T62);
+	SET(c, d, a, b, 2, 15, T63);
+	SET(b, c, d, a, 9, 21, T64);
+
+#undef SET
+
+	/*
+	 * Then perform the following additions. (That is increment each
+	 * of the four registers by the value it had before this block was started.)
+	 */
+	pms->abcd[0] += a;
+	pms->abcd[1] += b;
+	pms->abcd[2] += c;
+	pms->abcd[3] += d;
+}
+
+
+void xs_md5_init(t_xs_md5state * pms)
+{
+	pms->count[0] = pms->count[1] = 0;
+	pms->abcd[0] = 0x67452301;
+	pms->abcd[1] = 0xefcdab89;
+	pms->abcd[2] = 0x98badcfe;
+	pms->abcd[3] = 0x10325476;
+}
+
+
+void xs_md5_append(t_xs_md5state * pms, const guint8 * data, int nbytes)
+{
+	const guint8 *p = data;
+	gint left = nbytes;
+	gint offset = (pms->count[0] >> 3) & 63;
+	guint32 nbits = (guint32) (nbytes << 3);
+
+	if (nbytes <= 0)
+		return;
+
+	/* Update the message length. */
+	pms->count[1] += nbytes >> 29;
+	pms->count[0] += nbits;
+	if (pms->count[0] < nbits)
+		pms->count[1]++;
+
+	/* Process an initial partial block. */
+	if (offset) {
+		int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+		memcpy(pms->buf + offset, p, copy);
+
+		if (offset + copy < 64)
+			return;
+
+		p += copy;
+		left -= copy;
+		xs_md5_process(pms, pms->buf);
+	}
+
+	/* Process full blocks. */
+	for (; left >= 64; p += 64, left -= 64)
+		xs_md5_process(pms, p);
+
+	/* Process a final partial block. */
+	if (left)
+		memcpy(pms->buf, p, left);
+}
+
+
+void xs_md5_finish(t_xs_md5state * pms, t_xs_md5hash digest)
+{
+	static const guint8 pad[64] = {
+		0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+	};
+
+	guint8 data[8];
+	gint i;
+
+	/* Save the length before padding. */
+	for (i = 0; i < 8; ++i)
+		data[i] = (guint8) (pms->count[i >> 2] >> ((i & 3) << 3));
+
+	/* Pad to 56 bytes mod 64. */
+	xs_md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+
+	/* Append the length. */
+	xs_md5_append(pms, data, 8);
+	for (i = 0; i < XS_MD5HASH_LENGTH; ++i)
+		digest[i] = (guint8) (pms->abcd[i >> 2] >> ((i & 3) << 3));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_md5.h	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,36 @@
+#ifndef XS_MD5_H
+#define XS_MD5_H
+
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Typedefs
+ */
+typedef struct md5_state_s {
+    guint32 count[2];	/* message length in bits, lsw first */
+    guint32 abcd[4];	/* digest buffer */
+    guint8 buf[64];	/* accumulate block */
+} t_xs_md5state;
+
+#define XS_MD5HASH_LENGTH	(16)
+#define XS_MD5HASH_LENGTH_CH	(XS_MD5HASH_LENGTH * 2)
+
+typedef guint8 t_xs_md5hash[XS_MD5HASH_LENGTH];
+
+
+/*
+ * Functions
+ */
+void xs_md5_init(t_xs_md5state *pms);
+void xs_md5_append(t_xs_md5state *pms, const guint8 *data, int nbytes);
+void xs_md5_finish(t_xs_md5state *pms, t_xs_md5hash digest);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* XS_MD5_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_sidplay.h	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,73 @@
+/*
+ * Here comes the really ugly code...
+ * Get all SID-tune information (for all sub-tunes)
+ * including name, length, etc.
+ */
+t_xs_tuneinfo *TFUNCTION(gchar * pcFilename)
+{
+	t_xs_sldb_node *tuneLength = NULL;
+	t_xs_tuneinfo *pResult;
+	TTUNEINFO tuneInfo;
+	TTUNE *testTune;
+	gboolean haveInfo = TRUE;
+	gint i;
+
+	/* Check if the tune exists and is readable */
+	if ((testTune = new TTUNE(pcFilename)) == NULL)
+		return NULL;
+
+	if (!testTune->getStatus()) {
+		delete testTune;
+		return NULL;
+	}
+
+	/* Get general tune information */
+#ifdef _XS_SIDPLAY1_H
+	haveInfo = testTune->getInfo(tuneInfo);
+#endif
+#ifdef _XS_SIDPLAY2_H
+	testTune->getInfo(tuneInfo);
+	haveInfo = TRUE;
+#endif
+
+	/* Get length information (NOTE: Do not free this!) */
+	tuneLength = xs_songlen_get(pcFilename);
+
+	/* Allocate tuneinfo structure */
+	pResult = xs_tuneinfo_new(pcFilename,
+				  tuneInfo.songs, tuneInfo.startSong,
+				  tuneInfo.infoString[0], tuneInfo.infoString[1], tuneInfo.infoString[2],
+				  tuneInfo.loadAddr, tuneInfo.initAddr, tuneInfo.playAddr, tuneInfo.dataFileLen);
+
+	if (!pResult) {
+		delete testTune;
+		return NULL;
+	}
+
+	/* Get information for subtunes */
+	for (i = 0; i < pResult->nsubTunes; i++) {
+		/* Make the title */
+		if (haveInfo) {
+			pResult->subTunes[i].tuneTitle =
+			    xs_make_titlestring(pcFilename, i + 1, pResult->nsubTunes, tuneInfo.sidModel,
+						tuneInfo.formatString, tuneInfo.infoString[0],
+						tuneInfo.infoString[1], tuneInfo.infoString[2]);
+		} else
+			pResult->subTunes[i].tuneTitle = g_strdup(pcFilename);
+
+		/* Get song length */
+		if (tuneLength && (i < tuneLength->nLengths))
+			pResult->subTunes[i].tuneLength = tuneLength->sLengths[i];
+		else
+			pResult->subTunes[i].tuneLength = -1;
+	}
+
+	delete testTune;
+
+	return pResult;
+}
+
+/* Undefine these */
+#undef TFUNCTION
+#undef TTUNEINFO
+#undef TTUNE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_sidplay1.cc	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,342 @@
+/*
+   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
+
+   libSIDPlay v1 support
+
+   Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org>
+   (C) Copyright 1999-2005 Tecnic Software productions (TNSP)
+
+   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 "xmms-sid.h"
+
+#ifdef HAVE_SIDPLAY1
+
+#include "xs_sidplay1.h"
+#include <stdio.h>
+#include "xs_config.h"
+#include "xs_length.h"
+#include "xs_title.h"
+
+#include <sidplay/player.h>
+#include <sidplay/myendian.h>
+#include <sidplay/fformat.h>
+
+
+typedef struct
+{
+	emuEngine *currEng;
+	emuConfig currConfig;
+	sidTune *currTune;
+} t_xs_sidplay1;
+
+
+/* We need to 'export' all this pseudo-C++ crap */
+extern "C"
+{
+
+
+/* Check if we can play the given file
+ */
+gboolean xs_sidplay1_isourfile(gchar * pcFilename)
+{
+	sidTune *testTune = new sidTune(pcFilename);
+
+	if (!testTune) return FALSE;
+
+	if (!testTune->getStatus()) {
+		delete testTune;
+		 return FALSE;
+	}
+
+	delete testTune;
+	return TRUE;
+}
+
+
+/* Initialize SIDPlay1
+ */
+gboolean xs_sidplay1_init(t_xs_status * myStatus)
+{
+	gint tmpFreq;
+	t_xs_sidplay1 *myEngine;
+	assert(myStatus);
+
+	/* Allocate internal structures */
+	myEngine = (t_xs_sidplay1 *) g_malloc0(sizeof(t_xs_sidplay1));
+	if (!myEngine) return FALSE;
+
+	/* Initialize engine */
+	myEngine->currEng = new emuEngine();
+	if (!myEngine->currEng) {
+		XSERR("Could not initialize libSIDPlay1 emulation engine\n");
+		g_free(myEngine);
+		return FALSE;
+	}
+
+	/* Verify endianess */
+	if (!myEngine->currEng->verifyEndianess()) {
+		XSERR("Endianess verification failed\n");
+		delete myEngine->currEng;
+		g_free(myEngine);
+		return FALSE;
+	}
+
+	myStatus->sidEngine = myEngine;
+
+	/* Get current configuration */
+	myEngine->currEng->getConfig(myEngine->currConfig);
+
+	/* Configure channel parameters */
+	switch (myStatus->audioChannels) {
+
+	case XS_CHN_AUTOPAN:
+		myEngine->currConfig.channels = SIDEMU_STEREO;
+		myEngine->currConfig.autoPanning = SIDEMU_CENTEREDAUTOPANNING;
+		myEngine->currConfig.volumeControl = SIDEMU_FULLPANNING;
+		break;
+
+	case XS_CHN_STEREO:
+		myEngine->currConfig.channels = SIDEMU_STEREO;
+		myEngine->currConfig.autoPanning = SIDEMU_NONE;
+		myEngine->currConfig.volumeControl = SIDEMU_NONE;
+		break;
+
+	case XS_CHN_MONO:
+	default:
+		myEngine->currConfig.channels = SIDEMU_MONO;
+		myEngine->currConfig.autoPanning = SIDEMU_NONE;
+		myEngine->currConfig.volumeControl = SIDEMU_NONE;
+		myStatus->audioChannels = XS_CHN_MONO;
+		break;
+	}
+
+
+	/* Memory mode settings */
+	switch (xs_cfg.memoryMode) {
+	case XS_MPU_TRANSPARENT_ROM:
+		myEngine->currConfig.memoryMode = MPU_TRANSPARENT_ROM;
+		break;
+
+	case XS_MPU_PLAYSID_ENVIRONMENT:
+		myEngine->currConfig.memoryMode = MPU_PLAYSID_ENVIRONMENT;
+		break;
+
+	case XS_MPU_BANK_SWITCHING:
+	default:
+		myEngine->currConfig.memoryMode = MPU_BANK_SWITCHING;
+		xs_cfg.memoryMode = XS_MPU_BANK_SWITCHING;
+		break;
+	}
+
+
+	/* Audio parameters sanity checking and setup */
+	myEngine->currConfig.bitsPerSample = myStatus->audioBitsPerSample;
+	tmpFreq = myStatus->audioFrequency;
+
+	if (myStatus->oversampleEnable) {
+		if ((tmpFreq * myStatus->oversampleFactor) > SIDPLAY1_MAX_FREQ) {
+			myStatus->oversampleEnable = FALSE;
+		} else {
+			tmpFreq = (tmpFreq * myStatus->oversampleFactor);
+		}
+	} else {
+		if (tmpFreq > SIDPLAY1_MAX_FREQ)
+			tmpFreq = SIDPLAY1_MAX_FREQ;
+	}
+
+	myEngine->currConfig.frequency = tmpFreq;
+
+	switch (myStatus->audioBitsPerSample) {
+	case XS_RES_8BIT:
+		switch (myStatus->audioFormat) {
+		case FMT_S8:
+			myStatus->audioFormat = FMT_S8;
+			myEngine->currConfig.sampleFormat = SIDEMU_SIGNED_PCM;
+			break;
+
+		case FMT_U8:
+		default:
+			myStatus->audioFormat = FMT_U8;
+			myEngine->currConfig.sampleFormat = SIDEMU_UNSIGNED_PCM;
+			break;
+		}
+		break;
+
+	case XS_RES_16BIT:
+	default:
+		switch (myStatus->audioFormat) {
+		case FMT_U16_NE:
+		case FMT_U16_LE:
+		case FMT_U16_BE:
+			myStatus->audioFormat = FMT_U16_NE;
+			myEngine->currConfig.sampleFormat = SIDEMU_UNSIGNED_PCM;
+			break;
+
+		case FMT_S16_NE:
+		case FMT_S16_LE:
+		case FMT_S16_BE:
+		default:
+			myStatus->audioFormat = FMT_S16_NE;
+			myEngine->currConfig.sampleFormat = SIDEMU_SIGNED_PCM;
+			break;
+		}
+		break;
+	}
+
+	/* Clockspeed settings */
+	switch (xs_cfg.clockSpeed) {
+	case XS_CLOCK_NTSC:
+		myEngine->currConfig.clockSpeed = SIDTUNE_CLOCK_NTSC;
+		break;
+
+	case XS_CLOCK_PAL:
+	default:
+		myEngine->currConfig.clockSpeed = SIDTUNE_CLOCK_PAL;
+		xs_cfg.clockSpeed = XS_CLOCK_PAL;
+		break;
+	}
+
+	myEngine->currConfig.forceSongSpeed = xs_cfg.forceSpeed;
+	
+	
+	/* Configure rest of the emulation */
+	/* if (xs_cfg.forceModel) */
+	myEngine->currConfig.mos8580 = xs_cfg.mos8580;
+	myEngine->currConfig.emulateFilter = xs_cfg.emulateFilters;
+	myEngine->currConfig.filterFs = xs_cfg.filterFs;
+	myEngine->currConfig.filterFm = xs_cfg.filterFm;
+	myEngine->currConfig.filterFt = xs_cfg.filterFt;
+
+
+	/* Now set the emulator configuration */
+	if (!myEngine->currEng->setConfig(myEngine->currConfig)) {
+		XSERR("Emulator engine configuration failed!\n");
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+
+/* Close SIDPlay1 engine
+ */
+void xs_sidplay1_close(t_xs_status * myStatus)
+{
+	t_xs_sidplay1 *myEngine;
+	assert(myStatus);
+
+	myEngine = (t_xs_sidplay1 *) myStatus->sidEngine;
+
+	/* Free internals */
+	if (myEngine->currEng) {
+		delete myEngine->currEng;
+		myEngine->currEng = NULL;
+	}
+
+	g_free(myEngine);
+	myStatus->sidEngine = NULL;
+}
+
+
+/* Initialize current song and sub-tune
+ */
+gboolean xs_sidplay1_initsong(t_xs_status * myStatus)
+{
+	t_xs_sidplay1 *myEngine;
+	assert(myStatus);
+
+	myEngine = (t_xs_sidplay1 *) myStatus->sidEngine;
+	if (!myEngine) return FALSE;
+
+	if (!myEngine->currTune) {
+		XSERR("Tune was NULL\n");
+		return FALSE;
+	}
+
+	if (!myEngine->currTune->getStatus()) {
+		XSERR("Tune status check failed\n");
+		return FALSE;
+	}
+
+	return sidEmuInitializeSong(*myEngine->currEng, *myEngine->currTune, myStatus->currSong);
+}
+
+
+/* Emulate and render audio data to given buffer
+ */
+guint xs_sidplay1_fillbuffer(t_xs_status * myStatus, gchar * audioBuffer, guint audioBufSize)
+{
+	t_xs_sidplay1 *myEngine;
+	assert(myStatus);
+
+	myEngine = (t_xs_sidplay1 *) myStatus->sidEngine;
+	if (!myEngine) return 0;
+
+	sidEmuFillBuffer(*myEngine->currEng, *myEngine->currTune, audioBuffer, audioBufSize);
+
+	return audioBufSize;
+}
+
+
+/* Load a given SID-tune file
+ */
+gboolean xs_sidplay1_loadsid(t_xs_status * myStatus, gchar * pcFilename)
+{
+	t_xs_sidplay1 *myEngine;
+	sidTune *newTune;
+	assert(myStatus);
+
+	myEngine = (t_xs_sidplay1 *) myStatus->sidEngine;
+	if (!myEngine) return FALSE;
+
+	/* Try to load the file/tune */
+	if (!pcFilename) return FALSE;
+
+	newTune = new sidTune(pcFilename);
+	if (!newTune) return FALSE;
+
+	myEngine->currTune = newTune;
+
+	return TRUE;
+}
+
+
+/* Delete INTERNAL information
+ */
+void xs_sidplay1_deletesid(t_xs_status * myStatus)
+{
+	t_xs_sidplay1 *myEngine;
+	assert(myStatus);
+
+	myEngine = (t_xs_sidplay1 *) myStatus->sidEngine;
+	if (!myEngine) return;
+
+	if (myEngine->currTune) {
+		delete myEngine->currTune;
+		myEngine->currTune = NULL;
+	}
+}
+
+
+/* Return song information
+ */
+#define TFUNCTION	xs_sidplay1_getsidinfo
+#define TTUNEINFO	sidTuneInfo
+#define TTUNE		sidTune
+#include "xs_sidplay.h"
+
+}				/* extern "C" */
+#endif				/* HAVE_SIDPLAY1 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_sidplay1.h	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,25 @@
+#ifndef _XS_SIDPLAY1_H
+#define _XS_SIDPLAY1_H
+
+#include "xmms-sid.h"
+
+/* Maximum audio frequency supported by libSIDPlay v1 */
+#define SIDPLAY1_MAX_FREQ	(48000)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+gboolean	xs_sidplay1_isourfile(gchar *);
+void		xs_sidplay1_close(t_xs_status *);
+gboolean	xs_sidplay1_init(t_xs_status *);
+gboolean	xs_sidplay1_initsong(t_xs_status *);
+guint		xs_sidplay1_fillbuffer(t_xs_status *, gchar *, guint);
+gboolean	xs_sidplay1_loadsid(t_xs_status *, gchar *);
+void		xs_sidplay1_deletesid(t_xs_status *);
+t_xs_tuneinfo*	xs_sidplay1_getsidinfo(gchar *);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _XS_SIDPLAY1_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_sidplay2.cc	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,426 @@
+/*
+   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
+
+   libSIDPlay v2 support
+
+   Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org>
+   (C) Copyright 1999-2005 Tecnic Software productions (TNSP)
+
+   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 "xmms-sid.h"
+
+#ifdef HAVE_SIDPLAY2
+
+#include "xs_sidplay2.h"
+#include <stdio.h>
+#include "xs_config.h"
+#include "xs_support.h"
+#include "xs_length.h"
+#include "xs_title.h"
+
+#include <sidplay/sidplay2.h>
+#ifdef HAVE_RESID_BUILDER
+#include <sidplay/builders/resid.h>
+#endif
+#ifdef HAVE_HARDSID_BUILDER
+#include <sidplay/builders/hardsid.h>
+#endif
+
+
+typedef struct
+{
+	sidplay2 *currEng;
+	sidbuilder *currBuilder;
+	sid2_config_t currConfig;
+	SidTune *currTune;
+} t_xs_sidplay2;
+
+
+/* We need to 'export' all this pseudo-C++ crap */
+extern "C"
+{
+
+
+/* Check if we can play the given file
+ */
+gboolean xs_sidplay2_isourfile(gchar * pcFilename)
+{
+	SidTune *testTune = new SidTune(pcFilename);
+
+	if (!testTune) return FALSE;
+
+	if (!testTune->getStatus()) {
+		delete testTune;
+		return FALSE;
+	}
+
+	delete testTune;
+	return TRUE;
+}
+
+
+
+/* Initialize SIDPlay2
+ */
+gboolean xs_sidplay2_init(t_xs_status * myStatus)
+{
+	gint tmpFreq;
+	t_xs_sidplay2 *myEngine;
+	assert(myStatus);
+
+	/* Allocate internal structures */
+	myEngine = (t_xs_sidplay2 *) g_malloc0(sizeof(t_xs_sidplay2));
+	myStatus->sidEngine = myEngine;
+	if (!myEngine) return FALSE;
+
+	/* Initialize the engine */
+	myEngine->currEng = new sidplay2;
+	if (!myEngine->currEng) {
+		XSERR("Could not initialize libSIDPlay2 emulation engine\n");
+		return FALSE;
+	}
+
+	/* Get current configuration */
+	myEngine->currConfig = myEngine->currEng->config();
+
+	/* Configure channels and stuff */
+	switch (myStatus->audioChannels) {
+
+	case XS_CHN_AUTOPAN:
+		myEngine->currConfig.playback = sid2_stereo;
+		break;
+
+	case XS_CHN_STEREO:
+		myEngine->currConfig.playback = sid2_stereo;
+		break;
+
+	case XS_CHN_MONO:
+	default:
+		myEngine->currConfig.playback = sid2_mono;
+		myStatus->audioChannels = XS_CHN_MONO;
+		break;
+	}
+
+
+	/* Memory mode settings */
+	switch (xs_cfg.memoryMode) {
+	case XS_MPU_BANK_SWITCHING:
+		myEngine->currConfig.environment = sid2_envBS;
+		break;
+
+	case XS_MPU_TRANSPARENT_ROM:
+		myEngine->currConfig.environment = sid2_envTP;
+		break;
+
+	case XS_MPU_PLAYSID_ENVIRONMENT:
+		myEngine->currConfig.environment = sid2_envPS;
+		break;
+
+	case XS_MPU_REAL:
+	default:
+		myEngine->currConfig.environment = sid2_envR;
+		xs_cfg.memoryMode = XS_MPU_REAL;
+		break;
+	}
+
+
+	/* Audio parameters sanity checking and setup */
+	myEngine->currConfig.precision = myStatus->audioBitsPerSample;
+	tmpFreq = myStatus->audioFrequency;
+
+	if (myStatus->oversampleEnable)
+		tmpFreq = (tmpFreq * myStatus->oversampleFactor);
+
+	myEngine->currConfig.frequency = tmpFreq;
+
+	switch (myStatus->audioBitsPerSample) {
+	case XS_RES_8BIT:
+		myStatus->audioFormat = FMT_U8;
+		myEngine->currConfig.sampleFormat = SID2_LITTLE_UNSIGNED;
+		break;
+
+	case XS_RES_16BIT:
+	default:
+		switch (myStatus->audioFormat) {
+		case FMT_U16_LE:
+			myEngine->currConfig.sampleFormat = SID2_LITTLE_UNSIGNED;
+			break;
+
+		case FMT_U16_BE:
+			myEngine->currConfig.sampleFormat = SID2_BIG_UNSIGNED;
+			break;
+
+		case FMT_U16_NE:
+#ifdef WORDS_BIGENDIAN
+			myEngine->currConfig.sampleFormat = SID2_BIG_UNSIGNED;
+#else
+			myEngine->currConfig.sampleFormat = SID2_LITTLE_UNSIGNED;
+#endif
+			break;
+
+		case FMT_S16_LE:
+			myEngine->currConfig.sampleFormat = SID2_LITTLE_SIGNED;
+			break;
+
+		case FMT_S16_BE:
+			myEngine->currConfig.sampleFormat = SID2_BIG_SIGNED;
+			break;
+
+		default:
+			myStatus->audioFormat = FMT_S16_NE;
+#ifdef WORDS_BIGENDIAN
+			myEngine->currConfig.sampleFormat = SID2_BIG_SIGNED;
+#else
+			myEngine->currConfig.sampleFormat = SID2_LITTLE_SIGNED;
+#endif
+			break;
+
+		}
+		break;
+	}
+
+	/* Initialize builder object */
+	XSDEBUG("init builder #%i, maxsids=%i\n", xs_cfg.sid2Builder, (myEngine->currEng->info()).maxsids);
+#ifdef HAVE_RESID_BUILDER
+	if (xs_cfg.sid2Builder == XS_BLD_RESID) {
+		ReSIDBuilder *rs = new ReSIDBuilder("ReSID builder");
+		myEngine->currBuilder = (sidbuilder *) rs;
+		if (rs) {
+			/* Builder object created, initialize it */
+			rs->create((myEngine->currEng->info()).maxsids);
+			if (!*rs) {
+				XSERR("rs->create() failed. SIDPlay2 suxx again.\n");
+				return FALSE;
+			}
+
+			rs->filter(xs_cfg.emulateFilters);
+			if (!*rs) {
+				XSERR("rs->filter(%d) failed.\n", xs_cfg.emulateFilters);
+				return FALSE;
+			}
+
+			rs->sampling(tmpFreq);
+			if (!*rs) {
+				XSERR("rs->sampling(%d) failed.\n", tmpFreq);
+				return FALSE;
+			}
+
+			rs->filter((sid_filter_t *) NULL);
+			if (!*rs) {
+				XSERR("rs->filter(NULL) failed.\n");
+				return FALSE;
+			}
+		}
+	}
+#endif
+#ifdef HAVE_HARDSID_BUILDER
+	if (xs_cfg.sid2Builder == XS_BLD_HARDSID) {
+		HardSIDBuilder *hs = new HardSIDBuilder("HardSID builder");
+		myEngine->currBuilder = (sidbuilder *) hs;
+		if (hs) {
+			/* Builder object created, initialize it */
+			hs->create((myEngine->currEng->info()).maxsids);
+			if (!*hs) {
+				XSERR("hs->create() failed. SIDPlay2 suxx again.\n");
+				return FALSE;
+			}
+
+			hs->filter(xs_cfg.emulateFilters);
+			if (!*hs) {
+				XSERR("hs->filter(%d) failed.\n", xs_cfg.emulateFilters);
+				return FALSE;
+			}
+		}
+	}
+#endif
+
+	if (!myEngine->currBuilder) {
+		XSERR("Could not initialize SIDBuilder object.\n");
+		return FALSE;
+	}
+
+	XSDEBUG("%s\n", myEngine->currBuilder->credits());
+
+
+	/* Clockspeed settings */
+	switch (xs_cfg.clockSpeed) {
+	case XS_CLOCK_NTSC:
+		myEngine->currConfig.clockDefault = SID2_CLOCK_NTSC;
+		break;
+
+	case XS_CLOCK_PAL:
+	default:
+		myEngine->currConfig.clockDefault = SID2_CLOCK_PAL;
+		xs_cfg.clockSpeed = XS_CLOCK_PAL;
+		break;
+	}
+
+
+	/* Configure rest of the emulation */
+	myEngine->currConfig.sidEmulation = myEngine->currBuilder;
+	
+	if (xs_cfg.forceSpeed) { 
+		myEngine->currConfig.clockForced = true;
+		myEngine->currConfig.clockSpeed = myEngine->currConfig.clockDefault;
+	} else {
+		myEngine->currConfig.clockForced = false;
+		myEngine->currConfig.clockSpeed = SID2_CLOCK_CORRECT;
+	}
+	
+	if (xs_cfg.sid2OptLevel)
+		myEngine->currConfig.optimisation = 1;
+	else
+		myEngine->currConfig.optimisation = 0;
+
+	if (xs_cfg.mos8580)
+		myEngine->currConfig.sidDefault = SID2_MOS8580;
+	else
+		myEngine->currConfig.sidDefault = SID2_MOS6581;
+
+	if (xs_cfg.forceModel)
+		myEngine->currConfig.sidModel = myEngine->currConfig.sidDefault;
+	else
+		myEngine->currConfig.sidModel = SID2_MODEL_CORRECT;
+
+	myEngine->currConfig.sidSamples = TRUE;	// FIXME FIX ME, make configurable!
+
+
+	/* Now set the emulator configuration */
+	if (myEngine->currEng->config(myEngine->currConfig) < 0) {
+		XSERR("Emulator engine configuration failed!\n");
+		return FALSE;
+	}
+
+	/* Create the sidtune */
+	myEngine->currTune = new SidTune(0);
+	if (!myEngine->currTune) {
+		XSERR("Could not initialize SIDTune object.\n");
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+
+/* Close SIDPlay2 engine
+ */
+void xs_sidplay2_close(t_xs_status * myStatus)
+{
+	t_xs_sidplay2 *myEngine;
+	assert(myStatus);
+
+	myEngine = (t_xs_sidplay2 *) myStatus->sidEngine;
+
+	/* Free internals */
+	if (myEngine->currBuilder) {
+		delete myEngine->currBuilder;
+		myEngine->currBuilder = NULL;
+	}
+
+	if (myEngine->currEng) {
+		delete myEngine->currEng;
+		myEngine->currEng = NULL;
+	}
+
+	if (myEngine->currTune) {
+		delete myEngine->currTune;
+		myEngine->currTune = NULL;
+	}
+
+	xs_sidplay2_deletesid(myStatus);
+
+	g_free(myEngine);
+	myStatus->sidEngine = NULL;
+}
+
+
+/* Initialize current song and sub-tune
+ */
+gboolean xs_sidplay2_initsong(t_xs_status * myStatus)
+{
+	t_xs_sidplay2 *myEngine;
+	assert(myStatus);
+
+	myEngine = (t_xs_sidplay2 *) myStatus->sidEngine;
+	if (!myEngine) return FALSE;
+
+	if (!myEngine->currTune->selectSong(myStatus->currSong)) {
+		XSERR("currTune->selectSong() failed\n");
+		return FALSE;
+	}
+
+	if (myEngine->currEng->load(myEngine->currTune) < 0) {
+		XSERR("currEng->load() failed\n");
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+
+/* Emulate and render audio data to given buffer
+ */
+guint xs_sidplay2_fillbuffer(t_xs_status * myStatus, gchar * audioBuffer, guint audioBufSize)
+{
+	t_xs_sidplay2 *myEngine;
+	assert(myStatus);
+
+	myEngine = (t_xs_sidplay2 *) myStatus->sidEngine;
+	if (!myEngine) return 0;
+
+	return myEngine->currEng->play(audioBuffer, audioBufSize);
+}
+
+
+/* Load a given SID-tune file
+ */
+gboolean xs_sidplay2_loadsid(t_xs_status * myStatus, gchar * pcFilename)
+{
+	t_xs_sidplay2 *myEngine;
+	assert(myStatus);
+
+	myEngine = (t_xs_sidplay2 *) myStatus->sidEngine;
+	if (!myEngine) return FALSE;
+
+	/* Try to get the tune */
+	if (!pcFilename) return FALSE;
+
+	if (!myEngine->currTune->load(pcFilename))
+		return FALSE;
+
+	return TRUE;
+}
+
+
+/* Delete INTERNAL information
+ */
+void xs_sidplay2_deletesid(t_xs_status * myStatus)
+{
+	assert(myStatus);
+
+	/* With the current scheme of handling sidtune-loading, we don't do anything here. */
+}
+
+
+/* Return song information
+ */
+#define TFUNCTION	xs_sidplay2_getsidinfo
+#define TTUNEINFO	SidTuneInfo
+#define TTUNE		SidTune
+#include "xs_sidplay.h"
+
+}				/* extern "C" */
+#endif				/* HAVE_SIDPLAY2 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_sidplay2.h	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,22 @@
+#ifndef _XS_SIDPLAY2_H
+#define _XS_SIDPLAY2_H
+
+#include "xmms-sid.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+gboolean	xs_sidplay2_isourfile(gchar *);
+void		xs_sidplay2_close(t_xs_status *);
+gboolean	xs_sidplay2_init(t_xs_status *);
+gboolean	xs_sidplay2_initsong(t_xs_status *);
+guint		xs_sidplay2_fillbuffer(t_xs_status *, gchar *, guint);
+gboolean	xs_sidplay2_loadsid(t_xs_status *, gchar *);
+void		xs_sidplay2_deletesid(t_xs_status *);
+t_xs_tuneinfo*	xs_sidplay2_getsidinfo(gchar *);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _XS_SIDPLAY2_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_stil.c	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,461 @@
+/*  
+   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
+
+   STIL-database handling functions
+   
+   Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org>
+   (C) Copyright 1999-2005 Tecnic Software productions (TNSP)
+
+   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 "xs_stil.h"
+#include "xs_support.h"
+#include "xs_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+
+/* Database handling functions
+ */
+static t_xs_stil_node *xs_stildb_node_new(gchar * pcFilename)
+{
+	t_xs_stil_node *pResult;
+
+	/* Allocate memory for new node */
+	pResult = (t_xs_stil_node *) g_malloc0(sizeof(t_xs_stil_node));
+	if (!pResult)
+		return NULL;
+
+	pResult->pcFilename = g_strdup(pcFilename);
+	if (!pResult->pcFilename) {
+		g_free(pResult);
+		return NULL;
+	}
+
+	return pResult;
+}
+
+
+static void xs_stildb_node_free(t_xs_stil_node * pNode)
+{
+	gint i;
+
+	if (pNode) {
+		/* Free subtune information */
+		for (i = 0; i <= XS_STIL_MAXENTRY; i++) {
+			g_free(pNode->subTunes[i].pName);
+			g_free(pNode->subTunes[i].pAuthor);
+			g_free(pNode->subTunes[i].pInfo);
+		}
+
+		g_free(pNode->pcFilename);
+		g_free(pNode);
+	}
+}
+
+
+/* Insert given node to db linked list
+ */
+static void xs_stildb_node_insert(t_xs_stildb * db, t_xs_stil_node * pNode)
+{
+	assert(db);
+
+	if (db->pNodes) {
+		/* The first node's pPrev points to last node */
+		LPREV = db->pNodes->pPrev;	/* New node's prev = Previous last node */
+		db->pNodes->pPrev->pNext = pNode;	/* Previous last node's next = New node */
+		db->pNodes->pPrev = pNode;	/* New last node = New node */
+		LNEXT = NULL;	/* But next is NULL! */
+	} else {
+		db->pNodes = pNode;	/* First node ... */
+		LPREV = pNode;	/* ... it's also last */
+		LNEXT = NULL;	/* But next is NULL! */
+	}
+}
+
+
+/* Read database (additively) to given db-structure
+ */
+#define XS_STILDB_MULTI if (isMulti) { isMulti = FALSE; xs_pstrcat(&(tmpNode->subTunes[subEntry].pInfo), "\n"); }
+
+
+gint xs_stildb_read(t_xs_stildb * db, gchar * dbFilename)
+{
+	FILE *inFile;
+	gchar inLine[XS_BUF_SIZE + 16];	/* Since we add some chars here and there */
+	guint lineNum, linePos, eolPos;
+	t_xs_stil_node *tmpNode;
+	gboolean isError, isMulti;
+	gint subEntry;
+	assert(db);
+
+	/* Try to open the file */
+	if ((inFile = fopen(dbFilename, "ra")) == NULL) {
+		XSERR("Could not open STILDB '%s'\n", dbFilename);
+		return -1;
+	}
+
+	/* Read and parse the data */
+	lineNum = 0;
+	isError = FALSE;
+	isMulti = FALSE;
+	tmpNode = NULL;
+	subEntry = 0;
+
+	while (!feof(inFile) && !isError) {
+		fgets(inLine, XS_BUF_SIZE, inFile);
+		inLine[XS_BUF_SIZE - 1] = 0;
+		linePos = eolPos = 0;
+		xs_findeol(inLine, &eolPos);
+		inLine[eolPos] = 0;
+		lineNum++;
+
+		switch (inLine[0]) {
+		case '/':
+			/* Check if we are already parsing entry */
+			isMulti = FALSE;
+			if (tmpNode) {
+				XSERR("New entry ('%s') before end of current ('%s')! Possibly malformed STIL-file!\n",
+				      inLine, tmpNode->pcFilename);
+
+				xs_stildb_node_free(tmpNode);
+			}
+
+			/* A new node */
+			subEntry = 0;
+			tmpNode = xs_stildb_node_new(inLine);
+			if (!tmpNode) {
+				/* Allocation failed */
+				XSERR("Could not allocate new STILdb-node for '%s'!\n", inLine);
+				isError = TRUE;
+			}
+			break;
+
+		case '(':
+			/* A new sub-entry */
+			isMulti = FALSE;
+			linePos++;
+			if (inLine[linePos] == '#') {
+				linePos++;
+				if (inLine[linePos]) {
+					xs_findnum(inLine, &linePos);
+					inLine[linePos] = 0;
+					subEntry = atol(&inLine[2]);
+
+					/* Sanity check */
+					if ((subEntry < 1) || (subEntry > XS_STIL_MAXENTRY)) {
+						XSERR("Number of subEntry (%i) for '%s' is invalid\n", subEntry,
+						      tmpNode->pcFilename);
+						subEntry = 0;
+					}
+				}
+			}
+
+			break;
+
+		case 0:
+		case '#':
+		case '\n':
+		case '\r':
+			/* End of entry/field */
+			isMulti = FALSE;
+			if (tmpNode) {
+				/* Insert to database */
+				xs_stildb_node_insert(db, tmpNode);
+				tmpNode = NULL;
+			}
+			break;
+
+		default:
+			/* Check if we are parsing an entry */
+			if (!tmpNode) {
+				XSERR("Entry data encountered outside of entry!\n");
+				break;
+			}
+
+			/* Some other type */
+			if (strncmp(inLine, "   NAME:", 8) == 0) {
+				XS_STILDB_MULTI g_free(tmpNode->subTunes[subEntry].pName);
+				tmpNode->subTunes[subEntry].pName = g_strdup(&inLine[9]);
+			} else if (strncmp(inLine, " AUTHOR:", 8) == 0) {
+				XS_STILDB_MULTI g_free(tmpNode->subTunes[subEntry].pAuthor);
+				tmpNode->subTunes[subEntry].pAuthor = g_strdup(&inLine[9]);
+			} else if (strncmp(inLine, "  TITLE:", 8) == 0) {
+				XS_STILDB_MULTI inLine[eolPos++] = '\n';
+				inLine[eolPos++] = 0;
+				xs_pstrcat(&(tmpNode->subTunes[subEntry].pInfo), &inLine[2]);
+			} else if (strncmp(inLine, " ARTIST:", 8) == 0) {
+				XS_STILDB_MULTI inLine[eolPos++] = '\n';
+				inLine[eolPos++] = 0;
+				xs_pstrcat(&(tmpNode->subTunes[subEntry].pInfo), &inLine[1]);
+			} else if (strncmp(inLine, "COMMENT:", 8) == 0) {
+				XS_STILDB_MULTI isMulti = TRUE;
+				xs_pstrcat(&(tmpNode->subTunes[subEntry].pInfo), inLine);
+			} else if (strncmp(inLine, "        ", 8) == 0) {
+				xs_pstrcat(&(tmpNode->subTunes[subEntry].pInfo), &inLine[8]);
+			}
+			break;
+		}
+
+	}			/* while */
+
+	/* Check if there is one remaining node */
+	if (tmpNode)
+		xs_stildb_node_insert(db, tmpNode);
+
+	/* Close the file */
+	fclose(inFile);
+
+	return 0;
+}
+
+
+/* Compare two nodes
+ */
+static gint xs_stildb_cmp(const void *pNode1, const void *pNode2)
+{
+	/* We assume here that we never ever get NULL-pointers or similar */
+	return strcmp((*(t_xs_stil_node **) pNode1)->pcFilename, (*(t_xs_stil_node **) pNode2)->pcFilename);
+}
+
+
+/* (Re)create index
+ */
+gint xs_stildb_index(t_xs_stildb * db)
+{
+	t_xs_stil_node *pCurr;
+	gint i;
+
+	/* Free old index */
+	if (db->ppIndex) {
+		g_free(db->ppIndex);
+		db->ppIndex = NULL;
+	}
+
+	/* Get size of db */
+	pCurr = db->pNodes;
+	db->n = 0;
+	while (pCurr) {
+		db->n++;
+		pCurr = pCurr->pNext;
+	}
+
+	/* Check number of nodes */
+	if (db->n > 0) {
+		/* Allocate memory for index-table */
+		db->ppIndex = (t_xs_stil_node **) g_malloc(sizeof(t_xs_stil_node *) * db->n);
+		if (!db->ppIndex)
+			return -1;
+
+		/* Get node-pointers to table */
+		i = 0;
+		pCurr = db->pNodes;
+		while (pCurr && (i < db->n)) {
+			db->ppIndex[i++] = pCurr;
+			pCurr = pCurr->pNext;
+		}
+
+		/* Sort the indexes */
+		qsort(db->ppIndex, db->n, sizeof(t_xs_stil_node *), xs_stildb_cmp);
+	}
+
+	return 0;
+}
+
+/* Free a given STIL database
+ */
+void xs_stildb_free(t_xs_stildb * db)
+{
+	t_xs_stil_node *pCurr, *pNext;
+
+	if (!db)
+		return;
+
+	/* Free the memory allocated for nodes */
+	pCurr = db->pNodes;
+	while (pCurr) {
+		pNext = pCurr->pNext;
+		xs_stildb_node_free(pCurr);
+		pCurr = pNext;
+	}
+
+	db->pNodes = NULL;
+
+	/* Free memory allocated for index */
+	if (db->ppIndex) {
+		g_free(db->ppIndex);
+		db->ppIndex = NULL;
+	}
+
+	/* Free structure */
+	db->n = 0;
+	g_free(db);
+}
+
+
+/* Get STIL information node from database
+ */
+static t_xs_stil_node *xs_stildb_get_node(t_xs_stildb * db, gchar * pcFilename)
+{
+	gint iStartNode, iEndNode, iQNode, r, i;
+	gboolean iFound;
+	t_xs_stil_node *pResult;
+
+	/* Check the database pointers */
+	if (!db || !db->pNodes || !db->ppIndex)
+		return NULL;
+
+	/* Look-up via index using binary search */
+	pResult = NULL;
+	iStartNode = 0;
+	iEndNode = (db->n - 1);
+	iQNode = (iEndNode / 2);
+	iFound = FALSE;
+
+	while ((!iFound) && ((iEndNode - iStartNode) > XS_BIN_BAILOUT)) {
+		r = strcmp(pcFilename, db->ppIndex[iQNode]->pcFilename);
+		if (r < 0) {
+			/* Hash was in the <- LEFT side */
+			iEndNode = iQNode;
+			iQNode = iStartNode + ((iEndNode - iStartNode) / 2);
+		} else if (r > 0) {
+			/* Hash was in the RIGHT -> side */
+			iStartNode = iQNode;
+			iQNode = iStartNode + ((iEndNode - iStartNode) / 2);
+		} else
+			iFound = TRUE;
+	}
+
+	/* If not found already */
+	if (!iFound) {
+		/* Search the are linearly */
+		iFound = FALSE;
+		i = iStartNode;
+		while ((i <= iEndNode) && (!iFound)) {
+			if (strcmp(pcFilename, db->ppIndex[i]->pcFilename) == 0)
+				iFound = TRUE;
+			else
+				i++;
+		}
+
+		/* Check the result */
+		if (iFound)
+			pResult = db->ppIndex[i];
+
+	} else {
+		/* Found via binary search */
+		pResult = db->ppIndex[iQNode];
+	}
+
+	return pResult;
+}
+
+
+/*
+ * These should be moved out of this module some day ...
+ */
+static t_xs_stildb *xs_stildb_db = NULL;
+XS_MUTEX(xs_stildb_db);
+
+gint xs_stil_init(void)
+{
+	XS_MUTEX_LOCK(xs_cfg);
+
+	if (!xs_cfg.stilDBPath) {
+		XS_MUTEX_UNLOCK(xs_cfg);
+		return -1;
+	}
+
+	XS_MUTEX_LOCK(xs_stildb_db);
+
+	/* Check if already initialized */
+	if (xs_stildb_db)
+		xs_stildb_free(xs_stildb_db);
+
+	/* Allocate database */
+	xs_stildb_db = (t_xs_stildb *) g_malloc0(sizeof(t_xs_stildb));
+	if (!xs_stildb_db) {
+		XS_MUTEX_UNLOCK(xs_cfg);
+		XS_MUTEX_UNLOCK(xs_stildb_db);
+		return -2;
+	}
+
+	/* Read the database */
+	if (xs_stildb_read(xs_stildb_db, xs_cfg.stilDBPath) != 0) {
+		xs_stildb_free(xs_stildb_db);
+		xs_stildb_db = NULL;
+		XS_MUTEX_UNLOCK(xs_cfg);
+		XS_MUTEX_UNLOCK(xs_stildb_db);
+		return -3;
+	}
+
+	/* Create index */
+	if (xs_stildb_index(xs_stildb_db) != 0) {
+		xs_stildb_free(xs_stildb_db);
+		xs_stildb_db = NULL;
+		XS_MUTEX_UNLOCK(xs_cfg);
+		XS_MUTEX_UNLOCK(xs_stildb_db);
+		return -4;
+	}
+
+	XS_MUTEX_UNLOCK(xs_cfg);
+	XS_MUTEX_UNLOCK(xs_stildb_db);
+	return 0;
+}
+
+
+void xs_stil_close(void)
+{
+	XS_MUTEX_LOCK(xs_stildb_db);
+	xs_stildb_free(xs_stildb_db);
+	xs_stildb_db = NULL;
+	XS_MUTEX_UNLOCK(xs_stildb_db);
+}
+
+
+t_xs_stil_node *xs_stil_get(gchar * pcFilename)
+{
+	t_xs_stil_node *pResult;
+	gchar *tmpFilename;
+
+	XS_MUTEX_LOCK(xs_stildb_db);
+	XS_MUTEX_LOCK(xs_cfg);
+
+	if (xs_cfg.stilDBEnable && xs_stildb_db) {
+		if (xs_cfg.hvscPath) {
+			/* Remove postfixed directory separator from HVSC-path */
+			tmpFilename = xs_strrchr(xs_cfg.hvscPath, '/');
+			if (tmpFilename && (tmpFilename[1] == 0))
+				tmpFilename[0] = 0;
+
+			/* Remove HVSC location-prefix from filename */
+			tmpFilename = strstr(pcFilename, xs_cfg.hvscPath);
+			if (tmpFilename)
+				tmpFilename += strlen(xs_cfg.hvscPath);
+			else
+				tmpFilename = pcFilename;
+		} else
+			tmpFilename = pcFilename;
+
+		pResult = xs_stildb_get_node(xs_stildb_db, tmpFilename);
+	} else
+		pResult = NULL;
+
+	XS_MUTEX_UNLOCK(xs_stildb_db);
+	XS_MUTEX_UNLOCK(xs_cfg);
+
+	return pResult;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_stil.h	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,49 @@
+#ifndef XS_STIL_H
+#define XS_STIL_H
+
+#include "xmms-sid.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Defines and typedefs
+ */
+typedef struct {
+	gchar	*pName,
+		*pAuthor,
+		*pInfo;
+} t_xs_stil_subnode;
+
+typedef struct _t_xs_stil_node {
+	gchar			*pcFilename;
+	t_xs_stil_subnode	subTunes[XS_STIL_MAXENTRY+1];
+	struct _t_xs_stil_node	*pPrev, *pNext;
+} t_xs_stil_node;
+
+
+typedef struct {
+	t_xs_stil_node	*pNodes,
+			**ppIndex;
+	gint		n;
+} t_xs_stildb;
+
+
+/*
+ * Functions
+ */
+gint			xs_stildb_read(t_xs_stildb *, gchar *);
+gint			xs_stildb_index(t_xs_stildb *);
+void			xs_stildb_free(t_xs_stildb *);
+t_xs_stil_node *	xs_stildb_get(t_xs_stildb *, gchar *, gchar *);
+
+
+gint			xs_stil_init(void);
+void			xs_stil_close(void);
+t_xs_stil_node *	xs_stil_get(gchar *);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* XS_STIL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_support.c	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,217 @@
+/*  
+   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
+
+   Miscellaneous support functions
+   
+   Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org>
+   (C) Copyright 1999-2005 Tecnic Software productions (TNSP)
+
+   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 "xmms-sid.h"
+#include "xs_support.h"
+#include <ctype.h>
+
+
+/* Bigendian file reading functions
+ */
+guint16 xs_rd_be16(FILE * f)
+{
+	return (((guint16) fgetc(f)) << 8) | ((guint16) fgetc(f));
+}
+
+
+guint32 xs_rd_be32(FILE * f)
+{
+	return (((guint32) fgetc(f)) << 24) |
+	    (((guint32) fgetc(f)) << 16) | (((guint32) fgetc(f)) << 8) | ((guint32) fgetc(f));
+}
+
+
+size_t xs_rd_str(FILE * f, gchar * s, size_t l)
+{
+	return fread(s, sizeof(gchar), l, f);
+}
+
+
+/* Copy a string
+ */
+gchar *xs_strncpy(gchar * pDest, gchar * pSource, size_t n)
+{
+	gchar *s, *d;
+	size_t i;
+
+	/* Check the string pointers */
+	if (!pSource || !pDest)
+		return pDest;
+
+	/* Copy to the destination */
+	i = n;
+	s = pSource;
+	d = pDest;
+	while (*s && (i > 0)) {
+		*(d++) = *(s++);
+		i--;
+	}
+
+	/* Fill rest of space with zeros */
+	while (i > 0) {
+		*(d++) = 0;
+		i--;
+	}
+
+	/* Ensure that last is always zero */
+	pDest[n - 1] = 0;
+
+	return pDest;
+}
+
+
+/* Copy a given string over in *ppResult.
+ */
+gint xs_pstrcpy(gchar ** ppResult, const gchar * pStr)
+{
+	/* Check the string pointers */
+	if (!ppResult || !pStr)
+		return -1;
+
+	/* Allocate memory for destination */
+	if (*ppResult)
+		g_free(*ppResult);
+	*ppResult = (gchar *) g_malloc(strlen(pStr) + 1);
+	if (!*ppResult)
+		return -2;
+
+	/* Copy to the destination */
+	strcpy(*ppResult, pStr);
+
+	return 0;
+}
+
+
+/* Concatenates a given string into string pointed by *ppResult.
+ */
+gint xs_pstrcat(gchar ** ppResult, const gchar * pStr)
+{
+	/* Check the string pointers */
+	if (!ppResult || !pStr)
+		return -1;
+
+	if (*ppResult != NULL) {
+		*ppResult = (gchar *) g_realloc(*ppResult, strlen(*ppResult) + strlen(pStr) + 1);
+		if (*ppResult == NULL)
+			return -1;
+		strcat(*ppResult, pStr);
+	} else {
+		*ppResult = (gchar *) g_malloc(strlen(pStr) + 1);
+		if (*ppResult == NULL)
+			return -1;
+		strcpy(*ppResult, pStr);
+	}
+
+	return 0;
+}
+
+
+/* Concatenate a given string up to given dest size or \n.
+ * If size max is reached, change the end to "..."
+ */
+void xs_pnstrcat(gchar * pDest, size_t iSize, gchar * pStr)
+{
+	size_t i, n;
+	gchar *s, *d;
+
+	d = pDest;
+	i = 0;
+	while (*d && (i < iSize)) {
+		i++;
+		d++;
+	}
+
+	s = pStr;
+	while (*s && (*s != '\n') && (i < iSize)) {
+		*d = *s;
+		d++;
+		s++;
+		i++;
+	}
+
+	*d = 0;
+
+	if (i >= iSize) {
+		i--;
+		d--;
+		n = 3;
+		while ((i > 0) && (n > 0)) {
+			*d = '.';
+			d--;
+			i--;
+			n--;
+		}
+	}
+}
+
+
+/* Locate character in string
+ */
+gchar *xs_strrchr(gchar * pcStr, gchar ch)
+{
+	gchar *lastPos = NULL;
+
+	while (*pcStr) {
+		if (*pcStr == ch)
+			lastPos = pcStr;
+		pcStr++;
+	}
+
+	return lastPos;
+}
+
+
+void xs_findnext(gchar * pcStr, guint * piPos)
+{
+	while (pcStr[*piPos] && isspace(pcStr[*piPos]))
+		(*piPos)++;
+}
+
+
+void xs_findeol(gchar * pcStr, guint * piPos)
+{
+	while (pcStr[*piPos] && (pcStr[*piPos] != '\n') && (pcStr[*piPos] != '\r'))
+		(*piPos)++;
+}
+
+
+void xs_findnum(gchar * pcStr, guint * piPos)
+{
+	while (pcStr[*piPos] && isdigit(pcStr[*piPos]))
+		(*piPos)++;
+}
+
+
+#ifndef HAVE_MEMSET
+void *xs_memset(void *p, int c, size_t n)
+{
+	gchar *dp;
+
+	dp = (gchar *) p;
+	while (n--) {
+		*dp = (gchar) c;
+		n--;
+	}
+
+	return p;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_support.h	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,48 @@
+#ifndef XS_SUPPORT_H
+#define XS_SUPPORT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "xmms-sid.h"
+#include <stdio.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+
+
+/*
+ * Functions
+ */
+guint16 xs_rd_be16(FILE *);
+guint32 xs_rd_be32(FILE *);
+size_t	xs_rd_str(FILE *, gchar *, size_t);
+gchar	*xs_strncpy(gchar *, gchar *, size_t);
+gint	xs_pstrcpy(gchar **, const gchar *);
+gint	xs_pstrcat(gchar **, const gchar *);
+void	xs_pnstrcat(gchar *, size_t, gchar *);
+gchar	*xs_strrchr(gchar *, gchar);
+inline 	void xs_findnext(gchar *, guint *);
+inline 	void xs_findeol(gchar *, guint *);
+inline	void xs_findnum(gchar *, guint *);
+
+#ifdef HAVE_MEMSET
+#define	xs_memset memset
+#else
+void	*xs_memset(void *, int, size_t);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* XS_SUPPORT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_title.c	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,184 @@
+/*  
+   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
+
+   Titlestring handling
+   
+   Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org>
+   (C) Copyright 1999-2005 Tecnic Software productions (TNSP)
+
+   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 "xs_title.h"
+#include "xs_support.h"
+#include "xs_config.h"
+#include "libaudacious/titlestring.h"
+
+
+/*
+ * Create a title string based on given information and settings.
+ */
+#define VPUTCH(MCH)	\
+if (iIndex < XS_BUF_SIZE) tmpBuf[iIndex++] = MCH;
+#define VPUTSTR(MSTR) {						\
+	if (MSTR) {						\
+		if ((iIndex + strlen(MSTR) + 1) < XS_BUF_SIZE) {	\
+			strcpy(&tmpBuf[iIndex], MSTR);		\
+			iIndex += strlen(MSTR); 		\
+			} else					\
+			iIndex = XS_BUF_SIZE;			\
+		}						\
+	}
+
+
+gchar *xs_make_titlestring(gchar * pcFilename, gint iSubTune, gint nSubTunes, gint iSidModel,
+			   const gchar * formatString, const gchar * infoString0,
+			   const gchar * infoString1, const gchar * infoString2)
+{
+	gchar *tmpFilename, *tmpFilePath, *tmpFileExt, *pcStr, *pcResult, tmpStr[XS_BUF_SIZE], tmpBuf[XS_BUF_SIZE];
+	gint iIndex;
+#ifdef HAVE_XMMSEXTRA
+	TitleInput *ptInput;
+#endif
+
+	/* Split the filename into path */
+	tmpFilePath = g_strdup(pcFilename);
+	tmpFilename = xs_strrchr(tmpFilePath, '/');
+	if (tmpFilename)
+		tmpFilename[1] = 0;
+
+	/* Filename */
+	tmpFilename = xs_strrchr(pcFilename, '/');
+	if (tmpFilename)
+		tmpFilename = g_strdup(tmpFilename + 1);
+	else
+		tmpFilename = g_strdup(pcFilename);
+
+	tmpFileExt = xs_strrchr(tmpFilename, '.');
+	tmpFileExt[0] = 0;
+
+	/* Extension */
+	tmpFileExt = xs_strrchr(pcFilename, '.');
+
+
+#ifdef HAVE_XMMSEXTRA
+	/* Check if the titles are overridden or not */
+	if (!xs_cfg.titleOverride) {
+		/* Use generic XMMS titles */
+		/* XMMS_NEW_TITLEINPUT(ptInput);
+		 * We duplicate and add typecast to the code here due to XMMS's braindead headers
+		 */
+		ptInput = (TitleInput *) g_malloc0(sizeof(TitleInput));
+		ptInput->__size = XMMS_TITLEINPUT_SIZE;
+		ptInput->__version = XMMS_TITLEINPUT_VERSION;
+
+		/* Create the input fields */
+		ptInput->file_name = tmpFilename;
+		ptInput->file_ext = tmpFileExt;
+		ptInput->file_path = tmpFilePath;
+
+		ptInput->track_name = g_strdup(infoString0);
+		ptInput->track_number = iSubTune;
+		ptInput->album_name = NULL;
+		ptInput->performer = g_strdup(infoString1);
+		ptInput->date = g_strdup((iSidModel == XS_SIDMODEL_6581) ? "SID6581" : "SID8580");
+
+		ptInput->year = 0;
+		ptInput->genre = g_strdup("SID-tune");
+		ptInput->comment = g_strdup(infoString2);
+
+		/* Create the string */
+		pcResult = xmms_get_titlestring(xmms_get_gentitle_format(), ptInput);
+
+		/* Dispose all allocated memory */
+		g_free(ptInput->track_name);
+		g_free(ptInput->performer);
+		g_free(ptInput->comment);
+		g_free(ptInput->date);
+		g_free(ptInput->genre);
+		g_free(ptInput);
+	} else
+#endif
+	{
+		/* Create the string */
+		pcStr = xs_cfg.titleFormat;
+		iIndex = 0;
+		while (*pcStr && (iIndex < XS_BUF_SIZE)) {
+			if (*pcStr == '%') {
+				pcStr++;
+				switch (*pcStr) {
+				case '%':
+					VPUTCH('%');
+					break;
+				case 'f':
+					VPUTSTR(tmpFilename);
+					break;
+				case 'F':
+					VPUTSTR(tmpFilePath);
+					break;
+				case 'e':
+					VPUTSTR(tmpFileExt);
+					break;
+				case 'p':
+					VPUTSTR(infoString1);
+					break;
+				case 't':
+					VPUTSTR(infoString0);
+					break;
+				case 'c':
+					VPUTSTR(infoString2);
+					break;
+				case 's':
+					VPUTSTR(formatString);
+					break;
+				case 'm':
+					switch (iSidModel) {
+					case XS_SIDMODEL_6581:
+						VPUTSTR("6581");
+						break;
+					case XS_SIDMODEL_8580:
+						VPUTSTR("8580");
+						break;
+					default:
+						VPUTSTR("Unknown");
+						break;
+					}
+					break;
+				case 'n':
+					snprintf(tmpStr, XS_BUF_SIZE, "%i", iSubTune);
+					VPUTSTR(tmpStr);
+					break;
+				case 'N':
+					snprintf(tmpStr, XS_BUF_SIZE, "%i", nSubTunes);
+					VPUTSTR(tmpStr);
+					break;
+				}
+			} else {
+				VPUTCH(*pcStr);
+			}
+			pcStr++;
+		}
+
+		tmpBuf[iIndex] = 0;
+
+		/* Make resulting string */
+		pcResult = g_strdup(tmpBuf);
+	}
+
+	/* Free temporary strings */
+	g_free(tmpFilename);
+	g_free(tmpFilePath);
+
+	return pcResult;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/sid/xs_title.h	Thu Dec 08 15:12:12 2005 -0800
@@ -0,0 +1,18 @@
+#ifndef XS_TITLE_H
+#define XS_TITLE_H
+
+#include "xmms-sid.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Functions
+ */
+gchar *xs_make_titlestring(gchar *, gint, gint, gint, const gchar *, const gchar *, const gchar *, const gchar *);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* XS_TITLE_H */
--- a/configure.ac	Thu Dec 08 13:29:31 2005 -0800
+++ b/configure.ac	Thu Dec 08 15:12:12 2005 -0800
@@ -428,6 +428,19 @@
 AM_CONDITIONAL(ENABLE_CROSSFADE, test "$enable_crossfade" = "yes")
 AM_CONDITIONAL(HAVE_LIBSAMPLERATE, test "$have_libsamplerate" = "yes")
 
+dnl *** sid
+AC_ARG_ENABLE( sid,
+[  --disable-sid           disable sid input plugin [default=enabled]],,
+                enable_sid="yes")
+
+if test "x$enable_sid" = xyes; then
+        AM_PATH_SIDPLAY(have_sidplay=yes, have_sidplay=no)
+else
+        AC_MSG_RESULT([*** sid plugin disabled per user request ***])
+        have_sidplay=no
+fi
+AM_CONDITIONAL(HAVE_SIDPLAY,test "x$have_sidplay" = xyes)
+
 dnl *** OSS output
 
 AC_ARG_ENABLE(oss,
@@ -722,6 +735,7 @@
         Plugins/Input/wav/Makefile
 	Plugins/Input/flac/Makefile
 	Plugins/Input/flac/plugin_common/Makefile
+	Plugins/Input/sid/Makefile
 	Plugins/Input/console/Makefile
 	Plugins/Input/wma/Makefile
 	Plugins/Input/wma/libffwma/Makefile
@@ -784,6 +798,7 @@
 echo "  Tone Generator:                         yes"
 echo "  Ogg Vorbis (vorbis):                    $have_oggvorbis"
 echo "  FLAC:                                   $have_flac"
+echo "  SID:                                    $have_sidplay"
 echo "  Game Music:                             yes"
 echo ""
 echo "  General"