inchannels.cpp Source File

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