]> git.vomp.tv Git - vompclient.git/blob - audiovpe.cc
Switch back to system libav and add audio options
[vompclient.git] / audiovpe.cc
1 /*
2     Copyright 2004-2005 Chris Tallon, 2009 Marten Richter
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21 #include "audiovpe.h"
22 #include "videovpeogl.h"
23 #include "log.h"
24 #include "vdr.h"
25 #include "woptionpane.h"
26
27 AudioVPE::AudioVPE()
28 {
29   initted = 0;
30   lastpacketnum=-1;
31   currentpacketnum=-1;
32   streamType = 0;
33   volume = 20;
34   muted = 0;
35   lastAType = MPTYPE_MPEG_AUDIO;
36
37   canpass_ac3=false;
38   canpass_mp2=false;
39   canpass_mp3=false;
40   canpass_pcm_mch=false;
41
42   prefered_ac3=0; //0 stereo PCM, 1 passthrough 2 Multichannel PCM
43   prefered_mp2=0;
44   prefered_mp3=0;
45 }
46
47 AudioVPE::~AudioVPE()
48 {
49 }
50
51 int AudioVPE::init(UCHAR tstreamType)
52 {
53   if (initted) return 0;
54   initted = 1;
55
56 // // if ((fdAudio = open("/dev/adec_mpg", O_RDWR | O_NONBLOCK)) < 0) return 0;
57  // if ((fdAudio = open("/dev/adec_mpg", O_WRONLY)) < 0) return 0;
58
59   streamType = tstreamType;
60
61   if (!initAllParams())
62   {
63     shutdown();
64     return 0;
65   }
66
67   unMute();
68
69   // Set the volume variable to what the hardware is set at now
70   int hwvol = -1;
71 /*  int hwvolFail = ioctl(fdAudio, AV_GET_AUD_VOLUME, &hwvol);
72   if (!hwvolFail)
73   {
74     volume = 20 - ((hwvol >> 16) & 0xFF);
75     if ((volume < 0) || (volume > 20)) volume = 20;
76   }*/
77
78   return 1;
79 }
80
81 int AudioVPE::initAllParams()
82 {
83   return (setStreamType(streamType) && setChannel() && setSource());
84 }
85
86 int AudioVPE::shutdown()
87 {
88   if (!initted) return 0;
89   initted = 0;
90   //close(fdAudio);
91   return 1;
92 }
93
94 bool AudioVPE::loadOptionsfromServer(VDR* vdr)
95 {
96     char *name=vdr->configLoad("AudioOMX","AC3DecodingMode");
97
98     if (name != NULL) {
99                 if (STRCASECMP(name, "PCM") == 0) {
100                         prefered_ac3 = 0;
101                 } else if (STRCASECMP(name, "Passthrough") == 0) {
102                         prefered_ac3 = 1;
103                 } else if (STRCASECMP(name, "PCMMultichannel") == 0) {
104                         prefered_ac3 = 2;
105                 }
106         }
107
108     name = vdr->configLoad("AudioOMX", "Mp2DecodingMode");
109
110         if (name != NULL) {
111                 if (STRCASECMP(name, "PCM") == 0) {
112                         prefered_mp2 = 0;
113                 } else if (STRCASECMP(name, "Passthrough") == 0) {
114                         prefered_mp2 = 1;
115                 } else if (STRCASECMP(name, "PCMMultichannel") == 0) {
116                         prefered_mp2 = 2;
117                 }
118         }
119
120         name = vdr->configLoad("AudioOMX", "Mp3DecodingMode");
121
122         if (name != NULL) {
123                 if (STRCASECMP(name, "PCM") == 0) {
124                         prefered_mp3 = 0;
125                 } else if (STRCASECMP(name, "Passthrough") == 0) {
126                         prefered_mp3 = 1;
127                 } else if (STRCASECMP(name, "PCMMultichannel") == 0) {
128                         prefered_mp3 = 2;
129                 }
130         }
131
132         name = vdr->configLoad("AudioOMX", "AudioOutput");
133
134         if (name != NULL) {
135                 if (STRCASECMP(name, "analog") == 0) {
136                         hdmi = false;
137                 } else if (STRCASECMP(name, "HDMI") == 0) {
138                         hdmi = true;
139                 }
140         }
141
142
143    return true;
144
145 }
146
147 bool AudioVPE::handleOptionChanges(Option* option)
148 {
149     if (Audio::handleOptionChanges(option))
150                 return true;
151         switch (option->id) {
152         case 4: {
153                 if (STRCASECMP(option->options[option->userSetChoice], "analog") == 0) {
154                         hdmi = false;
155                 } else if (STRCASECMP(option->options[option->userSetChoice], "HDMI")
156                                 == 0) {
157                         hdmi = true;
158                 }
159                 return true;
160         }
161                 break;
162         case 1: {
163                 if (STRCASECMP(option->options[option->userSetChoice], "PCM") == 0) {
164                         prefered_ac3 = 0;
165                 } else if (STRCASECMP(option->options[option->userSetChoice],
166                                 "Passthrough") == 0) {
167                         prefered_ac3 = 1;
168                 } else if (STRCASECMP(option->options[option->userSetChoice],
169                                 "PCMMultichannel") == 0) {
170                         prefered_ac3 = 2;
171                 }
172         }
173                 break;
174         case 2: {
175                 if (STRCASECMP(option->options[option->userSetChoice], "PCM") == 0) {
176                         prefered_mp2 = 0;
177                 } else if (STRCASECMP(option->options[option->userSetChoice],
178                                 "Passthrough") == 0) {
179                         prefered_mp2 = 1;
180                 } else if (STRCASECMP(option->options[option->userSetChoice],
181                                 "PCMMultichannel") == 0) {
182                         prefered_mp2 = 2;
183                 }
184         }
185                 break;
186         case 3: {
187                 if (STRCASECMP(option->options[option->userSetChoice], "PCM") == 0) {
188                         prefered_mp3 = 0;
189                 } else if (STRCASECMP(option->options[option->userSetChoice],
190                                 "Passthrough") == 0) {
191                         prefered_mp3 = 1;
192                 } else if (STRCASECMP(option->options[option->userSetChoice],
193                                 "PCMMultichannel") == 0) {
194                         prefered_mp3 = 2;
195                 }
196         }
197                 break;
198         };
199         return false;
200
201 }
202
203 bool AudioVPE::saveOptionstoServer()
204 {
205
206     switch (prefered_ac3) {
207         case 0:
208                 VDR::getInstance()->configSave("AudioOMX", "AC3DecodingMode", "PCM");
209                 break;
210         case 1:
211                 VDR::getInstance()->configSave("AudioOMX", "AC3DecodingMode",
212                                 "Passthrough");
213                 break;
214         case 2:
215                 VDR::getInstance()->configSave("AudioOMX", "AC3DecodingMode",
216                                 "PCMMultichannel");
217                 break;
218         };
219
220         switch (prefered_mp2) {
221         case 0:
222                 VDR::getInstance()->configSave("AudioOMX", "Mp2DecodingMode", "PCM");
223                 break;
224         case 1:
225                 VDR::getInstance()->configSave("AudioOMX", "Mp2DecodingMode",
226                                 "Passthrough");
227                 break;
228         case 2:
229                 VDR::getInstance()->configSave("AudioOMX", "Mp2DecodingMode",
230                                 "PCMMultichannel");
231                 break;
232         };
233
234         switch (prefered_mp3) {
235         case 0:
236                 VDR::getInstance()->configSave("AudioOMX", "Mp3DecodingMode", "PCM");
237                 break;
238         case 1:
239                 VDR::getInstance()->configSave("AudioOMX", "Mp3DecodingMode",
240                                 "Passthrough");
241                 break;
242         case 2:
243                 VDR::getInstance()->configSave("AudioOMX", "Mp3DecodingMode",
244                                 "PCMMultichannel");
245                 break;
246         };
247
248         if (hdmi)
249                 VDR::getInstance()->configSave("AudioOMX", "AudioOutput", "analog");
250         else
251                 VDR::getInstance()->configSave("AudioOMX", "AudioOutput", "HDMI");
252
253
254     return true;
255 }
256
257 /*Option(UINT id, const char* displayText, const char* configSection, const char* configKey, UINT optionType,
258            UINT numChoices, UINT defaultChoice, UINT startInt,
259            const char * const * options, const char * const * optionkeys = NULL, AbstractOption* handler=NULL);*/
260
261 bool AudioVPE::addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane)
262 {
263     if (!Audio::addOptionsToPanes(panenumber,options,pane)) return false;
264
265
266     Option* option;
267     if (panenumber == 2)
268     {
269
270         static const char* audioopts[]={"analog","HDMI"};
271         option = new Option(4,tr("Audio Output"), "AudioOMX","AudioOutput",Option::TYPE_TEXT,2,0,0,audioopts,NULL,false,this);
272         options->push_back(option);
273         pane->addOptionLine(option);
274
275
276         char **ac3opts=new char *[3];
277         int i=0;
278         ac3opts[i]=new char[strlen("PCM")+1];
279         strcpy(ac3opts[i],"PCM");
280         i++;
281         if (canpass_ac3) {
282                 ac3opts[i]=new char[strlen("Passthrough")+1];
283             strcpy(ac3opts[i],"PassThrough");
284             i++;
285         }
286         if (canpass_pcm_mch) {
287                 ac3opts[i]=new char[strlen("PCMMultichannel")+1];
288             strcpy(ac3opts[i],"PCMMultichannel");
289             i++;
290         }
291         option = new Option(1 ,tr("AC3 HDMI Mode"), "AudioOMX", "AC3DecodingMode", Option::TYPE_TEXT, i, 0, 0, ac3opts,NULL,true, this);
292         options->push_back(option);
293         pane->addOptionLine(option);
294
295         char **mp2opts = new char *[3];
296                 i = 0;
297                 mp2opts[i] = new char[strlen("PCM") + 1];
298                 strcpy(mp2opts[i], "PCM");
299                 i++;
300                 if (canpass_mp2) {
301                         mp2opts[i] = new char[strlen("Passthrough") + 1];
302                         strcpy(mp2opts[i], "PassThrough");
303                         i++;
304                 }
305                 if (canpass_pcm_mch) {
306                         mp2opts[i] = new char[strlen("PCMMultichannel") + 1];
307                         strcpy(mp2opts[i], "PCMMultichannel");
308                         i++;
309                 }
310                 option = new Option(2, tr("Mp2 HDMI Mode"), "AudioOMX",
311                                 "Mp2DecodingMode", Option::TYPE_TEXT, i, 0, 0,
312                                 mp2opts, NULL, true, this);
313                 options->push_back(option);
314                 pane->addOptionLine(option);
315
316                 char **mp3opts = new char *[3];
317                 i = 0;
318                 mp3opts[i] = new char[strlen("PCM") + 1];
319                 strcpy(mp3opts[i], "PCM");
320                 i++;
321                 if (canpass_mp3) {
322                         mp3opts[i] = new char[strlen("Passthrough") + 1];
323                         strcpy(mp3opts[i], "PassThrough");
324                         i++;
325                 }
326                 if (canpass_pcm_mch) {
327                         mp3opts[i] = new char[strlen("PCMMultichannel") + 1];
328                         strcpy(mp3opts[i], "PCMMultichannel");
329                         i++;
330                 }
331                 option = new Option(3, tr("Mp3 HDMI Mode"), "AudioOMX",
332                                 "Mp2DecodingMode", Option::TYPE_TEXT, i, 0, 0, mp3opts,
333                                 NULL, true, this);
334                 options->push_back(option);
335                 pane->addOptionLine(option);
336
337
338     }
339
340     return true;
341 }
342
343
344
345
346 int AudioVPE::setStreamType(UCHAR type)
347 {
348   if (!initted) return 0;
349
350  // if (ioctl(fdAudio, AV_SET_AUD_STREAMTYPE, type) != 0) return 0;
351   return 1;
352 }
353
354 int AudioVPE::setChannel()
355 {
356   if (!initted) return 0;
357
358  // if (ioctl(fdAudio, AV_SET_AUD_CHANNEL, 0) != 0) return 0;
359   return 1;
360 }
361
362 int AudioVPE::setSource()
363 {
364   if (!initted) return 0;
365
366  // if (ioctl(fdAudio, AV_SET_AUD_SRC, 1) != 0) return 0;
367   return 1;
368 }
369
370 int AudioVPE::sync()
371 {
372   if (!initted) return 0;
373
374  // if (ioctl(fdAudio, AV_SET_AUD_SYNC, 2) != 0) return 0;
375   return 1;
376 }
377
378 int AudioVPE::play()
379 {
380   if (!initted) return 0;
381   lastpacketnum=-1;
382   currentpacketnum=-1;
383
384
385   //if (ioctl(fdAudio, AV_SET_AUD_PLAY, 0) != 0) return 0;
386   return 1;
387 }
388
389 int AudioVPE::stop()
390 {
391   if (!initted) return 0;
392
393   //if (ioctl(fdAudio, AV_SET_AUD_RESET, 0x11) != 0) return 0;
394   return 1;
395 }
396
397 int AudioVPE::mute()
398 {
399   if (!initted) return 0;
400
401 //  if (ioctl(fdAudio, AV_SET_AUD_MUTE, 1) != 0) return 0;
402   Log::getInstance()->log("Audio", Log::DEBUG, "MUTE MUTE MUTE");
403
404   muted = 1;
405   return 1;
406 }
407
408 int AudioVPE::unMute()
409 {
410   if (!initted) return 0;
411
412 //  if (ioctl(fdAudio, AV_SET_AUD_MUTE, 0) != 0) return 0;
413   Log::getInstance()->log("Audio", Log::DEBUG, "MUTE OFF OFF OFF");
414
415   muted = 0;
416   return 1;
417 }
418
419 int AudioVPE::pause()
420 {
421   if (!initted) return 0;
422
423  // if (ioctl(fdAudio, AV_SET_AUD_PAUSE, 1) != 0) return 0;
424   return 1;
425 }
426
427 int AudioVPE::unPause()
428 {
429   if (!initted) return 0;
430
431  // if (ioctl(fdAudio, AV_SET_AUD_UNPAUSE, 1) != 0) return 0;
432   return 1;
433 }
434
435 int AudioVPE::reset()
436 {
437   if (!initted) return 0;
438 //test();
439   Log::getInstance()->log("Audio", Log::DEBUG, "reset called");
440
441
442 //  if (ioctl(fdAudio, AV_SET_AUD_RESET, 0x11) != 0) return 0;
443 //  Log::getInstance()->log("Audio", Log::DEBUG, "reset back");
444  // if (ioctl(fdAudio, AV_SET_AUD_PLAY, 0) != 0) return 0;
445
446   doMuting();
447   return 1;
448 }
449
450 int AudioVPE::setVolume(int tvolume)
451 {
452   // parameter: 0 for silence, 20 for full
453   if ((tvolume < 0) || (tvolume > 20)) return 0;
454
455 // volume = 2 * (20 - volume);
456 // Right, that one was rubbish... 0-10 were almost
457 // inaudible, 11-20 did what should have been done
458 // over the whole 0-20 range
459
460   tvolume = 20 - tvolume;
461
462   audio_volume Avolume;
463   Avolume.frontleft = tvolume + Aoffset.frontleft;
464   Avolume.frontright = tvolume + Aoffset.frontright;
465   Avolume.rearleft = tvolume + Aoffset.rearleft;
466   Avolume.rearright = tvolume + Aoffset.rearright;
467   Avolume.center = tvolume + Aoffset.center;
468   Avolume.lfe = tvolume + Aoffset.lfe;
469
470 //  if (ioctl(fdAudio, AV_SET_AUD_VOLUME, &Avolume) != 0) return 0;
471
472 //  unsigned long vol = (tvolume << 24) | (tvolume << 16);
473 //
474 //  Log::getInstance()->log("Audio", Log::DEBUG, "%lx", vol);
475 //  Log::getInstance()->log("Audio", Log::DEBUG, "%i", tvolume);
476
477 //  if (ioctl(fdAudio, AV_SET_AUD_VOLUME, &vol) != 0) return 0;
478   return 1;
479 }
480
481 #ifdef DEV
482 int AudioVPE::test()
483 {
484 //  ULLONG stc = 0;
485 //  return ioctl(fdAudio, AV_SET_AUD_STC, &stc);
486
487 /*  aud_sync_parms_t a;
488   a.parm1 = 0;
489   a.parm2 = 0;
490 */
491 //  int b = ioctl(fdAudio, AV_SET_AUD_DISABLE_SYNC, &a);
492
493
494   /*OK*/ //printf("Audio sync disable = %i\n", b);
495
496   return 1;
497
498
499 }
500 #endif
501
502 void AudioVPE::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
503 {
504   packet = mplist.front();
505 }
506
507 UINT AudioVPE::DeliverMediaSample(UCHAR* buffer, UINT* samplepos)
508 {/*
509         VideoVPEOGL *video=(VideoVPEOGL*)Video::getInstance();
510         //Log::getInstance()->log("Audio", Log::DEBUG, "lastpacket %d lastbuddypacket %d currentpacket %d",lastpacketnum,video->getLastPacketNum(),packet.index);
511         currentpacketnum=packet.index;
512   if (lastpacketnum!=-1 && packet.index-1!=lastpacketnum && packet.index-1>video->getLastPacketNum()) return 0; //Not in order
513
514   //format pes
515   switch (packet.type) {
516           case MPTYPE_MPEG_AUDIO:
517                  buffer[packet.pos_buffer + 3]=0xc0; break;
518           case MPTYPE_AC3:
519                   buffer[packet.pos_buffer +buffer[packet.pos_buffer+8]+9]=0x80;
520                   buffer[packet.pos_buffer + 3]=0xbd; break;
521                   break;
522           default:
523           case MPTYPE_AC3_PRE13://Not tested no recording availiable
524                   buffer[packet.pos_buffer + 3]=0xbd; break;
525                   break;
526   };
527
528    if (packet.type!=lastAType && lastpacketnum!=-1){//Format Change //Push data out !
529       video->deinitMuxer();
530           lastAType=packet.type;
531           video->initMuxer();
532   }
533   lastAType=packet.type;
534
535
536  /* Mutex *mutex=video->getMuxMutex();
537   mutex->Lock();
538   FILE *muxout=video->getMuxFile();
539   if (!muxout) {mutex->Unlock(); return 0;}*
540   int written=0;
541   //written=fwrite(buffer + packet.pos_buffer,1,packet.length,muxout);
542   written=video->WriteOutTS(buffer + packet.pos_buffer,packet.length,packet.type);
543   lastpacketnum=packet.index;
544   
545   //mutex->Unlock();
546
547    //Log::getInstance()->log("Audio", Log::DEBUG, "wrote %d bytes to mux",written);
548   
549   if (written == (int)packet.length) { *samplepos = 0; return 1;}
550   if (written <= 0) {
551           return 0;
552   }
553   *samplepos = written;*/
554   // Handle a partial write. Is this possible? Should we bother? No!
555  
556   *samplepos=packet.length;
557   return 1;
558 }
559
560 void AudioVPE::ResetTimeOffsets()
561 {
562 }