2 Copyright 2004-2019 Chris Tallon
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/>.
20 #include "vrecording.h"
24 #include "vquestion.h"
30 #include "messagequeue.h"
34 #include "vrecordinglist.h"
35 #include "recording.h"
38 #include "wmovieview.h"
39 #include "wseriesview.h"
40 #include "wpictureview.h"
42 static const char* TAG = "VRecording";
44 VRecording::VRecording(RecMan* trecman, Recording* trec)
51 LogNT::getInstance()->debug(TAG, "{}", rec->getProgName());
53 LogNT::getInstance()->debug(TAG, "{}", rec->getProgName());
56 if (Video::getInstance()->getFormat() == Video::PAL)
70 if (rec->recInfo && strlen(rec->recInfo->title))
71 setTitleText(rec->recInfo->title);
73 setTitleText(rec->getProgName());
74 setTitleBarColour(DrawStyle::TITLEBARBACKGROUND);
76 tabbar.setPosition(10+130+10, 30 + 5);
77 tabbar.setSize(area.w - 20-10-130, area.h - 30 - 10);
82 epgSummaryTextBox = new WTextbox();
84 epgSummaryTextBox->setParaMode(true);
87 epgSummaryTextBox->setText(rec->recInfo->buildSummaryWithDetails());
89 epgSummaryTextBox->setText(tr("Summary unavailable"));
91 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
93 tabbar.addTab(tr("EPG"), epgSummaryTextBox);
95 WMovieView *movieview = new WMovieView(rec->movieInfo);
96 movieview->setParaMode(true);
97 tabbar.addTab(tr("TheTVDB Info"), movieview);
99 if (rec->movieInfo->actors.size() > 0 && osdv)
101 WActorGallery *gallery= new WActorGallery(rec->movieInfo->actors);
102 tabbar.addTab(tr("Cast"),gallery);
104 WArtworkGallery *artgallery= new WArtworkGallery(*rec->movieInfo);
105 tabbar.addTab(tr("Gallery"),artgallery);
107 } else if (rec->seriesInfo) {
108 WSeriesView *seriesview = new WSeriesView(rec->seriesInfo);
109 seriesview->setParaMode(true);
110 tabbar.addTab(tr("TheTVDB Info"), seriesview);
112 if (rec->seriesInfo->actors.size() > 0 && osdv)
114 WActorGallery *gallery= new WActorGallery(rec->seriesInfo->actors);
115 tabbar.addTab(tr("Cast"),gallery);
117 WArtworkGallery *artgallery= new WArtworkGallery(*rec->seriesInfo);
118 tabbar.addTab(tr("Gallery"),artgallery);
125 int sfh = getFontHeight();
127 buttonRegion.y = 10+30;
128 buttonRegion.w = 130;
129 buttonRegion.h = sfh*2*last;
131 button[PLAY].setText(tr("Play"));
132 button[RESUME].setText(tr("Resume"));
133 button[MARKASNEW].setText(tr("Mark as new"));
134 button[MOVE].setText(tr("Move"));
135 button[A_DELETE].setText(tr("Delete"));
137 for (int i=PLAY, ver=10+30; i<last; i++, ver+= sfh*2)
139 button[i].setPosition(10, ver);
140 button[i].setSize(130, sfh);
145 button[selected].setActive(1);
146 tabbar.activateFocus(false);
148 MessageQueue::getInstance()->addReceiver(this);
151 VRecording::~VRecording()
153 MessageQueue::getInstance()->removeReceiver(this);
156 void VRecording::setParent(MessageReceiver* tvRecList)
158 vRecList = tvRecList;
161 void VRecording::draw()
164 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
166 TVMediaStruct poster; // does not need any image creation, it's copying from an already made Movie/SeriesInfo object
167 if (rec->movieInfo) {
168 poster = rec->movieInfo->poster;
170 if (rec->seriesInfo) {
171 if (rec->seriesInfo->seasonposter.height) {
172 poster=rec->seriesInfo->seasonposter;
175 if (rec->seriesInfo->posters.size()) {
176 poster=rec->seriesInfo->posters[0];
180 // float aspect=((float)poster.height)/((float)poster.width)/Osd::getInstance()->getPixelAspect();
181 drawImage(poster.image, static_cast<float>(buttonRegion.x), static_cast<float>(tabbar.getY2() - 3),
182 static_cast<float>(buttonRegion.w), /*buttonRegion.w*aspect*/ 0.f, BottomLeft);
188 int VRecording::handleCommand(int command)
190 if (command==Input::BACK)
192 return BoxStack::DELETE_ME;
199 tabbar.activateFocus(false);
201 return BoxStack::COMMAND_HANDLED;
206 tabbar.activateFocus(false);
208 return BoxStack::COMMAND_HANDLED;
214 button[selected].setActive(0);
215 tabbar.activateFocus(true);
216 button[selected].draw();
218 BoxStack::getInstance()->update(this);
219 return BoxStack::COMMAND_HANDLED;
224 if (selected == PLAY)
226 Message* m = new Message(); // Must be done after this view deleted
229 m->message = Message::PLAY_SELECTED_RECORDING;
230 MessageQueue::getInstance()->postMessage(m);
231 return BoxStack::DELETE_ME;
234 if (selected == RESUME)
236 Message* m = new Message(); // Must be done after this view deleted
239 m->message = Message::RESUME_SELECTED_RECORDING;
240 MessageQueue::getInstance()->postMessage(m);
241 return BoxStack::DELETE_ME;
244 if (selected == MARKASNEW)
246 int ret = rec->resetResume();
248 VInfo* vi = new VInfo();
249 vi->setSize(400, 150);
253 vi->setTitleBarOn(0);
255 if (Video::getInstance()->getFormat() == Video::PAL)
256 vi->setPosition(170, 200);
258 vi->setPosition(160, 150);
260 if (ret == 1) vi->setOneLiner(tr("Success"));
261 else if (ret == 2) vi->setOneLiner(tr("No resume point exists"));
262 else if (ret == 4) vi->setOneLiner(tr("Failure deleting resume point"));
263 else if (ret == 5) vi->setOneLiner(tr("Not supported with VDR < 2.4.0"));
266 Message* m = new Message();
267 m->message = Message::ADD_VIEW;
268 m->p_to = Message::BOXSTACK;
269 m->data = reinterpret_cast<void*>(vi);
270 MessageQueue::getInstance()->postMessage(m);
274 // Change Resume at text in summary
275 rec->recInfo->resumePoint = 0;
276 epgSummaryTextBox->setText(rec->recInfo->buildSummaryWithDetails(true));
278 BoxStack::getInstance()->update(this);
280 // Update vrecordingslist to remove the * for new
282 Message* m2 = new Message();
285 m2->message = Message::REDRAW;
286 MessageQueue::getInstance()->postMessage(m2);
289 return BoxStack::COMMAND_HANDLED;
292 if (selected == MOVE)
294 VRecMove* vrm = new VRecMove(recman);
295 vrm->setParent(this);
297 BoxStack::getInstance()->add(vrm);
298 BoxStack::getInstance()->update(vrm);
299 return BoxStack::COMMAND_HANDLED;
302 if (selected == A_DELETE)
304 VQuestion* v = new VQuestion(this);
305 v->setSize(260, 180);
307 v->setTitleBarColour(DrawStyle::DANGER);
310 v->setTitleText(tr("Delete recording"));
311 v->setMainText(tr("Are you sure you want to delete this recording?"));
312 v->setDefault(VQuestion::NO);
313 if (Video::getInstance()->getFormat() == Video::PAL)
315 v->setPosition(230, 160);
319 v->setPosition(220, 140);
323 BoxStack::getInstance()->add(v);
324 BoxStack::getInstance()->update(v);
325 return BoxStack::COMMAND_HANDLED;
331 int retval = tabbar.handleCommand(command);
334 BoxStack::getInstance()->update(this);
335 return BoxStack::COMMAND_HANDLED;
337 else if (retval == 2)
339 // command was taken and actively ignored
340 if (command==Input::LEFT || command==Input::RIGHT)
343 button[selected].setActive(1);
344 tabbar.activateFocus(false);
345 button[selected].draw();
347 BoxStack::getInstance()->update(this);
349 return BoxStack::COMMAND_HANDLED;
354 // stop command getting to any more views
355 return BoxStack::ABANDON_COMMAND;
358 void VRecording::moveCursor(Direction direction)
360 button[selected].setActive(0);
361 button[selected].draw();
362 if (direction == RIGHT)
364 if (++selected == last) selected = PLAY;
368 if (--selected < 0) selected = last - 1;
370 button[selected].setActive(1);
371 button[selected].draw();
372 BoxStack::getInstance()->update(this, &buttonRegion);
375 void VRecording::processMessage(Message* m)
377 if (m->message == Message::MOUSE_MOVE)
379 for (int i = PLAY; i < last; i++)
381 if (button[i].mouseMove(m->parameter - getScreenX(), m->tag - getScreenY()))
383 for (int j = PLAY; j < last; j++)
384 button[j].setActive(0);
385 button[i].setActive(1);
386 tabbar.activateFocus(false);
390 BoxStack::getInstance()->update(this);
394 if (tabbar.mouseMove(m->parameter - getScreenX(), m->tag - getScreenY()))
396 BoxStack::getInstance()->update(this);
400 else if (m->message == Message::MOUSE_SCROLL)
402 if (tabbar.mouseAndroidScroll(m->parameter - getScreenX(), m->tag - getScreenY(), 0, reinterpret_cast<ULONG>(m->data)))
404 BoxStack::getInstance()->update(this);
408 else if (m->message == Message::MOUSE_LBDOWN)
411 for (int i = PLAY; i < last; i++)
413 if (button[i].mouseLBDOWN(m->parameter - getScreenX(), m->tag - getScreenY()))
415 Input::sendInputKey(Input::OK);
421 if (cancel && tabbar.mouseLBDOWN(m->parameter - getScreenX(), m->tag - getScreenY()))
424 button[selected].setActive(0);
426 BoxStack::getInstance()->update(this);
431 if (coordsOutsideBox(m))
433 Input::sendInputKey(Input::BACK);
437 else if (m->message == Message::QUESTION_YES)
439 if (selected == A_DELETE)
441 Message* m2 = new Message(); // Delete self
443 m2->p_to = Message::BOXSTACK;
444 m2->message = Message::CLOSE_ME;
445 MessageQueue::getInstance()->postMessage(m2);
447 m2 = new Message(); // OK. Want this to delete before this message does its job
450 m2->message = Message::DELETE_SELECTED_RECORDING;
451 MessageQueue::getInstance()->postMessage(m2);
454 else if (m->message == Message::MOVE_RECORDING)
456 Message* m2 = new Message(); // Delete self
458 m2->p_to = Message::BOXSTACK;
459 m2->message = Message::CLOSE_ME;
460 MessageQueue::getInstance()->postMessage(m2);
465 m2->message = Message::MOVE_RECORDING;
466 m2->parameter = m->parameter;
467 MessageQueue::getInstance()->postMessage(m2);