]> git.vomp.tv Git - vompclient.git/blob - vaudioselector.cc
Fix black background for 16:9 live TV on 4:3 screen
[vompclient.git] / vaudioselector.cc
1 /*
2     Copyright 2006 Chris Tallon, 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 "vaudioselector.h"
22
23 #include "input.h"
24 #include "colour.h"
25 #include "video.h"
26 #include "audio.h"
27 #include "boxstack.h"
28 #include "i18n.h"
29 #include "message.h"
30 #include "messagequeue.h"
31 #include "recinfo.h"
32 #include "log.h"
33 #include "channel.h"
34
35
36
37 VAudioSelector::VAudioSelector(void* tparent, bool* availableMpegAudioChannels,
38         bool* availableAc3AudioChannels, int currentAudioChannel, bool *availableSubtitleChannels,int*ttxtpages,
39         int currentSubtitleChannel,int currentSubtitleType, RecInfo* recInfo)
40 {
41   Log::getInstance()->log("VAS", Log::DEBUG, "%i", currentAudioChannel);
42
43
44   parent = tparent;
45
46   liveMode = false;
47   subtitles =false;
48   editsubtitles = false;
49
50   int i;
51   if (availableSubtitleChannels != NULL) {
52       for (i = 0; i < PES_DVBSUBTITLE_MAXCHANNELS; i++) {
53           if (availableSubtitleChannels[i])
54           {
55               AudioSubtitleChannel* sc = new AudioSubtitleChannel();
56               sc->type = 0x10;//dvbsubtitle
57               sc->name = NULL;
58               sc->pestype = PES_DVBSUBTITLE_START+ i;
59               scl.push_back(sc);
60           }
61       }
62       for (i=0;i<10;i++) {
63           if (ttxtpages[i]>0) {
64               AudioSubtitleChannel* sc = new AudioSubtitleChannel();
65               int length=strlen(tr("TTxt:"))+1+1+3+1;
66               sc->type = 0x11;//Teletxt
67               sc->name = new char[length];
68               SNPRINTF(sc->name,length,"%s %3x",tr("TTxt:"),ttxtpages[i]);
69               sc->pestype = ttxtpages[i];
70               scl.push_back(sc);
71           }
72       }
73   }
74
75   if (scl.size()>0) {
76         AudioSubtitleChannel* sc = new AudioSubtitleChannel();
77         sc->type = 0xFF;//special
78         sc->name = new char[strlen(tr("No Subtitles"))+1];
79         strcpy(sc->name,tr("No Subtitles"));
80         sc->pestype = 0;
81         scl.insert(scl.begin(),sc);
82         subtitles=true;
83   }
84
85
86
87   if (subtitles) {
88       setSize(400, 120);
89   } else {
90       setSize(200, 120);
91   }
92
93   createBuffer();
94
95   asl.setPosition(40, 30);
96   asl.setSize(200 - 45, area.h - 30);
97   add(&asl);
98
99   if (subtitles) {
100       ssl.setPosition(200+40,30);
101       ssl.setSize(200 - 45, area.h - 30);
102       add(&ssl);
103   }
104
105   // Load data from availableAudioChannels, currentAudioChannel and recInfo
106
107
108   for (i = 0; i < PES_AUDIO_MAXCHANNELS; i++)
109   {
110     if (availableMpegAudioChannels[i])
111     {
112       AudioSubtitleChannel* ac = new AudioSubtitleChannel();
113       ac->type = 0;
114       ac->name = NULL;
115       ac->pestype = PES_AUDIO_START + i;
116       acl.push_back(ac);
117     }
118   }
119   if (availableAc3AudioChannels != NULL)
120   {
121     for (i = 0; i < PES_AUDIO_AC3_MAXCHANNELS; i++)
122     {
123       if (availableAc3AudioChannels[i])
124       {
125         AudioSubtitleChannel* ac = new AudioSubtitleChannel();
126         ac->type = 1;//ac3
127         ac->name = NULL;
128         ac->pestype = PES_AUDIO_AC3_START + i;
129         acl.push_back(ac);
130       }
131     }
132   }
133
134
135
136       
137
138
139   unsigned char numchan_recinfo = recInfo->numComponents;
140   unsigned char numchan_siz = acl.size();
141   unsigned char numchan_subtitles_siz = scl.size();
142   int mp_audcounter = 0;
143   int ac3_counter = 0;
144   int ac3_offset = 0;
145   int dvb_subcounter = 1;
146
147   for (i = 0; i < numchan_siz; i++)
148   {
149     AudioSubtitleChannel* ac = acl[i];
150     if (ac)
151     {
152       if (ac->type==0)
153       {
154         ac3_offset++;
155       }
156     }
157   }
158
159   unsigned char type;
160   char* lang;
161   char* description;
162   int type_int;
163
164   for (i = 0; i < numchan_recinfo; i++)
165   {   
166     
167     type = recInfo->types[i];
168     lang = recInfo->languages[i];
169     description = recInfo->descriptions[i];
170     AudioSubtitleChannel* ac = NULL;
171     type_int = 0;
172     if (recInfo->streams[i] == 2) {
173         switch (type)
174         {
175         case 1: //mpaudio mono
176         case 3: //mpaudio stereo
177             if (mp_audcounter < numchan_siz) ac = acl[mp_audcounter];
178             type_int = 0;
179             break;
180         case 5: //ac3
181             if (ac3_counter + ac3_offset < numchan_siz) ac = acl[ac3_counter + ac3_offset];
182             type_int = 1;
183             break;
184         }
185     } else if (recInfo->streams[i] == 3){
186       /*  switch (type)
187         {
188         case 20:*/
189             if (dvb_subcounter < numchan_subtitles_siz) ac = scl[dvb_subcounter];
190             type_int=0x10;
191        /*     break;
192         };*/
193     } else continue; //neither audio nor subtitle
194
195     if (ac)
196     {
197       if (ac->type == type_int)
198       {
199         if (description && (strlen(description) > 0))
200         {
201           ac->name = new char[strlen(description)+1];
202           strcpy(ac->name, description);
203         }
204         else if (lang && (strlen(lang) > 0))
205         {
206           ac->name = new char[strlen(lang)+1];
207           strcpy(ac->name, lang);
208         }
209       }
210     }
211
212     switch (type_int)
213     {
214       case 0: //mpaudio
215         mp_audcounter++;
216         break;
217       case 1: //ac3
218         ac3_counter++;
219         break;
220       case 0x10:
221           dvb_subcounter++;
222         break;
223     }
224   }
225
226   // Now do display
227
228   char tempString[300];
229   int audioChannelListSize = acl.size();
230
231   if (audioChannelListSize)
232   {
233     for(i = 0; i < audioChannelListSize; i++)
234     {
235       AudioSubtitleChannel* ac = acl[i];
236
237       if (ac->name)
238       {
239         asl.addOption(ac->name, ac, (ac->pestype == currentAudioChannel));
240       }
241       else
242       {
243         if (ac->type==0)
244         {
245           SNPRINTF(tempString, 299, "%lu", (ULONG)(ac->pestype - PES_AUDIO_START));
246         }
247         else if (ac->type==1)
248         {
249           SNPRINTF(tempString, 299, "ac3 %lu", (ULONG)(ac->pestype - PES_AUDIO_AC3_START));
250         }
251         else
252         {
253           SNPRINTF(tempString, 299, "unknown");
254         }
255         asl.addOption(tempString, ac, (ac->pestype == currentAudioChannel));
256       }
257     }
258   }
259   else
260   {
261     asl.addOption(tr("No audio channel data available"), 0, 1);
262   }
263
264   int subtitlesChannelListSize = scl.size();
265
266   if (subtitles) {
267       ssl.setDarkSelOption(true);
268       for(i = 0; i < subtitlesChannelListSize; i++)
269       {
270           AudioSubtitleChannel* sc = scl[i];
271           bool selected=false;
272           if (sc->pestype == currentSubtitleChannel && sc->type ==currentSubtitleType) selected=true;
273
274           if (sc->name)
275           {
276               ssl.addOption(sc->name, sc, selected);
277           }
278           else
279           {
280               if (sc->type==0x10)
281               {
282                   SNPRINTF(tempString, 299, "%lu", (ULONG)(sc->pestype - PES_DVBSUBTITLE_START));
283               }
284               else
285               {
286                   SNPRINTF(tempString, 299, "unknown");
287               }
288               ssl.addOption(tempString, sc, selected);
289           }
290       }
291   }
292
293 }
294
295 VAudioSelector::VAudioSelector(void* tparent, Channel* channel, int currentAudioChannel,int currentSubtitletype,int currentSubtitleChannel,int*ttxtpages)
296 {
297   parent = tparent;
298
299   liveMode = true;
300   editsubtitles = false;
301   subtitles =false;
302   UINT i;
303   
304   for (i = 0; i < channel->numSPids; i++)
305   {
306       AudioSubtitleChannel* sc = new AudioSubtitleChannel();
307       sc->type = 0x10;
308       sc->name = new char[strlen(channel->spids[i].desc) + 1];
309       strcpy(sc->name, channel->spids[i].desc);
310       sc->pestype = channel->spids[i].pid;
311       scl.push_back(sc);  
312   }
313   if (ttxtpages) {
314      for (i=0;i<10;i++) {
315           if (ttxtpages[i]>0) {
316             AudioSubtitleChannel* sc = new AudioSubtitleChannel();
317             int length=strlen(tr("TTxt:"))+1+1+3+1;
318             sc->type = 0x11;//Teletxt
319             sc->name = new char[length];
320             SNPRINTF(sc->name,length,"%s %3x",tr("TTxt:"),ttxtpages[i]);
321             sc->pestype = ttxtpages[i];
322             scl.push_back(sc);
323           }
324      }
325   }
326   
327
328   if (scl.size()>0) {
329         AudioSubtitleChannel* sc = new AudioSubtitleChannel();
330         sc->type = 0xFF;//special
331         sc->name = new char[strlen(tr("No Subtitles"))+1];
332         strcpy(sc->name,tr("No Subtitles"));
333         sc->pestype = 0;
334         scl.insert(scl.begin(),sc);
335         subtitles=true;
336   }
337
338
339
340   if (subtitles) {
341       setSize(400, 120);
342   } else {
343       setSize(200, 120);
344   }
345   createBuffer();
346
347   
348   asl.setPosition(40, 30);
349   asl.setSize(200 - 45, area.h - 30);
350   add(&asl);
351
352   if (subtitles) {
353       ssl.setPosition(200+40,30);
354       ssl.setSize(200 - 45, area.h - 30);
355       add(&ssl);
356   }
357
358   // Load data from availableAudioChannels, currentAudioChannel and recInfo
359
360   for (i = 0; i < channel->numAPids; i++)
361   {
362     AudioSubtitleChannel* ac = new AudioSubtitleChannel();
363     ac->type = 0;
364     ac->name = new char[strlen(channel->apids[i].desc) + 1];
365     strcpy(ac->name, channel->apids[i].desc);
366     ac->pestype = channel->apids[i].pid;
367     ac->streamtype=channel->apids[i].type;
368     if (Audio::getInstance()->streamTypeSupported(ac->streamtype))acl.push_back(ac);
369   }
370   
371   if (Audio::getInstance()->supportsAc3())
372   {
373     for (i = 0; i < channel->numDPids; i++)
374     {
375       AudioSubtitleChannel* ac = new AudioSubtitleChannel();
376       ac->type = 1;
377       ac->name = new char[strlen(channel->dpids[i].desc) + 1];
378       strcpy(ac->name, channel->dpids[i].desc);
379       ac->pestype = channel->dpids[i].pid;
380       ac->streamtype=channel->dpids[i].type;
381       if (Audio::getInstance()->streamTypeSupported(ac->streamtype))acl.push_back(ac);
382     }
383   }
384     
385   int audioChannelListSize = acl.size();
386
387   if (audioChannelListSize)
388   {
389     for(int j = 0; j < audioChannelListSize; j++)
390     {
391       AudioSubtitleChannel* ac = acl[j];
392       asl.addOption(ac->name, ac, (ac->pestype == currentAudioChannel));
393     }
394   }
395   else
396   {
397     asl.addOption(tr("No audio channel data available"), 0, 1);
398   }
399  int subtitlesChannelListSize = scl.size();
400
401   if (subtitles) {
402       ssl.setDarkSelOption(true);
403       for(int j = 0; j < subtitlesChannelListSize; j++)
404       {
405           AudioSubtitleChannel* sc = scl[j];
406           bool selected=false;
407           if ((sc->type==currentSubtitletype) && (sc->pestype == currentSubtitleChannel)) selected=true;
408           ssl.addOption(sc->name, sc, selected);
409           
410       }
411   }
412 }
413
414 VAudioSelector::~VAudioSelector()
415 {
416   int audioChannelListSize = acl.size();
417   for(int i = 0; i < audioChannelListSize; i++)
418   {
419     // FIXME memory leak - nobody is deleting audio channel name? // try:
420     delete[] acl[i]->name;
421     Log::getInstance()->log("VAudioSelector", Log::DEBUG, "Deleted char[] on close");
422     delete acl[i];
423   }
424   acl.clear();
425
426   asl.clear();
427
428   int subtitleChannelListSize = scl.size();
429   for(int i = 0; i < subtitleChannelListSize; i++)
430   {
431     // FIXME memory leak - nobody is deleting audio channel name? // try:
432     delete[] scl[i]->name;
433     Log::getInstance()->log("VAudioSelector", Log::DEBUG, "Deleted char[] on close");
434     delete scl[i];
435   }
436   scl.clear();
437
438   ssl.clear();
439
440   Message* m = new Message();
441   m->from = this;
442   m->to = parent;
443   m->message = Message::CHILD_CLOSE;
444   MessageQueue::getInstance()->postMessage(m);
445 }
446
447 void VAudioSelector::draw()
448 {
449   TBBoxx::draw();
450   
451   // FIXME bad drawing
452   
453   rectangle(0, 0, area.w, 30, DrawStyle::TITLEBARBACKGROUND);
454   drawText(tr("Audio"), 45, 5, DrawStyle::LIGHTTEXT);
455   if (subtitles) {
456       drawText(tr("Subtitles"), 45+200, 5, DrawStyle::LIGHTTEXT);
457
458       ssl.setBackgroundColour(backgroundColour);
459       ssl.draw();
460   }
461   asl.setBackgroundColour(backgroundColour);
462   asl.draw();
463
464   
465 }
466
467 int VAudioSelector::handleCommand(int command)
468 {
469   switch (command)
470   {
471     case Input::BACK:
472     case Input::OK:
473     case Input::GREEN:
474     {
475       return 4;
476     }
477     case Input::UP:
478     {
479         if (editsubtitles) {
480             ssl.up();
481             ssl.draw();
482             BoxStack::getInstance()->update(this);
483             Message* m = new Message();
484             m->from = this;
485             m->to = parent;
486             m->message = Message::SUBTITLE_CHANGE_CHANNEL;
487             m->parameter = (((AudioSubtitleChannel*)ssl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)ssl.getCurrentOptionData())->type &0xFF)<<16 ;
488             MessageQueue::getInstance()->postMessage(m);
489         } else {
490             asl.up();
491             asl.draw();
492             BoxStack::getInstance()->update(this);
493             Message* m = new Message();
494             m->from = this;
495             m->to = parent;
496             m->message = Message::AUDIO_CHANGE_CHANNEL;
497             m->parameter = (((AudioSubtitleChannel*)asl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)asl.getCurrentOptionData())->type &0xFF)<<16 ;
498             MessageQueue::getInstance()->postMessage(m);
499         }
500
501       return 2;
502     }
503     case Input::DOWN:
504     {
505         if (editsubtitles) {
506             ssl.down();
507             ssl.draw();
508             BoxStack::getInstance()->update(this);
509             Message* m = new Message();
510             m->from = this;
511             m->to = parent;
512             m->message = Message::SUBTITLE_CHANGE_CHANNEL;
513             m->parameter = (((AudioSubtitleChannel*)ssl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)ssl.getCurrentOptionData())->type &0xFF)<<16
514                         |(((AudioSubtitleChannel*)asl.getCurrentOptionData())->streamtype &0xFF)<<24 ;
515             MessageQueue::getInstance()->postMessage(m);
516         } else {
517             asl.down();
518             asl.draw();
519             BoxStack::getInstance()->update(this);
520             Message* m = new Message();
521             m->from = this;
522             m->to = parent;
523             m->message = Message::AUDIO_CHANGE_CHANNEL;
524             m->parameter = (((AudioSubtitleChannel*)asl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)asl.getCurrentOptionData())->type &0xFF)<<16
525                         |(((AudioSubtitleChannel*)asl.getCurrentOptionData())->streamtype &0xFF)<<24 ;
526             MessageQueue::getInstance()->postMessage(m);
527         }
528
529       return 2;
530     }
531     case Input::LEFT:
532      {
533         if (editsubtitles && subtitles) {
534             ssl.setDarkSelOption(true);
535             asl.setDarkSelOption(false);
536             editsubtitles=false;
537             asl.draw();
538             ssl.draw();
539             BoxStack::getInstance()->update(this);
540         }
541         return 2;
542      }
543      case Input::RIGHT:
544      {
545          if (!editsubtitles && subtitles) {
546              ssl.setDarkSelOption(false);
547              asl.setDarkSelOption(true);
548              editsubtitles=true;
549              asl.draw();
550              ssl.draw();
551              BoxStack::getInstance()->update(this);
552          }
553         return 2;
554      }
555   }
556
557   return 1;
558 }
559
560 void VAudioSelector::processMessage(Message* m)
561 {
562   if (m->message == Message::MOUSE_MOVE)
563   {
564     
565       UINT lastsel=asl.getCurrentOption();
566       
567       if (((m->parameter>>16)-getScreenX()) < 200 && asl.mouseMove((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY()))
568       {
569           editsubtitles=false;
570           ssl.setDarkSelOption(true);
571           asl.setDarkSelOption(false);
572           asl.draw();
573           ssl.draw();
574           BoxStack::getInstance()->update(this);
575           if ((int)lastsel!=asl.getCurrentOption()) 
576           { 
577               Message* m2 = new Message();
578               m2->from = this;
579               m2->to = parent;
580               m2->message = Message::AUDIO_CHANGE_CHANNEL;
581               m2->parameter = (((AudioSubtitleChannel*)asl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)asl.getCurrentOptionData())->type &0xFF)<<16 ;
582               MessageQueue::getInstance()->postMessage(m2);
583           }
584           return;
585         
586       }
587       lastsel=ssl.getCurrentOption();
588       
589       if (ssl.mouseMove((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY()))
590       {
591          editsubtitles=true;
592          ssl.setDarkSelOption(false);
593          asl.setDarkSelOption(true);
594          asl.draw();
595          ssl.draw();
596          BoxStack::getInstance()->update(this);
597          if ((int)lastsel!=ssl.getCurrentOption()) 
598          { 
599               Message* m2 = new Message();
600               m2->from = this;
601               m2->to = parent;
602               m2->message = Message::SUBTITLE_CHANGE_CHANNEL;
603               m2->parameter = (((AudioSubtitleChannel*)ssl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)ssl.getCurrentOptionData())->type &0xFF)<<16 ;
604               MessageQueue::getInstance()->postMessage(m2);
605           }
606          return;
607      } 
608   }
609   else if (m->message == Message::MOUSE_LBDOWN)
610   {
611     if (asl.mouseLBDOWN((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY()))
612     {
613       editsubtitles=false;
614       ssl.setDarkSelOption(true);
615       asl.setDarkSelOption(false);
616       asl.draw();
617       ssl.draw();
618       BoxStack::getInstance()->handleCommand(Input::OK); //simulate OK press
619     }
620     else if (ssl.mouseLBDOWN((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY()))
621     {
622       editsubtitles=true;
623       ssl.setDarkSelOption(false);
624       asl.setDarkSelOption(true);
625       asl.draw();
626       ssl.draw();
627       BoxStack::getInstance()->handleCommand(Input::OK); //simulate OK press
628     }
629     else
630     { //check if press is outside this view! then simulate cancel
631       int x=(m->parameter>>16)-getScreenX();
632       int y=(m->parameter&0xFFFF)-getScreenY();
633       if (x<0 || y <0 || x>(int)getWidth() || y>(int)getHeight())
634       {
635         BoxStack::getInstance()->handleCommand(Input::BACK); //simulate cancel press
636       }
637     }
638   }
639 }
640