2 Copyright 2006-2020 Chris Tallon, Marten Richter
4 This file is part of VOMP.
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.
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.
16 You should have received a copy of the GNU General Public License
17 along with VOMP. If not, see <https://www.gnu.org/licenses/>.
31 #include "messagequeue.h"
36 #include "vaudioselector.h"
38 VAudioSelector::VAudioSelector(MessageReceiver* tparent, bool* availableMpegAudioChannels,
39 bool* availableAc3AudioChannels, int currentAudioChannel, bool* availableSubtitleChannels, int* ttxtpages,
40 int currentSubtitleChannel, int currentSubtitleType, RecInfo* recInfo)
43 LogNT::getInstance()->debug("VAudioSelector", "{}", currentAudioChannel);
47 if (availableSubtitleChannels != NULL)
49 for (i = 0; i < PES_DVBSUBTITLE_MAXCHANNELS; i++)
51 if (availableSubtitleChannels[i])
53 AudioSubtitleChannel sc;
54 sc.type = 0x10; //dvbsubtitle
55 sc.pestype = PES_DVBSUBTITLE_START + i;
56 scl.push_back(std::move(sc));
60 for (i = 0; i < 10; i++)
64 AudioSubtitleChannel sc;
65 sc.type = 0x11; //Teletxt
66 sc.pestype = ttxtpages[i];
67 std::ostringstream oss;
68 oss << tr("TTxt:") << " " << std::hex << std::setw(3) << ttxtpages[i];
70 scl.push_back(std::move(sc));
77 AudioSubtitleChannel sc;
78 sc.type = 0xFF; //special
79 sc.name = tr("No Subtitles");
81 scl.insert(scl.begin(), std::move(sc));
92 asl.setPosition(40, 30);
93 asl.setSize(200 - 45, area.h - 30);
98 ssl.setPosition(200 + 40, 30);
99 ssl.setSize(200 - 45, area.h - 30);
103 // Load data from availableAudioChannels, currentAudioChannel and recInfo
105 for (i = 0; i < PES_AUDIO_MAXCHANNELS; i++)
107 if (availableMpegAudioChannels[i])
109 AudioSubtitleChannel ac;
111 ac.pestype = PES_AUDIO_START + i;
112 acl.push_back(std::move(ac));
116 if (availableAc3AudioChannels != NULL)
118 for (i = 0; i < PES_AUDIO_AC3_MAXCHANNELS; i++)
120 if (availableAc3AudioChannels[i])
122 AudioSubtitleChannel ac;
124 ac.pestype = PES_AUDIO_AC3_START + i;
125 acl.push_back(std::move(ac));
130 int numchan_recinfo = recInfo->numComponents;
131 u4 mp_audcounter = 0;
134 u4 dvb_subcounter = 1;
138 if (ac.type == 0) ++ac3_offset;
146 for (i = 0; i < numchan_recinfo; i++)
148 type = recInfo->types[i];
149 lang = recInfo->languages[i];
150 description = recInfo->descriptions[i];
151 AudioSubtitleChannel* acp = NULL;
154 if (recInfo->streams[i] == 2)
158 case 1: //mpaudio mono
159 case 3: //mpaudio stereo
160 if (mp_audcounter < acl.size()) acp = &acl[mp_audcounter];
166 if (ac3_counter + ac3_offset < acl.size()) acp = &acl[ac3_counter + ac3_offset];
172 else if (recInfo->streams[i] == 3)
177 if (dvb_subcounter < scl.size()) acp = &scl[dvb_subcounter];
183 else continue; //neither audio nor subtitle
187 if (acp->type == type_int)
189 if (description && (strlen(description) > 0))
191 acp->name = description;
193 else if (lang && (strlen(lang) > 0))
216 // Now do display. acl and scl are read only from now on, so pointers always remain valid
222 if (!ac.name.empty())
224 asl.addOption(ac.name, &ac, (ac.pestype == currentAudioChannel));
228 std::string tempString;
230 if (ac.type == 0) tempString = std::to_string(ac.pestype - PES_AUDIO_START);
231 else if (ac.type == 1) tempString = "ac3 " + std::to_string(ac.pestype - PES_AUDIO_AC3_START);
232 else tempString = "unknown";
234 asl.addOption(tempString, &ac, (ac.pestype == currentAudioChannel));
240 asl.addOption(tr("No audio channel data available"), 0, 1);
245 ssl.setDarkSelOption(true);
249 bool selected = false;
251 if (sc.pestype == currentSubtitleChannel && sc.type == currentSubtitleType) selected = true;
253 if (!sc.name.empty())
255 ssl.addOption(sc.name, &sc, selected);
259 std::string tempString;
261 if (sc.type == 0x10) tempString = std::to_string(sc.pestype - PES_DVBSUBTITLE_START);
262 else tempString = "unknown";
264 ssl.addOption(tempString, &sc, selected);
269 MessageQueue::getInstance()->addReceiver(this);
272 VAudioSelector::VAudioSelector(MessageReceiver* tparent, Channel* channel, int currentAudioChannel, int currentSubtitletype, int currentSubtitleChannel, int* ttxtpages)
277 for (i = 0; i < channel->numSPids; i++)
279 AudioSubtitleChannel sc;
281 sc.name = channel->spids[i].desc;
282 sc.pestype = channel->spids[i].pid;
283 scl.push_back(std::move(sc));
288 for (i = 0; i < 10; i++)
290 if (ttxtpages[i] > 0)
292 AudioSubtitleChannel sc;
293 sc.type = 0x11; //Teletxt
294 sc.pestype = ttxtpages[i];
295 std::ostringstream oss;
296 oss << tr("TTxt:") << " " << std::hex << std::setw(3) << ttxtpages[i];
298 scl.push_back(std::move(sc));
305 AudioSubtitleChannel sc;
306 sc.type = 0xFF; //special
307 sc.name = tr("No Subtitles");
309 scl.insert(scl.begin(), std::move(sc));
320 asl.setPosition(40, 30);
321 asl.setSize(200 - 45, area.h - 30);
326 ssl.setPosition(200 + 40, 30);
327 ssl.setSize(200 - 45, area.h - 30);
331 // Load data from availableAudioChannels, currentAudioChannel and recInfo
333 for (i = 0; i < channel->numAPids; i++)
335 if (Audio::getInstance()->streamTypeSupported(channel->apids[i].type))
337 AudioSubtitleChannel ac;
339 ac.name = channel->apids[i].desc;
340 ac.pestype = channel->apids[i].pid;
341 ac.streamtype = channel->apids[i].type;
342 acl.push_back(std::move(ac));
346 if (Audio::getInstance()->supportsAc3())
348 for (i = 0; i < channel->numDPids; i++)
350 if (Audio::getInstance()->streamTypeSupported(channel->dpids[i].type))
352 AudioSubtitleChannel ac;
354 ac.name = channel->dpids[i].desc;
355 ac.pestype = channel->dpids[i].pid;
356 ac.streamtype = channel->dpids[i].type;
357 acl.push_back(std::move(ac));
362 // acl and scl now read only so pointers are always valid
368 asl.addOption(ac.name, &ac, (ac.pestype == currentAudioChannel));
373 asl.addOption(tr("No audio channel data available"), 0, 1);
378 ssl.setDarkSelOption(true);
382 bool selected = false;
383 if ((sc.type == currentSubtitletype) && (sc.pestype == currentSubtitleChannel)) selected = true;
384 ssl.addOption(sc.name, &sc, selected);
388 MessageQueue::getInstance()->addReceiver(this);
391 VAudioSelector::~VAudioSelector()
393 MessageQueue::getInstance()->removeReceiver(this);
395 Message* m = new Message();
398 m->message = Message::CHILD_CLOSE;
399 MessageQueue::getInstance()->postMessage(m);
402 void VAudioSelector::draw()
408 rectangle(0, 0, area.w, 30, DrawStyle::TITLEBARBACKGROUND);
409 drawText(tr("Audio"), 45, 5, DrawStyle::LIGHTTEXT);
413 drawText(tr("Subtitles"), 45 + 200, 5, DrawStyle::LIGHTTEXT);
415 ssl.setBackgroundColour(backgroundColour);
419 asl.setBackgroundColour(backgroundColour);
423 int VAudioSelector::handleCommand(int command)
431 return BoxStack::DELETE_ME;
440 BoxStack::getInstance()->update(this);
441 Message* m = new Message();
444 m->message = Message::SUBTITLE_CHANGE_CHANNEL;
445 AudioSubtitleChannel* asc = static_cast<AudioSubtitleChannel*>(ssl.getCurrentOptionData());
446 m->parameter = (asc->pestype & 0xFFFF) | (asc->type & 0xFF) << 16;
447 MessageQueue::getInstance()->postMessage(m);
453 BoxStack::getInstance()->update(this);
454 Message* m = new Message();
457 m->message = Message::AUDIO_CHANGE_CHANNEL;
458 AudioSubtitleChannel* asc = static_cast<AudioSubtitleChannel*>(asl.getCurrentOptionData());
459 m->parameter = (asc->pestype & 0xFFFF) | (asc->type & 0xFF) << 16;
460 MessageQueue::getInstance()->postMessage(m);
463 return BoxStack::COMMAND_HANDLED;
472 BoxStack::getInstance()->update(this);
473 Message* m = new Message();
476 m->message = Message::SUBTITLE_CHANGE_CHANNEL;
477 AudioSubtitleChannel* subchan = static_cast<AudioSubtitleChannel*>(ssl.getCurrentOptionData());
478 AudioSubtitleChannel* audchan = static_cast<AudioSubtitleChannel*>(asl.getCurrentOptionData());
479 m->parameter = (subchan->pestype & 0xFFFF)
480 | (subchan->type & 0xFF) << 16
481 | (audchan->streamtype & 0xFF) << 24; // FIXME: Is this really supposed to be audio channel here? Old code did audio, looks wrong
482 MessageQueue::getInstance()->postMessage(m);
488 BoxStack::getInstance()->update(this);
489 Message* m = new Message();
492 m->message = Message::AUDIO_CHANGE_CHANNEL;
493 AudioSubtitleChannel* asc = static_cast<AudioSubtitleChannel*>(asl.getCurrentOptionData());
494 m->parameter = (asc->pestype & 0xFFFF)
495 | (asc->type & 0xFF) << 16
496 | (asc->streamtype & 0xFF) << 24;
497 MessageQueue::getInstance()->postMessage(m);
500 return BoxStack::COMMAND_HANDLED;
505 if (editsubtitles && subtitles)
507 ssl.setDarkSelOption(true);
508 asl.setDarkSelOption(false);
509 editsubtitles = false;
512 BoxStack::getInstance()->update(this);
515 return BoxStack::COMMAND_HANDLED;
520 if (!editsubtitles && subtitles)
522 ssl.setDarkSelOption(false);
523 asl.setDarkSelOption(true);
524 editsubtitles = true;
527 BoxStack::getInstance()->update(this);
530 return BoxStack::COMMAND_HANDLED;
534 return BoxStack::ABANDON_COMMAND;
537 void VAudioSelector::processMessage(Message* m)
539 if (m->message == Message::MOUSE_MOVE)
541 int lastsel = asl.getCurrentOption();
543 if ((m->parameter - getScreenX()) < 200 && asl.mouseMove(m->parameter - getScreenX(), m->tag - getScreenY()))
545 editsubtitles = false;
546 ssl.setDarkSelOption(true);
547 asl.setDarkSelOption(false);
550 BoxStack::getInstance()->update(this);
552 if (lastsel != asl.getCurrentOption())
554 Message* m2 = new Message();
557 m2->message = Message::AUDIO_CHANGE_CHANNEL;
558 AudioSubtitleChannel* asc = static_cast<AudioSubtitleChannel*>(asl.getCurrentOptionData());
559 m2->parameter = (asc->pestype & 0xFFFF) | (asc->type & 0xFF) << 16 ;
560 MessageQueue::getInstance()->postMessage(m2);
566 lastsel = ssl.getCurrentOption();
568 if (ssl.mouseMove(m->parameter - getScreenX(), m->tag - getScreenY()))
570 editsubtitles = true;
571 ssl.setDarkSelOption(false);
572 asl.setDarkSelOption(true);
575 BoxStack::getInstance()->update(this);
577 if (lastsel != ssl.getCurrentOption())
579 Message* m2 = new Message();
582 m2->message = Message::SUBTITLE_CHANGE_CHANNEL;
583 AudioSubtitleChannel* asc = static_cast<AudioSubtitleChannel*>(ssl.getCurrentOptionData());
584 m2->parameter = (asc->pestype & 0xFFFF) | (asc->type & 0xFF) << 16 ;
585 MessageQueue::getInstance()->postMessage(m2);
591 else if (m->message == Message::MOUSE_LBDOWN)
593 if (asl.mouseLBDOWN(m->parameter - getScreenX(), m->tag - getScreenY()))
595 editsubtitles = false;
596 ssl.setDarkSelOption(true);
597 asl.setDarkSelOption(false);
600 Input::sendInputKey(Input::OK);
602 else if (ssl.mouseLBDOWN(m->parameter - getScreenX(), m->tag - getScreenY()))
604 editsubtitles = true;
605 ssl.setDarkSelOption(false);
606 asl.setDarkSelOption(true);
609 Input::sendInputKey(Input::OK);
613 //check if press is outside this view! then simulate cancel
614 int x = m->parameter - getScreenX();
615 int y = m->tag - getScreenY();
617 if (x < 0 || y < 0 || x > toi4(getWidth()) || y > toi4(getHeight()))
619 Input::sendInputKey(Input::BACK);