]> git.vomp.tv Git - vompclient.git/blob - vaudioselector.cc
Rewritten vomp discovery protocol
[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 "remote.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 "command.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, (ULONG)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, (ULONG)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, (ULONG)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, (ULONG)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].name) + 1];
309       strcpy(sc->name, channel->spids[i].name);
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].name) + 1];
365     strcpy(ac->name, channel->apids[i].name);
366     ac->pestype = channel->apids[i].pid;
367     acl.push_back(ac);
368   }
369   
370   if (Audio::getInstance()->supportsAc3())
371   {
372     for (i = 0; i < channel->numDPids; i++)
373     {
374       AudioSubtitleChannel* ac = new AudioSubtitleChannel();
375       ac->type = 1;
376       ac->name = new char[strlen(channel->dpids[i].name) + 1];
377       strcpy(ac->name, channel->dpids[i].name);
378       ac->pestype = channel->dpids[i].pid;
379       acl.push_back(ac);
380     }
381   }
382     
383   int audioChannelListSize = acl.size();
384
385   if (audioChannelListSize)
386   {
387     for(int j = 0; j < audioChannelListSize; j++)
388     {
389       AudioSubtitleChannel* ac = acl[j];
390       asl.addOption(ac->name, (ULONG)ac, (ac->pestype == currentAudioChannel));
391     }
392   }
393   else
394   {
395     asl.addOption(tr("No audio channel data available"), 0, 1);
396   }
397  int subtitlesChannelListSize = scl.size();
398
399   if (subtitles) {
400       ssl.setDarkSelOption(true);
401       for(int j = 0; j < subtitlesChannelListSize; j++)
402       {
403           AudioSubtitleChannel* sc = scl[j];
404           bool selected=false;
405           if ((sc->type==currentSubtitletype) && (sc->pestype == currentSubtitleChannel)) selected=true;
406           ssl.addOption(sc->name, (ULONG)sc, selected);
407           
408       }
409   }
410 }
411
412 VAudioSelector::~VAudioSelector()
413 {
414   int audioChannelListSize = acl.size();
415   for(int i = 0; i < audioChannelListSize; i++)
416   {
417     // FIXME memory leak - nobody is deleting audio channel name? // try:
418     delete[] acl[i]->name;
419     Log::getInstance()->log("VAudioSelector", Log::DEBUG, "Deleted char[] on close");
420     delete acl[i];
421   }
422   acl.clear();
423
424   asl.clear();
425
426   int subtitleChannelListSize = scl.size();
427   for(int i = 0; i < subtitleChannelListSize; i++)
428   {
429     // FIXME memory leak - nobody is deleting audio channel name? // try:
430     delete[] scl[i]->name;
431     Log::getInstance()->log("VAudioSelector", Log::DEBUG, "Deleted char[] on close");
432     delete scl[i];
433   }
434   scl.clear();
435
436   ssl.clear();
437
438   Message* m = new Message();
439   m->from = this;
440   m->to = parent;
441   m->message = Message::CHILD_CLOSE;
442   Command::getInstance()->postMessageNoLock(m);
443 }
444
445 void VAudioSelector::draw()
446 {
447   TBBoxx::draw();
448   
449   // FIXME bad drawing
450   
451   rectangle(0, 0, area.w, 30, Colour::TITLEBARBACKGROUND);
452   drawText(tr("Audio"), 45, 5, Colour::LIGHTTEXT);
453   if (subtitles) {
454       drawText(tr("Subtitles"), 45+200, 5, Colour::LIGHTTEXT);
455       ssl.setBackgroundColour(backgroundColour);
456       ssl.draw();
457   }
458
459   asl.setBackgroundColour(backgroundColour);
460   asl.draw();
461
462   
463 }
464
465 int VAudioSelector::handleCommand(int command)
466 {
467   switch (command)
468   {
469     case Remote::BACK:
470     case Remote::OK:
471     case Remote::GREEN:
472     {
473       return 4;
474     }
475     case Remote::DF_UP:
476     case Remote::UP:
477     {
478         if (editsubtitles) {
479             ssl.up();
480             ssl.draw();
481             BoxStack::getInstance()->update(this);
482             Message* m = new Message();
483             m->from = this;
484             m->to = parent;
485             m->message = Message::SUBTITLE_CHANGE_CHANNEL;
486             m->parameter = (((AudioSubtitleChannel*)ssl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)ssl.getCurrentOptionData())->type &0xFF)<<16 ;
487             Command::getInstance()->postMessageNoLock(m);
488         } else {
489             asl.up();
490             asl.draw();
491             BoxStack::getInstance()->update(this);
492             Message* m = new Message();
493             m->from = this;
494             m->to = parent;
495             m->message = Message::AUDIO_CHANGE_CHANNEL;
496             m->parameter = (((AudioSubtitleChannel*)asl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)asl.getCurrentOptionData())->type &0xFF)<<16 ;
497             Command::getInstance()->postMessageNoLock(m);
498         }
499
500       return 2;
501     }
502     case Remote::DF_DOWN:
503     case Remote::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             Command::getInstance()->postMessageNoLock(m);
515         } else {
516             asl.down();
517             asl.draw();
518             BoxStack::getInstance()->update(this);
519             Message* m = new Message();
520             m->from = this;
521             m->to = parent;
522             m->message = Message::AUDIO_CHANGE_CHANNEL;
523             m->parameter = (((AudioSubtitleChannel*)asl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)asl.getCurrentOptionData())->type &0xFF)<<16 ;
524             Command::getInstance()->postMessageNoLock(m);
525         }
526
527       return 2;
528     }
529     case Remote::LEFT:
530     case Remote::DF_LEFT:
531      {
532         if (editsubtitles && subtitles) {
533             ssl.setDarkSelOption(true);
534             asl.setDarkSelOption(false);
535             editsubtitles=false;
536             asl.draw();
537             ssl.draw();
538             BoxStack::getInstance()->update(this);
539         }
540         return 2;
541      }
542      case Remote::RIGHT:
543      case Remote::DF_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               Command::getInstance()->postMessageNoLock(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               Command::getInstance()->postMessageNoLock(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(Remote::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(Remote::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(Remote::BACK); //simulate cancel press
636       }
637     }
638   }
639 }
640