00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
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
00051 #define PARADEC if(!dec) error("%s:%s %i :: decoder is NULL",__FILE__,__FUNCTION__,__LINE__);
00052
00053
00054
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
00084
00085
00086 quit = true;
00087
00088 while(running) jsleep(0,20);
00089
00090
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;
00102 lock();
00103 func("InChanThread! here i am");
00104 running = true;
00105 unlock();
00106 signal();
00107
00108 quit = false;
00109
00110 while(!quit) {
00111
00112 if(on) {
00113 PARADEC
00114 dec->lock();
00115
00116
00117
00118
00119
00120
00121
00122
00123 buff = dec->get_audio();
00124 dec->unlock();
00125
00126
00127
00128 if(buff) {
00129 buff = resample(buff);
00130
00131
00132 while( erbapipa->write
00133 (samples<<2,buff) <0
00134 && !quit) jsleep(0,20);
00135
00136 if(dec->seekable) state = upd_time();
00137
00138 } else
00139 if(dec->eos) upd_eos();
00140 else if(dec->err) upd_err();
00141 else {
00142 error("unknown state on %s channel",dec->name);
00143 report(); state = 0.0;
00144 }
00145
00146 } else {
00147
00148
00149 jsleep(0,20);
00150
00151 }
00152
00153 }
00154 running = false;
00155 }
00156
00157 IN_DATATYPE *Channel::resample(IN_DATATYPE *audio) {
00158
00159
00160
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
00168 }
00169
00170 frames = dec->frames;
00171 frames = (*munch)(buffo,audio,prev_smp,frames,volume);
00172 samples = frames/2;
00173
00174
00175
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
00222 on = false;
00223 if(opened) {
00224
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
00237
00238
00239
00240
00241
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
00256
00257
00258
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);
00273 ndec->unlock();
00274
00275 if(!res) {
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
00292
00293
00294 if(dec) delete dec;
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
00329
00330
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
00368 res = (float)dec->framepos/(float)dec->frametot;
00369
00370
00371 if( ((res-time.f)>0.003) || (time.f-res)>0.003) {
00372 time.f = res;
00373 secs = dec->framepos / dec->fps;
00374
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
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
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
00452
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
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
00493
00494 pthread_attr_setdetachstate(&_attr,PTHREAD_CREATE_DETACHED);
00495
00496 }
00497
00498 void Channel::_thread_destroy() {
00499 opened = false;
00500
00501
00502
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
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 }