Mercurial > audlegacy
changeset 1387:b0590e16329f trunk
[svn] import amidi-plug 0.5
line wrap: on
line diff
--- a/ChangeLog Mon Jul 10 04:42:53 2006 -0700 +++ b/ChangeLog Mon Jul 10 04:52:51 2006 -0700 @@ -1,3 +1,12 @@ +2006-07-10 11:42:53 +0000 William Pitcock <nenolod@nenolod.net> + revision [1686] + - disconnect mms code + + + Changes: Modified: + +3 -0 trunk/Plugins/Input/wma/libffwma/allformats.c + + 2006-07-10 11:39:43 +0000 William Pitcock <nenolod@nenolod.net> revision [1684] - vast improvements to the songchange plugin
--- a/Plugins/Input/amidi-plug/Makefile.in Mon Jul 10 04:42:53 2006 -0700 +++ b/Plugins/Input/amidi-plug/Makefile.in Mon Jul 10 04:52:51 2006 -0700 @@ -2,19 +2,24 @@ include ../../../mk/objective.mk OBJECTIVE_LIBS = libamidi-plug.so +SUBDIRS = pcfg @AMIDIPLUG_BACKENDS@ -noinst_HEADERS = amidi-plug.h i_seq.h i_midi.h i_configure.h \ - i_fileinfo.h i_utils.h i_common.h +noinst_HEADERS = amidi-plug.h i_backend.h i_midi.h i_midievent.h \ + i_configure.h i_configure-ap.h i_configure-alsa.h \ + i_configure-fluidsynth.h i_configure-dummy.h \ + i_fileinfo.h i_utils.h i_common.h \ + amidi-plug-icon.xpm amidi-plug.logo.xpm \ + amidi-plug.midiicon.xpm LIBDIR = $(plugindir)/$(INPUT_PLUGIN_DIR) -LIBADD = $(GTK_LIBS) $(ALSA_LIBS) -lpthread -SOURCES = amidi-plug.c i_seq.c i_midi.c \ - i_configure.c i_utils.c i_fileinfo.c - -DATA = amidi-plug.logo.xpm amidi-plug.midiicon.xpm +LIBADD = $(GTK_LIBS) $(GMODULE_LIBS) -lpthread ./pcfg/libpcfg.a +SOURCES = amidi-plug.c i_midi.c i_backend.c \ + i_configure.c i_configure-ap.c i_configure-alsa.c \ + i_configure-fluidsynth.c i_configure-dummy.c \ + i_utils.c i_fileinfo.c OBJECTS = ${SOURCES:.c=.o} -CFLAGS += -fPIC -DPIC $(GTK_CFLAGS) $(ALSA_CFLAGS) \ - -I../../../intl -I../../.. +CFLAGS += -fPIC -DPIC $(GTK_CFLAGS) $(GMODULE_CFLAGS) -DAMIDIPLUGDATADIR=\"$(AMIDIPLUGDATADIR)\" \ + -I../../../intl -I../../..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/amidi-plug-icon.xpm Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,398 @@ +/* XPM */ +static char * amidi_plug_icon_xpm[] = { +"48 48 347 2", +" c #FFFFFF", +". c #FAFAFA", +"+ c #7E7E7E", +"@ c #414141", +"# c #646464", +"$ c #858585", +"% c #848484", +"& c #828282", +"* c #838383", +"= c #868686", +"- c #878787", +"; c #888888", +"> c #898989", +", c #8A8A8A", +"' c #595959", +") c #4C4C4C", +"! c #ADADAD", +"~ c #F8F8F8", +"{ c #575757", +"] c #090909", +"^ c #040404", +"/ c #000000", +"( c #010101", +"_ c #030303", +": c #050505", +"< c #080808", +"[ c #0C0C0C", +"} c #2B2B28", +"| c #494944", +"1 c #4B4B46", +"2 c #3C3C37", +"3 c #49493F", +"4 c #4C4C41", +"5 c #4F4F44", +"6 c #4B4D46", +"7 c #444A4A", +"8 c #4A4D47", +"9 c #4E4E42", +"0 c #4D4D41", +"a c #43433D", +"b c #4F4F49", +"c c #4D4D47", +"d c #181816", +"e c #060606", +"f c #020202", +"g c #0E0E0E", +"h c #929292", +"i c #515151", +"j c #0A0A0A", +"k c #0D0D0D", +"l c #40403C", +"m c #6E6E66", +"n c #717169", +"o c #7C7C6A", +"p c #CFCFA9", +"q c #D1D1AA", +"r c #D3D3AC", +"s c #C8CAA9", +"t c #AFB8A3", +"u c #B0B9A4", +"v c #C4C8A9", +"w c #D7D7AE", +"x c #D8D8AE", +"y c #D7D7AD", +"z c #727265", +"A c #6C6C63", +"B c #21211F", +"C c #070707", +"D c #8D8D8D", +"E c #3F3F3B", +"F c #63635C", +"G c #65655E", +"H c #7A7A68", +"I c #D4D4AD", +"J c #D6D6AF", +"K c #D8D8B0", +"L c #D9D9B1", +"M c #DADAB2", +"N c #DBDBB2", +"O c #DCDCB2", +"P c #DCDCB3", +"Q c #DDDDB2", +"R c #DCDCB1", +"S c #727263", +"T c #6A6A62", +"U c #696960", +"V c #2F2F2C", +"W c #0B0B0B", +"X c #3D3D39", +"Y c #5B5B55", +"Z c #5E5E57", +"` c #747463", +" . c #C5C5A1", +".. c #C7C7A2", +"+. c #C8C8A4", +"@. c #CACAA5", +"#. c #CBCBA6", +"$. c #CCCCA6", +"%. c #CBCBA5", +"&. c #CACAA3", +"*. c #6F6F5F", +"=. c #5A5A53", +"-. c #585851", +";. c #121212", +">. c #181818", +",. c #252523", +"'. c #363631", +"). c #383833", +"!. c #373732", +"~. c #3C3C36", +"{. c #3A3A34", +"]. c #383832", +"^. c #35352F", +"/. c #31312C", +"(. c #1B1B19", +"_. c #111111", +":. c #101010", +"<. c #525252", +"[. c #131313", +"}. c #151515", +"|. c #191919", +"1. c #1A1A1A", +"2. c #171717", +"3. c #0F0F0F", +"4. c #1C1C1C", +"5. c #1D1D1D", +"6. c #1E1E1E", +"7. c #8F8F8F", +"8. c #5F5F5F", +"9. c #323232", +"0. c #272727", +"a. c #313131", +"b. c #1F1F1F", +"c. c #333333", +"d. c #3D3D3D", +"e. c #2C2C2C", +"f. c #383838", +"g. c #474747", +"h. c #404040", +"i. c #141414", +"j. c #444444", +"k. c #242424", +"l. c #5B5B5B", +"m. c #464646", +"n. c #5C5C5C", +"o. c #3E3E3E", +"p. c #717171", +"q. c #212121", +"r. c #353535", +"s. c #5A5A5A", +"t. c #6C6C6C", +"u. c #4A4A4A", +"v. c #202020", +"w. c #737373", +"x. c #5D5D5D", +"y. c #777777", +"z. c #161616", +"A. c #909090", +"B. c #7D7D7D", +"C. c #797979", +"D. c #818181", +"E. c #222222", +"F. c #7F7F7F", +"G. c #2A2A2A", +"H. c #979797", +"I. c #6B6B6B", +"J. c #6D6D6D", +"K. c #F9F9F9", +"L. c #7B7B7B", +"M. c #454545", +"N. c #727272", +"O. c #626262", +"P. c #1B1B1B", +"Q. c #7C7C7C", +"R. c #919191", +"S. c #808080", +"T. c #555555", +"U. c #686868", +"V. c #676767", +"W. c #7A7A7A", +"X. c #959595", +"Y. c #8E8E8E", +"Z. c #2E2E2E", +"`. c #FBFBFB", +" + c #656565", +".+ c #585858", +"++ c #616161", +"@+ c #5E5E5E", +"#+ c #6A6A6A", +"$+ c #696969", +"%+ c #6F6F6F", +"&+ c #989898", +"*+ c #2F2F2F", +"=+ c #363636", +"-+ c #757575", +";+ c #8B8B8B", +">+ c #282828", +",+ c #6E6E6E", +"'+ c #9A9A9A", +")+ c #232323", +"!+ c #787878", +"~+ c #9B9B9B", +"{+ c #707070", +"]+ c #9C9C9C", +"^+ c #303030", +"/+ c #9D9D9D", +"(+ c #A6A6A6", +"_+ c #939393", +":+ c #4F4F4F", +"<+ c #8C8C8C", +"[+ c #949494", +"}+ c #999999", +"|+ c #9E9E9E", +"1+ c #747474", +"2+ c #C9C9C9", +"3+ c #666666", +"4+ c #969696", +"5+ c #9F9F9F", +"6+ c #A0A0A0", +"7+ c #D4D4D4", +"8+ c #A3A3A3", +"9+ c #767676", +"0+ c #A1A1A1", +"a+ c #A5A5A5", +"b+ c #A8A8A8", +"c+ c #A9A9A9", +"d+ c #A7A7A7", +"e+ c #B1B1B1", +"f+ c #DBDBDB", +"g+ c #FCFCFC", +"h+ c #BBBBBB", +"i+ c #B9B9B9", +"j+ c #BEBEBE", +"k+ c #C1C1C1", +"l+ c #C4C4C4", +"m+ c #CACACA", +"n+ c #AAAAAA", +"o+ c #BFBFBF", +"p+ c #D6D6D6", +"q+ c #B2B2B2", +"r+ c #E5E5E5", +"s+ c #E7E7E7", +"t+ c #ACACAC", +"u+ c #EDEDED", +"v+ c #F0F0F0", +"w+ c #F2F2F2", +"x+ c #F3F3F3", +"y+ c #B7B7B7", +"z+ c #F4F4F4", +"A+ c #F5F5F5", +"B+ c #E6E6E6", +"C+ c #D9D9D9", +"D+ c #CECECE", +"E+ c #EBEBEB", +"F+ c #D3D3D3", +"G+ c #636363", +"H+ c #CBCBCB", +"I+ c #565656", +"J+ c #C3C3C3", +"K+ c #AEAEAE", +"L+ c #A2A2A2", +"M+ c #B4B4B4", +"N+ c #C6C6C6", +"O+ c #C7C7C7", +"P+ c #CCCCCC", +"Q+ c #C2C2C2", +"R+ c #E3E3E3", +"S+ c #ABABAB", +"T+ c #B5B5B5", +"U+ c #BCBCBC", +"V+ c #C5C5C5", +"W+ c #CDCDCD", +"X+ c #AFAFAF", +"Y+ c #B3B3B3", +"Z+ c #BABABA", +"`+ c #CFCFCF", +" @ c #D1D1D1", +".@ c #D5D5D5", +"+@ c #D2D2D2", +"@@ c #D7D7D7", +"#@ c #FDFDFD", +"$@ c #BDBDBD", +"%@ c #C0C0C0", +"&@ c #C8C8C8", +"*@ c #D8D8D8", +"=@ c #DFDFDF", +"-@ c #E2E2E2", +";@ c #E9E9E9", +">@ c #ECECEC", +",@ c #EEEEEE", +"'@ c #F6F6F6", +")@ c #F7F7F7", +"!@ c #DADADA", +"~@ c #D0D0D0", +"{@ c #DCDCDC", +"]@ c #FEFEFE", +"^@ c #DDDDDD", +"/@ c #E0E0E0", +"(@ c #E4E4E4", +"_@ c #EAEAEA", +":@ c #E8E8E8", +"<@ c #F1F1F1", +"[@ c #373737", +"}@ c #393939", +"|@ c #3A3A3A", +"1@ c #3B3B3B", +"2@ c #3C3C3C", +"3@ c #3F3F3F", +"4@ c #434343", +"5@ c #494949", +"6@ c #4D4D4D", +"7@ c #545454", +"8@ c #4B4B4B", +"9@ c #FEFCFC", +"0@ c #E3DCDC", +"a@ c #D08585", +"b@ c #CF8484", +"c@ c #D38D8D", +"d@ c #F7EAEA", +"e@ c #EFEFEF", +"f@ c #AD7575", +"g@ c #AC2929", +"h@ c #AD2929", +"i@ c #BA5454", +"j@ c #F1E4E4", +"k@ c #F9F8F8", +"l@ c #B0B0B0", +"m@ c #B6B6B6", +"n@ c #B54242", +"o@ c #AB2424", +"p@ c #AB2525", +"q@ c #AE2D2D", +"r@ c #B8B8B8", +"s@ c #FFFEFE", +"t@ c #D59292", +"u@ c #AB2828", +"v@ c #AB2727", +"w@ c #C16060", +"x@ c #E9DEDE", +"y@ c #E5E1E1", +"z@ c #E5E2E2", +"A@ c #E6E2E2", +"B@ c #CCB0B0", +"C@ c #BF9090", +"D@ c #C09191", +"E@ c #D0BBBB", +"F@ c #E1E1E1", +" . + @ # $ $ $ $ $ % & * * % $ = = - $ = = $ * % % % $ $ $ = - - ; - - ; > > > , ' ) ! ", +" ~ { ] ^ / / / / ( ( _ : < [ } | 1 2 3 4 5 6 7 7 8 5 9 0 0 a b c d e ^ f ( ( / / ] g h ", +" ~ i / / / / / / ( f _ e j k l m n o p q r s t u v w x x y z m A B C ^ f ( / / / / _ D ", +" ~ i / / / / / / ( f ^ C j g E F G H I J K L M N O P Q O R S T U V < : f ( / / / / _ D ", +" ~ i / / / / / / ( f ^ C W g X Y Z ` ...+.@.#.$.$.$.$.%.&.*.=.-.} < : _ f ( / / / _ D ", +" ~ i / / / / / ( f f : < j g ;.;.>.,.'.).!.'.~.).'.{.].^./.(._.:.j < e _ f ( / / ( _ D ", +" ~ <.( / / / / / ( / f ^ ( e ] ( k _.[.}.k C |.[ j 1.|.|.>.: ] 2.f [ }./ 3.4.5.6.[.^ 7. ", +" ~ 8._.f [.9.0.a.[./ b._./ 0.:.( c.d.e.f.[ g f.j _.g.d.h.@ e i.j.^ 4.j.f k.l.m.n.o.C 7. ", +" ~ p.q._ r.p.s.t.k./ u.q./ n.v._ w.= x.y.|.|.y.z.6.A.B.C.$ :.1.D.j E.F.C G.H.I.H.J.g D ", +" K.L.6.f M.N.' I.6./ <.5./ O.6.e y.- 8.L.P.|.Q.|.4.A.- N.7.}.3., :.;.D g i.H.w.R.& 1.D ", +" . S.2.( T.N.' U.>./ s.|._ V.P.< W.; U.+ 4.|.& P.>.A.7.p.X.v.j , 5.< D b.e Y.& & A.Z.D ", +" `.L._.( +N..+++i._ @+z.e #+|.W B., $+D.6.|.= b.>.7.X.%+&+Z.C D.*+_ F.=+f L.h -+H.M.Y. ", +" . w.k < J.N.' l._.< @+i.[ #+|.:.D.;+#+$ E.v., >+E.Y.&+,+'+h.)+L.j.2.!+) [ t.~+J.~+8.h ", +" . C.6.b.p.{+n.s.|.i.++4.i.%+q.;.% D t., G.2.Y.9.i.R.~+,+]+T.^+L.@+}.C.$+k {+/+I./++ (+ ", +" `._+:+.+N.t.++y.%+n.B.y.s.% & n.<+Y.,+[+h O.}+H. +]+/+{+|+]+1+]+]+U.~+]+V.]+|+J./+}+2+ ", +" `.]+8.V.w.3+I.!+%+I.+ C.#+= $ #+Y.A.%+4+&+{+~+/+N.|+5+1+5+5+p.|+|+p.]+|+w.}+5+C.R.6+7+ ", +" `.]+@+I.w.8.w.!+U.w.F.-+p.- % %+7.R.p.H.'+-+/+5+-+6+6+1+6+6+1+|+5+C.4+5+* <+5+7.L.6+7+ ", +" `.8+U.9+y.8.W.Q.3+B.* w.L.<+- y.X.H.y.|+0+C.a+(+L.b+c+L.b+b+S.5+d+<+A.d+'+* (+8+% e+f+ ", +" g+h+% c+i+7.j+k+H.l+m+n+o+p+m+q+r+s+t+u+v+e+w+x+y+z+z+i+z+A+l+B+z+C+D+z+E+i+x+v+a+F+E+ ", +" `.5+G+1+-+n.!+W.O.Q.S.,+W.$ F.1+D D p._+4+9+'+'+C.~+~+C.}+H.L.7.[+; D.R.X.{+;+~+I.7.H+ ", +" . 7.' T.<.i <.T.I+' n.@+8.++ + +V.t.J.%+w.N.N.9+1+w.-+1+p.p.-+p.{+Q.,+J.D.t.t.$ -+Q.J+ ", +" `.K+> A.4+&+'+/+5+L+a+d+n+K+e+M+y+h+j+k+J+N+O+2+m+H+P+P+P+H+H+H+m+m+m+m+m+m+m+m+Q+k+R+ ", +" g+M+h [+4+&+~+/+5+L+a+b+S+K+q+T+i+U+o+Q+V+O+2+m+P+P+W+W+W+P+P+P+H+H+m+m+m+m+m+m+m+H+s+ ", +" g+M+h [+H.}+~+/+6+8+(+c+t+X+Y+y+Z+j+k+l+O+2+H+P+W+D+`+`+D+D+W+W+P+H+H+H+H+m+H+H+H+P+s+ ", +" g+y+H.H.H.}+]+5+0+a+b+S+X+Y+y+h+o+J+N+m+P+`+ @F+7+.@.@.@.@7+F+F++@+@+@ @ @ @ @+@@@C+u+ ", +" #@m+Y+y+Z+$@%@Q+V+&@H+D+ @.@*@f+=@-@B+;@>@,@v+w+x+z+A+'@'@)@~ ~ K.K.. . . `.`.g+'@A+. ", +" #@!@H+~@p+C+{@=@-@B+;@>@v+z+)@`.#@]@ ", +" #@m+Y+%@P+`++@7+@@!@^@/@(@s+_@,@w+A+)@K.K.. . . . . `.`.`.`.`.`.`.`.`.`.`.`.`.`.:@-@<@ ", +" . S.m.d.=+[@f.}@f.f.}@|@1@2@d.o.3@3@3@@ 4@m.5@6@<.T..+l.x.x.x.x.n.s..+I+7@<.6@8@{ n.T+ ", +" ~ 7@^ f / / / / / / / / / / / / / / ( f ^ < [ 3.[.z.|.P.5.6.6.5.P.>.}._.g j e _ ^ < 7. ", +" ~ i / / / / / / / / / / / / / / / / / ( _ : < [ g _.[.}.2.2.2.z.i.;.:.k ] e _ f / _ D ", +" ~ i / / / / / / / / / / / / / / / / / ( ( f ^ C j k g :._._._._.3.g W < : _ f ( / _ D ", +" ~ i / / / / / / / / / / / / / / / / / / / ( f ^ : < j W [ [ [ [ W ] C ^ _ f ( / / _ D ", +" ~ .+] ^ / / / / / / / / / / / / / / / / / / / / ( f f f _ _ _ _ f f ( ( / / / / j :.h ", +" `.(+B.y.p.8.i p.p.9+9+9+9+9+9+9+9+9+9+9+9+9+9+L.L.L.L.L.L.L.L.L.Q.F.F.D.* * * * = ; 2+ ", +" ]@e+=@ ", +" '@|+#@ . '@ 9@ ", +" B+t+ ]@!@'@ N+<+{@A+*@]@ F+D R+ s+_+4+t+0@a@b@a@a@a@a@a@a@a@c@d@ ", +" !@y+ >@D.T+e@D n+U+j+C.. `.S+a+k+ K.L+}+o+, f@g@g@g@g@g@g@g@g@h@i@j@k@k@]@ ", +" -@b+)@ W+h+[+{@l@~+~@6+D `.;@S+(+p+ !@m@]@ , n@o@p@p@p@p@p@p@p@q@, , , , , ", +" . D L+p+q+W.r@p+t.}+v+I.r@ (@# d+#@g+b+(@ s@t@u@v@v@v@v@v@v@v@u@w@x@y@z@A@k@ ", +" ,@X+; -+g.$ % N.S+A.t.X+O+R.%+J+`+d+l@]@ B@C@D@D@D@D@D@D@D@D@E@ ", +" x+;@{@2+f+^@(+m+F@'+[+J+{@A.D.L+)@ ", +" K.)@ A+<@`. ", +" ", +" ", +" ", +" "};
--- a/Plugins/Input/amidi-plug/amidi-plug.c Mon Jul 10 04:42:53 2006 -0700 +++ b/Plugins/Input/amidi-plug/amidi-plug.c Mon Jul 10 04:52:51 2006 -0700 @@ -30,20 +30,20 @@ static gint amidiplug_is_our_file( gchar * filename ) { -#ifdef MIDIFILE_PROBE_MAGICBYTES - VFSFile * fp; +#if defined(MIDIFILE_PROBE_MAGICBYTES) + FILE * fp; gchar magic_bytes[4]; - fp = vfs_fopen( filename , "rb" ); + fp = fopen( filename , "rb" ); - if (fp == NULL) - return FALSE; + if ( fp == NULL ) + return FALSE; - vfs_fread( magic_bytes , 1 , 4 , fp ); + fread( magic_bytes , 1 , 4 , fp ); if ( !strncmp( magic_bytes , "MThd" , 4 ) ) { - vfs_fclose( fp ); + fclose( fp ); DEBUGMSG( "MIDI found, %s is a standard midi file\n" , filename ); return TRUE; } @@ -52,16 +52,16 @@ { /* skip the four bytes after RIFF, then read the next four */ - vfs_fseek( fp , 4 , SEEK_CUR ); - vfs_fread( magic_bytes , 1 , 4 , fp ); + fseek( fp , 4 , SEEK_CUR ); + fread( magic_bytes , 1 , 4 , fp ); if ( !strncmp( magic_bytes , "RMID" , 4 ) ) { - vfs_fclose( fp ); + fclose( fp ); DEBUGMSG( "MIDI found, %s is a riff midi file\n" , filename ); return TRUE; } } - vfs_fclose( fp ); + fclose( fp ); #else gchar * ext = strrchr( filename, '.' ); /* check the filename extension */ @@ -78,40 +78,27 @@ { g_log_set_handler(NULL , G_LOG_LEVEL_WARNING , g_log_default_handler , NULL); DEBUGMSG( "init, read configuration\n" ); - /* read configuration */ - i_configure_cfg_read(); + /* read configuration for amidi-plug */ + i_configure_cfg_ap_read(); amidiplug_playing_status = AMIDIPLUG_STOP; + backend.gmodule = NULL; + /* load the backend selected by user */ + i_backend_load( amidiplug_cfg_ap.ap_seq_backend ); } static void amidiplug_cleanup( void ) { + i_backend_unload(); /* unload currently loaded backend */ g_free( amidiplug_ip.description ); } static void amidiplug_configure( void ) { - if ( amidiplug_gui_prefs.config_win ) - { - return; - } - else - { - GSList * wports = NULL; - GSList * scards = NULL; - /* get an updated list of writable ALSA MIDI ports and ALSA-enabled sound cards*/ - DEBUGMSG( "get an updated list of writable ALSA MIDI ports\n" ); - wports = i_seq_port_get_list(); - DEBUGMSG( "get an updated list of ALSA-enabled sound cards\n" ); - scards = i_seq_card_get_list(); - /* display them in our nice config dialog */ - DEBUGMSG( "opening config window\n" ); - i_configure_gui( wports , scards ); - /* free the cards list and the ports list */ - i_seq_card_free_list( scards ); - i_seq_port_free_list( wports ); - } + /* display the nice config dialog */ + DEBUGMSG( "opening config system\n" ); + i_configure_gui(); } @@ -137,6 +124,8 @@ amidiplug_playing_status = AMIDIPLUG_STOP; pthread_mutex_unlock( &amidiplug_playing_mutex ); pthread_join( amidiplug_play_thread , NULL ); + if ( backend.autonomous_audio == FALSE ) + pthread_join( amidiplug_audio_thread , NULL ); DEBUGMSG( "STOP activated (play thread joined)\n" ); } else if ( amidiplug_playing_status == AMIDIPLUG_PAUSE ) @@ -150,10 +139,25 @@ DEBUGMSG( "STOP activated (in error handling, ok)\n" ); pthread_mutex_unlock( &amidiplug_playing_mutex ); } - /* kill the sequencer (while it has been already killed if we come from - pause, it's safe to do anyway since it checks for multiple calls */ - i_seq_off(); - /* free midi data (same as above) */ + + /* kill the sequencer (while it may have been already killed if coming + from pause, it's safe to do anyway since it checks for multiple calls) */ + if ( backend.gmodule != NULL ) + backend.seq_off(); + + /* call seq_stop */ + if ( backend.gmodule != NULL ) + backend.seq_stop(); + + /* close audio if current backend works with output plugin */ + if (( backend.gmodule != NULL ) && ( backend.autonomous_audio == FALSE )) + { + DEBUGMSG( "STOP activated, closing audio output plugin\n" ); + amidiplug_ip.output->buffer_free(); + amidiplug_ip.output->buffer_free(); + amidiplug_ip.output->close_audio(); + } + /* free midi data (if it has not been freed yet) */ i_midi_free( &midifile ); } @@ -171,22 +175,30 @@ pthread_mutex_unlock( &amidiplug_playing_mutex ); pthread_join( amidiplug_play_thread , NULL ); + if ( backend.autonomous_audio == FALSE ) + pthread_join( amidiplug_audio_thread , NULL ); DEBUGMSG( "PAUSE activated (play thread joined)\n" , midifile.playing_tick ); + if ( backend.autonomous_audio == FALSE ) + amidiplug_ip.output->pause(paused); + /* kill the sequencer */ - i_seq_off(); + backend.seq_off(); } else { DEBUGMSG( "PAUSE deactivated, returning to tick %i\n" , midifile.playing_tick ); /* revive the sequencer */ - i_seq_on( 0 , NULL ); + backend.seq_on(); /* re-set initial tempo */ i_midi_setget_tempo( &midifile ); - i_seq_queue_set_tempo( midifile.current_tempo , midifile.ppq ); + backend.seq_queue_tempo( midifile.current_tempo , midifile.ppq ); /* get back to the previous state */ amidiplug_skipto( midifile.playing_tick ); + if ( backend.autonomous_audio == FALSE ) + amidiplug_ip.output->pause(paused); + pthread_mutex_lock( &amidiplug_playing_mutex ); /* play play play! */ DEBUGMSG( "PAUSE deactivated, starting play thread again\n" ); @@ -205,24 +217,30 @@ pthread_mutex_lock( &amidiplug_playing_mutex ); /* this cond is used to avoid race conditions */ while ( amidiplug_playing_status != AMIDIPLUG_PLAY ) - pthread_cond_wait( &amidiplug_playing_cond , &amidiplug_playing_mutex ); + pthread_cond_wait( &amidiplug_playing_cond , &amidiplug_playing_mutex ); amidiplug_playing_status = AMIDIPLUG_PAUSE; pthread_mutex_unlock( &amidiplug_playing_mutex ); pthread_join( amidiplug_play_thread , NULL ); + if ( backend.autonomous_audio == FALSE ) + pthread_join( amidiplug_audio_thread , NULL ); DEBUGMSG( "SEEK requested (time %i), song paused\n" , time ); /* kill the sequencer */ - i_seq_off(); + backend.seq_off(); /* revive the sequencer */ - i_seq_on( 0 , NULL ); + backend.seq_on(); /* re-set initial tempo */ i_midi_setget_tempo( &midifile ); - i_seq_queue_set_tempo( midifile.current_tempo , midifile.ppq ); + backend.seq_queue_tempo( midifile.current_tempo , midifile.ppq ); /* get back to the previous state */ DEBUGMSG( "SEEK requested (time %i), moving to tick %i of %i\n" , time , (gint)((time * 1000000) / midifile.avg_microsec_per_tick) , midifile.max_tick ); midifile.playing_tick = (gint)((time * 1000000) / midifile.avg_microsec_per_tick); amidiplug_skipto( midifile.playing_tick ); + + if ( backend.autonomous_audio == FALSE ) + amidiplug_ip.output->flush(time * 1000); + /* play play play! */ DEBUGMSG( "SEEK done, starting play thread again\n" ); pthread_create(&amidiplug_play_thread, NULL, amidiplug_play_loop, NULL); @@ -231,52 +249,77 @@ static gint amidiplug_get_time( void ) { - gint pt; - pthread_mutex_lock( &amidiplug_playing_mutex ); - if (( amidiplug_playing_status == AMIDIPLUG_PLAY ) || - ( amidiplug_playing_status == AMIDIPLUG_PAUSE )) + if ( backend.autonomous_audio == FALSE ) { - pthread_mutex_unlock( &amidiplug_playing_mutex ); - pthread_mutex_lock(&amidiplug_gettime_mutex); - pt = midifile.playing_tick; - pthread_mutex_unlock(&amidiplug_gettime_mutex); - return (gint)((pt * midifile.avg_microsec_per_tick) / 1000); + pthread_mutex_lock( &amidiplug_playing_mutex ); + if (( amidiplug_playing_status == AMIDIPLUG_PLAY ) || + ( amidiplug_playing_status == AMIDIPLUG_PAUSE ) || + (( amidiplug_playing_status == AMIDIPLUG_STOP ) && ( amidiplug_ip.output->buffer_playing() ))) + { + pthread_mutex_unlock( &amidiplug_playing_mutex ); + return amidiplug_ip.output->output_time(); + } + else if ( amidiplug_playing_status == AMIDIPLUG_STOP ) + { + pthread_mutex_unlock( &amidiplug_playing_mutex ); + DEBUGMSG( "GETTIME on stopped song, returning -1\n" , time ); + return -1; + } + else /* AMIDIPLUG_ERR */ + { + pthread_mutex_unlock( &amidiplug_playing_mutex ); + DEBUGMSG( "GETTIME on halted song (an error occurred?), returning -1 and stopping the player\n" ); + xmms_remote_stop(0); + return -1; + } } - else if ( amidiplug_playing_status == AMIDIPLUG_STOP ) + else { - pthread_mutex_unlock( &amidiplug_playing_mutex ); - DEBUGMSG( "GETTIME on stopped song, returning -1\n" , time ); - return -1; - } - else /* AMIDIPLUG_ERR */ - { - pthread_mutex_unlock( &amidiplug_playing_mutex ); - DEBUGMSG( "GETTIME on halted song (an error occurred?), returning -1 and stopping the player\n" , time ); - xmms_remote_stop(0); - return -1; + gint pt; + pthread_mutex_lock( &amidiplug_playing_mutex ); + if (( amidiplug_playing_status == AMIDIPLUG_PLAY ) || + ( amidiplug_playing_status == AMIDIPLUG_PAUSE )) + { + pthread_mutex_unlock( &amidiplug_playing_mutex ); + pthread_mutex_lock(&amidiplug_gettime_mutex); + pt = midifile.playing_tick; + pthread_mutex_unlock(&amidiplug_gettime_mutex); + return (gint)((pt * midifile.avg_microsec_per_tick) / 1000); + } + else if ( amidiplug_playing_status == AMIDIPLUG_STOP ) + { + pthread_mutex_unlock( &amidiplug_playing_mutex ); + DEBUGMSG( "GETTIME on stopped song, returning -1\n" , time ); + return -1; + } + else /* AMIDIPLUG_ERR */ + { + pthread_mutex_unlock( &amidiplug_playing_mutex ); + DEBUGMSG( "GETTIME on halted song (an error occurred?), returning -1 and stopping the player\n" , time ); + xmms_remote_stop(0); + return -1; + } } } -static void amidiplug_get_volume( gint * l , gint * r ) +static void amidiplug_get_volume( gint * l_p , gint * r_p ) { - gchar mixer_card[10]; - snprintf( mixer_card , 8 , "hw:%i" , amidiplug_cfg.mixer_card_id ); - mixer_card[9] = '\0'; - /* get volume */ - i_seq_mixer_get_volume( l , r , mixer_card , amidiplug_cfg.mixer_control_name , - amidiplug_cfg.mixer_control_id ); + if ( backend.autonomous_audio == TRUE ) + backend.audio_volume_get( l_p , r_p ); + else + amidiplug_ip.output->get_volume( l_p , r_p ); + return; } static void amidiplug_set_volume( gint l , gint r ) { - gchar mixer_card[10]; - snprintf( mixer_card , 8 , "hw:%i" , amidiplug_cfg.mixer_card_id ); - mixer_card[9] = '\0'; - /* set volume */ - i_seq_mixer_set_volume( l , r , mixer_card , amidiplug_cfg.mixer_control_name , - amidiplug_cfg.mixer_control_id ); + if ( backend.autonomous_audio == TRUE ) + backend.audio_volume_set( l , r ); + else + amidiplug_ip.output->set_volume( l , r ); + return; } @@ -286,11 +329,9 @@ *title = G_PATH_GET_BASENAME(filename); /* sure, it's possible to calculate the length of a MIDI file anytime, - but the file must be entirely parsed to calculate it; this could lead - to performance loss, for now it's safer to calculate the length only - right before playing the file */ - - if ( amidiplug_cfg.length_precalc_enable ) + but the file must be entirely parsed to calculate it; this could + lead to a bit of performance loss, so let the user decide here */ + if ( amidiplug_cfg_ap.ap_opts_length_precalc ) { /* let's calculate the midi length, using this nice helper function that will return 0 if a problem occurs and the length can't be calculated */ @@ -313,15 +354,38 @@ static void amidiplug_play( gchar * filename ) { gint port_count = 0; + gint au_samplerate = -1, au_bitdepth = -1, au_channels = -1; + + if ( backend.gmodule == NULL ) + { + g_warning( "No sequencer backend selected\n" ); + i_message_gui( _("AMIDI-Plug - warning") , + _("No sequencer backend has been selected!\nPlease configure AMIDI-Plug before playing.") , + AMIDIPLUG_MESSAGE_WARN , NULL ); + amidiplug_playing_status = AMIDIPLUG_ERR; + return; + } + + /* get information about audio from backend, if available */ + backend.audio_info_get( &au_channels , &au_bitdepth , &au_samplerate ); + DEBUGMSG( "PLAY requested, audio details: channels -> %i , bitdepth -> %i , samplerate -> %i\n" , + au_channels , au_bitdepth , au_samplerate ); + + if ( backend.autonomous_audio == FALSE ) + { + DEBUGMSG( "PLAY requested, opening audio output plugin\n" ); + amidiplug_ip.output->open_audio( FMT_S16_NE , au_samplerate , au_channels ); + } + DEBUGMSG( "PLAY requested, midifile init\n" ); /* midifile init */ i_midi_init( &midifile ); - /* get the number of selected alsa ports */ - port_count = i_util_str_count( amidiplug_cfg.seq_writable_ports , ':' ); + /* get the number of selected ports */ + port_count = backend.seq_get_port_count(); if ( port_count < 1 ) { - g_warning( "No ALSA ports selected\n" ); + g_warning( "No ports selected\n" ); amidiplug_playing_status = AMIDIPLUG_ERR; return; } @@ -362,16 +426,21 @@ if ( !i_midi_setget_tempo( &midifile ) ) WARNANDBREAKANDPLAYERR( "%s: invalid values while setting ppq and tempo\n" , filename ); - DEBUGMSG( "PLAY requested, sequencer init\n" ); + DEBUGMSG( "PLAY requested, sequencer start\n" ); + /* sequencer start */ + if ( !backend.seq_start( filename ) ) + WARNANDBREAKANDPLAYERR( "%s: problem with seq_start, play aborted\n" , filename ); + + DEBUGMSG( "PLAY requested, sequencer on\n" ); /* sequencer on */ - if ( !i_seq_on( 1 , amidiplug_cfg.seq_writable_ports ) ) - WARNANDBREAKANDPLAYERR( "%s: ALSA problem, play aborted\n" , filename ); + if ( !backend.seq_on() ) + WARNANDBREAKANDPLAYERR( "%s: problem with seq_on, play aborted\n" , filename ); DEBUGMSG( "PLAY requested, setting sequencer queue tempo...\n" ); /* set sequencer queue tempo using ppq and tempo (call only after i_midi_setget_tempo) */ - if ( !i_seq_queue_set_tempo( midifile.current_tempo , midifile.ppq ) ) + if ( !backend.seq_queue_tempo( midifile.current_tempo , midifile.ppq ) ) { - i_seq_off(); /* kill the sequencer */ + backend.seq_off(); /* kill the sequencer */ WARNANDBREAKANDPLAYERR( "%s: ALSA queue problem, play aborted\n" , filename ); } @@ -380,7 +449,10 @@ DEBUGMSG( "PLAY requested, song length calculated: %i msec\n" , (gint)(midifile.length / 1000) ); /* our length is in microseconds, but the player wants milliseconds */ - amidiplug_ip.set_info( G_PATH_GET_BASENAME(filename) , (gint)(midifile.length / 1000) , -1 , -1 , -1 ); + amidiplug_ip.set_info( G_PATH_GET_BASENAME(filename) , + (gint)(midifile.length / 1000) , + au_bitdepth * au_samplerate * au_channels / 8 , + au_samplerate , au_channels ); /* play play play! */ DEBUGMSG( "PLAY requested, starting play thread\n" ); @@ -405,8 +477,7 @@ void * amidiplug_play_loop( void * arg ) { - snd_seq_event_t ev; - gint i, p, c; + gint i = 0; gboolean rewind = FALSE; pthread_mutex_lock( &amidiplug_playing_mutex ); @@ -428,14 +499,16 @@ /* initialize current position in each track */ for (i = 0; i < midifile.num_tracks; ++i) midifile.tracks[i].current_event = midifile.tracks[i].first_event; - snd_seq_start_queue(sc.seq, sc.queue, NULL); + backend.seq_queue_start(); + } + + if ( backend.autonomous_audio == FALSE ) + { + pthread_create(&amidiplug_audio_thread, NULL, amidiplug_audio_loop, NULL); } /* common settings for all our events */ - snd_seq_ev_clear(&ev); - ev.queue = sc.queue; - ev.source.port = 0; - ev.flags = SND_SEQ_TIME_STAMP_TICK; + backend.seq_event_init(); DEBUGMSG( "PLAY thread, start the play loop\n" ); for (;;) @@ -471,124 +544,67 @@ /* advance pointer to next event */ event_track->current_event = event->next; + /* consider the midifile.skip_offset */ + event->tick_real = event->tick - midifile.skip_offset; - /* output the event */ - ev.type = event->type; - ev.time.tick = event->tick - midifile.skip_offset; - ev.dest = sc.dest_port[event->port]; - switch (ev.type) + switch (event->type) { case SND_SEQ_EVENT_NOTEON: + backend.seq_event_noteon( event ); + break; case SND_SEQ_EVENT_NOTEOFF: - case SND_SEQ_EVENT_KEYPRESS: - { - snd_seq_ev_set_fixed(&ev); - ev.data.note.channel = event->data.d[0]; - ev.data.note.note = event->data.d[1]; - ev.data.note.velocity = event->data.d[2]; + backend.seq_event_noteoff( event ); break; - } + case SND_SEQ_EVENT_KEYPRESS: + backend.seq_event_keypress( event ); + break; case SND_SEQ_EVENT_CONTROLLER: - { - snd_seq_ev_set_fixed(&ev); - ev.data.control.channel = event->data.d[0]; - ev.data.control.param = event->data.d[1]; - ev.data.control.value = event->data.d[2]; + backend.seq_event_controller( event ); break; - } case SND_SEQ_EVENT_PGMCHANGE: + backend.seq_event_pgmchange( event ); + break; case SND_SEQ_EVENT_CHANPRESS: - { - snd_seq_ev_set_fixed(&ev); - ev.data.control.channel = event->data.d[0]; - ev.data.control.value = event->data.d[1]; + backend.seq_event_chanpress( event ); break; - } case SND_SEQ_EVENT_PITCHBEND: - { - snd_seq_ev_set_fixed(&ev); - ev.data.control.channel = event->data.d[0]; - ev.data.control.value = ((event->data.d[1]) | ((event->data.d[2]) << 7)) - 0x2000; + backend.seq_event_pitchbend( event ); break; - } case SND_SEQ_EVENT_SYSEX: - { - snd_seq_ev_set_variable(&ev, event->data.length, event->sysex); + backend.seq_event_sysex( event ); break; - } case SND_SEQ_EVENT_TEMPO: - { - snd_seq_ev_set_fixed(&ev); - ev.dest.client = SND_SEQ_CLIENT_SYSTEM; - ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER; - ev.data.queue.queue = sc.queue; - ev.data.queue.param.value = event->data.tempo; + backend.seq_event_tempo( event ); DEBUGMSG( "PLAY thread, processing tempo event with value %i on tick %i\n" , event->data.tempo , event->tick ); pthread_mutex_lock(&amidiplug_gettime_mutex); midifile.current_tempo = event->data.tempo; pthread_mutex_unlock(&amidiplug_gettime_mutex); break; - } default: - { - DEBUGMSG( "PLAY thread, encountered invalid event type %i\n" , ev.type ); + DEBUGMSG( "PLAY thread, encountered invalid event type %i\n" , event->type ); break; - } } pthread_mutex_lock(&amidiplug_gettime_mutex); midifile.playing_tick = event->tick; pthread_mutex_unlock(&amidiplug_gettime_mutex); - snd_seq_event_output(sc.seq, &ev); - snd_seq_drain_output(sc.seq); - snd_seq_sync_output_queue(sc.seq); - } - - /* time to shutdown playback! */ - /* send "ALL SOUNDS OFF" to all channels on all ports */ - ev.type = SND_SEQ_EVENT_CONTROLLER; - ev.time.tick = 0; - snd_seq_ev_set_fixed(&ev); - ev.data.control.param = MIDI_CTL_ALL_SOUNDS_OFF; - ev.data.control.value = 0; - for ( p = 0 ; p < sc.dest_port_num ; p++) - { - ev.queue = sc.queue; - ev.dest = sc.dest_port[p]; - - for ( c = 0 ; c < 16 ; c++ ) + if ( backend.autonomous_audio == TRUE ) { - ev.data.control.channel = c; - snd_seq_event_output(sc.seq, &ev); - snd_seq_drain_output(sc.seq); + /* these backends deal with audio production themselves (i.e. ALSA) */ + backend.seq_output( NULL , NULL ); } } - /* schedule queue stop at end of song */ - snd_seq_ev_clear(&ev); - ev.queue = sc.queue; - ev.source.port = 0; - ev.flags = SND_SEQ_TIME_STAMP_TICK; - - snd_seq_ev_set_fixed(&ev); - ev.type = SND_SEQ_EVENT_STOP; - ev.time.tick = midifile.max_tick - midifile.skip_offset; - ev.dest.client = SND_SEQ_CLIENT_SYSTEM; - ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER; - ev.data.queue.queue = sc.queue; - snd_seq_event_output(sc.seq, &ev); - snd_seq_drain_output(sc.seq); - /* snd_seq_sync_output_queue(sc.seq); */ + backend.seq_output_shut( midifile.max_tick , midifile.skip_offset ); pthread_mutex_lock( &amidiplug_playing_mutex ); if ( amidiplug_playing_status != AMIDIPLUG_PAUSE ) { amidiplug_playing_status = AMIDIPLUG_STOP; DEBUGMSG( "PLAY thread, song stopped/ended\n" ); - } pthread_mutex_unlock( &amidiplug_playing_mutex ); @@ -602,7 +618,6 @@ also obtain the correct skip_offset from the playing_tick */ void amidiplug_skipto( gint playing_tick ) { - snd_seq_event_t ev; gint i; /* this check is always made, for safety*/ @@ -614,12 +629,8 @@ midifile.tracks[i].current_event = midifile.tracks[i].first_event; /* common settings for all our events */ - snd_seq_ev_clear(&ev); - ev.queue = sc.queue; - ev.source.port = 0; - ev.flags = SND_SEQ_TIME_STAMP_TICK; - - snd_seq_start_queue(sc.seq, sc.queue, NULL); + backend.seq_event_init(); + backend.seq_queue_start(); DEBUGMSG( "SKIPTO request, starting skipto loop\n" ); for (;;) @@ -657,13 +668,10 @@ /* advance pointer to next event */ event_track->current_event = event->next; + /* set the time tick to 0 */ + event->tick_real = 0; - /* output the event */ - ev.type = event->type; - ev.time.tick = event->tick; - ev.dest = sc.dest_port[event->port]; - - switch (ev.type) + switch (event->type) { /* do nothing for these case SND_SEQ_EVENT_NOTEON: @@ -673,65 +681,32 @@ break; } */ case SND_SEQ_EVENT_CONTROLLER: - { - snd_seq_ev_set_fixed(&ev); - ev.data.control.channel = event->data.d[0]; - ev.data.control.param = event->data.d[1]; - ev.data.control.value = event->data.d[2]; - ev.time.tick = 0; - snd_seq_event_output(sc.seq, &ev); - snd_seq_drain_output(sc.seq); - snd_seq_sync_output_queue(sc.seq); + backend.seq_event_controller( event ); break; - } case SND_SEQ_EVENT_PGMCHANGE: + backend.seq_event_pgmchange( event ); + break; case SND_SEQ_EVENT_CHANPRESS: - { - snd_seq_ev_set_fixed(&ev); - ev.data.control.channel = event->data.d[0]; - ev.data.control.value = event->data.d[1]; - ev.time.tick = 0; - snd_seq_event_output(sc.seq, &ev); - snd_seq_drain_output(sc.seq); - snd_seq_sync_output_queue(sc.seq); + backend.seq_event_chanpress( event ); break; - } case SND_SEQ_EVENT_PITCHBEND: - { - snd_seq_ev_set_fixed(&ev); - ev.data.control.channel = event->data.d[0]; - ev.data.control.value = ((event->data.d[1]) | ((event->data.d[2]) << 7)) - 0x2000; - ev.time.tick = 0; - snd_seq_event_output(sc.seq, &ev); - snd_seq_drain_output(sc.seq); - snd_seq_sync_output_queue(sc.seq); + backend.seq_event_pitchbend( event ); break; - } case SND_SEQ_EVENT_SYSEX: - { - snd_seq_ev_set_variable(&ev, event->data.length, event->sysex); - ev.time.tick = 0; - snd_seq_event_output(sc.seq, &ev); - snd_seq_drain_output(sc.seq); - snd_seq_sync_output_queue(sc.seq); + backend.seq_event_sysex( event ); break; - } case SND_SEQ_EVENT_TEMPO: - { - snd_seq_ev_set_fixed(&ev); - ev.dest.client = SND_SEQ_CLIENT_SYSTEM; - ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER; - ev.data.queue.queue = sc.queue; - ev.data.queue.param.value = event->data.tempo; + backend.seq_event_tempo( event ); pthread_mutex_lock(&amidiplug_gettime_mutex); midifile.current_tempo = event->data.tempo; pthread_mutex_unlock(&amidiplug_gettime_mutex); - ev.time.tick = 0; - snd_seq_event_output(sc.seq, &ev); - snd_seq_drain_output(sc.seq); - snd_seq_sync_output_queue(sc.seq); break; - } + } + + if ( backend.autonomous_audio == TRUE ) + { + /* these backends deal with audio production themselves (i.e. ALSA) */ + backend.seq_output( NULL , NULL ); } } @@ -739,3 +714,28 @@ return; } + + +void * amidiplug_audio_loop( void * arg ) +{ + gboolean going = 1; + gpointer buffer = NULL; + gint buffer_size = 0; + while ( going ) + { + if ( backend.seq_output( &buffer , &buffer_size ) ) + { + while( ( amidiplug_ip.output->buffer_free() < buffer_size ) && ( going == TRUE ) ) + G_USLEEP(10000); + produce_audio( amidiplug_ip.output->written_time() , + FMT_S16_NE , 2 , buffer_size , buffer , &going ); + } + pthread_mutex_lock( &amidiplug_playing_mutex ); + if ( amidiplug_playing_status != AMIDIPLUG_PLAY ) + going = FALSE; + pthread_mutex_unlock( &amidiplug_playing_mutex ); + } + if ( buffer != NULL ) + g_free( buffer ); + pthread_exit(NULL); +}
--- a/Plugins/Input/amidi-plug/amidi-plug.h Mon Jul 10 04:42:53 2006 -0700 +++ b/Plugins/Input/amidi-plug/amidi-plug.h Mon Jul 10 04:52:51 2006 -0700 @@ -28,11 +28,12 @@ #include "i_common.h" #include "audacious/plugin.h" +#include "audacious/output.h" #include "libaudacious/beepctrl.h" #include "libaudacious/vfs.h" #include <pthread.h> +#include "i_backend.h" #include "i_configure.h" -#include "i_seq.h" #include "i_midi.h" #include "i_fileinfo.h" #include "i_utils.h" @@ -45,6 +46,7 @@ static pthread_t amidiplug_play_thread; +static pthread_t amidiplug_audio_thread; static pthread_mutex_t amidiplug_gettime_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t amidiplug_playing_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t amidiplug_playing_cond = PTHREAD_COND_INITIALIZER; @@ -52,25 +54,18 @@ gint amidiplug_playing_status = AMIDIPLUG_STOP; midifile_t midifile; -sequencer_client_t sc = + +amidiplug_sequencer_backend_t backend; + +amidiplug_cfg_ap_t amidiplug_cfg_ap = { - NULL, /* seq */ - 0, /* client_port */ - 0, /* queue */ - NULL, /* dest_port */ - 0 /* dest_port_num */ + NULL, /* ap_seq_backend */ + 0 /* ap_opts_length_precalc */ }; -amidiplug_cfg_t amidiplug_cfg = -{ - NULL, /* seq_writable_ports */ - 0, /* mixer_card_id */ - NULL, /* mixer_control_name */ - 0, /* mixer_control_id */ - 0 /* length_precalc_enable */ -}; void * amidiplug_play_loop( void * ); +void * amidiplug_audio_loop( void * ); void amidiplug_skipto( gint ); static void amidiplug_init( void ); static void amidiplug_cleanup( void ); @@ -112,7 +107,8 @@ NULL, /* set_info_text */ amidiplug_get_song_info, /* get_song_info */ amidiplug_file_info_box, /* file_info_box */ - NULL /* output */ + NULL, /* output */ + NULL /* get_song_tuple */ }; #endif /* !_I_AMIDIPLUG_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/backend-alsa/Makefile.in Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,15 @@ +include ../../../../mk/rules.mk +include ../../../../mk/objective.mk + +noinst_HEADERS = b-alsa.h b-alsa-config.h backend-alsa-icon.xpm + +CFLAGS += -fPIC -DPIC $(GLIB_CFLAGS) $(ALSA_CFLAGS) -I../../../../intl -I../../../.. + +libdir = $(AMIDIPLUGDATADIR) + +OBJECTIVE_LIBS = ap-alsa.so + +LIBADD = $(GLIB_LIBS) $(ALSA_LIBS) ../pcfg/libpcfg.a +SOURCES = b-alsa.c + +OBJECTS = ${SOURCES:.c=.o}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/backend-alsa/b-alsa-config.h Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,35 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#ifndef _B_ALSA_CONFIG_H +#define _B_ALSA_CONFIG_H 1 + + +typedef struct +{ + gchar * alsa_seq_wports; + gint alsa_mixer_card_id; + gchar * alsa_mixer_ctl_name; + gint alsa_mixer_ctl_id; +} +amidiplug_cfg_alsa_t; + + +#endif /* !_B_ALSA_CONFIG_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/backend-alsa/b-alsa.c Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,875 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#include "b-alsa.h" +#include "b-alsa-config.h" + +/* sequencer instance */ +static sequencer_client_t sc; +/* options */ +static amidiplug_cfg_alsa_t amidiplug_cfg_alsa; + + +gint backend_info_get( gchar ** name , gchar ** longname , gchar ** desc , gint * ppos ) +{ + if ( name != NULL ) + *name = g_strdup( "alsa" ); + if ( longname != NULL ) + *longname = g_strdup( "ALSA Backend " AMIDIPLUG_VERSION ); + if ( desc != NULL ) + *desc = g_strdup( _("This backend sends MIDI events to a group of user-chosen " + "ALSA sequencer ports. The ALSA sequencer interface is very " + "versatile, it can provide ports for audio cards hardware " + "synthesizers (i.e. emu10k1) but also for software synths, " + "external devices, etc.\n" + "This backend does not produce audio, MIDI events are handled " + "directly from devices/programs behind the ALSA ports; in example, " + "MIDI events sent to the hardware synth will be directly played.\n" + "Backend written by Giacomo Lozito.") ); + if ( ppos != NULL ) + *ppos = 1; /* preferred position in backend list */ + return 1; +} + + +gint backend_init( void ) +{ + /* read configuration options */ + i_cfg_read(); + + sc.seq = NULL; + sc.client_port = 0; + sc.queue = 0; + sc.dest_port = NULL; + sc.dest_port_num = 0; + sc.queue_tempo = NULL; + sc.is_start = FALSE; + + return 1; +} + +gint backend_cleanup( void ) +{ + /* free configuration options */ + i_cfg_free(); + + return 1; +} + + +gint sequencer_get_port_count( void ) +{ + return i_util_str_count( amidiplug_cfg_alsa.alsa_seq_wports , ':' ); +} + + +gint sequencer_start( gchar * midi_fname ) +{ + sc.is_start = TRUE; + return 1; /* success */ +} + + +gint sequencer_stop( void ) +{ + return 1; /* success */ +} + + +/* activate sequencer client */ +gint sequencer_on( void ) +{ + gchar * wports_str = amidiplug_cfg_alsa.alsa_seq_wports; + + if ( !i_seq_open() ) + { + sc.seq = NULL; + return 0; + } + + if ( !i_seq_port_create() ) + { + i_seq_close(); + sc.seq = NULL; + return 0; + } + + if ( !i_seq_queue_create() ) + { + i_seq_close(); + sc.seq = NULL; + return 0; + } + + if (( sc.is_start == TRUE ) && ( wports_str )) + { + sc.is_start = FALSE; + i_seq_port_wparse( wports_str ); + } + + if ( !i_seq_port_connect() ) + { + i_seq_queue_free(); + i_seq_close(); + sc.seq = NULL; + return 0; + } + + /* success */ + return 1; +} + + +/* shutdown sequencer client */ +gint sequencer_off( void ) +{ + if ( sc.seq ) + { + i_seq_port_disconnect(); + i_seq_queue_free(); + i_seq_close(); + sc.seq = NULL; + /* return 1 here */ + return 1; + } + /* return 2 if it was already freed */ + return 2; +} + + +/* queue set tempo */ +gint sequencer_queue_tempo( gint tempo , gint ppq ) +{ + /* interpret and set tempo */ + snd_seq_queue_tempo_alloca( &sc.queue_tempo ); + snd_seq_queue_tempo_set_tempo( sc.queue_tempo , tempo ); + snd_seq_queue_tempo_set_ppq( sc.queue_tempo , ppq ); + + if ( snd_seq_set_queue_tempo( sc.seq , sc.queue , sc.queue_tempo ) < 0 ) + { + g_warning( "Cannot set queue tempo (%u/%i)\n", + snd_seq_queue_tempo_get_tempo(sc.queue_tempo), + snd_seq_queue_tempo_get_ppq(sc.queue_tempo) ); + return 0; + } + return 1; +} + + +gint sequencer_queue_start( void ) +{ + return snd_seq_start_queue( sc.seq , sc.queue , NULL ); +} + + +gint sequencer_event_init( void ) +{ + /* common settings for all our events */ + snd_seq_ev_clear(&sc.ev); + sc.ev.queue = sc.queue; + sc.ev.source.port = 0; + sc.ev.flags = SND_SEQ_TIME_STAMP_TICK; + return 1; +} + + +gint sequencer_event_noteon( midievent_t * event ) +{ + i_seq_event_common_init( event ); + snd_seq_ev_set_fixed(&sc.ev); + sc.ev.data.note.channel = event->data.d[0]; + sc.ev.data.note.note = event->data.d[1]; + sc.ev.data.note.velocity = event->data.d[2]; + return 1; +} + + +gint sequencer_event_noteoff( midievent_t * event ) +{ + i_seq_event_common_init( event ); + snd_seq_ev_set_fixed(&sc.ev); + sc.ev.data.note.channel = event->data.d[0]; + sc.ev.data.note.note = event->data.d[1]; + sc.ev.data.note.velocity = event->data.d[2]; + return 1; +} + + +gint sequencer_event_keypress( midievent_t * event ) +{ + i_seq_event_common_init( event ); + snd_seq_ev_set_fixed(&sc.ev); + sc.ev.data.note.channel = event->data.d[0]; + sc.ev.data.note.note = event->data.d[1]; + sc.ev.data.note.velocity = event->data.d[2]; + return 1; +} + + +gint sequencer_event_controller( midievent_t * event ) +{ + i_seq_event_common_init( event ); + snd_seq_ev_set_fixed(&sc.ev); + sc.ev.data.control.channel = event->data.d[0]; + sc.ev.data.control.param = event->data.d[1]; + sc.ev.data.control.value = event->data.d[2]; + return 1; +} + + +gint sequencer_event_pgmchange( midievent_t * event ) +{ + i_seq_event_common_init( event ); + snd_seq_ev_set_fixed(&sc.ev); + sc.ev.data.control.channel = event->data.d[0]; + sc.ev.data.control.value = event->data.d[1]; + return 1; +} + + +gint sequencer_event_chanpress( midievent_t * event ) +{ + i_seq_event_common_init( event ); + snd_seq_ev_set_fixed(&sc.ev); + sc.ev.data.control.channel = event->data.d[0]; + sc.ev.data.control.value = event->data.d[1]; + return 1; +} + + +gint sequencer_event_pitchbend( midievent_t * event ) +{ + i_seq_event_common_init( event ); + snd_seq_ev_set_fixed(&sc.ev); + sc.ev.data.control.channel = event->data.d[0]; + sc.ev.data.control.value = ((event->data.d[1]) | ((event->data.d[2]) << 7)) - 0x2000; + return 1; +} + + +gint sequencer_event_sysex( midievent_t * event ) +{ + i_seq_event_common_init( event ); + snd_seq_ev_set_variable(&sc.ev, event->data.length, event->sysex); + return 1; +} + + +gint sequencer_event_tempo( midievent_t * event ) +{ + i_seq_event_common_init( event ); + snd_seq_ev_set_fixed(&sc.ev); + sc.ev.dest.client = SND_SEQ_CLIENT_SYSTEM; + sc.ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER; + sc.ev.data.queue.queue = sc.queue; + sc.ev.data.queue.param.value = event->data.tempo; + return 1; +} + + +gint sequencer_event_other( midievent_t * event ) +{ + /* unhandled */ + return 1; +} + + +gint sequencer_output( gpointer * buffer , gint * len ) +{ + snd_seq_event_output( sc.seq , &sc.ev ); + snd_seq_drain_output( sc.seq ); + snd_seq_sync_output_queue( sc.seq ); + return 0; +} + + +gint sequencer_output_shut( guint max_tick , gint skip_offset ) +{ + gint i = 0 , c = 0; + /* time to shutdown playback! */ + /* send "ALL SOUNDS OFF" to all channels on all ports */ + sc.ev.type = SND_SEQ_EVENT_CONTROLLER; + sc.ev.time.tick = 0; + snd_seq_ev_set_fixed(&sc.ev); + sc.ev.data.control.param = MIDI_CTL_ALL_SOUNDS_OFF; + sc.ev.data.control.value = 0; + for ( i = 0 ; i < sc.dest_port_num ; i++ ) + { + sc.ev.queue = sc.queue; + sc.ev.dest = sc.dest_port[i]; + + for ( c = 0 ; c < 16 ; c++ ) + { + sc.ev.data.control.channel = c; + snd_seq_event_output(sc.seq, &sc.ev); + snd_seq_drain_output(sc.seq); + } + } + + /* schedule queue stop at end of song */ + snd_seq_ev_clear(&sc.ev); + sc.ev.queue = sc.queue; + sc.ev.source.port = 0; + sc.ev.flags = SND_SEQ_TIME_STAMP_TICK; + + snd_seq_ev_set_fixed(&sc.ev); + sc.ev.type = SND_SEQ_EVENT_STOP; + sc.ev.time.tick = max_tick - skip_offset; + sc.ev.dest.client = SND_SEQ_CLIENT_SYSTEM; + sc.ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER; + sc.ev.data.queue.queue = sc.queue; + snd_seq_event_output(sc.seq, &sc.ev); + snd_seq_drain_output(sc.seq); + /* snd_seq_sync_output_queue(sc.seq); */ + + return 1; +} + + +gint audio_volume_get( gint * left_volume , gint * right_volume ) +{ + snd_mixer_t * mixer_h = NULL; + snd_mixer_elem_t * mixer_elem = NULL; + gchar mixer_card[10]; + snprintf( mixer_card , 8 , "hw:%i" , amidiplug_cfg_alsa.alsa_mixer_card_id ); + mixer_card[9] = '\0'; + + if ( snd_mixer_open( &mixer_h , 0 ) > -1 ) + i_seq_mixer_find_selem( mixer_h , mixer_card , + amidiplug_cfg_alsa.alsa_mixer_ctl_name , + amidiplug_cfg_alsa.alsa_mixer_ctl_id , + &mixer_elem ); + else + mixer_h = NULL; + + if ( ( mixer_elem ) && ( snd_mixer_selem_has_playback_volume( mixer_elem ) ) ) + { + glong pv_min , pv_max , pv_range; + glong lc, rc; + + snd_mixer_selem_get_playback_volume_range( mixer_elem , &pv_min , &pv_max ); + pv_range = pv_max - pv_min; + if ( pv_range > 0 ) + { + if ( snd_mixer_selem_has_playback_channel( mixer_elem , SND_MIXER_SCHN_FRONT_LEFT ) ) + { + snd_mixer_selem_get_playback_volume( mixer_elem , SND_MIXER_SCHN_FRONT_LEFT , &lc ); + /* convert the range to 0-100 (for the case that pv_range is not 0-100 already) */ + *left_volume = (gint)(((lc - pv_min) * 100) / pv_range); + DEBUGMSG( "GET VOLUME requested, get left channel (%i)\n" , *left_volume ); + } + if ( snd_mixer_selem_has_playback_channel( mixer_elem , SND_MIXER_SCHN_FRONT_RIGHT ) ) + { + snd_mixer_selem_get_playback_volume( mixer_elem , SND_MIXER_SCHN_FRONT_RIGHT , &rc ); + /* convert the range to 0-100 (for the case that pv_range is not 0-100 already) */ + *right_volume = (gint)(((rc - pv_min) * 100) / pv_range); + DEBUGMSG( "GET VOLUME requested, get right channel (%i)\n" , *right_volume ); + } + } + } + + if ( mixer_h ) + snd_mixer_close( mixer_h ); + /* always return 1 here */ + return 1; +} + + +gint audio_volume_set( gint left_volume , gint right_volume ) +{ + snd_mixer_t * mixer_h = NULL; + snd_mixer_elem_t * mixer_elem = NULL; + gchar mixer_card[10]; + snprintf( mixer_card , 8 , "hw:%i" , amidiplug_cfg_alsa.alsa_mixer_card_id ); + mixer_card[9] = '\0'; + + if ( snd_mixer_open( &mixer_h , 0 ) > -1 ) + i_seq_mixer_find_selem( mixer_h , mixer_card , + amidiplug_cfg_alsa.alsa_mixer_ctl_name , + amidiplug_cfg_alsa.alsa_mixer_ctl_id , + &mixer_elem ); + else + mixer_h = NULL; + + if ( ( mixer_elem ) && ( snd_mixer_selem_has_playback_volume( mixer_elem ) ) ) + { + glong pv_min , pv_max , pv_range; + + snd_mixer_selem_get_playback_volume_range( mixer_elem , &pv_min , &pv_max ); + pv_range = pv_max - pv_min; + if ( pv_range > 0 ) + { + if ( snd_mixer_selem_has_playback_channel( mixer_elem , SND_MIXER_SCHN_FRONT_LEFT ) ) + { + DEBUGMSG( "SET VOLUME requested, setting left channel to %i%%\n" , left_volume ); + snd_mixer_selem_set_playback_volume( mixer_elem , SND_MIXER_SCHN_FRONT_LEFT , + (gint)((gdouble)(0.01 * (gdouble)(left_volume * pv_range)) + pv_min) ); + } + if ( snd_mixer_selem_has_playback_channel( mixer_elem , SND_MIXER_SCHN_FRONT_RIGHT ) ) + { + DEBUGMSG( "SET VOLUME requested, setting right channel to %i%%\n" , right_volume ); + snd_mixer_selem_set_playback_volume( mixer_elem , SND_MIXER_SCHN_FRONT_RIGHT , + (gint)((gdouble)(0.01 * (gdouble)(right_volume * pv_range)) + pv_min) ); + } + } + } + + if ( mixer_h ) + snd_mixer_close( mixer_h ); + /* always return 1 here */ + return 1; +} + + +gint audio_info_get( gint * channels , gint * bitdepth , gint * samplerate ) +{ + /* not applicable for ALSA backend */ + *channels = -1; + *bitdepth = -1; + *samplerate = -1; + return 0; /* not valid information */ +} + + +gboolean audio_check_autonomous( void ) +{ + return TRUE; /* ALSA deals directly with audio production */ +} + + + +/* ****************************************************************** + *** EXTRA FUNCTIONS ********************************************** + ****************************************************************** */ + + +/* get a list of writable ALSA MIDI ports + use the data_bucket_t here... + bint[0] = client id , bint[1] = port id + bcharp[0] = client name , bcharp[1] = port name + bpointer[0] = (not used) , bpointer[1] = (not used) */ +GSList * sequencer_port_get_list( void ) +{ + snd_seq_t * pseq; + snd_seq_open( &pseq , "default" , SND_SEQ_OPEN_DUPLEX , 0 ); + + GSList * wports = NULL; + snd_seq_client_info_t *cinfo; + snd_seq_port_info_t *pinfo; + + snd_seq_client_info_alloca( &cinfo ); + snd_seq_port_info_alloca( &pinfo ); + + snd_seq_client_info_set_client( cinfo , -1 ); + while ( snd_seq_query_next_client( pseq , cinfo ) >= 0 ) + { + gint client = snd_seq_client_info_get_client( cinfo ); + snd_seq_port_info_set_client( pinfo , client ); + snd_seq_port_info_set_port( pinfo , -1 ); + while (snd_seq_query_next_port( pseq , pinfo ) >= 0 ) + { + if ((snd_seq_port_info_get_capability(pinfo) + & (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)) + == (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)) + { + data_bucket_t * portinfo = (data_bucket_t*)g_malloc(sizeof(data_bucket_t)); + portinfo->bint[0] = snd_seq_port_info_get_client( pinfo ); + portinfo->bint[1] = snd_seq_port_info_get_port( pinfo ); + portinfo->bcharp[0] = g_strdup(snd_seq_client_info_get_name(cinfo)); + portinfo->bcharp[1] = g_strdup(snd_seq_port_info_get_name(pinfo)); + wports = g_slist_append( wports , portinfo ); + } + } + } + /* snd_seq_port_info_free( pinfo ); + snd_seq_client_info_free( cinfo ); */ + snd_seq_close( pseq ); + return wports; +} + + +void sequencer_port_free_list( GSList * wports ) +{ + GSList * start = wports; + while ( wports != NULL ) + { + data_bucket_t * portinfo = wports->data; + g_free( (gpointer)portinfo->bcharp[0] ); + g_free( (gpointer)portinfo->bcharp[1] ); + g_free( portinfo ); + wports = wports->next; + } + g_slist_free( start ); + return; +} + + +/* get a list of available sound cards and relative mixer controls; + use the data_bucket_t here... + bint[0] = card id , bint[1] = (not used) + bcharp[0] = card name , bcharp[1] = (not used) + bpointer[0] = list (GSList) of mixer controls on the card , bpointer[1] = (not used) */ +GSList * alsa_card_get_list( void ) +{ + gint soundcard_id = -1; + GSList * scards = NULL; + + snd_card_next( &soundcard_id ); + while ( soundcard_id > -1 ) + { + /* card container */ + data_bucket_t * cardinfo = (data_bucket_t*)g_malloc(sizeof(data_bucket_t)); + cardinfo->bint[0] = soundcard_id; + /* snd_card_get_name calls strdup on its own */ + snd_card_get_name( soundcard_id , &cardinfo->bcharp[0] ); + /* for each sound card, get a list of available mixer controls */ + cardinfo->bpointer[0] = i_seq_mixctl_get_list( soundcard_id ); + + scards = g_slist_append( scards , cardinfo ); + snd_card_next( &soundcard_id ); + } + return scards; +} + + +void alsa_card_free_list( GSList * scards ) +{ + GSList * start = scards; + while ( scards != NULL ) + { + data_bucket_t * cardinfo = scards->data; + /* free the list of mixer controls for the sound card */ + i_seq_mixctl_free_list( (GSList*)cardinfo->bpointer[0] ); + g_free( (gpointer)cardinfo->bcharp[0] ); + g_free( cardinfo ); + scards = scards->next; + } + g_slist_free( start ); + return; +} + + + +/* ****************************************************************** + *** INTERNALS **************************************************** + ****************************************************************** */ + + +/* create sequencer client */ +gint i_seq_open( void ) +{ + gint err; + err = snd_seq_open( &sc.seq , "default" , SND_SEQ_OPEN_DUPLEX , 0 ); + if (err < 0) + return 0; + snd_seq_set_client_name( sc.seq , "amidi-plug" ); + return 1; +} + + +/* free sequencer client */ +gint i_seq_close( void ) +{ + if ( snd_seq_close( sc.seq ) < 0 ) + return 0; /* fail */ + else + return 1; /* success */ +} + + +/* create queue */ +gint i_seq_queue_create( void ) +{ + sc.queue = snd_seq_alloc_named_queue( sc.seq , "AMIDI-Plug" ); + if ( sc.queue < 0 ) + return 0; /* fail */ + else + return 1; /* success */ +} + + +/* free queue */ +gint i_seq_queue_free( void ) +{ + if ( snd_seq_free_queue( sc.seq , sc.queue ) < 0 ) + return 0; /* fail */ + else + return 1; /* success */ +} + + +/* create sequencer port */ +gint i_seq_port_create( void ) +{ + sc.client_port = snd_seq_create_simple_port( sc.seq , "AMIDI-Plug" , 0 , + SND_SEQ_PORT_TYPE_MIDI_GENERIC | + SND_SEQ_PORT_TYPE_APPLICATION ); + if ( sc.client_port < 0 ) + return 0; /* fail */ + else + return 1; /* success */ +} + + +/* port connection */ +gint i_seq_port_connect( void ) +{ + gint i = 0 , err = 0; + for ( i = 0 ; i < sc.dest_port_num ; i++ ) + { + if ( snd_seq_connect_to( sc.seq , sc.client_port , + sc.dest_port[i].client , + sc.dest_port[i].port ) < 0 ) + ++err; + } + /* if these values are equal, it means + that all port connections failed */ + if ( err == i ) + return 0; /* fail */ + else + return 1; /* success */ +} + + +/* port disconnection */ +gint i_seq_port_disconnect( void ) +{ + gint i = 0 , err = 0; + for ( i = 0 ; i < sc.dest_port_num ; i++ ) + { + if ( snd_seq_disconnect_to( sc.seq , sc.client_port , + sc.dest_port[i].client , + sc.dest_port[i].port ) < 0 ) + ++err; + } + /* if these values are equal, it means + that all port disconnections failed */ + if ( err == i ) + return 0; /* fail */ + else + return 1; /* success */ +} + + +/* parse writable ports */ +gint i_seq_port_wparse( gchar * wportlist ) +{ + gint i = 0 , err = 0; + gchar **portstr = g_strsplit( wportlist , "," , 0 ); + + sc.dest_port_num = 0; + + /* fill sc.dest_port_num with the writable port number */ + while ( portstr[sc.dest_port_num] != NULL ) + ++sc.dest_port_num; + + /* check if there is already an allocated array and free it */ + if ( sc.dest_port ) + free( sc.dest_port ); + + if ( sc.dest_port_num > 0 ) + /* allocate the array of writable ports */ + sc.dest_port = calloc( sc.dest_port_num , sizeof(snd_seq_addr_t) ); + + for ( i = 0 ; i < sc.dest_port_num ; i++ ) + { + if ( snd_seq_parse_address( sc.seq , &sc.dest_port[i] , portstr[i] ) < 0 ) + ++err; + } + + g_strfreev( portstr ); + + /* if these values are equal, it means + that all port translations failed */ + if ( err == i ) + return 0; /* fail */ + else + return 1; /* success */ +} + + +gint i_seq_event_common_init( midievent_t * event ) +{ + sc.ev.type = event->type; + sc.ev.time.tick = event->tick_real; + sc.ev.dest = sc.dest_port[event->port]; + return 1; +} + + +/* get a list of available mixer controls for a given sound card; + use the data_bucket_t here... + bint[0] = control id , bint[1] = (not used) + bcharp[0] = control name , bcharp[1] = (not used) + bpointer[0] = (not used) , bpointer[1] = (not used) */ +GSList * i_seq_mixctl_get_list( gint soundcard_id ) +{ + GSList * mixctls = NULL; + snd_mixer_t * mixer_h; + snd_mixer_selem_id_t * mixer_selem_id; + snd_mixer_elem_t * mixer_elem; + gchar card[10]; + + snprintf( card , 8 , "hw:%i" , soundcard_id ); + card[9] = '\0'; + + snd_mixer_selem_id_alloca( &mixer_selem_id ); + snd_mixer_open( &mixer_h , 0 ); + snd_mixer_attach( mixer_h , card ); + snd_mixer_selem_register( mixer_h , NULL , NULL ); + snd_mixer_load( mixer_h ); + for ( mixer_elem = snd_mixer_first_elem( mixer_h ) ; mixer_elem ; + mixer_elem = snd_mixer_elem_next( mixer_elem ) ) + { + data_bucket_t * mixctlinfo = (data_bucket_t*)g_malloc(sizeof(data_bucket_t)); + snd_mixer_selem_get_id( mixer_elem , mixer_selem_id ); + mixctlinfo->bint[0] = snd_mixer_selem_id_get_index(mixer_selem_id); + mixctlinfo->bcharp[0] = g_strdup(snd_mixer_selem_id_get_name(mixer_selem_id)); + mixctls = g_slist_append( mixctls , mixctlinfo ); + } + snd_mixer_close( mixer_h ); + return mixctls; +} + + +void i_seq_mixctl_free_list( GSList * mixctls ) +{ + GSList * start = mixctls; + while ( mixctls != NULL ) + { + data_bucket_t * mixctlinfo = mixctls->data; + g_free( (gpointer)mixctlinfo->bcharp[0] ); + g_free( mixctlinfo ); + mixctls = mixctls->next; + } + g_slist_free( start ); + return; +} + + +gint i_seq_mixer_find_selem( snd_mixer_t * mixer_h , gchar * mixer_card , + gchar * mixer_control_name , gint mixer_control_id , + snd_mixer_elem_t ** mixer_elem ) +{ + snd_mixer_selem_id_t * mixer_selem_id = NULL; + snd_mixer_selem_id_alloca( &mixer_selem_id ); + snd_mixer_selem_id_set_index( mixer_selem_id , mixer_control_id ); + snd_mixer_selem_id_set_name( mixer_selem_id , mixer_control_name ); + snd_mixer_attach( mixer_h , mixer_card ); + snd_mixer_selem_register( mixer_h , NULL , NULL); + snd_mixer_load( mixer_h ); + /* assign the mixer element (can be NULL if there is no such element) */ + *mixer_elem = snd_mixer_find_selem( mixer_h , mixer_selem_id ); + /* always return 1 here */ + return 1; +} + + +gchar * i_configure_read_seq_ports_default( void ) +{ + FILE * fp = NULL; + /* first try, get seq ports from proc on card0 */ + fp = fopen( "/proc/asound/card0/wavetableD1" , "rb" ); + if ( fp ) + { + gchar buffer[100]; + while ( !feof( fp ) ) + { + fgets( buffer , 100 , fp ); + if (( strlen( buffer ) > 11 ) && ( !strncasecmp( buffer , "addresses: " , 11 ) )) + { + /* change spaces between ports (65:0 65:1 65:2 ...) + into commas (65:0,65:1,65:2,...) */ + g_strdelimit( &buffer[11] , " " , ',' ); + /* remove lf and cr from the end of the string */ + g_strdelimit( &buffer[11] , "\r\n" , '\0' ); + /* ready to go */ + DEBUGMSG( "init, default values for seq ports detected: %s\n" , &buffer[11] ); + fclose( fp ); + return g_strdup( &buffer[11] ); + } + } + fclose( fp ); + } + + /* second option: do not set ports at all, let the user + select the right ones in the nice config window :) */ + return g_strdup( "" ); +} + + +/* count the number of occurrencies of a specific character 'c' + in the string 'string' (it must be a null-terminated string) */ +gint i_util_str_count( gchar * string , gchar c ) +{ + gint i = 0 , count = 0; + while ( string[i] != '\0' ) + { + if ( string[i] == c ) + ++count; + ++i; + } + return count; +} + + +void i_cfg_read( void ) +{ + pcfg_t *cfgfile; + gchar * config_pathfilename = g_strjoin( "" , g_get_home_dir() , "/" , + PLAYER_LOCALRCDIR , "/amidi-plug.conf" , NULL ); + cfgfile = i_pcfg_new_from_file( config_pathfilename ); + + if ( !cfgfile ) + { + /* alsa backend defaults */ + amidiplug_cfg_alsa.alsa_seq_wports = i_configure_read_seq_ports_default(); + amidiplug_cfg_alsa.alsa_mixer_card_id = 0; + amidiplug_cfg_alsa.alsa_mixer_ctl_name = g_strdup( "Synth" ); + amidiplug_cfg_alsa.alsa_mixer_ctl_id = 0; + } + else + { + i_pcfg_read_string( cfgfile , "alsa" , "alsa_seq_wports" , + &amidiplug_cfg_alsa.alsa_seq_wports , NULL ); + if ( amidiplug_cfg_alsa.alsa_seq_wports == NULL ) + amidiplug_cfg_alsa.alsa_seq_wports = i_configure_read_seq_ports_default(); /* pick default values */ + + i_pcfg_read_integer( cfgfile , "alsa" , "alsa_mixer_card_id" , + &amidiplug_cfg_alsa.alsa_mixer_card_id , 0 ); + + i_pcfg_read_string( cfgfile , "alsa" , "alsa_mixer_ctl_name" , + &amidiplug_cfg_alsa.alsa_mixer_ctl_name , "Synth" ); + + i_pcfg_read_integer( cfgfile , "alsa" , "alsa_mixer_ctl_id" , + &amidiplug_cfg_alsa.alsa_mixer_ctl_id , 0 ); + + i_pcfg_free( cfgfile ); + } + + g_free( config_pathfilename ); +} + + +void i_cfg_free( void ) +{ + g_free( amidiplug_cfg_alsa.alsa_seq_wports ); + g_free( amidiplug_cfg_alsa.alsa_mixer_ctl_name ); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/backend-alsa/b-alsa.h Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,63 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#ifndef _B_ALSA_H +#define _B_ALSA_H 1 + +#include <alsa/asoundlib.h> +#include "../i_common.h" +#include "../pcfg/i_pcfg.h" +#include "../i_midievent.h" + + +typedef struct +{ + snd_seq_t * seq; + gint client_port; + gint queue; + + snd_seq_addr_t * dest_port; + gint dest_port_num; + + snd_seq_queue_tempo_t * queue_tempo; + + snd_seq_event_t ev; + + gboolean is_start; +} +sequencer_client_t; + +gint i_seq_open( void ); +gint i_seq_close( void ); +gint i_seq_queue_create( void ); +gint i_seq_queue_free( void ); +gint i_seq_port_create( void ); +gint i_seq_port_connect( void ); +gint i_seq_port_disconnect( void ); +gint i_seq_port_wparse( gchar * ); +gint i_seq_event_common_init( midievent_t * ); +GSList * i_seq_mixctl_get_list( gint ); +void i_seq_mixctl_free_list( GSList * ); +gint i_seq_mixer_find_selem( snd_mixer_t * , gchar * , gchar * , gint , snd_mixer_elem_t ** ); +void i_cfg_read( void ); +void i_cfg_free( void ); +gint i_util_str_count( gchar * , gchar ); + +#endif /* !_B_ALSA_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/backend-alsa/backend-alsa-icon.xpm Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,444 @@ +/* XPM */ +static char * backend_alsa_icon_xpm[] = { +"48 48 393 2", +" c None", +". c #FFFFFF", +"+ c #F5F8F4", +"@ c #E2EBE1", +"# c #D6E3D5", +"$ c #C5D5C3", +"% c #ABBCAA", +"& c #9BAB9A", +"* c #92A190", +"= c #8E9D8D", +"- c #FAFBF9", +"; c #EAF1E9", +"> c #CAD9C8", +", c #A7B7A6", +"' c #747E73", +") c #4B504B", +"! c #383B39", +"~ c #4A4C4A", +"{ c #646764", +"] c #787878", +"^ c #818181", +"/ c #FCFDFC", +"( c #DDE7DC", +"_ c #C0D1BE", +": c #828E81", +"< c #3B3F3B", +"[ c #434544", +"} c #8B8C8B", +"| c #CBCCCA", +"1 c #F1F1EF", +"2 c #FEFEFC", +"3 c #EFF4EF", +"4 c #C8D8C6", +"5 c #303231", +"6 c #6A6B69", +"7 c #D2D3D0", +"8 c #FEFEFE", +"9 c #DCE7DB", +"0 c #A8B7A7", +"a c #454945", +"b c #5E5F5E", +"c c #DADBD9", +"d c #FDFDFB", +"e c #F9FBF9", +"f c #D8E4D7", +"g c #8A9689", +"h c #343635", +"i c #AFB0AE", +"j c #FBFBF9", +"k c #737D72", +"l c #454745", +"m c #E5E6E3", +"n c #666E66", +"o c #5F605F", +"p c #F3F3F1", +"q c #F1F2F0", +"r c #C5C8C4", +"s c #A1A3A1", +"t c #8A8D8A", +"u c #9B9D9A", +"v c #CFD1CF", +"w c #FAFAF8", +"x c #FCFCFB", +"y c #D8D9D7", +"z c #838683", +"A c #535653", +"B c #717371", +"C c #949794", +"D c #AAACA9", +"E c #9A9E9A", +"F c #676A67", +"G c #979A97", +"H c #FCFCFA", +"I c #DADCD9", +"J c #808380", +"K c #676B67", +"L c #B5B7B5", +"M c #F7F8F6", +"N c #AFB1AE", +"O c #DEE0DD", +"P c #F5F5F3", +"Q c #A5A8A5", +"R c #6D706C", +"S c #BABBB9", +"T c #F6F7F4", +"U c #F0F1EF", +"V c #E4E5E3", +"W c #777A77", +"X c #939693", +"Y c #EFEFEE", +"Z c #FBFBFA", +"` c #E7EAE5", +" . c #B8B9B7", +".. c #515451", +"+. c #D0D1CF", +"@. c #DBDCD9", +"#. c #E4E6E2", +"$. c #ECECEA", +"%. c #C0C1BF", +"&. c #8E928E", +"*. c #737873", +"=. c #798079", +"-. c #838B84", +";. c #828C82", +">. c #929F92", +",. c #9DAB9D", +"'. c #A2B0A2", +"). c #A0AEA0", +"!. c #9EAD9E", +"~. c #9CA99C", +"{. c #9EA99E", +"]. c #9FA79E", +"^. c #A0A6A0", +"/. c #C8CBC7", +"(. c #EAEBE8", +"_. c #F9F9F7", +":. c #DDDEDC", +"<. c #767876", +"[. c #5F645F", +"}. c #8E9B8F", +"|. c #BBCDBB", +"1. c #D4E9D3", +"2. c #D9F0D8", +"3. c #D6ECD5", +"4. c #D4EAD3", +"5. c #D3EAD4", +"6. c #D0E7D1", +"7. c #D2E9D3", +"8. c #D2E9D4", +"9. c #D0E7D2", +"0. c #CAE0CB", +"a. c #CDE4CE", +"b. c #CFE6CF", +"c. c #CCE3CD", +"d. c #C6DAC7", +"e. c #B7CAB8", +"f. c #BECBBE", +"g. c #D7DBD6", +"h. c #F6F6F5", +"i. c #F5F6F3", +"j. c #828482", +"k. c #555B56", +"l. c #B0C1B0", +"m. c #D7EED8", +"n. c #D4EBD5", +"o. c #D4EBD4", +"p. c #D6ECD4", +"q. c #A6B6A4", +"r. c #4A504B", +"s. c #D4E9D2", +"t. c #515751", +"u. c #A4B4A5", +"v. c #D1E8D3", +"w. c #7B857B", +"x. c #1A1B1B", +"y. c #919E91", +"z. c #3F4340", +"A. c #ABBCAC", +"B. c #CBE2CC", +"C. c #CAE1CB", +"D. c #CCDDCB", +"E. c #E1E9E1", +"F. c #676967", +"G. c #8F9C8F", +"H. c #D2E8D3", +"I. c #93A192", +"J. c #323533", +"K. c #D2E6D0", +"L. c #444A44", +"M. c #9FAFA0", +"N. c #C8DCC9", +"O. c #3A3D3A", +"P. c #B5C6B5", +"Q. c #C8DDC8", +"R. c #2B2E2C", +"S. c #92A192", +"T. c #CBE1CC", +"U. c #C8DEC9", +"V. c #C8DCC7", +"W. c #D2E4D3", +"X. c #EDEFEB", +"Y. c #A1A3A0", +"Z. c #899489", +"`. c #808A80", +" + c #1F201F", +".+ c #CCE0CA", +"++ c #CAE0CC", +"@+ c #B5C8B6", +"#+ c #C2D7C3", +"$+ c #1B1C1B", +"%+ c #7C867C", +"&+ c #C7D9C5", +"*+ c #C2DAC4", +"=+ c #C6DBC7", +"-+ c #E4EBE3", +";+ c #787C78", +">+ c #D1E6D1", +",+ c #CFE6D1", +"'+ c #656C65", +")+ c #0A0A0B", +"!+ c #C5D9C3", +"~+ c #666F67", +"{+ c #757F75", +"]+ c #BDD2BE", +"^+ c #606861", +"/+ c #C4DAC4", +"(+ c #C5D8C3", +"_+ c #ECEEEB", +":+ c #A0A7A0", +"<+ c #CEE5D0", +"[+ c #D5EBD4", +"}+ c #D4EBD3", +"|+ c #515851", +"1+ c #1C1E1D", +"2+ c #B3C4B2", +"3+ c #B5C7B6", +"4+ c #323432", +"5+ c #C2D8C3", +"6+ c #B0C2B1", +"7+ c #1B1C1C", +"8+ c #4C514C", +"9+ c #C9DFC9", +"0+ c #C3DAC4", +"a+ c #C3D6C1", +"b+ c #CBD6CA", +"c+ c #DEE2DD", +"d+ c #D0E6D0", +"e+ c #D2E7D0", +"f+ c #424742", +"g+ c #474A47", +"h+ c #96A496", +"i+ c #434944", +"j+ c #D0E6D1", +"k+ c #4F554F", +"l+ c #909C90", +"m+ c #9AA99B", +"n+ c #424542", +"o+ c #373B38", +"p+ c #C6DAC6", +"q+ c #C8DCC8", +"r+ c #9EAA9D", +"s+ c #E9EAE8", +"t+ c #D8E8D9", +"u+ c #CFE6D0", +"v+ c #CDE2CE", +"w+ c #313431", +"x+ c #6D766D", +"y+ c #7E897E", +"z+ c #CEE5CF", +"A+ c #859286", +"B+ c #5D655E", +"C+ c #869387", +"D+ c #697269", +"E+ c #252726", +"F+ c #BED2BF", +"G+ c #C7DBC7", +"H+ c #C2D5C0", +"I+ c #7A8179", +"J+ c #D6D9D5", +"K+ c #F0F3EF", +"L+ c #D0E5D1", +"M+ c #C4D8C5", +"N+ c #2E312F", +"O+ c #6F7870", +"P+ c #636A64", +"Q+ c #9AAB9B", +"R+ c #4A514B", +"S+ c #727C73", +"T+ c #6C756D", +"U+ c #222422", +"V+ c #B5C8B5", +"W+ c #C7DAC6", +"X+ c #C5D9C5", +"Y+ c #C3D8C2", +"Z+ c #545854", +"`+ c #ECEDEB", +" @ c #EEF1ED", +".@ c #D4E3D4", +"+@ c #CCE2CD", +"@@ c #BBD0BD", +"#@ c #161717", +"$@ c #262927", +"%@ c #424843", +"&@ c #9CAC9D", +"*@ c #7F8B7F", +"=@ c #616962", +"-@ c #5D635D", +";@ c #212322", +">@ c #101111", +",@ c #AABCAB", +"'@ c #C2D8C2", +")@ c #B1C1B0", +"!@ c #595E59", +"~@ c #A1A4A1", +"{@ c #FBFCFA", +"]@ c #E3EAE2", +"^@ c #CBDACB", +"/@ c #CBE1CB", +"(@ c #AFC2B1", +"_@ c #383C39", +":@ c #ACBEAD", +"<@ c #3C413D", +"[@ c #3D423D", +"}@ c #8E9B8E", +"|@ c #3E413E", +"1@ c #242625", +"2@ c #A7B8A8", +"3@ c #4A504A", +"4@ c #97A698", +"5@ c #4B504C", +"6@ c #94A295", +"7@ c #C7DBC6", +"8@ c #C4D8C3", +"9@ c #BFD2BE", +"0@ c #8C978D", +"a@ c #404341", +"b@ c #A0A2A0", +"c@ c #F5F5F4", +"d@ c #D5D7D4", +"e@ c #BBC6BB", +"f@ c #BECDBE", +"g@ c #BED1BE", +"h@ c #B0C1AF", +"i@ c #C7DCC8", +"j@ c #AFC1B0", +"k@ c #AFC0AF", +"l@ c #A3B4A3", +"m@ c #B4C6B4", +"n@ c #BBCEBC", +"o@ c #AEBFAF", +"p@ c #C0D3C0", +"q@ c #B8CBB8", +"r@ c #B1BBB0", +"s@ c #808780", +"t@ c #555955", +"u@ c #747674", +"v@ c #E2E4E1", +"w@ c #F5F6F4", +"x@ c #DDDFDC", +"y@ c #B8BDB7", +"z@ c #A1AAA1", +"A@ c #919991", +"B@ c #9DAA9C", +"C@ c #A3AFA2", +"D@ c #A8B5A7", +"E@ c #ACBCAC", +"F@ c #AFBFAF", +"G@ c #AFBEAF", +"H@ c #ABBAAB", +"I@ c #98A497", +"J@ c #899688", +"K@ c #7E877E", +"L@ c #707770", +"M@ c #676B66", +"N@ c #AEB0AD", +"O@ c #E7E8E5", +"P@ c #F3F3F2", +"Q@ c #E2E4E0", +"R@ c #C8C9C7", +"S@ c #B7BAB7", +"T@ c #A4A8A3", +"U@ c #636763", +"V@ c #4D4F4D", +"W@ c #999C98", +"X@ c #A7ABA6", +"Y@ c #B6B6B6", +"Z@ c #CACBC9", +"`@ c #E0E2DF", +" # c #F4F5F3", +".# c #7E827D", +"+# c #868886", +"@# c #ECEDEA", +"## c #E3E5E2", +"$# c #969B97", +"%# c #696C69", +"&# c #BFC1BE", +"*# c #F8F8F7", +"=# c #B5B9B4", +"-# c #909190", +";# c #E8E8E6", +"># c #C4C6C3", +",# c #7A7C7A", +"'# c #5A5D5A", +")# c #A6A7A5", +"!# c #EEEFED", +"~# c #A7ABA7", +"{# c #535753", +"]# c #515551", +"^# c #707370", +"/# c #C0C2BF", +"(# c #E8E9E7", +"_# c #EBECEA", +":# c #F4F5F2", +". . . . . . . . . . . . . . . . + @ # $ % & * = = * & % $ # @ + . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . - ; > , ' ) ! ~ { ] ^ ^ ] { ~ ! ) ' , > ; - . . . . . . . . . . . . . ", +". . . . . . . . . . . / ( _ : < [ } | 1 2 2 2 2 2 2 2 2 1 | } [ < : _ ( / . . . . . . . . . . . ", +". . . . . . . . . . 3 4 : 5 6 7 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 7 6 5 : 4 3 . . . . . . . . . . ", +". . . . . . . . 8 9 0 a b c d 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 d c b a 0 9 8 . . . . . . . . ", +". . . . . . . e f g h i j 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 j i h g f e . . . . . . . ", +". . . . . . e 4 k l m 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 m l k 4 e . . . . . . ", +". . . . . e 4 n o 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 o n 4 e . . . . . ", +". . . . 8 f k o p 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 p o k f 8 . . . . ", +". . . . 9 g l 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 l g 9 . . . . ", +". . . 3 0 h m 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 m h 0 3 . . . ", +". . / 4 a i 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 q r s t u v w 2 2 2 2 2 2 2 i a 4 / . . ", +". . ( : b j 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 x y z A B C D E F G H 2 2 2 2 2 2 j b : ( . . ", +". - _ 5 c 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 d I J K L q d 2 2 2 M N O 2 2 2 2 2 2 2 c 5 _ - . ", +". ; : 6 d 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 P Q R S T 2 2 2 2 2 2 2 w U 2 2 2 2 2 2 2 d 6 : ; . ", +". > < 7 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 V W X Y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 7 < > . ", +"+ , [ 2 2 2 2 2 2 2 2 2 2 2 2 2 Z p ` O ...G +.@.#.p H 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 [ , + ", +"@ ' } 2 2 2 2 2 2 2 2 2 d $.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.2 2 2 2 2 2 2 2 2 2 2 2 2 } ' @ ", +"# ) | 2 2 2 2 2 2 2 d :.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.2 2 2 2 2 2 2 2 2 2 2 | ) # ", +"$ ! 1 2 2 2 2 2 2 i.j.k.l.m.n.o.p.p.q.r.s.t.u.v.w.x.y.0.z.A.B.0.C.D.E.d 2 2 2 2 2 2 2 2 2 1 ! $ ", +"% ~ 2 2 2 2 2 2 P F.G.H.5.8.8.p.p.p.I.J.K.L.M.N.O.P.0.Q.R.S.T.U.U.U.V.W.X.2 2 2 2 2 2 2 2 2 ~ % ", +"& { 2 2 2 2 2 2 Y.Z.5.6.8.8.8.p.p.p.`. +.+L.M.++< @+a.#+$+%+T.U.U.Q.&+*+=+-+2 2 2 2 2 2 2 2 { & ", +"* ] 2 2 2 2 2 - ;+>+a.,+8.8.8.p.p.p.'+)+!+L.M.8.~+{+a.]+)+^+T.U.U.Q.&+*+/+(+_+2 2 2 2 2 2 2 ] * ", +"= ^ 2 2 2 2 2 Z :+7.a.<+8.8.8.[+p.}+|+1+2+L.M.8.3+4+5+6+7+8+9+U.U.Q.&+*+0+a+b+H 2 2 2 2 2 2 ^ = ", +"= ^ 2 2 2 2 2 2 c+d+a.a.v.8.8.8.[+e+f+g+h+i+M.8.j+k+l+m+n+o+p+U.U.q+&+*+0+a+r+s+2 2 2 2 2 2 ^ = ", +"* ] 2 2 2 2 2 2 j t+a.a.u+8.8.8.8.v+w+x+y+i+M.8.z+A+B+C+D+E+F+U.U.G+&+*+0+H+I+J+2 2 2 2 2 2 ] * ", +"& { 2 2 2 2 2 2 2 K+L+a.a.u+8.8.8.M+N+O+P+i+M.6.a.Q+R+S+T+U+V+U.U.W+X+*+Y+2+Z+`+2 2 2 2 2 2 { & ", +"% ~ 2 2 2 2 2 2 2 2 @.@+@a.u+8.8.@@#@$@r.%@&@c.U.*@=@-@;@>@,@U.Q.&+/+'@)@!@~@d 2 2 2 2 2 2 ~ % ", +"$ ! 1 2 2 2 2 2 2 2 2 {@]@^@/@z+6.(@_@:@<@[@<@}@|@1@2@3@4@5@6@U.7@8@9@0@a@b@d 2 2 2 2 2 2 1 ! $ ", +"# ) | 2 2 2 2 2 2 2 2 2 2 c@d@e@f@g@h@i@j@k@l@F+m@n@T.o@p@k@q@9@r@s@t@u@v@2 2 2 2 2 2 2 2 | ) # ", +"@ ' } 2 2 2 2 2 2 2 2 2 2 2 2 w@x@y@z@A@B@C@D@E@F@G@H@I@J@K@L@M@;+N@O@x 2 2 2 2 2 2 2 2 2 } ' @ ", +"+ , [ 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 x P@Q@R@S@T@U@V@W@X@Y@Z@`@ #d 2 2 2 2 2 2 2 2 2 2 2 2 [ , + ", +". > < 7 2 2 2 2 2 2 2 2 H 2 2 2 2 2 2 2 2 2 :..#+#@#2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 7 < > . ", +". ; : 6 d 2 2 2 2 2 2 H v j 2 2 2 2 2 d ##$#%#&#*#2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 d 6 : ; . ", +". - _ 5 c 2 2 2 2 2 2 2 =#-#`@c@c@;#>#,#'#)#!#2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 c 5 _ - . ", +". . ( : b j 2 2 2 2 2 2 H ~#'#{#]#t@^#/#c@2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 j b : ( . . ", +". . / 4 a i 2 2 2 2 2 2 2 2 P (#_#:#d 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 i a 4 / . . ", +". . . 3 0 h m 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 m h 0 3 . . . ", +". . . . 9 g l 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 l g 9 . . . . ", +". . . . 8 f k o p 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 p o k f 8 . . . . ", +". . . . . e 4 n o 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 o n 4 e . . . . . ", +". . . . . . e 4 k l m 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 m l k 4 e . . . . . . ", +". . . . . . . e f g h i j 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 j i h g f e . . . . . . . ", +". . . . . . . . 8 9 0 a b c d 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 d c b a 0 9 8 . . . . . . . . ", +". . . . . . . . . . 3 4 : 5 6 7 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 7 6 5 : 4 3 . . . . . . . . . . ", +". . . . . . . . . . . / ( _ : < [ } | 1 2 2 2 2 2 2 2 2 1 | } [ < : _ ( / . . . . . . . . . . . ", +". . . . . . . . . . . . . - ; > , ' ) ! ~ { ] ^ ^ ] { ~ ! ) ' , > ; - . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . + @ # $ % & * = = * & % $ # @ + . . . . . . . . . . . . . . . . "};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/backend-dummy/Makefile.in Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,15 @@ +include ../../../../mk/rules.mk +include ../../../../mk/objective.mk + +noinst_HEADERS = b-dummy.h b-dummy-config.h backend-dummy-icon.xpm + +CFLAGS += -fPIC -DPIC $(GLIB_CFLAGS) -I../../../../intl -I../../../.. + +libdir = $(AMIDIPLUGDATADIR) + +OBJECTIVE_LIBS = ap-dummy.so + +LIBADD = $(GLIB_LIBS) ../pcfg/libpcfg.a +SOURCES = b-dummy.c + +OBJECTS = ${SOURCES:.c=.o}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/backend-dummy/b-dummy-config.h Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,36 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#ifndef _B_DUMMY_CONFIG_H +#define _B_DUMMY_CONFIG_H 1 + + +typedef struct +{ + gint dumm_logger_enable; + gint dumm_logger_lfstyle; + gint dumm_playback_speed; + gchar * dumm_logger_logfile; + gchar * dumm_logger_logdir; +} +amidiplug_cfg_dumm_t; + + +#endif /* !_B_DUMMY_CONFIG_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/backend-dummy/b-dummy.c Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,392 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#include "b-dummy.h" +#include "b-dummy-config.h" + +/* dummy sequencer instance */ +static sequencer_client_t sc; +/* options */ +static amidiplug_cfg_dumm_t amidiplug_cfg_dumm; + + +gint backend_info_get( gchar ** name , gchar ** longname , gchar ** desc , gint * ppos ) +{ + if ( name != NULL ) + *name = g_strdup( "dummy" ); + if ( longname != NULL ) + *longname = g_strdup( "Dummy Backend " AMIDIPLUG_VERSION ); + if ( desc != NULL ) + *desc = g_strdup( _("This backend does not produce audio at all. It is mostly " + "useful for analysis and testing purposes, as it can log " + "all MIDI events to standard output, standard error or file.\n" + "Backend written by Giacomo Lozito.") ); + if ( ppos != NULL ) + *ppos = 3; /* preferred position in backend list */ + return 1; +} + + +gint backend_init( void ) +{ + i_cfg_read(); /* read configuration options */ + + return 1; +} + + +gint backend_cleanup( void ) +{ + i_cfg_free(); /* free configuration options */ + + return 1; +} + + +gint sequencer_get_port_count( void ) +{ + return 1; /* always return a single port here */ +} + + +gint sequencer_start( gchar * midi_fname ) +{ + switch( amidiplug_cfg_dumm.dumm_logger_enable ) + { + case 1: + { + sc.file = stdout; /* log to standard output */ + break; + } + case 2: + { + sc.file = stderr; /* log to standard error */ + break; + } + case 3: + { + switch ( amidiplug_cfg_dumm.dumm_logger_lfstyle ) + { + case 0: + { + sc.file = fopen( amidiplug_cfg_dumm.dumm_logger_logfile , "w" ); + break; + } + case 1: + { + sc.file = fopen( amidiplug_cfg_dumm.dumm_logger_logfile , "a" ); + break; + } + case 2: + { + gchar *midi_basefname = G_PATH_GET_BASENAME( midi_fname ); + gchar *logfile = g_strjoin( "" , amidiplug_cfg_dumm.dumm_logger_logdir , + "/" , midi_basefname , ".log" , NULL ); + sc.file = fopen( logfile , "w" ); + g_free( logfile ); + g_free( midi_basefname ); + break; + } + default: /* shouldn't happen, let's handle this anyway */ + { + sc.file = NULL; + break; + } + } + break; + } + case 0: + default: + { + sc.file = NULL; + break; + } + } + + if (( sc.file == NULL ) && ( amidiplug_cfg_dumm.dumm_logger_enable != 0 )) + { + DEBUGMSG( "Unable to get a FILE pointer\n" ); + return 0; + } + else + return 1; /* success */ +} + + +gint sequencer_stop( void ) +{ + if (( sc.file != NULL ) && ( amidiplug_cfg_dumm.dumm_logger_enable == 3 )) + fclose( sc.file ); + + return 1; /* success */ +} + + +/* activate sequencer client */ +gint sequencer_on( void ) +{ + sc.tick_offset = 0; + if ( amidiplug_cfg_dumm.dumm_playback_speed == 0 ) + sc.timer_seq = g_timer_new(); /* create the sequencer timer */ + return 1; /* success */ +} + + +/* shutdown sequencer client */ +gint sequencer_off( void ) +{ + if (( amidiplug_cfg_dumm.dumm_playback_speed == 0 ) && ( sc.timer_seq != NULL )) + { + g_timer_destroy( sc.timer_seq ); /* destroy the sequencer timer */ + sc.timer_seq = NULL; + } + return 1; /* success */ +} + + +/* queue set tempo */ +gint sequencer_queue_tempo( gint tempo , gint ppq ) +{ + sc.ppq = ppq; + sc.usec_per_tick = (gdouble)tempo / (gdouble)ppq; + return 1; +} + + +gint sequencer_queue_start( void ) +{ + if ( amidiplug_cfg_dumm.dumm_playback_speed == 0 ) + g_timer_start( sc.timer_seq ); /* reset the sequencer timer */ + return 1; +} + + +gint sequencer_event_init( void ) +{ + /* common settings for all our events */ + return 1; +} + + +gint sequencer_event_noteon( midievent_t * event ) +{ + i_sleep( event->tick_real ); + i_printf( sc.file , "NOTEON : ti %i : ch %i : no %i : ve %i\n" , + event->tick , event->data.d[0] , event->data.d[1] , event->data.d[2] ); + return 1; +} + + +gint sequencer_event_noteoff( midievent_t * event ) +{ + i_sleep( event->tick_real ); + i_printf( sc.file , "NOTEOFF : ti %i : ch %i : no %i : ve %i\n" , + event->tick , event->data.d[0] , event->data.d[1] , event->data.d[2] ); + return 1; +} + + +gint sequencer_event_keypress( midievent_t * event ) +{ + i_sleep( event->tick_real ); + i_printf( sc.file , "KEYPRESS : ti %i : ch %i : no %i : ve %i\n" , + event->tick , event->data.d[0] , event->data.d[1] , event->data.d[2] ); + return 1; +} + + +gint sequencer_event_controller( midievent_t * event ) +{ + i_sleep( event->tick_real ); + i_printf( sc.file , "CONTROLLER : ti %i : ch %i : pa %i : va %i\n" , + event->tick , event->data.d[0] , event->data.d[1] , event->data.d[2] ); + return 1; +} + + +gint sequencer_event_pgmchange( midievent_t * event ) +{ + i_sleep( event->tick_real ); + i_printf( sc.file , "PGMCHANGE : ti %i : ch %i : va %i\n" , + event->tick , event->data.d[0] , event->data.d[1] ); + return 1; +} + + +gint sequencer_event_chanpress( midievent_t * event ) +{ + i_sleep( event->tick_real ); + i_printf( sc.file , "CHANPRESS : ti %i : ch %i : va %i\n" , + event->tick , event->data.d[0] , event->data.d[1] ); + return 1; +} + + +gint sequencer_event_pitchbend( midievent_t * event ) +{ + i_sleep( event->tick_real ); + i_printf( sc.file , "PITCHBEND : ti %i : ch %i : va %i\n" , + event->tick , event->data.d[0] , + ((((event->data.d[2]) & 0x7f) << 7) | ((event->data.d[1]) & 0x7f)) ); + return 1; +} + + +gint sequencer_event_sysex( midievent_t * event ) +{ + i_sleep( event->tick_real ); + i_printf( sc.file , "SYSEX : ti %i\n" , + event->tick ); + return 1; +} + + +gint sequencer_event_tempo( midievent_t * event ) +{ + i_sleep( event->tick_real ); + i_printf( sc.file , "TEMPOCHANGE : ti %i : va %i\n" , + event->tick , event->data.tempo ); + sc.usec_per_tick = (gdouble)event->data.tempo / (gdouble)sc.ppq; + if ( amidiplug_cfg_dumm.dumm_playback_speed == 0 ) + g_timer_start( sc.timer_seq ); /* reset the sequencer timer */ + sc.tick_offset = event->tick_real; + return 1; +} + + +gint sequencer_event_other( midievent_t * event ) +{ + return 1; +} + + +gint sequencer_output( gpointer * buffer , gint * len ) +{ + return 0; +} + + +gint sequencer_output_shut( guint max_tick , gint skip_offset ) +{ + return 1; +} + + +/* unimplemented (useless for dummy backend) */ +gint audio_volume_get( gint * left_volume , gint * right_volume ) +{ + return 0; +} +gint audio_volume_set( gint left_volume , gint right_volume ) +{ + return 0; +} + + +gint audio_info_get( gint * channels , gint * bitdepth , gint * samplerate ) +{ + /* not applicable for dummy backend */ + *channels = -1; + *bitdepth = -1; + *samplerate = -1; + return 0; /* not valid information */ +} + + +gboolean audio_check_autonomous( void ) +{ + return TRUE; /* Dummy deals itself with audio (well, it doesn't produce any at all :)) */ +} + + + +/* ****************************************************************** + *** INTERNALS **************************************************** + ****************************************************************** */ + + +void i_sleep( guint tick ) +{ + if ( amidiplug_cfg_dumm.dumm_playback_speed == 0 ) + { + gdouble elapsed_tick_usecs = (gdouble)(tick - sc.tick_offset) * sc.usec_per_tick; + gdouble elapsed_seq_usecs = g_timer_elapsed( sc.timer_seq , NULL ) * 1000000; + if ( elapsed_seq_usecs < elapsed_tick_usecs ) + { + G_USLEEP( elapsed_tick_usecs - elapsed_seq_usecs ); + } + } +} + + +void i_printf( FILE * fp , const gchar * format , ... ) +{ + va_list args; + va_start( args , format ); + if ( fp != NULL ) + G_VFPRINTF( fp , format , args ); + va_end( args ); +} + + +void i_cfg_read( void ) +{ + pcfg_t *cfgfile; + gchar * def_logfile = g_strjoin( "" , g_get_home_dir() , "/amidi-plug.log" , NULL ); + gchar * def_logdir = (gchar*)g_get_home_dir(); + gchar * config_pathfilename = g_strjoin( "" , g_get_home_dir() , "/" , + PLAYER_LOCALRCDIR , "/amidi-plug.conf" , NULL ); + cfgfile = i_pcfg_new_from_file( config_pathfilename ); + + if ( !cfgfile ) + { + /* fluidsynth backend defaults */ + amidiplug_cfg_dumm.dumm_logger_enable = 0; + amidiplug_cfg_dumm.dumm_logger_lfstyle = 0; + amidiplug_cfg_dumm.dumm_playback_speed = 0; + amidiplug_cfg_dumm.dumm_logger_logfile = g_strdup( def_logfile ); + amidiplug_cfg_dumm.dumm_logger_logdir = g_strdup( def_logdir ); + } + else + { + i_pcfg_read_integer( cfgfile , "dumm" , "dumm_logger_enable" , + &amidiplug_cfg_dumm.dumm_logger_enable , 0 ); + i_pcfg_read_integer( cfgfile , "dumm" , "dumm_logger_lfstyle" , + &amidiplug_cfg_dumm.dumm_logger_lfstyle , 0 ); + i_pcfg_read_integer( cfgfile , "dumm" , "dumm_playback_speed" , + &amidiplug_cfg_dumm.dumm_playback_speed , 0 ); + i_pcfg_read_string( cfgfile , "dumm" , "dumm_logger_logfile" , + &amidiplug_cfg_dumm.dumm_logger_logfile , def_logfile ); + i_pcfg_read_string( cfgfile , "dumm" , "dumm_logger_logdir" , + &amidiplug_cfg_dumm.dumm_logger_logdir , def_logdir ); + + i_pcfg_free( cfgfile ); + } + + g_free( config_pathfilename ); + g_free( def_logfile ); +} + + +void i_cfg_free( void ) +{ + g_free( amidiplug_cfg_dumm.dumm_logger_logfile ); + g_free( amidiplug_cfg_dumm.dumm_logger_logdir ); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/backend-dummy/b-dummy.h Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,49 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#ifndef _B_DUMMY_H +#define _B_DUMMY_H 1 + + +#include "../i_common.h" +#include <glib/gprintf.h> +#include "../pcfg/i_pcfg.h" +#include "../i_midievent.h" + + +typedef struct +{ + FILE * file; + + gint ppq; + gdouble usec_per_tick; + guint tick_offset; + + GTimer * timer_seq; +} +sequencer_client_t; + + +void i_sleep( guint ); +void i_printf( FILE * , const gchar * , ... ); +void i_cfg_read( void ); +void i_cfg_free( void ); + +#endif /* !_B_DUMMY_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/backend-dummy/backend-dummy-icon.xpm Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,852 @@ +/* XPM */ +static char * backend_dummy_icon_xpm[] = { +"48 48 801 2", +" c #FFFFFF", +". c #D4D4D4", +"+ c #BEBEBE", +"@ c #DFDFDF", +"# c #E7E7E7", +"$ c #F4F4F4", +"% c #7F7F7F", +"& c #484848", +"* c #AEAEAE", +"= c #C0C0C0", +"- c #EFEFEF", +"; c #C1C1C1", +"> c #FEFEFE", +", c #7A7A7A", +"' c #6E6E6E", +") c #E2E2E2", +"! c #9A9A9A", +"~ c #767676", +"{ c #D9D9D9", +"] c #CBCBCB", +"^ c #DDDDDD", +"/ c #9C9C9C", +"( c #B9B9B9", +"_ c #D0D0D0", +": c #BFBFBF", +"< c #E4E4E4", +"[ c #C2C2C2", +"} c #E3E3E3", +"| c #DCDCDC", +"1 c #F7F6F6", +"2 c #C8C7C7", +"3 c #ABAAAA", +"4 c #868585", +"5 c #686666", +"6 c #5C5B5B", +"7 c #595858", +"8 c #626161", +"9 c #737272", +"0 c #8D8C8C", +"a c #A5A4A4", +"b c #D5D5D5", +"c c #A2A2A2", +"d c #C6C6C6", +"e c #D2D2D2", +"f c #D8D8D8", +"g c #AEADAD", +"h c #8C8B8B", +"i c #8A8989", +"j c #828080", +"k c #757373", +"l c #787676", +"m c #7B7A7A", +"n c #727272", +"o c #717070", +"p c #676666", +"q c #656464", +"r c #9B9A9A", +"s c #EAEAEA", +"t c #C7C7C7", +"u c #7C7C7C", +"v c #E6E6E6", +"w c #A6A5A5", +"x c #9E9C9C", +"y c #999898", +"z c #908E8E", +"A c #858484", +"B c #767575", +"C c #6E6C6E", +"D c #6F6D70", +"E c #6B6A6E", +"F c #6B6A6F", +"G c #6E6C70", +"H c #767577", +"I c #707070", +"J c #5F5E5E", +"K c #949393", +"L c #F0F0F0", +"M c #F1F1F1", +"N c #ABABAB", +"O c #454545", +"P c #F6F6F6", +"Q c #B0AFAF", +"R c #969595", +"S c #8E8D8D", +"T c #807E80", +"U c #817F80", +"V c #84847B", +"W c #838476", +"X c #BEC0B1", +"Y c #C7C8AE", +"Z c #C7C8AB", +"` c #BABBA2", +" . c #909182", +".. c #858676", +"+. c #69686A", +"@. c #6E6D71", +"#. c #C3C3C3", +"$. c #989898", +"%. c #E5E5E5", +"&. c #FCFCFC", +"*. c #878787", +"=. c #7B7B7B", +"-. c #929191", +";. c #929090", +">. c #8F8C8C", +",. c #868485", +"'. c #7E7D7B", +"). c #9E9E96", +"!. c #C3C3B4", +"~. c #FDFDEC", +"{. c #FAFCE2", +"]. c #F8F9D6", +"^. c #F4F6D1", +"/. c #F3F6CE", +"(. c #F3F5CA", +"_. c #F8FACC", +":. c #F8FACE", +"<. c #DFE0B5", +"[. c #BCBC9C", +"}. c #6D6C65", +"|. c #6B6A70", +"1. c #757474", +"2. c #7A7979", +"3. c #666464", +"4. c #A09F9F", +"5. c #E1E0E0", +"6. c #7A7878", +"7. c #848383", +"8. c #868484", +"9. c #848182", +"0. c #797778", +"a. c #9E9F9A", +"b. c #E0E1D7", +"c. c #FCFDE9", +"d. c #F8F9E0", +"e. c #F7F9DE", +"f. c #F6F8DB", +"g. c #F6F8D8", +"h. c #F5F7D4", +"i. c #F4F6D0", +"j. c #F4F6CC", +"k. c #F2F5C8", +"l. c #F2F4C5", +"m. c #F0F4C0", +"n. c #F2F6BE", +"o. c #F9FBC5", +"p. c #B7B793", +"q. c #676668", +"r. c #727072", +"s. c #6A6969", +"t. c #939292", +"u. c #E7E8E8", +"v. c #696767", +"w. c #747272", +"x. c #767474", +"y. c #A8A9A0", +"z. c #FEFEF3", +"A. c #FAFBE7", +"B. c #F9FAE6", +"C. c #F9FAE5", +"D. c #F8F9E2", +"E. c #F6F8D7", +"F. c #F5F7D3", +"G. c #F4F6CE", +"H. c #F3F6CA", +"I. c #F2F5C7", +"J. c #F1F4C2", +"K. c #F0F3BE", +"L. c #EFF2B9", +"M. c #F1F4B6", +"N. c #E1E3A8", +"O. c #6D6D67", +"P. c #A2A1A1", +"Q. c #C4C4C4", +"R. c #999999", +"S. c #6C6C6C", +"T. c #E8E8E8", +"U. c #777676", +"V. c #797878", +"W. c #727171", +"X. c #6C6B6B", +"Y. c #C2C2BD", +"Z. c #FEFEF6", +"`. c #FAFCED", +" + c #FBFBEC", +".+ c #FAFBEA", +"++ c #FAFBE8", +"@+ c #F6F8DA", +"#+ c #F6F7D6", +"$+ c #F4F7D0", +"%+ c #F2F4C4", +"&+ c #F0F3BF", +"*+ c #EFF3BA", +"=+ c #EEF2B6", +"-+ c #F0F4B2", +";+ c #DEE0A2", +">+ c #84837D", +",+ c #C5C5C5", +"'+ c #EBEBEB", +")+ c #CCCCCC", +"!+ c #898888", +"~+ c #7C7B7B", +"{+ c #6D6C6D", +"]+ c #A8A7A0", +"^+ c #FDFDF5", +"/+ c #FCFCF0", +"(+ c #FCFCF2", +"_+ c #FCFCF1", +":+ c #FBFCEF", +"<+ c #FAFBEC", +"[+ c #F6F8DC", +"}+ c #F4F7D2", +"|+ c #F2F5C9", +"1+ c #F1F4C0", +"2+ c #F0F2BB", +"3+ c #EEF2B7", +"4+ c #EEF1B2", +"5+ c #ECF0AE", +"6+ c #DEDF9D", +"7+ c #6C6C66", +"8+ c #727172", +"9+ c #787878", +"0+ c #6C6A6A", +"a+ c #EDEDED", +"b+ c #747474", +"c+ c #6C6A6C", +"d+ c #999894", +"e+ c #FBFCF2", +"f+ c #FCFDF4", +"g+ c #FCFDF6", +"h+ c #FDFDF6", +"i+ c #FCFCF3", +"j+ c #F8FAE2", +"k+ c #F7F8DE", +"l+ c #F6F8D9", +"m+ c #F4F6CF", +"n+ c #F2F5CA", +"o+ c #F2F4C6", +"p+ c #F0F4C1", +"q+ c #F0F3BC", +"r+ c #EEF2B8", +"s+ c #EEF1B3", +"t+ c #EDF0AE", +"u+ c #EEF2AB", +"v+ c #D8DA9C", +"w+ c #626069", +"x+ c #F2F2F2", +"y+ c #B5B5B5", +"z+ c #FDFDFD", +"A+ c #B7B6B6", +"B+ c #8A8888", +"C+ c #7E7D7D", +"D+ c #6A6968", +"E+ c #FEFEF8", +"F+ c #FDFEF8", +"G+ c #FEFFFC", +"H+ c #A6A6A8", +"I+ c #A7A7A7", +"J+ c #FBFCEA", +"K+ c #F8FAE3", +"L+ c #F9FAD0", +"M+ c #E5E6BE", +"N+ c #A6A598", +"O+ c #AAA998", +"P+ c #FAFCC2", +"Q+ c #F0F4B4", +"R+ c #ECF0AA", +"S+ c #EEF2A6", +"T+ c #A8A886", +"U+ c #6F6D72", +"V+ c #7E7C7C", +"W+ c #404040", +"X+ c #FAFAFA", +"Y+ c #8E8E8E", +"Z+ c #747373", +"`+ c #6A696B", +" @ c #BABAB6", +".@ c #FBFCED", +"+@ c #FCFCF4", +"@@ c #FEFEFB", +"#@ c #7F7F80", +"$@ c #AEAEAF", +"%@ c #D3D3D4", +"&@ c #82827F", +"*@ c #D2D3CD", +"=@ c #F9FAE3", +"-@ c #F5F7D5", +";@ c #FAFAD6", +">@ c #828185", +",@ c #AAA9B0", +"'@ c #D4D4D6", +")@ c #84848B", +"!@ c #D2D4A6", +"~@ c #EAEEA4", +"{@ c #F7FAAB", +"]@ c #5D5C64", +"^@ c #807F7F", +"/@ c #929292", +"(@ c #CFCFCF", +"_@ c #F8F8F8", +":@ c #CACACA", +"<@ c #9A9999", +"[@ c #6E6C6B", +"}@ c #FEFEF5", +"|@ c #FAFBE9", +"1@ c #FBFCEE", +"2@ c #D4D3D4", +"3@ c #7E7E7C", +"4@ c #FCFCEC", +"5@ c #D4D4C2", +"6@ c #ACACAF", +"7@ c #808079", +"8@ c #F4F7B2", +"9@ c #EAEEA5", +"0@ c #ECF1A1", +"a@ c #A6A486", +"b@ c #727173", +"c@ c #A7A6A6", +"d@ c #868686", +"e@ c #787777", +"f@ c #717071", +"g@ c #959590", +"h@ c #FCFCEB", +"i@ c #FAFAE8", +"j@ c #AAAAA8", +"k@ c #D2D2C9", +"l@ c #F7F9DC", +"m@ c #FAFBD9", +"n@ c #818084", +"o@ c #ABABAD", +"p@ c #D2D3A2", +"q@ c #EBF0A9", +"r@ c #E9EEA0", +"s@ c #D6D890", +"t@ c #64626E", +"u@ c #838383", +"v@ c #828181", +"w@ c #CECECE", +"x@ c #949494", +"y@ c #6C6A6D", +"z@ c #C3C3B9", +"A@ c #F8FAE1", +"B@ c #FCFDF5", +"C@ c #A4A4A6", +"D@ c #A2A29B", +"E@ c #F7F8DA", +"F@ c #FAFBDD", +"G@ c #A6A5AB", +"H@ c #A4A483", +"I@ c #EBEFA8", +"J@ c #EAEFA3", +"K@ c #E9EE9F", +"L@ c #F4F6A3", +"M@ c #5F5E62", +"N@ c #9F9E9E", +"O@ c #888787", +"P@ c #9E9E9E", +"Q@ c #68676A", +"R@ c #E2E2D2", +"S@ c #F8F9DE", +"T@ c #A2A2A4", +"U@ c #9E9F96", +"V@ c #FAFBDA", +"W@ c #A2A2A9", +"X@ c #A0A07E", +"Y@ c #EBEFA7", +"Z@ c #EAEEA2", +"`@ c #E8EE9E", +" # c #F0F49C", +".# c #7F7F77", +"+# c #727070", +"@# c #6D6C6A", +"## c #FAFCE8", +"$# c #A2A298", +"%# c #F5F8D6", +"&# c #FAFAD9", +"*# c #A5A5AA", +"=# c #A4A481", +"-# c #EAEFA6", +";# c #EAEEA1", +"># c #E9ED9C", +",# c #E7EC96", +"'# c #999881", +")# c #585757", +"!# c #77766F", +"~# c #FAFBE2", +"{# c #FBFCE7", +"]# c #7F7F81", +"^# c #282828", +"/# c #686868", +"(# c #A9A9A1", +"_# c #D2D2C3", +":# c #F5F7D2", +"<# c #F9FAD1", +"[# c #80807F", +"}# c #AAAAA5", +"|# c #D2D29E", +"1# c #EAEFA4", +"2# c #E8ED9B", +"3# c #EAEF98", +"4# c #99987D", +"5# c #ACABAB", +"6# c #808075", +"7# c #DFDFC7", +"8# c #F6F8D6", +"9# c #D3D3C8", +"0# c #BBBBBB", +"a# c #1E1E1E", +"b# c #666667", +"c# c #7C7C72", +"d# c #FAFBDB", +"e# c #F3F5CC", +"f# c #D3D4B6", +"g# c #7E7E6B", +"h# c #F3F6AC", +"i# c #E9EE9E", +"j# c #E8ED9A", +"k# c #F2F69C", +"l# c #575849", +"m# c #636262", +"n# c #ECEBEB", +"o# c #7F7E7E", +"p# c #8B8A8A", +"q# c #61605C", +"r# c #DFE0C2", +"s# c #FAFCDF", +"t# c #7C7D73", +"u# c #B0AFAE", +"v# c #939394", +"w# c #CCCCC9", +"x# c #7F7F70", +"y# c #D2D2BC", +"z# c #F7FAC7", +"A# c #7E7E71", +"B# c #B0B0B0", +"C# c #CCCCCA", +"D# c #808179", +"E# c #D1D29D", +"F# c #EAEFA5", +"G# c #EAEEA0", +"H# c #E8ED9C", +"I# c #E8EC98", +"J# c #F1F597", +"K# c #898A74", +"L# c #888686", +"M# c #B1B1B1", +"N# c #88898C", +"O# c #ACADAF", +"P# c #A6A6A6", +"Q# c #878686", +"R# c #787877", +"S# c #B7B89D", +"T# c #F3F6CC", +"U# c #F4F7D1", +"V# c #F4F6D2", +"W# c #FAFADA", +"X# c #D2D2BF", +"Y# c #A2A292", +"Z# c #A5A592", +"`# c #FCFDE2", +" $ c #F6F8CF", +".$ c #F1F4C5", +"+$ c #F6F8C0", +"@$ c #D2D3A9", +"#$ c #A3A482", +"$$ c #A6A684", +"%$ c #F8FAB7", +"&$ c #EEF2A9", +"*$ c #F2F59E", +"=$ c #414148", +"-$ c #7E7E7E", +";$ c #FBFBFB", +">$ c #666344", +",$ c #696F76", +"'$ c #E4E3E3", +")$ c #BBBABA", +"!$ c #A8A7A7", +"~$ c #A5A49C", +"{$ c #B2B29D", +"]$ c #F5F8CA", +"^$ c #F3F6CB", +"/$ c #F4F6CD", +"($ c #F1F4C1", +"_$ c #EFF2BB", +":$ c #EEF1B4", +"<$ c #EDF1B0", +"[$ c #ECF0AD", +"}$ c #EBF0A8", +"|$ c #E8EC99", +"1$ c #E7EC94", +"2$ c #F6F8AF", +"3$ c #444445", +"4$ c #A3A2A2", +"5$ c #CDCDCD", +"6$ c #B7B7B7", +"7$ c #8C8B7A", +"8$ c #61593A", +"9$ c #B4B5B7", +"0$ c #D0CFD6", +"a$ c #F2F2B2", +"b$ c #86866E", +"c$ c #F8FACF", +"d$ c #F2F4C7", +"e$ c #F3F5C9", +"f$ c #F2F5C6", +"g$ c #F0F3BD", +"h$ c #EFF2BA", +"i$ c #EDF1B1", +"j$ c #EBEFAA", +"k$ c #E9ED9E", +"l$ c #E6EB90", +"m$ c #9F9E70", +"n$ c #626263", +"o$ c #5A5B61", +"p$ c #CBB250", +"q$ c #757A83", +"r$ c #ACACAE", +"s$ c #A1A09B", +"t$ c #F8FE9A", +"u$ c #65646D", +"v$ c #DEDFB6", +"w$ c #F1F4C3", +"x$ c #F1F4C4", +"y$ c #EFF3BC", +"z$ c #EEF2B4", +"A$ c #EBEFA6", +"B$ c #E6EC94", +"C$ c #EFF48E", +"D$ c #5C5A6B", +"E$ c #72727A", +"F$ c #BCBCBC", +"G$ c #948A57", +"H$ c #5A5548", +"I$ c #C8C8BB", +"J$ c #FBFE9D", +"K$ c #9D9C95", +"L$ c #74755E", +"M$ c #F6F9C2", +"N$ c #F0F2BC", +"O$ c #EFF2B8", +"P$ c #EEF2B5", +"Q$ c #EDF1B2", +"R$ c #EAEEA3", +"S$ c #E7EC98", +"T$ c #E6EB8F", +"U$ c #C4C691", +"V$ c #88877C", +"W$ c #D8D8B9", +"X$ c #ACACAC", +"Y$ c #7A8693", +"Z$ c #887750", +"`$ c #C0C38A", +" % c #A4A39C", +".% c #E0DFE2", +"+% c #91918E", +"@% c #D8DAAE", +"#% c #F1F5BB", +"$% c #DADDA4", +"%% c #EAEDAC", +"&% c #ECF0AC", +"*% c #ECEFA9", +"=% c #E7EC95", +"-% c #EAEF94", +";% c #E4E891", +">% c #83827E", +",% c #FAFCA8", +"'% c #F4F89C", +")% c #A2A1B6", +"!% c #6E717A", +"~% c #C0AC50", +"{% c #575C67", +"]% c #D2D2D4", +"^% c #EEEEEE", +"/% c #737466", +"(% c #DDE0AA", +"_% c #67684C", +":% c #727453", +"<% c #DADE9D", +"[% c #E6EB92", +"}% c #EEF292", +"|% c #373820", +"1% c #E6E6EA", +"2% c #CFD0C4", +"3% c #F3F6B1", +"4% c #EEF0AB", +"5% c #CECED5", +"6% c #C2C2C8", +"7% c #AAA982", +"8% c #9E925B", +"9% c #3B3730", +"0% c #9D9D9D", +"a% c #BBBABB", +"b% c #6A6C5C", +"c% c #F0F3B2", +"d% c #EDF0B0", +"e% c #ECF0B0", +"f% c #D9DC9D", +"g% c #EEF390", +"h% c #8C8C75", +"i% c #818085", +"j% c #9F9F9F", +"k% c #A0A0AE", +"l% c #FAFEAA", +"m% c #B2B2C2", +"n% c #D4D4C8", +"o% c #838368", +"p% c #686E76", +"q% c #6E6140", +"r% c #7F828C", +"s% c #797A68", +"t% c #DEDFA3", +"u% c #EFF3AE", +"v% c #ECF0AB", +"w% c #E9EE9D", +"x% c #E6EC92", +"y% c #F4F896", +"z% c #65664C", +"A% c #85858A", +"B% c #F1F1F3", +"C% c #DCDE94", +"D% c #E1E39F", +"E% c #E1E3BD", +"F% c #9D9C7F", +"G% c #BFC1C2", +"H% c #968E54", +"I% c #727988", +"J% c #50504E", +"K% c #D1D39D", +"L% c #F3F6AD", +"M% c #EAEFA7", +"N% c #E8ED99", +"O% c #E9EE90", +"P% c #F6FAA8", +"Q% c #4A4A44", +"R% c #909094", +"S% c #B6B6B6", +"T% c #BABABA", +"U% c #B7B7C0", +"V% c #F5F894", +"W% c #92919F", +"X% c #ACABB2", +"Y% c #EDEEB2", +"Z% c #B8B795", +"`% c #888876", +" & c #726949", +".& c #9C9C9E", +"+& c #88888C", +"@& c #60604F", +"#& c #D2D497", +"$& c #F4F6AB", +"%& c #EDF1A2", +"&& c #F0F495", +"*& c #F6F8AE", +"=& c #8C8C76", +"-& c #4C4C56", +";& c #C1C1C2", +">& c #CAC9D7", +",& c #F4F898", +"'& c #ACAAA0", +")& c #B8B7C5", +"!& c #F4F6A0", +"~& c #5A5D66", +"{& c #C79A29", +"]& c #565961", +"^& c #898989", +"/& c #BDBDBD", +"(& c #565660", +"_& c #50504D", +":& c #848366", +"<& c #A1A16C", +"[& c #F6F9B4", +"}& c #F2F5A2", +"|& c #F2F5A9", +"1& c #CBCD94", +"2& c #88885F", +"3& c #525250", +"4& c #6B6A76", +"5& c #8E8E90", +"6& c #B8B8B8", +"7& c #9696A4", +"8& c #F4F6A2", +"9& c #D2D1AE", +"0& c #BCBC99", +"a& c #9F9F92", +"b& c #787253", +"c& c #AFA99C", +"d& c #606061", +"e& c #DDDDE4", +"f& c #CACACC", +"g& c #BFBFC1", +"h& c #808087", +"i& c #808088", +"j& c #808086", +"k& c #A1A0B3", +"l& c #A3A3A3", +"m& c #B9B9C4", +"n& c #F5F79E", +"o& c #EDF0B2", +"p& c #ACACB8", +"q& c #C2C2AE", +"r& c #77796E", +"s& c #968261", +"t& c #88876C", +"u& c #B3B293", +"v& c #E3E2D6", +"w& c #B4B3B6", +"x& c #DADADA", +"y& c #ECECEC", +"z& c #C6C6A2", +"A& c #ECF0A1", +"B& c #EAECC6", +"C& c #C2C2C4", +"D& c #E8E9C4", +"E& c #EDF1A0", +"F& c #ECEFB1", +"G& c #E6E8C2", +"H& c #A0A09C", +"I& c #E9EBBD", +"J& c #FDFF9C", +"K& c #8E8C95", +"L& c #CFCE96", +"M& c #9E9DA9", +"N& c #DBDBDB", +"O& c #C9C9CB", +"P& c #B6B5C4", +"Q& c #F2F698", +"R& c #ECF0A2", +"S& c #B8B893", +"T& c #B4B4B4", +"U& c #E0E0E0", +"V& c #9796A7", +"W& c #F4F89F", +"X& c #ECF09F", +"Y& c #EEF29A", +"Z& c #A6A4CC", +"`& c #E4E4A8", +" * c #E8E8C1", +".* c #A1A0A8", +"+* c #B6B6B8", +"@* c #E1E3B0", +"#* c #EFF49A", +"$* c #F6FA9D", +"%* c #A1A0B1", +"&* c #E1E0E3", +"** c #BCBCB2", +"=* c #ECF09E", +"-* c #DFDFC4", +";* c #D8D8A0", +">* c #B2B28E", +",* c #A4A4A9", +"'* c #848490", +")* c #D0D1AB", +"!* c #F1F5AE", +"~* c #EAEE9B", +"{* c #9998A9", +"]* c #DCDCDF", +"^* c #B9B9BC", +"/* c #BEBEB5", +"(* c #F2F59F", +"_* c #EBEFA0", +":* c #F5FA96", +"<* c #EEF0A6", +"[* c #BCBBC1", +"}* c #8D8D8F", +"|* c #BFBEC3", +"1* c #AFAE8C", +"2* c #DFE0A6", +"3* c #DADDA2", +"4* c #EDF29C", +"5* c #BEBD9C", +"6* c #CECD9D", +"7* c #B8B8BC", +"8* c #D1D1D3", +"9* c #ACACA0", +"0* c #E4E6C0", +"a* c #E3E6BF", +"b* c #D4D4B0", +"c* c #ACABB7", +"d* c #F7F7F7", +"e* c #B1B09C", +"f* c #DEDDF2", +"g* c #89886A", +"h* c #FAFAB4", +"i* c #A6A4C2", +"j* c #F5F4B3", +"k* c #C2C2B4", +"l* c #B6B5BC", +"m* c #B3B3B3", +"n* c #A4A4A4", +"o* c #98989D", +"p* c #5A5A5C", +"q* c #6A6A6A", +"r* c #8D8D92", +"s* c #464648", +"t* c #9B9AA2", +"u* c #838371", +"v* c #86868F", +"w* c #7E7E87", +"x* c #868688", +"y* c #9B9B9B", +"z* c #D7D7D7", +" ", +" . + @ # ", +" $ % & * = - ; > , ' ) ", +" ! ~ { > ] ^ / ( _ : < ", +" > [ } } [ | 1 2 3 4 5 6 7 8 9 0 a b c ", +" > d : e f g h i j k 9 9 9 l m n o p q r s : ", +" t ^ u v | w x y z A B C D E F G H n 9 9 9 I J K L b ' M ", +" ] + N O L P Q y r R S T U V W X Y Z ` ...+.@.9 9 9 9 9 #. $.I %. ", +" &.*.=. { < # z -.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.9 1.2.3.4. > ", +" s L 5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.n 9 s.t. > f ", +" u.v.w.x.k 9 y.z.A.B.C.D.e.f.E.F.G.H.I.J.K.L.M.N.O.r.9 9 s.P. ) Q. ", +" R.S.T. =.U.V.W.X.Y.Z.`. +.+++C.D.e.@+#+$+j.k.%+&+*+=+-+;+>+r.9 n 1.,+ ", +" '+)+{ Q !+~+1.{+]+^+/+(+_+:+<+++C.d.[+g.}+G.|+l.1+2+3+4+5+6+7+8+n 9+0+$ ", +" + a+b+!+W.c+d+Z.e+f+g+h+i+:+.+B.j+k+l+h.m+n+o+p+q+r+s+t+u+v+w+9 n ~ 3 ", +" x+y+z+ A+B+C+W.D+E+:+f+F+G+: H+I+E+J+K+e.l+h.i.L+M+N+O+P+Q+5+R+S+T+U+9 m V+P ", +" d W+[ X+: Y+Z+`+ @.@:++@@@#@$@ %@&@*@=@e.@+-@;@>@,@ '@)@!@5+R+~@{@]@n ^@/@(@ ", +" _@! :@<@B o [@}@|@1@i+2@N 3@4@k+l+h.5@6@ 7@8@R+9@0@a@b@9+0 c@ ", +" 2 W.d@e@f@g@h@i@<+h+#@ j@k@l@g.m@n@ o@p@q@~@r@s@t@1.u@v@S $ ", +" w@I <@x@m y@z@A@C.++B@C@ D@E@E.F@G@ H@I@J@K@L@M@b+4 N@j O@ ", +" P@u@! b+b+Q@R@S@D.C.i+T@ U@g.-@V@W@ X@Y@Z@`@ #.#1.+#*.R.7 ", +" P@2.^@Z+x.@###f.S@A@_+C@ X+L &. $#%#}+&#*# X+L &. =#-#;#>#,#'#B 1.e@v@)# ", +" P@9 Z+1.x.!#~#g.f.l@{#]# { ^#/# (#_#:#m+<#[# { ^#/# }#|#1#r@2#3#4#l 1.Z+Z+)# ", +" 5#n V+B 1.6#7#h.8#g.@+9#o@0#a#b# c#d#m+e#k.f#6@0#a#b# g#h#Z@i#j#k#l#V.Z+V.u m# ", +" n#o#p#C+1.q#r#i.:#h.#+s#t#u#v#w#x#y#m+e#k.l.z#A#B#v#C#D#E#F#G#H#I#J#K#m B L#C+g ", +" M#N#O#P#Q#W.R#S#T#G.i.U#V#W#X#Y#Z#`# $H.k..$J.K.+$@$#$$$%$&$Z@i#j#,#*$=$9 V.-$;$ ", +" I+>$,$'$)$!$~${$]$(.^$T#/$G.G./$T#H.k.I.%+($K._$r+:$<$[$}$1#G#H#|$1$2$3$4$c@5$ ", +" 6$7$8$9$Q.0$a$b$c$l.d$k.k.k.e$k.I.f$%+J.m.g$h$3+:$i$[$j$-#Z@k$j#,#l$m$n$ (@ ", +" ] o$p$q$r$s$t$u$v$1+J.w$x$%+%+x$J.p+m.K.y$L.=+z$i$[$j$A$Z@K@2#I#B$C$D$E$ F$ ", +" , G$H$I$J$K$ L$M$K.K.&+&+&+K.K.q+N$h$O$P$Q$<$[$j$A$R$r@H#S$1$T$U$V$W$L . - ", +" X$Y$Z$`$ %.% +%@%#%L.*+h$h$h$L.r+=+P$$%$%%%&%*%A$R$r@H#|$=%-%;%>%,%'%)%L . ", +" )+!%~%{%]%^% /%(%M.P$=+=+P$z$s+4+<$_%:%<%I@F#Z@r@H#|$=%[%}%|%1%2%3%4%5%+ ", +" 6%7%8%9%0%( y+y+a%b%P+c%d%d%d%e%5+5+&%f%I@Y@~@;#i#H#|$,#[%g%h%i%6$j%k%l%m%5$ ", +" - n%o%p%q%r%f : s%t%u%&%v%v%R+q@I@A$1#Z@r@w%j#S$=%x%y%z%A% B%C%D%,@ ", +" < E%F%G%H%I%S.y+y+y+y+0#J%K%L%M%-#A$~@R$Z@r@i#H#N%,#B$O%P%Q%R%S%y+y+y+T%U%V%W% ", +" X%Y%Z%M#`% &.&L +&@&#&$&%&r@i#>#H#j#I#1$&&*&=&-&;& >&,&'&a+ ", +" )&!&Z%L ~&{&]&^&/&( y+y+y+S%F$(&_&:&<&[&L@}&|&1&2&3&4&5&6$6$6$6$6$6$6$6&7&8&9&= ", +" )&!&0&5$a&b&c&d&e&f& g&h&i&i&j&j& ;$> z+z+z+z+z+z+z+z+> k&8&E%l& ", +" m&n&o&p&q&r&s&t&u&v&w&| x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&y&z&A&B&6& ", +" C&D&E&F&G&H&I&J&K&L&M&| x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&N&O&P&Q&R&S&T& ", +" U&V&W&Z@Z@X&Y&Z&`& *.*| x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&{ f %.+*@*#*$*%*. - ", +" > Q.&*** #Z@Z@=*-*;*>*,*| x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&( '*)*!*~*e%{*]*- . ", +" . - ^*/*(*Z@_*:*<*[*}*6$6$6$6$6$6$6$6$6$6$6$6$6$6$6$6$6$6$6$T%|*1*2*3*4*5*6*7* F$ ", +" F$ &.8*9*0*a*b*c*f&d*z+z+z+z+z+z+z+z+z+z+z+z+z+z+z+z+z+z+z+> e*f*g*h*i*j*k*l* Q. ", +" F$ m*6&S%* l&n*o*p*q*0#y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+X$r*s*t*u*v*w*x*y* F$ ", +" z*y& #. ", +" ( w@Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q./&e ", +" ", +" "};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/backend-fluidsynth/Makefile.in Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,15 @@ +include ../../../../mk/rules.mk +include ../../../../mk/objective.mk + +noinst_HEADERS = b-fluidsynth.h b-fluidsynth-config.h backend-fluidsynth-icon.xpm + +CFLAGS += -fPIC -DPIC $(GLIB_CFLAGS) $(FLUIDSYNTH_CFLAGS) -I../../../../intl -I../../../.. + +libdir = $(AMIDIPLUGDATADIR) + +OBJECTIVE_LIBS = ap-fluidsynth.so + +LIBADD = -lm $(GLIB_LIBS) $(FLUIDSYNTH_LIBS) ../pcfg/libpcfg.a +SOURCES = b-fluidsynth.c + +OBJECTS = ${SOURCES:.c=.o}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/backend-fluidsynth/b-fluidsynth-config.h Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,41 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#ifndef _B_FLUIDSYNTH_CONFIG_H +#define _B_FLUIDSYNTH_CONFIG_H 1 + + +typedef struct +{ + gchar * fsyn_soundfont_file; + gint fsyn_soundfont_load; + gint fsyn_synth_samplerate; + gint fsyn_synth_gain; + gint fsyn_synth_poliphony; + gint fsyn_synth_reverb; + gint fsyn_synth_chorus; + gint fsyn_buffer_size; + gint fsyn_buffer_margin; + gint fsyn_buffer_increment; +} +amidiplug_cfg_fsyn_t; + + +#endif /* !_B_FLUIDSYNTH_CONFIG_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/backend-fluidsynth/b-fluidsynth.c Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,455 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#include "b-fluidsynth.h" +#include "b-fluidsynth-config.h" + +/* sequencer instance */ +static sequencer_client_t sc; +/* options */ +static amidiplug_cfg_fsyn_t amidiplug_cfg_fsyn; + + +gint backend_info_get( gchar ** name , gchar ** longname , gchar ** desc , gint * ppos ) +{ + if ( name != NULL ) + *name = g_strdup( "fluidsynth" ); + if ( longname != NULL ) + *longname = g_strdup( "FluidSynth Backend " AMIDIPLUG_VERSION ); + if ( desc != NULL ) + *desc = g_strdup( _("This backend produces audio by sending MIDI events " + "to FluidSynth, a real-time software synthesizer based " + "on the SoundFont2 specification (www.fluidsynth.org).\n" + "Produced audio can be manipulated via player effect " + "plugins and is processed by chosen ouput plugin.\n" + "Backend written by Giacomo Lozito.") ); + if ( ppos != NULL ) + *ppos = 2; /* preferred position in backend list */ + return 1; +} + + +gint backend_init( void ) +{ + /* read configuration options */ + i_cfg_read(); + + sc.soundfont_id = -1; + sc.sample_rate = amidiplug_cfg_fsyn.fsyn_synth_samplerate; + sc.settings = new_fluid_settings(); + + fluid_settings_setnum( sc.settings , "synth.sample-rate" , amidiplug_cfg_fsyn.fsyn_synth_samplerate ); + if ( amidiplug_cfg_fsyn.fsyn_synth_gain != -1 ) + fluid_settings_setnum( sc.settings , "synth.gain" , (gdouble)amidiplug_cfg_fsyn.fsyn_synth_gain / 10 ); + if ( amidiplug_cfg_fsyn.fsyn_synth_poliphony != -1 ) + fluid_settings_setint( sc.settings , "synth.poliphony" , amidiplug_cfg_fsyn.fsyn_synth_poliphony ); + if ( amidiplug_cfg_fsyn.fsyn_synth_reverb == 1 ) + fluid_settings_setstr( sc.settings , "synth.reverb.active" , "yes" ); + else if ( amidiplug_cfg_fsyn.fsyn_synth_reverb == 0 ) + fluid_settings_setstr( sc.settings , "synth.reverb.active" , "no" ); + if ( amidiplug_cfg_fsyn.fsyn_synth_chorus == 1 ) + fluid_settings_setstr( sc.settings , "synth.chorus.active" , "yes" ); + else if ( amidiplug_cfg_fsyn.fsyn_synth_chorus == 0 ) + fluid_settings_setstr( sc.settings , "synth.chorus.active" , "no" ); + + sc.synth = new_fluid_synth( sc.settings ); + + /* soundfont loader, check if we should load soundfont on backend init */ + if ( amidiplug_cfg_fsyn.fsyn_soundfont_load == 0 ) + i_soundfont_load(); + + return 1; +} + + +gint backend_cleanup( void ) +{ + if ( sc.soundfont_id != -1 ) + fluid_synth_sfunload( sc.synth , sc.soundfont_id , 0 ); + delete_fluid_synth( sc.synth ); + delete_fluid_settings( sc.settings ); + + i_cfg_free(); /* free configuration options */ + + return 1; +} + + +gint sequencer_get_port_count( void ) +{ + /* always return a single port here */ + return 1; +} + + +gint sequencer_start( gchar * midi_fname ) +{ + /* soundfont loader, check if we should load soundfont on first midifile play */ + if (( amidiplug_cfg_fsyn.fsyn_soundfont_load == 1 ) && (sc.soundfont_id == -1 )) + i_soundfont_load(); + + return 1; /* success */ +} + + +gint sequencer_stop( void ) +{ + return 1; /* success */ +} + + +/* activate sequencer client */ +gint sequencer_on( void ) +{ + sc.last_sample_time = 0; + sc.tick_offset = 0; + + sc.timer_seq = g_timer_new(); /* create the sequencer timer */ + sc.timer_sample = g_timer_new(); /* create the sampler timer */ + + return 1; /* success */ +} + + +/* shutdown sequencer client */ +gint sequencer_off( void ) +{ + if ( sc.timer_seq != NULL ) + { + g_timer_destroy( sc.timer_seq ); /* destroy the sequencer timer */ + sc.timer_seq = NULL; + } + if ( sc.timer_sample != NULL ) + { + g_timer_destroy( sc.timer_sample ); /* destroy the sampler timer */ + sc.timer_sample = NULL; + } + return 1; /* success */ +} + + +/* queue set tempo */ +gint sequencer_queue_tempo( gint tempo , gint ppq ) +{ + sc.ppq = ppq; + /* sc.cur_tick_per_sec = (gdouble)( ppq * 1000000 ) / (gdouble)tempo; */ + sc.cur_microsec_per_tick = (gdouble)tempo / (gdouble)ppq; + return 1; +} + + +gint sequencer_queue_start( void ) +{ + g_timer_start( sc.timer_seq ); /* reset the sequencer timer */ + g_timer_start( sc.timer_sample ); /* reset the sampler timer */ + return 1; +} + + +gint sequencer_event_init( void ) +{ + /* common settings for all our events */ + return 1; +} + + +gint sequencer_event_noteon( midievent_t * event ) +{ + i_sleep( event->tick_real ); + fluid_synth_noteon( sc.synth , + event->data.d[0] , + event->data.d[1] , + event->data.d[2] ); + return 1; +} + + +gint sequencer_event_noteoff( midievent_t * event ) +{ + i_sleep( event->tick_real ); + fluid_synth_noteoff( sc.synth , + event->data.d[0] , + event->data.d[1] ); + return 1; +} + + +gint sequencer_event_keypress( midievent_t * event ) +{ + /* KEY PRESSURE events are not handled by FluidSynth sequencer? */ + DEBUGMSG( "KEYPRESS EVENT with FluidSynth backend (unhandled)\n" ); + i_sleep( event->tick_real ); + return 1; +} + + +gint sequencer_event_controller( midievent_t * event ) +{ + i_sleep( event->tick_real ); + fluid_synth_cc( sc.synth , + event->data.d[0] , + event->data.d[1] , + event->data.d[2] ); + return 1; +} + + +gint sequencer_event_pgmchange( midievent_t * event ) +{ + i_sleep( event->tick_real ); + fluid_synth_program_change( sc.synth , + event->data.d[0] , + event->data.d[1] ); + return 1; +} + + +gint sequencer_event_chanpress( midievent_t * event ) +{ + /* CHANNEL PRESSURE events are not handled by FluidSynth sequencer? */ + DEBUGMSG( "CHANPRESS EVENT with FluidSynth backend (unhandled)\n" ); + i_sleep( event->tick_real ); + return 1; +} + + +gint sequencer_event_pitchbend( midievent_t * event ) +{ + gint pb_value = (((event->data.d[2]) & 0x7f) << 7) | ((event->data.d[1]) & 0x7f); + i_sleep( event->tick_real ); + fluid_synth_pitch_bend( sc.synth , + event->data.d[0] , + pb_value ); + return 1; +} + + +gint sequencer_event_sysex( midievent_t * event ) +{ + DEBUGMSG( "SYSEX EVENT with FluidSynth backend (unhandled)\n" ); + i_sleep( event->tick_real ); + return 1; +} + + +gint sequencer_event_tempo( midievent_t * event ) +{ + i_sleep( event->tick_real ); + /* sc.cur_tick_per_sec = (gdouble)( sc.ppq * 1000000 ) / (gdouble)event->data.tempo; */ + sc.cur_microsec_per_tick = (gdouble)event->data.tempo / (gdouble)sc.ppq; + g_timer_start( sc.timer_seq ); /* reset the sequencer timer */ + sc.tick_offset = event->tick_real; + return 1; +} + + +gint sequencer_event_other( midievent_t * event ) +{ + /* unhandled */ + i_sleep( event->tick_real ); + return 1; +} + + +gint sequencer_output( gpointer * buffer , gint * len ) +{ + gdouble current_time = g_timer_elapsed( sc.timer_sample , NULL ); + if (( current_time > 0.000500 ) && + ( (current_time - sc.last_sample_time) * 1000000 >= + ((gdouble)amidiplug_cfg_fsyn.fsyn_buffer_size * 1000000 / sc.sample_rate) )) + { + sc.last_sample_time = g_timer_elapsed( sc.timer_sample , NULL ) - 0.000500; + /* number of samples to get = buffer size + incremental margin */ + /* g_print( "buf increment: %i\n" , amidiplug_cfg_fsyn.fsyn_buffer_margin + + ((gint)sc.last_sample_time / amidiplug_cfg_fsyn.fsyn_buffer_increment) ); */ + *len = (amidiplug_cfg_fsyn.fsyn_buffer_size + amidiplug_cfg_fsyn.fsyn_buffer_margin + + ((gint)sc.last_sample_time / amidiplug_cfg_fsyn.fsyn_buffer_increment) ); + *buffer = g_realloc( *buffer , *len * 4 ); + fluid_synth_write_s16( sc.synth , *len , *buffer , 0 , 2 , *buffer , 1 , 2 ); + *len = *len * 4; /* return the real buffer size in bytes */ + return 1; + } + else + { + G_USLEEP( 500 ); + return 0; + } +} + + +gint sequencer_output_shut( guint max_tick , gint skip_offset ) +{ + fluid_synth_system_reset( sc.synth ); /* all notes off and channels reset */ + return 1; +} + + +/* unimplemented, for autonomous audio == FALSE volume is set by the + output plugin mixer controls and is not handled by input plugins */ +gint audio_volume_get( gint * left_volume , gint * right_volume ) +{ + return 0; +} +gint audio_volume_set( gint left_volume , gint right_volume ) +{ + return 0; +} + + +gint audio_info_get( gint * channels , gint * bitdepth , gint * samplerate ) +{ + *channels = 2; + *bitdepth = 16; /* always 16 bit, we use fluid_synth_write_s16() */ + *samplerate = amidiplug_cfg_fsyn.fsyn_synth_samplerate; + return 1; /* valid information */ +} + + +gboolean audio_check_autonomous( void ) +{ + return FALSE; /* FluidSynth gives produced audio back to player */ +} + + + +/* ****************************************************************** + *** INTERNALS **************************************************** + ****************************************************************** */ + + +void i_sleep( guint tick ) +{ + gdouble elapsed_tick_usecs = (gdouble)(tick - sc.tick_offset) * sc.cur_microsec_per_tick; + gdouble elapsed_seq_usecs = g_timer_elapsed( sc.timer_seq , NULL ) * 1000000; + if ( elapsed_seq_usecs < elapsed_tick_usecs ) + { + G_USLEEP( elapsed_tick_usecs - elapsed_seq_usecs ); + } +} + + +void i_soundfont_load( void ) +{ + if ( strcmp( amidiplug_cfg_fsyn.fsyn_soundfont_file , "" ) ) + { + DEBUGMSG( "loading soundfont %s\n" , amidiplug_cfg_fsyn.fsyn_soundfont_file ); + sc.soundfont_id = fluid_synth_sfload( sc.synth , amidiplug_cfg_fsyn.fsyn_soundfont_file , 0 ); + if ( sc.soundfont_id == -1 ) + g_warning( "unable to load SoundFont file %s\n" , amidiplug_cfg_fsyn.fsyn_soundfont_file ); +#ifdef DEBUG + else + DEBUGMSG( "soundfont %s successfully loaded\n" , amidiplug_cfg_fsyn.fsyn_soundfont_file ); +#endif + } + else + { + g_warning( "FluidSynth backend was selected, but no SoundFont has been specified\n" ); + sc.soundfont_id = -1; + } +} + + +gboolean i_bounds_check( gint value , gint min , gint max ) +{ + if (( value >= min ) && ( value <= max )) + return TRUE; + else + return FALSE; +} + + +void i_cfg_read( void ) +{ + pcfg_t *cfgfile; + gchar * config_pathfilename = g_strjoin( "" , g_get_home_dir() , "/" , + PLAYER_LOCALRCDIR , "/amidi-plug.conf" , NULL ); + cfgfile = i_pcfg_new_from_file( config_pathfilename ); + + if ( !cfgfile ) + { + /* fluidsynth backend defaults */ + amidiplug_cfg_fsyn.fsyn_soundfont_file = g_strdup( "" ); + amidiplug_cfg_fsyn.fsyn_soundfont_load = 1; + amidiplug_cfg_fsyn.fsyn_synth_samplerate = 44100; + amidiplug_cfg_fsyn.fsyn_synth_gain = -1; + amidiplug_cfg_fsyn.fsyn_synth_poliphony = -1; + amidiplug_cfg_fsyn.fsyn_synth_reverb = -1; + amidiplug_cfg_fsyn.fsyn_synth_chorus = -1; + amidiplug_cfg_fsyn.fsyn_buffer_size = 512; + amidiplug_cfg_fsyn.fsyn_buffer_margin = 10; + amidiplug_cfg_fsyn.fsyn_buffer_increment = 18; + } + else + { + i_pcfg_read_string( cfgfile , "fsyn" , "fsyn_soundfont_file" , + &amidiplug_cfg_fsyn.fsyn_soundfont_file , "" ); + + i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_soundfont_load" , + &amidiplug_cfg_fsyn.fsyn_soundfont_load , 1 ); + + i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_synth_samplerate" , + &amidiplug_cfg_fsyn.fsyn_synth_samplerate , 44100 ); + if ( !i_bounds_check( amidiplug_cfg_fsyn.fsyn_synth_samplerate , 22050 , 96000 ) ) + amidiplug_cfg_fsyn.fsyn_synth_samplerate = 44100; + + i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_synth_gain" , + &amidiplug_cfg_fsyn.fsyn_synth_gain , -1 ); + if (( amidiplug_cfg_fsyn.fsyn_synth_gain != -1 ) && + ( !i_bounds_check( amidiplug_cfg_fsyn.fsyn_synth_gain , 0 , 100 ) )) + amidiplug_cfg_fsyn.fsyn_synth_gain = -1; + + i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_synth_poliphony" , + &amidiplug_cfg_fsyn.fsyn_synth_poliphony , -1 ); + if (( amidiplug_cfg_fsyn.fsyn_synth_poliphony != -1 ) && + ( !i_bounds_check( amidiplug_cfg_fsyn.fsyn_synth_poliphony , 0 , 100 ) )) + amidiplug_cfg_fsyn.fsyn_synth_poliphony = -1; + + i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_synth_reverb" , + &amidiplug_cfg_fsyn.fsyn_synth_reverb , -1 ); + + i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_synth_chorus" , + &amidiplug_cfg_fsyn.fsyn_synth_chorus , -1 ); + + i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_buffer_size" , + &amidiplug_cfg_fsyn.fsyn_buffer_size , 512 ); + if ( !i_bounds_check( amidiplug_cfg_fsyn.fsyn_buffer_size , 100 , 99999 ) ) + amidiplug_cfg_fsyn.fsyn_buffer_size = 512; + + i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_buffer_margin" , + &amidiplug_cfg_fsyn.fsyn_buffer_margin , 15 ); + if ( !i_bounds_check( amidiplug_cfg_fsyn.fsyn_buffer_margin , 0 , 100 ) ) + amidiplug_cfg_fsyn.fsyn_buffer_margin = 15; + + i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_buffer_increment" , + &amidiplug_cfg_fsyn.fsyn_buffer_increment , 18 ); + if ( !i_bounds_check( amidiplug_cfg_fsyn.fsyn_buffer_increment , 6 , 1000 ) ) + amidiplug_cfg_fsyn.fsyn_buffer_increment = 18; + + i_pcfg_free( cfgfile ); + } + + g_free( config_pathfilename ); +} + + +void i_cfg_free( void ) +{ + g_free( amidiplug_cfg_fsyn.fsyn_soundfont_file ); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/backend-fluidsynth/b-fluidsynth.h Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,56 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#ifndef _B_FLUIDSYNTH_H +#define _B_FLUIDSYNTH_H 1 + +#include <fluidsynth.h> +#include <math.h> +#include "../i_common.h" +#include "../pcfg/i_pcfg.h" +#include "../i_midievent.h" + + +typedef struct +{ + fluid_settings_t * settings; + fluid_synth_t * synth; + + gint soundfont_id; + + gint ppq; + gdouble cur_microsec_per_tick; + guint tick_offset; + + GTimer * timer_seq; + GTimer * timer_sample; + + guint sample_rate; + gdouble last_sample_time; +} +sequencer_client_t; + + +void i_sleep( guint ); +void i_soundfont_load( void ); +void i_cfg_read( void ); +void i_cfg_free( void ); + +#endif /* !_B_FLUIDSYNTH_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/backend-fluidsynth/backend-fluidsynth-icon.xpm Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,1408 @@ +/* XPM */ +static char * backend_fluidsynth_icon_xpm[] = { +"48 48 1357 2", +" c None", +". c #11002D", +"+ c #11002E", +"@ c #160830", +"# c #12022E", +"$ c #251F3E", +"% c #2C2B44", +"& c #170B32", +"* c #10002D", +"= c #160730", +"- c #211A3A", +"; c #10002C", +"> c #241839", +", c #1A0E33", +"' c #170930", +") c #11012D", +"! c #11022D", +"~ c #14052F", +"{ c #160931", +"] c #2A233E", +"^ c #16092F", +"/ c #332A41", +"( c #11012C", +"_ c #1A0D31", +": c #211534", +"< c #271F41", +"[ c #211838", +"} c #12032D", +"| c #363343", +"1 c #14062E", +"2 c #10012C", +"3 c #10002B", +"4 c #221A37", +"5 c #2F253D", +"6 c #1F1333", +"7 c #1B1036", +"8 c #1D1434", +"9 c #170C2F", +"0 c #12032C", +"a c #170B2F", +"b c #13072D", +"c c #10002A", +"d c #16072E", +"e c #231437", +"f c #28193C", +"g c #2F2140", +"h c #352841", +"i c #14052D", +"j c #231537", +"k c #12022B", +"l c #14052E", +"m c #251A3A", +"n c #231438", +"o c #2E2040", +"p c #13042D", +"q c #1E1033", +"r c #1B0C32", +"s c #17092F", +"t c #888277", +"u c #928C7F", +"v c #969083", +"w c #9B9587", +"x c #5B5258", +"y c #706868", +"z c #5E565B", +"A c #14052C", +"B c #0F002A", +"C c #11012B", +"D c #3E3249", +"E c #787070", +"F c #1B0B31", +"G c #989187", +"H c #CDCAA9", +"I c #493D50", +"J c #170C30", +"K c #392F42", +"L c #7B746F", +"M c #2A1E3A", +"N c #10012A", +"O c #1C0E31", +"P c #E2E3B0", +"Q c #EDEEBA", +"R c #F4F5BF", +"S c #F9F9C3", +"T c #6E6862", +"U c #B9B498", +"V c #847E72", +"W c #14062C", +"X c #281A3B", +"Y c #10012B", +"Z c #5F5560", +"` c #C0BCA3", +" . c #534958", +".. c #FBFBCA", +"+. c #FFFFCB", +"@. c #CBC8A6", +"#. c #11022B", +"$. c #14082E", +"%. c #201C39", +"&. c #3D3244", +"*. c #C1BF99", +"=. c #453B4B", +"-. c #2C2140", +";. c #1F1531", +">. c #17092E", +",. c #E3E3B1", +"'. c #F1F1BC", +"). c #F8F8C2", +"!. c #FDFDC6", +"~. c #716C65", +"{. c #B6B298", +"]. c #8B8677", +"^. c #2D203D", +"/. c #8B837C", +"(. c #16082F", +"_. c #5E5461", +":. c #C0BCA5", +"<. c #A49F8F", +"[. c #FFFFCD", +"}. c #FDFDC8", +"|. c #10022B", +"1. c #403645", +"2. c #C4C39B", +"3. c #433849", +"4. c #0F0029", +"5. c #291D3D", +"6. c #221A32", +"7. c #13052C", +"8. c #E2E2B2", +"9. c #E2E1B3", +"0. c #DEDCB2", +"a. c #E0DEB5", +"b. c #5A5258", +"c. c #AFAB95", +"d. c #8E897A", +"e. c #15062C", +"f. c #2A2344", +"g. c #14062D", +"h. c #645B5F", +"i. c #D1CFA8", +"j. c #5D5360", +"k. c #C0BCA4", +"l. c #100129", +"m. c #DCDAB5", +"n. c #E4E3B9", +"o. c #BEBA9E", +"p. c #FCFCC8", +"q. c #1E1032", +"r. c #443B48", +"s. c #C6C69D", +"t. c #3C3244", +"u. c #12052B", +"v. c #12042A", +"w. c #767167", +"x. c #231635", +"y. c #1F1133", +"z. c #15072D", +"A. c #A9A394", +"B. c #918C7E", +"C. c #15072C", +"D. c #292641", +"E. c #11032B", +"F. c #6B6264", +"G. c #DBDAAD", +"H. c #100229", +"I. c #5C525F", +"J. c #F5F5C7", +"K. c #5F565E", +"L. c #180A2F", +"M. c #C2BFA0", +"N. c #1D0F32", +"O. c #11022A", +"P. c #1B0E30", +"Q. c #483F4A", +"R. c #C8C89E", +"S. c #362A41", +"T. c #261E38", +"U. c #0F0028", +"V. c #110229", +"W. c #E1E1B1", +"X. c #726D65", +"Y. c #13052A", +"Z. c #190C2F", +"`. c #A59F94", +" + c #948F82", +".+ c #16082B", +"++ c #4A3F4F", +"@+ c #BDBA9B", +"#+ c #281B3B", +"$+ c #13042B", +"%+ c #5C525E", +"&+ c #C0BDA5", +"*+ c #231536", +"=+ c #FAFACB", +"-+ c #544A56", +";+ c #1C0E30", +">+ c #1F1135", +",+ c #544956", +"'+ c #2E223D", +")+ c #4C424C", +"!+ c #CACA9F", +"~+ c #33273E", +"{+ c #1B1131", +"]+ c #0F0128", +"^+ c #DEDDB1", +"/+ c #767068", +"(+ c #120429", +"_+ c #AAA99C", +":+ c #999488", +"<+ c #17092C", +"[+ c #352A40", +"}+ c #C1BDA5", +"|+ c #2B1E3B", +"1+ c #F4F4C7", +"2+ c #13052B", +"3+ c #12032A", +"4+ c #756A6F", +"5+ c #584D58", +"6+ c #50464F", +"7+ c #CCCCA0", +"8+ c #2F233B", +"9+ c #11032A", +"0+ c #322A4B", +"a+ c #1F1532", +"b+ c #DDDCB1", +"c+ c #78726B", +"d+ c #110429", +"e+ c #0E0028", +"f+ c #AFAFA3", +"g+ c #9D998F", +"h+ c #170A2C", +"i+ c #100128", +"j+ c #100228", +"k+ c #17082D", +"l+ c #605661", +"m+ c #FCFCCC", +"n+ c #1E1031", +"o+ c #180C2D", +"p+ c #160A2C", +"q+ c #110329", +"r+ c #231636", +"s+ c #7F7577", +"t+ c #716967", +"u+ c #534A52", +"v+ c #CECEA2", +"w+ c #30253D", +"x+ c #11052A", +"y+ c #0E0027", +"z+ c #231934", +"A+ c #DAD9B1", +"B+ c #7B766F", +"C+ c #120529", +"D+ c #959094", +"E+ c #A19D97", +"F+ c #170B2C", +"G+ c #281B3C", +"H+ c #261A38", +"I+ c #201235", +"J+ c #2C1E3E", +"K+ c #291C3B", +"L+ c #10032A", +"M+ c #0E012B", +"N+ c #190C31", +"O+ c #392A4A", +"P+ c #786E75", +"Q+ c #C2BFA6", +"R+ c #190D30", +"S+ c #3E3348", +"T+ c #0E0129", +"U+ c #1C1333", +"V+ c #261C39", +"W+ c #241637", +"X+ c #3B2D49", +"Y+ c #2A1C3D", +"Z+ c #372947", +"`+ c #2A1D3D", +" @ c #3E2F4E", +".@ c #1A0C2F", +"+@ c #41354B", +"@@ c #9A9386", +"#@ c #8E887C", +"$@ c #352842", +"%@ c #574E55", +"&@ c #CFCFA2", +"*@ c #54475C", +"=@ c #251738", +"-@ c #D2D0B0", +";@ c #807C7B", +">@ c #170B2D", +",@ c #12052A", +"'@ c #8F8996", +")@ c #A4A3A9", +"!@ c #231939", +"~@ c #9E9797", +"{@ c #2B2647", +"]@ c #0E022F", +"^@ c #7D767D", +"/@ c #4E4A66", +"(@ c #332E5B", +"_@ c #8C868A", +":@ c #110E50", +"<@ c #0E0C4F", +"[@ c #655E6E", +"}@ c #DAD7BA", +"|@ c #C7C3AB", +"1@ c #C4C4B0", +"2@ c #100F50", +"3@ c #F0F0C6", +"4@ c #888381", +"5@ c #0E0C4E", +"6@ c #0D0D4F", +"7@ c #37345F", +"8@ c #928D84", +"9@ c #0E0B4E", +"0@ c #0F0A49", +"a@ c #766C72", +"b@ c #7E7777", +"c@ c #7C777B", +"d@ c #786D73", +"e@ c #A8A28F", +"f@ c #9E9A84", +"g@ c #100329", +"h@ c #5C505F", +"i@ c #C2BF9E", +"j@ c #B9B698", +"k@ c #958E81", +"l@ c #65626C", +"m@ c #D0D0A4", +"n@ c #6E646B", +"o@ c #A3A085", +"p@ c #3B3241", +"q@ c #0E0026", +"r@ c #CCC9B1", +"s@ c #AAA798", +"t@ c #4D4157", +"u@ c #423552", +"v@ c #3F3450", +"w@ c #8F8DA5", +"x@ c #A6A6B1", +"y@ c #292553", +"z@ c #F7F7E2", +"A@ c #2F2E5A", +"B@ c #0E0C52", +"C@ c #C1C0BC", +"D@ c #6C6C83", +"E@ c #494874", +"F@ c #D6D6C2", +"G@ c #101055", +"H@ c #181758", +"I@ c #E0DEBF", +"J@ c #FFFFD5", +"K@ c #FFFFD3", +"L@ c #C7C6B5", +"M@ c #100E60", +"N@ c #D0D0BA", +"O@ c #231D50", +"P@ c #0E0E57", +"Q@ c #353568", +"R@ c #F7F7C4", +"S@ c #151354", +"T@ c #B3AD97", +"U@ c #9F9F96", +"V@ c #AFAF9E", +"W@ c #BEBA9D", +"X@ c #EFEFBA", +"Y@ c #403A57", +"Z@ c #746970", +"`@ c #E1E1B0", +" # c #DDDDAC", +".# c #6C6B72", +"+# c #D1D1A4", +"@# c #A9A58C", +"## c #C5C599", +"$# c #83806C", +"%# c #C7C4B2", +"&# c #F3F3E4", +"*# c #E0DEE1", +"=# c #DDDBE0", +"-# c #8C8B99", +";# c #8C8BA9", +"># c #ABABB6", +",# c #26245D", +"'# c #F7F7EB", +")# c #31315F", +"!# c #0E0C53", +"~# c #BBBBBC", +"{# c #6F6F8B", +"]# c #464775", +"^# c #DADAC6", +"/# c #141265", +"(# c #45437D", +"_# c #FEFED5", +":# c #C8C8BE", +"<# c #141583", +"[# c #9393AF", +"}# c #FFFFCE", +"|# c #767079", +"1# c #131379", +"2# c #1E1E74", +"3# c #FAFAC6", +"4# c #333368", +"5# c #1F1C56", +"6# c #CDCAA7", +"7# c #7B7B85", +"8# c #B1B19F", +"9# c #EBEBB9", +"0# c #E5E6B5", +"a# c #F0F0BB", +"b# c #6F6E7E", +"c# c #958F85", +"d# c #E6E7B3", +"e# c #DBDCAB", +"f# c #6F6E74", +"g# c #D1D2A4", +"h# c #C8C79D", +"i# c #BFBF96", +"j# c #A2A27F", +"k# c #120528", +"l# c #C0BDB5", +"m# c #FFFFFB", +"n# c #FFFFFF", +"o# c #9F9FAB", +"p# c #8787A5", +"q# c #B0B0BD", +"r# c #21205C", +"s# c #F6F6F4", +"t# c #343467", +"u# c #0D0D54", +"v# c #B7B7BC", +"w# c #737397", +"x# c #474584", +"y# c #DDDDCA", +"z# c #161676", +"A# c #8080A3", +"B# c #F9F9D4", +"C# c #6F70A6", +"D# c #A8A8BC", +"E# c #C9C9C5", +"F# c #191AA2", +"G# c #5252AF", +"H# c #FEFECE", +"I# c #DDDBB5", +"J# c #242189", +"K# c #19199C", +"L# c #E4E4C1", +"M# c #575890", +"N# c #2D2866", +"O# c #E7E6B7", +"P# c #535374", +"Q# c #B4B4A6", +"R# c #EBEBBA", +"S# c #313162", +"T# c #CACAAB", +"U# c #8B8B8C", +"V# c #747381", +"W# c #D7D7AD", +"X# c #A9A894", +"Y# c #828281", +"Z# c #6C6C77", +"`# c #D3D3A5", +" $ c #898473", +".$ c #67656F", +"+$ c #ACAC86", +"@$ c #201430", +"#$ c #0E0432", +"$$ c #B7B6C0", +"%$ c #9D9DAC", +"&$ c #7D7CA0", +"*$ c #B4B4C2", +"=$ c #21215C", +"-$ c #F6F6F8", +";$ c #36366C", +">$ c #100F64", +",$ c #B6B5C3", +"'$ c #76769C", +")$ c #444387", +"!$ c #E0E0CE", +"~$ c #181882", +"{$ c #AAABB9", +"]$ c #BCBCC5", +"^$ c #1A1A9F", +"/$ c #5F5FB3", +"($ c #CACAC8", +"_$ c #1C1CB2", +":$ c #2020B6", +"<$ c #D3D4CA", +"[$ c #FEFECC", +"}$ c #66639D", +"|$ c #C3C3BE", +"1$ c #7A7AAB", +"2$ c #403A73", +"3$ c #F8F8C1", +"4$ c #323270", +"5$ c #B8B8AD", +"6$ c #A8A89A", +"7$ c #0E0E54", +"8$ c #9A9A94", +"9$ c #9D9D94", +"0$ c #4B4B73", +"a$ c #C5C6A5", +"b$ c #5C5A74", +"c$ c #0F0C53", +"d$ c #6A6979", +"e$ c #D2D3A4", +"f$ c #392F3F", +"g$ c #484561", +"h$ c #A9A988", +"i$ c #2B2037", +"j$ c #0F0B4F", +"k$ c #B2B1C5", +"l$ c #D0D0D4", +"m$ c #9191B0", +"n$ c #8C8CB2", +"o$ c #54548A", +"p$ c #75759E", +"q$ c #B7B7C6", +"r$ c #21215D", +"s$ c #F4F4F7", +"t$ c #3A3976", +"u$ c #12106B", +"v$ c #B4B4C3", +"w$ c #7979A1", +"x$ c #41428F", +"y$ c #E1E1D1", +"z$ c #1A1A8A", +"A$ c #C6C6C6", +"B$ c #8383BE", +"C$ c #1C1CB1", +"D$ c #5F5FBE", +"E$ c #CACACC", +"F$ c #1E1EC1", +"G$ c #1F1FC6", +"H$ c #7373CD", +"I$ c #B0AEAE", +"J$ c #1E1FC1", +"K$ c #A3A3C3", +"L$ c #9B9BB8", +"M$ c #5E5A88", +"N$ c #F2F2C1", +"O$ c #1D1E7F", +"P$ c #BBBCB4", +"Q$ c #727382", +"R$ c #0D0D55", +"S$ c #89888D", +"T$ c #A5A598", +"U$ c #45456E", +"V$ c #C5C5A4", +"W$ c #555472", +"X$ c #0E0C54", +"Y$ c #6D6C7B", +"Z$ c #CACA9E", +"`$ c #130628", +" % c #47455A", +".% c #A5A589", +"+% c #2F2439", +"@% c #110E60", +"#% c #ACACC7", +"$% c #A9A9B0", +"%% c #201F69", +"&% c #11116E", +"*% c #111270", +"=% c #7374A9", +"-% c #BABAC9", +";% c #212161", +">% c #F2F2F6", +",% c #3F3E7C", +"'% c #121171", +")% c #B1B1C4", +"!% c #7B7CA8", +"~% c #3D3D92", +"{% c #E4E4D3", +"]% c #1C1C96", +"^% c #D8D8CE", +"/% c #6363BD", +"(% c #1E1EBD", +"_% c #5F5FC8", +":% c #CDCDCE", +"<% c #2121CF", +"[% c #2222D7", +"}% c #2A29DB", +"|% c #E0E0CF", +"1% c #E2E2C1", +"2% c #2222D2", +"3% c #8485CD", +"4% c #BCBDC2", +"5% c #8282AE", +"6% c #D6D6BE", +"7% c #1A1B93", +"8% c #BFBFB9", +"9% c #6D6D85", +"0% c #0E0D55", +"a% c #87878F", +"b% c #A6A699", +"c% c #3F3F6B", +"d% c #C6C6A5", +"e% c #4E4F70", +"f% c #706F7C", +"g% c #C2C29C", +"h% c #0E0534", +"i% c #4A4759", +"j% c #A9A98A", +"k% c #2E2439", +"l% c #110F67", +"m% c #A4A4C5", +"n% c #AEADB5", +"o% c #21216C", +"p% c #111271", +"q% c #121273", +"r% c #6F70AA", +"s% c #C0BFCC", +"t% c #22216D", +"u% c #EFEFF4", +"v% c #434381", +"w% c #121375", +"x% c #AEAFC6", +"y% c #8080AD", +"z% c #3C3D96", +"A% c #E5E5D4", +"B% c #1E1E9F", +"C% c #E3E3D1", +"D% c #5151BD", +"E% c #1F1FC2", +"F% c #5E5ECD", +"G% c #CECED1", +"H% c #2322D9", +"I% c #2424E0", +"J% c #2424DF", +"K% c #8888D5", +"L% c #3333DE", +"M% c #6464D2", +"N% c #DFDFC8", +"O% c #A5A5C1", +"P% c #B3B4BD", +"Q% c #1D1EA4", +"R% c #C1C1BB", +"S% c #68688F", +"T% c #100F60", +"U% c #888890", +"V% c #A5A698", +"W% c #3A3A68", +"X% c #4D4D77", +"Y% c #11116B", +"Z% c #757581", +"`% c #BEBE9C", +" & c #4C4A60", +".& c #AFAF8E", +"+& c #2C2237", +"@& c #9E9DC3", +"#& c #B1B1B9", +"$& c #23246E", +"%& c #121274", +"&& c #6869A7", +"*& c #C4C3CF", +"=& c #201F6E", +"-& c #EBEBF2", +";& c #464685", +">& c #13137A", +",& c #AAAAC6", +"'& c #8585B1", +")& c #3B3B97", +"!& c #E7E7D6", +"~& c #1F1FA3", +"{& c #E7E7D3", +"]& c #4D4DC0", +"^& c #1F1FC5", +"/& c #5D5DD0", +"(& c #D0D0D1", +"_& c #2323DB", +":& c #2424E2", +"<& c #2424E3", +"[& c #4343DE", +"}& c #4343E2", +"|& c #4545D9", +"1& c #F9F9C6", +"2& c #D7D7B5", +"3& c #9293BF", +"4& c #1F20B2", +"5& c #C3C4BE", +"6& c #676792", +"7& c #12116D", +"8& c #868691", +"9& c #A3A397", +"0& c #363666", +"a& c #C7C8A5", +"b& c #4C4C83", +"c& c #111272", +"d& c #787884", +"e& c #BABA9B", +"f& c #11106A", +"g& c #4E4D6A", +"h& c #B4B491", +"i& c #291F35", +"j& c #12116F", +"k& c #9999C0", +"l& c #B5B5BC", +"m& c #262670", +"n& c #121376", +"o& c #121377", +"p& c #5E5FA3", +"q& c #BDBDD1", +"r& c #1F1F78", +"s& c #E8E8F0", +"t& c #494988", +"u& c #13147C", +"v& c #A4A4C7", +"w& c #8787B3", +"x& c #3A3A99", +"y& c #E8E8D7", +"z& c #201FA5", +"A& c #DFDFD3", +"B& c #5353BE", +"C& c #2020C9", +"D& c #5D5DD2", +"E& c #D2D2D2", +"F& c #2424DB", +"G& c #2727DE", +"H& c #2525E6", +"I& c #2829E7", +"J& c #F0F0CE", +"K& c #5252E2", +"L& c #2D2DE2", +"M& c #F8F8C8", +"N& c #F4F4BE", +"O& c #7172C3", +"P& c #2022BA", +"Q& c #C5C5BE", +"R& c #656595", +"S& c #131271", +"T& c #75748F", +"U& c #A0A095", +"V& c #34346A", +"W& c #C9CAA5", +"X& c #474883", +"Y& c #121374", +"Z& c #7C7C84", +"`& c #B4B49A", +" * c #515174", +".* c #B7B793", +"+* c #251A32", +"@* c #121271", +"#* c #9191BC", +"$* c #BBBBC1", +"%* c #272770", +"&* c #4B4B99", +"** c #8586C4", +"=* c #2C2C85", +"-* c #E5E5EE", +";* c #4E4E8A", +">* c #13147D", +",* c #A2A2C7", +"'* c #8A8AB5", +")* c #373798", +"!* c #E9E9D7", +"~* c #2020A7", +"{* c #D6D6D1", +"]* c #6E6CAF", +"^* c #2120CC", +"/* c #5E5DD4", +"(* c #D3D3D2", +"_* c #2929DC", +":* c #3332CB", +"<* c #2525EA", +"[* c #2727EC", +"}* c #5F5FE2", +"|* c #2526E9", +"1* c #E0E0CC", +"2* c #FEFFC6", +"3* c #4F50C9", +"4* c #2223BE", +"5* c #C7C7BF", +"6* c #646497", +"7* c #131172", +"8* c #444487", +"9* c #90909A", +"0* c #343477", +"a* c #CBCBA6", +"b* c #414281", +"c* c #7F7F86", +"d* c #ACAD98", +"e* c #121270", +"f* c #545378", +"g* c #B8B893", +"h* c #211631", +"i* c #8989B9", +"j* c #BFBFC5", +"k* c #282970", +"l* c #121272", +"m* c #2E2E85", +"n* c #6162AD", +"o* c #3C3C91", +"p* c #DCDCE9", +"q* c #65648D", +"r* c #15157E", +"s* c #9F9FC6", +"t* c #8C8CB7", +"u* c #363698", +"v* c #ECECD8", +"w* c #2121A9", +"x* c #C5C5CF", +"y* c #94929D", +"z* c #2727CC", +"A* c #5C5CD5", +"B* c #3636DE", +"C* c #5E5BA0", +"D* c #2626EB", +"E* c #312EDA", +"F* c #DDDDC8", +"G* c #5D5EE5", +"H* c #2526EC", +"I* c #C1C1D1", +"J* c #FCFDC6", +"K* c #3132CE", +"L* c #2223C1", +"M* c #C8C9BF", +"N* c #616195", +"O* c #131170", +"P* c #242376", +"Q* c #51518C", +"R* c #302F73", +"S* c #CDCDA7", +"T* c #414180", +"U* c #2B2B78", +"V* c #848489", +"W* c #A8A897", +"X* c #565679", +"Y* c #201847", +"Z* c #8484B6", +"`* c #C3C3C9", +" = c #2B2B70", +".= c #131270", +"+= c #1A1A7A", +"@= c #191979", +"#= c #23237D", +"$= c #BFBFDB", +"%= c #737194", +"&= c #2F2972", +"*= c #B3B2C8", +"== c #8E8EB9", +"-= c #323297", +";= c #EEEED8", +">= c #2222A9", +",= c #ACACCA", +"'= c #ADA89B", +")= c #5D578D", +"!= c #6A6ABE", +"~= c #D0D0C0", +"{= c #2A2888", +"]= c #A39E95", +"^= c #362F99", +"/= c #463C89", +"(= c #EEEEC7", +"_= c #5353E8", +":= c #2526ED", +"<= c #ACACD3", +"[= c #EAEAC9", +"}= c #2123D0", +"|= c #2324C1", +"1= c #CACBBF", +"2= c #474793", +"3= c #12106D", +"4= c #1E1D72", +"5= c #252472", +"6= c #2C2B6D", +"7= c #8B8A89", +"8= c #787683", +"9= c #8C8C8B", +"0= c #A4A495", +"a= c #59597B", +"b= c #B8B892", +"c= c #1E1C6A", +"d= c #7E7FB3", +"e= c #C8C8CE", +"f= c #2C2D6F", +"g= c #191877", +"h= c #1A1B7D", +"i= c #151578", +"j= c #24257E", +"k= c #7B7CB7", +"l= c #9993A3", +"m= c #534768", +"n= c #E4E3E6", +"o= c #9090B9", +"p= c #302F97", +"q= c #F0F0D9", +"r= c #2323A6", +"s= c #8787C4", +"t= c #D9D7BC", +"u= c #625C83", +"v= c #8080B2", +"w= c #D0D0BF", +"x= c #272578", +"y= c #C7C7C4", +"z= c #615464", +"A= c #7B7176", +"B= c #FDFDCC", +"C= c #3939E8", +"D= c #2627EA", +"E= c #9FA0D3", +"F= c #C9C9CC", +"G= c #2022CF", +"H= c #2A2BC6", +"I= c #B0B2CB", +"J= c #27288A", +"K= c #1F1D72", +"L= c #1A186C", +"M= c #27276A", +"N= c #C7C7A4", +"O= c #8A8379", +"P= c #847D78", +"Q= c #94938B", +"R= c #9E9E94", +"S= c #5C5C7D", +"T= c #B6B691", +"U= c #191871", +"V= c #7576AE", +"W= c #CECED3", +"X= c #2D2D6D", +"Y= c #12116E", +"Z= c #1C1D7D", +"`= c #181980", +" - c #16167A", +".- c #2C2D82", +"+- c #3E4090", +"@- c #CCC9D6", +"#- c #9C97AD", +"$- c #FDFDFC", +"%- c #9494BA", +"&- c #2B2B95", +"*- c #F2F2DA", +"=- c #2322A1", +"-- c #5555BA", +";- c #F9F9D8", +">- c #8282C0", +",- c #7C7DBE", +"'- c #9798AC", +")- c #1A1979", +"!- c #474797", +"~- c #BFBEB9", +"{- c #ECEBC1", +"]- c #ECECCF", +"^- c #2627E5", +"/- c #2929E4", +"(- c #B2B2CF", +"_- c #A9A9CE", +":- c #2021CE", +"<- c #3132C8", +"[- c #7577CC", +"}- c #262782", +"|- c #1F1E73", +"1- c #1D1D6F", +"2- c #23236C", +"3- c #B3B39C", +"4- c #B8B595", +"5- c #B7B595", +"6- c #92918A", +"7- c #979792", +"8- c #5F5F7F", +"9- c #B4B490", +"0- c #171772", +"a- c #D2D2D7", +"b- c #2D2D6C", +"c- c #181972", +"d- c #1A1B80", +"e- c #171982", +"f- c #18187E", +"g- c #292A80", +"h- c #1F1F75", +"i- c #B5B5D6", +"j- c #E5E5ED", +"k- c #9696BB", +"l- c #292894", +"m- c #22229E", +"n- c #2322AD", +"o- c #A2A3C9", +"p- c #2C2DA4", +"q- c #1B1C97", +"r- c #161789", +"s- c #14147D", +"t- c #5D5D9D", +"u- c #F8F8CD", +"v- c #B7B7D4", +"w- c #2324E0", +"x- c #3030DD", +"y- c #CCCCCB", +"z- c #8788D0", +"A- c #1F21CB", +"B- c #2829BD", +"C- c #3B3DB0", +"D- c #212179", +"E- c #212075", +"F- c #1D1C71", +"G- c #24256F", +"H- c #7E7E89", +"I- c #DADAA9", +"J- c #CECFA3", +"K- c #8E8E8A", +"L- c #939390", +"M- c #5F5E80", +"N- c #B1B28F", +"O- c #151572", +"P- c #6767A4", +"Q- c #CFCFD7", +"R- c #1E1E6D", +"S- c #1E1E79", +"T- c #191B82", +"U- c #161885", +"V- c #151682", +"W- c #151577", +"X- c #11116A", +"Y- c #6A6BA7", +"Z- c #E6E6F0", +"`- c #9797C3", +" ; c #9090BB", +".; c #272692", +"+; c #1E1E9A", +"@; c #1A1AA3", +"#; c #2223A3", +"$; c #1A1BA9", +"%; c #1A1BAB", +"&; c #181899", +"*; c #16178F", +"=; c #151686", +"-; c #191A7B", +";; c #C1C2BB", +">; c #5B5CD0", +",; c #2223D9", +"'; c #393AD7", +"); c #E5E6CA", +"!; c #6364D0", +"~; c #1F20C6", +"{; c #1C1DAF", +"]; c #222399", +"^; c #29297F", +"/; c #141270", +"(; c #202077", +"_; c #1D1E73", +":; c #232471", +"<; c #30316E", +"[; c #C9C9A3", +"}; c #B0B099", +"|; c #6C6B83", +"1; c #8C8C8E", +"2; c #121275", +"3; c #3F3F7D", +"4; c #A9A98D", +"5; c #131373", +"6; c #131274", +"7; c #26257D", +"8; c #424188", +"9; c #212275", +"0; c #232481", +"a; c #1A1C85", +"b; c #141687", +"c; c #141686", +"d; c #14147E", +"e; c #2D2E7F", +"f; c #525298", +"g; c #31318C", +"h; c #343492", +"i; c #1A1A8D", +"j; c #4D4DA0", +"k; c #191995", +"l; c #1C1DAD", +"m; c #1C1DB5", +"n; c #1D1EBD", +"o; c #1B1CB0", +"p; c #18199B", +"q; c #16178E", +"r; c #383993", +"s; c #1F21BF", +"t; c #2021CB", +"u; c #4849D1", +"v; c #F8F8C9", +"w; c #4142CB", +"x; c #1E1FC0", +"y; c #1A1CAB", +"z; c #272891", +"A; c #272679", +"B; c #181875", +"C; c #191975", +"D; c #1F2075", +"E; c #19196C", +"F; c #161563", +"G; c #5A5A7B", +"H; c #313073", +"I; c #242372", +"J; c #313179", +"K; c #131276", +"L; c #1A1B79", +"M; c #3B3C7D", +"N; c #131273", +"O; c #131171", +"P; c #161670", +"Q; c #2C2D80", +"R; c #1E1F83", +"S; c #181A87", +"T; c #15178B", +"U; c #15178C", +"V; c #242576", +"W; c #131375", +"X; c #151584", +"Y; c #16168A", +"Z; c #16168E", +"`; c #171791", +" > c #171895", +".> c #1D1FBB", +"+> c #1E1FC3", +"@> c #2021CC", +"#> c #151688", +"$> c #16177D", +"%> c #1A1CAA", +"&> c #1C1EB8", +"*> c #6263C9", +"=> c #F5F5C9", +"-> c #2527C2", +";> c #1D1EBB", +">> c #201F7D", +",> c #24247B", +"'> c #191978", +")> c #1D1E76", +"!> c #14146C", +"~> c #111163", +"{> c #202069", +"]> c #111069", +"^> c #141477", +"/> c #141475", +"(> c #121170", +"_> c #1C1C73", +":> c #1F207D", +"<> c #151689", +"[> c #15178D", +"}> c #161790", +"|> c #141582", +"1> c #16168C", +"2> c #16178D", +"3> c #191A9C", +"4> c #1F20C4", +"5> c #2122D3", +"6> c #19199B", +"7> c #16168D", +"8> c #14147B", +"9> c #161890", +"0> c #191BA5", +"a> c #8585C6", +"b> c #D9DAC7", +"c> c #1D1EB9", +"d> c #1D1EAF", +"e> c #15137A", +"f> c #1A1977", +"g> c #17167A", +"h> c #131377", +"i> c #181975", +"j> c #191A71", +"k> c #1A1B6B", +"l> c #21216A", +"m> c #111168", +"n> c #141476", +"o> c #161576", +"p> c #151571", +"q> c #14137C", +"r> c #161791", +"s> c #161892", +"t> c #161893", +"u> c #15178F", +"v> c #17177F", +"w> c #131378", +"x> c #141580", +"y> c #151587", +"z> c #15168A", +"A> c #1B1DA7", +"B> c #2324DE", +"C> c #2223DB", +"D> c #1C1DB4", +"E> c #19199E", +"F> c #141480", +"G> c #18198F", +"H> c #A7A7C8", +"I> c #B7B7C1", +"J> c #24249F", +"K> c #262685", +"L> c #1B1B7B", +"M> c #14137B", +"N> c #13137B", +"O> c #141574", +"P> c #1A1B73", +"Q> c #1C1D6E", +"R> c #1F206B", +"S> c #171769", +"T> c #121069", +"U> c #141375", +"V> c #1A1B78", +"W> c #171777", +"X> c #141481", +"Y> c #171999", +"Z> c #171897", +"`> c #171894", +" , c #161891", +"., c #171880", +"+, c #171885", +"@, c #151687", +"#, c #1D1FB1", +"$, c #2123D6", +"%, c #2324E1", +"&, c #2324DD", +"*, c #1D1DB7", +"=, c #1A19A0", +"-, c #171794", +";, c #151585", +">, c #1C1C82", +",, c #7272AE", +"', c #494996", +"), c #1A197C", +"!, c #16157C", +"~, c #15147E", +"{, c #14147F", +"], c #13147E", +"^, c #121479", +"/, c #151677", +"(, c #191B75", +"_, c #1C1D71", +":, c #1E1F6C", +"<, c #1A1A78", +"[, c #191977", +"}, c #131275", +"|, c #18199D", +"1, c #181A9F", +"2, c #17199A", +"3, c #171998", +"4, c #171997", +"5, c #161895", +"6, c #16178C", +"7, c #171786", +"8, c #191983", +"9, c #2223A9", +"0, c #2425D4", +"a, c #2324DF", +"b, c #2121D0", +"c, c #1D1EBA", +"d, c #1A1A97", +"e, c #181889", +"f, c #1F1F7D", +"g, c #191779", +"h, c #1B1A7F", +"i, c #161680", +"j, c #131581", +"k, c #13157F", +"l, c #141679", +"m, c #161775", +"n, c #191B72", +"o, c #20216E", +"p, c #19196E", +"q, c #131272", +"r, c #16168B", +"s, c #181898", +"t, c #181AA0", +"u, c #191BA4", +"v, c #18199C", +"w, c #161685", +"x, c #1C1B85", +"y, c #1F1F8B", +"z, c #1C1C99", +"A, c #1F20A8", +"B, c #2222AA", +"C, c #1C1C8E", +"D, c #1F1F87", +"E, c #1C1B81", +"F, c #1C1B84", +"G, c #171782", +"H, c #141688", +"I, c #141685", +"J, c #13147A", +"K, c #161772", +"L, c #15166C", +"M, c #18186B", +"N, c #18186D", +"O, c #181977", +"P, c #1C1C79", +"Q, c #191BA7", +"R, c #181A9E", +"S, c #15178E", +"T, c #17188D", +"U, c #191B8E", +"V, c #16178B", +"W, c #17188C", +"X, c #16188C", +"Y, c #15168B", +"Z, c #141584", +"`, c #131580", +" ' c #151673", +".' c #17196F", +"+' c #15156B", +"@' c #12116B", +"#' c #151575", +"$' c #181877", +"%' c #1D1D7A", +"&' c #171792", +"*' c #191AA0", +"=' c #1A1BA7", +"-' c #1A1CAD", +";' c #1A1CAC", +">' c #191AA1", +",' c #181AA1", +"'' c #181A9D", +")' c #17199B", +"!' c #161996", +"~' c #141585", +"{' c #131374", +"]' c #171871", +"^' c #18196E", +"/' c #17176E", +"(' c #141370", +"_' c #141373", +":' c #181878", +"<' c #1D1E7A", +"[' c #141482", +"}' c #171793", +"|' c #1B1CAE", +"1' c #1B1DB0", +"2' c #1B1CAD", +"3' c #1A1BA8", +"4' c #191AA5", +"5' c #191AA3", +"6' c #171996", +"7' c #171896", +"8' c #13147F", +"9' c #13147B", +"0' c #171970", +"a' c #181970", +"b' c #181873", +"c' c #171775", +"d' c #161677", +"e' c #171778", +"f' c #151583", +"g' c #1B1DB1", +"h' c #1B1DB2", +"i' c #1B1DB3", +"j' c #1C1DB3", +"k' c #191BA6", +"l' c #191AA4", +"m' c #18199A", +"n' c #171898", +"o' c #171874", +"p' c #171776", +"q' c #171677", +"r' c #1E1E7A", +"s' c #1B1DB4", +"t' c #1B1CAF", +"u' c #1A1BAA", +"v' c #18199E", +"w' c #181999", +"x' c #171893", +"y' c #141581", +"z' c #121379", +"A' c #151573", +"B' c #181A74", +"C' c #171875", +"D' c #171678", +". . + + + + + + + + + + + + + + + + + + + + + + + + + + + + @ + # + + $ + + + + + + + + + + . . ", +". . . . . . . . + + + + + + + + + + + + + + + + + + + + + + + + % + + & + + + + . . . . . . . . ", +"* * * * . . . . . . . . . . . = . . + + + + + + + + + + + + . . - . . . . . . . . . . * * * * * ", +"; ; ; ; * * * * * * * * * * . > . . . . . . . . . . . . . . . . . * , * * * * * * * ' * ; ; ; ; ", +"; ; ; ; ; ; ; ; ; ; ; ) * * * ! * * * * * * ~ { * * * * * * * * * * ] * ; ; ; ; ^ ; / ; ; ; ; ; ", +"; ; ( _ ; ; ; : ; ; ; < ! ; ; ; ; ; ; ; ; ; , [ ; ; ; ; ; ; ; ; ; ; } ; ; ; ; ; | ; 1 ; 2 ; ; ; ", +"3 3 4 5 3 ; ; 6 ; ; ; 7 2 ; ; ; ; ; ; ; ; ; ( ! ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ^ ; ; 3 8 3 3 3 ", +"3 3 9 0 3 3 3 3 3 3 3 3 3 3 3 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 3 3 3 3 3 3 3 3 3 3 3 3 a 3 3 3 ", +"3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 b 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 ", +"c d e f g h i j k 3 3 3 3 3 3 3 3 3 3 3 l m 3 3 n o p 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 q r c c c c ", +"s t u v w x y z A B c c c c c C c c c c D E c F G H I c c c 0 J c c c c c B B B B B K L M B N B ", +"O P Q R S T U V W B B B B B B X Y B B B Z ` B ...+.@.#.B B $.%.B B B B B B B B B B &.*.=.B -.;.", +">.,.'.).!.~.{.].W B B B B B ^./.(.B B B _.:.B <.[.+.}.q B B B |.B B B B B B B B B B 1.2.3.4.5.6.", +"7.8.9.0.a.b.c.d.e.4.4.f.g.4.h.i.W 4.4.4.j.k.l.m.n.o.p.q.4.4.4.4.4.4.4.4.4.4.4.4.4.4.r.s.t.4.u.4.", +"v.8.w.x.y.z.A.B.C.4.4.D.E.4.F.G.H.l.4.4.I.k.>.J.K.L.M.N.4.4.4.4.4.4.4.4.4.4.O.P.l.4.Q.R.S.4.T.U.", +"V.W.X.Y.U.Z.`. +.+U.U.H.U.4.++@+4.#+$+4.%+&+*+=+q.4.-+;+4.4.4.4.4.4.4.U.U.U.>+,+'+U.)+!+~+U.{+U.", +"]+^+/+(+U.U._+:+<+U.U.U.U.U.v.[+U.N.V.U.%+}+|+1+V.U.2+3+U.U.U.U.U.U.U.U.U.U.l.4+5+U.6+7+8+9+0+U.", +"a+b+c+d+e+U.f+g+h+i+j+U.]+j+U.U.U.U.U.k+l+}+|+m+n+U.o+p+j+U.U.q+j+q+]+>.U.U.r+s+t+i+u+v+w+i+x+y+", +"z+A+B+C+y+y+D+E+F+G+H+y+I+J+j+K+L+M+N+O+P+Q+R+=+S+T+U+V+W+y+y+X+Y+Z+`+ @.@y++@@@#@$@%@&@*@=@y+y+", +"y+-@;@>@,@,@'@)@!@~@{@]@^@/@(@_@:@<@[@}@|@1@2@3@4@5@6@7@8@9@0@a@b@c@d@e@f@g@h@i@j@k@l@m@n@o@p@y+", +"q@r@s@t@u@v@w@x@y@z@A@B@C@D@E@F@G@H@I@J@K@L@M@N@m.O@P@Q@R@H@S@T@U@V@W@'.X@Y@Z@`@,. #.#+#@###$#q@", +"q@%#&#*#=#-#;#>#,#'#)#!#~#{#]#^#/#(#_#J@K@:#<#[#}#|#1#2#3#4#5#6#7#8#9#0#a#b#c#d#P e#f#g#h#i#j#k#", +"q@l#m#n#n#o#p#q#r#s#t#u#v#w#x#y#z#A#B#C#D#E#F#G#H#I#J#K#L#M#N#O#P#Q#R#S#T#U#V#W#X#Y#Z#`# $.$+$@$", +"#$$$n#n#n#%$&$*$=$-$;$>$,$'$)$!$~${$]$^$/$($_$:$<$[$}$_$|$1$2$3$4$5$6$7$8$9$0$a$b$c$d$e$f$g$h$i$", +"j$k$l$m$n$o$p$q$r$s$t$u$v$w$x$y$z$A$B$C$D$E$F$G$H$[.I$J$K$L$M$N$O$P$Q$R$S$T$U$V$W$X$Y$Z$`$ %.%+%", +"@%#%$%%%&%*%=%-%;%>%,%'%)%!%~%{%]%^%/%(%_%:%<%[%}%|%1%2%3%4%5%6%7%8%9%0%a%b%c%d%e%0%f%g%h%i%j%k%", +"l%m%n%o%p%q%r%s%t%u%v%w%x%y%z%A%B%C%D%E%F%G%H%I%J%K%[$L%M%N%O%P%Q%R%S%T%U%V%W%d%X%Y%Z%`%M@ &.&+&", +"u$@&#&$&%&w%&&*&=&-&;&>&,&'&)&!&~&{&]&^&/&(&_&:&<&[&m+}&|&1&2&3&4&5&6&7&8&9&0&a&b&c&d&e&f&g&h&i&", +"j&k&l&m&n&o&p&q&r&s&t&u&v&w&x&y&z&A&B&C&D&E&F&G&H&I&J&K&L&M&N&O&P&Q&R&S&T&U&V&W&X&Y&Z&`&7& *.*+*", +"@*#*$*%*o&n&&***=*-*;*>*,*'*)*!*~*{*]*^*/*(*_*:*<*[*!$}*|*1*2*3*4*5*6*7*8*9*0*a*b*w%c*d*e*f*g*h*", +"q%i*j*k*n&l*m*n*o*p*q*r*s*t*u*v*w*x*y*z*A*(*B*C*D*E*F*G*H*I*J*K*L*M*N*O*P*Q*R*S*T*U*V*W*l*X*g*Y*", +"%&Z*`* =w%.=+=@=#=$=%=&=*===-=;=>=,='=)=!=~={=]=^=/=(=_=:=<=[=}=|=1=2=3=4=5=6=a*7=8=9=0=q%a=b=c=", +"w%d=e=f='%g=h=i=j=k=l=m=n=o=p=q=r=s=t=u=v=w=x=y=z=A=B=C=D=E=F=G=H=I=J=j&K=L=M=N=O=P=Q=R=%&S=T=U=", +"w%V=W=X=Y=Z=`= -.-+-@-#-$-%-&-*-=---;->-,-'-)-!-~-{-]-^-/-(-_-:-<-[-}-3=|-1-2-3-4-5-6-7-%&8-9-0-", +"w%r%a-b-c-d-e-f-g-h-i-n#j-k-l-*-m-n-o-p-q-r-<#s-t-u-v-w-x-y-z-A-B-C-D-3=E-F-G-H-I-J-K-L-%&M-N-O-", +"w%P-Q-R-S-T-U-V-W-X-Y-Z-`- ;.;;=+;@;#;$;%;&;*;=;-;;;>;,;';);!;~;{;];^;/;(;_;:;<;[;};|;1;2;3;4;5;", +"6;7;8;9;0;a;b;c;d;&%e;f;g;h;i;j;k;&;l;m;n;o;p;q;V-r;s;t;u;v;w;x;y;z;A;B;C;D;E;F;G;H;I;J;K;L;M;%&", +"N;O;P;Q;R;S;T;U;c;1#V;W;s-X;Y;Z;`; >.>+>@>x;$; >#>$>%>&>*>=>->;>F#>>,>'>6;)>!>~>{>]>3=l*6;^>L;/>", +"7*(>_>:>X;<>[>}>[>b;+=5;>&|><>1>2>3>4>5>[%~;C$6>7>8>9>0>a>b>c>d>e>f>g>h>2;i>j>k>l>m>u$(>6;n>L;o>", +"O;e*p>q>1>r>}>s>t>u><>v>w>x>y>z><>A>@>B>C>C&D>E>`;F>>*G>H>I>J>K>L>M>N>>&o&O>P>Q>R>S>T>(>N;U>V>W>", +"O;@*q%X>`;Y>Z>`> > > ,[>|>.,+,c;@,#,$,%,&,@>*,=,-,;,h>>,,,',),!,~,{,],u&^,/,(,_,:,:,T>j&N;U><,[,", +"l*l*},y> >|,1,2,3,Y>4,5, ,6,7,F>8,9,0,a,B>b,c,@;d,e,f,g,h,i,X>|><#|>j,k,u&l,m,n,Q>o,p,j&q,U>'>V>", +"q%l*1#r,s,t,u,F#v,p;v,2,4,5,u>[>w,x,y,z,A,B,s,C,D,E,F,G,;,=;b;H,b;c;I,|>],J,w%K,L,M,N,Y=7*/>O,P,", +"%&q%d;}>v,u,Q,$;0>1,R,R,v,v,Y>4,5,s>}>S,T,U,z>V,W,X,U;Y,U;T;U;T;z><>b;Z,`,u&o& '.'+'@'j&N;#'$'%'", +"2;q%F>&'*'='%>-';'0>>'F#,','t,'')'3,!'5,t>s>s> ,s>s>s>s>s> ,}>q;[>T;<>~'|>],1#{']'^'/'('_'z#:'<'", +"w%N;['}'>'y;|'o;1'2'$;3'4'5'F#1,1,v,p;2,Y>3,3,4,4,6'4,7'7' >`>r>*;2>z>@,<#8'9'n& '0'a'b'c'd'e'<'", +"},},f'}'>';'g'h'i'j'1'2'y;k'l'F#F#t,*'1,R,R,''v,v,m'p;Y>3,n'7'`>r>q;Y,#>Z,x>u&o&5;c-c-o'p'q'e'r'", +"6;K;X;}'>';'i's'm;&>D>|'t'u'0>u,0>l'4'l'5'5'>','1,R,v'v,m'w'Z> >x'}>6,<>;,y'>*z'w%A'B'C'p'q'D'%'"};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/i_backend.c Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,174 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#include "i_backend.h" + + +gboolean i_str_has_pref_and_suff( const gchar *str , gchar *pref , gchar *suff ) +{ + if ( (g_str_has_prefix( str , pref )) && + (g_str_has_suffix( str , suff )) ) + return TRUE; + else + return FALSE; +} + +GSList * i_backend_list_lookup( void ) +{ + GDir * backend_directory; + GSList * backend_list = NULL; + + backend_directory = g_dir_open( AMIDIPLUGDATADIR , 0 , NULL ); + if ( backend_directory != NULL ) + { + const gchar * backend_directory_entry = g_dir_read_name( backend_directory ); + while ( backend_directory_entry != NULL ) + { + /* simple filename checking */ + if ( i_str_has_pref_and_suff( backend_directory_entry , "ap-" , ".so" ) == TRUE ) + { + GModule * module; + gchar * (*getapmoduleinfo)( gchar ** , gchar ** , gchar ** , gint * ); + gchar * module_pathfilename = g_strjoin( "" , AMIDIPLUGDATADIR , "/" , + backend_directory_entry , NULL ); + /* seems to be a backend for amidi-plug , try to load it */ + module = g_module_open( module_pathfilename , 0 ); + if ( module == NULL ) + g_warning( "Error loading module %s - %s\n" , module_pathfilename , g_module_error() ); + else + { + /* try to get the module name */ + if ( g_module_symbol( module , "backend_info_get" , (gpointer*)&getapmoduleinfo ) ) + { + /* module name found, ok! add its name and filename to the list */ + amidiplug_sequencer_backend_name_t * mn = g_malloc(sizeof(amidiplug_sequencer_backend_name_t)); + /* name and desc dinamically allocated */ + getapmoduleinfo( &mn->name , &mn->longname , &mn->desc , &mn->ppos ); + mn->filename = g_strdup(module_pathfilename); /* dinamically allocated */ + DEBUGMSG( "Backend found and added in list, filename: %s and lname: %s\n" , + mn->filename, mn->longname ); + backend_list = g_slist_append( backend_list , mn ); + } + else + { + /* module name not found, this is not a backend for amidi-plug */ + g_warning( "File %s is not a backend for amidi-plug!\n" , module_pathfilename ); + } + g_module_close( module ); + } + } + backend_directory_entry = g_dir_read_name( backend_directory ); + } + g_dir_close( backend_directory ); + } + else + g_warning( "Unable to open the backend directory %s\n" , AMIDIPLUGDATADIR ); + + return backend_list; +} + + +void i_backend_list_free( GSList * backend_list ) +{ + while ( backend_list != NULL ) + { + amidiplug_sequencer_backend_name_t * mn = backend_list->data; + g_free( mn->desc ); + g_free( mn->name ); + g_free( mn->longname ); + g_free( mn->filename ); + g_free( mn ); + backend_list = backend_list->next; + } + return; +} + + +gint i_backend_load( gchar * module_name ) +{ + gchar * module_pathfilename = g_strjoin( "" , AMIDIPLUGDATADIR , "/ap-" , module_name , ".so" , NULL ); + DEBUGMSG( "loading backend '%s'\n" , module_pathfilename ); + backend.gmodule = g_module_open( module_pathfilename , 0 ); + + if ( backend.gmodule != NULL ) + { + gchar * (*getapmoduleinfo)( gchar ** , gchar ** , gchar ** , gint * ); + gboolean (*checkautonomousaudio)( void ); + g_module_symbol( backend.gmodule , "backend_init" , (gpointer *)&backend.init ); + g_module_symbol( backend.gmodule , "backend_cleanup" , (gpointer *)&backend.cleanup ); + g_module_symbol( backend.gmodule , "audio_info_get" , (gpointer*)&backend.audio_info_get ); + g_module_symbol( backend.gmodule , "audio_volume_get" , (gpointer *)&backend.audio_volume_get ); + g_module_symbol( backend.gmodule , "audio_volume_set" , (gpointer *)&backend.audio_volume_set ); + g_module_symbol( backend.gmodule , "sequencer_start" , (gpointer *)&backend.seq_start ); + g_module_symbol( backend.gmodule , "sequencer_stop" , (gpointer *)&backend.seq_stop ); + g_module_symbol( backend.gmodule , "sequencer_on" , (gpointer *)&backend.seq_on ); + g_module_symbol( backend.gmodule , "sequencer_off" , (gpointer *)&backend.seq_off ); + g_module_symbol( backend.gmodule , "sequencer_queue_tempo" , (gpointer *)&backend.seq_queue_tempo ); + g_module_symbol( backend.gmodule , "sequencer_queue_start" , (gpointer *)&backend.seq_queue_start ); + g_module_symbol( backend.gmodule , "sequencer_event_init" , (gpointer *)&backend.seq_event_init ); + g_module_symbol( backend.gmodule , "sequencer_event_noteon" , (gpointer *)&backend.seq_event_noteon ); + g_module_symbol( backend.gmodule , "sequencer_event_noteoff" , (gpointer *)&backend.seq_event_noteoff ); + g_module_symbol( backend.gmodule , "sequencer_event_keypress" , (gpointer *)&backend.seq_event_keypress ); + g_module_symbol( backend.gmodule , "sequencer_event_controller" , (gpointer *)&backend.seq_event_controller ); + g_module_symbol( backend.gmodule , "sequencer_event_pgmchange" , (gpointer *)&backend.seq_event_pgmchange ); + g_module_symbol( backend.gmodule , "sequencer_event_chanpress" , (gpointer *)&backend.seq_event_chanpress ); + g_module_symbol( backend.gmodule , "sequencer_event_pitchbend" , (gpointer *)&backend.seq_event_pitchbend ); + g_module_symbol( backend.gmodule , "sequencer_event_sysex" , (gpointer *)&backend.seq_event_sysex ); + g_module_symbol( backend.gmodule , "sequencer_event_tempo" , (gpointer *)&backend.seq_event_tempo ); + g_module_symbol( backend.gmodule , "sequencer_event_other" , (gpointer *)&backend.seq_event_other ); + g_module_symbol( backend.gmodule , "sequencer_output" , (gpointer *)&backend.seq_output ); + g_module_symbol( backend.gmodule , "sequencer_output_shut" , (gpointer *)&backend.seq_output_shut ); + g_module_symbol( backend.gmodule , "sequencer_get_port_count" , (gpointer *)&backend.seq_get_port_count ); + g_module_symbol( backend.gmodule , "backend_info_get" , (gpointer*)&getapmoduleinfo ); + g_module_symbol( backend.gmodule , "audio_check_autonomous" , (gpointer*)&checkautonomousaudio ); + getapmoduleinfo( &backend.name , NULL , NULL , NULL ); + backend.autonomous_audio = checkautonomousaudio(); + DEBUGMSG( "backend %s (name '%s') successfully loaded\n" , module_pathfilename , backend.name ); + backend.init(); + g_free( module_pathfilename ); + return 1; + } + else + { + g_warning( "unable to load backend '%s'\n" , module_pathfilename ); + g_free( module_pathfilename ); + return 0; + } +} + + +gint i_backend_unload( void ) +{ + if ( backend.gmodule != NULL ) + { + DEBUGMSG( "unloading backend '%s'\n" , backend.name ); + backend.cleanup(); + g_module_close( backend.gmodule ); + DEBUGMSG( "backend '%s' unloaded\n" , backend.name ); + g_free( backend.name ); + backend.gmodule = NULL; + return 1; + } + else + { + g_warning( "attempting to unload backend, but no backend is loaded\n" ); + return 0; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/i_backend.h Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,82 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#ifndef _I_BACKEND_H +#define _I_BACKEND_H 1 + +#include <gmodule.h> +#include "i_midievent.h" +#include "i_common.h" + + +typedef struct +{ + gchar * desc; + gchar * filename; + gchar * longname; + gchar * name; + gint ppos; +} +amidiplug_sequencer_backend_name_t; + + +typedef struct +{ + gint id; + GModule * gmodule; + gchar * name; + gint (*init)( void ); + gint (*cleanup)( void ); + gint (*audio_info_get)( gint * , gint * , gint * ); + gint (*audio_volume_get)( gint * , gint * ); + gint (*audio_volume_set)( gint , gint ); + gint (*seq_start)( gchar * ); + gint (*seq_stop)( void ); + gint (*seq_on)( void ); + gint (*seq_off)( void ); + gint (*seq_queue_tempo)( gint , gint ); + gint (*seq_queue_start)( void ); + gint (*seq_event_init)( void ); + gint (*seq_event_noteon)( midievent_t * ); + gint (*seq_event_noteoff)( midievent_t * ); + gint (*seq_event_keypress)( midievent_t * ); + gint (*seq_event_controller)( midievent_t * ); + gint (*seq_event_pgmchange)( midievent_t * ); + gint (*seq_event_chanpress)( midievent_t * ); + gint (*seq_event_pitchbend)( midievent_t * ); + gint (*seq_event_sysex)( midievent_t * ); + gint (*seq_event_tempo)( midievent_t * ); + gint (*seq_event_other)( midievent_t * ); + gint (*seq_output)( gpointer * , gint * ); + gint (*seq_output_shut)( guint , gint ); + gint (*seq_get_port_count)( void ); + gboolean autonomous_audio; +} +amidiplug_sequencer_backend_t; + +extern amidiplug_sequencer_backend_t backend; + + +GSList * i_backend_list_lookup( void ); +void i_backend_list_free( GSList * ); +gint i_backend_load( gchar * ); +gint i_backend_unload( void ); + +#endif /* !_I_BACKEND_H */
--- a/Plugins/Input/amidi-plug/i_common.h Mon Jul 10 04:42:53 2006 -0700 +++ b/Plugins/Input/amidi-plug/i_common.h Mon Jul 10 04:52:51 2006 -0700 @@ -21,7 +21,6 @@ #ifndef _I_COMMON_H #define _I_COMMON_H 1 - #include "config.h" #include <stdio.h> #include <stdlib.h> @@ -44,10 +43,14 @@ #endif /* DEBUG */ -#define AMIDIPLUG_VERSION "0.2+" +#define AMIDIPLUG_VERSION "0.5" #define PLAYER_NAME "Audacious" +#define PLAYER_LOCALRCDIR ".audacious" #define G_PATH_GET_BASENAME(x) g_path_get_basename(x) #define G_STRING_PRINTF(...) g_string_printf(__VA_ARGS__) +#define G_USLEEP(x) g_usleep(x) +#define G_VFPRINTF(x,y,z) g_vfprintf(x,y,z) + /* multi-purpose data bucket */ typedef struct
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/i_configure-alsa.c Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,555 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + + +#include "i_configure-alsa.h" +#include "backend-alsa/b-alsa-config.h" +#include "backend-alsa/backend-alsa-icon.xpm" + + +enum +{ + LISTPORT_TOGGLE_COLUMN = 0, + LISTPORT_PORTNUM_COLUMN, + LISTPORT_CLIENTNAME_COLUMN, + LISTPORT_PORTNAME_COLUMN, + LISTPORT_POINTER_COLUMN, + LISTPORT_N_COLUMNS +}; + +enum +{ + LISTCARD_NAME_COLUMN = 0, + LISTCARD_ID_COLUMN, + LISTCARD_MIXERPTR_COLUMN, + LISTCARD_N_COLUMNS +}; + +enum +{ + LISTMIXER_NAME_COLUMN = 0, + LISTMIXER_ID_COLUMN, + LISTMIXER_N_COLUMNS +}; + + +void i_configure_ev_portlv_changetoggle( GtkCellRendererToggle * rdtoggle , + gchar * path_str , gpointer data ) +{ + GtkTreeModel *model = (GtkTreeModel*)data; + GtkTreeIter iter; + GtkTreePath *path = gtk_tree_path_new_from_string( path_str ); + gboolean toggled; + + gtk_tree_model_get_iter( model , &iter , path ); + gtk_tree_model_get( model , &iter , LISTPORT_TOGGLE_COLUMN , &toggled , -1 ); + + toggled ^= 1; + gtk_list_store_set( GTK_LIST_STORE(model), &iter , LISTPORT_TOGGLE_COLUMN , toggled , -1 ); + + gtk_tree_path_free (path); +} + + +gboolean i_configure_ev_mixctlcmb_inspect( GtkTreeModel * store , GtkTreePath * path, + GtkTreeIter * iter , gpointer mixctl_cmb ) +{ + gint ctl_id; + gchar * ctl_name; + amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa; + gtk_tree_model_get( GTK_TREE_MODEL(store) , iter , + LISTMIXER_ID_COLUMN , &ctl_id , + LISTMIXER_NAME_COLUMN , &ctl_name , -1 ); + if (( !strcmp( ctl_name , alsacfg->alsa_mixer_ctl_name ) ) && + ( ctl_id == alsacfg->alsa_mixer_ctl_id )) + { + /* this is the selected control in the mixer control combobox */ + gtk_combo_box_set_active_iter( GTK_COMBO_BOX(mixctl_cmb) , iter ); + return TRUE; + } + g_free( ctl_name ); + return FALSE; +} + + +void i_configure_ev_cardcmb_changed( GtkWidget * card_cmb , gpointer mixctl_cmb ) +{ + GtkTreeIter iter; + if( gtk_combo_box_get_active_iter( GTK_COMBO_BOX(card_cmb) , &iter ) ) + { + amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa; + gpointer mixctl_store; + gint card_id; + GtkTreeModel * store = gtk_combo_box_get_model( GTK_COMBO_BOX(card_cmb) ); + gtk_tree_model_get( GTK_TREE_MODEL(store) , &iter , + LISTCARD_ID_COLUMN , &card_id , + LISTCARD_MIXERPTR_COLUMN , &mixctl_store , -1 ); + gtk_combo_box_set_model( GTK_COMBO_BOX(mixctl_cmb) , GTK_TREE_MODEL(mixctl_store) ); + + /* check if the selected card is the one contained in configuration */ + if ( card_id == alsacfg->alsa_mixer_card_id ) + { + /* search for the selected mixer control in combo box */ + gtk_tree_model_foreach( GTK_TREE_MODEL(mixctl_store) , + i_configure_ev_mixctlcmb_inspect , mixctl_cmb ); + } + } +} + + +gboolean i_configure_ev_portlv_inspecttoggle( GtkTreeModel * model , GtkTreePath * path , + GtkTreeIter * iter , gpointer wpp ) +{ + gboolean toggled = FALSE; + gchar * portstring; + GString * wps = wpp; + gtk_tree_model_get ( model , iter , + LISTPORT_TOGGLE_COLUMN , &toggled , + LISTPORT_PORTNUM_COLUMN , &portstring , -1 ); + if ( toggled ) /* check if the row points to an enabled port */ + { + /* if this is not the first port added to wp, use comma as separator */ + if ( wps->str[0] != '\0' ) g_string_append_c( wps , ',' ); + g_string_append( wps , portstring ); + } + g_free( portstring ); + return FALSE; +} + + +void i_configure_ev_portlv_commit( gpointer port_lv ) +{ + amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa; + GtkTreeModel * store; + GString *wp = g_string_new( "" ); + /* get the model of the port listview */ + store = gtk_tree_view_get_model( GTK_TREE_VIEW(port_lv) ); + /* after going through this foreach, wp contains a comma-separated list of selected ports */ + gtk_tree_model_foreach( store , i_configure_ev_portlv_inspecttoggle , wp ); + g_free( alsacfg->alsa_seq_wports ); /* free previous */ + alsacfg->alsa_seq_wports = g_strdup( wp->str ); /* set with new */ + g_string_free( wp , TRUE ); /* not needed anymore */ + return; +} + +void i_configure_ev_cardcmb_commit( gpointer card_cmb ) +{ + GtkTreeModel * store; + GtkTreeIter iter; + store = gtk_combo_box_get_model( GTK_COMBO_BOX(card_cmb) ); + /* get the selected item */ + if ( gtk_combo_box_get_active_iter( GTK_COMBO_BOX(card_cmb) , &iter ) ) + { + amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa; + /* update amidiplug_cfg.alsa_mixer_card_id */ + gtk_tree_model_get( GTK_TREE_MODEL(store) , &iter , + LISTCARD_ID_COLUMN , + &alsacfg->alsa_mixer_card_id , -1 ); + } + return; +} + +void i_configure_ev_mixctlcmb_commit( gpointer mixctl_cmb ) +{ + GtkTreeModel * store; + GtkTreeIter iter; + store = gtk_combo_box_get_model( GTK_COMBO_BOX(mixctl_cmb) ); + /* get the selected item */ + if ( gtk_combo_box_get_active_iter( GTK_COMBO_BOX(mixctl_cmb) , &iter ) ) + { + amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa; + g_free( alsacfg->alsa_mixer_ctl_name ); /* free previous */ + /* update amidiplug_cfg.alsa_mixer_card_id */ + gtk_tree_model_get( GTK_TREE_MODEL(store) , &iter , + LISTMIXER_NAME_COLUMN , + &alsacfg->alsa_mixer_ctl_name , + LISTMIXER_ID_COLUMN , + &alsacfg->alsa_mixer_ctl_id , -1 ); + } + return; +} + + +void i_configure_gui_ctlcmb_datafunc( GtkCellLayout *cell_layout , GtkCellRenderer *cr , + GtkTreeModel *store , GtkTreeIter *iter , gpointer p ) +{ + gchar *ctl_display, *ctl_name; + gint ctl_id; + gtk_tree_model_get( store , iter , + LISTMIXER_NAME_COLUMN , &ctl_name , + LISTMIXER_ID_COLUMN , &ctl_id , -1 ); + if ( ctl_id == 0 ) + ctl_display = g_strdup_printf( "%s" , ctl_name ); + else + ctl_display = g_strdup_printf( "%s (%i)" , ctl_name , ctl_id ); + g_object_set( G_OBJECT(cr) , "text" , ctl_display , NULL ); + g_free( ctl_display ); + g_free( ctl_name ); +} + + +void i_configure_gui_tab_alsa( GtkWidget * alsa_page_alignment , + gpointer backend_list_p , + gpointer commit_button ) +{ + GtkWidget *alsa_page_vbox; + GtkWidget *title_widget; + GtkWidget *content_vbox; /* this vbox will contain two items of equal space (50%/50%) */ + GSList * backend_list = backend_list_p; + gboolean alsa_module_ok = FALSE; + gchar * alsa_module_pathfilename; + + alsa_page_vbox = gtk_vbox_new( FALSE , 0 ); + + title_widget = i_configure_gui_draw_title( _("ALSA BACKEND CONFIGURATION") ); + gtk_box_pack_start( GTK_BOX(alsa_page_vbox) , title_widget , FALSE , FALSE , 2 ); + + content_vbox = gtk_vbox_new( TRUE , 2 ); + + /* check if the ALSA module is available */ + while ( backend_list != NULL ) + { + amidiplug_sequencer_backend_name_t * mn = backend_list->data; + if ( !strcmp( mn->name , "alsa" ) ) + { + alsa_module_ok = TRUE; + alsa_module_pathfilename = mn->filename; + break; + } + backend_list = backend_list->next; + } + + if ( alsa_module_ok ) + { + GtkListStore *port_store, *mixer_card_store; + GtkWidget *port_lv, *port_lv_sw, *port_lv_frame; + GtkCellRenderer *port_lv_toggle_rndr, *port_lv_text_rndr; + GtkTreeViewColumn *port_lv_toggle_col, *port_lv_portnum_col; + GtkTreeViewColumn *port_lv_clientname_col, *port_lv_portname_col; + GtkTreeSelection *port_lv_sel; + GtkTreeIter iter; + GtkWidget *mixer_table, *mixer_frame; + GtkCellRenderer *mixer_card_cmb_text_rndr, *mixer_ctl_cmb_text_rndr; + GtkWidget *mixer_card_cmb_evbox, *mixer_card_cmb, *mixer_card_label; + GtkWidget *mixer_ctl_cmb_evbox, *mixer_ctl_cmb, *mixer_ctl_label; + GtkTooltips *tips; + + amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa; + + gchar **portstring_from_cfg = NULL; + + GModule * alsa_module; + GSList *wports = NULL, *wports_h = NULL, *scards = NULL, *scards_h = NULL; + GSList * (*get_port_list)( void ); + void (*free_port_list)( GSList * ); + GSList * (*get_card_list)( void ); + void (*free_card_list)( GSList * ); + + if ( strlen( alsacfg->alsa_seq_wports ) > 0 ) + portstring_from_cfg = g_strsplit( alsacfg->alsa_seq_wports , "," , 0 ); + + tips = gtk_tooltips_new(); + g_object_set_data_full( G_OBJECT(alsa_page_alignment) , "tt" , tips , g_object_unref ); + + /* it's legit to assume that this can't fail, + since the module is present in the backend_list */ + alsa_module = g_module_open( alsa_module_pathfilename , 0 ); + g_module_symbol( alsa_module , "sequencer_port_get_list" , (gpointer*)&get_port_list ); + g_module_symbol( alsa_module , "sequencer_port_free_list" , (gpointer*)&free_port_list ); + g_module_symbol( alsa_module , "alsa_card_get_list" , (gpointer*)&get_card_list ); + g_module_symbol( alsa_module , "alsa_card_free_list" , (gpointer*)&free_card_list ); + /* get an updated list of writable ALSA MIDI ports and ALSA-enabled sound cards*/ + wports = get_port_list(); wports_h = wports; + scards = get_card_list(); scards_h = scards; + + /* ALSA MIDI PORT LISTVIEW */ + port_store = gtk_list_store_new( LISTPORT_N_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_STRING , + G_TYPE_STRING , G_TYPE_STRING , G_TYPE_POINTER ); + while ( wports != NULL ) + { + gboolean toggled = FALSE; + data_bucket_t * portinfo = (data_bucket_t *)wports->data; + GString * portstring = g_string_new(""); + G_STRING_PRINTF( portstring , "%i:%i" , portinfo->bint[0] , portinfo->bint[1] ); + gtk_list_store_append( port_store , &iter ); + /* in the existing configuration there may be previously selected ports */ + if ( portstring_from_cfg != NULL ) + { + gint i = 0; + /* check if current row contains a port selected by user */ + for ( i = 0 ; portstring_from_cfg[i] != NULL ; i++ ) + { + /* if it's one of the selected ports, toggle its checkbox */ + if ( !strcmp( portstring->str, portstring_from_cfg[i] ) ) + toggled = TRUE; + } + } + gtk_list_store_set( port_store , &iter , + LISTPORT_TOGGLE_COLUMN , toggled , + LISTPORT_PORTNUM_COLUMN , portstring->str , + LISTPORT_CLIENTNAME_COLUMN , portinfo->bcharp[0] , + LISTPORT_PORTNAME_COLUMN , portinfo->bcharp[1] , + LISTPORT_POINTER_COLUMN , portinfo , -1 ); + g_string_free( portstring , TRUE ); + /* on with next */ + wports = wports->next; + } + g_strfreev( portstring_from_cfg ); /* not needed anymore */ + port_lv = gtk_tree_view_new_with_model( GTK_TREE_MODEL(port_store) ); + gtk_tree_view_set_rules_hint( GTK_TREE_VIEW(port_lv), TRUE ); + g_object_unref( port_store ); + port_lv_toggle_rndr = gtk_cell_renderer_toggle_new(); + gtk_cell_renderer_toggle_set_radio( GTK_CELL_RENDERER_TOGGLE(port_lv_toggle_rndr) , FALSE ); + gtk_cell_renderer_toggle_set_active( GTK_CELL_RENDERER_TOGGLE(port_lv_toggle_rndr) , TRUE ); + g_signal_connect( port_lv_toggle_rndr , "toggled" , + G_CALLBACK(i_configure_ev_portlv_changetoggle) , port_store ); + port_lv_text_rndr = gtk_cell_renderer_text_new(); + port_lv_toggle_col = gtk_tree_view_column_new_with_attributes( "", port_lv_toggle_rndr, + "active", LISTPORT_TOGGLE_COLUMN, NULL ); + port_lv_portnum_col = gtk_tree_view_column_new_with_attributes( _("Port"), port_lv_text_rndr, + "text", LISTPORT_PORTNUM_COLUMN, NULL ); + port_lv_clientname_col = gtk_tree_view_column_new_with_attributes( _("Client name"), port_lv_text_rndr, + "text", LISTPORT_CLIENTNAME_COLUMN, NULL ); + port_lv_portname_col = gtk_tree_view_column_new_with_attributes( _("Port name"), port_lv_text_rndr, + "text", LISTPORT_PORTNAME_COLUMN, NULL ); + gtk_tree_view_append_column( GTK_TREE_VIEW(port_lv), port_lv_toggle_col ); + gtk_tree_view_append_column( GTK_TREE_VIEW(port_lv), port_lv_portnum_col ); + gtk_tree_view_append_column( GTK_TREE_VIEW(port_lv), port_lv_clientname_col ); + gtk_tree_view_append_column( GTK_TREE_VIEW(port_lv), port_lv_portname_col ); + port_lv_sel = gtk_tree_view_get_selection( GTK_TREE_VIEW(port_lv) ); + gtk_tree_selection_set_mode( GTK_TREE_SELECTION(port_lv_sel) , GTK_SELECTION_NONE ); + port_lv_sw = gtk_scrolled_window_new( NULL , NULL ); + gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(port_lv_sw), + GTK_POLICY_NEVER, GTK_POLICY_ALWAYS ); + port_lv_frame = gtk_frame_new( _("ALSA output ports") ); + gtk_container_add( GTK_CONTAINER(port_lv_sw) , port_lv ); + gtk_container_add( GTK_CONTAINER(port_lv_frame) , port_lv_sw ); + gtk_box_pack_start( GTK_BOX(content_vbox) , port_lv_frame , TRUE , TRUE , 0 ); + g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" , + G_CALLBACK(i_configure_ev_portlv_commit) , port_lv ); + + /* MIXER CARD/CONTROL COMBOBOXES */ + mixer_card_store = gtk_list_store_new( LISTCARD_N_COLUMNS , G_TYPE_STRING , G_TYPE_INT , G_TYPE_POINTER ); + mixer_card_cmb = gtk_combo_box_new_with_model( GTK_TREE_MODEL(mixer_card_store) ); /* soundcard combo box */ + mixer_ctl_cmb = gtk_combo_box_new(); /* mixer control combo box */ + g_signal_connect( mixer_card_cmb , "changed" , G_CALLBACK(i_configure_ev_cardcmb_changed) , mixer_ctl_cmb ); + while ( scards != NULL ) + { + GtkListStore *mixer_ctl_store; + GtkTreeIter itermix; + data_bucket_t * cardinfo = (data_bucket_t *)scards->data; + GSList *mixctl_list = cardinfo->bpointer[0]; + mixer_ctl_store = gtk_list_store_new( LISTMIXER_N_COLUMNS , G_TYPE_STRING , G_TYPE_INT ); + while ( mixctl_list != NULL ) + { + data_bucket_t * mixctlinfo = (data_bucket_t *)mixctl_list->data; + gtk_list_store_append( mixer_ctl_store , &itermix ); + gtk_list_store_set( mixer_ctl_store , &itermix , + LISTMIXER_NAME_COLUMN , mixctlinfo->bcharp[0] , + LISTMIXER_ID_COLUMN , mixctlinfo->bint[0] , -1 ); + mixctl_list = mixctl_list->next; /* on with next mixer control */ + } + gtk_list_store_append( mixer_card_store , &iter ); + gtk_list_store_set( mixer_card_store , &iter , + LISTCARD_NAME_COLUMN , cardinfo->bcharp[0] , + LISTCARD_ID_COLUMN , cardinfo->bint[0] , + LISTCARD_MIXERPTR_COLUMN , mixer_ctl_store , -1 ); + /* check if this corresponds to the value previously selected by user */ + if ( cardinfo->bint[0] == alsacfg->alsa_mixer_card_id ) + gtk_combo_box_set_active_iter( GTK_COMBO_BOX(mixer_card_cmb) , &iter ); + scards = scards->next; /* on with next card */ + } + g_object_unref( mixer_card_store ); /* free a reference, no longer needed */ + /* create renderer to display text in the mixer combo box */ + mixer_card_cmb_text_rndr = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(mixer_card_cmb) , mixer_card_cmb_text_rndr , TRUE ); + gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(mixer_card_cmb) , mixer_card_cmb_text_rndr , + "text" , LISTCARD_NAME_COLUMN ); + mixer_ctl_cmb_text_rndr = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(mixer_ctl_cmb) , mixer_ctl_cmb_text_rndr , TRUE ); + gtk_cell_layout_set_cell_data_func( GTK_CELL_LAYOUT(mixer_ctl_cmb) , mixer_ctl_cmb_text_rndr , + i_configure_gui_ctlcmb_datafunc , NULL , NULL ); + /* the event box is needed to display a tooltip for the mixer combo box */ + mixer_card_cmb_evbox = gtk_event_box_new(); + gtk_container_add( GTK_CONTAINER(mixer_card_cmb_evbox) , mixer_card_cmb ); + mixer_ctl_cmb_evbox = gtk_event_box_new(); + gtk_container_add( GTK_CONTAINER(mixer_ctl_cmb_evbox) , mixer_ctl_cmb ); + mixer_card_label = gtk_label_new( _("Soundcard: ") ); + gtk_misc_set_alignment( GTK_MISC(mixer_card_label) , 0 , 0.5 ); + mixer_ctl_label = gtk_label_new( _("Mixer control: ") ); + gtk_misc_set_alignment( GTK_MISC(mixer_ctl_label) , 0 , 0.5 ); + mixer_table = gtk_table_new( 3 , 2 , FALSE ); + gtk_container_set_border_width( GTK_CONTAINER(mixer_table), 4 ); + gtk_table_attach( GTK_TABLE(mixer_table) , mixer_card_label , 0 , 1 , 0 , 1 , + GTK_FILL , 0 , 1 , 2 ); + gtk_table_attach( GTK_TABLE(mixer_table) , mixer_card_cmb_evbox , 1 , 2 , 0 , 1 , + GTK_EXPAND | GTK_FILL , 0 , 1 , 2 ); + gtk_table_attach( GTK_TABLE(mixer_table) , mixer_ctl_label , 0 , 1 , 1 , 2 , + GTK_FILL , 0 , 1 , 2 ); + gtk_table_attach( GTK_TABLE(mixer_table) , mixer_ctl_cmb_evbox , 1 , 2 , 1 , 2 , + GTK_EXPAND | GTK_FILL , 0 , 1 , 2 ); + mixer_frame = gtk_frame_new( _("Mixer settings") ); + gtk_container_add( GTK_CONTAINER(mixer_frame) , mixer_table ); + gtk_box_pack_start( GTK_BOX(content_vbox) , mixer_frame , TRUE , TRUE , 0 ); + g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" , + G_CALLBACK(i_configure_ev_cardcmb_commit) , mixer_card_cmb ); + g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" , + G_CALLBACK(i_configure_ev_mixctlcmb_commit) , mixer_ctl_cmb ); + + free_card_list( scards_h ); + free_port_list( wports_h ); + g_module_close( alsa_module ); + + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , port_lv , + _("* Select ALSA output ports *\n" + "MIDI events will be sent to the ports selected here. In example, if your " + "audio card provides a hardware synth and you want to play MIDI with it, " + "you'll probably want to select the wavetable synthesizer ports.") , "" ); + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , mixer_card_cmb_evbox , + _("* Select ALSA mixer card *\n" + "The ALSA backend outputs directly through ALSA, it doesn't use effect " + "and ouput plugins from the player. During playback, the player volume" + "slider will manipulate the mixer control you select here. " + "If you're using wavetable synthesizer ports, you'll probably want to " + "select the Synth control here.") , "" ); + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , mixer_ctl_cmb_evbox , + _("* Select ALSA mixer control *\n" + "The ALSA backend outputs directly through ALSA, it doesn't use effect " + "and ouput plugins from the player. During playback, the player volume " + "slider will manipulate the mixer control you select here. " + "If you're using wavetable synthesizer ports, you'll probably want to " + "select the Synth control here.") , "" ); + } + else + { + /* display "not available" information */ + GtkWidget * info_label; + info_label = gtk_label_new( _("ALSA Backend not loaded or not available") ); + gtk_box_pack_start( GTK_BOX(alsa_page_vbox) , info_label , FALSE , FALSE , 2 ); + } + + gtk_box_pack_start( GTK_BOX(alsa_page_vbox) , content_vbox , TRUE , TRUE , 2 ); + gtk_container_add( GTK_CONTAINER(alsa_page_alignment) , alsa_page_vbox ); +} + + +void i_configure_gui_tablabel_alsa( GtkWidget * alsa_page_alignment , + gpointer backend_list_p , + gpointer commit_button ) +{ + GtkWidget *pagelabel_vbox, *pagelabel_image, *pagelabel_label; + GdkPixbuf *pagelabel_image_pix; + pagelabel_vbox = gtk_vbox_new( FALSE , 1 ); + pagelabel_image_pix = gdk_pixbuf_new_from_xpm_data( (const gchar **)backend_alsa_icon_xpm ); + pagelabel_image = gtk_image_new_from_pixbuf( pagelabel_image_pix ); g_object_unref( pagelabel_image_pix ); + pagelabel_label = gtk_label_new( "" ); + gtk_label_set_markup( GTK_LABEL(pagelabel_label) , "<span size=\"smaller\">ALSA\nbackend</span>" ); + gtk_label_set_justify( GTK_LABEL(pagelabel_label) , GTK_JUSTIFY_CENTER ); + gtk_box_pack_start( GTK_BOX(pagelabel_vbox) , pagelabel_image , FALSE , FALSE , 1 ); + gtk_box_pack_start( GTK_BOX(pagelabel_vbox) , pagelabel_label , FALSE , FALSE , 1 ); + gtk_container_add( GTK_CONTAINER(alsa_page_alignment) , pagelabel_vbox ); + gtk_widget_show_all( alsa_page_alignment ); + return; +} + + +gchar * i_configure_read_seq_ports_default( void ) +{ + FILE * fp = NULL; + /* first try, get seq ports from proc on card0 */ + fp = fopen( "/proc/asound/card0/wavetableD1" , "rb" ); + if ( fp ) + { + gchar buffer[100]; + while ( !feof( fp ) ) + { + fgets( buffer , 100 , fp ); + if (( strlen( buffer ) > 11 ) && ( !strncasecmp( buffer , "addresses: " , 11 ) )) + { + /* change spaces between ports (65:0 65:1 65:2 ...) + into commas (65:0,65:1,65:2,...) */ + g_strdelimit( &buffer[11] , " " , ',' ); + /* remove lf and cr from the end of the string */ + g_strdelimit( &buffer[11] , "\r\n" , '\0' ); + /* ready to go */ + DEBUGMSG( "init, default values for seq ports detected: %s\n" , &buffer[11] ); + fclose( fp ); + return g_strdup( &buffer[11] ); + } + } + fclose( fp ); + } + + /* second option: do not set ports at all, let the user + select the right ones in the nice config window :) */ + return g_strdup( "" ); +} + + + +void i_configure_cfg_alsa_alloc( void ) +{ + amidiplug_cfg_alsa_t * alsacfg = g_malloc(sizeof(amidiplug_cfg_alsa_t)); + amidiplug_cfg_backend->alsa = alsacfg; +} + + +void i_configure_cfg_alsa_free( void ) +{ + amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa; + g_free( alsacfg->alsa_seq_wports ); + g_free( alsacfg->alsa_mixer_ctl_name ); + g_free( amidiplug_cfg_backend->alsa ); +} + + +void i_configure_cfg_alsa_read( pcfg_t * cfgfile ) +{ + amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa; + + if (!cfgfile) + { + /* alsa backend defaults */ + alsacfg->alsa_seq_wports = i_configure_read_seq_ports_default(); + alsacfg->alsa_mixer_card_id = 0; + alsacfg->alsa_mixer_ctl_name = g_strdup( "Synth" ); + alsacfg->alsa_mixer_ctl_id = 0; + } + else + { + i_pcfg_read_string( cfgfile , "alsa" , "alsa_seq_wports" , &alsacfg->alsa_seq_wports , NULL ); + if ( alsacfg->alsa_seq_wports == NULL ) + alsacfg->alsa_seq_wports = i_configure_read_seq_ports_default(); /* pick default values */ + i_pcfg_read_integer( cfgfile , "alsa" , "alsa_mixer_card_id" , &alsacfg->alsa_mixer_card_id , 0 ); + i_pcfg_read_string( cfgfile , "alsa" , "alsa_mixer_ctl_name" , &alsacfg->alsa_mixer_ctl_name , "Synth" ); + i_pcfg_read_integer( cfgfile , "alsa" , "alsa_mixer_ctl_id" , &alsacfg->alsa_mixer_ctl_id , 0 ); + } +} + + +void i_configure_cfg_alsa_save( pcfg_t * cfgfile ) +{ + amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa; + + i_pcfg_write_string( cfgfile , "alsa" , "alsa_seq_wports" , alsacfg->alsa_seq_wports ); + i_pcfg_write_integer( cfgfile , "alsa" , "alsa_mixer_card_id" , alsacfg->alsa_mixer_card_id ); + i_pcfg_write_string( cfgfile , "alsa" , "alsa_mixer_ctl_name" , alsacfg->alsa_mixer_ctl_name ); + i_pcfg_write_integer( cfgfile , "alsa" , "alsa_mixer_ctl_id" , alsacfg->alsa_mixer_ctl_id ); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/i_configure-alsa.h Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,36 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#ifndef _I_CONFIGURE_ALSA_H +#define _I_CONFIGURE_ALSA_H 1 + +#include "i_configure_private.h" + + +extern amidiplug_cfg_backend_t * amidiplug_cfg_backend; + +void i_configure_gui_tab_alsa( GtkWidget * , gpointer , gpointer ); +void i_configure_gui_tablabel_alsa( GtkWidget * , gpointer , gpointer ); +void i_configure_cfg_alsa_alloc( void ); +void i_configure_cfg_alsa_free( void ); +void i_configure_cfg_alsa_read( pcfg_t * ); +void i_configure_cfg_alsa_save( pcfg_t * ); + +#endif /* !_I_CONFIGURE_ALSA_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/i_configure-ap.c Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,279 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + + +#include "i_configure-ap.h" +#include "amidi-plug-icon.xpm" + + +enum +{ + LISTBACKEND_NAME_COLUMN = 0, + LISTBACKEND_LONGNAME_COLUMN, + LISTBACKEND_DESC_COLUMN, + LISTBACKEND_FILENAME_COLUMN, + LISTBACKEND_PPOS_COLUMN, + LISTBACKEND_N_COLUMNS +}; + + +void i_configure_ev_backendlv_info( gpointer backend_lv ) +{ + GtkTreeModel * store; + GtkTreeIter iter; + GtkTreeSelection *sel = gtk_tree_view_get_selection( GTK_TREE_VIEW(backend_lv) ); + /* get the selected item */ + if ( gtk_tree_selection_get_selected( sel , &store , &iter ) ) + { + GtkWidget *bidialog; + GdkGeometry bi_hints; + GtkWidget *title_label, *title_frame; + GtkWidget *filename_entry, *filename_frame; + GtkWidget *description_label, *description_frame; + GtkWidget *parent_window = gtk_widget_get_toplevel( backend_lv ); + gchar *longname_title, *longname, *filename, *description; + gtk_tree_model_get( GTK_TREE_MODEL(store) , &iter , + LISTBACKEND_LONGNAME_COLUMN , &longname , + LISTBACKEND_DESC_COLUMN , &description , + LISTBACKEND_FILENAME_COLUMN , &filename , -1 ); + bidialog = gtk_dialog_new_with_buttons( _("AMIDI-Plug - backend information") , + GTK_WINDOW(parent_window) , + GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL , + GTK_STOCK_OK , GTK_RESPONSE_NONE , NULL ); + bi_hints.min_width = 360; bi_hints.min_height = -1; + gtk_window_set_geometry_hints( GTK_WINDOW(bidialog) , GTK_WIDGET(bidialog) , + &bi_hints , GDK_HINT_MIN_SIZE ); + + longname_title = g_markup_printf_escaped( "<span size=\"larger\" weight=\"bold\" >%s</span>" , longname ); + title_frame = gtk_frame_new( NULL ); + title_label = gtk_label_new( "" ); + gtk_label_set_markup( GTK_LABEL(title_label) , longname_title ); + g_free( longname_title ); g_free( longname ); + gtk_container_add( GTK_CONTAINER(title_frame) , title_label ); + gtk_box_pack_start( GTK_BOX(GTK_DIALOG(bidialog)->vbox) , title_frame , FALSE , FALSE , 0 ); + + filename_frame = gtk_frame_new( NULL ); + filename_entry = gtk_entry_new(); + gtk_entry_set_text( GTK_ENTRY(filename_entry) , filename ); + gtk_entry_set_alignment( GTK_ENTRY(filename_entry) , 0.5 ); + gtk_editable_set_editable( GTK_EDITABLE(filename_entry) , FALSE ); + gtk_entry_set_has_frame( GTK_ENTRY(filename_entry) , FALSE ); + g_free( filename ); + gtk_container_add( GTK_CONTAINER(filename_frame) , filename_entry ); + gtk_box_pack_start( GTK_BOX(GTK_DIALOG(bidialog)->vbox) , filename_frame , FALSE , FALSE , 0 ); + + description_frame = gtk_frame_new( NULL ); + description_label = gtk_label_new( description ); + gtk_misc_set_padding( GTK_MISC(description_label) , 4 , 4 ); + gtk_label_set_line_wrap( GTK_LABEL(description_label) , TRUE ); + g_free( description ); + gtk_container_add( GTK_CONTAINER(description_frame) , description_label ); + gtk_box_pack_start( GTK_BOX(GTK_DIALOG(bidialog)->vbox) , description_frame , TRUE , TRUE , 0 ); + + gtk_widget_show_all( bidialog ); + gtk_window_set_focus( GTK_WINDOW(bidialog) , NULL ); + gtk_dialog_run( GTK_DIALOG(bidialog) ); + gtk_widget_destroy( bidialog ); + } + return; +} + + +void i_configure_ev_backendlv_commit( gpointer backend_lv ) +{ + GtkTreeModel * store; + GtkTreeIter iter; + GtkTreeSelection *sel = gtk_tree_view_get_selection( GTK_TREE_VIEW(backend_lv) ); + /* get the selected item */ + if ( gtk_tree_selection_get_selected( sel , &store , &iter ) ) + { + g_free( amidiplug_cfg_ap.ap_seq_backend ); /* free previous */ + /* update amidiplug_cfg_ap.ap_seq_backend */ + gtk_tree_model_get( GTK_TREE_MODEL(store) , &iter , + LISTBACKEND_NAME_COLUMN , &amidiplug_cfg_ap.ap_seq_backend , -1 ); + } + return; +} + + +void i_configure_ev_settings_commit( gpointer settings_vbox ) +{ + GtkWidget * settings_precalc_checkbt = g_object_get_data( G_OBJECT(settings_vbox) , + "ap_opts_length_precalc" ); + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(settings_precalc_checkbt) ) ) + amidiplug_cfg_ap.ap_opts_length_precalc = 1; + else + amidiplug_cfg_ap.ap_opts_length_precalc = 0; + return; +} + + +gint i_configure_backendlist_sortf( GtkTreeModel * model , GtkTreeIter * a , + GtkTreeIter * b , gpointer data ) +{ + gint v_a = 0, v_b = 0; + gtk_tree_model_get( model , a , LISTBACKEND_PPOS_COLUMN , &v_a , -1 ); + gtk_tree_model_get( model , b , LISTBACKEND_PPOS_COLUMN , &v_b , -1 ); + return (v_a - v_b); +} + + +void i_configure_gui_tab_ap( GtkWidget * ap_page_alignment , + gpointer backend_list_p , + gpointer commit_button ) +{ + GtkWidget *ap_page_vbox; + GtkWidget *title_widget; + GtkWidget *content_vbox; /* this vbox will contain two items of equal space (50%/50%) */ + GtkWidget *settings_frame, *settings_vbox, *settings_precalc_checkbt; + GtkWidget *backend_lv_frame, *backend_lv, *backend_lv_sw; + GtkWidget *backend_lv_hbox, *backend_lv_vbbox, *backend_lv_infobt; + GtkListStore *backend_store; + GtkCellRenderer *backend_lv_text_rndr; + GtkTreeViewColumn *backend_lv_name_col; + GtkTreeIter backend_lv_iter_selected; + GtkTreeSelection *backend_lv_sel; + GtkTreeIter iter; + GtkTooltips *tips; + GSList * backend_list = backend_list_p; + + tips = gtk_tooltips_new(); + g_object_set_data_full( G_OBJECT(ap_page_alignment) , "tt" , tips , g_object_unref ); + + ap_page_vbox = gtk_vbox_new( FALSE , 0 ); + + title_widget = i_configure_gui_draw_title( _("AMIDI-PLUG PREFERENCES") ); + gtk_box_pack_start( GTK_BOX(ap_page_vbox) , title_widget , FALSE , FALSE , 2 ); + + content_vbox = gtk_vbox_new( TRUE , 2 ); + + backend_store = gtk_list_store_new( LISTBACKEND_N_COLUMNS , G_TYPE_STRING , G_TYPE_STRING , + G_TYPE_STRING , G_TYPE_STRING , G_TYPE_INT ); + gtk_tree_sortable_set_default_sort_func( GTK_TREE_SORTABLE(backend_store) , + i_configure_backendlist_sortf , NULL , NULL ); + gtk_tree_sortable_set_sort_column_id( GTK_TREE_SORTABLE(backend_store) , + GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID , + GTK_SORT_ASCENDING ); + while ( backend_list != NULL ) + { + amidiplug_sequencer_backend_name_t * mn = backend_list->data; + gtk_list_store_append( backend_store , &iter ); + gtk_list_store_set ( backend_store, &iter, + LISTBACKEND_NAME_COLUMN , mn->name , + LISTBACKEND_LONGNAME_COLUMN , mn->longname , + LISTBACKEND_DESC_COLUMN , mn->desc , + LISTBACKEND_FILENAME_COLUMN , mn->filename , + LISTBACKEND_PPOS_COLUMN , mn->ppos , -1 ); + if ( !strcmp( mn->name , amidiplug_cfg_ap.ap_seq_backend ) ) + backend_lv_iter_selected = iter; + backend_list = backend_list->next; + } + + backend_lv_frame = gtk_frame_new( _("Backend selection") ); + backend_lv = gtk_tree_view_new_with_model( GTK_TREE_MODEL(backend_store) ); + g_object_unref( backend_store ); + backend_lv_text_rndr = gtk_cell_renderer_text_new(); + backend_lv_name_col = gtk_tree_view_column_new_with_attributes( _("Available backends") , + backend_lv_text_rndr , + "text" , 1 , NULL ); + gtk_tree_view_append_column( GTK_TREE_VIEW(backend_lv), backend_lv_name_col ); + + backend_lv_sel = gtk_tree_view_get_selection( GTK_TREE_VIEW(backend_lv) ); + gtk_tree_selection_set_mode( GTK_TREE_SELECTION(backend_lv_sel) , GTK_SELECTION_BROWSE ); + gtk_tree_selection_select_iter( GTK_TREE_SELECTION(backend_lv_sel) , &backend_lv_iter_selected ); + + backend_lv_sw = gtk_scrolled_window_new( NULL , NULL ); + gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(backend_lv_sw) , + GTK_POLICY_NEVER , GTK_POLICY_ALWAYS ); + gtk_container_add( GTK_CONTAINER(backend_lv_sw) , backend_lv ); + g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" , + G_CALLBACK(i_configure_ev_backendlv_commit) , backend_lv ); + + backend_lv_hbox = gtk_hbox_new( FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(backend_lv_hbox) , backend_lv_sw , TRUE , TRUE , 0 ); + backend_lv_vbbox = gtk_vbox_new( FALSE , 2 ); + gtk_box_pack_start( GTK_BOX(backend_lv_hbox) , backend_lv_vbbox , FALSE , FALSE , 3 ); + backend_lv_infobt = gtk_button_new(); + gtk_button_set_image( GTK_BUTTON(backend_lv_infobt) , + gtk_image_new_from_stock( GTK_STOCK_DIALOG_INFO , GTK_ICON_SIZE_BUTTON ) ); + g_signal_connect_swapped( G_OBJECT(backend_lv_infobt) , "clicked" , + G_CALLBACK(i_configure_ev_backendlv_info) , backend_lv ); + gtk_box_pack_start( GTK_BOX(backend_lv_vbbox) , backend_lv_infobt , FALSE , FALSE , 0 ); + gtk_container_add( GTK_CONTAINER(backend_lv_frame) , backend_lv_hbox ); + + settings_frame = gtk_frame_new( _("Advanced settings") ); + settings_vbox = gtk_vbox_new( FALSE , 0 ); + gtk_container_set_border_width( GTK_CONTAINER(settings_vbox), 4 ); + settings_precalc_checkbt = gtk_check_button_new_with_label( _("pre-calculate length of MIDI files in playlist") ); + if ( amidiplug_cfg_ap.ap_opts_length_precalc ) + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(settings_precalc_checkbt) , TRUE ); + gtk_box_pack_start( GTK_BOX(settings_vbox) , settings_precalc_checkbt , FALSE , FALSE , 2 ); + gtk_container_add( GTK_CONTAINER(settings_frame) , settings_vbox ); + /* attach pointers of options to settings_vbox so we can handle all of them in a single callback */ + g_object_set_data( G_OBJECT(settings_vbox) , "ap_opts_length_precalc" , settings_precalc_checkbt ); + g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" , + G_CALLBACK(i_configure_ev_settings_commit) , settings_vbox ); + + gtk_box_pack_start( GTK_BOX(content_vbox) , backend_lv_frame , TRUE , TRUE , 0 ); + gtk_box_pack_start( GTK_BOX(content_vbox) , settings_frame , TRUE , TRUE , 0 ); + gtk_box_pack_start( GTK_BOX(ap_page_vbox) , content_vbox , TRUE , TRUE , 2 ); + gtk_container_add( GTK_CONTAINER(ap_page_alignment) , ap_page_vbox ); + + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , backend_lv , + _("* Backend selection *\n" + "AMIDI-Plug works with backends, in a modular fashion; here you should " + "select your backend; that is, the way MIDI events are going to be handled " + "and played.\nIf you have a hardware synthesizer on your audio card, and ALSA " + "supports it, you'll want to use the ALSA backend. It can also be " + "used with anything that provides an interface to the ALSA sequencer, including " + "software synths or external devices.\nIf you want to rely on a software " + "synthesizer and/or want to pipe audio into effect and output plugins of the " + "player you'll want to use the good FluidSynth backend.\nPress the info " + "button to read specific information about each backend.") , "" ); + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , settings_precalc_checkbt , + _("* Pre-calculate MIDI length *\n" + "If this option is enabled, AMIDI-Plug will calculate the MIDI file " + "length as soon as the player requests it, instead of doing that only " + "when the MIDI file is being played. In example, MIDI length " + "will be calculated straight after adding MIDI files in a playlist. " + "Disable this option if you want faster playlist loading (when a lot " + "of MIDI files are added), enable it to display more information " + "in the playlist straight after loading.") , "" ); +} + + +void i_configure_gui_tablabel_ap( GtkWidget * ap_page_alignment , + gpointer backend_list_p , + gpointer commit_button ) +{ + GtkWidget *pagelabel_vbox, *pagelabel_image, *pagelabel_label; + GdkPixbuf *pagelabel_image_pix; + pagelabel_vbox = gtk_vbox_new( FALSE , 1 ); + pagelabel_image_pix = gdk_pixbuf_new_from_xpm_data( (const gchar **)amidi_plug_icon_xpm ); + pagelabel_image = gtk_image_new_from_pixbuf( pagelabel_image_pix ); g_object_unref( pagelabel_image_pix ); + pagelabel_label = gtk_label_new( "" ); + gtk_label_set_markup( GTK_LABEL(pagelabel_label) , "<span size=\"smaller\">AMIDI\nPlug</span>" ); + gtk_label_set_justify( GTK_LABEL(pagelabel_label) , GTK_JUSTIFY_CENTER ); + gtk_box_pack_start( GTK_BOX(pagelabel_vbox) , pagelabel_image , FALSE , FALSE , 1 ); + gtk_box_pack_start( GTK_BOX(pagelabel_vbox) , pagelabel_label , FALSE , FALSE , 1 ); + gtk_container_add( GTK_CONTAINER(ap_page_alignment) , pagelabel_vbox ); + gtk_widget_show_all( ap_page_alignment ); + return; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/i_configure-ap.h Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,33 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#ifndef _I_CONFIGURE_AP_H +#define _I_CONFIGURE_AP_H 1 + +#include "i_configure.h" +#include "i_configure_private.h" + + +extern amidiplug_cfg_ap_t amidiplug_cfg_ap; + +void i_configure_gui_tab_ap( GtkWidget * , gpointer , gpointer ); +void i_configure_gui_tablabel_ap( GtkWidget * , gpointer , gpointer ); + +#endif /* !_I_CONFIGURE_AP_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/i_configure-dummy.c Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,410 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + + +#include "i_configure-dummy.h" +#include "backend-dummy/b-dummy-config.h" +#include "backend-dummy/backend-dummy-icon.xpm" + + +void i_configure_ev_logfile_toggle( GtkToggleButton *diflogfiles_radiobt , gpointer logfile_table ) +{ + GList * tc_list = gtk_container_get_children( GTK_CONTAINER(logfile_table) ); + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(diflogfiles_radiobt) ) ) + { + gtk_widget_set_sensitive( g_list_nth_data(tc_list,0) , TRUE ); /* dir bbutton */ + gtk_widget_set_sensitive( g_list_nth_data(tc_list,1) , TRUE ); /* dir entry */ + gtk_widget_set_sensitive( g_list_nth_data(tc_list,2) , TRUE ); /* dir label */ + gtk_widget_set_sensitive( g_list_nth_data(tc_list,4) , FALSE ); /* file bbutton */ + gtk_widget_set_sensitive( g_list_nth_data(tc_list,5) , FALSE ); /* file entry */ + gtk_widget_set_sensitive( g_list_nth_data(tc_list,6) , FALSE ); /* file label */ + } + else + { + gtk_widget_set_sensitive( g_list_nth_data(tc_list,0) , FALSE ); /* dir bbutton */ + gtk_widget_set_sensitive( g_list_nth_data(tc_list,1) , FALSE ); /* dir entry */ + gtk_widget_set_sensitive( g_list_nth_data(tc_list,2) , FALSE ); /* dir label */ + gtk_widget_set_sensitive( g_list_nth_data(tc_list,4) , TRUE ); /* file bbutton */ + gtk_widget_set_sensitive( g_list_nth_data(tc_list,5) , TRUE ); /* file entry */ + gtk_widget_set_sensitive( g_list_nth_data(tc_list,6) , TRUE ); /* file label */ + } +} + + +void i_configure_ev_enablelog_toggle( GtkToggleButton *logwithfile_radiobt , gpointer logfile_table ) +{ + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(logwithfile_radiobt) ) ) + { + gtk_widget_set_sensitive( GTK_WIDGET(logfile_table) , TRUE ); + i_configure_ev_logfile_toggle( g_object_get_data(G_OBJECT(logfile_table),"lfstyle-opt2") , logfile_table ); + } + else + { + gtk_widget_set_sensitive( GTK_WIDGET(logfile_table) , FALSE ); + } +} + + +void i_configure_ev_enablelog_commit( gpointer enablelog_radiobt ) +{ + amidiplug_cfg_dumm_t * dummcfg = amidiplug_cfg_backend->dumm; + GSList *group = gtk_radio_button_get_group( GTK_RADIO_BUTTON(enablelog_radiobt) ); + while ( group != NULL ) + { + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(group->data) ) ) + { + dummcfg->dumm_logger_enable = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(group->data),"val")); + group = NULL; /* do not iterate further */ + } + else + group = group->next; + } +} + +void i_configure_ev_lfstyle_commit( gpointer lfstyle_radiobt ) +{ + amidiplug_cfg_dumm_t * dummcfg = amidiplug_cfg_backend->dumm; + GSList *group = gtk_radio_button_get_group( GTK_RADIO_BUTTON(lfstyle_radiobt) ); + while ( group != NULL ) + { + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(group->data) ) ) + { + dummcfg->dumm_logger_lfstyle = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(group->data),"val")); + group = NULL; /* do not iterate further */ + } + else + group = group->next; + } +} + + +void i_configure_ev_plspeed_commit( gpointer plspeed_normal_radiobt ) +{ + amidiplug_cfg_dumm_t * dummcfg = amidiplug_cfg_backend->dumm; + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(plspeed_normal_radiobt) ) ) + dummcfg->dumm_playback_speed = 0; + else + dummcfg->dumm_playback_speed = 1; +} + + +void i_configure_ev_logfname_commit( gpointer logfname_entry ) +{ + amidiplug_cfg_dumm_t * dummcfg = amidiplug_cfg_backend->dumm; + g_free( dummcfg->dumm_logger_logfile ); /* free previous */ + dummcfg->dumm_logger_logfile = g_strdup( gtk_entry_get_text(GTK_ENTRY(logfname_entry)) ); +} + + +void i_configure_ev_logdir_commit( gpointer logdir_entry ) +{ + amidiplug_cfg_dumm_t * dummcfg = amidiplug_cfg_backend->dumm; + g_free( dummcfg->dumm_logger_logdir ); /* free previous */ + dummcfg->dumm_logger_logdir = g_strdup( gtk_entry_get_text(GTK_ENTRY(logdir_entry)) ); +} + + +void i_configure_gui_tab_dumm( GtkWidget * dumm_page_alignment , + gpointer backend_list_p , + gpointer commit_button ) +{ + GtkWidget *dumm_page_vbox; + GtkWidget *title_widget; + GtkWidget *content_vbox; + GSList * backend_list = backend_list_p; + gboolean dumm_module_ok = FALSE; + gchar * dumm_module_pathfilename; + + dumm_page_vbox = gtk_vbox_new( FALSE , 0 ); + + title_widget = i_configure_gui_draw_title( _("DUMMY BACKEND CONFIGURATION") ); + gtk_box_pack_start( GTK_BOX(dumm_page_vbox) , title_widget , FALSE , FALSE , 2 ); + + content_vbox = gtk_vbox_new( FALSE , 2 ); + + /* check if the dummy module is available */ + while ( backend_list != NULL ) + { + amidiplug_sequencer_backend_name_t * mn = backend_list->data; + if ( !strcmp( mn->name , "dummy" ) ) + { + dumm_module_ok = TRUE; + dumm_module_pathfilename = mn->filename; + break; + } + backend_list = backend_list->next; + } + + if ( dumm_module_ok ) + { + GtkWidget *midilogger_frame, *midilogger_vbox; + GtkWidget *midilogger_enablelog_vbox, *midilogger_enablelog_option[4]; + GtkWidget *midilogger_logfile_frame, *midilogger_logfile_table, *midilogger_logfile_option[3]; + GtkWidget *midilogger_logfile_logdir_labelalign, *midilogger_logfile_logdir_label; + GtkWidget *midilogger_logfile_logdir_entry, *midilogger_logfile_logdir_bbutton; + GtkWidget *midilogger_logfile_logfname_labelalign, *midilogger_logfile_logfname_label; + GtkWidget *midilogger_logfile_logfname_entry, *midilogger_logfile_logfname_bbutton; + GtkWidget *plspeed_frame, *plspeed_vbox, *plspeed_option[2]; + GtkTooltips *tips; + + amidiplug_cfg_dumm_t * dummcfg = amidiplug_cfg_backend->dumm; + + tips = gtk_tooltips_new(); + g_object_set_data_full( G_OBJECT(dumm_page_alignment) , "tt" , tips , g_object_unref ); + + /* midilogger settings */ + midilogger_frame = gtk_frame_new( _("MIDI logger settings") ); + midilogger_vbox = gtk_vbox_new( FALSE , 4 ); + gtk_container_set_border_width( GTK_CONTAINER(midilogger_vbox), 4 ); + gtk_container_add( GTK_CONTAINER(midilogger_frame) , midilogger_vbox ); + + /* midilogger settings - enable/disable */ + midilogger_enablelog_vbox = gtk_vbox_new( FALSE , 0 ); + midilogger_enablelog_option[0] = gtk_radio_button_new_with_label( NULL , + _("Do not log anything") ); + g_object_set_data( G_OBJECT(midilogger_enablelog_option[0]) , "val" , GINT_TO_POINTER(0) ); + midilogger_enablelog_option[1] = gtk_radio_button_new_with_label_from_widget( + GTK_RADIO_BUTTON(midilogger_enablelog_option[0]) , + _("Log MIDI events to standard output") ); + g_object_set_data( G_OBJECT(midilogger_enablelog_option[1]) , "val" , GINT_TO_POINTER(1) ); + midilogger_enablelog_option[2] = gtk_radio_button_new_with_label_from_widget( + GTK_RADIO_BUTTON(midilogger_enablelog_option[0]) , + _("Log MIDI events to standard error") ); + g_object_set_data( G_OBJECT(midilogger_enablelog_option[2]) , "val" , GINT_TO_POINTER(2) ); + midilogger_enablelog_option[3] = gtk_radio_button_new_with_label_from_widget( + GTK_RADIO_BUTTON(midilogger_enablelog_option[0]) , + _("Log MIDI events to file") ); + g_object_set_data( G_OBJECT(midilogger_enablelog_option[3]) , "val" , GINT_TO_POINTER(3) ); + gtk_box_pack_start( GTK_BOX(midilogger_enablelog_vbox) , midilogger_enablelog_option[0] , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(midilogger_enablelog_vbox) , midilogger_enablelog_option[1] , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(midilogger_enablelog_vbox) , midilogger_enablelog_option[2] , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(midilogger_enablelog_vbox) , midilogger_enablelog_option[3] , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(midilogger_vbox) , midilogger_enablelog_vbox , FALSE , FALSE , 0 ); + + /* midilogger settings - logfile options */ + midilogger_logfile_frame = gtk_frame_new( _("Logfile settings") ); + midilogger_logfile_table = gtk_table_new( 5 , 3 , FALSE ); + gtk_table_set_col_spacings( GTK_TABLE(midilogger_logfile_table) , 2 ); + gtk_container_set_border_width( GTK_CONTAINER(midilogger_logfile_table), 4 ); + gtk_container_add( GTK_CONTAINER(midilogger_logfile_frame) , midilogger_logfile_table ); + gtk_box_pack_start( GTK_BOX(midilogger_vbox) , midilogger_logfile_frame , FALSE , FALSE , 0 ); + midilogger_logfile_option[0] = gtk_radio_button_new_with_label( NULL , + _("Use a single file to log everything (rewrite)") ); + g_object_set_data( G_OBJECT(midilogger_logfile_option[0]) , "val" , GINT_TO_POINTER(0) ); + midilogger_logfile_option[1] = gtk_radio_button_new_with_label_from_widget( + GTK_RADIO_BUTTON(midilogger_logfile_option[0]) , + _("Use a single file to log everything (append)") ); + g_object_set_data( G_OBJECT(midilogger_logfile_option[1]) , "val" , GINT_TO_POINTER(1) ); + midilogger_logfile_option[2] = gtk_radio_button_new_with_label_from_widget( + GTK_RADIO_BUTTON(midilogger_logfile_option[0]) , + _("Use a different logfile for each MIDI file") ); + g_object_set_data( G_OBJECT(midilogger_logfile_option[2]) , "val" , GINT_TO_POINTER(2) ); + g_object_set_data( G_OBJECT(midilogger_logfile_table) , "lfstyle-opt2" , midilogger_logfile_option[2] ); + /* midilogger settings - logfile options - dir entry box */ + midilogger_logfile_logdir_labelalign = gtk_alignment_new( 0.5 , 0.5 , 1 , 1 ); + gtk_alignment_set_padding( GTK_ALIGNMENT(midilogger_logfile_logdir_labelalign) , 0 , 0 , 15 , 0 ); + midilogger_logfile_logdir_label = gtk_label_new( _("\302\273 Log dir:") ); + gtk_container_add( GTK_CONTAINER(midilogger_logfile_logdir_labelalign) , midilogger_logfile_logdir_label ); + midilogger_logfile_logdir_entry = gtk_entry_new(); + gtk_entry_set_text( GTK_ENTRY(midilogger_logfile_logdir_entry) , dummcfg->dumm_logger_logdir ); + g_object_set_data( G_OBJECT(midilogger_logfile_logdir_entry) , "fc-act", + GINT_TO_POINTER(GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) ); + midilogger_logfile_logdir_bbutton = gtk_button_new_with_label( _("browse") ); + g_signal_connect_swapped( G_OBJECT(midilogger_logfile_logdir_bbutton) , "clicked" , + G_CALLBACK(i_configure_ev_browse_for_entry) , midilogger_logfile_logdir_entry ); + /* midilogger settings - logfile options - file entry box */ + midilogger_logfile_logfname_labelalign = gtk_alignment_new( 0.5 , 0.5 , 1 , 1 ); + gtk_alignment_set_padding( GTK_ALIGNMENT(midilogger_logfile_logfname_labelalign) , 0 , 0 , 15 , 0 ); + midilogger_logfile_logfname_label = gtk_label_new( _("\302\273 Log file:") ); + gtk_container_add( GTK_CONTAINER(midilogger_logfile_logfname_labelalign) , midilogger_logfile_logfname_label ); + midilogger_logfile_logfname_entry = gtk_entry_new(); + gtk_entry_set_text( GTK_ENTRY(midilogger_logfile_logfname_entry) , dummcfg->dumm_logger_logfile ); + g_object_set_data( G_OBJECT(midilogger_logfile_logfname_entry) , "fc-act", + GINT_TO_POINTER(GTK_FILE_CHOOSER_ACTION_OPEN) ); + midilogger_logfile_logfname_bbutton = gtk_button_new_with_label( _("browse") ); + g_signal_connect_swapped( G_OBJECT(midilogger_logfile_logfname_bbutton) , "clicked" , + G_CALLBACK(i_configure_ev_browse_for_entry) , midilogger_logfile_logfname_entry ); + /* midilogger settings - logfile options - pack everything in table */ + gtk_table_attach( GTK_TABLE(midilogger_logfile_table) , midilogger_logfile_option[0] , + 0 , 3 , 0 , 1 , GTK_EXPAND | GTK_FILL , 0 , 0 , 0 ); + gtk_table_attach( GTK_TABLE(midilogger_logfile_table) , midilogger_logfile_option[1] , + 0 , 3 , 1 , 2 , GTK_EXPAND | GTK_FILL , 0 , 0 , 0 ); + gtk_table_attach( GTK_TABLE(midilogger_logfile_table) , midilogger_logfile_logfname_labelalign , + 0 , 1 , 2 , 3 , GTK_FILL , 0 , 0 , 0 ); + gtk_table_attach( GTK_TABLE(midilogger_logfile_table) , midilogger_logfile_logfname_entry , + 1 , 2 , 2 , 3 , GTK_EXPAND | GTK_FILL , 0 , 0 , 0 ); + gtk_table_attach( GTK_TABLE(midilogger_logfile_table) , midilogger_logfile_logfname_bbutton , + 2 , 3 , 2 , 3 , GTK_FILL , 0 , 0 , 0 ); + gtk_table_attach( GTK_TABLE(midilogger_logfile_table) , midilogger_logfile_option[2] , + 0 , 3 , 3 , 4 , GTK_EXPAND | GTK_FILL , 0 , 0 , 0 ); + gtk_table_attach( GTK_TABLE(midilogger_logfile_table) , midilogger_logfile_logdir_labelalign , + 0 , 1 , 4 , 5 , GTK_FILL , 0 , 0 , 0 ); + gtk_table_attach( GTK_TABLE(midilogger_logfile_table) , midilogger_logfile_logdir_entry , + 1 , 2 , 4 , 5 , GTK_EXPAND | GTK_FILL , 0 , 0 , 0 ); + gtk_table_attach( GTK_TABLE(midilogger_logfile_table) , midilogger_logfile_logdir_bbutton , + 2 , 3 , 4 , 5 , GTK_FILL , 0 , 0 , 0 ); + + gtk_box_pack_start( GTK_BOX(content_vbox) , midilogger_frame , FALSE , FALSE , 0 ); + + /* playback speed settings */ + plspeed_frame = gtk_frame_new( _("Playback speed") ); + plspeed_vbox = gtk_vbox_new( FALSE , 2 ); + gtk_container_set_border_width( GTK_CONTAINER(plspeed_vbox), 4 ); + gtk_container_add( GTK_CONTAINER(plspeed_frame) , plspeed_vbox ); + plspeed_option[0] = gtk_radio_button_new_with_label( NULL , + _("Play at normal speed") ); + plspeed_option[1] = gtk_radio_button_new_with_label_from_widget( + GTK_RADIO_BUTTON(plspeed_option[0]) , + _("Play as fast as possible") ); + gtk_box_pack_start( GTK_BOX(plspeed_vbox) , plspeed_option[0] , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(plspeed_vbox) , plspeed_option[1] , FALSE , FALSE , 0 ); + + gtk_box_pack_start( GTK_BOX(content_vbox) , plspeed_frame , FALSE , FALSE , 0 ); + + /* set values */ + /* we check this before connecting signals, it would be a useless work to + set/unset widget sensitivity at this time; in fact everything in the table is + going to lose sensitivity anyway, until i_configure_ev_enablelog_toggle is called */ + switch ( dummcfg->dumm_logger_lfstyle ) + { + case 1: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(midilogger_logfile_option[1]) , TRUE ); break; + case 2: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(midilogger_logfile_option[2]) , TRUE ); break; + case 0: + default: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(midilogger_logfile_option[0]) , TRUE ); break; + } + gtk_widget_set_sensitive( GTK_WIDGET(midilogger_logfile_table) , FALSE ); + g_signal_connect( G_OBJECT(midilogger_enablelog_option[3]) , "toggled" , + G_CALLBACK(i_configure_ev_enablelog_toggle) , midilogger_logfile_table ); + g_signal_connect( G_OBJECT(midilogger_logfile_option[2]) , "toggled" , + G_CALLBACK(i_configure_ev_logfile_toggle) , midilogger_logfile_table ); + switch ( dummcfg->dumm_logger_enable ) + { + case 1: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(midilogger_enablelog_option[1]) , TRUE ); break; + case 2: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(midilogger_enablelog_option[2]) , TRUE ); break; + case 3: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(midilogger_enablelog_option[3]) , TRUE ); break; + case 0: + default: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(midilogger_enablelog_option[0]) , TRUE ); break; + } + switch ( dummcfg->dumm_playback_speed ) + { + case 1: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(plspeed_option[1]) , TRUE ); break; + case 0: + default: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(plspeed_option[0]) , TRUE ); break; + } + + /* commit events */ + g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" , + G_CALLBACK(i_configure_ev_enablelog_commit) , midilogger_enablelog_option[0] ); + g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" , + G_CALLBACK(i_configure_ev_lfstyle_commit) , midilogger_logfile_option[0] ); + g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" , + G_CALLBACK(i_configure_ev_plspeed_commit) , plspeed_option[0] ); + g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" , + G_CALLBACK(i_configure_ev_logfname_commit) , midilogger_logfile_logfname_entry ); + g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" , + G_CALLBACK(i_configure_ev_logdir_commit) , midilogger_logfile_logdir_entry ); + + } + else + { + /* display "not available" information */ + GtkWidget * info_label; + info_label = gtk_label_new( _("Dummy Backend not loaded or not available") ); + gtk_box_pack_start( GTK_BOX(dumm_page_vbox) , info_label , FALSE , FALSE , 2 ); + } + + gtk_box_pack_start( GTK_BOX(dumm_page_vbox) , content_vbox , TRUE , TRUE , 2 ); + gtk_container_add( GTK_CONTAINER(dumm_page_alignment) , dumm_page_vbox ); +} + + +void i_configure_gui_tablabel_dumm( GtkWidget * dumm_page_alignment , + gpointer backend_list_p , + gpointer commit_button ) +{ + GtkWidget *pagelabel_vbox, *pagelabel_image, *pagelabel_label; + GdkPixbuf *pagelabel_image_pix; + pagelabel_vbox = gtk_vbox_new( FALSE , 1 ); + pagelabel_image_pix = gdk_pixbuf_new_from_xpm_data( (const gchar **)backend_dummy_icon_xpm ); + pagelabel_image = gtk_image_new_from_pixbuf( pagelabel_image_pix ); g_object_unref( pagelabel_image_pix ); + pagelabel_label = gtk_label_new( "" ); + gtk_label_set_markup( GTK_LABEL(pagelabel_label) , "<span size=\"smaller\">Dummy\nbackend</span>" ); + gtk_label_set_justify( GTK_LABEL(pagelabel_label) , GTK_JUSTIFY_CENTER ); + gtk_box_pack_start( GTK_BOX(pagelabel_vbox) , pagelabel_image , FALSE , FALSE , 1 ); + gtk_box_pack_start( GTK_BOX(pagelabel_vbox) , pagelabel_label , FALSE , FALSE , 1 ); + gtk_container_add( GTK_CONTAINER(dumm_page_alignment) , pagelabel_vbox ); + gtk_widget_show_all( dumm_page_alignment ); + return; +} + + +void i_configure_cfg_dumm_alloc( void ) +{ + amidiplug_cfg_dumm_t * dummcfg = g_malloc(sizeof(amidiplug_cfg_dumm_t)); + amidiplug_cfg_backend->dumm = dummcfg; +} + + +void i_configure_cfg_dumm_free( void ) +{ + amidiplug_cfg_dumm_t * dummcfg = amidiplug_cfg_backend->dumm; + g_free( dummcfg->dumm_logger_logfile ); + g_free( dummcfg->dumm_logger_logdir ); +} + + +void i_configure_cfg_dumm_read( pcfg_t * cfgfile ) +{ + amidiplug_cfg_dumm_t * dummcfg = amidiplug_cfg_backend->dumm; + gchar * def_logfile = g_strjoin( "" , g_get_home_dir() , "/amidi-plug.log" , NULL ); + gchar * def_logdir = (gchar*)g_get_home_dir(); + + if (!cfgfile) + { + /* fluidsynth backend defaults */ + dummcfg->dumm_logger_enable = 0; + dummcfg->dumm_logger_lfstyle = 0; + dummcfg->dumm_playback_speed = 0; + dummcfg->dumm_logger_logfile = g_strdup( def_logfile ); + dummcfg->dumm_logger_logdir = g_strdup( def_logdir ); + } + else + { + i_pcfg_read_integer( cfgfile , "dumm" , "dumm_logger_enable" , &dummcfg->dumm_logger_enable , 0 ); + i_pcfg_read_integer( cfgfile , "dumm" , "dumm_logger_lfstyle" , &dummcfg->dumm_logger_lfstyle , 0 ); + i_pcfg_read_integer( cfgfile , "dumm" , "dumm_playback_speed" , &dummcfg->dumm_playback_speed , 0 ); + i_pcfg_read_string( cfgfile , "dumm" , "dumm_logger_logfile" , &dummcfg->dumm_logger_logfile , def_logfile ); + i_pcfg_read_string( cfgfile , "dumm" , "dumm_logger_logdir" , &dummcfg->dumm_logger_logdir , def_logdir ); + } + + g_free( def_logfile ); +} + + +void i_configure_cfg_dumm_save( pcfg_t * cfgfile ) +{ + amidiplug_cfg_dumm_t * dummcfg = amidiplug_cfg_backend->dumm; + + i_pcfg_write_integer( cfgfile , "dumm" , "dumm_logger_enable" , dummcfg->dumm_logger_enable ); + i_pcfg_write_integer( cfgfile , "dumm" , "dumm_logger_lfstyle" , dummcfg->dumm_logger_lfstyle ); + i_pcfg_write_integer( cfgfile , "dumm" , "dumm_playback_speed" , dummcfg->dumm_playback_speed ); + i_pcfg_write_string( cfgfile , "dumm" , "dumm_logger_logfile" , dummcfg->dumm_logger_logfile ); + i_pcfg_write_string( cfgfile , "dumm" , "dumm_logger_logdir" , dummcfg->dumm_logger_logdir ); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/i_configure-dummy.h Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,36 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#ifndef _I_CONFIGURE_DUMMY_H +#define _I_CONFIGURE_DUMMY_H 1 + +#include "i_configure_private.h" + + +extern amidiplug_cfg_backend_t * amidiplug_cfg_backend; + +void i_configure_gui_tab_dumm( GtkWidget * , gpointer , gpointer ); +void i_configure_gui_tablabel_dumm( GtkWidget * , gpointer , gpointer ); +void i_configure_cfg_dumm_alloc( void ); +void i_configure_cfg_dumm_free( void ); +void i_configure_cfg_dumm_read( pcfg_t * ); +void i_configure_cfg_dumm_save( pcfg_t * ); + +#endif /* !_I_CONFIGURE_DUMMY_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/i_configure-fluidsynth.c Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,843 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + + +#include "i_configure-fluidsynth.h" +#include "backend-fluidsynth/b-fluidsynth-config.h" +#include "backend-fluidsynth/backend-fluidsynth-icon.xpm" + + +void i_configure_ev_toggle_default( GtkToggleButton *togglebutton , gpointer hbox ) +{ + if ( gtk_toggle_button_get_active( togglebutton ) ) + gtk_widget_set_sensitive( GTK_WIDGET(hbox) , FALSE ); + else + gtk_widget_set_sensitive( GTK_WIDGET(hbox) , TRUE ); +} + + +void i_configure_ev_buffertuner_valuechanged( GtkRange *buffertuner_range ) +{ + gint bufsize_val, bufmarginsize_val; + gint i = (gint)gtk_range_get_value( GTK_RANGE(buffertuner_range) ); + GtkWidget *bufsize_spin = g_object_get_data( G_OBJECT(buffertuner_range) , "bufsize_spin" ); + GtkWidget *bufmarginsize_spin = g_object_get_data( G_OBJECT(buffertuner_range) , "bufmarginsize_spin" ); + + if ( i < 33 ) + { + bufsize_val = 256 + (i * 16); /* linear growth of 16i - bufsize_val <= 768 */ + if ( i > 16 ) + bufmarginsize_val = 15 + ((i - 15) / 2); /* linear growth of i/2 */ + else + bufmarginsize_val = 15; /* do not go below 10 even when bufsize < 512 */ + } + else if ( i < 42 ) + { + bufsize_val = 768 + ((i - 33) * 32); /* linear growth of 32i - bufsize_val <= 1024 */ + bufmarginsize_val = 15 + ( (i - 16) / 2 ); /* linear growth of i/2 */ + } + else + { + bufsize_val = 1024 + ( 32 << (i - 42) ); /* exponential growth - bufsize_val > 1024 */ + bufmarginsize_val = 15 + ( (i - 16) / 2 ); /* linear growth of i/2 */ + } + + gtk_spin_button_set_value( GTK_SPIN_BUTTON(bufsize_spin) , bufsize_val ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON(bufmarginsize_spin) , bufmarginsize_val ); +} + + +void i_configure_ev_sffile_commit( gpointer sffile_entry ) +{ + amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn; + g_free( fsyncfg->fsyn_soundfont_file ); /* free previous */ + fsyncfg->fsyn_soundfont_file = g_strdup( gtk_entry_get_text(GTK_ENTRY(sffile_entry)) ); +} + + +void i_configure_ev_sfload_commit( gpointer sfload_radiobt ) +{ + amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn; + GSList *group = gtk_radio_button_get_group( GTK_RADIO_BUTTON(sfload_radiobt) ); + while ( group != NULL ) + { + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(group->data) ) ) + fsyncfg->fsyn_soundfont_load = GPOINTER_TO_INT(g_object_get_data( G_OBJECT(group->data) , "val" )); + group = group->next; + } +} + + +void i_configure_ev_sygain_commit( gpointer gain_spinbt ) +{ + amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn; + if ( GTK_WIDGET_IS_SENSITIVE(GTK_WIDGET(gain_spinbt)) ) + fsyncfg->fsyn_synth_gain = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(gain_spinbt)) * 10); + else + fsyncfg->fsyn_synth_gain = -1; +} + + +void i_configure_ev_sypoly_commit( gpointer poly_spinbt ) +{ + amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn; + if ( GTK_WIDGET_IS_SENSITIVE(GTK_WIDGET(poly_spinbt)) ) + fsyncfg->fsyn_synth_poliphony = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(poly_spinbt))); + else + fsyncfg->fsyn_synth_poliphony = -1; +} + + +void i_configure_ev_syreverb_commit( gpointer reverb_yes_radiobt ) +{ + amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn; + if ( GTK_WIDGET_IS_SENSITIVE(GTK_WIDGET(reverb_yes_radiobt)) ) + { + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(reverb_yes_radiobt) ) ) + fsyncfg->fsyn_synth_reverb = 1; + else + fsyncfg->fsyn_synth_reverb = 0; + } + else + fsyncfg->fsyn_synth_reverb = -1; +} + + +void i_configure_ev_sychorus_commit( gpointer chorus_yes_radiobt ) +{ + amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn; + if ( GTK_WIDGET_IS_SENSITIVE(GTK_WIDGET(chorus_yes_radiobt)) ) + { + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(chorus_yes_radiobt) ) ) + fsyncfg->fsyn_synth_chorus = 1; + else + fsyncfg->fsyn_synth_chorus = 0; + } + else + fsyncfg->fsyn_synth_chorus = -1; +} + + +void i_configure_ev_sysamplerate_togglecustom( GtkToggleButton *custom_radiobt , gpointer custom_entry ) +{ + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(custom_radiobt) ) ) + gtk_widget_set_sensitive( GTK_WIDGET(custom_entry) , TRUE ); + else + gtk_widget_set_sensitive( GTK_WIDGET(custom_entry) , FALSE ); +} + + +void i_configure_ev_sysamplerate_commit( gpointer samplerate_custom_radiobt ) +{ + amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn; + if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(samplerate_custom_radiobt)) ) + { + GtkWidget *customentry = g_object_get_data( G_OBJECT(samplerate_custom_radiobt) , "customentry" ); + gint customvalue = strtol( gtk_entry_get_text(GTK_ENTRY(customentry)) , NULL , 10 ); + if (( customvalue > 22050 ) && ( customvalue < 96000 )) + fsyncfg->fsyn_synth_samplerate = customvalue; + else + fsyncfg->fsyn_synth_samplerate = 44100; + } + else + { + GSList *group = gtk_radio_button_get_group( GTK_RADIO_BUTTON(samplerate_custom_radiobt) ); + while ( group != NULL ) + { + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(group->data) ) ) + fsyncfg->fsyn_synth_samplerate = GPOINTER_TO_INT(g_object_get_data( G_OBJECT(group->data) , "val" )); + group = group->next; + } + } +} + + +void i_configure_ev_bufsize_commit( gpointer bufsize_spinbt ) +{ + amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn; + fsyncfg->fsyn_buffer_size = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(bufsize_spinbt))); +} + + +void i_configure_ev_bufmarginsize_commit( gpointer marginsize_spinbt ) +{ + amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn; + fsyncfg->fsyn_buffer_margin = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(marginsize_spinbt))); +} + + +void i_configure_ev_bufmargininc_commit( gpointer margininc_spinbt ) +{ + amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn; + fsyncfg->fsyn_buffer_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(margininc_spinbt))); +} + + +void i_configure_buffertuner_setvalue( GtkWidget * buftuner_hscale , gint bufsize ) +{ + gint scale_value = 0; + if ( bufsize <= 768 ) + { + scale_value = ( bufsize - 256 ) / 16; + } + else if ( bufsize <= 1024 ) + { + scale_value = ( bufsize + 288 ) / 32; + } + else + { + gint tcount = 0, tval = bufsize - 1024; + tval = tval >> 1; + while ( tval > 0 ) + { + tval = tval >> 1; + tcount++; + } + scale_value = 37 + tcount; + } + if ( scale_value < 0 ) + scale_value = 0; + else if ( scale_value > 53 ) + scale_value = 53; + gtk_range_set_value( GTK_RANGE(buftuner_hscale) , scale_value ); +} + + +void i_configure_ev_buffertuner_default( gpointer buffertuner_hscale ) +{ + GtkWidget *bufsize_spin = g_object_get_data( G_OBJECT(buffertuner_hscale) , "bufsize_spin" ); + GtkWidget *bufmarginsize_spin = g_object_get_data( G_OBJECT(buffertuner_hscale) , "bufmarginsize_spin" ); + GtkWidget *bufmargininc_spin = g_object_get_data( G_OBJECT(buffertuner_hscale) , "bufmargininc_spin" ); + i_configure_buffertuner_setvalue( GTK_WIDGET(buffertuner_hscale) , 512 ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON(bufsize_spin) , 512 ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON(bufmarginsize_spin) , 15 ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON(bufmargininc_spin) , 18 ); +} + + +void i_configure_gui_tab_fsyn( GtkWidget * fsyn_page_alignment , + gpointer backend_list_p , + gpointer commit_button ) +{ + GtkWidget *fsyn_page_vbox; + GtkWidget *title_widget; + GtkWidget *content_vbox; /* this vbox will contain the various frames for config sections */ + GSList * backend_list = backend_list_p; + gboolean fsyn_module_ok = FALSE; + gchar * fsyn_module_pathfilename; + + fsyn_page_vbox = gtk_vbox_new( FALSE , 0 ); + + title_widget = i_configure_gui_draw_title( _("FLUIDSYNTH BACKEND CONFIGURATION") ); + gtk_box_pack_start( GTK_BOX(fsyn_page_vbox) , title_widget , FALSE , FALSE , 2 ); + + content_vbox = gtk_vbox_new( FALSE , 2 ); + + /* check if the FluidSynth module is available */ + while ( backend_list != NULL ) + { + amidiplug_sequencer_backend_name_t * mn = backend_list->data; + if ( !strcmp( mn->name , "fluidsynth" ) ) + { + fsyn_module_ok = TRUE; + fsyn_module_pathfilename = mn->filename; + break; + } + backend_list = backend_list->next; + } + + if ( fsyn_module_ok ) + { + GtkWidget *soundfont_frame, *soundfont_vbox; + GtkWidget *soundfont_file_label, *soundfont_file_entry, *soundfont_file_bbutton, *soundfont_file_hbox; + GtkWidget *soundfont_load_hsep, *soundfont_load_vbox, *soundfont_load_option[2]; + GtkWidget *synth_frame, *synth_hbox, *synth_leftcol_vbox, *synth_rightcol_vbox; + GtkWidget *synth_samplerate_frame, *synth_samplerate_vbox, *synth_samplerate_option[4]; + GtkWidget *synth_samplerate_optionhbox, *synth_samplerate_optionentry, *synth_samplerate_optionlabel; + GtkWidget *synth_gain_frame, *synth_gain_hbox, *synth_gain_value_hbox; + GtkWidget *synth_gain_value_label, *synth_gain_value_spin, *synth_gain_defcheckbt; + GtkWidget *synth_poly_frame, *synth_poly_hbox, *synth_poly_value_hbox; + GtkWidget *synth_poly_value_label, *synth_poly_value_spin, *synth_poly_defcheckbt; + GtkWidget *synth_reverb_frame, *synth_reverb_hbox, *synth_reverb_value_hbox; + GtkWidget *synth_reverb_value_option[2], *synth_reverb_defcheckbt; + GtkWidget *synth_chorus_frame, *synth_chorus_hbox, *synth_chorus_value_hbox; + GtkWidget *synth_chorus_value_option[2], *synth_chorus_defcheckbt; + GtkWidget *buffer_frame, *buffer_table , *buffer_vsep[4]; + GtkWidget *buffer_tuner_label, *buffer_tuner_hscale; + GtkWidget *buffer_tuner_defbt, *buffer_tuner_defbt_label; + GtkWidget *buffer_bufsize_label, *buffer_bufsize_spin; + GtkWidget *buffer_marginsize_label, *buffer_marginsize_spin; + GtkWidget *buffer_margininc_label, *buffer_margininc_spin; + GtkTooltips *tips; + + amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn; + + tips = gtk_tooltips_new(); + g_object_set_data_full( G_OBJECT(fsyn_page_alignment) , "tt" , tips , g_object_unref ); + + /* soundfont settings */ + soundfont_frame = gtk_frame_new( _("SoundFont settings") ); + soundfont_vbox = gtk_vbox_new( FALSE , 2 ); + gtk_container_set_border_width( GTK_CONTAINER(soundfont_vbox), 4 ); + gtk_container_add( GTK_CONTAINER(soundfont_frame) , soundfont_vbox ); + /* soundfont settings - file */ + soundfont_file_hbox = gtk_hbox_new( FALSE , 2 ); + soundfont_file_label = gtk_label_new( _("SoundFont filename:") ); + soundfont_file_entry = gtk_entry_new(); + g_object_set_data( G_OBJECT(soundfont_file_entry) , "fc-act" , + GINT_TO_POINTER(GTK_FILE_CHOOSER_ACTION_OPEN) ); + gtk_entry_set_text( GTK_ENTRY(soundfont_file_entry) , fsyncfg->fsyn_soundfont_file ); + soundfont_file_bbutton = gtk_button_new_with_label( _("browse") ); + g_signal_connect_swapped( G_OBJECT(soundfont_file_bbutton) , "clicked" , + G_CALLBACK(i_configure_ev_browse_for_entry) , soundfont_file_entry ); + gtk_box_pack_start( GTK_BOX(soundfont_file_hbox) , soundfont_file_label , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(soundfont_file_hbox) , soundfont_file_entry , TRUE , TRUE , 0 ); + gtk_box_pack_start( GTK_BOX(soundfont_file_hbox) , soundfont_file_bbutton , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(soundfont_vbox) , soundfont_file_hbox , FALSE , FALSE , 0 ); + /* soundfont settings - load */ + soundfont_load_hsep = gtk_hseparator_new(); + soundfont_load_vbox = gtk_vbox_new( FALSE , 0 ); + soundfont_load_option[0] = gtk_radio_button_new_with_label( NULL , + _("Load SoundFont on player start") ); + g_object_set_data( G_OBJECT(soundfont_load_option[0]) , "val" , GINT_TO_POINTER(0) ); + soundfont_load_option[1] = gtk_radio_button_new_with_label_from_widget( + GTK_RADIO_BUTTON(soundfont_load_option[0]) , + _("Load SoundFont on first midifile play") ); + g_object_set_data( G_OBJECT(soundfont_load_option[1]) , "val" , GINT_TO_POINTER(1) ); + if ( fsyncfg->fsyn_soundfont_load == 0 ) + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(soundfont_load_option[0]) , TRUE ); + else + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(soundfont_load_option[1]) , TRUE ); + gtk_box_pack_start( GTK_BOX(soundfont_load_vbox) , soundfont_load_option[0] , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(soundfont_load_vbox) , soundfont_load_option[1] , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(soundfont_vbox) , soundfont_load_hsep , FALSE , FALSE , 3 ); + gtk_box_pack_start( GTK_BOX(soundfont_vbox) , soundfont_load_vbox , FALSE , FALSE , 0 ); + + gtk_box_pack_start( GTK_BOX(content_vbox) , soundfont_frame , FALSE , FALSE , 0 ); + + /* synth settings */ + synth_frame = gtk_frame_new( _("Synthesizer settings") ); + synth_hbox = gtk_hbox_new( FALSE , 4 ); + gtk_container_set_border_width( GTK_CONTAINER(synth_hbox), 4 ); + gtk_container_add( GTK_CONTAINER(synth_frame) , synth_hbox ); + synth_leftcol_vbox = gtk_vbox_new( TRUE , 0 ); + synth_rightcol_vbox = gtk_vbox_new( FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(synth_hbox) , synth_leftcol_vbox , TRUE , TRUE , 0 ); + gtk_box_pack_start( GTK_BOX(synth_hbox) , synth_rightcol_vbox , FALSE , FALSE , 0 ); + /* synth settings - gain */ + synth_gain_frame = gtk_frame_new( _("gain") ); + gtk_frame_set_label_align( GTK_FRAME(synth_gain_frame) , 0.5 , 0.5 ); + gtk_box_pack_start( GTK_BOX(synth_leftcol_vbox) , synth_gain_frame , TRUE , TRUE , 0 ); + synth_gain_hbox = gtk_hbox_new( TRUE , 2 ); + gtk_container_set_border_width( GTK_CONTAINER(synth_gain_hbox), 2 ); + gtk_container_add( GTK_CONTAINER(synth_gain_frame) , synth_gain_hbox ); + synth_gain_defcheckbt = gtk_check_button_new_with_label( _("use default") ); + gtk_box_pack_start( GTK_BOX(synth_gain_hbox) , synth_gain_defcheckbt , FALSE , FALSE , 0 ); + synth_gain_value_hbox = gtk_hbox_new( FALSE , 4 ); + synth_gain_value_label = gtk_label_new( _("value:") ); + synth_gain_value_spin = gtk_spin_button_new_with_range( 0.0 , 10.0 , 0.1 ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON(synth_gain_value_spin) , 0.2 ); + g_signal_connect( G_OBJECT(synth_gain_defcheckbt) , "toggled" , + G_CALLBACK(i_configure_ev_toggle_default) , synth_gain_value_hbox ); + if ( fsyncfg->fsyn_synth_gain < 0 ) + { + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_gain_defcheckbt) , TRUE ); + } + else + { + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_gain_defcheckbt) , FALSE ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON(synth_gain_value_spin) , + (gdouble)fsyncfg->fsyn_synth_gain / 10 ); + } + gtk_box_pack_start( GTK_BOX(synth_gain_hbox) , synth_gain_value_hbox , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(synth_gain_value_hbox) , synth_gain_value_label , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(synth_gain_value_hbox) , synth_gain_value_spin , FALSE , FALSE , 0 ); + /* synth settings - poliphony */ + synth_poly_frame = gtk_frame_new( _("poliphony") ); + gtk_frame_set_label_align( GTK_FRAME(synth_poly_frame) , 0.5 , 0.5 ); + gtk_box_pack_start( GTK_BOX(synth_leftcol_vbox) , synth_poly_frame , TRUE , TRUE , 0 ); + synth_poly_hbox = gtk_hbox_new( TRUE , 2 ); + gtk_container_set_border_width( GTK_CONTAINER(synth_poly_hbox), 2 ); + gtk_container_add( GTK_CONTAINER(synth_poly_frame) , synth_poly_hbox ); + synth_poly_defcheckbt = gtk_check_button_new_with_label( _("use default") ); + gtk_box_pack_start( GTK_BOX(synth_poly_hbox) , synth_poly_defcheckbt , FALSE , FALSE , 0 ); + synth_poly_value_hbox = gtk_hbox_new( FALSE , 4 ); + synth_poly_value_label = gtk_label_new( _("value:") ); + synth_poly_value_spin = gtk_spin_button_new_with_range( 16 , 4096 , 1 ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON(synth_poly_value_spin) , 256 ); + g_signal_connect( G_OBJECT(synth_poly_defcheckbt) , "toggled" , + G_CALLBACK(i_configure_ev_toggle_default) , synth_poly_value_hbox ); + if ( fsyncfg->fsyn_synth_poliphony < 0 ) + { + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_poly_defcheckbt) , TRUE ); + } + else + { + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_poly_defcheckbt) , FALSE ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON(synth_poly_value_spin) , + (gdouble)fsyncfg->fsyn_synth_poliphony ); + } + gtk_box_pack_start( GTK_BOX(synth_poly_hbox) , synth_poly_value_hbox , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(synth_poly_value_hbox) , synth_poly_value_label , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(synth_poly_value_hbox) , synth_poly_value_spin , FALSE , FALSE , 0 ); + /* synth settings - reverb */ + synth_reverb_frame = gtk_frame_new( _("reverb") ); + gtk_frame_set_label_align( GTK_FRAME(synth_reverb_frame) , 0.5 , 0.5 ); + gtk_box_pack_start( GTK_BOX(synth_leftcol_vbox) , synth_reverb_frame , TRUE , TRUE , 0 ); + synth_reverb_hbox = gtk_hbox_new( TRUE , 2 ); + gtk_container_set_border_width( GTK_CONTAINER(synth_reverb_hbox), 2 ); + gtk_container_add( GTK_CONTAINER(synth_reverb_frame) , synth_reverb_hbox ); + synth_reverb_defcheckbt = gtk_check_button_new_with_label( _("use default") ); + gtk_box_pack_start( GTK_BOX(synth_reverb_hbox) , synth_reverb_defcheckbt , FALSE , FALSE , 0 ); + synth_reverb_value_hbox = gtk_hbox_new( TRUE , 4 ); + synth_reverb_value_option[0] = gtk_radio_button_new_with_label( NULL , _("yes") ); + synth_reverb_value_option[1] = gtk_radio_button_new_with_label_from_widget( + GTK_RADIO_BUTTON(synth_reverb_value_option[0]) , _("no") ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_reverb_value_option[0]) , TRUE ); + g_signal_connect( G_OBJECT(synth_reverb_defcheckbt) , "toggled" , + G_CALLBACK(i_configure_ev_toggle_default) , synth_reverb_value_hbox ); + if ( fsyncfg->fsyn_synth_reverb < 0 ) + { + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_reverb_defcheckbt) , TRUE ); + } + else + { + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_reverb_defcheckbt) , FALSE ); + if ( fsyncfg->fsyn_synth_reverb == 0 ) + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_reverb_value_option[1]) , TRUE ); + else + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_reverb_value_option[0]) , TRUE ); + } + gtk_box_pack_start( GTK_BOX(synth_reverb_hbox) , synth_reverb_value_hbox , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(synth_reverb_value_hbox) , synth_reverb_value_option[0] , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(synth_reverb_value_hbox) , synth_reverb_value_option[1] , FALSE , FALSE , 0 ); + /* synth settings - chorus */ + synth_chorus_frame = gtk_frame_new( _("chorus") ); + gtk_frame_set_label_align( GTK_FRAME(synth_chorus_frame) , 0.5 , 0.5 ); + gtk_box_pack_start( GTK_BOX(synth_leftcol_vbox) , synth_chorus_frame , TRUE , TRUE , 0 ); + synth_chorus_hbox = gtk_hbox_new( TRUE , 2 ); + gtk_container_set_border_width( GTK_CONTAINER(synth_chorus_hbox), 2 ); + gtk_container_add( GTK_CONTAINER(synth_chorus_frame) , synth_chorus_hbox ); + synth_chorus_defcheckbt = gtk_check_button_new_with_label( _("use default") ); + gtk_box_pack_start( GTK_BOX(synth_chorus_hbox) , synth_chorus_defcheckbt , FALSE , FALSE , 0 ); + synth_chorus_value_hbox = gtk_hbox_new( TRUE , 4 ); + synth_chorus_value_option[0] = gtk_radio_button_new_with_label( NULL , _("yes") ); + synth_chorus_value_option[1] = gtk_radio_button_new_with_label_from_widget( + GTK_RADIO_BUTTON(synth_chorus_value_option[0]) , _("no") ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_chorus_value_option[0]) , TRUE ); + g_signal_connect( G_OBJECT(synth_chorus_defcheckbt) , "toggled" , + G_CALLBACK(i_configure_ev_toggle_default) , synth_chorus_value_hbox ); + if ( fsyncfg->fsyn_synth_chorus < 0 ) + { + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_chorus_defcheckbt) , TRUE ); + } + else + { + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_chorus_defcheckbt) , FALSE ); + if ( fsyncfg->fsyn_synth_chorus == 0 ) + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_chorus_value_option[1]) , TRUE ); + else + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_chorus_value_option[0]) , TRUE ); + } + gtk_box_pack_start( GTK_BOX(synth_chorus_hbox) , synth_chorus_value_hbox , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(synth_chorus_value_hbox) , synth_chorus_value_option[0] , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(synth_chorus_value_hbox) , synth_chorus_value_option[1] , FALSE , FALSE , 0 ); + /* synth settings - samplerate */ + synth_samplerate_frame = gtk_frame_new( _("sample rate") ); + gtk_frame_set_label_align( GTK_FRAME(synth_samplerate_frame) , 0.5 , 0.5 ); + synth_samplerate_vbox = gtk_vbox_new( TRUE , 0 ); + gtk_container_set_border_width( GTK_CONTAINER(synth_samplerate_vbox), 6 ); + gtk_container_add( GTK_CONTAINER(synth_samplerate_frame) , synth_samplerate_vbox ); + gtk_box_pack_start( GTK_BOX(synth_rightcol_vbox) , synth_samplerate_frame , FALSE , FALSE , 0 ); + synth_samplerate_option[0] = gtk_radio_button_new_with_label( NULL , "22050 Hz " ); + g_object_set_data( G_OBJECT(synth_samplerate_option[0]) , "val" , GINT_TO_POINTER(22050) ); + synth_samplerate_option[1] = gtk_radio_button_new_with_label_from_widget( + GTK_RADIO_BUTTON(synth_samplerate_option[0]) , "44100 Hz " ); + g_object_set_data( G_OBJECT(synth_samplerate_option[1]) , "val" , GINT_TO_POINTER(44100) ); + synth_samplerate_option[2] = gtk_radio_button_new_with_label_from_widget( + GTK_RADIO_BUTTON(synth_samplerate_option[0]) , "96000 Hz " ); + g_object_set_data( G_OBJECT(synth_samplerate_option[2]) , "val" , GINT_TO_POINTER(96000) ); + synth_samplerate_option[3] = gtk_radio_button_new_with_label_from_widget( + GTK_RADIO_BUTTON(synth_samplerate_option[0]) , _("custom ") ); + synth_samplerate_optionhbox = gtk_hbox_new( FALSE , 4 ); + synth_samplerate_optionentry = gtk_entry_new(); + gtk_widget_set_sensitive( GTK_WIDGET(synth_samplerate_optionentry) , FALSE ); + gtk_entry_set_width_chars( GTK_ENTRY(synth_samplerate_optionentry) , 8 ); + gtk_entry_set_max_length( GTK_ENTRY(synth_samplerate_optionentry) , 5 ); + g_object_set_data( G_OBJECT(synth_samplerate_option[3]) , "customentry" , synth_samplerate_optionentry ); + g_signal_connect( G_OBJECT(synth_samplerate_option[3]) , "toggled" , + G_CALLBACK(i_configure_ev_sysamplerate_togglecustom) , synth_samplerate_optionentry ); + synth_samplerate_optionlabel = gtk_label_new( "Hz " ); + gtk_box_pack_start( GTK_BOX(synth_samplerate_optionhbox) , synth_samplerate_optionentry , TRUE , TRUE , 0 ); + gtk_box_pack_start( GTK_BOX(synth_samplerate_optionhbox) , synth_samplerate_optionlabel , FALSE , FALSE , 0 ); + switch ( fsyncfg->fsyn_synth_samplerate ) + { + case 22050: + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_samplerate_option[0]) , TRUE ); + break; + case 44100: + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_samplerate_option[1]) , TRUE ); + break; + case 96000: + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_samplerate_option[2]) , TRUE ); + break; + default: + if (( fsyncfg->fsyn_synth_samplerate > 22050 ) && ( fsyncfg->fsyn_synth_samplerate < 96000 )) + { + gchar *samplerate_value = g_strdup_printf( "%i" , fsyncfg->fsyn_synth_samplerate ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_samplerate_option[3]) , TRUE ); + gtk_entry_set_text( GTK_ENTRY(synth_samplerate_optionentry) , samplerate_value ); + g_free( samplerate_value ); + } + else + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(synth_samplerate_option[1]) , TRUE ); + } + gtk_box_pack_start( GTK_BOX(synth_samplerate_vbox) , synth_samplerate_option[0] , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(synth_samplerate_vbox) , synth_samplerate_option[1] , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(synth_samplerate_vbox) , synth_samplerate_option[2] , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(synth_samplerate_vbox) , synth_samplerate_option[3] , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(synth_samplerate_vbox) , synth_samplerate_optionhbox , FALSE , FALSE , 0 ); + + gtk_box_pack_start( GTK_BOX(content_vbox) , synth_frame , TRUE , TRUE , 0 ); + + /* buffer settings */ + buffer_frame = gtk_frame_new( _("Buffer settings") ); + buffer_table = gtk_table_new( 2 , 9 , FALSE ); + gtk_table_set_col_spacings( GTK_TABLE(buffer_table) , 2 ); + gtk_container_set_border_width( GTK_CONTAINER(buffer_table), 4 ); + gtk_container_add( GTK_CONTAINER(buffer_frame) , buffer_table ); + /* buffer settings - slider */ + buffer_tuner_defbt = gtk_button_new(); + buffer_tuner_defbt_label = gtk_label_new( "" ); + gtk_label_set_markup( GTK_LABEL(buffer_tuner_defbt_label) , + _("<span size=\"smaller\">def</span>") ); + gtk_container_add( GTK_CONTAINER(buffer_tuner_defbt) , buffer_tuner_defbt_label ); + gtk_table_attach( GTK_TABLE(buffer_table) , buffer_tuner_defbt , 0 , 1 , 0 , 2 , + 0 , GTK_FILL , 2 , 0 ); + buffer_vsep[0] = gtk_vseparator_new(); + gtk_table_attach( GTK_TABLE(buffer_table) , buffer_vsep[0] , 1 , 2 , 0 , 2 , + 0 , GTK_FILL , 0 , 0 ); + buffer_tuner_label = gtk_label_new( "" ); + gtk_label_set_markup( GTK_LABEL(buffer_tuner_label) , + _("<span size=\"smaller\">handy buffer tuner</span>") ); + buffer_tuner_hscale = gtk_hscale_new_with_range( 0 , 53 , 1 ); + gtk_scale_set_draw_value( GTK_SCALE(buffer_tuner_hscale) , FALSE ); + i_configure_buffertuner_setvalue( buffer_tuner_hscale , fsyncfg->fsyn_buffer_size ); + gtk_table_attach( GTK_TABLE(buffer_table) , buffer_tuner_label , 2 , 3 , 0 , 1 , + GTK_EXPAND | GTK_FILL , GTK_EXPAND | GTK_FILL , 0 , 0 ); + gtk_table_attach( GTK_TABLE(buffer_table) , buffer_tuner_hscale , 2 , 3 , 1 , 2 , + GTK_EXPAND | GTK_FILL , GTK_EXPAND | GTK_FILL , 0 , 0 ); + buffer_vsep[1] = gtk_vseparator_new(); + gtk_table_attach( GTK_TABLE(buffer_table) , buffer_vsep[1] , 3 , 4 , 0 , 2 , + 0 , GTK_FILL , 0 , 0 ); + /* buffer settings - size */ + buffer_bufsize_label = gtk_label_new( "" ); + gtk_label_set_markup( GTK_LABEL(buffer_bufsize_label) , + _("<span size=\"smaller\">size</span>") ); + buffer_bufsize_spin = gtk_spin_button_new_with_range( 100 , 99999 , 20 ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON(buffer_bufsize_spin) , + (gdouble)fsyncfg->fsyn_buffer_size ); + gtk_table_attach( GTK_TABLE(buffer_table) , buffer_bufsize_label , 4 , 5 , 0 , 1 , + GTK_FILL , 0 , 1 , 1 ); + gtk_table_attach( GTK_TABLE(buffer_table) , buffer_bufsize_spin , 4 , 5 , 1 , 2 , + 0 , 0 , 1 , 1 ); + buffer_vsep[2] = gtk_vseparator_new(); + gtk_table_attach( GTK_TABLE(buffer_table) , buffer_vsep[2] , 5 , 6 , 0 , 2 , + 0 , GTK_FILL , 0 , 0 ); + /* buffer settings - margin */ + buffer_marginsize_label = gtk_label_new( "" ); + gtk_label_set_markup( GTK_LABEL(buffer_marginsize_label) , + _("<span size=\"smaller\">margin</span>") ); + buffer_marginsize_spin = gtk_spin_button_new_with_range( 0 , 100 , 1 ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON(buffer_marginsize_spin) , + (gdouble)fsyncfg->fsyn_buffer_margin ); + gtk_table_attach( GTK_TABLE(buffer_table) , buffer_marginsize_label , 6 , 7 , 0 , 1 , + GTK_FILL , 0 , 1 , 1 ); + gtk_table_attach( GTK_TABLE(buffer_table) , buffer_marginsize_spin , 6 , 7 , 1 , 2 , + 0 , 0 , 1 , 1 ); + buffer_vsep[3] = gtk_vseparator_new(); + gtk_table_attach( GTK_TABLE(buffer_table) , buffer_vsep[3] , 7 , 8 , 0 , 2 , + 0 , GTK_FILL , 0 , 0 ); + /* buffer settings - increment */ + buffer_margininc_label = gtk_label_new( "" ); + gtk_label_set_markup( GTK_LABEL(buffer_margininc_label) , + _("<span size=\"smaller\">increment</span>") ); + buffer_margininc_spin = gtk_spin_button_new_with_range( 6 , 1000 , 1 ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON(buffer_margininc_spin) , + (gdouble)fsyncfg->fsyn_buffer_increment ); + gtk_table_attach( GTK_TABLE(buffer_table) , buffer_margininc_label , 8 , 9 , 0 , 1 , + GTK_FILL , 0 , 1 , 1 ); + gtk_table_attach( GTK_TABLE(buffer_table) , buffer_margininc_spin , 8 , 9 , 1 , 2 , + 0 , 0 , 1 , 1 ); + + g_object_set_data( G_OBJECT(buffer_tuner_hscale) , "bufsize_spin" , buffer_bufsize_spin ); + g_object_set_data( G_OBJECT(buffer_tuner_hscale) , "bufmarginsize_spin" , buffer_marginsize_spin ); + g_object_set_data( G_OBJECT(buffer_tuner_hscale) , "bufmargininc_spin" , buffer_margininc_spin ); + g_signal_connect_swapped( G_OBJECT(buffer_tuner_defbt) , "clicked" , + G_CALLBACK(i_configure_ev_buffertuner_default) , buffer_tuner_hscale ); + g_signal_connect( G_OBJECT(buffer_tuner_hscale) , "value-changed" , + G_CALLBACK(i_configure_ev_buffertuner_valuechanged) , NULL ); + + gtk_box_pack_start( GTK_BOX(content_vbox) , buffer_frame , FALSE , FALSE , 0 ); + + /* commit events */ + g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" , + G_CALLBACK(i_configure_ev_sffile_commit) , soundfont_file_entry ); + g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" , + G_CALLBACK(i_configure_ev_sfload_commit) , soundfont_load_option[0] ); + g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" , + G_CALLBACK(i_configure_ev_sygain_commit) , synth_gain_value_spin ); + g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" , + G_CALLBACK(i_configure_ev_sypoly_commit) , synth_poly_value_spin ); + g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" , + G_CALLBACK(i_configure_ev_syreverb_commit) , synth_reverb_value_option[0] ); + g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" , + G_CALLBACK(i_configure_ev_sychorus_commit) , synth_chorus_value_option[0] ); + g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" , + G_CALLBACK(i_configure_ev_sysamplerate_commit) , synth_samplerate_option[3] ); + g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" , + G_CALLBACK(i_configure_ev_bufsize_commit) , buffer_bufsize_spin ); + g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" , + G_CALLBACK(i_configure_ev_bufmarginsize_commit) , buffer_marginsize_spin ); + g_signal_connect_swapped( G_OBJECT(commit_button) , "clicked" , + G_CALLBACK(i_configure_ev_bufmargininc_commit) , buffer_margininc_spin ); + + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , soundfont_file_entry , + _("* Select SoundFont *\n" + "In order to play MIDI with FluidSynth, you need to specify a " + "valid SoundFont file here (use absolute paths).") , "" ); + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , soundfont_load_option[0] , + _("* Load SoundFont on player start *\n" + "Depending on your system speed, SoundFont loading in FluidSynth will " + "require up to a few seconds. This is a one-time task (the soundfont " + "will stay loaded until it is changed or the backend is unloaded) that " + "can be done at player start, or before the first MIDI file is played " + "(the latter is a better choice if you don't use your player to listen " + "MIDI files only).") , "" ); + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , soundfont_load_option[1] , + _("* Load SoundFont on first midifile play *\n" + "Depending on your system speed, SoundFont loading in FluidSynth will " + "require up to a few seconds. This is a one-time task (the soundfont " + "will stay loaded until it is changed or the backend is unloaded) that " + "can be done at player start, or before the first MIDI file is played " + "(the latter is a better choice if you don't use your player to listen " + "MIDI files only).") , "" ); + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , synth_gain_value_spin , + _("* Synthesizer gain *\n" + "From FluidSynth docs: the gain is applied to the final or master output " + "of the synthesizer; it is set to a low value by default to avoid the " + "saturation of the output when random MIDI files are played.") , "" ); + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , synth_poly_value_spin , + _("* Synthesizer polyphony *\n" + "From FluidSynth docs: the polyphony defines how many voices can be played " + "in parallel; the number of voices is not necessarily equivalent to the " + "number of notes played simultaneously; indeed, when a note is struck on a " + "specific MIDI channel, the preset on that channel may create several voices, " + "for example, one for the left audio channel and one for the right audio " + "channels; the number of voices activated depends on the number of instrument " + "zones that fall in the correspond to the velocity and key of the played " + "note.") , "" ); + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , synth_reverb_value_option[0] , + _("* Synthesizer reverb *\n" + "From FluidSynth docs: when set to \"yes\" the reverb effects module is " + "activated; note that when the reverb module is active, the amount of " + "signal sent to the reverb module depends on the \"reverb send\" generator " + "defined in the SoundFont.") , "" ); + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , synth_reverb_value_option[1] , + _("* Synthesizer reverb *\n" + "From FluidSynth docs: when set to \"yes\" the reverb effects module is " + "activated; note that when the reverb module is active, the amount of " + "signal sent to the reverb module depends on the \"reverb send\" generator " + "defined in the SoundFont.") , "" ); + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , synth_chorus_value_option[0] , + _("* Synthesizer chorus *\n" + "From FluidSynth docs: when set to \"yes\" the chorus effects module is " + "activated; note that when the chorus module is active, the amount of " + "signal sent to the chorus module depends on the \"chorus send\" generator " + "defined in the SoundFont.") , "" ); + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , synth_chorus_value_option[1] , + _("* Synthesizer chorus *\n" + "From FluidSynth docs: when set to \"yes\" the chorus effects module is " + "activated; note that when the chorus module is active, the amount of " + "signal sent to the chorus module depends on the \"chorus send\" generator " + "defined in the SoundFont.") , "" ); + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , synth_samplerate_option[0] , + _("* Synthesizer samplerate *\n" + "The sample rate of the audio generated by the synthesizer. You can also specify " + "a custom value in the interval 22050Hz-96000Hz.\n" + "NOTE: the default buffer parameters are tuned for 44100Hz; changing the sample " + "rate may require buffer params tuning to obtain good sound quality.") , "" ); + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , synth_samplerate_option[1] , + _("* Synthesizer samplerate *\n" + "The sample rate of the audio generated by the synthesizer. You can also specify " + "a custom value in the interval 22050Hz-96000Hz.\n" + "NOTE: the default buffer parameters are tuned for 44100Hz; changing the sample " + "rate may require buffer params tuning to obtain good sound quality.") , "" ); + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , synth_samplerate_option[2] , + _("* Synthesizer samplerate *\n" + "The sample rate of the audio generated by the synthesizer. You can also specify " + "a custom value in the interval 22050Hz-96000Hz.\n" + "NOTE: the default buffer parameters are tuned for 44100Hz; changing the sample " + "rate may require buffer params tuning to obtain good sound quality.") , "" ); + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , synth_samplerate_option[3] , + _("* Synthesizer samplerate *\n" + "The sample rate of the audio generated by the synthesizer. You can also specify " + "a custom value in the interval 22050Hz-96000Hz.\n" + "NOTE: the default buffer parameters are tuned for 44100Hz; changing the sample " + "rate may require buffer params tuning to obtain good sound quality.") , "" ); + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , buffer_tuner_defbt , + _("* FluidSynth backend buffer *\n" + "This button resets the backend buffer parameters to default values.") , "" ); + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , buffer_tuner_hscale , + _("* FluidSynth backend buffer *\n" + "If you notice skips during song playback and your system is not performing " + "any cpu-intensive task (except FluidSynth itself), you may want to tune the " + "buffer in order to prevent skipping. Try to move the \"handy buffer tuner\" " + "a single step to the right until playback is fluid again.") , "" ); + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , buffer_bufsize_spin , + _("* FluidSynth backend buffer *\n" + "It is a good idea to make buffer adjustments with the \"handy buffer tuner\" " + "before resorting to manual editing of buffer parameters.\n" + "However, if you want to fine-tune something and want to know what you're doing, " + "you can understand how these parameters work by reading the backend code " + "(b-fluidsynth.c). In short words, every amount of time " + "(proportional to buffer_SIZE and sample rate), right before gathering samples, " + "the buffer is resized as follows:\n" + "buffer_SIZE + buffer_MARGIN + extramargin\nwhere extramargin is a value " + "computed as number_of_seconds_of_playback / margin_INCREMENT .") , "" ); + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , buffer_marginsize_spin , + _("* FluidSynth backend buffer *\n" + "It is a good idea to make buffer adjustments with the \"handy buffer tuner\" " + "before resorting to manual editing of buffer parameters.\n" + "However, if you want to fine-tune something and want to know what you're doing, " + "you can understand how these parameters work by reading the backend code " + "(b-fluidsynth.c). In short words, every amount of time " + "(proportional to buffer_SIZE and sample rate), right before gathering samples, " + "the buffer is resized as follows:\n" + "buffer_SIZE + buffer_MARGIN + extramargin\nwhere extramargin is a value " + "computed as number_of_seconds_of_playback / margin_INCREMENT .") , "" ); + gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , buffer_margininc_spin , + _("* FluidSynth backend buffer *\n" + "It is a good idea to make buffer adjustments with the \"handy buffer tuner\" " + "before resorting to manual editing of buffer parameters.\n" + "However, if you want to fine-tune something and want to know what you're doing, " + "you can understand how these parameters work by reading the backend code " + "(b-fluidsynth.c). In short words, every amount of time " + "(proportional to buffer_SIZE and sample rate), right before gathering samples, " + "the buffer is resized as follows:\n" + "buffer_SIZE + buffer_MARGIN + extramargin\nwhere extramargin is a value " + "computed as number_of_seconds_of_playback / margin_INCREMENT .") , "" ); + } + else + { + /* display "not available" information */ + GtkWidget * info_label; + info_label = gtk_label_new( _("FluidSynth Backend not loaded or not available") ); + gtk_box_pack_start( GTK_BOX(fsyn_page_vbox) , info_label , FALSE , FALSE , 2 ); + } + + gtk_box_pack_start( GTK_BOX(fsyn_page_vbox) , content_vbox , TRUE , TRUE , 2 ); + gtk_container_add( GTK_CONTAINER(fsyn_page_alignment) , fsyn_page_vbox ); +} + + +void i_configure_gui_tablabel_fsyn( GtkWidget * fsyn_page_alignment , + gpointer backend_list_p , + gpointer commit_button ) +{ + GtkWidget *pagelabel_vbox, *pagelabel_image, *pagelabel_label; + GdkPixbuf *pagelabel_image_pix; + pagelabel_vbox = gtk_vbox_new( FALSE , 1 ); + pagelabel_image_pix = gdk_pixbuf_new_from_xpm_data( (const gchar **)backend_fluidsynth_icon_xpm ); + pagelabel_image = gtk_image_new_from_pixbuf( pagelabel_image_pix ); g_object_unref( pagelabel_image_pix ); + pagelabel_label = gtk_label_new( "" ); + gtk_label_set_markup( GTK_LABEL(pagelabel_label) , "<span size=\"smaller\">FluidSynth\nbackend</span>" ); + gtk_label_set_justify( GTK_LABEL(pagelabel_label) , GTK_JUSTIFY_CENTER ); + gtk_box_pack_start( GTK_BOX(pagelabel_vbox) , pagelabel_image , FALSE , FALSE , 1 ); + gtk_box_pack_start( GTK_BOX(pagelabel_vbox) , pagelabel_label , FALSE , FALSE , 1 ); + gtk_container_add( GTK_CONTAINER(fsyn_page_alignment) , pagelabel_vbox ); + gtk_widget_show_all( fsyn_page_alignment ); + return; +} + + +void i_configure_cfg_fsyn_alloc( void ) +{ + amidiplug_cfg_fsyn_t * fsyncfg = g_malloc(sizeof(amidiplug_cfg_fsyn_t)); + amidiplug_cfg_backend->fsyn = fsyncfg; +} + + +void i_configure_cfg_fsyn_free( void ) +{ + amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn; + g_free( fsyncfg->fsyn_soundfont_file ); +} + + +void i_configure_cfg_fsyn_read( pcfg_t * cfgfile ) +{ + amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn; + + if (!cfgfile) + { + /* fluidsynth backend defaults */ + fsyncfg->fsyn_soundfont_file = g_strdup( "" ); + fsyncfg->fsyn_soundfont_load = 1; + fsyncfg->fsyn_synth_samplerate = 44100; + fsyncfg->fsyn_synth_gain = -1; + fsyncfg->fsyn_synth_poliphony = -1; + fsyncfg->fsyn_synth_reverb = -1; + fsyncfg->fsyn_synth_chorus = -1; + fsyncfg->fsyn_buffer_size = 512; + fsyncfg->fsyn_buffer_margin = 10; + fsyncfg->fsyn_buffer_increment = 18; + } + else + { + i_pcfg_read_string( cfgfile , "fsyn" , "fsyn_soundfont_file" , &fsyncfg->fsyn_soundfont_file , "" ); + i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_soundfont_load" , &fsyncfg->fsyn_soundfont_load , 1 ); + i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_synth_samplerate" , &fsyncfg->fsyn_synth_samplerate , 44100 ); + i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_synth_gain" , &fsyncfg->fsyn_synth_gain , -1 ); + i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_synth_poliphony" , &fsyncfg->fsyn_synth_poliphony , -1 ); + i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_synth_reverb" , &fsyncfg->fsyn_synth_reverb , -1 ); + i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_synth_chorus" , &fsyncfg->fsyn_synth_chorus , -1 ); + i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_buffer_size" , &fsyncfg->fsyn_buffer_size , 512 ); + i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_buffer_margin" , &fsyncfg->fsyn_buffer_margin , 15 ); + i_pcfg_read_integer( cfgfile , "fsyn" , "fsyn_buffer_increment" , &fsyncfg->fsyn_buffer_increment , 18 ); + } +} + + +void i_configure_cfg_fsyn_save( pcfg_t * cfgfile ) +{ + amidiplug_cfg_fsyn_t * fsyncfg = amidiplug_cfg_backend->fsyn; + + i_pcfg_write_string( cfgfile , "fsyn" , "fsyn_soundfont_file" , fsyncfg->fsyn_soundfont_file ); + i_pcfg_write_integer( cfgfile , "fsyn" , "fsyn_soundfont_load" , fsyncfg->fsyn_soundfont_load ); + i_pcfg_write_integer( cfgfile , "fsyn" , "fsyn_synth_samplerate" , fsyncfg->fsyn_synth_samplerate ); + i_pcfg_write_integer( cfgfile , "fsyn" , "fsyn_synth_gain" , fsyncfg->fsyn_synth_gain ); + i_pcfg_write_integer( cfgfile , "fsyn" , "fsyn_synth_poliphony" , fsyncfg->fsyn_synth_poliphony ); + i_pcfg_write_integer( cfgfile , "fsyn" , "fsyn_synth_reverb" , fsyncfg->fsyn_synth_reverb ); + i_pcfg_write_integer( cfgfile , "fsyn" , "fsyn_synth_chorus" , fsyncfg->fsyn_synth_chorus ); + i_pcfg_write_integer( cfgfile , "fsyn" , "fsyn_buffer_size" , fsyncfg->fsyn_buffer_size ); + i_pcfg_write_integer( cfgfile , "fsyn" , "fsyn_buffer_margin" , fsyncfg->fsyn_buffer_margin ); + i_pcfg_write_integer( cfgfile , "fsyn" , "fsyn_buffer_increment" , fsyncfg->fsyn_buffer_increment ); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/i_configure-fluidsynth.h Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,36 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#ifndef _I_CONFIGURE_FLUIDSYNTH_H +#define _I_CONFIGURE_FLUIDSYNTH_H 1 + +#include "i_configure_private.h" + + +extern amidiplug_cfg_backend_t * amidiplug_cfg_backend; + +void i_configure_gui_tab_fsyn( GtkWidget * , gpointer , gpointer ); +void i_configure_gui_tablabel_fsyn( GtkWidget * , gpointer , gpointer ); +void i_configure_cfg_fsyn_alloc( void ); +void i_configure_cfg_fsyn_free( void ); +void i_configure_cfg_fsyn_read( pcfg_t * ); +void i_configure_cfg_fsyn_save( pcfg_t * ); + +#endif /* !_I_CONFIGURE_FLUIDSYNTH_H */
--- a/Plugins/Input/amidi-plug/i_configure.c Mon Jul 10 04:42:53 2006 -0700 +++ b/Plugins/Input/amidi-plug/i_configure.c Mon Jul 10 04:52:51 2006 -0700 @@ -20,189 +20,158 @@ #include "i_configure.h" +#include "i_configure_private.h" +#include "i_backend.h" +#include "i_configure-ap.h" +#include "i_configure-alsa.h" +#include "i_configure-fluidsynth.h" +#include "i_configure-dummy.h" +#include "i_utils.h" +#include "libaudacious/beepctrl.h" -/* internals */ -void i_configure_upd_portlist( void ); -void i_configure_upd_mixercardlist( void ); -gchar * i_configure_read_seq_ports_default( void ); -gboolean i_configure_ev_checktoggle( GtkTreeModel * , GtkTreePath * , GtkTreeIter * , gpointer ); -void i_configure_ev_changetoggle( GtkCellRendererToggle * , gchar * , gpointer ); + +amidiplug_cfg_backend_t * amidiplug_cfg_backend; + + +void i_configure_ev_bcancel( gpointer ); +void i_configure_ev_bok( gpointer ); +void i_configure_cfg_backend_alloc( void ); +void i_configure_cfg_backend_free( void ); +void i_configure_cfg_backend_save( void ); +void i_configure_cfg_backend_read( void ); +void i_configure_cfg_ap_save( void ); +void i_configure_cfg_ap_read( void ); + + +GtkWidget * i_configure_gui_draw_title( gchar * title_string ) +{ + GtkWidget *title_label, *title_evbox, *title_frame; + GtkStyle * style = gtk_widget_get_default_style(); + GdkColor title_fgcol = style->fg[GTK_STATE_SELECTED]; + GdkColor title_bgcol = style->bg[GTK_STATE_SELECTED]; + title_label = gtk_label_new( title_string ); + title_evbox = gtk_event_box_new(); + title_frame = gtk_frame_new( NULL ); + gtk_frame_set_shadow_type( GTK_FRAME(title_frame) , GTK_SHADOW_OUT ); + gtk_container_add( GTK_CONTAINER(title_evbox) , title_label ); + gtk_container_set_border_width( GTK_CONTAINER(title_evbox) , 5 ); + gtk_container_add( GTK_CONTAINER(title_frame) , title_evbox ); + gtk_widget_modify_fg( GTK_WIDGET(title_label) , GTK_STATE_NORMAL , &title_fgcol ); + gtk_widget_modify_bg( GTK_WIDGET(title_evbox) , GTK_STATE_NORMAL , &title_bgcol ); + return title_frame; +} -void i_configure_gui( GSList * wports , GSList * scards ) +void i_configure_ev_browse_for_entry( GtkWidget * target_entry ) { - GtkWidget *configwin_vbox; - GtkWidget *port_lv, *port_lv_sw, *port_frame; - GtkWidget *mixer_card_cmb_evbox, *mixer_card_cmb, *mixer_vbox, *mixer_frame; - GtkWidget *advanced_precalc_checkbt, *advanced_vbox, *advanced_frame; - GtkWidget *hseparator, *hbuttonbox, *button_ok, *button_cancel; - GtkListStore *port_liststore, *mixer_card_liststore; - GtkTreeIter iter; - GtkTreeSelection *port_lv_sel; - GtkCellRenderer *port_lv_toggle_rndr, *port_lv_text_rndr, *mixer_card_cmb_text_rndr; - GtkTreeViewColumn *port_lv_toggle_col, *port_lv_portnum_col; - GtkTreeViewColumn *port_lv_clientname_col, *port_lv_portname_col; - gchar **portstring_from_cfg = NULL; - - if ( amidiplug_gui_prefs.config_win ) - return; - - if ( strlen( amidiplug_cfg.seq_writable_ports ) > 0 ) - portstring_from_cfg = g_strsplit( amidiplug_cfg.seq_writable_ports , "," , 0 ); - - amidiplug_gui_prefs.config_win = gtk_window_new( GTK_WINDOW_TOPLEVEL ); - gtk_window_set_type_hint( GTK_WINDOW(amidiplug_gui_prefs.config_win), GDK_WINDOW_TYPE_HINT_DIALOG ); - gtk_window_set_title( GTK_WINDOW(amidiplug_gui_prefs.config_win), _("AMIDI-Plug - configuration") ); - gtk_container_set_border_width( GTK_CONTAINER(amidiplug_gui_prefs.config_win), 10 ); - g_signal_connect( G_OBJECT(amidiplug_gui_prefs.config_win) , - "destroy" , G_CALLBACK(i_configure_ev_destroy) , NULL ); - - configwin_vbox = gtk_vbox_new( FALSE , 0 ); - gtk_container_add( GTK_CONTAINER(amidiplug_gui_prefs.config_win) , configwin_vbox ); - - port_liststore = gtk_list_store_new( LISTPORT_N_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_STRING , - G_TYPE_STRING , G_TYPE_STRING , G_TYPE_POINTER ); + GtkWidget *parent_window = gtk_widget_get_toplevel( target_entry ); + GtkFileChooserAction act = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(target_entry),"fc-act")); + if ( GTK_WIDGET_TOPLEVEL(parent_window) ) + { + GtkWidget *browse_dialog = gtk_file_chooser_dialog_new( _("AMIDI-Plug - select file") , + GTK_WINDOW(parent_window) , act , + GTK_STOCK_CANCEL , GTK_RESPONSE_CANCEL , + GTK_STOCK_OPEN , GTK_RESPONSE_ACCEPT , NULL ); + if ( strcmp( gtk_entry_get_text(GTK_ENTRY(target_entry)) , "" ) ) + gtk_file_chooser_set_filename( GTK_FILE_CHOOSER(browse_dialog) , + gtk_entry_get_text(GTK_ENTRY(target_entry)) ); + if ( gtk_dialog_run(GTK_DIALOG(browse_dialog)) == GTK_RESPONSE_ACCEPT ) + { + gchar *filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(browse_dialog) ); + gtk_entry_set_text( GTK_ENTRY(target_entry) , filename ); + DEBUGMSG( "selected file: %s\n" , filename ); + g_free( filename ); + } + gtk_widget_destroy( browse_dialog ); + } +} - /* append ALSA MIDI ports */ - while ( wports != NULL ) - { - gint i = 0; - gboolean toggled = FALSE; - data_bucket_t * portinfo = (data_bucket_t *)wports->data; - GString * portstring = g_string_new(""); - G_STRING_PRINTF( portstring , "%i:%i" , - portinfo->bint[0] , portinfo->bint[1] ); - gtk_list_store_append( port_liststore , &iter ); + +void i_configure_gui( void ) +{ + static GtkWidget *configwin = NULL; + GdkGeometry cw_hints; + GtkWidget *configwin_vbox; + GtkWidget *hseparator, *hbuttonbox, *button_ok, *button_cancel; + + GtkWidget *configwin_notebook; - /* in the existing configuration there may be previously selected ports */ - if ( portstring_from_cfg ) - { - /* check if current row contains a port selected by user */ - for ( i = 0 ; portstring_from_cfg[i] != NULL ; i++ ) - { - /* if it's one of the selected ports, toggle its checkbox */ - if ( !strcmp( portstring->str, portstring_from_cfg[i] ) ) - toggled = TRUE; - } - } + GtkWidget *ap_page_alignment, *ap_pagelabel_alignment; /* amidi-plug */ + GtkWidget *alsa_page_alignment, *alsa_pagelabel_alignment; /* alsa */ + GtkWidget *dumm_page_alignment, *dumm_pagelabel_alignment; /* dummy */ + GtkWidget *fsyn_page_alignment, *fsyn_pagelabel_alignment; /* fluidsynth */ - gtk_list_store_set( port_liststore , &iter , - LISTPORT_TOGGLE_COLUMN , toggled , - LISTPORT_PORTNUM_COLUMN , portstring->str , - LISTPORT_CLIENTNAME_COLUMN , portinfo->bcharp[0] , - LISTPORT_PORTNAME_COLUMN , portinfo->bcharp[1] , - LISTPORT_POINTER_COLUMN , portinfo , -1 ); + GSList *backend_list = NULL, *backend_list_h = NULL; - g_string_free( portstring , TRUE ); - /* on with next */ - wports = wports->next; + if ( configwin != NULL ) + { + DEBUGMSG( "config window is already open!\n" ); + return; } - /* this string array is not needed anymore */ - g_strfreev( portstring_from_cfg ); + /* get configuration information for backends */ + i_configure_cfg_backend_alloc(); + i_configure_cfg_backend_read(); - port_lv = gtk_tree_view_new_with_model( GTK_TREE_MODEL(port_liststore) ); - amidiplug_gui_prefs.port_treeview = port_lv; - g_object_unref( port_liststore ); - port_lv_toggle_rndr = gtk_cell_renderer_toggle_new(); - gtk_cell_renderer_toggle_set_radio( GTK_CELL_RENDERER_TOGGLE(port_lv_toggle_rndr) , FALSE ); - gtk_cell_renderer_toggle_set_active( GTK_CELL_RENDERER_TOGGLE(port_lv_toggle_rndr) , TRUE ); - g_signal_connect( port_lv_toggle_rndr , "toggled" , - G_CALLBACK(i_configure_ev_changetoggle) , port_liststore ); - port_lv_text_rndr = gtk_cell_renderer_text_new(); - port_lv_toggle_col = gtk_tree_view_column_new_with_attributes( "", port_lv_toggle_rndr, - "active", LISTPORT_TOGGLE_COLUMN, NULL ); - port_lv_portnum_col = gtk_tree_view_column_new_with_attributes( _("Port"), port_lv_text_rndr, - "text", LISTPORT_PORTNUM_COLUMN, NULL ); - port_lv_clientname_col = gtk_tree_view_column_new_with_attributes( _("Client name"), port_lv_text_rndr, - "text", LISTPORT_CLIENTNAME_COLUMN, NULL ); - port_lv_portname_col = gtk_tree_view_column_new_with_attributes( _("Port name"), port_lv_text_rndr, - "text", LISTPORT_PORTNAME_COLUMN, NULL ); - gtk_tree_view_append_column( GTK_TREE_VIEW(port_lv), port_lv_toggle_col ); - gtk_tree_view_append_column( GTK_TREE_VIEW(port_lv), port_lv_portnum_col ); - gtk_tree_view_append_column( GTK_TREE_VIEW(port_lv), port_lv_clientname_col ); - gtk_tree_view_append_column( GTK_TREE_VIEW(port_lv), port_lv_portname_col ); + configwin = gtk_window_new( GTK_WINDOW_TOPLEVEL ); + gtk_window_set_type_hint( GTK_WINDOW(configwin), GDK_WINDOW_TYPE_HINT_DIALOG ); + gtk_window_set_title( GTK_WINDOW(configwin), _("AMIDI-Plug - configuration") ); + gtk_container_set_border_width( GTK_CONTAINER(configwin), 10 ); + g_signal_connect( G_OBJECT(configwin) , "destroy" , + G_CALLBACK(gtk_widget_destroyed) , &configwin ); + button_ok = gtk_button_new_from_stock( GTK_STOCK_OK ); + cw_hints.min_width = 480; cw_hints.min_height = -1; + gtk_window_set_geometry_hints( GTK_WINDOW(configwin) , GTK_WIDGET(configwin) , + &cw_hints , GDK_HINT_MIN_SIZE ); - port_lv_sel = gtk_tree_view_get_selection( GTK_TREE_VIEW(port_lv) ); - gtk_tree_selection_set_mode( GTK_TREE_SELECTION(port_lv_sel) , GTK_SELECTION_SINGLE ); + configwin_vbox = gtk_vbox_new( FALSE , 0 ); + gtk_container_add( GTK_CONTAINER(configwin) , configwin_vbox ); - port_lv_sw = gtk_scrolled_window_new( NULL , NULL ); - gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(port_lv_sw), - GTK_POLICY_NEVER, GTK_POLICY_NEVER ); - port_frame = gtk_frame_new( _("ALSA output ports") ); + configwin_notebook = gtk_notebook_new(); + gtk_notebook_set_tab_pos( GTK_NOTEBOOK(configwin_notebook) , GTK_POS_LEFT ); + gtk_box_pack_start( GTK_BOX(configwin_vbox) , configwin_notebook , TRUE , TRUE , 2 ); - gtk_container_add( GTK_CONTAINER(port_lv_sw) , port_lv ); - gtk_container_set_border_width( GTK_CONTAINER(port_lv_sw) , 5 ); - gtk_container_add( GTK_CONTAINER(port_frame) , port_lv_sw ); - gtk_box_pack_start( GTK_BOX(configwin_vbox) , port_frame , TRUE , TRUE , 2 ); + /* GET A LIST OF BACKENDS */ + backend_list = i_backend_list_lookup(); /* get a list of available backends */; + backend_list_h = backend_list; - /**********************/ - /*** MIXER SETTINGS ***/ - mixer_card_liststore = gtk_list_store_new( LISTMIXER_N_COLUMNS , G_TYPE_STRING , G_TYPE_INT , - G_TYPE_INT , G_TYPE_STRING ); - mixer_card_cmb = gtk_combo_box_new_with_model( GTK_TREE_MODEL(mixer_card_liststore) ); - amidiplug_gui_prefs.mixercard_combo = mixer_card_cmb; - /* fill models with sound cards and relative mixer controls */ - while ( scards != NULL ) - { - data_bucket_t * cardinfo = (data_bucket_t *)scards->data; - GString * desc_cardmix_string = g_string_new( "" ); - GSList * mixctl_list = cardinfo->bpointer[0]; - while ( mixctl_list != NULL ) - { - data_bucket_t * mixctlinfo = (data_bucket_t *)mixctl_list->data; - G_STRING_PRINTF( desc_cardmix_string , "%s - ctl: %s (ID %i)" , cardinfo->bcharp[0] , - mixctlinfo->bcharp[0] , mixctlinfo->bint[0] ); - gtk_list_store_append( mixer_card_liststore , &iter ); - gtk_list_store_set( mixer_card_liststore , &iter , - LISTMIXER_DESC_COLUMN , desc_cardmix_string->str , - LISTMIXER_CARDID_COLUMN , cardinfo->bint[0] , - LISTMIXER_MIXCTLID_COLUMN , mixctlinfo->bint[0] , - LISTMIXER_MIXCTLNAME_COLUMN , mixctlinfo->bcharp[0] , -1 ); - /* check if this corresponds to the value previously selected by user */ - if ( ( cardinfo->bint[0] == amidiplug_cfg.mixer_card_id ) && - ( !strcasecmp( mixctlinfo->bcharp[0] , amidiplug_cfg.mixer_control_name ) ) && - ( mixctlinfo->bint[0] == amidiplug_cfg.mixer_control_id ) ) - gtk_combo_box_set_active_iter( GTK_COMBO_BOX(mixer_card_cmb) , &iter ); - mixctl_list = mixctl_list->next; - } - g_string_free( desc_cardmix_string , TRUE ); - /* on with next */ - scards = scards->next; - } - /* free the instance of liststore, we already have one in the combo box */ - g_object_unref( mixer_card_liststore ); - /* create renderer to display text in the mixer combo box */ - mixer_card_cmb_text_rndr = gtk_cell_renderer_text_new(); - gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(mixer_card_cmb) , mixer_card_cmb_text_rndr , TRUE ); - gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(mixer_card_cmb) , mixer_card_cmb_text_rndr , "text" , 0 ); + /* AMIDI-PLUG PREFERENCES TAB */ + ap_pagelabel_alignment = gtk_alignment_new( 0.5 , 0.5 , 1 , 1 ); + ap_page_alignment = gtk_alignment_new( 0.5 , 0.5 , 1 , 1 ); + gtk_alignment_set_padding( GTK_ALIGNMENT(ap_page_alignment) , 3 , 3 , 8 , 3 ); + i_configure_gui_tab_ap( ap_page_alignment , backend_list , button_ok ); + i_configure_gui_tablabel_ap( ap_pagelabel_alignment , backend_list , button_ok ); + gtk_notebook_append_page( GTK_NOTEBOOK(configwin_notebook) , + ap_page_alignment , ap_pagelabel_alignment ); + + /* ALSA BACKEND CONFIGURATION TAB */ + alsa_pagelabel_alignment = gtk_alignment_new( 0.5 , 0.5 , 1 , 1 ); + alsa_page_alignment = gtk_alignment_new( 0.5 , 0.5 , 1 , 1 ); + gtk_alignment_set_padding( GTK_ALIGNMENT(alsa_page_alignment) , 3 , 3 , 8 , 3 ); + i_configure_gui_tab_alsa( alsa_page_alignment , backend_list , button_ok ); + i_configure_gui_tablabel_alsa( alsa_pagelabel_alignment , backend_list , button_ok ); + gtk_notebook_append_page( GTK_NOTEBOOK(configwin_notebook) , + alsa_page_alignment , alsa_pagelabel_alignment ); - /* the event box is needed to display a tooltip for the mixer combo box */ - mixer_card_cmb_evbox = gtk_event_box_new(); - gtk_container_add( GTK_CONTAINER(mixer_card_cmb_evbox) , mixer_card_cmb ); - mixer_vbox = gtk_vbox_new( FALSE , 0 ); - gtk_container_set_border_width( GTK_CONTAINER(mixer_vbox) , 5 ); - gtk_box_pack_start( GTK_BOX(mixer_vbox) , mixer_card_cmb_evbox , TRUE , TRUE , 0 ); - - mixer_frame = gtk_frame_new( _("Mixer settings") ); - gtk_container_add( GTK_CONTAINER(mixer_frame) , mixer_vbox ); - gtk_box_pack_start( GTK_BOX(configwin_vbox) , mixer_frame , TRUE , TRUE , 2 ); + /* FLUIDSYNTH BACKEND CONFIGURATION TAB */ + fsyn_pagelabel_alignment = gtk_alignment_new( 0.5 , 0.5 , 1 , 1 ); + fsyn_page_alignment = gtk_alignment_new( 0.5 , 0.5 , 1 , 1 ); + gtk_alignment_set_padding( GTK_ALIGNMENT(fsyn_page_alignment) , 3 , 3 , 8 , 3 ); + i_configure_gui_tab_fsyn( fsyn_page_alignment , backend_list , button_ok ); + i_configure_gui_tablabel_fsyn( fsyn_pagelabel_alignment , backend_list , button_ok ); + gtk_notebook_append_page( GTK_NOTEBOOK(configwin_notebook) , + fsyn_page_alignment , fsyn_pagelabel_alignment ); - /*************************/ - /*** ADVANCED SETTINGS ***/ - advanced_vbox = gtk_vbox_new( FALSE , 0 ); - gtk_container_set_border_width( GTK_CONTAINER(advanced_vbox) , 5 ); - - advanced_precalc_checkbt = gtk_check_button_new_with_label( _("pre-calculate length of MIDI files in playlist") ); - amidiplug_gui_prefs.precalc_checkbt = advanced_precalc_checkbt; - if ( amidiplug_cfg.length_precalc_enable ) - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(advanced_precalc_checkbt) , TRUE ); - gtk_box_pack_start( GTK_BOX(advanced_vbox) , advanced_precalc_checkbt , TRUE , TRUE , 0 ); + /* DUMMY BACKEND CONFIGURATION TAB */ + dumm_pagelabel_alignment = gtk_alignment_new( 0.5 , 0.5 , 1 , 1 ); + dumm_page_alignment = gtk_alignment_new( 0.5 , 0.5 , 1 , 1 ); + gtk_alignment_set_padding( GTK_ALIGNMENT(dumm_page_alignment) , 3 , 3 , 8 , 3 ); + i_configure_gui_tab_dumm( dumm_page_alignment , backend_list , button_ok ); + i_configure_gui_tablabel_dumm( dumm_pagelabel_alignment , backend_list , button_ok ); + gtk_notebook_append_page( GTK_NOTEBOOK(configwin_notebook) , + dumm_page_alignment , dumm_pagelabel_alignment ); - advanced_frame = gtk_frame_new( _("Advanced settings") ); - gtk_container_add( GTK_CONTAINER(advanced_frame) , advanced_vbox ); - gtk_box_pack_start( GTK_BOX(configwin_vbox) , advanced_frame , TRUE , TRUE , 2 ); - + i_backend_list_free( backend_list_h ); /* done, free the list of available backends */ /* horizontal separator and buttons */ hseparator = gtk_hseparator_new(); @@ -210,238 +179,174 @@ hbuttonbox = gtk_hbutton_box_new(); gtk_button_box_set_layout( GTK_BUTTON_BOX(hbuttonbox) , GTK_BUTTONBOX_END ); button_cancel = gtk_button_new_from_stock( GTK_STOCK_CANCEL ); - g_signal_connect( G_OBJECT(button_cancel) , "clicked" , G_CALLBACK(i_configure_ev_bcancel) , NULL ); + g_signal_connect_swapped( G_OBJECT(button_cancel) , "clicked" , + G_CALLBACK(i_configure_ev_bcancel) , configwin ); gtk_container_add( GTK_CONTAINER(hbuttonbox) , button_cancel ); - button_ok = gtk_button_new_from_stock( GTK_STOCK_OK ); - g_signal_connect( G_OBJECT(button_ok) , "clicked" , G_CALLBACK(i_configure_ev_bok) , NULL ); + /* button_ok = gtk_button_new_from_stock( GTK_STOCK_OK ); created above */ + g_signal_connect_swapped( G_OBJECT(button_ok) , "clicked" , + G_CALLBACK(i_configure_ev_bok) , configwin ); gtk_container_add( GTK_CONTAINER(hbuttonbox) , button_ok ); gtk_box_pack_start( GTK_BOX(configwin_vbox) , hbuttonbox , FALSE , FALSE , 0 ); - /* tooltips */ - amidiplug_gui_prefs.config_tips = gtk_tooltips_new(); - gtk_tooltips_set_tip( GTK_TOOLTIPS(amidiplug_gui_prefs.config_tips) , port_lv , - _("* Select ALSA output ports *\n" - "MIDI events will be sent to the ports selected here. At least one " - "port must be selected in order to play MIDI with AMIDI-Plug. Unless " - "you know what you're doing, you'll probably want to use the " - "wavetable synthesizer ports.") , "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS(amidiplug_gui_prefs.config_tips) , mixer_card_cmb_evbox , - _("* Select ALSA mixer control *\n" - "AMIDI-Plug outputs directly through ALSA, it doesn't use effect " - "and ouput plugins from the player. While playing with AMIDI-Plug, " - "the player volume will manipulate the control you select here. " - "Unless you know what you're doing, you'll probably want to select " - "the Synth control here.") , "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS(amidiplug_gui_prefs.config_tips) , advanced_precalc_checkbt , - _("* Pre-calculate MIDI length *\n" - "If this option is enabled, AMIDI-Plug will calculate the MIDI file " - "length as soon as the player requests it, instead of doing that only " - "when the the MIDI file is being played. In example, MIDI length " - "will be calculated straight after adding MIDI files in a playlist. " - "Disable this option if you want faster playlist loading (when a lot " - "of MIDI files are added), enable it to display more information " - "in the playlist straight after loading.") , "" ); - - gtk_widget_show_all( amidiplug_gui_prefs.config_win ); + gtk_widget_show_all( configwin ); } -void i_configure_upd_portlist( void ) -{ - GtkTreeModel * liststore; - GString *wp = g_string_new( "" ); - /* get the model of the port list control */ - liststore = gtk_tree_view_get_model( GTK_TREE_VIEW(amidiplug_gui_prefs.port_treeview) ); - /* after the following foreach, wp contains a comma-separated list of selected ports */ - gtk_tree_model_foreach( liststore , i_configure_ev_checktoggle , wp ); - /* free previous */ - g_free( amidiplug_cfg.seq_writable_ports ); - /* update point amidiplug_cfg.seq_writable_ports - so it points to the new list of ports */ - amidiplug_cfg.seq_writable_ports = g_strdup( wp->str ); - /* not needed anymore */ - g_string_free( wp , TRUE ); - return; -} - - -void i_configure_upd_mixercardlist( void ) +void i_configure_ev_bcancel( gpointer configwin ) { - GtkTreeModel * liststore; - GtkTreeIter iter; - /* get the model of the card-mixer list control */ - liststore = gtk_combo_box_get_model( GTK_COMBO_BOX(amidiplug_gui_prefs.mixercard_combo) ); - /* get the selected item */ - if ( gtk_combo_box_get_active_iter( GTK_COMBO_BOX(amidiplug_gui_prefs.mixercard_combo) , &iter ) ) - { - /* free previous */ - g_free( amidiplug_cfg.mixer_control_name ); - /* update amidiplug_cfg.mixer_card_id and amidiplug_cfg.mixer_control_name */ - gtk_tree_model_get( GTK_TREE_MODEL(liststore) , &iter , - LISTMIXER_CARDID_COLUMN , &amidiplug_cfg.mixer_card_id , - LISTMIXER_MIXCTLID_COLUMN , &amidiplug_cfg.mixer_control_id , - LISTMIXER_MIXCTLNAME_COLUMN , &amidiplug_cfg.mixer_control_name , -1 ); - } - return; -} - - -gboolean i_configure_ev_checktoggle( GtkTreeModel * model , GtkTreePath * path , - GtkTreeIter * iter , gpointer wpp ) -{ - gboolean toggled = FALSE; - gchar * portstring; - GString * wps = wpp; - gtk_tree_model_get ( model , iter , - LISTPORT_TOGGLE_COLUMN , &toggled , - LISTPORT_PORTNUM_COLUMN , &portstring , -1 ); - /* check if the row points to an enabled port */ - if ( toggled ) - { - /* if this is not the first port added to wp, use comma as separator */ - if ( wps->str[0] != '\0' ) g_string_append_c( wps , ',' ); - g_string_append( wps , portstring ); - } - g_free( portstring ); - return FALSE; + i_configure_cfg_backend_free(); + gtk_widget_destroy(GTK_WIDGET(configwin)); } -void i_configure_ev_changetoggle( GtkCellRendererToggle * rdtoggle , - gchar * path_str , gpointer data ) -{ - GtkTreeModel *model = (GtkTreeModel *)data; - GtkTreeIter iter; - GtkTreePath *path = gtk_tree_path_new_from_string( path_str ); - gboolean toggled; - - gtk_tree_model_get_iter( model , &iter , path ); - gtk_tree_model_get( model , &iter , LISTPORT_TOGGLE_COLUMN , &toggled , -1); - - toggled ^= 1; - gtk_list_store_set( GTK_LIST_STORE(model), &iter , LISTPORT_TOGGLE_COLUMN , toggled , -1); - - gtk_tree_path_free (path); -} - - -void i_configure_ev_destroy( void ) -{ - g_object_unref( amidiplug_gui_prefs.config_tips ); - amidiplug_gui_prefs.config_tips = NULL; - amidiplug_gui_prefs.config_win = NULL; -} - - -void i_configure_ev_bcancel( void ) -{ - gtk_widget_destroy(amidiplug_gui_prefs.config_win); -} - - -void i_configure_ev_bok( void ) +void i_configure_ev_bok( gpointer configwin ) { - /* update amidiplug_cfg.seq_writable_ports - using the selected values from the port list */ - i_configure_upd_portlist(); - - /* update amidiplug_cfg.mixer_card_id and amidiplug_cfg.mixer_control_name - using the selected values from the card-mixer combo list */ - i_configure_upd_mixercardlist(); - - /* update amidiplug_cfg.length_precalc_enable using - the check control in the advanced settings frame */ - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(amidiplug_gui_prefs.precalc_checkbt) ) ) - amidiplug_cfg.length_precalc_enable = 1; - else - amidiplug_cfg.length_precalc_enable = 0; - - /* save settings */ - i_configure_cfg_save(); - - gtk_widget_destroy(amidiplug_gui_prefs.config_win); -} - - -gchar * i_configure_read_seq_ports_default( void ) -{ - FILE * fp = NULL; - /* first try, get seq ports from proc on card0 */ - fp = fopen( "/proc/asound/card0/wavetableD1" , "rb" ); - if ( fp ) + if ( xmms_remote_is_playing(0) || xmms_remote_is_paused(0) ) { - gchar buffer[100]; - while ( !feof( fp ) ) + /* we can't change settings while a song is being played */ + static GtkWidget * configwin_warnmsg = NULL; + if ( configwin_warnmsg != NULL ) { - fgets( buffer , 100 , fp ); - if (( strlen( buffer ) > 11 ) && ( !strncasecmp( buffer , "addresses: " , 11 ) )) - { - /* change spaces between ports (65:0 65:1 65:2 ...) - into commas (65:0,65:1,65:2,...) */ - g_strdelimit( &buffer[11] , " " , ',' ); - /* remove lf and cr from the end of the string */ - g_strdelimit( &buffer[11] , "\r\n" , '\0' ); - /* ready to go */ - DEBUGMSG( "init, default values for seq ports detected: %s\n" , &buffer[11] ); - fclose( fp ); - return g_strdup( &buffer[11] ); - } + gdk_window_raise( configwin_warnmsg->window ); } - fclose( fp ); - } - - /* second option: do not set ports at all, let the user - select the right ones in the nice preferences dialog :) */ - return g_strdup( "" ); -} - - -void i_configure_cfg_read( void ) -{ - ConfigDb *cfgfile; - cfgfile = bmp_cfg_db_open(); - - if (!cfgfile) - { - /* use defaults */ - amidiplug_cfg.seq_writable_ports = i_configure_read_seq_ports_default(); - amidiplug_cfg.mixer_card_id = 0; - amidiplug_cfg.mixer_control_name = g_strdup( "Synth" ); - amidiplug_cfg.mixer_control_id = 0; - amidiplug_cfg.length_precalc_enable = 0; + else + { + configwin_warnmsg = (GtkWidget*)i_message_gui( _("AMIDI-Plug message") , + _("Please stop the player before changing AMIDI-Plug settings.") , + AMIDIPLUG_MESSAGE_WARN , configwin ); + g_signal_connect( G_OBJECT(configwin_warnmsg) , "destroy" , + G_CALLBACK(gtk_widget_destroyed) , &configwin_warnmsg ); + gtk_widget_show_all( configwin_warnmsg ); + } } else { - if ( !bmp_cfg_db_get_string( cfgfile , "amidi-plug" , "writable_ports" , &amidiplug_cfg.seq_writable_ports ) ) - amidiplug_cfg.seq_writable_ports = i_configure_read_seq_ports_default(); /* default value */ - - if ( !bmp_cfg_db_get_int( cfgfile , "amidi-plug" , "mixer_card_id" , &amidiplug_cfg.mixer_card_id ) ) - amidiplug_cfg.mixer_card_id = 0; /* default value */ + DEBUGMSG( "saving configuration...\n" ); + i_configure_cfg_ap_save(); /* save amidiplug settings */ + i_configure_cfg_backend_save(); /* save backend settings */ + i_configure_cfg_backend_free(); /* free backend settings */ + DEBUGMSG( "configuration saved\n" ); - if ( !bmp_cfg_db_get_string( cfgfile , "amidi-plug" , "mixer_control_name" , &amidiplug_cfg.mixer_control_name ) ) - amidiplug_cfg.mixer_control_name = g_strdup( "Synth" ); /* default value */ + /* check if a different backend has been selected */ + if ( strcmp( amidiplug_cfg_ap.ap_seq_backend , backend.name ) ) + { + DEBUGMSG( "a new backend has been selected, unloading previous and loading the new one\n" ); + i_backend_unload(); /* unload previous backend */ + i_backend_load( amidiplug_cfg_ap.ap_seq_backend ); /* load new backend */ + } + else /* same backend, just reload updated configuration */ + { + DEBUGMSG( "the selected backend is already loaded, so just perform backend cleanup and reinit\n" ); + backend.cleanup(); + backend.init(); + } - if ( !bmp_cfg_db_get_int( cfgfile , "amidi-plug" , "mixer_control_id" , &amidiplug_cfg.mixer_control_id ) ) - amidiplug_cfg.mixer_control_id = 0; /* default value */ - - if ( !bmp_cfg_db_get_int( cfgfile , "amidi-plug" , "length_precalc_enable" , &amidiplug_cfg.length_precalc_enable ) ) - amidiplug_cfg.length_precalc_enable = 0; /* default value */ - - bmp_cfg_db_close(cfgfile); + gtk_widget_destroy(GTK_WIDGET(configwin)); } } -void i_configure_cfg_save( void ) +void i_configure_cfg_backend_alloc( void ) +{ + amidiplug_cfg_backend = g_malloc(sizeof(amidiplug_cfg_backend)); + + i_configure_cfg_alsa_alloc(); /* alloc alsa backend configuration */ + i_configure_cfg_fsyn_alloc(); /* alloc fluidsynth backend configuration */ + i_configure_cfg_dumm_alloc(); /* alloc dummy backend configuration */ +} + + +void i_configure_cfg_backend_free( void ) +{ + i_configure_cfg_alsa_free(); /* free alsa backend configuration */ + i_configure_cfg_fsyn_free(); /* free fluidsynth backend configuration */ + i_configure_cfg_dumm_free(); /* free dummy backend configuration */ + + g_free( amidiplug_cfg_backend ); +} + + +void i_configure_cfg_backend_read( void ) { - ConfigDb *cfgfile; - cfgfile = bmp_cfg_db_open(); + pcfg_t *cfgfile; + + gchar * config_pathfilename = g_strjoin( "" , g_get_home_dir() , "/" , + PLAYER_LOCALRCDIR , "/amidi-plug.conf" , NULL ); + cfgfile = i_pcfg_new_from_file( config_pathfilename ); + + i_configure_cfg_alsa_read( cfgfile ); /* get alsa backend configuration */ + i_configure_cfg_fsyn_read( cfgfile ); /* get fluidsynth backend configuration */ + i_configure_cfg_dumm_read( cfgfile ); /* get dummy backend configuration */ + + if ( cfgfile != NULL ) + i_pcfg_free(cfgfile); + + g_free( config_pathfilename ); +} + + +void i_configure_cfg_backend_save( void ) +{ + pcfg_t *cfgfile; + gchar * config_pathfilename = g_strjoin( "" , g_get_home_dir() , "/" , + PLAYER_LOCALRCDIR , "/amidi-plug.conf" , NULL ); + cfgfile = i_pcfg_new_from_file( config_pathfilename ); + + if (!cfgfile) + cfgfile = i_pcfg_new(); - bmp_cfg_db_set_string( cfgfile , "amidi-plug" , "writable_ports" , amidiplug_cfg.seq_writable_ports ); - bmp_cfg_db_set_int( cfgfile , "amidi-plug" , "mixer_card_id" , amidiplug_cfg.mixer_card_id ); - bmp_cfg_db_set_string( cfgfile , "amidi-plug" , "mixer_control_name" , amidiplug_cfg.mixer_control_name ); - bmp_cfg_db_set_int( cfgfile , "amidi-plug" , "mixer_control_id" , amidiplug_cfg.mixer_control_id ); - bmp_cfg_db_set_int( cfgfile , "amidi-plug" , "length_precalc_enable" , amidiplug_cfg.length_precalc_enable ); + i_configure_cfg_alsa_save( cfgfile ); /* save alsa backend configuration */ + i_configure_cfg_fsyn_save( cfgfile ); /* save fluidsynth backend configuration */ + i_configure_cfg_dumm_save( cfgfile ); /* save dummy backend configuration */ + + i_pcfg_write_to_file( cfgfile , config_pathfilename ); + i_pcfg_free( cfgfile ); + g_free( config_pathfilename ); +} + + +/* read only the amidi-plug part of configuration */ +void i_configure_cfg_ap_read( void ) +{ + pcfg_t *cfgfile; + gchar * config_pathfilename = g_strjoin( "" , g_get_home_dir() , "/" , + PLAYER_LOCALRCDIR , "/amidi-plug.conf" , NULL ); + cfgfile = i_pcfg_new_from_file( config_pathfilename ); - bmp_cfg_db_close(cfgfile); + if (!cfgfile) + { + /* amidi-plug defaults */ + amidiplug_cfg_ap.ap_seq_backend = g_strdup( "alsa" ); + amidiplug_cfg_ap.ap_opts_length_precalc = 0; + } + else + { + i_pcfg_read_string( cfgfile , "general" , "ap_seq_backend" , + &amidiplug_cfg_ap.ap_seq_backend , "alsa" ); + i_pcfg_read_integer( cfgfile , "general" , "ap_opts_length_precalc" , + &amidiplug_cfg_ap.ap_opts_length_precalc , 0 ); + i_pcfg_free( cfgfile ); + } + + g_free( config_pathfilename ); } + + +void i_configure_cfg_ap_save( void ) +{ + pcfg_t *cfgfile; + gchar * config_pathfilename = g_strjoin( "" , g_get_home_dir() , "/" , + PLAYER_LOCALRCDIR , "/amidi-plug.conf" , NULL ); + cfgfile = i_pcfg_new_from_file( config_pathfilename ); + + if (!cfgfile) + cfgfile = i_pcfg_new(); + + /* save amidi-plug config information */ + i_pcfg_write_string( cfgfile , "general" , "ap_seq_backend" , amidiplug_cfg_ap.ap_seq_backend ); + i_pcfg_write_integer( cfgfile , "general" , "ap_opts_length_precalc" , amidiplug_cfg_ap.ap_opts_length_precalc ); + + i_pcfg_write_to_file( cfgfile , config_pathfilename ); + i_pcfg_free( cfgfile ); + g_free( config_pathfilename ); +}
--- a/Plugins/Input/amidi-plug/i_configure.h Mon Jul 10 04:42:53 2006 -0700 +++ b/Plugins/Input/amidi-plug/i_configure.h Mon Jul 10 04:52:51 2006 -0700 @@ -22,59 +22,22 @@ #define _I_CONFIGURE_H 1 #include "i_common.h" -#include <gtk/gtk.h> -#include "libaudacious/configdb.h" -enum -{ - LISTPORT_TOGGLE_COLUMN, - LISTPORT_PORTNUM_COLUMN, - LISTPORT_CLIENTNAME_COLUMN, - LISTPORT_PORTNAME_COLUMN, - LISTPORT_POINTER_COLUMN, - LISTPORT_N_COLUMNS -}; - -enum -{ - LISTMIXER_DESC_COLUMN, - LISTMIXER_CARDID_COLUMN, - LISTMIXER_MIXCTLID_COLUMN, - LISTMIXER_MIXCTLNAME_COLUMN, - LISTMIXER_N_COLUMNS -}; - typedef struct { - gchar * seq_writable_ports; - gint mixer_card_id; - gchar * mixer_control_name; - gint mixer_control_id; - gint length_precalc_enable; + gchar * ap_seq_backend; + gint ap_opts_length_precalc; } -amidiplug_cfg_t; +amidiplug_cfg_ap_t; -extern amidiplug_cfg_t amidiplug_cfg; -typedef struct -{ - GtkWidget * config_win; - GtkWidget * port_treeview; - GtkWidget * mixercard_combo; - GtkWidget * precalc_checkbt; - GtkTooltips * config_tips; -} -amidiplug_gui_prefs_t; +extern amidiplug_cfg_ap_t amidiplug_cfg_ap; + -static amidiplug_gui_prefs_t amidiplug_gui_prefs = { NULL , NULL , NULL , NULL , NULL }; - -void i_configure_gui( GSList * , GSList * ); -void i_configure_ev_destroy( void ); -void i_configure_ev_bcancel( void ); -void i_configure_ev_bok( void ); -void i_configure_cfg_save( void ); -void i_configure_cfg_read( void ); +void i_configure_gui( void ); +void i_configure_cfg_ap_read( void ); +void i_configure_cfg_ap_save( void ); #endif /* !_I_CONFIGURE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/i_configure_private.h Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,42 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#ifndef _I_CONFIGURE_PRIVATE_H +#define _I_CONFIGURE_PRIVATE_H 1 + +#include "i_common.h" +#include "i_backend.h" +#include "pcfg/i_pcfg.h" +#include <gtk/gtk.h> + + +typedef struct +{ + gpointer alsa; /* advanced linux sound architecture */ + gpointer fsyn; /* fluidsynth */ + gpointer dumm; /* dummy */ +} +amidiplug_cfg_backend_t; + + +GtkWidget * i_configure_gui_draw_title( gchar * ); +void i_configure_ev_browse_for_entry( GtkWidget * ); + +#endif /* !_I_CONFIGURE_PRIVATE_H */
--- a/Plugins/Input/amidi-plug/i_fileinfo.c Mon Jul 10 04:42:53 2006 -0700 +++ b/Plugins/Input/amidi-plug/i_fileinfo.c Mon Jul 10 04:52:51 2006 -0700 @@ -19,26 +19,24 @@ */ +#include <gtk/gtk.h> #include "i_fileinfo.h" /* this is needed to retrieve information */ #include "i_midi.h" /* icon from gnome-mime-audio-midi.png of the GNOME ICON SET */ #include "amidi-plug.midiicon.xpm" -static amidiplug_gui_fileinfo_t amidiplug_gui_fileinfo = { NULL }; - void i_fileinfo_ev_destroy( GtkWidget * win , gpointer mf ) { i_midi_free( (midifile_t *)mf ); g_free( mf ); - amidiplug_gui_fileinfo.fileinfo_win = NULL; } -void i_fileinfo_ev_close( void ) +void i_fileinfo_ev_close( GtkWidget * button , gpointer fileinfowin ) { - gtk_widget_destroy( amidiplug_gui_fileinfo.fileinfo_win ); + gtk_widget_destroy( GTK_WIDGET(fileinfowin) ); } @@ -63,6 +61,7 @@ void i_fileinfo_gui( gchar * filename ) { + static GtkWidget *fileinfowin = NULL; GtkWidget *fileinfowin_vbox; GtkWidget *title_hbox , *title_icon_image , *title_name_f_label , *title_name_v_entry; GtkWidget *info_frame , *info_table; @@ -73,11 +72,13 @@ GString *value_gstring; gchar *title , *filename_utf8; gint bpm = 0, wavg_bpm = 0; - midifile_t * mf = g_malloc(sizeof(midifile_t)); + midifile_t *mf; - if ( amidiplug_gui_fileinfo.fileinfo_win ) + if ( fileinfowin ) return; + mf = g_malloc(sizeof(midifile_t)); + /****************** midifile parser ******************/ if ( !i_midi_parse_from_filename( filename , mf ) ) return; @@ -86,16 +87,16 @@ i_midi_get_bpm( mf , &bpm , &wavg_bpm ); /*****************************************************/ - amidiplug_gui_fileinfo.fileinfo_win = gtk_window_new( GTK_WINDOW_TOPLEVEL ); - gtk_window_set_type_hint( GTK_WINDOW(amidiplug_gui_fileinfo.fileinfo_win), GDK_WINDOW_TYPE_HINT_DIALOG ); - gtk_window_set_resizable( GTK_WINDOW(amidiplug_gui_fileinfo.fileinfo_win) , FALSE ); - gtk_window_set_position( GTK_WINDOW(amidiplug_gui_fileinfo.fileinfo_win) , GTK_WIN_POS_CENTER ); - g_signal_connect( G_OBJECT(amidiplug_gui_fileinfo.fileinfo_win) , - "destroy" , G_CALLBACK(i_fileinfo_ev_destroy) , mf ); - gtk_container_set_border_width( GTK_CONTAINER(amidiplug_gui_fileinfo.fileinfo_win), 10 ); + fileinfowin = gtk_window_new( GTK_WINDOW_TOPLEVEL ); + gtk_window_set_type_hint( GTK_WINDOW(fileinfowin), GDK_WINDOW_TYPE_HINT_DIALOG ); + gtk_window_set_resizable( GTK_WINDOW(fileinfowin) , FALSE ); + gtk_window_set_position( GTK_WINDOW(fileinfowin) , GTK_WIN_POS_CENTER ); + g_signal_connect( G_OBJECT(fileinfowin) , "destroy" , G_CALLBACK(i_fileinfo_ev_destroy) , mf ); + g_signal_connect( G_OBJECT(fileinfowin) , "destroy" , G_CALLBACK(gtk_widget_destroyed) , &fileinfowin ); + gtk_container_set_border_width( GTK_CONTAINER(fileinfowin), 10 ); fileinfowin_vbox = gtk_vbox_new( FALSE , 10 ); - gtk_container_add( GTK_CONTAINER(amidiplug_gui_fileinfo.fileinfo_win) , fileinfowin_vbox ); + gtk_container_add( GTK_CONTAINER(fileinfowin) , fileinfowin_vbox ); /* pango attributes */ pangoattrlist = pango_attr_list_new(); @@ -165,7 +166,7 @@ footer_hbbox = gtk_hbutton_box_new(); gtk_button_box_set_layout( GTK_BUTTON_BOX(footer_hbbox) , GTK_BUTTONBOX_END ); footer_bclose = gtk_button_new_from_stock( GTK_STOCK_CLOSE ); - g_signal_connect( G_OBJECT(footer_bclose) , "clicked" , G_CALLBACK(i_fileinfo_ev_close) , NULL ); + g_signal_connect( G_OBJECT(footer_bclose) , "clicked" , G_CALLBACK(i_fileinfo_ev_close) , fileinfowin ); gtk_container_add( GTK_CONTAINER(footer_hbbox) , footer_bclose ); gtk_box_pack_start( GTK_BOX(fileinfowin_vbox) , footer_hbbox , FALSE , FALSE , 0 ); @@ -185,7 +186,7 @@ g_free(convert_str); } title = g_strdup_printf( "%s - " PLAYER_NAME , g_basename(filename_utf8)); - gtk_window_set_title( GTK_WINDOW(amidiplug_gui_fileinfo.fileinfo_win) , title); + gtk_window_set_title( GTK_WINDOW(fileinfowin) , title); g_free(title); /* set the text for the filename header too */ gtk_entry_set_text( GTK_ENTRY(title_name_v_entry) , filename_utf8 ); @@ -193,5 +194,5 @@ g_free(filename_utf8); gtk_widget_grab_focus( GTK_WIDGET(footer_bclose) ); - gtk_widget_show_all( amidiplug_gui_fileinfo.fileinfo_win ); + gtk_widget_show_all( fileinfowin ); }
--- a/Plugins/Input/amidi-plug/i_fileinfo.h Mon Jul 10 04:42:53 2006 -0700 +++ b/Plugins/Input/amidi-plug/i_fileinfo.h Mon Jul 10 04:52:51 2006 -0700 @@ -22,16 +22,8 @@ #define _I_FILEINFO_H 1 #include "i_common.h" -#include <gtk/gtk.h> -#include "libaudacious/util.h" -typedef struct -{ - GtkWidget * fileinfo_win; -} -amidiplug_gui_fileinfo_t; - void i_fileinfo_gui( gchar * );
--- a/Plugins/Input/amidi-plug/i_midi.h Mon Jul 10 04:42:53 2006 -0700 +++ b/Plugins/Input/amidi-plug/i_midi.h Mon Jul 10 04:52:51 2006 -0700 @@ -22,36 +22,202 @@ #define _I_MIDI_H 1 #include "i_common.h" -#include <alsa/asoundlib.h> +#include "i_midievent.h" #define MAKE_ID(c1, c2, c3, c4) ((c1) | ((c2) << 8) | ((c3) << 16) | ((c4) << 24)) -/* MIDI event we care of */ -#define MIDI_EVENT_NOTEOFF 1 -#define MIDI_EVENT_NOTEON 2 -#define MIDI_EVENT_KEYPRESS 3 -#define MIDI_EVENT_CONTROLLER 4 -#define MIDI_EVENT_PGMCHANGE 5 -#define MIDI_EVENT_CHANPRESS 6 -#define MIDI_EVENT_PITCHBEND 7 -#define MIDI_EVENT_SYSEX 8 -#define MIDI_EVENT_TEMPO 9 + +/* sequencer event type, got from ALSA header alsa/seq_event.h */ +enum snd_seq_event_type { + /* system status; event data type = #snd_seq_result_t */ + SND_SEQ_EVENT_SYSTEM = 0, + /* returned result status; event data type = #snd_seq_result_t */ + SND_SEQ_EVENT_RESULT, + + /* note on and off with duration; event data type = #snd_seq_ev_note_t */ + SND_SEQ_EVENT_NOTE = 5, + /* note on; event data type = #snd_seq_ev_note_t */ + SND_SEQ_EVENT_NOTEON, + /* note off; event data type = #snd_seq_ev_note_t */ + SND_SEQ_EVENT_NOTEOFF, + /* key pressure change (aftertouch); event data type = #snd_seq_ev_note_t */ + SND_SEQ_EVENT_KEYPRESS, + + /* controller; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_CONTROLLER = 10, + /* program change; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_PGMCHANGE, + /* channel pressure; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_CHANPRESS, + /* pitchwheel; event data type = #snd_seq_ev_ctrl_t; data is from -8192 to 8191) */ + SND_SEQ_EVENT_PITCHBEND, + /* 14 bit controller value; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_CONTROL14, + /* 14 bit NRPN; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_NONREGPARAM, + /* 14 bit RPN; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_REGPARAM, + + /* SPP with LSB and MSB values; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_SONGPOS = 20, + /* Song Select with song ID number; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_SONGSEL, + /* midi time code quarter frame; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_QFRAME, + /* SMF Time Signature event; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_TIMESIGN, + /* SMF Key Signature event; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_KEYSIGN, + /* MIDI Real Time Start message; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_START = 30, + /* MIDI Real Time Continue message; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_CONTINUE, + /* MIDI Real Time Stop message; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_STOP, + /* Set tick queue position; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_SETPOS_TICK, + /* Set real-time queue position; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_SETPOS_TIME, + /* (SMF) Tempo event; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_TEMPO, + /* MIDI Real Time Clock message; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_CLOCK, + /* MIDI Real Time Tick message; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_TICK, + /* Queue timer skew; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_QUEUE_SKEW, + /* Sync position changed; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_SYNC_POS, + + /* Tune request; event data type = none */ + SND_SEQ_EVENT_TUNE_REQUEST = 40, + /* Reset to power-on state; event data type = none */ + SND_SEQ_EVENT_RESET, + /* Active sensing event; event data type = none */ + SND_SEQ_EVENT_SENSING, + + /* Echo-back event; event data type = any type */ + SND_SEQ_EVENT_ECHO = 50, + /* OSS emulation raw event; event data type = any type */ + SND_SEQ_EVENT_OSS, + + /* New client has connected; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_CLIENT_START = 60, + /* Client has left the system; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_CLIENT_EXIT, + /* Client status/info has changed; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_CLIENT_CHANGE, + /* New port was created; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_PORT_START, + /* Port was deleted from system; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_PORT_EXIT, + /* Port status/info has changed; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_PORT_CHANGE, + + /* Ports connected; event data type = #snd_seq_connect_t */ + SND_SEQ_EVENT_PORT_SUBSCRIBED, + /* Ports disconnected; event data type = #snd_seq_connect_t */ + SND_SEQ_EVENT_PORT_UNSUBSCRIBED, -struct midievent_stru { - struct midievent_stru * next; /* linked list */ - guchar type; /* SND_SEQ_EVENT_xxx */ - guchar port; /* port index */ - guint tick; - union { - guchar d[3]; /* channel and data bytes */ - gint tempo; - guint length; /* length of sysex data */ - } data; - guchar sysex[0]; + /* Sample select; event data type = #snd_seq_ev_sample_control_t */ + SND_SEQ_EVENT_SAMPLE = 70, + /* Sample cluster select; event data type = #snd_seq_ev_sample_control_t */ + SND_SEQ_EVENT_SAMPLE_CLUSTER, + /* voice start */ + SND_SEQ_EVENT_SAMPLE_START, + /* voice stop */ + SND_SEQ_EVENT_SAMPLE_STOP, + /* playback frequency */ + SND_SEQ_EVENT_SAMPLE_FREQ, + /* volume and balance */ + SND_SEQ_EVENT_SAMPLE_VOLUME, + /* sample loop */ + SND_SEQ_EVENT_SAMPLE_LOOP, + /* sample position */ + SND_SEQ_EVENT_SAMPLE_POSITION, + /* private (hardware dependent) event */ + SND_SEQ_EVENT_SAMPLE_PRIVATE1, + + /* user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR0 = 90, + /* user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR1, + /* user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR2, + /* user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR3, + /* user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR4, + /* user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR5, + /* user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR6, + /* user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR7, + /* user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR8, + /* user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR9, + + /* begin of instrument management */ + SND_SEQ_EVENT_INSTR_BEGIN = 100, + /* end of instrument management */ + SND_SEQ_EVENT_INSTR_END, + /* query instrument interface info */ + SND_SEQ_EVENT_INSTR_INFO, + /* result of instrument interface info */ + SND_SEQ_EVENT_INSTR_INFO_RESULT, + /* query instrument format info */ + SND_SEQ_EVENT_INSTR_FINFO, + /* result of instrument format info */ + SND_SEQ_EVENT_INSTR_FINFO_RESULT, + /* reset instrument instrument memory */ + SND_SEQ_EVENT_INSTR_RESET, + /* get instrument interface status */ + SND_SEQ_EVENT_INSTR_STATUS, + /* result of instrument interface status */ + SND_SEQ_EVENT_INSTR_STATUS_RESULT, + /* put an instrument to port */ + SND_SEQ_EVENT_INSTR_PUT, + /* get an instrument from port */ + SND_SEQ_EVENT_INSTR_GET, + /* result of instrument query */ + SND_SEQ_EVENT_INSTR_GET_RESULT, + /* free instrument(s) */ + SND_SEQ_EVENT_INSTR_FREE, + /* get instrument list */ + SND_SEQ_EVENT_INSTR_LIST, + /* result of instrument list */ + SND_SEQ_EVENT_INSTR_LIST_RESULT, + /* set cluster parameters */ + SND_SEQ_EVENT_INSTR_CLUSTER, + /* get cluster parameters */ + SND_SEQ_EVENT_INSTR_CLUSTER_GET, + /* result of cluster parameters */ + SND_SEQ_EVENT_INSTR_CLUSTER_RESULT, + /* instrument change */ + SND_SEQ_EVENT_INSTR_CHANGE, + + /* system exclusive data (variable length); event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_SYSEX = 130, + /* error event; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_BOUNCE, + /* reserved for user apps; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_USR_VAR0 = 135, + /* reserved for user apps; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_USR_VAR1, + /* reserved for user apps; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_USR_VAR2, + /* reserved for user apps; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_USR_VAR3, + /* reserved for user apps; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_USR_VAR4, + + /* NOP; ignored in any case */ + SND_SEQ_EVENT_NONE = 255 }; -typedef struct midievent_stru midievent_t; typedef struct {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/i_midievent.h Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,40 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#ifndef _I_MIDIEVENT_H +#define _I_MIDIEVENT_H 1 + +struct midievent_stru { + struct midievent_stru * next; /* linked list */ + guchar type; /* SND_SEQ_EVENT_xxx */ + guchar port; /* port index */ + guint tick; + guint tick_real; /* tick with custom offset */ + union { + guchar d[3]; /* channel and data bytes */ + gint tempo; + guint length; /* length of sysex data */ + } data; + guchar sysex[0]; +}; + +typedef struct midievent_stru midievent_t; + +#endif /* !_I_MIDIEVENT_H */
--- a/Plugins/Input/amidi-plug/i_seq.c Mon Jul 10 04:42:53 2006 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,493 +0,0 @@ -/* -* -* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of the GNU General Public License as published by the -* Free Software Foundation; either version 2 of the License, or (at your -* option) any later version. -* -* This program is distributed in the hope that it will be useful, but -* WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* General Public License for more details. -* -* You should have received a copy of the GNU General Public License along -* with this program; if not, write to the Free Software Foundation, Inc., -* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -* -*/ - - -#include "i_seq.h" - - -/* activate sequencer client */ -gint i_seq_on( gshort with_wparse , gchar * wports_str ) -{ - if ( !i_seq_open() ) - { - sc.seq = NULL; - return 0; - } - - if ( !i_seq_port_create() ) - { - i_seq_close(); - sc.seq = NULL; - return 0; - } - - if ( !i_seq_queue_create() ) - { - i_seq_close(); - sc.seq = NULL; - return 0; - } - - if (( with_wparse > 0 ) && ( wports_str )) - i_seq_port_wparse( wports_str ); - - if ( !i_seq_port_connect() ) - { - i_seq_queue_free(); - i_seq_close(); - sc.seq = NULL; - return 0; - } - - /* success */ - return 1; -} - - -/* shutdown sequencer client */ -gint i_seq_off( void ) -{ - if ( sc.seq ) - { - i_seq_port_disconnect(); - i_seq_queue_free(); - i_seq_close(); - sc.seq = NULL; - /* return 1 here */ - return 1; - } - /* return 2 if it was already freed */ - return 2; -} - - -/* create sequencer client */ -gint i_seq_open( void ) -{ - gint err; - err = snd_seq_open(&sc.seq, "default", SND_SEQ_OPEN_DUPLEX, 0); - if (err < 0) - return 0; - snd_seq_set_client_name(sc.seq, "amidi-plug"); - return 1; -} - - -/* free sequencer client */ -gint i_seq_close( void ) -{ - if ( snd_seq_close( sc.seq ) < 0 ) - return 0; /* fail */ - else - return 1; /* success */ -} - - -/* create queue */ -gint i_seq_queue_create( void ) -{ - sc.queue = snd_seq_alloc_named_queue( sc.seq , "AMIDI-Plug" ); - if ( sc.queue < 0 ) - return 0; /* fail */ - else - return 1; /* success */ -} - - -/* free queue */ -gint i_seq_queue_free( void ) -{ - if ( snd_seq_free_queue( sc.seq , sc.queue ) < 0 ) - return 0; /* fail */ - else - return 1; /* success */ -} - - -/* queue set tempo */ -gint i_seq_queue_set_tempo( gint tempo , gint ppq ) -{ - /* interpret and set tempo */ - snd_seq_queue_tempo_alloca( &sc.queue_tempo ); - snd_seq_queue_tempo_set_tempo( sc.queue_tempo , tempo ); - snd_seq_queue_tempo_set_ppq( sc.queue_tempo , ppq ); - - if ( snd_seq_set_queue_tempo( sc.seq , sc.queue , sc.queue_tempo ) < 0 ) - { - g_warning( "Cannot set queue tempo (%u/%i)\n", - snd_seq_queue_tempo_get_tempo(sc.queue_tempo), - snd_seq_queue_tempo_get_ppq(sc.queue_tempo) ); - return 0; - } - return 1; -} - - -/* create sequencer port */ -gint i_seq_port_create( void ) -{ - sc.client_port = snd_seq_create_simple_port( sc.seq , "AMIDI-Plug" , 0 , - SND_SEQ_PORT_TYPE_MIDI_GENERIC | - SND_SEQ_PORT_TYPE_APPLICATION ); - if ( sc.client_port < 0 ) - return 0; /* fail */ - else - return 1; /* success */ -} - - -/* port connection */ -gint i_seq_port_connect( void ) -{ - gint i = 0 , err = 0; - for ( i = 0 ; i < sc.dest_port_num ; i++ ) - { - if ( snd_seq_connect_to( sc.seq , sc.client_port , - sc.dest_port[i].client , - sc.dest_port[i].port ) < 0 ) - ++err; - } - /* if these values are equal, it means - that all port connections failed */ - if ( err == i ) - return 0; /* fail */ - else - return 1; /* success */ -} - - -/* port disconnection */ -gint i_seq_port_disconnect( void ) -{ - gint i = 0 , err = 0; - for ( i = 0 ; i < sc.dest_port_num ; i++ ) - { - if ( snd_seq_disconnect_to( sc.seq , sc.client_port , - sc.dest_port[i].client , - sc.dest_port[i].port ) < 0 ) - ++err; - } - /* if these values are equal, it means - that all port disconnections failed */ - if ( err == i ) - return 0; /* fail */ - else - return 1; /* success */ -} - - -/* parse writable ports */ -gint i_seq_port_wparse( gchar * wportlist ) -{ - gint i = 0 , err = 0; - gchar **portstr = g_strsplit( wportlist , "," , 0 ); - - sc.dest_port_num = 0; - - /* fill sc.dest_port_num with the writable port number */ - while ( portstr[sc.dest_port_num] != NULL ) - ++sc.dest_port_num; - - /* check if there is already an allocated array and free it */ - if ( sc.dest_port ) - free( sc.dest_port ); - - if ( sc.dest_port_num > 0 ) - /* allocate the array of writable ports */ - sc.dest_port = calloc( sc.dest_port_num , sizeof(snd_seq_addr_t) ); - - for ( i = 0 ; i < sc.dest_port_num ; i++ ) - { - if ( snd_seq_parse_address( sc.seq , &sc.dest_port[i] , portstr[i] ) < 0 ) - ++err; - } - - g_strfreev( portstr ); - - /* if these values are equal, it means - that all port translations failed */ - if ( err == i ) - return 0; /* fail */ - else - return 1; /* success */ -} - - -/* get a list of writable ALSA MIDI ports - use the data_bucket_t here... - bint[0] = client id , bint[1] = port id - bcharp[0] = client name , bcharp[1] = port name - bpointer[0] = (not used) , bpointer[1] = (not used) */ -GSList * i_seq_port_get_list( void ) -{ - snd_seq_t * pseq; - snd_seq_open( &pseq , "default" , SND_SEQ_OPEN_DUPLEX , 0 ); - - GSList * wports = NULL; - snd_seq_client_info_t *cinfo; - snd_seq_port_info_t *pinfo; - - snd_seq_client_info_alloca( &cinfo ); - snd_seq_port_info_alloca( &pinfo ); - - snd_seq_client_info_set_client( cinfo , -1 ); - while ( snd_seq_query_next_client( pseq , cinfo ) >= 0 ) - { - gint client = snd_seq_client_info_get_client( cinfo ); - snd_seq_port_info_set_client( pinfo , client ); - snd_seq_port_info_set_port( pinfo , -1 ); - while (snd_seq_query_next_port( pseq , pinfo ) >= 0 ) - { - if ((snd_seq_port_info_get_capability(pinfo) - & (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)) - == (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)) - { - data_bucket_t * portinfo = (data_bucket_t*)g_malloc(sizeof(data_bucket_t)); - portinfo->bint[0] = snd_seq_port_info_get_client( pinfo ); - portinfo->bint[1] = snd_seq_port_info_get_port( pinfo ); - portinfo->bcharp[0] = g_strdup(snd_seq_client_info_get_name(cinfo)); - portinfo->bcharp[1] = g_strdup(snd_seq_port_info_get_name(pinfo)); - wports = g_slist_append( wports , portinfo ); - } - } - } - /* snd_seq_port_info_free( pinfo ); - snd_seq_client_info_free( cinfo ); */ - snd_seq_close( pseq ); - return wports; -} - - -void i_seq_port_free_list( GSList * wports ) -{ - GSList * start = wports; - while ( wports != NULL ) - { - data_bucket_t * portinfo = wports->data; - g_free( (gpointer)portinfo->bcharp[0] ); - g_free( (gpointer)portinfo->bcharp[1] ); - g_free( portinfo ); - wports = wports->next; - } - g_slist_free( start ); - return; -} - - -/* get a list of available sound cards and relative mixer controls; - use the data_bucket_t here... - bint[0] = card id , bint[1] = (not used) - bcharp[0] = card name , bcharp[1] = (not used) - bpointer[0] = list (GSList) of mixer controls on the card , bpointer[1] = (not used) */ -GSList * i_seq_card_get_list( void ) -{ - gint soundcard_id = -1; - GSList * scards = NULL; - - snd_card_next( &soundcard_id ); - while ( soundcard_id > -1 ) - { - /* card container */ - data_bucket_t * cardinfo = (data_bucket_t*)g_malloc(sizeof(data_bucket_t)); - cardinfo->bint[0] = soundcard_id; - /* snd_card_get_name calls strdup on its own */ - snd_card_get_name( soundcard_id , &cardinfo->bcharp[0] ); - /* for each sound card, get a list of available mixer controls */ - cardinfo->bpointer[0] = i_seq_mixctl_get_list( soundcard_id ); - - scards = g_slist_append( scards , cardinfo ); - snd_card_next( &soundcard_id ); - } - return scards; -} - - -void i_seq_card_free_list( GSList * scards ) -{ - GSList * start = scards; - while ( scards != NULL ) - { - data_bucket_t * cardinfo = scards->data; - g_free( (gpointer)cardinfo->bcharp[0] ); - g_free( cardinfo ); - scards = scards->next; - } - g_slist_free( start ); - return; -} - - -/* get a list of available mixer controls for a given sound card; - use the data_bucket_t here... - bint[0] = control id , bint[1] = (not used) - bcharp[0] = control name , bcharp[1] = (not used) - bpointer[0] = (not used) , bpointer[1] = (not used) */ -GSList * i_seq_mixctl_get_list( gint soundcard_id ) -{ - GSList * mixctls = NULL; - snd_mixer_t * mixer_h; - snd_mixer_selem_id_t * mixer_selem_id; - snd_mixer_elem_t * mixer_elem; - gchar card[10]; - - snprintf( card , 8 , "hw:%i" , soundcard_id ); - card[9] = '\0'; - - snd_mixer_selem_id_alloca( &mixer_selem_id ); - snd_mixer_open( &mixer_h , 0 ); - snd_mixer_attach( mixer_h , card ); - snd_mixer_selem_register( mixer_h , NULL , NULL ); - snd_mixer_load( mixer_h ); - for ( mixer_elem = snd_mixer_first_elem( mixer_h ) ; mixer_elem ; - mixer_elem = snd_mixer_elem_next( mixer_elem ) ) - { - data_bucket_t * mixctlinfo = (data_bucket_t*)g_malloc(sizeof(data_bucket_t)); - snd_mixer_selem_get_id( mixer_elem , mixer_selem_id ); - mixctlinfo->bint[0] = snd_mixer_selem_id_get_index(mixer_selem_id); - mixctlinfo->bcharp[0] = g_strdup(snd_mixer_selem_id_get_name(mixer_selem_id)); - mixctls = g_slist_append( mixctls , mixctlinfo ); - } - snd_mixer_close( mixer_h ); - return mixctls; -} - - -void i_seq_mixctl_free_list( GSList * mixctls ) -{ - GSList * start = mixctls; - while ( mixctls != NULL ) - { - data_bucket_t * mixctlinfo = mixctls->data; - g_free( (gpointer)mixctlinfo->bcharp[0] ); - g_free( mixctlinfo ); - mixctls = mixctls->next; - } - g_slist_free( start ); - return; -} - - -gint i_seq_mixer_find_selem( snd_mixer_t * mixer_h , gchar * mixer_card , - gchar * mixer_control_name , gint mixer_control_id , - snd_mixer_elem_t ** mixer_elem ) -{ - snd_mixer_selem_id_t * mixer_selem_id = NULL; - - snd_mixer_selem_id_alloca( &mixer_selem_id ); - snd_mixer_selem_id_set_index( mixer_selem_id , mixer_control_id ); - snd_mixer_selem_id_set_name( mixer_selem_id , mixer_control_name ); - - snd_mixer_attach( mixer_h , mixer_card ); - snd_mixer_selem_register( mixer_h , NULL , NULL); - snd_mixer_load( mixer_h ); - - /* assign the mixer element (can be NULL if there is no such element) */ - *mixer_elem = snd_mixer_find_selem( mixer_h , mixer_selem_id ); - - /* always return 1 here */ - return 1; -} - - -gint i_seq_mixer_get_volume( gint * left_volume , gint * right_volume , - gchar * mixer_card , gchar * mixer_control_name , gint mixer_control_id ) -{ - snd_mixer_t * mixer_h = NULL; - snd_mixer_elem_t * mixer_elem = NULL; - - if ( snd_mixer_open( &mixer_h , 0 ) > -1 ) - i_seq_mixer_find_selem( mixer_h , mixer_card , mixer_control_name , mixer_control_id , &mixer_elem ); - else - mixer_h = NULL; - - if ( ( mixer_elem ) && ( snd_mixer_selem_has_playback_volume( mixer_elem ) ) ) - { - glong pv_min , pv_max , pv_range; - glong lc, rc; - - snd_mixer_selem_get_playback_volume_range( mixer_elem , &pv_min , &pv_max ); - pv_range = pv_max - pv_min; - if ( pv_range > 0 ) - { - if ( snd_mixer_selem_has_playback_channel( mixer_elem , SND_MIXER_SCHN_FRONT_LEFT ) ) - { - snd_mixer_selem_get_playback_volume( mixer_elem , SND_MIXER_SCHN_FRONT_LEFT , &lc ); - /* convert the range to 0-100 (for the case that pv_range is not 0-100 already) */ - *left_volume = (gint)(((lc - pv_min) * 100) / pv_range); - DEBUGMSG( "GET VOLUME requested, get left channel (%i)\n" , *left_volume ); - } - if ( snd_mixer_selem_has_playback_channel( mixer_elem , SND_MIXER_SCHN_FRONT_RIGHT ) ) - { - snd_mixer_selem_get_playback_volume( mixer_elem , SND_MIXER_SCHN_FRONT_RIGHT , &rc ); - /* convert the range to 0-100 (for the case that pv_range is not 0-100 already) */ - *right_volume = (gint)(((rc - pv_min) * 100) / pv_range); - DEBUGMSG( "GET VOLUME requested, get right channel (%i)\n" , *right_volume ); - } - } - } - - if ( mixer_h ) - snd_mixer_close( mixer_h ); - - /* for now, always return 1 here */ - return 1; -} - - -gint i_seq_mixer_set_volume( gint left_volume , gint right_volume , - gchar * mixer_card , gchar * mixer_control_name , gint mixer_control_id ) -{ - snd_mixer_t * mixer_h = NULL; - snd_mixer_elem_t * mixer_elem = NULL; - - if ( snd_mixer_open( &mixer_h , 0 ) > -1 ) - i_seq_mixer_find_selem( mixer_h , mixer_card , mixer_control_name , mixer_control_id , &mixer_elem ); - else - mixer_h = NULL; - - if ( ( mixer_elem ) && ( snd_mixer_selem_has_playback_volume( mixer_elem ) ) ) - { - glong pv_min , pv_max , pv_range; - - snd_mixer_selem_get_playback_volume_range( mixer_elem , &pv_min , &pv_max ); - pv_range = pv_max - pv_min; - if ( pv_range > 0 ) - { - if ( snd_mixer_selem_has_playback_channel( mixer_elem , SND_MIXER_SCHN_FRONT_LEFT ) ) - { - DEBUGMSG( "SET VOLUME requested, setting left channel to %i%%\n" , left_volume ); - snd_mixer_selem_set_playback_volume( mixer_elem , SND_MIXER_SCHN_FRONT_LEFT , - (gint)((gdouble)(0.01 * (gdouble)(left_volume * pv_range)) + pv_min) ); - } - if ( snd_mixer_selem_has_playback_channel( mixer_elem , SND_MIXER_SCHN_FRONT_RIGHT ) ) - { - DEBUGMSG( "SET VOLUME requested, setting right channel to %i%%\n" , right_volume ); - snd_mixer_selem_set_playback_volume( mixer_elem , SND_MIXER_SCHN_FRONT_RIGHT , - (gint)((gdouble)(0.01 * (gdouble)(right_volume * pv_range)) + pv_min) ); - } - } - } - - if ( mixer_h ) - snd_mixer_close( mixer_h ); - - /* for now, always return 1 here */ - return 1; -}
--- a/Plugins/Input/amidi-plug/i_seq.h Mon Jul 10 04:42:53 2006 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/* -* -* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of the GNU General Public License as published by the -* Free Software Foundation; either version 2 of the License, or (at your -* option) any later version. -* -* This program is distributed in the hope that it will be useful, but -* WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* General Public License for more details. -* -* You should have received a copy of the GNU General Public License along -* with this program; if not, write to the Free Software Foundation, Inc., -* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -* -*/ - -#ifndef _I_SEQ_H -#define _I_SEQ_H 1 - -#include "i_common.h" -#include <alsa/asoundlib.h> - -typedef struct -{ - snd_seq_t * seq; - gint client_port; - gint queue; - - snd_seq_addr_t * dest_port; - gint dest_port_num; - - snd_seq_queue_tempo_t * queue_tempo; -} -sequencer_client_t; - -extern sequencer_client_t sc; - -gint i_seq_on( gshort , gchar * ); -gint i_seq_off( void ); -gint i_seq_open( void ); -gint i_seq_close( void ); -gint i_seq_port_create( void ); -gint i_seq_port_connect( void ); -gint i_seq_port_disconnect( void ); -gint i_seq_queue_create( void ); -gint i_seq_queue_free( void ); -gint i_seq_queue_set_tempo( gint , gint ); -gint i_seq_mixer_get_volume( gint * , gint * , gchar * , gchar * , gint ); -gint i_seq_mixer_set_volume( gint , gint , gchar * , gchar * , gint ); -gint i_seq_port_wparse( gchar * ); -GSList * i_seq_port_get_list( void ); -GSList * i_seq_card_get_list( void ); -GSList * i_seq_mixctl_get_list( gint ); -void i_seq_port_free_list( GSList * ); -void i_seq_card_free_list( GSList * ); -void i_seq_mixctl_free_list( GSList * ); - -#endif /* !_I_SEQ_H */
--- a/Plugins/Input/amidi-plug/i_utils.c Mon Jul 10 04:42:53 2006 -0700 +++ b/Plugins/Input/amidi-plug/i_utils.c Mon Jul 10 04:52:51 2006 -0700 @@ -20,31 +20,13 @@ #include "i_utils.h" +#include <gtk/gtk.h> #include "amidi-plug.logo.xpm" -static amidiplug_gui_about_t amidiplug_gui_about = { NULL }; - -void i_about_ev_destroy( void ); -void i_about_ev_bok( void ); - - -/* count the number of occurrencies of a specific character 'c' - in the string 'string' (it must be a null-terminated string) */ -gint i_util_str_count( gchar * string , gchar c ) -{ - gint i = 0 , count = 0; - while ( string[i] != '\0' ) - { - if ( string[i] == c ) - ++count; - ++i; - } - return count; -} - void i_about_gui( void ) { + static GtkWidget * aboutwin = NULL; GtkWidget *logoandinfo_vbox , *aboutwin_vbox; GtkWidget *logo_image , *logo_frame; GtkWidget *info_frame , *info_scrolledwin , *info_textview; @@ -52,21 +34,20 @@ GtkTextBuffer *info_textbuffer; GdkPixbuf *logo_pixbuf; - if ( amidiplug_gui_about.about_win ) + if ( aboutwin != NULL ) return; - amidiplug_gui_about.about_win = gtk_window_new( GTK_WINDOW_TOPLEVEL ); - gtk_window_set_type_hint( GTK_WINDOW(amidiplug_gui_about.about_win), GDK_WINDOW_TYPE_HINT_DIALOG ); - gtk_window_set_title( GTK_WINDOW(amidiplug_gui_about.about_win), "AMIDI-Plug - about" ); - gtk_window_set_resizable( GTK_WINDOW(amidiplug_gui_about.about_win) , FALSE ); - gtk_container_set_border_width( GTK_CONTAINER(amidiplug_gui_about.about_win), 10 ); - g_signal_connect( G_OBJECT(amidiplug_gui_about.about_win) , - "destroy" , G_CALLBACK(i_about_ev_destroy) , NULL ); + aboutwin = gtk_window_new( GTK_WINDOW_TOPLEVEL ); + gtk_window_set_type_hint( GTK_WINDOW(aboutwin), GDK_WINDOW_TYPE_HINT_DIALOG ); + gtk_window_set_title( GTK_WINDOW(aboutwin), "AMIDI-Plug - about" ); + gtk_window_set_resizable( GTK_WINDOW(aboutwin) , FALSE ); + gtk_container_set_border_width( GTK_CONTAINER(aboutwin), 10 ); + g_signal_connect( G_OBJECT(aboutwin) , "destroy" , G_CALLBACK(gtk_widget_destroyed) , &aboutwin ); aboutwin_vbox = gtk_vbox_new( FALSE , 0 ); logoandinfo_vbox = gtk_vbox_new( TRUE , 2 ); - gtk_container_add( GTK_CONTAINER(amidiplug_gui_about.about_win) , aboutwin_vbox ); + gtk_container_add( GTK_CONTAINER(aboutwin) , aboutwin_vbox ); logo_pixbuf = gdk_pixbuf_new_from_xpm_data( (const gchar **)amidiplug_xpm_logo ); logo_image = gtk_image_new_from_pixbuf( logo_pixbuf ); @@ -84,8 +65,8 @@ gtk_text_view_set_left_margin( GTK_TEXT_VIEW(info_textview) , 10 ); gtk_text_buffer_set_text( info_textbuffer , - "\nAMIDI-Plug " AMIDIPLUG_VERSION - "\nplay MIDI music through the ALSA sequencer\n" + "\nAMIDI-Plug " VERSION + "\nmodular MIDI music player\n" "http://www.develia.org/projects.php?p=amidiplug\n\n" "written by Giacomo Lozito\n" "< james@develia.org >\n\n\n" @@ -117,21 +98,38 @@ hbuttonbox = gtk_hbutton_box_new(); gtk_button_box_set_layout( GTK_BUTTON_BOX(hbuttonbox) , GTK_BUTTONBOX_END ); button_ok = gtk_button_new_from_stock( GTK_STOCK_OK ); - g_signal_connect( G_OBJECT(button_ok) , "clicked" , G_CALLBACK(i_about_ev_bok) , NULL ); + g_signal_connect_swapped( G_OBJECT(button_ok) , "clicked" , G_CALLBACK(gtk_widget_destroy) , aboutwin ); gtk_container_add( GTK_CONTAINER(hbuttonbox) , button_ok ); gtk_box_pack_start( GTK_BOX(aboutwin_vbox) , hbuttonbox , FALSE , FALSE , 0 ); - gtk_widget_show_all( amidiplug_gui_about.about_win ); + gtk_widget_show_all( aboutwin ); } -void i_about_ev_destroy( void ) +gpointer i_message_gui( gchar * title , gchar * message , + gint type , gpointer parent_win ) { - amidiplug_gui_about.about_win = NULL; -} + GtkWidget *win; + GtkMessageType mtype = GTK_MESSAGE_INFO; + switch ( type ) + { + case AMIDIPLUG_MESSAGE_INFO: + mtype = GTK_MESSAGE_INFO; break; + case AMIDIPLUG_MESSAGE_WARN: + mtype = GTK_MESSAGE_WARNING; break; + case AMIDIPLUG_MESSAGE_ERR: + mtype = GTK_MESSAGE_ERROR; break; + } -void i_about_ev_bok( void ) -{ - gtk_widget_destroy(amidiplug_gui_about.about_win); + if ( parent_win != NULL ) + win = gtk_message_dialog_new( GTK_WINDOW(parent_win) , GTK_DIALOG_DESTROY_WITH_PARENT , + mtype , GTK_BUTTONS_OK , message ); + else + win = gtk_message_dialog_new( NULL , 0 , mtype , GTK_BUTTONS_OK , message ); + + gtk_window_set_title( GTK_WINDOW(win) , title ); + g_signal_connect_swapped( G_OBJECT(win) , "response" , G_CALLBACK(gtk_widget_destroy) , win ); + + return win; }
--- a/Plugins/Input/amidi-plug/i_utils.h Mon Jul 10 04:42:53 2006 -0700 +++ b/Plugins/Input/amidi-plug/i_utils.h Mon Jul 10 04:52:51 2006 -0700 @@ -22,17 +22,13 @@ #define _I_UTILS_H 1 #include "i_common.h" -#include <gtk/gtk.h> + +#define AMIDIPLUG_MESSAGE_INFO 0 +#define AMIDIPLUG_MESSAGE_WARN 1 +#define AMIDIPLUG_MESSAGE_ERR 2 -typedef struct -{ - GtkWidget * about_win; -} -amidiplug_gui_about_t; - void i_about_gui( void ); -gint i_util_str_count( gchar * , gchar ); - +gpointer i_message_gui( gchar * , gchar * , gint , gpointer ); #endif /* !_I_UTILS_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/pcfg/Makefile.in Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,12 @@ +include ../../../../mk/rules.mk +include ../../../../mk/objective.mk + +noinst_HEADERS = i_pcfg.h + +CFLAGS += -fPIC -DPIC $(GLIB_CFLAGS) -I../../../../intl -I../../../.. + +OBJECTIVE_LIBS_NOINST = libpcfg.a + +SOURCES = i_pcfg.c + +OBJECTS = ${SOURCES:.c=.o}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/pcfg/i_pcfg.c Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,158 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + + +#include "i_pcfg.h" + + +pcfg_t * i_pcfg_new( void ) +{ + pcfg_t * configfile = g_key_file_new(); + return configfile; +} + + +pcfg_t * i_pcfg_new_from_file( gchar * pathfilename ) +{ + pcfg_t * configfile = g_key_file_new(); + if ( g_key_file_load_from_file( configfile , pathfilename , G_KEY_FILE_NONE , NULL ) == FALSE ) + { + g_key_file_free( configfile ); + configfile = NULL; + } + return configfile; +} + + +void i_pcfg_free( pcfg_t * configfile ) +{ + g_key_file_free( configfile ); + return; +} + + +gboolean i_pcfg_write_to_file( pcfg_t * configfile , gchar * pathfilename ) +{ + GError * error = NULL; + gchar *configfile_string = g_key_file_to_data( configfile , NULL , &error ); + if ( error != NULL ) + { + g_clear_error( &error ); + return FALSE; + } + else + { + if ( g_file_set_contents( pathfilename , configfile_string , -1 , NULL ) == FALSE ) + { + g_free( configfile_string ); + return FALSE; + } + else + { + g_free( configfile_string ); + return TRUE; + } + } +} + + +gboolean i_pcfg_read_string( pcfg_t * configfile , + const gchar * group , + const gchar * key , + gchar ** value , + gchar * default_value ) +{ + GError * error = NULL; + *value = g_key_file_get_string( configfile , group , key , &error ); + if ( error != NULL ) + { + if ( default_value != NULL ) + *value = g_strdup( default_value ); + g_clear_error( &error ); + return FALSE; + } + return TRUE; +} + + +gboolean i_pcfg_read_integer( pcfg_t * configfile , + const gchar * group , + const gchar * key , + gint * value , + gint default_value ) +{ + GError * error = NULL; + *value = g_key_file_get_integer( configfile , group , key , &error ); + if ( error != NULL ) + { + *value = default_value; + g_clear_error( &error ); + return FALSE; + } + return TRUE; +} + + +gboolean i_pcfg_read_boolean( pcfg_t * configfile , + const gchar * group , + const gchar * key , + gboolean * value , + gboolean default_value ) +{ + GError * error = NULL; + *value = g_key_file_get_boolean( configfile , group , key , &error ); + if ( error != NULL ) + { + *value = default_value; + g_clear_error( &error ); + return FALSE; + } + return TRUE; +} + + +gboolean i_pcfg_write_string( pcfg_t * configfile , + const gchar * group , + const gchar * key , + gchar * value ) +{ + g_key_file_set_string( configfile , group , key , value ); + return TRUE; +} + + +gboolean i_pcfg_write_integer( pcfg_t * configfile , + const gchar * group , + const gchar * key , + gint value ) +{ + g_key_file_set_integer( configfile , group , key , value ); + return TRUE; +} + + +gboolean i_pcfg_write_boolean( pcfg_t * configfile , + const gchar * group , + const gchar * key , + gboolean value ) +{ + g_key_file_set_boolean( configfile , group , key , value ); + return TRUE; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/amidi-plug/pcfg/i_pcfg.h Mon Jul 10 04:52:51 2006 -0700 @@ -0,0 +1,39 @@ +/* +* +* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#ifndef _I_PCFG_H +#define _I_PCFG_H 1 + +#include <glib.h> + +typedef void pcfg_t; + +pcfg_t * i_pcfg_new( void ); +pcfg_t * i_pcfg_new_from_file( gchar * ); +void i_pcfg_free( pcfg_t * ); +gboolean i_pcfg_write_to_file( pcfg_t * , gchar * ); +gboolean i_pcfg_read_string( pcfg_t * , const gchar * , const gchar * , gchar ** , gchar * ); +gboolean i_pcfg_read_integer( pcfg_t * , const gchar * , const gchar * , gint * , gint ); +gboolean i_pcfg_read_boolean( pcfg_t * , const gchar * , const gchar * , gboolean * , gboolean ); +gboolean i_pcfg_write_string( pcfg_t * , const gchar * , const gchar * , gchar * ); +gboolean i_pcfg_write_integer( pcfg_t * , const gchar * , const gchar * , gint ); +gboolean i_pcfg_write_boolean( pcfg_t * , const gchar * , const gchar * , gboolean ); + +#endif /* !_I_PCFG_H */
--- a/configure.ac Mon Jul 10 04:42:53 2006 -0700 +++ b/configure.ac Mon Jul 10 04:52:51 2006 -0700 @@ -584,7 +584,8 @@ OUTPUT_PLUGINS="$OUTPUT_PLUGINS alsa" fi -dnl *** amidi-plug (note: should appear somewhere after the alsa ouput plugin check) + +dnl *** amidi-plug (note: to avoid checking twice ALSA, this should appear somewhere after the alsa ouput plugin check) AC_ARG_ENABLE(amidiplug, [ --disable-amidiplug disable amidi-plug input plugin (default=check) ], @@ -592,33 +593,124 @@ [enable_amidiplug=check] ) +AC_ARG_ENABLE(amidiplug-alsa, + [ --disable-amidiplug-alsa disable amidi-plug ALSA backend (default=enabled) ], + [enable_amidiplug_alsa=$enableval], + [enable_amidiplug_alsa=auto] +) + +AC_ARG_ENABLE(amidiplug-flsyn, + [ --disable-amidiplug-flsyn disable amidi-plug FluidSynth backend (default=enabled) ], + [enable_amidiplug_fluidsynth=$enableval], + [enable_amidiplug_fluidsynth=auto] +) + +AC_ARG_ENABLE(amidiplug-dummy, + [ --disable-amidiplug-dummy disable amidi-plug dummy backend (default=enabled) ], + [enable_amidiplug_dummy=$enableval], + [enable_amidiplug_dummy=auto] +) + + if test "x$enable_amidiplug" = "xno"; then AC_MSG_RESULT([*** amidi-plug disabled per user request ***]) enable_amidiplug=no else + if test "x$enable_amidiplug_alsa" != "xauto"; then + enable_amidiplug=yes + elif test "x$enable_amidiplug_fluidsynth" != "xauto"; then + enable_amidiplug=yes + elif test "x$enable_amidiplug_dummy" != "xauto"; then + enable_amidiplug=yes + fi +fi + +if test "x$enable_amidiplug" = "xcheck"; then if test "x$alsalib_available" = "xcheck"; then PKG_CHECK_MODULES(ALSA, [alsa >= 1.0], [alsalib_available=yes],[alsalib_available=no]) fi if test "x$alsalib_available" = "xyes"; then - if test "x$enable_amidiplug" = "xcheck"; then - AM_PATH_AMIDIPLUG(enable_amidiplug=yes, enable_amidiplug=no) - if test "x$enable_amidiplug" = "xyes"; then - ap_disable_timidity=yes - fi + AM_PATH_AMIDIPLUG_HWSYNTH(ap_have_hwsynth=yes, ap_have_hwsynth=no) + if test "x$ap_have_hwsynth" = "xyes"; then + enable_amidiplug=yes + ap_disable_timidity=yes else - enable_amidiplug=yes + PKG_CHECK_MODULES(FLUIDSYNTH, [fluidsynth >= 1.0.6], + [fluidsynth_available=yes],[fluidsynth_available=no]) + if test "x$fluidsynth_available" = "xyes"; then + enable_amidiplug=yes + ap_disable_timidity=yes + else + enable_amidiplug=no + AC_MSG_WARN([*** Neither an ALSA-supported hardware synth or FluidSynth software synth (>= 1.0.6) have been found (even if ALSA was detected), so amidi-plug won't be compiled unless you explicitly request it with --enable-amidiplug ***]) + fi fi else - AC_MSG_WARN([*** ALSA not found, amidi-plug won't be compiled ***]) - enable_amidiplug=no + PKG_CHECK_MODULES(FLUIDSYNTH, [fluidsynth >= 1.0.6], + [fluidsynth_available=yes],[fluidsynth_available=no]) + if test "x$fluidsynth_available" = "xyes"; then + enable_amidiplug=yes + ap_disable_timidity=yes + else + enable_amidiplug=no + AC_MSG_WARN([*** Neither ALSA or FluidSynth software synth (>= 1.0.6) have been found, so amidi-plug won't be compiled unless you explicitly request it with --enable-amidiplug ***]) + fi fi fi -if test "$enable_amidiplug" = "yes"; then - INPUT_PLUGINS="$INPUT_PLUGINS amidi-plug" +if test "x$enable_amidiplug" = "xyes"; then + INPUT_PLUGINS="$INPUT_PLUGINS amidi-plug" + PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.6.0],,) + PKG_CHECK_MODULES(GMODULE, [gmodule-2.0 >= 2.6.0],,) + AMIDIPLUGDATADIR=${datadir}/amidi-plug/audacious + AC_SUBST(AMIDIPLUGDATADIR) + if test "x$enable_amidiplug_alsa" = "xauto" -o "x$enable_amidiplug_alsa" = "xyes"; then + if test "x$alsalib_available" = "xcheck"; then + PKG_CHECK_MODULES(ALSA, [alsa >= 1.0], + [alsalib_available=yes],[alsalib_available=no]) + fi + if test "x$alsalib_available" = "xyes"; then + AMIDIPLUG_BACKENDS="$AMIDIPLUG_BACKENDS backend-alsa" + enable_amidiplug_alsa=yes + else + if test "x$enable_amidiplug_alsa" = "xyes"; then + AC_MSG_ERROR([Cannot find ALSA development files (ver >= 1.0), but compilation of AMIDI-Plug ALSA backend has been explicitly requested; please install ALSA dev files and run configure again]) + enable_amidiplug_alsa=no + else + enable_amidiplug_alsa=no + fi + fi + fi + if test "x$enable_amidiplug_fluidsynth" = "xauto" -o "x$enable_amidiplug_fluidsynth" = "xyes"; then + if test "x$fluidsynth_available" != "xyes" -a "x$fluidsynth_available" != "xno"; then + PKG_CHECK_MODULES(FLUIDSYNTH, [fluidsynth >= 1.0.6], + [fluidsynth_available=yes],[fluidsynth_available=no]) + fi + if test "x$fluidsynth_available" = "xyes"; then + AMIDIPLUG_BACKENDS="$AMIDIPLUG_BACKENDS backend-fluidsynth" + enable_amidiplug_fluidsynth=yes + else + if test "x$enable_amidiplug_fluidsynth" = "xyes"; then + AC_MSG_ERROR([Cannot find FluidSynth development files (ver >= 1.0.6), but compilation of AMIDI-Plug FluidSynth backend has been explicitly requested; please install FluidSynth dev files and run configure again]) + enable_amidiplug_fluidsynth=no + else + enable_amidiplug_fluidsynth=no + fi + fi + fi + if test "x$enable_amidiplug_dummy" = "xauto" -o "x$enable_amidiplug_dummy" = "xyes"; then + AMIDIPLUG_BACKENDS="$AMIDIPLUG_BACKENDS backend-dummy" + enable_amidiplug_dummy=yes + fi + AC_SUBST(AMIDIPLUG_BACKENDS) fi +if test "x$enable_amidiplug" = "xyes"; then + INPUT_PLUGINS="$INPUT_PLUGINS amidi-plug" +fi + + dnl *** TiMidity input plugin (note: should appear somewhere after the amidi-plug check) AC_ARG_ENABLE(timidity, @@ -890,6 +982,10 @@ Plugins/Input/adplug/Makefile Plugins/Input/adplug/core/Makefile Plugins/Input/amidi-plug/Makefile + Plugins/Input/amidi-plug/pcfg/Makefile + Plugins/Input/amidi-plug/backend-alsa/Makefile + Plugins/Input/amidi-plug/backend-fluidsynth/Makefile + Plugins/Input/amidi-plug/backend-dummy/Makefile Plugins/Visualization/Makefile Plugins/Visualization/blur_scope/Makefile Plugins/General/Makefile @@ -950,7 +1046,10 @@ echo " Windows Media Audio (wma): $enable_wma" echo " .mpc playback (musepack): $enable_musepack" echo " Module decoder (modplug): $have_modplug" -echo " MIDI hw synth via ALSA (amidi-plug): $enable_amidiplug" +echo " MIDI modular plugin (amidi-plug): $enable_amidiplug" +echo " -> ALSA backend: $enable_amidiplug_alsa" +echo " -> FluidSynth backend: $enable_amidiplug_fluidsynth" +echo " -> dummy backend: $enable_amidiplug_dummy" echo " MIDI to WAVE converter (timidity): $enable_timidity" echo " CD Digital Audio (cdda): yes" echo " Microsoft WAV (wav): yes" @@ -1000,9 +1099,9 @@ fi if test "x$ap_disable_timidity" = "xyes" && test "x$enable_timidity" = "xno"; then - echo "Note: an ALSA-supported hardware midi synth was detected in configuration;" - echo "in order to use it, the amidi-plug (MIDI through ALSA) input plugin" - echo "will be compiled in place of timidity. If you wish to compile timidity" + echo "Note: an ALSA-supported hardware midi synth or a FluidSynth software synth" + echo "was detected in configuration; in order to use it, the amidi-plug input" + echo "plugin will be compiled in place of timidity. If you wish to compile timidity" echo "anyway, simply use --enable-timidity in configuration." echo "" fi
--- a/m4/amidi-plug.m4 Mon Jul 10 04:42:53 2006 -0700 +++ b/m4/amidi-plug.m4 Mon Jul 10 04:52:51 2006 -0700 @@ -1,9 +1,9 @@ # Checks for amidi-plug -dnl AM_PATH_AMIDIPLUG([ACTION-IF-FOUND , ACTION-IF-NOT-FOUND]) -dnl Test for AMIDI-Plug and ALSA-supported hardware synth +dnl AM_PATH_AMIDIPLUG_HWSYNTH([ACTION-IF-FOUND , ACTION-IF-NOT-FOUND]) +dnl Test for ALSA-supported hardware synth dnl -AC_DEFUN([AM_PATH_AMIDIPLUG], +AC_DEFUN([AM_PATH_AMIDIPLUG_HWSYNTH], [ AMIDIPLUG_EVERYTHINGOK="yes"
--- a/mk/rules.mk.in Mon Jul 10 04:42:53 2006 -0700 +++ b/mk/rules.mk.in Mon Jul 10 04:52:51 2006 -0700 @@ -62,6 +62,7 @@ ALSA_LIBS ?= @ALSA_LIBS@ AMDEP_FALSE ?= @AMDEP_FALSE@ AMDEP_TRUE ?= @AMDEP_TRUE@ +AMIDIPLUGDATADIR ?= @AMIDIPLUGDATADIR@ AMTAR ?= @AMTAR@ AR ?= @AR@ ARCH_DEFINES ?= @ARCH_DEFINES@ @@ -122,12 +123,18 @@ ESD_CFLAGS ?= @ESD_CFLAGS@ ESD_LIBS ?= @ESD_LIBS@ EXEEXT ?= @EXEEXT@ +FLUIDSYNTH_CFLAGS ?= @FLUIDSYNTH_CFLAGS@ +FLUIDSYNTH_LIBS ?= @FLUIDSYNTH_LIBS@ GCONF_CFLAGS ?= @GCONF_CFLAGS@ GCONF_LIBS ?= @GCONF_LIBS@ GENCAT ?= @GENCAT@ GENERAL_PLUGINS ?= @GENERAL_PLUGINS@ GENERAL_PLUGIN_DIR ?= @GENERAL_PLUGIN_DIR@ GLIBC21 ?= @GLIBC21@ +GLIB_CFLAGS ?= @GLIB_CFLAGS@ +GLIB_LIBS ?= @GLIB_LIBS@ +GMODULE_CFLAGS ?= @GMODULE_CFLAGS@ +GMODULE_LIBS ?= @GMODULE_LIBS@ GMSGFMT ?= @GMSGFMT@ GNOMEVFS_CFLAGS ?= @GNOMEVFS_CFLAGS@ GNOMEVFS_LIBS ?= @GNOMEVFS_LIBS@