2 Copyright 2004-2006 Chris Tallon, Andreas Vogel
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP. If not, see <https://www.gnu.org/licenses/>.
20 #include "demuxeraudio.h"
22 #include "messagequeue.h"
27 #include "mediaplayer.h"
29 #include "audioplayer.h"
31 //how often do we retry if there is no data in stream
34 AudioPlayer * AudioPlayer::instance=NULL;
36 AudioPlayer * AudioPlayer::getInstance(Boxx * parent,bool create) {
37 // Log::getInstance()->log("AudioPlayer",Log::DEBUG,"getInstance for view %p, instance=%p",parent,instance);
38 AudioPlayer *np=instance;
39 if (! np && ! create) return NULL;
41 np=new AudioPlayer(parent);
45 instance->threadLock();
46 instance->frontend=parent;
47 instance->threadUnlock();
51 AudioPlayer::AudioPlayer(Boxx *parent) : afeed(this)
54 audio = Audio::getInstance();
55 logger = Log::getInstance();
56 vdr = VDR::getInstance();
57 logger->log("AudioPlayer", Log::DEBUG, "Audio player ctorI");
64 feederState=FEEDER_STOP;
68 Video::getInstance()->turnVideoOff();
72 currentPlaySequence=-1;
74 demuxer=new DemuxerAudio();
75 logger->log("AudioPlayer", Log::DEBUG, "Audio player ctorII");
76 if (!demuxer->init(this, audio, NULL, NULL, 0, DemuxerAudio::PACKET_SIZE+200,0))
78 logger->log("AudioPlayer", Log::ERR, "Demuxer failed to init");
82 logger->log("AudioPlayer", Log::DEBUG, "Audio player ctorIII");
86 logger->log("AudioPlayer", Log::DEBUG, "Audio player created");
90 AudioPlayer::~AudioPlayer()
92 if (threadBuffer) free(threadBuffer);
93 Timers::getInstance()->cancelTimer(this,1);
94 controlFeeder(FEEDER_STOP);
96 audio->setStreamType(Audio::MPEG2_PES);
102 void AudioPlayer::controlFeeder(int feederAction) {
103 logger->log("AudioPlayer",Log::DEBUG,"control feeder old=%d, new=%d",feederState,feederAction);
104 switch (feederAction) {
107 if (feederState == FEEDER_STOP)
112 if (feederState != FEEDER_STOP)
119 feederState=feederAction;
123 void AudioPlayer::run() {
124 if (playerRunnig) return;
130 void AudioPlayer::shutdown()
134 threadSignalNoLock();
135 //wait for the player thread to stop
136 logger->log("AudioPlayer",Log::DEBUG,"shutdown - warting for player thread to stop");
138 for (int loopcount=200;playerRunnig && loopcount > 0;loopcount--) {
142 logger->log("AudioPlayer",Log::ERR,"shutdown - unable to stop player within 10s");
149 bool AudioPlayer::isPlayerRunning() {
153 int AudioPlayer::setRequestedState(u1 rstate) {
158 rt=requestedSequence;
164 u1 AudioPlayer::getState() {
172 void AudioPlayer::setState(u1 s) {
178 //------------------- externally called functions --------------------------
179 int AudioPlayer::play(const MediaURI * u)
181 logger->log("AudioPlayer", Log::DEBUG, "play request for %s", u->getName());
188 rt=requestedSequence;
191 threadSignalNoLock();
195 int AudioPlayer::stop()
197 int rt= setRequestedState(S_STOP);
198 threadSignalNoLock();
202 int AudioPlayer::pause()
204 int rt= setRequestedState(S_PAUSE);
205 threadSignalNoLock();
208 int AudioPlayer::unpause()
210 int rt= setRequestedState(S_PLAY);
211 threadSignalNoLock();
215 int AudioPlayer::fastForward(){
216 if (! canPosition) return 1;
217 int rt=setRequestedState(S_FF);
218 threadSignalNoLock();
222 int AudioPlayer::fastBackward(){
223 if (! canPosition) return 1;
224 int rt=setRequestedState(S_BACK);
225 threadSignalNoLock();
228 int AudioPlayer::jumpToPercent(double percent){
229 if (! canPosition) return 1;
231 u4 fsec=demuxer->getSecondsFromLen(lenInBytes);
234 fsec=(u4)(((double)fsec*percent)/(double)100);
235 npos=demuxer->positionFromSeconds(fsec);
236 logger->log("AudioPlayer",Log::DEBUG,"new pos %ld from demux",npos);
239 //the demuxer cannot help us
240 npos=(u4)(((double)lenInBytes*percent)/(double)100);
241 logger->log("AudioPlayer",Log::DEBUG,"new pos %ld without demux",npos);
243 if (npos > lenInBytes) npos=lenInBytes-1;
244 requestedStreampos=npos;
245 requestState=S_POSITION;
248 //no need to wait here...
252 int AudioPlayer::skipForward(int seconds) {
253 if (! canPosition) return 1;
255 u4 curr=demuxer->getSecondsFromLen(streampos);
256 u4 dest=demuxer->positionFromSeconds(curr+(u4)seconds);
258 logger->log("AudioPlayer",Log::DEBUG,"new pos %ld skip %ds",dest,seconds);
259 requestedStreampos=dest;
261 requestState=S_POSITION;
266 int AudioPlayer::skipBackward(int seconds) {
267 if (! canPosition) return 1;
269 u4 curr=demuxer->getSecondsFromLen(streampos);
270 if (curr > (u4)seconds) {
271 u4 dest=demuxer->positionFromSeconds(curr-(u4)seconds);
273 logger->log("AudioPlayer",Log::DEBUG,"new pos %ld skip %ds",dest,seconds);
274 requestedStreampos=dest;
275 requestState=S_POSITION;
285 // ----------------------------------- Internal functions
288 void AudioPlayer::sendFrontendMessage(u4 para)
290 logger->log("AudioPlayer", Log::DEBUG, "sending frontend message %ld",para);
291 Message* m = new Message();
296 m->message = Message::PLAYER_EVENT;
298 MessageQueue::getInstance()->postMessage(m);
302 //called within the thread!
303 int AudioPlayer::openFile() {
310 MediaPlayer::getInstance()->closeMediaChannel(2);
311 int rt=MediaPlayer::getInstance()->openMedium(2,&fn,&lenInBytes,0,0);
312 Log::getInstance()->log("Audioplayer", Log::DEBUG, "request file rt=%d file=%s",rt,fn.getDisplayName());
317 rt=MediaPlayer::getInstance()->getMediaInfo(2,&mi);
318 canPosition=mi.canPosition;
322 rt=MediaPlayer::getInstance()->getMediaBlock(2,0,demuxer->headerBytes(),&rsize,&idbuf);
327 if (rsize < demuxer->headerBytes() || rt != 0 ) {
328 if (idbuf) free(idbuf);
329 Log::getInstance()->log("Audioplayer", Log::DEBUG, "unable to get header for file %s",fn.getName());
333 int hdrpos=demuxer->checkStart(idbuf,rsize);
338 if (idbuf) free(idbuf);
340 if (demuxer->getId3Tag() == NULL && canPosition) {
341 //OK - look at the end
342 rt=MediaPlayer::getInstance()->getMediaBlock(2,lenInBytes-demuxer->footerBytes(),demuxer->footerBytes(),&rsize,&idbuf);
343 if (rsize < demuxer->footerBytes() || rt != 0) {
344 if (idbuf) free(idbuf);
345 Log::getInstance()->log("Audioplayer", Log::DEBUG, "unable to get footer for file %s",fn.getName());
349 hdrpos=demuxer->checkID3(idbuf,rsize);
352 Log::getInstance()->log("Audioplayer", Log::DEBUG, "no ID3 in footer for file %s",fn.getName());
358 //method called by the playing thread to handle
359 //"commands" by the frontend
360 u1 AudioPlayer::checkState()
363 u1 rstate=requestState;
365 int rseq=requestedSequence;
367 int fseq=playSequence;
369 //flag to decide which message to send
374 logger->log("AudioPlayer", Log::DEBUG, "Switch state from %u to %u", cstate, rstate);
378 if (cstate != S_PLAY && cstate != S_FF && cstate != S_PAUSE) {
379 rstate=cstate; //ignore request
383 if (cstate != S_PAUSE) {
385 demuxer->setSkipFactor(0);
391 //if cstate==S_PAUSE fallthrough to S_PLAY
393 case S_PLAY: // to S_PLAY
395 demuxer->setSkipFactor(0);
396 if (fseq != currentPlaySequence || cstate == S_STOP || cstate == S_ERROR || cstate == S_DONE) {
397 //this is a new play request interrupting the current
398 logger->log("AudioPlayer", Log::DEBUG, "replay from start fseq=%d, startseq=%d", fseq, currentPlaySequence);
402 currentPlaySequence=fseq;
404 if (cstate != S_DONE) audio->mute();
411 if (cstate != S_DONE) {
412 //flush only if we are not coming from stream end
415 if (threadBuffer) free(threadBuffer);
417 controlFeeder(FEEDER_STOP);
419 controlFeeder(FEEDER_START);
421 audio->systemMuteOff();
422 audio->setStreamType(Audio::MP3);
428 else if (cstate == S_PAUSE){
433 else if (cstate == S_FF || S_BACK) {
441 Timers::getInstance()->setTimerD(this,1,4);
442 //inform the frontend
445 if (cstate != S_PLAY && cstate != S_PAUSE && cstate != S_FF) {
449 if (skipfactor == 0) skipfactor=2;
450 else skipfactor=skipfactor<<1;
451 if (skipfactor > 16 ) skipfactor=2;
452 demuxer->setSkipFactor(skipfactor);
454 if (cstate == S_PAUSE) {
460 if (cstate != S_PLAY && cstate != S_PAUSE) {
466 controlFeeder(FEEDER_STOP);
470 if (threadBuffer) free(threadBuffer);
472 streampos=requestedStreampos;
473 bytesWritten=streampos;
475 audio->setStreamType(Audio::MP3);
476 controlFeeder(FEEDER_START);
482 default: // to S_STOP
487 controlFeeder(FEEDER_STOP);
491 if (threadBuffer) free(threadBuffer);
493 logger->log("AudioPlayer", Log::DEBUG, "stop handled fseq: %d startseq %d completed", playSequence, currentPlaySequence);
500 if (newFile) sendFrontendMessage(NEW_SONG);
501 else if (cstate != rstate && rstate != S_DONE ) {
502 sendFrontendMessage(STATUS_CHANGE);
503 //any change after done cancels the "done" timer
504 Timers::getInstance()->cancelTimer(this,1);
506 logger->log("AudioPlayer", Log::DEBUG, "Switch state from %u to %u completed seq=%d, nf=%s", cstate, rstate,rseq,newFile?"true":"false");
507 //we return the newly set state
510 //rstate could be different but no new request - so return cstate
517 // ----------------------------------- Feed thread
519 void AudioPlayer::waitTimed(int ms) {
523 int us=1000*(ms - 1000*sec);
526 gettimeofday(&ct,NULL);
527 nt.tv_sec=ct.tv_sec+sec;
528 nt.tv_nsec=1000*us+1000*ct.tv_usec;
530 DWORD ct=timeGetTime();
531 nt.tv_sec=ct/1000+sec;
532 nt.tv_nsec=1000*us+1000*ct*1000;
534 threadWaitForSignalTimed(&nt);
538 void AudioPlayer::threadMethod()
540 logger->log("AudioPlayer", Log::DEBUG, "player thread started");
546 u1 cstate=checkState();
550 if (cstate != S_PLAY && cstate != S_FF && cstate != S_BACK) {
556 if (thisWrite == thisRead) {
557 //TODO: use normal blocks...
561 int rt=MediaPlayer::getInstance()->getMediaBlock(2,streampos,BUFLEN,&thisRead,&threadBuffer);
562 if (thisRead == 0 && threadBuffer) {
566 if ((!threadBuffer || thisRead == 0 ) && rt == 0) {
568 if (retrycount > MAXTRY) rt=-1;
570 logger->log("AudioPlayer", Log::DEBUG, "no data read, retrying");
575 if (!threadBuffer || thisRead == 0 || rt != 0) {
576 //OK we count this as end of stream
577 //hmm --- we should be able to detect if the audio has gone...
578 logger->log("AudioPlayer", Log::DEBUG, "stream end");
579 setRequestedState(S_DONE);
580 MediaPlayer::getInstance()->closeMediaChannel(2);
585 //logger->log("AudioPlayer", Log::DEBUG, "read %ld bytes at pos %ld",thisRead,streampos);
592 memset(&p,sizeof(p),0);
597 audio->PrepareMediaSample(pl,0);
599 u4 rt=audio->DeliverMediaSample(threadBuffer,&bytesWritten);
602 written=bytesWritten;
604 u4 written= demuxer->put(threadBuffer + thisWrite, thisRead - thisWrite);
606 bytesWritten+=written;
607 if (thisWrite < thisRead) {
609 // demuxer is full and can't take anymore
614 //logger->log("AudioPlayer", Log::DEBUG, "block written %d", thisWrite);
623 logger->log("AudioPlayer", Log::DEBUG, "finished");
624 MediaPlayer::getInstance()->closeMediaChannel(2);
629 int AudioPlayer::waitForSequence(int timeout, int seq) {
630 time_t starttime=time(NULL)+timeout;
632 logger->log("AudioPlayer", Log::DEBUG, "waiting for sequence %d",seq);
634 while ((curtime=time(NULL)) < starttime) {
635 int cseq=getSequence();
640 //logger->log("AudioPlayer", Log::DEBUG, "waiting for sequence loop");
643 logger->log("AudioPlayer", Log::DEBUG, "waiting for sequence %d returns %d",seq,rt);
647 int AudioPlayer::getSequence() {
657 void AudioPlayer::threadPostStopCleanup()
661 delete(threadBuffer);
667 void AudioPlayer::call(void *) {
668 threadSignalNoLock();
671 void AudioPlayer::timercall(int ref) {
673 logger->log("AudioPlayer", Log::DEBUG, "stream end - informing frontend");
674 sendFrontendMessage(STREAM_END);
678 //--------------------------- info functions -------------------
680 char * AudioPlayer::getTitle() {
681 logger->log("AudioPlayer", Log::DEBUG, "getTitle");
683 const id3_tag * tag=demuxer->getId3Tag();
684 const char * title=NULL;
689 if (title && strlen(title) != 0) {
690 rt=new char[strlen(title)+1];
694 //let the frontend fill in something
699 char * AudioPlayer::getID3Info() {
700 logger->log("AudioPlayer", Log::DEBUG, "getID3Info");
703 const id3_tag * tag=demuxer->getId3Tag();
705 if (tag) taglen=tag->stringlen(false);
707 const DemuxerAudio::mpegInfo *info=demuxer->getMpegInfo();
711 char bitrateType='C';
712 if (info && info->avrBitrate != info->bitRate) bitrateType='V';
715 int sr=info->sampleRate/1000;
716 SNPRINTF(rt,len-1,"%s: %s/L%d %cBR,SR=%d.%02dkBit/s,%s\n",tr("MpegInfo"),
717 info->mpegVersion,info->mpegLayer,bitrateType,sr,(info->sampleRate/10-sr*100),
720 else if (tag && info){
721 int sr=info->sampleRate/1000;
722 char *tmp=new char[taglen+1];
723 SNPRINTF(rt,len-1,"%s\n"
724 "%s: %s/L%d %cBR,SR=%d.%02dkBit/s,%s\n",
725 tag->toString(tmp,taglen,false),
727 info->mpegVersion,info->mpegLayer,bitrateType,sr,(info->sampleRate/10-sr*100),
731 else if (tag && !info){
732 char *tmp=new char[taglen+1];
733 SNPRINTF(rt,len-1,"%s\n",
734 tag->toString(tmp,taglen,false));
740 logger->log("AudioPlayer", Log::DEBUG, "getID3Info returns %s",rt);
744 u4 AudioPlayer::getCurrentTimes(){
748 rt=demuxer->getSecondsFromLen(bytesWritten);
751 rt= bytesWritten/DEFAULT_BITRATE;
758 u4 AudioPlayer::getSonglen(){
761 const DemuxerAudio::vbrInfo * vbr=demuxer->getVBRINfo();
762 if (vbr) rt=vbr->fileSeconds;
764 if (lenInBytes != 0) {
765 rt=demuxer->getSecondsFromLen(lenInBytes);
768 rt= lenInBytes/DEFAULT_BITRATE;
776 int AudioPlayer::getCurrentBitrate(){
777 int rt=DEFAULT_BITRATE;
779 const DemuxerAudio::mpegInfo *info=demuxer->getMpegInfo();
780 if (info) rt=info->bitRate;