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

inchannels.cpp

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