2 Copyright 2004-2005 Chris Tallon
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, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 #include "wwinaudiofilter.h"
26 #include "wwinmp3audiofilter.h"
38 audiofilterselected=-1;
39 mp3audiofilterselected=-1;
40 aud_type=Audio::MPEG2_PES;
48 for (i=0;i<audiofilterlist.size();i++)
50 if (audiofilterlist[i].displayname) delete [] audiofilterlist[i].displayname;
51 if (audiofilterlist[i].friendlyname) delete [] audiofilterlist[i].friendlyname;
53 audiofilterlist.clear();
55 for (i=0;i<mp3audiofilterlist.size();i++)
57 if (mp3audiofilterlist[i].displayname) delete [] mp3audiofilterlist[i].displayname;
58 if (mp3audiofilterlist[i].friendlyname) delete [] mp3audiofilterlist[i].friendlyname;
60 mp3audiofilterlist.clear();
64 int AudioWin::init(UCHAR tstreamType)
66 if (initted) return 0;
68 initMp3FilterDatabase();
73 int AudioWin::shutdown()
75 if (!initted) return 0;
80 int AudioWin::write(char *buf, int len)
82 return 0; //write(fdAudio, buf, len);
85 int AudioWin::setStreamType(UCHAR type)
87 ((VideoWin*)VideoWin::getInstance())->setAudioStreamType(type);
89 if (!initted) return 0;
93 int AudioWin::setChannel()
95 if (!initted) return 0;
99 int AudioWin::setSource()
101 if (!initted) return 0;
107 if (!initted) return 0;
113 if (!initted) return 0;
115 return ((VideoWin*)Video::getInstance())->dsplay();
121 if (!initted) return 0;
122 return ((VideoWin*)Video::getInstance())->dsstop();
125 int AudioWin::pause()
127 if (!initted) return 0;
128 return ((VideoWin*)Video::getInstance())->dspause();
131 int AudioWin::unPause()
133 if (!initted) return 0;
134 return ((VideoWin*)Video::getInstance())->dsunPause();
137 int AudioWin::reset()
140 if (!initted){return 0;}
141 return ((VideoWin*)Video::getInstance())->dsreset();
144 int AudioWin::setVolume(int tvolume)
146 // parameter: 0 for silence, 20 for full
147 if ((tvolume < 0) || (tvolume > 20)) return 0;
148 winvolume=((tvolume-20)*100*30)/20;
149 if (tvolume==0) winvolume=-10000;
150 ((VideoWin*)Video::getInstance())->SetAudioVolume(winvolume);
158 if (!initted) return 0;
159 ((VideoWin*)Video::getInstance())->SetAudioState(false);
160 ((VideoWin*)Video::getInstance())->SetAudioVolume(-10000);
164 int AudioWin::unMute()
166 if (!initted) return 0;
167 ((VideoWin*)Video::getInstance())->SetAudioState(true);
168 ((VideoWin*)Video::getInstance())->SetAudioVolume(winvolume);
172 void AudioWin::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
174 mediapacket = mplist.front();
177 void AudioWin::initFilterDatabase()
179 /* This method should determine all availiable DirectShow Filters */
180 IFilterMapper2* filtmap=NULL;
182 result = CoCreateInstance(CLSID_FilterMapper2,NULL,CLSCTX_INPROC,
183 IID_IFilterMapper2,(void**)&filtmap);
186 Log::getInstance()->log("AudioWin", Log::ERR , "Unable to create FilterMapper!");
189 /* Wishlist, what Mediatypes do we want */
190 GUID mtypesin[]={MEDIATYPE_Audio,MEDIASUBTYPE_MPEG2_AUDIO,
191 /*MEDIATYPE_Audio,MEDIASUBTYPE_MPEG1Payload,*/
192 MEDIATYPE_Audio,MEDIASUBTYPE_DOLBY_AC3,
193 MEDIATYPE_Audio, MEDIASUBTYPE_DOLBY_AC3_SPDIF};
194 IEnumMoniker *myenum;
195 result = filtmap->EnumMatchingFilters(&myenum,0,TRUE,MERIT_DO_NOT_USE+1,
196 TRUE,3,mtypesin,NULL,NULL,FALSE,TRUE,0,NULL,NULL,NULL);
200 Log::getInstance()->log("AudioWin", Log::ERR , "Unable to enum Filters!");
205 while(myenum->Next(1,&moni,&gethowmany)==S_OK)
207 AudioFilterDesc desc;
208 ZeroMemory(&desc,sizeof(desc));
211 moni->GetDisplayName(0,0,&string);
212 desc.displayname=new char[wcslen(string)+1];
213 wcstombs(desc.displayname,string,wcslen(string)+1);
214 CoTaskMemFree(string);
216 if (moni->BindToStorage(0,0,IID_IPropertyBag,(void**)&bag) == S_OK)
220 result = bag->Read(L"FriendlyName",&vari,NULL);
223 desc.friendlyname=new char[wcslen(vari.bstrVal)+1];
224 wcstombs(desc.friendlyname,vari.bstrVal,wcslen(vari.bstrVal)+1);
232 audiofilterlist.push_back(desc);
240 audiofilterselected=-1;
245 void AudioWin::initMp3FilterDatabase()
247 /* This method should determine all availiable DirectShow Filters */
248 IFilterMapper2* filtmap=NULL;
250 result = CoCreateInstance(CLSID_FilterMapper2,NULL,CLSCTX_INPROC,
251 IID_IFilterMapper2,(void**)&filtmap);
254 Log::getInstance()->log("AudioWin", Log::ERR , "Unable to create FilterMapper!");
257 /* Wishlist, what Mediatypes do we want */
258 GUID mtypesin[]={MEDIATYPE_Audio,MEDIATYPE_WaveFmt_Mpeg1Layer3,
259 MEDIATYPE_Audio,MEDIASUBTYPE_MPEG2_AUDIO};
260 IEnumMoniker *myenum;
261 result = filtmap->EnumMatchingFilters(&myenum,0,TRUE,MERIT_DO_NOT_USE+1,
262 TRUE,3,mtypesin,NULL,NULL,FALSE,TRUE,0,NULL,NULL,NULL);
266 Log::getInstance()->log("AudioWin", Log::ERR , "Unable to enum Filters!");
271 while(myenum->Next(1,&moni,&gethowmany)==S_OK)
273 AudioFilterDesc desc;
274 ZeroMemory(&desc,sizeof(desc));
277 moni->GetDisplayName(0,0,&string);
278 desc.displayname=new char[wcslen(string)+1];
279 wcstombs(desc.displayname,string,wcslen(string)+1);
280 CoTaskMemFree(string);
282 if (moni->BindToStorage(0,0,IID_IPropertyBag,(void**)&bag) == S_OK)
286 result = bag->Read(L"FriendlyName",&vari,NULL);
289 desc.friendlyname=new char[wcslen(vari.bstrVal)+1];
290 wcstombs(desc.friendlyname,vari.bstrVal,wcslen(vari.bstrVal)+1);
298 mp3audiofilterlist.push_back(desc);
306 mp3audiofilterselected=-1;
311 bool AudioWin::loadOptionsfromServer(VDR* vdr)
313 char *name=vdr->configLoad("DirectShow","AudioFilter");
317 for (int i = 0;i <audiofilterlist.size();i++)
319 if (strcmp(name,audiofilterlist[i].displayname)==0)
321 audiofilterselected = i;
326 name=vdr->configLoad("DirectShow","Mp3AudioFilter");
330 for (int i = 0;i <mp3audiofilterlist.size();i++)
332 if (strcmp(name,mp3audiofilterlist[i].displayname)==0)
334 mp3audiofilterselected = i;
343 bool AudioWin::saveOptionstoServer()
345 if (audiofilterselected!=-1) {
346 VDR::getInstance()->configSave("DirectShow",
347 "AudioFilter",audiofilterlist[audiofilterselected].displayname);
349 if (mp3audiofilterselected!=-1) {
350 VDR::getInstance()->configSave("DirectShow",
351 "Mp3AudioFilter",mp3audiofilterlist[mp3audiofilterselected].displayname);
356 UINT AudioWin::DeliverMediaSample(UCHAR* buffer, UINT *samplepos)
358 DeliverMediaPacket(mediapacket, buffer, samplepos);
359 if (*samplepos == mediapacket.length) {
366 UINT AudioWin::DeliverMediaPacket(const MediaPacket packet,
371 /*First Check, if we have an audio sample*/
372 VideoWin *vw=(VideoWin*)Video::getInstance();
373 if (!vw->isdsinited()) return 0;
374 if (vw->InIframemode()) {
377 return 0; //Not in iframe mode!
379 IMediaSample* ms=NULL;
380 REFERENCE_TIME reftime1=0;
381 REFERENCE_TIME reftime2=0;
384 if (packet.disconti) {
386 vw->DeliverAudioMediaSample();
389 if (packet.type!=vw->lastAType()){//Format Change //Push data out !
391 vw->DeliverAudioMediaSample();
396 /*Inspect PES-Header */
397 /* UINT header_length=buffer[(packet.pos_buffer+8)%bufferlength]+8/*is this right*;
399 if (*samplepos==0 && packet.type!=MPTYPE_MPEG_AUDIO_LAYER3) {//stripheader
400 headerstrip=buffer[packet.pos_buffer+8]+9;
401 if (packet.type == MPTYPE_AC3) headerstrip+=4; //skip ac3 bytes
402 *samplepos+=headerstrip;
403 if ( packet.synched ) {
404 vw->DeliverAudioMediaSample();//write out old data
405 reftime1=packet.presentation_time;
409 if (!firstsynched) {//
410 *samplepos=packet.length;//if we have not processed at least one
411 return packet.length;//synched packet ignore it!
419 if (!vw->getCurrentAudioMediaSample(&ms) || ms==NULL) {// get the current sample
424 ms_pos=ms->GetActualDataLength();
425 ms_length=ms->GetSize();
426 haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);
427 if ((ms_length-ms_pos)<1) {
428 vw->DeliverAudioMediaSample(); //we are full!
429 if (!vw->getCurrentAudioMediaSample(&ms) || ms==NULL) {// get the current sample
434 ms_pos=ms->GetActualDataLength();
435 ms_length=ms->GetSize();
436 haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);
438 ms->GetPointer(&ms_buf);
441 if (ms_pos==0) {//will only be changed on first packet
442 if (packet.disconti) {
443 ms->SetDiscontinuity(TRUE);
445 ms->SetDiscontinuity(FALSE);
447 if (packet.synched) {
448 ms->SetSyncPoint(TRUE);
449 ms->SetTime(&reftime1,&reftime2);
451 //ms->SetTime(NULL,NULL);
452 ms->SetMediaTime(NULL, NULL);
453 if (reftime1<0) ms->SetPreroll(TRUE);
454 else ms->SetPreroll(FALSE);
456 ms->SetSyncPoint(FALSE);
457 ms->SetTime(NULL,NULL);
458 ms->SetMediaTime(NULL, NULL);
459 ms->SetPreroll(FALSE);
460 // ms->SetSyncPoint(TRUE);
463 if (packet.type!=vw->lastAType()) {
464 vw->changeAType(packet.type,ms);
465 ms->SetDiscontinuity(TRUE);
469 memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy);
471 ms->SetActualDataLength(haveToCopy+ms_pos);
473 *samplepos+=haveToCopy;
475 return haveToCopy+headerstrip;
479 int AudioWin::dsInitAudioFilter(IGraphBuilder* dsgraphbuilder)
482 IFilterGraph2*fg2=NULL;
483 VideoWin *vw=(VideoWin*)Video::getInstance();
484 if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!= S_OK)
486 Log::getInstance()->log("AudiooWin", Log::WARN , "Failed querying for FilterGraph2 Interface!");
489 IBaseFilter*audiofilter;
490 if (aud_type!=Audio::MP3) {
491 audiofilter = getAudioFilter();
493 audiofilter = getMp3AudioFilter();
495 if (hres=dsgraphbuilder->AddFilter(audiofilter,NULL) != S_OK)
497 Log::getInstance()->log("AudioWin", Log::WARN , "Failed adding Video Filter!");
500 IEnumPins *pinenum=NULL;
502 if (audiofilter->EnumPins(&pinenum) == S_OK)
506 bool firststep=false;
507 while (pinenum->Next(1,¤t,&fetch)==S_OK)
510 if (current->QueryDirection(&dir)==S_OK)
512 if (dir == PINDIR_INPUT)
514 if (vw->getSourceFilter()->GetAudioPin()->Connect(current,NULL)==S_OK)
524 if (firststep==false)
526 Log::getInstance()->log("AudioWin", Log::WARN , "Audio Filter has no suitable input!");
527 audiofilter->Release();
530 bool secondstep=false;
532 while (pinenum->Next(1,¤t,&fetch)==S_OK)
535 if (current->QueryDirection(&dir)==S_OK)
537 if (dir == PINDIR_OUTPUT)
540 if (fg2->RenderEx((IPin*)current/*video*/,
551 if (secondstep==false)
553 Log::getInstance()->log("AudioWin", Log::WARN , "Audio Filter has no suitable output!");
554 audiofilter->Release();
559 audiofilter->Release();
571 IBaseFilter *AudioWin::getAudioFilter()
573 IBaseFilter *curfilter= NULL;
575 if (audiofilterselected == -1)
578 for (i = 0;i <audiofilterlist.size();i++)
580 audiofilterselected = i;
585 IBindCtx *bindctx=NULL;
586 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
587 IMoniker * moni=NULL;
588 LPCOLESTR name=new WCHAR[strlen(audiofilterlist[audiofilterselected].displayname)+1];
589 mbstowcs((wchar_t*)name,audiofilterlist[audiofilterselected].displayname,
590 strlen(audiofilterlist[audiofilterselected].displayname)+1);
592 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
594 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
596 if (curfilter != NULL && notset)
598 VDR *vdr=VDR::getInstance();
601 vdr->configSave("DirectShow","AudioFilter",
602 audiofilterlist[audiofilterselected].displayname);
618 IBaseFilter *AudioWin::getMp3AudioFilter()
620 IBaseFilter *curfilter= NULL;
622 if (mp3audiofilterselected == -1)
625 for (i = 0;i <mp3audiofilterlist.size();i++)
627 mp3audiofilterselected = i;
632 IBindCtx *bindctx=NULL;
633 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
634 IMoniker * moni=NULL;
635 LPCOLESTR name=new WCHAR[strlen(mp3audiofilterlist[mp3audiofilterselected].displayname)+1];
636 mbstowcs((wchar_t*)name,mp3audiofilterlist[mp3audiofilterselected].displayname,
637 strlen(mp3audiofilterlist[mp3audiofilterselected].displayname)+1);
639 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
641 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
643 if (curfilter != NULL && notset)
645 VDR *vdr=VDR::getInstance();
648 vdr->configSave("DirectShow","Mp3AudioFilter",
649 mp3audiofilterlist[mp3audiofilterselected].displayname);
666 bool AudioWin::addOptionPagesToWTB(WTabBar *wtb)
668 Boxx *box=new WWinAudioFilter();
669 wtb->addTab(tr("Audio Filter"), box);
672 box=new WWinMp3AudioFilter();
673 wtb->addTab(tr("Mp3 Audio Filter"), box);
679 const AudioFilterDescList *AudioWin::getAudioFilterList(int &selected)
681 selected=audiofilterselected;
682 return &audiofilterlist;
685 const AudioFilterDescList *AudioWin::getMp3AudioFilterList(int &selected)
687 selected=mp3audiofilterselected;
688 return &mp3audiofilterlist;
690 bool AudioWin::selectMp3AudioFilter(int filter)
692 mp3audiofilterselected=filter;
697 bool AudioWin::selectAudioFilter(int filter)
699 audiofilterselected=filter;
704 long long AudioWin::SetStartOffset(long long curreftime, bool *rsync){
705 VideoWin *vw=(VideoWin*)Video::getInstance();
706 return vw->SetStartAudioOffset(curreftime,rsync);
709 void AudioWin::ResetTimeOffsets() {
710 VideoWin *vw=(VideoWin*)Video::getInstance();
711 return vw->ResetTimeOffsets();
714 bool AudioWin::supportsAc3(){
715 VideoWin *vw=(VideoWin*)Video::getInstance();
716 return vw->supportsAc3();