Main Page   Modules   Class Hierarchy   Compound List   File List   Compound Members   File Members  

inchannels.cpp

00001 /* MuSE - Multiple Streaming Engine
00002  * Copyright (C) 2000-2002 Denis Roio aka jaromil <jaromil@dyne.org>
00003  *
00004  * This source code is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Public License as published 
00006  * by the Free Software Foundation; either version 2 of the License,
00007  * or (at your option) any later version.
00008  *
00009  * This source code is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00012  * Please refer to the GNU Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Public License along with
00015  * this source code; if not, write to:
00016  * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  
00018 "$Id: inchannels.cpp,v 1.13 2004/12/13 00:26:37 jaromil Exp $"
00019  
00020  different classes for different IN channels
00021  they are instantiated and used by the Stream_mixer class (jmixer.cpp)
00022 
00023 */
00024 
00025 #include <iostream>
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <unistd.h>
00029 #include <string.h>
00030 #include <sys/types.h>
00031 #include <sys/wait.h>
00032 #include <signal.h>
00033 
00034 /* mixing and audioprocessing algorithms*/
00035 #include <audioproc.h>
00036 
00037 #include <jutils.h>
00038 #include <inchannels.h>
00039 #include <config.h>
00040 #include <generic.h>
00041 
00042 #ifdef HAVE_VORBIS
00043 #include <dec_ogg.h>
00044 #endif
00045 #ifdef HAVE_SNDFILE
00046 #include <dec_snd.h>
00047 #endif
00048 #ifdef HAVE_JACK
00049 #include <dec_jack.h>
00050 #endif
00051 #include <dec_mp3.h>
00052 
00053 #include "httpstream.h"
00054 
00055 
00056 //#ifdef DEBUG
00057 #define PARADEC if(!dec) error("%s:%s %i :: decoder is NULL",__FILE__,__FUNCTION__,__LINE__);
00058 //#endif
00059 
00060 /* ----- Parent Class Channel ----- */
00061 
00062 typedef void* (kickoff)(void*);
00063 
00064 Channel::Channel() {
00065   func("Channel::Channel()");
00066   volume = 1.0;
00067   speed = 100;
00068   time.h = time.m = time.s = 0;
00069   position = time.f = 0.0;
00070   state = 0.0;
00071   playmode = PLAYMODE_PLAY;
00072   opened = false;
00073   on = false;
00074   update = false;
00075   running = false;
00076   quit = true;
00077   idle = true;
00078 
00079   _thread_init();
00080 
00081   // setup the pipe
00082   erbapipa = new Pipe(IN_PIPESIZE);
00083   erbapipa->set_output_type("mix_int16_to_int32");
00084   // blocking input and output, default timeout is 200 ms
00085   erbapipa->set_block(true,true);
00086   erbapipa->set_block_timeout(400,200);
00087 
00088   playlist = new Playlist();
00089   dec = NULL;
00090   fill_prev_smp = true;
00091   lcd[0] = '\0';
00092 }
00093 
00094 Channel::~Channel() {
00095   func("Channel::~Channel()");
00096 
00097   /* paranoia */
00098   //stop();
00099   //  clean();
00100   quit = true;
00101   
00102   while(running) jsleep(0,20);
00103 
00104   /* clean up specific channel implementation */
00105 
00106   delete erbapipa;
00107   delete playlist;
00108   if(dec) delete dec;
00109 
00110   _thread_destroy();
00111 }
00112 
00113 void Channel::run() {
00114 
00115   IN_DATATYPE *buff; // pointer to buffers to pass them around
00116   lock();
00117   func("InChanThread! here i am");
00118   running = true;
00119   unlock();
00120   signal(); // signal to the parent thread we are born!
00121 
00122   quit = false;
00123 
00124   while(!quit) {
00125     
00126     if(on) {
00127       idle = false;
00128       PARADEC
00129       dec->lock();
00130       /* now call get_audio() which
00131          returns the *IN_DATATYPE pointer to filled buffer
00132          setting up the following parameters:
00133          dec->state = 0.0-1.0 is the position of the stream
00134                       2.0 means end of the stream
00135                       3.0 means error decoding stream
00136          dec->frames  is updated with number of decoded 16bit frames (double if stereo)
00137          dec->samplerate and dec->channels tell about the audio format */
00138       buff = dec->get_audio();
00139       dec->unlock();
00140     /* then call resample() which sets up:
00141        frames = number of 16bit sound values
00142        and returns *IN_DATATYPE pointing to the resampled buffer */
00143       if(buff) {
00144         buff = resample(buff);
00145 
00146         /* at last pushes it up into the pipe
00147            bytes are samples<<2 being the audio 16bit stereo */
00148         erbapipa->write(frames<<1,buff);
00149 
00150         /* then calculates the position and time */
00151         if(dec->seekable) state = upd_time();
00152 
00153       } else /* if get_audio returns NULL then is eos or error */
00154         if(dec->eos) upd_eos();
00155         else if(dec->err) upd_err();
00156         else { // nothing comes out but we hang on
00157           //      error("unknown state on %s channel",dec->name);
00158           //      report(); state = 0.0;
00159           jsleep(0,20);
00160         }
00161 
00162     } else { // if(on)
00163 
00164       // just hang on
00165       idle = true;
00166       jsleep(0,20);
00167       
00168     }
00169     
00170   } // while(!quit)
00171   running = false;
00172 }
00173 
00174 IN_DATATYPE *Channel::resample(IN_DATATYPE *audio) {
00175 
00176   /* there is no previous samples saved 
00177      fill in with the first */
00178   if(fill_prev_smp) {
00179     prev_smp[0] = audio[0];
00180     prev_smp[1] = audio[1];
00181     prev_smp[2] = audio[2];
00182     prev_smp[3] = audio[3];
00183     fill_prev_smp = false;
00184     //    erbapipa->flush();
00185   }
00186 
00187   frames = dec->frames;
00188   frames = (*munch)(buffo,audio,prev_smp,frames,volume);
00189 
00190   /* save last part of the chunk
00191      for the next resampling */
00192   prev_smp[0] = audio[dec->frames-4];
00193   prev_smp[1] = audio[dec->frames-3];
00194   prev_smp[2] = audio[dec->frames-2];
00195   prev_smp[3] = audio[dec->frames-1];
00196 
00197   return(buffo);
00198 }
00199 
00200 bool Channel::play() {
00201   if(on) return(true);
00202 
00203   if(!running) {
00204     error(_("%i:%s %s channel thread not launched"),
00205           __LINE__,__FILE__,__FUNCTION__);
00206     return(false);
00207   }
00208 
00209   if(!opened) {
00210     Url *url;
00211     warning(_("Channel::play() : no song loaded"));
00212     url = (Url*) playlist->selected();
00213     if(!url) {
00214       warning(_("Channel::play() : no song selected in playlist"));
00215       url = (Url*)playlist->begin();
00216       if(!url) {
00217         error(_("Channel::play() : playlist is void"));
00218         return(false);
00219       }
00220     }
00221 
00222     if( !load( url->path ) ) {
00223       error(_("Channel::play() : can't load %s"),url->path);
00224       return(false);
00225     } else url->sel(true);
00226   }
00227 
00228   if(time.f!=position) {
00229     pos(position);
00230   } else fill_prev_smp = true;
00231 
00232   on = true;
00233   return(on);
00234 }
00235 
00236 bool Channel::stop() {
00237   //  lock();
00238   on = false;
00239   if(opened) {
00240     //  unlock();
00241     pos(0.0);
00242     state = 0.0;
00243     erbapipa->flush();
00244     fill_prev_smp = true;
00245   }
00246   return(!on);
00247 }
00248 
00249 int Channel::load(char *file) {
00250   MuseDec *ndec = NULL;
00251   char tmp[256];
00252   int res;
00253   /* returns:
00254      0 = error
00255      1 = stream is seakable
00256      2 = stream is not seekable  */ 
00257   hstream cod = HS_NONE;
00258 
00259   /* parse supported file types */
00260 
00261   snprintf(tmp,256,"%s",file);
00262   
00263   if (strstr(file, "http://")) {
00264     cod = stream_detect(file);
00265   }
00266 
00267   if(strncasecmp(file+strlen(file)-4,".ogg",4)==0 || cod==HS_OGG) {
00268 #ifdef HAVE_VORBIS
00269     func("creating Ogg decoder");
00270     ndec = new MuseDecOgg();
00271 #else
00272     error(_("Can't open OggVorbis (support not compiled)"));
00273 #endif
00274   }
00275   if(strncasecmp(file+strlen(file)-4,".mp3",4)==0 || cod==HS_MP3) {
00276     func("creating Mp3 decoder");
00277     ndec = new MuseDecMp3();
00278   }
00279   // pallotron: aggiungo lo string compare per i formati sndfile
00280   if(strncasecmp(file+strlen(file)-4,".wav",4)==0
00281      || strncasecmp(file+strlen(file)-4,".aif",4)==0
00282      || strncasecmp(file+strlen(file)-5,".aiff",4)==0
00283      || strncasecmp(file+strlen(file)-4,".snd",4)==0
00284      || strncasecmp(file+strlen(file)-3,".au",4)==0
00285      || strncasecmp(file+strlen(file)-4,".raw",4)==0
00286      || strncasecmp(file+strlen(file)-4,".paf",4)==0
00287      || strncasecmp(file+strlen(file)-4,".iff",4)==0
00288      || strncasecmp(file+strlen(file)-4,".svx",4)==0
00289      || strncasecmp(file+strlen(file)-3,".sf",4)==0
00290      || strncasecmp(file+strlen(file)-4,".voc",4)==0
00291      || strncasecmp(file+strlen(file)-4,".w64",4)==0
00292      || strncasecmp(file+strlen(file)-4,".pvf",4)==0
00293      || strncasecmp(file+strlen(file)-3,".xi",4)==0
00294      || strncasecmp(file+strlen(file)-4,".htk",4)==0
00295      || strncasecmp(file+strlen(file)-4,".mat",4)==0
00296      ) {
00297 #ifdef HAVE_SNDFILE
00298     func("creating LibSndFile decoder");
00299     ndec = new MuseDecSndFile();
00300 #else
00301     error(_("Can't open sound file (support not compiled)"));
00302 #endif
00303   }
00304 
00305   if(strncasecmp(file,"jack://",7)==0) {
00306 #ifdef HAVE_JACK
00307     func("creating Jack Audio Daemon input client");
00308     // setup the filename with a MuSE___ prefix
00309     // for the jack client name
00310     //    file[0]='M';file[1]='u';file[2]='S';file[3]='E';
00311     //    file[4]='_';file[5]='_';file[6]='_';
00312     ndec = new MuseDecJack();
00313 
00314     snprintf(tmp,256,"MuSE_in_%s",&file[7]);
00315   
00316 #else
00317     error(_("Jack audio daemon support is not compiled in this version of MuSE"));
00318 #endif
00319   }
00320   
00321   if(!ndec) {
00322     error(_("Can't open %s (unrecognized extension)"),file);
00323     return(0);
00324   }
00325 
00326   lock();
00327 
00328   ndec->lock();
00329   res = ndec->load(tmp); // try to load the file/stream into the decoder
00330   ndec->unlock();
00331 
00332   if(!res) { // there is an error: we keep everything as it is
00333     error(_("decoder load returns error"),file);
00334     unlock();
00335     delete ndec;
00336     return(0);
00337   }
00338   
00339   res = set_resampler(ndec);
00340 
00341   if(!res) {
00342     error(_("invalid input samplerate %u"),ndec->samplerate);
00343     unlock();
00344     delete ndec;
00345     return(0);
00346   }
00347 
00348   // decoder succesfully opened the file
00349   // here if res == 2 then we have a stream
00350   // TODO: oggvorbis stream playing using libcurl
00351   if(dec) delete dec; // delete the old decoder if present
00352   dec = ndec;
00353   opened = true;
00354 
00355   res = (dec->seekable)?1:2;
00356   seekable = (res==1) ? true : false;
00357   state = 0.0;
00358   
00359   unlock();
00360 
00361   notice(_("loaded %s"),file);
00362   if(dec->bitrate)
00363     notice("%s %s %iHz %s %iKb/s",
00364            dec->name,
00365            (dec->seekable) ? "file" : "stream",
00366            dec->samplerate,
00367            (dec->channels==1) ? "mono" : "stereo",
00368            dec->bitrate);
00369   else
00370     notice("%s %s %iHz %s",
00371            dec->name,
00372            (dec->seekable) ? "file" : "stream",
00373            dec->samplerate,
00374            (dec->channels==1) ? "mono" : "stereo");
00375            
00376   return res;
00377 }
00378      
00379 bool Channel::pos(float pos) {
00380   PARADEC
00381   if(!dec->seekable) return false;
00382   pos = (pos<0.0) ? 0.0 : (pos>1.0) ? 1.1 : pos;
00383   dec->lock();
00384   if(!dec->seek(pos))
00385     error(_("error seeking decoder position to %f"),position);
00386   else
00387     position = time.f = pos;
00388   dec->unlock();
00389   return true;
00390 }
00391 
00392 void Channel::clean() {
00393   on = false;
00394   //  dec->lock();
00395   //  dec->clean();
00396   //  dec->unlock();
00397   opened = false;
00398   while(!idle) jsleep(0,20);
00399   if(dec) delete dec;
00400   dec = NULL;
00401 }
00402 
00403 bool Channel::set_resampler(MuseDec *ndec) {
00404   switch(ndec->samplerate) {
00405   case 44100:
00406     if(ndec->channels==2) munch = resample_stereo_44;
00407     else munch = resample_mono_44;
00408     break;
00409   case 32000:
00410     if(ndec->channels==2) munch = resample_stereo_32;
00411     else munch = resample_mono_32;
00412     break;
00413   case 22050:
00414     if(ndec->channels==2) munch = resample_stereo_22;
00415     else munch = resample_mono_22;
00416     break;
00417   case 16000:
00418     if(ndec->channels==2) munch = resample_stereo_16;
00419     else munch = resample_mono_16;
00420     break;
00421   default:
00422     warning(_("Can't mix sound at %uhz"),
00423             ndec->samplerate);
00424     return(false);
00425   }
00426   return(true);
00427 }
00428 
00429 
00430 float Channel::upd_time() {
00431   PARADEC
00432   float res;
00433 
00434   /* calculate the float 0.0-1.0 position on stream */
00435   res = (float)dec->framepos/(float)dec->frametot;
00436 
00437 
00438   /* calculate the time */
00439   //  if( ((res-time.f)>0.003) || (time.f-res)>0.003) {
00440     time.f = res;
00441     secs = dec->framepos / dec->fps;
00442     //    func("secs %i",secs);
00443     if(secs>3600) {
00444       time.h = (int) secs / 3600;
00445       secs -= time.h*3600;
00446     } else time.h = 0;
00447     if(secs>60) {
00448       time.m = (int) secs / 60;
00449       secs -= time.m*60;
00450     } else time.m = 0;
00451     time.s = (int) secs;
00452     update = true;
00453     //  }
00454 
00455   return(res);
00456 }
00457 
00458 void Channel::skip() {
00459   switch(playmode) {
00460   case PLAYMODE_PLAY:
00461     stop();
00462     break;
00463   case PLAYMODE_LOOP:
00464     pos(0.0);
00465     break;
00466   case PLAYMODE_CONT:
00467     Url *n;
00468     stop();
00469     n = (Url*)playlist->selected();
00470     if(n) do {
00471       n->sel(false); n = (Url*)n->next;
00472       if(!n) n = (Url*)playlist->begin();
00473       if(!n) break;
00474       n->sel(true);
00475     } while( ! load(n->path) );
00476     if(n) {
00477       play();
00478       update = true;
00479     }
00480     break;
00481   default: break;
00482   }
00483 }
00484 
00485 /* called on end of stream, manages playmode */
00486 void Channel::upd_eos() {
00487   PARADEC
00488     if(!dec->eos) return;
00489   func(_("End of %s on %s playing for %i:%i:%i"),
00490        (seekable)?"stream":"file",dec->name,
00491        time.h,time.m,time.s);
00492   skip();
00493   dec->eos = false;
00494 }
00495 
00496 void Channel::upd_err() {
00497   PARADEC
00498     if(!dec->err) return;
00499   error(_("error on %s, skipping %s"),
00500         dec->name,(seekable)?_("stream"):_("file"));
00501   report();
00502   skip();
00503   dec->err = false;
00504 }
00505 
00506 /* ----- LiveIN DSP Channel ----- */
00507 
00508 LiveIn::LiveIn() { 
00509   on = false;
00510   gotin = NULL;
00511 }
00512 
00513 void LiveIn::init(int smpr, int chans, int *thedsp) {
00514   dsp = thedsp;
00515   sample_rate = smpr;
00516   channels = chans;
00517 
00518   /*
00519   num_samples=(int)((sample_rate*BUF_SIZE)/(sample_rate<<1));
00520   opt = (num_samples*channels);
00521   */
00522 
00523   gotin = (IN_DATATYPE*)malloc((MIX_CHUNK<<2) +128);
00524 }
00525 
00526 LiveIn::~LiveIn() {
00527   if(gotin) free(gotin);
00528 }
00529 
00530 int LiveIn::mix(int *mixpcm) {
00531   int res;
00532 
00533   res = get_audio();
00534   mixxx_stereo_44_novol(mixpcm,gotin,res);
00535 
00536   return(res);
00537 }
00538 
00539 
00540 int LiveIn::get_audio() {
00541   int res;
00542 
00543   do {res = read(*dsp,gotin,MIX_CHUNK<<2);} while (res==-1 && errno==EINTR);
00544   return(res>>2);
00545 }
00546 
00547 
00548 /* thread stuff */
00549 
00550 void Channel::_thread_init() {
00551 
00552   func("Channel::thread_init()");
00553   if(pthread_mutex_init (&_mutex,NULL) == -1)
00554     error("error initializing POSIX thread mutex");
00555   if(pthread_cond_init (&_cond, NULL) == -1)
00556     error("error initializing POSIX thread condition"); 
00557   if(pthread_attr_init (&_attr) == -1)
00558     error("error initializing POSIX thread attribute");
00559   
00560   /* set the thread as detached
00561      see: man pthread_attr_init(3) */
00562   pthread_attr_setdetachstate(&_attr,PTHREAD_CREATE_DETACHED);
00563 
00564 }
00565 
00566 void Channel::_thread_destroy() {
00567   opened = false;  
00568 
00569   /* we signal and then we check the thread
00570      exited by locking the conditional */
00571   while(running) {
00572     signal();
00573     lock(); unlock();
00574   }
00575 
00576   if(pthread_mutex_destroy(&_mutex) == -1)
00577     error("error destroying POSIX thread mutex");
00578   if(pthread_cond_destroy(&_cond) == -1)
00579     error("error destroying POSIX thread condition");
00580   if(pthread_attr_destroy(&_attr) == -1)
00581     error("error destroying POSIX thread attribute");
00582 }
00583 
00584 
00585 /* here for debugging purposes */
00586 void Channel::report() {
00587 
00588   func("Channel | %s | %s | %s | %s |",
00589        (opened)?"opened":" ",
00590          (running)?"running":" ",
00591          (on)?"on":"off",
00592          (seekable)?"seekable":" ");
00593 
00594   func("vol %.2f pos %.2f lcd[%s]",volume,position,lcd);
00595   func("state %.2f playmode %s",state,
00596       (playmode==PLAYMODE_PLAY) ? "PLAY" :
00597       (playmode==PLAYMODE_LOOP) ? "LOOP" :
00598       (playmode==PLAYMODE_CONT) ? "CONT" :
00599       "ERROR");
00600   if (dec) {
00601     func("time: %i:%i:%i framepos %i frametot %i",
00602         time.h, time.m, time.s, dec->framepos,dec->frametot);
00603     func("samplerate %i channels %i bitrate %i",
00604         dec->samplerate,dec->channels,dec->bitrate);
00605     func("frames (16bit) %i",dec->frames);
00606   } else {
00607     func("time: %i:%i:%i ", time.h, time.m, time.s);
00608   }
00609 }
00610 

Generated on Thu Dec 16 12:28:21 2004 for MuSE by doxygen1.3