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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 VDR::getInstance()->configSave("DirectShow",
346 "AudioFilter",audiofilterlist[audiofilterselected].displayname);
347 VDR::getInstance()->configSave("DirectShow",
348 "Mp3AudioFilter",mp3audiofilterlist[mp3audiofilterselected].displayname);
352 UINT AudioWin::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos)
354 DeliverMediaPacket(mediapacket, buffer, samplepos);
355 if (*samplepos == mediapacket.length) {
362 UINT AudioWin::DeliverMediaPacket(MediaPacket packet,
367 /*First Check, if we have an audio sample*/
368 VideoWin *vw=(VideoWin*)Video::getInstance();
369 if (!vw->isdsinited()) return 0;
370 if (vw->InIframemode()) {
373 return 0; //Not in iframe mode!
375 IMediaSample* ms=NULL;
376 REFERENCE_TIME reftime1=0;
377 REFERENCE_TIME reftime2=0;
380 if (packet.disconti) {
382 vw->DeliverAudioMediaSample();
385 if (packet.type!=vw->lastAType()){//Format Change //Push data out !
387 vw->DeliverAudioMediaSample();
392 /*Inspect PES-Header */
393 /* UINT header_length=buffer[(packet.pos_buffer+8)%bufferlength]+8/*is this right*;
395 if (*samplepos==0 && packet.type!=MPTYPE_MPEG_AUDIO_LAYER3) {//stripheader
396 headerstrip=buffer[packet.pos_buffer+8]+9;
397 if (packet.type == MPTYPE_AC3) headerstrip+=4; //skip ac3 bytes
398 *samplepos+=headerstrip;
399 if ( packet.synched ) {
400 vw->DeliverAudioMediaSample();//write out old data
401 reftime1=packet.presentation_time;
405 if (!firstsynched) {//
406 *samplepos=packet.length;//if we have not processed at least one
407 return packet.length;//synched packet ignore it!
415 if (!vw->getCurrentAudioMediaSample(&ms) || ms==NULL) {// get the current sample
420 ms_pos=ms->GetActualDataLength();
421 ms_length=ms->GetSize();
422 haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);
423 if ((ms_length-ms_pos)<1) {
424 vw->DeliverAudioMediaSample(); //we are full!
425 if (!vw->getCurrentAudioMediaSample(&ms) || ms==NULL) {// get the current sample
430 ms_pos=ms->GetActualDataLength();
431 ms_length=ms->GetSize();
432 haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);
434 ms->GetPointer(&ms_buf);
437 if (ms_pos==0) {//will only be changed on first packet
438 if (packet.disconti) {
439 ms->SetDiscontinuity(TRUE);
441 ms->SetDiscontinuity(FALSE);
443 if (packet.synched) {
444 ms->SetSyncPoint(TRUE);
445 ms->SetTime(&reftime1,&reftime2);
447 //ms->SetTime(NULL,NULL);
448 ms->SetMediaTime(NULL, NULL);
449 if (reftime1<0) ms->SetPreroll(TRUE);
450 else ms->SetPreroll(FALSE);
452 ms->SetSyncPoint(FALSE);
453 ms->SetTime(NULL,NULL);
454 ms->SetMediaTime(NULL, NULL);
455 ms->SetPreroll(FALSE);
456 // ms->SetSyncPoint(TRUE);
459 if (packet.type!=vw->lastAType()) {
460 vw->changeAType(packet.type,ms);
461 ms->SetDiscontinuity(TRUE);
465 memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy);
467 ms->SetActualDataLength(haveToCopy+ms_pos);
469 *samplepos+=haveToCopy;
471 return haveToCopy+headerstrip;
475 int AudioWin::dsInitAudioFilter(IGraphBuilder* dsgraphbuilder)
478 IFilterGraph2*fg2=NULL;
479 VideoWin *vw=(VideoWin*)Video::getInstance();
480 if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!= S_OK)
482 Log::getInstance()->log("AudiooWin", Log::WARN , "Failed querying for FilterGraph2 Interface!");
485 IBaseFilter*audiofilter;
486 if (aud_type!=Audio::MP3) {
487 audiofilter = getAudioFilter();
489 audiofilter = getMp3AudioFilter();
491 if (hres=dsgraphbuilder->AddFilter(audiofilter,NULL) != S_OK)
493 Log::getInstance()->log("AudioWin", Log::WARN , "Failed adding Video Filter!");
496 IEnumPins *pinenum=NULL;
498 if (audiofilter->EnumPins(&pinenum) == S_OK)
502 bool firststep=false;
503 while (pinenum->Next(1,¤t,&fetch)==S_OK)
506 if (current->QueryDirection(&dir)==S_OK)
508 if (dir == PINDIR_INPUT)
510 if (vw->getSourceFilter()->GetAudioPin()->Connect(current,NULL)==S_OK)
520 if (firststep==false)
522 Log::getInstance()->log("AudioWin", Log::WARN , "Audio Filter has no suitable input!");
523 audiofilter->Release();
526 bool secondstep=false;
528 while (pinenum->Next(1,¤t,&fetch)==S_OK)
531 if (current->QueryDirection(&dir)==S_OK)
533 if (dir == PINDIR_OUTPUT)
536 if (fg2->RenderEx((IPin*)current/*video*/,
547 if (secondstep==false)
549 Log::getInstance()->log("AudioWin", Log::WARN , "Audio Filter has no suitable output!");
550 audiofilter->Release();
555 audiofilter->Release();
567 IBaseFilter *AudioWin::getAudioFilter()
569 IBaseFilter *curfilter= NULL;
571 if (audiofilterselected == -1)
574 for (i = 0;i <audiofilterlist.size();i++)
576 audiofilterselected = i;
581 IBindCtx *bindctx=NULL;
582 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
583 IMoniker * moni=NULL;
584 LPCOLESTR name=new WCHAR[strlen(audiofilterlist[audiofilterselected].displayname)+1];
585 mbstowcs((wchar_t*)name,audiofilterlist[audiofilterselected].displayname,
586 strlen(audiofilterlist[audiofilterselected].displayname)+1);
588 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
590 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
592 if (curfilter != NULL && notset)
594 VDR *vdr=VDR::getInstance();
597 vdr->configSave("DirectShow","AudioFilter",
598 audiofilterlist[audiofilterselected].displayname);
614 IBaseFilter *AudioWin::getMp3AudioFilter()
616 IBaseFilter *curfilter= NULL;
618 if (mp3audiofilterselected == -1)
621 for (i = 0;i <mp3audiofilterlist.size();i++)
623 mp3audiofilterselected = i;
628 IBindCtx *bindctx=NULL;
629 if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
630 IMoniker * moni=NULL;
631 LPCOLESTR name=new WCHAR[strlen(mp3audiofilterlist[mp3audiofilterselected].displayname)+1];
632 mbstowcs((wchar_t*)name,mp3audiofilterlist[mp3audiofilterselected].displayname,
633 strlen(mp3audiofilterlist[mp3audiofilterselected].displayname)+1);
635 if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
637 if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
639 if (curfilter != NULL && notset)
641 VDR *vdr=VDR::getInstance();
644 vdr->configSave("DirectShow","Mp3AudioFilter",
645 mp3audiofilterlist[mp3audiofilterselected].displayname);
662 bool AudioWin::addOptionPagesToWTB(WTabBar *wtb)
664 Boxx *box=new WWinAudioFilter();
665 wtb->addTab(tr("Audio Filter"), box);
668 box=new WWinMp3AudioFilter();
669 wtb->addTab(tr("Mp3 Audio Filter"), box);
675 const AudioFilterDescList *AudioWin::getAudioFilterList(int &selected)
677 selected=audiofilterselected;
678 return &audiofilterlist;
681 const AudioFilterDescList *AudioWin::getMp3AudioFilterList(int &selected)
683 selected=mp3audiofilterselected;
684 return &mp3audiofilterlist;
686 bool AudioWin::selectMp3AudioFilter(int filter)
688 mp3audiofilterselected=filter;
693 bool AudioWin::selectAudioFilter(int filter)
695 audiofilterselected=filter;
700 long long AudioWin::SetStartOffset(long long curreftime, bool *rsync){
701 VideoWin *vw=(VideoWin*)Video::getInstance();
702 return vw->SetStartAudioOffset(curreftime,rsync);
705 void AudioWin::ResetTimeOffsets() {
706 VideoWin *vw=(VideoWin*)Video::getInstance();
707 return vw->ResetTimeOffsets();
710 bool AudioWin::supportsAc3(){
711 VideoWin *vw=(VideoWin*)Video::getInstance();
712 return vw->supportsAc3();