]> git.vomp.tv Git - vompclient.git/blob - vaudioselector.cc
Fix resuming recording directly after stopping it
[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].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, (ULONG)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, (ULONG)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   Command::getInstance()->postMessageNoLock(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 Remote::BACK:
472     case Remote::OK:
473     case Remote::GREEN:
474     {
475       return 4;
476     }
477     case Remote::DF_UP:
478     case Remote::UP:
479     {
480         if (editsubtitles) {
481             ssl.up();
482             ssl.draw();
483             BoxStack::getInstance()->update(this);
484             Message* m = new Message();
485             m->from = this;
486             m->to = parent;
487             m->message = Message::SUBTITLE_CHANGE_CHANNEL;
488             m->parameter.num = (((AudioSubtitleChannel*)ssl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)ssl.getCurrentOptionData())->type &0xFF)<<16 ;
489             Command::getInstance()->postMessageNoLock(m);
490         } else {
491             asl.up();
492             asl.draw();
493             BoxStack::getInstance()->update(this);
494             Message* m = new Message();
495             m->from = this;
496             m->to = parent;
497             m->message = Message::AUDIO_CHANGE_CHANNEL;
498             m->parameter.num = (((AudioSubtitleChannel*)asl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)asl.getCurrentOptionData())->type &0xFF)<<16 ;
499             Command::getInstance()->postMessageNoLock(m);
500         }
501
502       return 2;
503     }
504     case Remote::DF_DOWN:
505     case Remote::DOWN:
506     {
507         if (editsubtitles) {
508             ssl.down();
509             ssl.draw();
510             BoxStack::getInstance()->update(this);
511             Message* m = new Message();
512             m->from = this;
513             m->to = parent;
514             m->message = Message::SUBTITLE_CHANGE_CHANNEL;
515             m->parameter.num = (((AudioSubtitleChannel*)ssl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)ssl.getCurrentOptionData())->type &0xFF)<<16
516                         |(((AudioSubtitleChannel*)asl.getCurrentOptionData())->streamtype &0xFF)<<24 ;
517             Command::getInstance()->postMessageNoLock(m);
518         } else {
519             asl.down();
520             asl.draw();
521             BoxStack::getInstance()->update(this);
522             Message* m = new Message();
523             m->from = this;
524             m->to = parent;
525             m->message = Message::AUDIO_CHANGE_CHANNEL;
526             m->parameter.num = (((AudioSubtitleChannel*)asl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)asl.getCurrentOptionData())->type &0xFF)<<16
527                         |(((AudioSubtitleChannel*)asl.getCurrentOptionData())->streamtype &0xFF)<<24 ;
528             Command::getInstance()->postMessageNoLock(m);
529         }
530
531       return 2;
532     }
533     case Remote::LEFT:
534     case Remote::DF_LEFT:
535      {
536         if (editsubtitles && subtitles) {
537             ssl.setDarkSelOption(true);
538             asl.setDarkSelOption(false);
539             editsubtitles=false;
540             asl.draw();
541             ssl.draw();
542             BoxStack::getInstance()->update(this);
543         }
544         return 2;
545      }
546      case Remote::RIGHT:
547      case Remote::DF_RIGHT:
548      {
549          if (!editsubtitles && subtitles) {
550              ssl.setDarkSelOption(false);
551              asl.setDarkSelOption(true);
552              editsubtitles=true;
553              asl.draw();
554              ssl.draw();
555              BoxStack::getInstance()->update(this);
556          }
557         return 2;
558      }
559   }
560
561   return 1;
562 }
563
564 void VAudioSelector::processMessage(Message* m)
565 {
566   if (m->message == Message::MOUSE_MOVE)
567   {
568     
569       UINT lastsel=asl.getCurrentOption();
570       
571       if (((m->parameter.num>>16)-getScreenX()) < 200 && asl.mouseMove((m->parameter.num>>16)-getScreenX(),(m->parameter.num&0xFFFF)-getScreenY()))
572       {
573           editsubtitles=false;
574           ssl.setDarkSelOption(true);
575           asl.setDarkSelOption(false);
576           asl.draw();
577           ssl.draw();
578           BoxStack::getInstance()->update(this);
579           if ((int)lastsel!=asl.getCurrentOption()) 
580           { 
581               Message* m2 = new Message();
582               m2->from = this;
583               m2->to = parent;
584               m2->message = Message::AUDIO_CHANGE_CHANNEL;
585               m2->parameter.num = (((AudioSubtitleChannel*)asl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)asl.getCurrentOptionData())->type &0xFF)<<16 ;
586               Command::getInstance()->postMessageNoLock(m2);
587           }
588           return;
589         
590       }
591       lastsel=ssl.getCurrentOption();
592       
593       if (ssl.mouseMove((m->parameter.num>>16)-getScreenX(),(m->parameter.num&0xFFFF)-getScreenY()))
594       {
595          editsubtitles=true;
596          ssl.setDarkSelOption(false);
597          asl.setDarkSelOption(true);
598          asl.draw();
599          ssl.draw();
600          BoxStack::getInstance()->update(this);
601          if ((int)lastsel!=ssl.getCurrentOption()) 
602          { 
603               Message* m2 = new Message();
604               m2->from = this;
605               m2->to = parent;
606               m2->message = Message::SUBTITLE_CHANGE_CHANNEL;
607               m2->parameter.num = (((AudioSubtitleChannel*)ssl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)ssl.getCurrentOptionData())->type &0xFF)<<16 ;
608               Command::getInstance()->postMessageNoLock(m2);
609           }
610          return;
611      } 
612   }
613   else if (m->message == Message::MOUSE_LBDOWN)
614   {
615     if (asl.mouseLBDOWN((m->parameter.num>>16)-getScreenX(),(m->parameter.num&0xFFFF)-getScreenY()))
616     {
617       editsubtitles=false;
618       ssl.setDarkSelOption(true);
619       asl.setDarkSelOption(false);
620       asl.draw();
621       ssl.draw();
622       BoxStack::getInstance()->handleCommand(Remote::OK); //simulate OK press
623     }
624     else if (ssl.mouseLBDOWN((m->parameter.num>>16)-getScreenX(),(m->parameter.num&0xFFFF)-getScreenY()))
625     {
626       editsubtitles=true;
627       ssl.setDarkSelOption(false);
628       asl.setDarkSelOption(true);
629       asl.draw();
630       ssl.draw();
631       BoxStack::getInstance()->handleCommand(Remote::OK); //simulate OK press
632     }
633     else
634     { //check if press is outside this view! then simulate cancel
635       int x=(m->parameter.num>>16)-getScreenX();
636       int y=(m->parameter.num&0xFFFF)-getScreenY();
637       if (x<0 || y <0 || x>(int)getWidth() || y>(int)getHeight())
638       {
639         BoxStack::getInstance()->handleCommand(Remote::BACK); //simulate cancel press
640       }
641     }
642   }
643 }
644