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