- -( dyne // software :: culture :: events :: planet :: discussion :: museum \\ freaknet )- -
 
Main Page | Modules | Class Hierarchy | Class List | File List | Class Members | File Members

muse.cpp

Go to the documentation of this file.
00001 
00002 /* $Id: muse.cpp,v 1.21 2005/04/15 12:39:40 jaromil Exp $ */
00003 
00077 #include <iostream>
00078 #include <stdio.h>
00079 #include <stdlib.h>
00080 #include <getopt.h>
00081 #include <string.h>
00082 #include <unistd.h>
00083 #include <fcntl.h>
00084 #include <sys/stat.h>
00085 #include <sys/types.h>
00086 #include <signal.h>
00087 #include <assert.h>
00088 
00089 #include <config.h>
00090 
00091 #include <jutils.h>
00092 #include <generic.h>
00093 #include <jmixer.h>
00094 #include <gui.h>
00095 #include <out_lame.h>
00096 #include <out_vorbis.h>
00097 
00098 #ifdef GUI_NIGHTOLO
00099 #include <gtkgui/gtk_gui.h>
00100 #endif
00101 
00102 #ifdef GUI_NIGHTOLO2
00103 #include <gtkgui2/gtk2_gui.h>
00104 #endif
00105 
00106 #ifdef GUI_RUBIK
00107 #include <ncursesgui/ncurses_gui.h>
00108 #endif
00109 #ifdef HAVE_DARWIN
00110 #ifdef GUI_CARBON
00111 #include <carbon_gui.h>
00112 #endif
00113 #endif
00114 #ifdef UI_XMLRPC
00115 #include <xmlrpc/xmlrpc_ui.h>
00116 #endif
00117 
00118 #ifdef HAVE_SCHEDULER
00119 #include "radiosched.h"
00120 #endif
00121 
00122 
00123 /* command line stuff */
00124 
00125 char *version =
00126 "%s version %s http://muse.dyne.org";
00127 
00128 char *help =
00129 "Usage: muse [generic options] [-e [encoder options] [stream options] ] [files]\n"
00130 ":: generic options:\n"
00131 " -h --help         this help\n"
00132 " -v --version      version information\n"
00133 " -D --debug [1-3]  debug verbosity level       - default 1\n"
00134 " -o --dspout       disable souncard output     - default on\n"
00135 " -C --cli          command line input (no GUI)\n"
00136 " -g --gui          specify GUI to use (-g list)\n"
00137 ":: input channels options\n"
00138 " -i --live         mic/line soundcard input    - default off\n"
00139 " -I --liveamp      mic/line volume (1 - 32)    - default 1\n"
00140 " -N --number       channel number              - default 1\n"
00141 " -V --volume       channel volume              - default 1.0\n"
00142 " -S --position     channel starting position   - default 0.0\n"
00143 " -P --playmode     playmode: play, cont, loop  - default cont\n"
00144 ":: output encoders options:\n"
00145 " -e --encoder      codec to use [ogg|mp3]      - default ogg\n"
00146 " -b --bitrate      codec bitrate in Kbit/s     - default 24\n"
00147 " -r --frequency    encoding frequency          - default auto\n"
00148 " -q --quality      encoding quality (1-9)      - default 4\n"
00149 " -c --channels     number of audio channels    - default 1\n"
00150 " -f --filedump     dump stream to file\n"
00151 ":: broadcast stream options:\n"
00152 " -s --server       stream to server[:port]     - default port 8000\n"
00153 " -m --mount        mounpoint on server         - default live\n"
00154 " -l --login        login type [ice1|ice2|icy]  - default ice1\n"
00155 " -U --user         username on server          - default source\n"
00156 " -p --pass         encoder password on server\n"
00157 " -n --name         name of the stream\n"
00158 " -u --url          descriptive url of the stream\n"
00159 " -d --desc         description of the stream\n"
00160 "\n";
00161 
00162 static const struct option long_options[] = {
00163   { "help", no_argument, NULL, 'h' },
00164   { "version", no_argument, NULL, 'v' },
00165   { "debug", required_argument, NULL, 'D' },
00166   { "live", no_argument, NULL, 'i' },
00167   { "liveamp", required_argument, NULL, 'I' },
00168   { "dspout", no_argument, NULL, 'o' },
00169   { "cli", no_argument, NULL, 'C' },
00170   { "number", required_argument, NULL, 'N' },
00171   { "volume", required_argument, NULL, 'V' },
00172   { "position", required_argument, NULL, 'S' },
00173   { "playmode", required_argument, NULL, 'P' },
00174   { "encoder", required_argument, NULL, 'e' },
00175   { "bitrate", required_argument, NULL, 'b' },
00176   { "frequency", required_argument, NULL, 'r' },
00177   { "quality", required_argument, NULL, 'q' },
00178   { "channels", required_argument, NULL, 'c' },
00179   { "filedump", required_argument, NULL, 'f' },
00180   { "gui", required_argument, NULL, 'g' },
00181   { "server", required_argument, NULL, 's' },
00182   { "port", required_argument, NULL, 'p' },
00183   { "mount", required_argument, NULL, 'm' },
00184   { "login", required_argument, NULL, 'l' },
00185   { "user", required_argument, NULL, 'U' },
00186   { "pass",required_argument, NULL, 'p' },
00187   { "name",required_argument, NULL, 'n' },
00188   { "url",required_argument, NULL, 'u' },
00189   { "desc", required_argument, NULL, 'd' },
00190   { 0, 0, 0, 0 }
00191 };
00192 
00193 char *short_options = "-hvD:ioCN:V:S:P:e:b:r:q:c:f:g:s:m:l:U:p:n:u:d:";
00194 
00195 /* misc settings */
00196 #define MAX_CLI_CHARS 9182
00197 int debug = 1;
00198 bool daemon_mode = false;
00199 char *queue_file = NULL;
00200 
00201 int lfreq = 0;
00202 float quality = 1.0f;
00203 int channels = 1;
00204 
00205 int thegui = -1; /* no gui */
00206 enum interface { CLI, GTK1, GTK2, NCURSES, CARBON };
00207 
00208 // channel options
00209 int number = 0;
00210 int playmode = PLAYMODE_CONT;
00211 
00212 bool has_playlist = false;
00213 bool dspout = true;
00214 bool micrec = false;
00215 int micvol = 16;
00216 bool snddev = false;
00217 
00218 Stream_mixer *mix = NULL;
00219 GUI *gui = NULL;
00220 
00221 OutChannel *outch = NULL;
00222 int encid = 0;
00223 
00224 Shouter *ice = NULL;
00225 int iceid = 0;
00226 
00227 /* declare the sighandlers */
00228 void quitproc (int Sig);
00229 void fsigpipe (int Sig);
00230 bool got_sigpipe;
00231 /* ---------------------- */
00232 
00233 bool take_args(int argc, char **argv) {
00234   int res;
00235   
00236   MuseSetDebug(1);
00237   
00238   do {
00239     res = getopt_long(argc, argv, short_options, long_options, NULL);
00240     
00241     switch(res) {
00242 
00243     case 'h':
00244       fprintf(stderr,"%s",help);
00245       exit(0);
00246 
00247     case 'v':
00248       
00249       notice("GTK2 GUI by Antonino \"nightolo\" Radici <night@freaknet.org>");
00250       notice("Ncurses console by Luca \"rubik\" Profico <rubik@olografix.org>");
00251       act(" ");
00252       notice("BIG UP \\o/  dyne.org / FreakNet / RASTASOFT / Metro Olografix");
00253       act(" ");
00254       act("part of the redistributed code is copyright by the respective authors,");
00255       act("please refer to the AUTHORS file and to the sourcecode for complete");
00256       act("information.");
00257       act(" ");
00258       act("This source code is free software; you can redistribute it and/or");
00259       act("modify it under the terms of the GNU Public License as published");
00260       act("by the Free Software Foundation; either version 2 of the License,");
00261       act("or (at your option) any later version.");
00262       act(" ");
00263       act("This source code is distributed in the hope that it will be useful,");
00264       act("but WITHOUT ANY WARRANTY; without even the implied warranty of");
00265       act("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
00266       act("Please refer to the GNU Public License for more details.");
00267       act(" ");
00268       act("You should have received a copy of the GNU Public License along with");
00269       act("this source code; if not, write to:");
00270       act("Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.");
00271       exit(0);
00272 
00273     case 'D':
00274       MuseSetDebug( atoi(optarg) );
00275       break;
00276 
00277     case 'o':
00278       /* if( !mix->set_lineout(false) )
00279         error("soundcard not present");
00280       else {
00281         act("CLI: soundcard disabled");
00282         dspout = false;
00283         } */
00284       dspout = false;
00285       break;
00286 
00287     case 'i':
00288       /* if( !mix->set_live(true) )
00289         error("soundcard not present");
00290       else {
00291         act("CLI: recording from mic/linein");
00292         micrec = true;
00293         } */
00294       micrec = true;
00295       mix->set_mic_volume(micvol);
00296       notice("CLI: recording from mic/linein");
00297       break;
00298       
00299     case 'I':
00300       micvol = atoi(optarg);
00301       if(micvol < 1 || micvol > 32)
00302         error("invalid mic/line volume value, must be a approx between 1 and 32");
00303       else {
00304         mix->set_mic_volume(micvol);
00305         act("CLI: mic/linein volume gain %i",micvol);
00306       }
00307       break;
00308 
00309     case 'e':
00310       encid = 0;
00311 
00312 #ifdef HAVE_VORBIS
00313       if (strncasecmp("ogg",optarg,3) == 0) {
00314         encid = mix->create_enc(OGG);
00315         notice("CLI: created Ogg encoder");
00316       }
00317 #endif
00318       
00319 #ifdef HAVE_LAME
00320       if (strncasecmp("mp3",optarg,3) == 0) {
00321         encid = mix->create_enc(MP3);
00322         notice("CLI: created Mp3 encoder");
00323       }
00324 #endif
00325 
00326       if(encid>0) outch = mix->get_enc(encid);
00327       if(outch) break;
00328 
00329       error("you can specify an encoder with the -e option");
00330       act("supported encoders are:");
00331 #ifdef HAVE_VORBIS
00332       act("  OGG - Ogg/Vorbis codec");
00333 #endif
00334 #ifdef HAVE_LAME
00335       act("  MP3 - Lame MP3 codec");
00336 #endif
00337       exit(0);
00338 
00339     case 'b':
00340       if(!outch) {
00341         error("invalid command line argument: bps");
00342         error("you must specify a codec first with the -e option");
00343         break;
00344       }
00345       outch->bps( atoi(optarg) );
00346       act("CLI: bitrate set to %iKbit/s",outch->bps());
00347       break;
00348 
00349     case 'r':
00350       if(!outch) {
00351         error("invalid command line argument: frequency");
00352         error("you must specify a codec first with the -e option");
00353         break;
00354       }
00355       lfreq = atoi(optarg);
00356       if(lfreq != 0 &&
00357          lfreq != 11000 &&
00358          lfreq != 16000 &&
00359          lfreq != 22050 &&
00360          lfreq != 32000 &&
00361          lfreq != 44100) {
00362         error("invalid frequency %i",lfreq);
00363         error("must be 0, 11000, 16000, 22050, 32000 or 44100 Hz!");
00364         act("CLI: falling back to auto");
00365         lfreq = 0;
00366       }
00367       outch->freq(lfreq);
00368       act("CLI: frequency set to %iKhz",outch->freq());
00369       break; 
00370 
00371     case 'q':
00372       if(!outch) {
00373         error("invalid command line argument: quality");
00374         error("you must specify a codec first with the -e option");
00375         break;
00376       }
00377       if( sscanf(optarg,"%f",&quality) ) {
00378         
00379         /*
00380           if(quality<0.1f) quality = 0.1f;
00381           if(quality>9.0f) quality = 9.0f;
00382         */
00383         //      outch->quality(quality);
00384         act("CLI: quality set to %s",outch->quality(quality));
00385       } else error("invalid quality value");
00386       break;
00387         
00388     case 'c':
00389       if(!outch) {
00390         error("invalid command line argument: channels");
00391         error("you must specify a codec first with the -e option");
00392         break;
00393       }
00394       
00395       channels = atoi(optarg);
00396       if(channels>2 | channels<1) {
00397         error("audio channels can be only 1 (mono) or 2 (stereo)");
00398         act("falling back to default: 1 (mono)");
00399         channels = 1;
00400       }
00401       outch->channels(channels);
00402       act("CLI: encoding %i channel(s)",channels);
00403       break;
00404 
00405     case 'f':
00406       if(!outch) {
00407         error("invalid command line argument: file dump");
00408         error("you must specify a codec first with the -e option");
00409         break;
00410       }
00411       outch->dump_start( optarg );
00412       act("CLI: file saving to %s",optarg);
00413       break;
00414 
00415     case 'C':
00416       thegui = 0;
00417       break;
00418 
00419     case 'N':
00420       number = atoi(optarg);
00421       number = (number<0) ? 0 : (number>=MAX_CHANNELS) ? MAX_CHANNELS-1 : number;
00422       //      number--;
00423       if(!mix->chan[number]) {
00424         if(!mix->create_channel(number)) {
00425           error("got problems creating channel %i",number);
00426         } else {
00427           notice("CLI: created channel %i",number);
00428           mix->set_playmode(number,playmode);
00429         }
00430       }
00431       break;
00432 
00433     case 'V':
00434       float vol;
00435       if(sscanf(optarg,"%f",&vol)==EOF)
00436         error("CLI: invalid volume for channel %i",number);
00437       else {
00438         vol = (vol>1.0) ? 1.0 : (vol < 0.0) ? 0.0 : vol;
00439         mix->set_volume(number,vol);
00440         act("CLI: volume set to %.2f",vol);
00441       }
00442       break;
00443       
00444     case 'S':
00445       float pos;
00446       if(sscanf(optarg,"%f",&pos)==EOF)
00447         error("CLI: invalid position for channel %i",number);
00448       else {
00449         pos = (pos>1.0) ? 1.0 : (pos < 0.0) ? 0.0 : pos;
00450         mix->set_position(number,pos);
00451         act("CLI: starting from position %.2f",pos);
00452       }
00453       break;
00454 
00455     case 'P':
00456       playmode = 0;
00457       if(strncasecmp(optarg,"play",4)==0) playmode=PLAYMODE_PLAY;
00458       if(strncasecmp(optarg,"cont",4)==0) playmode=PLAYMODE_CONT;
00459       if(strncasecmp(optarg,"loop",4)==0) playmode=PLAYMODE_LOOP;
00460       if(!playmode)
00461         error("invalid playmode %s",optarg);
00462       else
00463         //      mix->set_playmode(number,playmode);
00464         act("CLI: set playmode \"%s\" for following channels",optarg);
00465       break;
00466 
00467     case 'g':
00468 #ifdef GUI_NIGHTOLO
00469       if(strcasecmp(optarg,"gtk")==0) thegui=GTK1;
00470 #endif
00471 #ifdef GUI_NIGHTOLO2
00472       if(strcasecmp(optarg,"gtk2")==0) thegui=GTK2;
00473 #endif
00474 #ifdef GUI_RUBIK
00475       if(strcasecmp(optarg,"ncurses")==0) thegui=NCURSES;
00476 #endif
00477 #ifdef GUI_CARBON
00478       if(strcasecmp(optarg,"carbon")==0) {
00479           thegui=CARBON;
00480           }
00481 #endif
00482       if(strcasecmp(optarg,"cli")==0) thegui=CLI;
00483 
00484       if(thegui>=0) break;
00485 
00486       notice("listing available user interfaces:");
00487 #ifdef GUI_NIGHTOLO
00488       act("[gtk] - Xwin graphical interactive clicky clicky");
00489 #endif
00490 #ifdef GUI_NIGHTOLO2
00491       act("[gtk2] - new graphical interactive, experimental with languages");
00492 #endif
00493 #ifdef GUI_RUBIK
00494       act("[ncurses] - 0ld sch00l l33t console display");
00495 #endif
00496       act("[cli] - command line interface, not interactive");
00497       exit(0);
00498 
00499     case 's':
00500       if(!outch) {
00501         error("invalid command line argument: server");
00502         error("you must specify a codec first with the -e option");
00503         break;
00504       }
00505 
00506       iceid = outch->create_ice();
00507       if(iceid<0) {
00508         error("could'nt create icecast shouter");
00509         break;
00510       } else func("created icecast shouter ID %i",iceid);
00511       ice = outch->get_ice(iceid);
00512 
00513       char *p;
00514       p = strstr(optarg,":");
00515       if(p) { 
00516         ice->port( atoi(p+1) );
00517         *p = '\0';
00518       } else ice->port(8000);
00519       ice->host(optarg);
00520       notice("CLI: created streamer to %s %i",
00521              ice->host(), ice->port());
00522       
00523       break;
00524 
00525     case 'l':
00526       if(!outch) {
00527         error("invalid command line argument: server login type");
00528         error("you must specify a codec first with the -e option");
00529         break;
00530       }
00531       if(!iceid) {
00532         error("invalid command line argument: server login type");
00533         error("you must specify a server first with the -s option");
00534         break;
00535       }
00536       int ltype;
00537       if(strncasecmp(optarg,"ice1",4)==0)
00538         ltype = SHOUT_PROTOCOL_XAUDIOCAST;
00539       else if(strncasecmp(optarg,"ice2",4)==0)
00540         ltype = SHOUT_PROTOCOL_HTTP;
00541       else if(strncasecmp(optarg,"icy",4)==0)
00542         ltype = SHOUT_PROTOCOL_ICY;
00543       else {
00544         error("unrecognized login type: %s",optarg);
00545         error("please use one of the following:");
00546         error("ice1 = icecast 1, darwin and litestream");
00547         error("ice2 = icecast 2 server");
00548         error("icy  = shoutcast server");
00549         break;
00550       }
00551       ice = outch->get_ice(iceid);
00552       ice->login(ltype);
00553       act("CLI: login type set to %s",optarg);
00554       break;
00555 
00556     case 'U':
00557       if(!outch) {
00558         error("invalid command line argument: server password");
00559         error("you must specify a codec first with the -e option");
00560         break;
00561       }
00562       if(!iceid) {
00563         error("invalid command line argument: server password");
00564         error("you must specify a server first with the -s option");
00565         break;
00566       }
00567       ice = outch->get_ice(iceid);
00568       ice->user(optarg);
00569       act("CLI: stream username: %s",optarg);
00570       break;
00571       
00572     case 'p':
00573       if(!outch) {
00574         error("invalid command line argument: server password");
00575         error("you must specify a codec first with the -e option");
00576         break;
00577       }
00578       if(!iceid) {
00579         error("invalid command line argument: server password");
00580         error("you must specify a server first with the -s option");
00581         break;
00582       }
00583       ice = outch->get_ice(iceid);
00584       ice->pass(optarg);
00585       act("CLI: stream password set");
00586       break;
00587 
00588     case 'm':
00589       if(!outch) {
00590         error("invalid command line argument: server mountpoint");
00591         error("you must specify a codec first with the -e option");
00592         break;
00593       }
00594       if(!iceid) {
00595         error("invalid command line argument: server mountpoint");
00596         error("you must specify a server first with the -s option");
00597         break;
00598       }
00599       ice = outch->get_ice(iceid);
00600       ice->mount(optarg);
00601       act("CLI: stream mountpoint %s",ice->mount());
00602       break;
00603 
00604     case 'n':
00605       if(!outch) {
00606         error("invalid command line argument: stream name");
00607         error("you must specify a codec first with the -e option");
00608         break;
00609       }
00610       if(!iceid) {
00611         error("invalid command line argument: stream name");
00612         error("you must specify a server first with the -s option");
00613         break;
00614       }
00615       ice = outch->get_ice(iceid);
00616       ice->name(optarg);
00617       act("CLI: stream descriptive name: %s",ice->name());
00618       break;
00619 
00620     case 'u':
00621       if(!outch) {
00622         error("CLI: invalid command line argument: stream url");
00623         error("you must specify a codec first with the -e option");
00624         break;
00625       }
00626       if(!iceid) {
00627         error("CLI: invalid command line argument: stream url");
00628         error("you must specify a server first with the -s option");
00629         break;
00630       }
00631       ice = outch->get_ice(iceid);
00632       ice->url(optarg);
00633       act("CLI: stream descriptive: url %s",ice->url());
00634       break;
00635 
00636     case 'd':
00637       if(!outch) {
00638         error("CLI: invalid command line argument: stream description");
00639         error("you must specify a codec first with the -e option");
00640         break;
00641       }
00642       if(!iceid) {
00643         error("CLI: invalid command line argument: stream description");
00644         error("you must specify a server first with the -s option");
00645         break;
00646       }
00647       ice = outch->get_ice(iceid);
00648       ice->desc(optarg);
00649       act("CLI: stream description: %s",ice->desc());
00650       break;
00651 
00652     case 1:
00653       act("CLI: queue %s on channel %i",optarg,number);
00654       if(!mix->chan[number])
00655         if(!mix->create_channel(number)) {
00656           error("CLI: can't create channel %i",number);
00657           break;
00658         } else {
00659           notice("CLI: created channel %i",number);
00660           mix->set_playmode(number,playmode);
00661         }
00662       if(!mix->add_to_playlist(number,optarg))
00663         error("CLI: can't add %s to channel %1",optarg,number);
00664       break;
00665 
00666     default:
00667       break;
00668     }
00669   } while(res > 0);  
00670   return true;
00671 }
00672 
00673 bool check_config() {
00674   /* checking config directory
00675      TODO: FIXME PLEASE */
00676   char temp[MAX_PATH_SIZE];
00677   char *home = getenv("HOME");
00678   sprintf(temp,"%s/.muse",home);
00679   mkdir(temp,0744);
00680   return(true);
00681 }
00682 
00683 void *mainLoop(void *) {
00684   while(!mix->quit)
00685     mix->cafudda();
00686    /* simple isn't it? */
00687 }
00688 
00689 int main(int argc, char **argv) {
00690 
00691   notice(version,PACKAGE,VERSION);
00692   act("by Denis \"jaromil\" Rojo http://rastasoft.org");
00693   act("--");
00694 
00695   /* register signal traps */
00696   if (signal (SIGINT, quitproc) == SIG_ERR) {
00697     error ("Couldn't install SIGINT handler"); exit (0);
00698   }
00699 
00700   if (signal (SIGQUIT, quitproc) == SIG_ERR) {
00701     error ("Couldn't install SIGQUIT handler"); exit (0);
00702   }
00703 
00704   if (signal (SIGTERM, quitproc) == SIG_ERR) {
00705     error ("Couldn't install SIGTERM handler"); exit (0);
00706   }
00707   got_sigpipe = false;
00708   if (signal (SIGPIPE, fsigpipe) == SIG_ERR) {
00709     error ("Couldn't install SIGPIPE handler"); exit (0);
00710   }
00711   
00712   mix = new Stream_mixer();
00713 #ifdef HAVE_SCHEDULER
00714   rscheduler = new Scheduler_xml( sched_file_path() );
00715   mix->register_sched( rscheduler );
00716   rscheduler->register_mixer(mix);
00717   rscheduler->lock();
00718   rscheduler->start();
00719   rscheduler->wait();
00720   rscheduler->unlock();
00721   //rscheduler->play();
00722 #endif
00723     
00724   if( !take_args(argc, argv) ) goto QUIT;
00725 
00726   check_config();
00727 
00728   // setup soundcard
00729   mix->set_lineout(dspout);
00730   mix->set_live(micrec);
00731   
00732   //  if(!snddev) {
00733   //    warning("no soundcard found");
00734   //    act("line-in and speaker out deactivated");
00735   //  }
00736 
00737   if(thegui==GTK1 || thegui==GTK2)
00738     if(!getenv("DISPLAY")) { /* no graphical environment */
00739       error("DISPLAY not found, falling back to console");
00740       thegui=-1;
00741     }
00742   
00743   if(thegui<0) { /* select default gui */
00744     if(getenv("DISPLAY")) { /* we are in a graphical environment */
00745 #ifdef GUI_NIGHTOLO2
00746       thegui=GTK2;
00747 #elif GUI_NIGHTOLO
00748       thegui=GTK1;
00749 #endif
00750     }
00751 #ifdef GUI_CARBON
00752       thegui=CARBON;
00753 #endif
00754     if(thegui<0) { /* if GUI is still not selected */
00755 #ifdef GUI_RUBIK
00756       thegui = NCURSES;
00757 #else
00758       thegui=CLI;
00759 #endif
00760     }
00761   }
00762 
00763   switch(thegui) {
00764   case GTK1:
00765 #ifdef GUI_NIGHTOLO
00766     notice("spawning the GTK-1.2 GUI");
00767     act("by nightolo <night@freaknet.org>");
00768     warning("GTK-1.2 should be upgraded to GTK 2 on your system");
00769     warning("this old version of the interface is much unstable");
00770     gui = new GTK_GUI(argc,argv,mix);
00771 #else
00772     error("the Gtk-1.2 interface is not compiled in");
00773 #endif
00774     break;
00775   case GTK2:
00776 #ifdef GUI_NIGHTOLO2
00777     notice("spawning the GTK-2 GUI");
00778     act("by Antonino \"nightolo\" Radici <night@freaknet.org>");
00779     gui = new GTK2_GUI(argc,argv,mix);
00780 #else
00781     error("the Gtk2 interface is not compiled in");
00782 #endif
00783     break;
00784   case NCURSES:
00785 #ifdef GUI_RUBIK
00786     notice("spawning the NCURSES console user interface");
00787     act("by Luca \"rubik\" Profico <rubik@olografix.org>");
00788 
00789     gui = new NCURSES_GUI(argc,argv,mix);
00790     MuseSetLog("muse.log");
00791 #else
00792     error("the ncurses console interface is not compiled in");
00793 #endif
00794     break;
00795   case CARBON:
00796 #ifdef GUI_CARBON
00797     notice("spawning the CARBON user interface");
00798         act("by Andrea \"xant\" Guzzo <xant@xant.net>");
00799         gui = new CARBON_GUI(argc,argv,mix);
00800 #else
00801         error("the carbon interface is not compiled in");
00802 #endif
00803     break;
00804   default:
00805     notice("using commandline interface (non interactive)");
00806     thegui=CLI;
00807   }
00808 
00809   if(thegui<0) error("no interface selected, this should never happen");
00810  
00811   if(thegui!=CLI) {
00812 
00813         gui->start();
00814         mix->register_gui(gui);
00815     set_guimsg(gui);
00816     notice("%s version %s",PACKAGE,VERSION);
00817   }
00818 
00819   /* apply configuration and startup all registered encoders */
00820   outch = (OutChannel*)mix->outchans.begin();
00821   while(outch) {
00822     
00823     if( (outch->icelist.len() == 0)
00824         && !outch->fd) { /* check if its worth to encode */
00825       error("codec %s [%u] has no server neither filedump configured",
00826             outch->name,outch->id);
00827       mix->delete_enc(outch->id);
00828       error("encoder removed");
00829       
00830     } else if(mix->apply_enc( outch->id )) outch->start();
00831 
00832     if(!outch) break;
00833     outch = (OutChannel*) outch->next;
00834   }
00835 
00836   if(thegui==CLI) { /* CLI interface logics ======================= */
00837   
00838     int c;
00839     for(c=0;c<MAX_CHANNELS;c++)
00840       if(mix->chan[c])
00841         if(!mix->set_channel(c,1))
00842           error("CLI: error in set_channel(%i,1)",c);     
00843         else
00844           if(!mix->play_channel(c))
00845             error("CLI: error in play_channel(%i)",c);
00846           else
00847             has_playlist = true;
00848   } /* === END CLI === */
00849 
00850   if((!has_playlist && !micrec) && (thegui==CLI)) {
00851     warning("nothing to play, you must specify at least songs or live input");
00852     act("see --help switch for more information");
00853     goto QUIT;
00854   }
00855 #ifndef GUI_CARBON
00856   /* MAIN LOOP */
00857   mainLoop(NULL);
00858 #else
00859   /* XXX - this hack is needed because carbon event model,
00860    * in a multithreaded environment, sends GUI events just to the main thread eventloop 
00861    * and not to 'dispatched' ones. So we have to run the eventloop in the main thread
00862    */
00863   EventLoopRef eventLoop;
00864   pthread_t mainThread;
00865   pthread_create(&mainThread, NULL, &mainLoop, NULL);
00866   RunApplicationEventLoop();
00867   if(!mix->quit) quitproc(2); /* if user quitted through the mac menu */
00868   pthread_join(mainThread,NULL);
00869 #endif
00870  
00871   QUIT:
00872   notice("quitting MuSE");
00873 
00874   if(thegui!=CLI) gui->quit = true;
00875 
00876   set_guimsg(NULL);
00877   
00878 #ifdef HAVE_SCHEDULER
00879   rscheduler->stop(); 
00880   rscheduler->quit = true; 
00881   jsleep(0,50);
00882   delete rscheduler; rscheduler = NULL;
00883 #endif
00884   if(mix) {
00885     act("stopping mixer...");  
00886   /* piglia o'tiemp e sputa in terra
00887      senza fa' troppo casino a segnala' ai canali */
00888     jsleep(0,50);
00889     delete mix;
00890   }
00891 
00892   if(thegui!=CLI) {
00893     act("quitting graphic interface");
00894     delete gui;
00895   }
00896   
00897   act("cya on http://muse.dyne.org");
00898   MuseCloseLog();
00899   exit(0);
00900 }
00901 
00902 /* signal handling */
00903 void quitproc (int Sig) {
00904   func("received signal %u on process %u",Sig,getpid());
00905   if(thegui!=CLI) gui->quit = true;
00906   mix->quit = true; 
00907 #ifdef GUI_CARBON
00908    QuitApplicationEventLoop();
00909 #endif
00910 }
00911 
00912 void fsigpipe (int Sig) {
00913   warning("received signal SIGPIPE (%u) on process %u",Sig,getpid());
00914   got_sigpipe = true;
00915 }