decoder-ogg.c
branchtrunk
changeset 33 65ed49cbc08b
parent 25 887faebaba0a
child 34 afc13760179b
equal deleted inserted replaced
32:cea1b4f741be 33:65ed49cbc08b
   210   return Abort(true);
   210   return Abort(true);
   211 }
   211 }
   212 
   212 
   213 // --- cOggDecoder -------------------------------------------------------------
   213 // --- cOggDecoder -------------------------------------------------------------
   214 
   214 
   215 cOggDecoder::cOggDecoder(const char *Filename)
   215 cOggDecoder::cOggDecoder(const char *Filename, bool preinit)
   216 :cDecoder(Filename)
   216 :cDecoder(Filename)
   217 ,file(Filename)
   217 {
   218 ,info(&file)
   218   file=0; info=0; pcm=0;
   219 {
   219   if(preinit) {
   220   pcm=0;
   220     file=new cOggFile(Filename);
       
   221     info=new cOggInfo(file);
       
   222   }
   221 }
   223 }
   222 
   224 
   223 cOggDecoder::~cOggDecoder()
   225 cOggDecoder::~cOggDecoder()
   224 {
   226 {
   225   Clean();
   227   Clean();
       
   228   delete info;
       
   229   delete file;
   226 }
   230 }
   227 
   231 
   228 bool cOggDecoder::Valid(void)
   232 bool cOggDecoder::Valid(void)
   229 {
   233 {
   230   bool res=false;
   234   bool res=false;
   231   if(TryLock()) {
   235   if(TryLock()) {
   232     if(file.Open(false)) res=true;
   236     if(file->Open(false)) res=true;
   233     Unlock();
   237     Unlock();
   234     }
   238     }
   235   return res;
   239   return res;
   236 }
   240 }
   237 
   241 
   238 cFileInfo *cOggDecoder::FileInfo(void)
   242 cFileInfo *cOggDecoder::FileInfo(void)
   239 {
   243 {
   240   cFileInfo *fi=0;
   244   cFileInfo *fi=0;
   241   if(file.HasInfo()) fi=&file;
   245   if(file->HasInfo()) fi=file;
   242   else if(TryLock()){
   246   else if(TryLock()){
   243     if(file.Open()) { fi=&file; file.Close(); }
   247     if(file->Open()) { fi=file; file->Close(); }
   244     Unlock();
   248     Unlock();
   245     }
   249     }
   246   return fi;
   250   return fi;
   247 }
   251 }
   248 
   252 
   249 cSongInfo *cOggDecoder::SongInfo(bool get)
   253 cSongInfo *cOggDecoder::SongInfo(bool get)
   250 {
   254 {
   251   cSongInfo *si=0;
   255   cSongInfo *si=0;
   252   if(info.HasInfo()) si=&info;
   256   if(info->HasInfo()) si=info;
   253   else if(get && TryLock()) {
   257   else if(get && TryLock()) {
   254     if(info.DoScan(false)) si=&info;
   258     if(info->DoScan(false)) si=info;
   255     Unlock();
   259     Unlock();
   256     }
   260     }
   257   return si;
   261   return si;
   258 }
   262 }
   259 
   263 
   260 cPlayInfo *cOggDecoder::PlayInfo(void)
   264 cPlayInfo *cOggDecoder::PlayInfo(void)
   261 {
   265 {
   262   if(playing) {
   266   if(playing) {
   263     pi.Index=index/1000;
   267     pi.Index=index/1000;
   264     pi.Total=info.Total;
   268     pi.Total=info->Total;
   265     return π
   269     return π
   266     }
   270     }
   267   return 0;
   271   return 0;
   268 }
   272 }
   269 
   273 
   276 
   280 
   277 bool cOggDecoder::Clean(void)
   281 bool cOggDecoder::Clean(void)
   278 {
   282 {
   279   playing=false;
   283   playing=false;
   280   delete pcm; pcm=0;
   284   delete pcm; pcm=0;
   281   file.Close();
   285   file->Close();
   282   return false;
   286   return false;
   283 }
   287 }
   284 
   288 
   285 #define SF_SAMPLES (sizeof(pcm->samples[0])/sizeof(mad_fixed_t))
   289 #define SF_SAMPLES (sizeof(pcm->samples[0])/sizeof(mad_fixed_t))
   286 
   290 
   287 bool cOggDecoder::Start(void)
   291 bool cOggDecoder::Start(void)
   288 {
   292 {
   289   Lock(true);
   293   Lock(true);
   290   Init(); playing=true;
   294   Init(); playing=true;
   291   if(file.Open() && info.DoScan(true)) {
   295   if(file->Open() && info->DoScan(true)) {
   292     d(printf("ogg: open rate=%d channels=%d seek=%d\n",
   296     d(printf("ogg: open rate=%d channels=%d seek=%d\n",
   293              info.SampleFreq,info.Channels,file.CanSeek()))
   297              info->SampleFreq,info->Channels,file->CanSeek()))
   294     if(info.Channels<=2) {
   298     if(info->Channels<=2) {
   295       Unlock();
   299       Unlock();
   296       return true;
   300       return true;
   297       }
   301       }
   298     else esyslog("ERROR: cannot play ogg file %s: more than 2 channels",filename);
   302     else esyslog("ERROR: cannot play ogg file %s: more than 2 channels",filename);
   299     }
   303     }
   322 struct Decode *cOggDecoder::Decode(void)
   326 struct Decode *cOggDecoder::Decode(void)
   323 {
   327 {
   324   Lock(); // this is released in Done()
   328   Lock(); // this is released in Done()
   325   if(playing) {
   329   if(playing) {
   326     short framebuff[2*SF_SAMPLES];
   330     short framebuff[2*SF_SAMPLES];
   327     int n=file.Stream(framebuff,SF_SAMPLES);
   331     int n=file->Stream(framebuff,SF_SAMPLES);
   328     if(n<0) return Done(dsError);
   332     if(n<0) return Done(dsError);
   329     if(n==0) return Done(dsEof);
   333     if(n==0) return Done(dsEof);
   330 
   334 
   331     pcm->samplerate=info.SampleFreq;
   335     pcm->samplerate=info->SampleFreq;
   332     pcm->channels=info.Channels;
   336     pcm->channels=info->Channels;
   333     n/=pcm->channels;
   337     n/=pcm->channels;
   334     pcm->length=n;
   338     pcm->length=n;
   335     index=file.IndexMs();
   339     index=file->IndexMs();
   336 
   340 
   337     short *data=framebuff;
   341     short *data=framebuff;
   338     mad_fixed_t *sam0=pcm->samples[0], *sam1=pcm->samples[1]; 
   342     mad_fixed_t *sam0=pcm->samples[0], *sam1=pcm->samples[1]; 
   339     const int s=MAD_F_FRACBITS+1-(sizeof(short)*8); // shift value for mad_fixed conversion
   343     const int s=MAD_F_FRACBITS+1-(sizeof(short)*8); // shift value for mad_fixed conversion
   340     if(pcm->channels>1) {
   344     if(pcm->channels>1) {
   345       }
   349       }
   346     else {
   350     else {
   347       for(; n>0 ; n--)
   351       for(; n>0 ; n--)
   348         *sam0++=(*data++) << s;
   352         *sam0++=(*data++) << s;
   349       }
   353       }
       
   354     info->InfoHook();
   350     return Done(dsPlay);
   355     return Done(dsPlay);
   351     }
   356     }
   352   return Done(dsError);
   357   return Done(dsError);
   353 }
   358 }
   354 
   359 
   355 bool cOggDecoder::Skip(int Seconds, float bsecs)
   360 bool cOggDecoder::Skip(int Seconds, float bsecs)
   356 {
   361 {
   357   Lock();
   362   Lock();
   358   bool res=false;
   363   bool res=false;
   359   if(playing && file.CanSeek()) {
   364   if(playing && file->CanSeek()) {
   360     float fsecs=(float)Seconds - bsecs;
   365     float fsecs=(float)Seconds - bsecs;
   361     long long newpos=file.IndexMs()+(long long)(fsecs*1000.0);
   366     long long newpos=file->IndexMs()+(long long)(fsecs*1000.0);
   362     if(newpos<0) newpos=0;
   367     if(newpos<0) newpos=0;
   363     d(printf("ogg: skip: secs=%d fsecs=%f current=%lld new=%lld\n",Seconds,fsecs,file.IndexMs(),newpos))
   368     d(printf("ogg: skip: secs=%d fsecs=%f current=%lld new=%lld\n",Seconds,fsecs,file->IndexMs(),newpos))
   364 
   369 
   365     newpos=file.Seek(newpos,false);
   370     newpos=file->Seek(newpos,false);
   366     if(newpos>=0) {
   371     if(newpos>=0) {
   367       index=file.IndexMs();
   372       index=file->IndexMs();
   368 #ifdef DEBUG
   373 #ifdef DEBUG
   369       int i=index/1000;
   374       int i=index/1000;
   370       printf("ogg: skipping to %02d:%02d\n",i/60,i%60);
   375       printf("ogg: skipping to %02d:%02d\n",i/60,i%60);
   371 #endif
   376 #endif
   372       res=true;
   377       res=true;