]> git.vomp.tv Git - vompclient.git/blob - audiowin.cc
Preparations for dynamic mode switching
[vompclient.git] / audiowin.cc
1 /*\r
2     Copyright 2004-2005 Chris Tallon\r
3 \r
4     This file is part of VOMP.\r
5 \r
6     VOMP is free software; you can redistribute it and/or modify\r
7     it under the terms of the GNU General Public License as published by\r
8     the Free Software Foundation; either version 2 of the License, or\r
9     (at your option) any later version.\r
10 \r
11     VOMP is distributed in the hope that it will be useful,\r
12     but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14     GNU General Public License for more details.\r
15 \r
16     You should have received a copy of the GNU General Public License\r
17     along with VOMP; if not, write to the Free Software\r
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
19 */\r
20 \r
21 #include "audiowin.h"\r
22 #include "videowin.h"\r
23 #include "vdr.h"\r
24 #include "wtabbar.h"\r
25 #include "wwinaudiofilter.h"\r
26 #include "wwinmp3audiofilter.h"\r
27 #include "i18n.h"\r
28 \r
29 \r
30 \r
31 \r
32 AudioWin::AudioWin()\r
33 {\r
34   initted = 0;\r
35   firstsynched=false;\r
36   winvolume=0;\r
37   volume=20;\r
38 audiofilterselected=-1;\r
39   mp3audiofilterselected=-1;\r
40   aud_type=Audio::MPEG2_PES;\r
41 \r
42 }\r
43 \r
44 AudioWin::~AudioWin()\r
45 {\r
46 \r
47   int i;\r
48   for (i=0;i<audiofilterlist.size();i++)\r
49   {\r
50    if (audiofilterlist[i].displayname) delete [] audiofilterlist[i].displayname;\r
51    if (audiofilterlist[i].friendlyname) delete [] audiofilterlist[i].friendlyname;\r
52   }\r
53   audiofilterlist.clear();\r
54 \r
55   for (i=0;i<mp3audiofilterlist.size();i++)\r
56   {\r
57    if (mp3audiofilterlist[i].displayname) delete [] mp3audiofilterlist[i].displayname;\r
58    if (mp3audiofilterlist[i].friendlyname) delete [] mp3audiofilterlist[i].friendlyname;\r
59   }\r
60   mp3audiofilterlist.clear();\r
61 \r
62 }\r
63 \r
64 int AudioWin::init(UCHAR tstreamType)\r
65 {\r
66   if (initted) return 0;\r
67   initFilterDatabase();\r
68   initMp3FilterDatabase();\r
69   initted = 1;\r
70   return 1;\r
71 }\r
72 \r
73 int AudioWin::shutdown()\r
74 {\r
75   if (!initted) return 0;\r
76   initted = 0;\r
77   return 1;\r
78 }\r
79 \r
80 int AudioWin::write(char *buf, int len)\r
81 {\r
82   return 0; //write(fdAudio, buf, len);\r
83 }\r
84 \r
85 int AudioWin::setStreamType(UCHAR type)\r
86 {\r
87   ((VideoWin*)VideoWin::getInstance())->setAudioStreamType(type);\r
88   aud_type=type;\r
89   if (!initted) return 0;\r
90   return 1;\r
91 }\r
92 \r
93 int AudioWin::setChannel()\r
94 {\r
95   if (!initted) return 0;\r
96   return 1;\r
97 }\r
98 \r
99 int AudioWin::setSource()\r
100 {\r
101   if (!initted) return 0;\r
102   return 1;\r
103 }\r
104 \r
105 int AudioWin::sync()\r
106 {\r
107   if (!initted) return 0;\r
108   return 1;\r
109 }\r
110 \r
111 int AudioWin::play()\r
112 {\r
113   if (!initted) return 0;\r
114   firstsynched=false;\r
115   return ((VideoWin*)Video::getInstance())->dsplay();\r
116 \r
117 }\r
118 \r
119 int AudioWin::stop()\r
120 {\r
121   if (!initted) return 0;\r
122   return ((VideoWin*)Video::getInstance())->dsstop();\r
123 }\r
124 \r
125 int AudioWin::pause()\r
126 {\r
127   if (!initted) return 0;\r
128   return ((VideoWin*)Video::getInstance())->dspause();\r
129 }\r
130 \r
131 int AudioWin::unPause()\r
132 {\r
133   if (!initted) return 0;\r
134   return ((VideoWin*)Video::getInstance())->dsunPause();\r
135 }\r
136 \r
137 int AudioWin::reset()\r
138 {\r
139   \r
140   if (!initted){return 0;}\r
141   return ((VideoWin*)Video::getInstance())->dsreset();\r
142 }\r
143 \r
144 int AudioWin::setVolume(int tvolume)\r
145 {\r
146   // parameter: 0 for silence, 20 for full\r
147   if ((tvolume < 0) || (tvolume > 20)) return 0;\r
148   winvolume=((tvolume-20)*100*30)/20;\r
149   if (tvolume==0) winvolume=-10000;\r
150   ((VideoWin*)Video::getInstance())->SetAudioVolume(winvolume);\r
151 \r
152 \r
153   return 1;\r
154 }\r
155 \r
156 int AudioWin::mute()\r
157 {\r
158   if (!initted) return 0;\r
159   ((VideoWin*)Video::getInstance())->SetAudioState(false);\r
160   ((VideoWin*)Video::getInstance())->SetAudioVolume(-10000);\r
161   return 1;\r
162 }\r
163 \r
164 int AudioWin::unMute()\r
165 {\r
166   if (!initted) return 0;\r
167   ((VideoWin*)Video::getInstance())->SetAudioState(true);\r
168   ((VideoWin*)Video::getInstance())->SetAudioVolume(winvolume);\r
169   return 1;\r
170 }\r
171 \r
172 void AudioWin::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)\r
173 {\r
174   mediapacket = mplist.front();\r
175 }\r
176 \r
177 void AudioWin::initFilterDatabase()\r
178 {\r
179      /* This method should determine all availiable DirectShow Filters */\r
180     IFilterMapper2* filtmap=NULL;\r
181     HRESULT result;\r
182     result = CoCreateInstance(CLSID_FilterMapper2,NULL,CLSCTX_INPROC,\r
183                 IID_IFilterMapper2,(void**)&filtmap);\r
184     if (result != S_OK)\r
185     {\r
186         Log::getInstance()->log("AudioWin", Log::ERR , "Unable to create FilterMapper!");\r
187         return;\r
188     }\r
189     /* Wishlist, what Mediatypes do we want */\r
190     GUID mtypesin[]={MEDIATYPE_Audio,MEDIASUBTYPE_MPEG2_AUDIO,\r
191     /*MEDIATYPE_Audio,MEDIASUBTYPE_MPEG1Payload,*/\r
192     MEDIATYPE_Audio,MEDIASUBTYPE_DOLBY_AC3,\r
193      MEDIATYPE_Audio, MEDIASUBTYPE_DOLBY_AC3_SPDIF};\r
194     IEnumMoniker *myenum;\r
195     result = filtmap->EnumMatchingFilters(&myenum,0,TRUE,MERIT_DO_NOT_USE+1,\r
196                     TRUE,3,mtypesin,NULL,NULL,FALSE,TRUE,0,NULL,NULL,NULL);\r
197     if (result != S_OK)\r
198     {\r
199         filtmap->Release();\r
200         Log::getInstance()->log("AudioWin", Log::ERR , "Unable to enum Filters!");\r
201         return;\r
202     }\r
203     ULONG gethowmany;\r
204     IMoniker * moni;\r
205     while(myenum->Next(1,&moni,&gethowmany)==S_OK)\r
206     {\r
207         AudioFilterDesc desc;\r
208         ZeroMemory(&desc,sizeof(desc));\r
209    \r
210         LPOLESTR string;\r
211         moni->GetDisplayName(0,0,&string);\r
212         desc.displayname=new char[wcslen(string)+1];\r
213         wcstombs(desc.displayname,string,wcslen(string)+1);\r
214         CoTaskMemFree(string);\r
215         IPropertyBag *bag;\r
216         if (moni->BindToStorage(0,0,IID_IPropertyBag,(void**)&bag) == S_OK)\r
217         {\r
218             VARIANT vari;\r
219             VariantInit(&vari);\r
220             result = bag->Read(L"FriendlyName",&vari,NULL);\r
221             if (result == S_OK)\r
222             {\r
223                 desc.friendlyname=new char[wcslen(vari.bstrVal)+1];\r
224                 wcstombs(desc.friendlyname,vari.bstrVal,wcslen(vari.bstrVal)+1);\r
225             }\r
226             VariantClear(&vari);\r
227             bag->Release();\r
228 \r
229         }\r
230         \r
231        \r
232         audiofilterlist.push_back(desc);\r
233        \r
234 \r
235         \r
236         moni->Release();\r
237        // bctx->Release();\r
238     }\r
239     int i;\r
240     audiofilterselected=-1;\r
241     myenum->Release();\r
242     filtmap->Release();\r
243 }\r
244 \r
245 void AudioWin::initMp3FilterDatabase()\r
246 {\r
247      /* This method should determine all availiable DirectShow Filters */\r
248     IFilterMapper2* filtmap=NULL;\r
249     HRESULT result;\r
250     result = CoCreateInstance(CLSID_FilterMapper2,NULL,CLSCTX_INPROC,\r
251                 IID_IFilterMapper2,(void**)&filtmap);\r
252     if (result != S_OK)\r
253     {\r
254         Log::getInstance()->log("AudioWin", Log::ERR , "Unable to create FilterMapper!");\r
255         return;\r
256     }\r
257     /* Wishlist, what Mediatypes do we want */\r
258     GUID mtypesin[]={MEDIATYPE_Audio,MEDIATYPE_WaveFmt_Mpeg1Layer3,\r
259                     MEDIATYPE_Audio,MEDIASUBTYPE_MPEG2_AUDIO};\r
260     IEnumMoniker *myenum;\r
261     result = filtmap->EnumMatchingFilters(&myenum,0,TRUE,MERIT_DO_NOT_USE+1,\r
262                     TRUE,3,mtypesin,NULL,NULL,FALSE,TRUE,0,NULL,NULL,NULL);\r
263     if (result != S_OK)\r
264     {\r
265         filtmap->Release();\r
266         Log::getInstance()->log("AudioWin", Log::ERR , "Unable to enum Filters!");\r
267         return;\r
268     }\r
269     ULONG gethowmany;\r
270     IMoniker * moni;\r
271     while(myenum->Next(1,&moni,&gethowmany)==S_OK)\r
272     {\r
273         AudioFilterDesc desc;\r
274         ZeroMemory(&desc,sizeof(desc));\r
275    \r
276         LPOLESTR string;\r
277         moni->GetDisplayName(0,0,&string);\r
278         desc.displayname=new char[wcslen(string)+1];\r
279         wcstombs(desc.displayname,string,wcslen(string)+1);\r
280         CoTaskMemFree(string);\r
281         IPropertyBag *bag;\r
282         if (moni->BindToStorage(0,0,IID_IPropertyBag,(void**)&bag) == S_OK)\r
283         {\r
284             VARIANT vari;\r
285             VariantInit(&vari);\r
286             result = bag->Read(L"FriendlyName",&vari,NULL);\r
287             if (result == S_OK)\r
288             {\r
289                 desc.friendlyname=new char[wcslen(vari.bstrVal)+1];\r
290                 wcstombs(desc.friendlyname,vari.bstrVal,wcslen(vari.bstrVal)+1);\r
291             }\r
292             VariantClear(&vari);\r
293             bag->Release();\r
294 \r
295         }\r
296         \r
297        \r
298         mp3audiofilterlist.push_back(desc);\r
299        \r
300 \r
301         \r
302         moni->Release();\r
303        // bctx->Release();\r
304     }\r
305     int i;\r
306     mp3audiofilterselected=-1;\r
307     myenum->Release();\r
308     filtmap->Release();\r
309 }\r
310 \r
311 bool AudioWin::loadOptionsfromServer(VDR* vdr)\r
312 {\r
313     char *name=vdr->configLoad("DirectShow","AudioFilter");\r
314     \r
315     if (name != NULL) \r
316     {\r
317         for (int i = 0;i <audiofilterlist.size();i++)\r
318         {\r
319             if (strcmp(name,audiofilterlist[i].displayname)==0)\r
320             {\r
321                 audiofilterselected = i;\r
322                 break;\r
323             }\r
324         }\r
325    }\r
326     name=vdr->configLoad("DirectShow","Mp3AudioFilter");\r
327     \r
328     if (name != NULL) \r
329     {\r
330         for (int i = 0;i <mp3audiofilterlist.size();i++)\r
331         {\r
332             if (strcmp(name,mp3audiofilterlist[i].displayname)==0)\r
333             {\r
334                 mp3audiofilterselected = i;\r
335                 break;\r
336             }\r
337         }\r
338    }\r
339    return true;\r
340 \r
341 }\r
342 \r
343 bool AudioWin::saveOptionstoServer()\r
344 {\r
345     if (audiofilterselected!=-1) {\r
346         VDR::getInstance()->configSave("DirectShow",\r
347             "AudioFilter",audiofilterlist[audiofilterselected].displayname);\r
348     }\r
349     if (mp3audiofilterselected!=-1) {\r
350         VDR::getInstance()->configSave("DirectShow",\r
351             "Mp3AudioFilter",mp3audiofilterlist[mp3audiofilterselected].displayname);\r
352     }\r
353     return true;\r
354 }\r
355 \r
356 UINT AudioWin::DeliverMediaSample(UCHAR* buffer, UINT *samplepos)\r
357 {\r
358   DeliverMediaPacket(mediapacket, buffer, samplepos);\r
359   if (*samplepos == mediapacket.length) {\r
360     *samplepos = 0;\r
361     return 1;\r
362   }\r
363   else return 0;\r
364 }\r
365 \r
366 UINT AudioWin::DeliverMediaPacket(const MediaPacket packet,\r
367      UCHAR* buffer,\r
368      UINT *samplepos)\r
369 {\r
370 \r
371   /*First Check, if we have an audio sample*/\r
372   VideoWin *vw=(VideoWin*)Video::getInstance();\r
373  if (!vw->isdsinited()) return 0;\r
374   if (vw->InIframemode()) {\r
375                 samplepos=0;\r
376                 MILLISLEEP(10);\r
377                 return 0; //Not in iframe mode!\r
378   }\r
379   IMediaSample* ms=NULL;\r
380   REFERENCE_TIME reftime1=0;\r
381   REFERENCE_TIME reftime2=0;\r
382 \r
383   UINT headerstrip=0;\r
384   if (packet.disconti) {\r
385     firstsynched=false;\r
386     vw->DeliverAudioMediaSample();\r
387   }\r
388 \r
389   if (packet.type!=vw->lastAType()){//Format Change //Push data out !\r
390       firstsynched=false;\r
391       vw->DeliverAudioMediaSample();\r
392   }\r
393 \r
394 \r
395 \r
396   /*Inspect PES-Header */\r
397 /*  UINT header_length=buffer[(packet.pos_buffer+8)%bufferlength]+8/*is this right*;\r
398 */\r
399   if (*samplepos==0 && packet.type!=MPTYPE_MPEG_AUDIO_LAYER3) {//stripheader\r
400       headerstrip=buffer[packet.pos_buffer+8]+9;\r
401     if (packet.type == MPTYPE_AC3) headerstrip+=4; //skip ac3 bytes\r
402     *samplepos+=headerstrip;\r
403     if ( packet.synched ) {\r
404       vw->DeliverAudioMediaSample();//write out old data\r
405       reftime1=packet.presentation_time;\r
406       reftime2=reftime1+1;\r
407       firstsynched=true;\r
408     } else {\r
409       if (!firstsynched) {//\r
410         *samplepos=packet.length;//if we have not processed at least one\r
411         return packet.length;//synched packet ignore it!\r
412       }\r
413     }\r
414   }\r
415   BYTE *ms_buf;\r
416   UINT ms_length;\r
417   UINT ms_pos;\r
418   UINT haveToCopy;\r
419   if (!vw->getCurrentAudioMediaSample(&ms) || ms==NULL) {// get the current sample\r
420     //samplepos=0;\r
421     //MILLISLEEP(10);\r
422     return *samplepos;\r
423   }\r
424   ms_pos=ms->GetActualDataLength();\r
425   ms_length=ms->GetSize();\r
426   haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);\r
427   if ((ms_length-ms_pos)<1) {\r
428     vw->DeliverAudioMediaSample(); //we are full!\r
429     if (!vw->getCurrentAudioMediaSample(&ms) || ms==NULL) {// get the current sample\r
430       //samplepos=0;\r
431       //MILLISLEEP(10);\r
432       return *samplepos;\r
433     }\r
434     ms_pos=ms->GetActualDataLength();\r
435     ms_length=ms->GetSize();\r
436     haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);\r
437   }\r
438   ms->GetPointer(&ms_buf);\r
439 \r
440 \r
441   if (ms_pos==0) {//will only be changed on first packet\r
442     if (packet.disconti) {\r
443       ms->SetDiscontinuity(TRUE);\r
444     } else {\r
445       ms->SetDiscontinuity(FALSE);\r
446     }\r
447     if (packet.synched) {\r
448       ms->SetSyncPoint(TRUE);\r
449       ms->SetTime(&reftime1,&reftime2);\r
450 \r
451       //ms->SetTime(NULL,NULL);\r
452       ms->SetMediaTime(NULL, NULL);\r
453     if (reftime1<0) ms->SetPreroll(TRUE);\r
454     else ms->SetPreroll(FALSE);\r
455     }else {\r
456       ms->SetSyncPoint(FALSE);\r
457       ms->SetTime(NULL,NULL);\r
458       ms->SetMediaTime(NULL, NULL);\r
459     ms->SetPreroll(FALSE);\r
460     //  ms->SetSyncPoint(TRUE);\r
461     }\r
462   }\r
463   if (packet.type!=vw->lastAType()) {\r
464       vw->changeAType(packet.type,ms);\r
465       ms->SetDiscontinuity(TRUE);\r
466   }\r
467 \r
468 \r
469   memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy);\r
470 \r
471     ms->SetActualDataLength(haveToCopy+ms_pos);\r
472 \r
473   *samplepos+=haveToCopy;\r
474 \r
475   return haveToCopy+headerstrip;\r
476 \r
477 }\r
478 \r
479 int AudioWin::dsInitAudioFilter(IGraphBuilder* dsgraphbuilder)\r
480 {\r
481     HRESULT hres;\r
482     IFilterGraph2*fg2=NULL;\r
483     VideoWin *vw=(VideoWin*)Video::getInstance();\r
484     if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!= S_OK)\r
485     {\r
486         Log::getInstance()->log("AudiooWin", Log::WARN , "Failed querying for FilterGraph2 Interface!");\r
487         return 0;\r
488     }\r
489     IBaseFilter*audiofilter;\r
490     if (aud_type!=Audio::MP3) {\r
491         audiofilter = getAudioFilter();\r
492     } else {\r
493         audiofilter = getMp3AudioFilter();\r
494     }\r
495     if (dsgraphbuilder->AddFilter(audiofilter,NULL) != S_OK)\r
496     {\r
497         Log::getInstance()->log("AudioWin", Log::WARN , "Failed adding Video Filter!");\r
498         return 0;\r
499     }\r
500     IEnumPins *pinenum=NULL;\r
501     bool error=false;\r
502     if (audiofilter->EnumPins(&pinenum) == S_OK)\r
503     {\r
504         IPin *current=NULL;\r
505         ULONG fetch=0;\r
506         bool firststep=false;\r
507         while (pinenum->Next(1,&current,&fetch)==S_OK)\r
508         {\r
509             PIN_DIRECTION dir;\r
510             if (current->QueryDirection(&dir)==S_OK)\r
511             {\r
512                 if (dir == PINDIR_INPUT)\r
513                 {\r
514                     if (vw->getSourceFilter()->GetAudioPin()->Connect(current,NULL)==S_OK)\r
515                     {\r
516                         current->Release();\r
517                         firststep=true;\r
518                             break;\r
519                     }\r
520                 }\r
521             }\r
522             current->Release();\r
523         }\r
524         if (firststep==false)\r
525         {\r
526             Log::getInstance()->log("AudioWin", Log::WARN , "Audio Filter has no suitable input!");\r
527             audiofilter->Release();\r
528             return 0;\r
529         }\r
530         bool secondstep=false;\r
531         pinenum->Reset();\r
532         while (pinenum->Next(1,&current,&fetch)==S_OK)\r
533         {\r
534             PIN_DIRECTION dir;\r
535             if (current->QueryDirection(&dir)==S_OK)\r
536             {\r
537                 if (dir == PINDIR_OUTPUT)\r
538                 {\r
539                    \r
540                     if (fg2->RenderEx((IPin*)current/*video*/,\r
541                                 0,NULL) ==S_OK)\r
542                     {\r
543                         current->Release();\r
544                         secondstep=true;\r
545                         break;\r
546                     }\r
547                 }\r
548             }\r
549             current->Release();\r
550         }\r
551         if (secondstep==false)\r
552         {\r
553            Log::getInstance()->log("AudioWin", Log::WARN , "Audio Filter has no suitable output!");\r
554            audiofilter->Release();\r
555            \r
556            return 0;\r
557         }\r
558             \r
559         audiofilter->Release();\r
560         pinenum->Release();\r
561 \r
562     }\r
563 \r
564 \r
565 \r
566     fg2->Release();\r
567     return 1;\r
568 }\r
569 \r
570 \r
571 IBaseFilter *AudioWin::getAudioFilter()\r
572 {\r
573     IBaseFilter *curfilter= NULL;\r
574     bool notset=false;\r
575     if (audiofilterselected == -1)\r
576     {\r
577         int i;\r
578         for (i = 0;i <audiofilterlist.size();i++)\r
579         {\r
580             audiofilterselected = i;\r
581             notset=true;\r
582             break;\r
583         }\r
584     }\r
585     IBindCtx *bindctx=NULL;\r
586     if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;\r
587     IMoniker * moni=NULL;\r
588     LPCOLESTR name=new WCHAR[strlen(audiofilterlist[audiofilterselected].displayname)+1];\r
589     mbstowcs((wchar_t*)name,audiofilterlist[audiofilterselected].displayname,\r
590     strlen(audiofilterlist[audiofilterselected].displayname)+1);\r
591     ULONG eater;\r
592     if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)\r
593     {\r
594         if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)\r
595         {\r
596             if (curfilter != NULL && notset)\r
597             {\r
598                 VDR *vdr=VDR::getInstance();\r
599                 if (vdr != NULL)\r
600                 {\r
601                     vdr->configSave("DirectShow","AudioFilter",\r
602                         audiofilterlist[audiofilterselected].displayname);\r
603                 }\r
604             }\r
605                     \r
606             moni->Release();\r
607             delete [] name;\r
608             bindctx->Release();\r
609             return curfilter; \r
610         }\r
611         bindctx->Release();\r
612         delete [] name;\r
613         return NULL;         \r
614     }\r
615     return NULL; \r
616 }\r
617 \r
618 IBaseFilter *AudioWin::getMp3AudioFilter()\r
619 {\r
620     IBaseFilter *curfilter= NULL;\r
621     bool notset=false;\r
622     if (mp3audiofilterselected == -1)\r
623     {\r
624         int i;\r
625         for (i = 0;i <mp3audiofilterlist.size();i++)\r
626         {\r
627             mp3audiofilterselected = i;\r
628             notset=true;\r
629             break;\r
630         }\r
631     }\r
632     IBindCtx *bindctx=NULL;\r
633     if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;\r
634     IMoniker * moni=NULL;\r
635     LPCOLESTR name=new WCHAR[strlen(mp3audiofilterlist[mp3audiofilterselected].displayname)+1];\r
636     mbstowcs((wchar_t*)name,mp3audiofilterlist[mp3audiofilterselected].displayname,\r
637     strlen(mp3audiofilterlist[mp3audiofilterselected].displayname)+1);\r
638     ULONG eater;\r
639     if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)\r
640     {\r
641         if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)\r
642         {\r
643             if (curfilter != NULL && notset)\r
644             {\r
645                 VDR *vdr=VDR::getInstance();\r
646                 if (vdr != NULL)\r
647                 {\r
648                     vdr->configSave("DirectShow","Mp3AudioFilter",\r
649                         mp3audiofilterlist[mp3audiofilterselected].displayname);\r
650                 }\r
651             }\r
652                     \r
653             moni->Release();\r
654             delete [] name;\r
655             bindctx->Release();\r
656             return curfilter; \r
657         }\r
658         bindctx->Release();\r
659         delete [] name;\r
660         return NULL;         \r
661     }\r
662     return NULL; \r
663 }\r
664 \r
665 \r
666 bool AudioWin::addOptionPagesToWTB(WTabBar *wtb)\r
667 {\r
668     Boxx *box=new WWinAudioFilter();\r
669     wtb->addTab(tr("Audio Filter"), box);\r
670 \r
671     \r
672     box=new WWinMp3AudioFilter();\r
673     wtb->addTab(tr("Mp3 Audio Filter"), box);\r
674     \r
675 \r
676     return true;\r
677 }\r
678 \r
679 const AudioFilterDescList *AudioWin::getAudioFilterList(int &selected)\r
680 {\r
681     selected=audiofilterselected;\r
682     return &audiofilterlist;\r
683 }\r
684 \r
685 const AudioFilterDescList *AudioWin::getMp3AudioFilterList(int &selected)\r
686 {\r
687     selected=mp3audiofilterselected;\r
688     return &mp3audiofilterlist;\r
689 }\r
690 bool AudioWin::selectMp3AudioFilter(int filter)\r
691 {\r
692     mp3audiofilterselected=filter;\r
693     return true;\r
694     \r
695 }\r
696 \r
697 bool AudioWin::selectAudioFilter(int filter)\r
698 {\r
699     audiofilterselected=filter;\r
700     return true;\r
701     \r
702 }\r
703 \r
704 long long AudioWin::SetStartOffset(long long curreftime, bool *rsync){\r
705   VideoWin *vw=(VideoWin*)Video::getInstance();\r
706   return vw->SetStartAudioOffset(curreftime,rsync);\r
707 }\r
708 \r
709 void AudioWin::ResetTimeOffsets() {\r
710   VideoWin *vw=(VideoWin*)Video::getInstance();\r
711   vw->ResetTimeOffsets();\r
712 }\r
713 \r
714 bool AudioWin::supportsAc3(){\r
715     VideoWin *vw=(VideoWin*)Video::getInstance();\r
716     return vw->supportsAc3();\r
717 }\r
718 \r
719 #ifdef DEV\r
720 int AudioWin::test()\r
721 {\r
722   return 0;\r
723 }\r
724 #endif\r
725 \r
726 \r
727 \r