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(void* tparent, bool* availableMpegAudioChannels,
39 bool* availableAc3AudioChannels, int currentAudioChannel, bool* availableSubtitleChannels, int* ttxtpages,
40 int currentSubtitleChannel, int currentSubtitleType, RecInfo* recInfo)
41 : parent(tparent), liveMode(false)
43 Log::getInstance()->log("VAS", Log::DEBUG, "%i", 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];
69 sc.name = std::move(oss.str());
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 UINT mp_audcounter = 0;
132 UINT ac3_counter = 0;
134 UINT 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.c_str(), &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.c_str(), &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.c_str(), &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.c_str(), &sc, selected);
270 VAudioSelector::VAudioSelector(void* tparent, Channel* channel, int currentAudioChannel, int currentSubtitletype, int currentSubtitleChannel, int* ttxtpages)
271 : parent(tparent), liveMode(true)
275 for (i = 0; i < channel->numSPids; i++)
277 AudioSubtitleChannel sc;
279 sc.name = channel->spids[i].desc;
280 sc.pestype = channel->spids[i].pid;
281 scl.push_back(std::move(sc));
286 for (i = 0; i < 10; i++)
288 if (ttxtpages[i] > 0)
290 AudioSubtitleChannel sc;
291 sc.type = 0x11; //Teletxt
292 sc.pestype = ttxtpages[i];
293 std::ostringstream oss;
294 oss << tr("TTxt:") << " " << std::hex << std::setw(3) << ttxtpages[i];
295 sc.name = std::move(oss.str());
296 scl.push_back(std::move(sc));
303 AudioSubtitleChannel sc;
304 sc.type = 0xFF; //special
305 sc.name = tr("No Subtitles");
307 scl.insert(scl.begin(), std::move(sc));
318 asl.setPosition(40, 30);
319 asl.setSize(200 - 45, area.h - 30);
324 ssl.setPosition(200 + 40, 30);
325 ssl.setSize(200 - 45, area.h - 30);
329 // Load data from availableAudioChannels, currentAudioChannel and recInfo
331 for (i = 0; i < channel->numAPids; i++)
333 if (Audio::getInstance()->streamTypeSupported(channel->apids[i].type))
335 AudioSubtitleChannel ac;
337 ac.name = channel->apids[i].desc;
338 ac.pestype = channel->apids[i].pid;
339 ac.streamtype = channel->apids[i].type;
340 acl.push_back(std::move(ac));
344 if (Audio::getInstance()->supportsAc3())
346 for (i = 0; i < channel->numDPids; i++)
348 if (Audio::getInstance()->streamTypeSupported(channel->dpids[i].type))
350 AudioSubtitleChannel ac;
352 ac.name = channel->dpids[i].desc;
353 ac.pestype = channel->dpids[i].pid;
354 ac.streamtype = channel->dpids[i].type;
355 acl.push_back(std::move(ac));
360 // acl and scl now read only so pointers are always valid
366 asl.addOption(ac.name.c_str(), &ac, (ac.pestype == currentAudioChannel));
371 asl.addOption(tr("No audio channel data available"), 0, 1);
376 ssl.setDarkSelOption(true);
380 bool selected = false;
381 if ((sc.type == currentSubtitletype) && (sc.pestype == currentSubtitleChannel)) selected = true;
382 ssl.addOption(sc.name.c_str(), &sc, selected);
387 VAudioSelector::~VAudioSelector()
389 Message* m = new Message();
392 m->message = Message::CHILD_CLOSE;
393 MessageQueue::getInstance()->postMessage(m);
396 void VAudioSelector::draw()
402 rectangle(0, 0, area.w, 30, DrawStyle::TITLEBARBACKGROUND);
403 drawText(tr("Audio"), 45, 5, DrawStyle::LIGHTTEXT);
407 drawText(tr("Subtitles"), 45 + 200, 5, DrawStyle::LIGHTTEXT);
409 ssl.setBackgroundColour(backgroundColour);
413 asl.setBackgroundColour(backgroundColour);
417 int VAudioSelector::handleCommand(int command)
434 BoxStack::getInstance()->update(this);
435 Message* m = new Message();
438 m->message = Message::SUBTITLE_CHANGE_CHANNEL;
439 AudioSubtitleChannel* asc = static_cast<AudioSubtitleChannel*>(ssl.getCurrentOptionData());
440 m->parameter = (asc->pestype & 0xFFFF) | (asc->type & 0xFF) << 16;
441 MessageQueue::getInstance()->postMessage(m);
447 BoxStack::getInstance()->update(this);
448 Message* m = new Message();
451 m->message = Message::AUDIO_CHANGE_CHANNEL;
452 AudioSubtitleChannel* asc = static_cast<AudioSubtitleChannel*>(asl.getCurrentOptionData());
453 m->parameter = (asc->pestype & 0xFFFF) | (asc->type & 0xFF) << 16;
454 MessageQueue::getInstance()->postMessage(m);
466 BoxStack::getInstance()->update(this);
467 Message* m = new Message();
470 m->message = Message::SUBTITLE_CHANGE_CHANNEL;
471 AudioSubtitleChannel* subchan = static_cast<AudioSubtitleChannel*>(ssl.getCurrentOptionData());
472 AudioSubtitleChannel* audchan = static_cast<AudioSubtitleChannel*>(asl.getCurrentOptionData());
473 m->parameter = (subchan->pestype & 0xFFFF)
474 | (subchan->type & 0xFF) << 16
475 | (audchan->streamtype & 0xFF) << 24; // FIXME: Is this really supposed to be audio channel here? Old code did audio, looks wrong
476 MessageQueue::getInstance()->postMessage(m);
482 BoxStack::getInstance()->update(this);
483 Message* m = new Message();
486 m->message = Message::AUDIO_CHANGE_CHANNEL;
487 AudioSubtitleChannel* asc = static_cast<AudioSubtitleChannel*>(asl.getCurrentOptionData());
488 m->parameter = (asc->pestype & 0xFFFF)
489 | (asc->type & 0xFF) << 16
490 | (asc->streamtype & 0xFF) << 24;
491 MessageQueue::getInstance()->postMessage(m);
499 if (editsubtitles && subtitles)
501 ssl.setDarkSelOption(true);
502 asl.setDarkSelOption(false);
503 editsubtitles = false;
506 BoxStack::getInstance()->update(this);
514 if (!editsubtitles && subtitles)
516 ssl.setDarkSelOption(false);
517 asl.setDarkSelOption(true);
518 editsubtitles = true;
521 BoxStack::getInstance()->update(this);
531 void VAudioSelector::processMessage(Message* m)
533 if (m->message == Message::MOUSE_MOVE)
535 int lastsel = asl.getCurrentOption();
537 if (((m->parameter >> 16) - getScreenX()) < 200 && asl.mouseMove((m->parameter >> 16) - getScreenX(), (m->parameter & 0xFFFF) - getScreenY()))
539 editsubtitles = false;
540 ssl.setDarkSelOption(true);
541 asl.setDarkSelOption(false);
544 BoxStack::getInstance()->update(this);
546 if (lastsel != asl.getCurrentOption())
548 Message* m2 = new Message();
551 m2->message = Message::AUDIO_CHANGE_CHANNEL;
552 AudioSubtitleChannel* asc = static_cast<AudioSubtitleChannel*>(asl.getCurrentOptionData());
553 m2->parameter = (asc->pestype & 0xFFFF) | (asc->type & 0xFF) << 16 ;
554 MessageQueue::getInstance()->postMessage(m2);
560 lastsel = ssl.getCurrentOption();
562 if (ssl.mouseMove((m->parameter >> 16) - getScreenX(), (m->parameter & 0xFFFF) - getScreenY()))
564 editsubtitles = true;
565 ssl.setDarkSelOption(false);
566 asl.setDarkSelOption(true);
569 BoxStack::getInstance()->update(this);
571 if (lastsel != ssl.getCurrentOption())
573 Message* m2 = new Message();
576 m2->message = Message::SUBTITLE_CHANGE_CHANNEL;
577 AudioSubtitleChannel* asc = static_cast<AudioSubtitleChannel*>(ssl.getCurrentOptionData());
578 m2->parameter = (asc->pestype & 0xFFFF) | (asc->type & 0xFF) << 16 ;
579 MessageQueue::getInstance()->postMessage(m2);
585 else if (m->message == Message::MOUSE_LBDOWN)
587 if (asl.mouseLBDOWN((m->parameter >> 16) - getScreenX(), (m->parameter & 0xFFFF) - getScreenY()))
589 editsubtitles = false;
590 ssl.setDarkSelOption(true);
591 asl.setDarkSelOption(false);
594 BoxStack::getInstance()->handleCommand(Input::OK); //simulate OK press
596 else if (ssl.mouseLBDOWN((m->parameter >> 16) - getScreenX(), (m->parameter & 0xFFFF) - getScreenY()))
598 editsubtitles = true;
599 ssl.setDarkSelOption(false);
600 asl.setDarkSelOption(true);
603 BoxStack::getInstance()->handleCommand(Input::OK); //simulate OK press
607 //check if press is outside this view! then simulate cancel
608 int x = (m->parameter >> 16) - getScreenX();
609 int y = (m->parameter & 0xFFFF) - getScreenY();
611 if (x < 0 || y < 0 || x > static_cast<int>(getWidth()) || y > static_cast<int>(getHeight()))
613 BoxStack::getInstance()->handleCommand(Input::BACK); //simulate cancel press