]> git.vomp.tv Git - vompclient.git/blob - vrecording.cc
Fix VRecording showing graphic at bottom left when it shouldn't
[vompclient.git] / vrecording.cc
1 /*
2     Copyright 2004-2019 Chris Tallon
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, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include "vrecording.h"
21
22 #include "input.h"
23 #include "recinfo.h"
24 #include "vquestion.h"
25 #include "vinfo.h"
26 #include "vdr.h"
27 #include "colour.h"
28 #include "video.h"
29 #include "i18n.h"
30 #include "messagequeue.h"
31 #include "vrecmove.h"
32 #include "boxstack.h"
33 #include "recman.h"
34 #include "vrecordinglist.h"
35 #include "recording.h"
36 #include "message.h"
37 #include "log.h"
38 #include "wmovieview.h"
39 #include "wseriesview.h"
40 #include "wpictureview.h"
41
42 static const char* TAG = "VRecording";
43
44 VRecording::VRecording(RecMan* trecman, Recording* trec)
45 {
46   rec = trec;
47   recman = trecman;
48   buttons = true;
49   selected = RESUME;
50   
51   LogNT::getInstance()->debug(TAG, "{}", rec->getProgName());
52   rec->loadRecInfo();
53   LogNT::getInstance()->debug(TAG, "{}", rec->getProgName());
54
55
56   if (Video::getInstance()->getFormat() == Video::PAL)
57   {
58     setSize(640, 500);
59         createBuffer();
60   }
61   else
62   {
63         setSize(560, 400);
64         createBuffer();
65   }
66   setPosition(40, 40);
67
68   setTitleBarOn(1);
69   setBorderOn(1);
70   if (rec->recInfo && strlen(rec->recInfo->title))
71           setTitleText(rec->recInfo->title);
72   else
73           setTitleText(rec->getProgName());
74   setTitleBarColour(DrawStyle::TITLEBARBACKGROUND);
75
76   tabbar.setPosition(10+130+10, 30 + 5);
77   tabbar.setSize(area.w - 20-10-130, area.h - 30 - 10);
78   add(&tabbar);
79
80
81
82   epgSummaryTextBox = new WTextbox();
83
84   epgSummaryTextBox->setParaMode(true);
85
86   if (rec->recInfo)
87     epgSummaryTextBox->setText(rec->recInfo->buildSummaryWithDetails());
88   else
89     epgSummaryTextBox->setText(tr("Summary unavailable"));
90
91   OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
92
93   tabbar.addTab(tr("EPG"), epgSummaryTextBox);
94   if (rec->movieInfo) {
95           WMovieView *movieview = new WMovieView(rec->movieInfo);
96           movieview->setParaMode(true);
97           tabbar.addTab(tr("TheTVDB Info"), movieview);
98           if (osdv) {
99                   if (rec->movieInfo->actors.size() > 0 && osdv)
100                   {
101                           WActorGallery *gallery= new WActorGallery(rec->movieInfo->actors);
102                           tabbar.addTab(tr("Cast"),gallery);
103                   }
104                   WArtworkGallery *artgallery= new WArtworkGallery(*rec->movieInfo);
105                   tabbar.addTab(tr("Gallery"),artgallery);
106           }
107   } else if (rec->seriesInfo) {
108           WSeriesView *seriesview = new WSeriesView(rec->seriesInfo);
109           seriesview->setParaMode(true);
110           tabbar.addTab(tr("TheTVDB Info"), seriesview);
111           if (osdv) {
112                   if (rec->seriesInfo->actors.size() > 0 && osdv)
113                   {
114                           WActorGallery *gallery= new WActorGallery(rec->seriesInfo->actors);
115                           tabbar.addTab(tr("Cast"),gallery);
116                   }
117                   WArtworkGallery *artgallery= new WArtworkGallery(*rec->seriesInfo);
118                   tabbar.addTab(tr("Gallery"),artgallery);
119           }
120
121   }
122
123
124   
125   int sfh = getFontHeight();
126   buttonRegion.x = 10;
127   buttonRegion.y = 10+30;
128   buttonRegion.w = 130;
129   buttonRegion.h = sfh*2*last;
130
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"));
136   
137   for (int i=PLAY, ver=10+30; i<last; i++, ver+= sfh*2)
138   {
139     button[i].setPosition(10, ver);
140     button[i].setSize(130, sfh);
141     add(&button[i]);
142   }
143   
144
145   button[selected].setActive(1);
146   tabbar.activateFocus(false);
147
148   MessageQueue::getInstance()->addReceiver(this);
149 }
150
151 VRecording::~VRecording()
152 {
153   MessageQueue::getInstance()->removeReceiver(this);
154 }
155
156 void VRecording::setParent(MessageReceiver* tvRecList)
157 {
158   vRecList = tvRecList;
159 }
160
161 void VRecording::draw()
162 {
163   TBBoxx::draw();
164   OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
165   if (osdv) {
166           TVMedia poster;
167           if (rec->movieInfo) {
168                   poster=rec->movieInfo->poster;
169           }
170           if (rec->seriesInfo) {
171                   if (rec->seriesInfo->seasonposter.height) {
172                           poster=rec->seriesInfo->seasonposter;
173                   }
174                   else
175                   if (rec->seriesInfo->posters.size()) {
176                           poster=rec->seriesInfo->posters[0];
177                   }
178           }
179           if (poster.height) {
180                  // float aspect=((float)poster.height)/((float)poster.width)/Osd::getInstance()->getPixelAspect();
181                   drawTVMedia(poster.info, static_cast<float>(buttonRegion.x), static_cast<float>(tabbar.getY2() - 3),
182                                                 static_cast<float>(buttonRegion.w), /*buttonRegion.w*aspect*/ 0.f, BottomLeft);
183           }
184   }
185
186 }
187
188 int VRecording::handleCommand(int command)
189 {
190     if (command==Input::BACK)
191     {
192         return BoxStack::DELETE_ME;
193         }
194         if (buttons) {
195                 switch(command)
196                 {
197                 case Input::UP:
198                 {
199                         tabbar.activateFocus(false);
200                         moveCursor(LEFT);
201             return BoxStack::COMMAND_HANDLED;
202                 }
203
204                 case Input::DOWN:
205                 {
206                         tabbar.activateFocus(false);
207                         moveCursor(RIGHT);
208             return BoxStack::COMMAND_HANDLED;
209                 }
210                 case Input::LEFT:
211                 case Input::RIGHT:
212                 {
213                         buttons = false;
214                         button[selected].setActive(0);
215                         tabbar.activateFocus(true);
216                         button[selected].draw();
217                         tabbar.draw();
218                         BoxStack::getInstance()->update(this);
219             return BoxStack::COMMAND_HANDLED;
220                 }
221                 case Input::OK:
222                 {
223
224                         if (selected == PLAY)
225                         {
226                                 Message* m = new Message(); // Must be done after this view deleted
227                                 m->from = this;
228                                 m->to = vRecList;
229                                 m->message = Message::PLAY_SELECTED_RECORDING;
230                                 MessageQueue::getInstance()->postMessage(m);
231                 return BoxStack::DELETE_ME;
232                         }
233
234                         if (selected == RESUME)
235                         {
236                                 Message* m = new Message(); // Must be done after this view deleted
237                                 m->from = this;
238                                 m->to = vRecList;
239                                 m->message = Message::RESUME_SELECTED_RECORDING;
240                                 MessageQueue::getInstance()->postMessage(m);
241                 return BoxStack::DELETE_ME;
242                         }
243
244                         if (selected == MARKASNEW)
245             {
246               int ret = rec->resetResume();
247
248               VInfo* vi = new VInfo();
249               vi->setSize(400, 150);
250               vi->createBuffer();
251               vi->setExitable();
252               vi->setBorderOn(1);
253               vi->setTitleBarOn(0);
254
255               if (Video::getInstance()->getFormat() == Video::PAL)
256               vi->setPosition(170, 200);
257               else
258               vi->setPosition(160, 150);
259
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"));
264               vi->draw();
265
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);
271
272               if (ret == 1)
273               {
274                 // Change Resume at text in summary
275                 rec->recInfo->resumePoint = 0;
276                 epgSummaryTextBox->setText(rec->recInfo->buildSummaryWithDetails(true));
277                 draw();
278                 BoxStack::getInstance()->update(this);
279
280                 // Update vrecordingslist to remove the * for new
281                 rec->setNew(true);
282                 Message* m2 = new Message();
283                 m2->from = this;
284                 m2->to = vRecList;
285                 m2->message = Message::REDRAW;
286                 MessageQueue::getInstance()->postMessage(m2);
287               }
288
289               return BoxStack::COMMAND_HANDLED;
290             }
291
292                         if (selected == MOVE)
293                         {
294                                 VRecMove* vrm = new VRecMove(recman);
295                                 vrm->setParent(this);
296                                 vrm->draw();
297                                 BoxStack::getInstance()->add(vrm);
298                                 BoxStack::getInstance()->update(vrm);
299                 return BoxStack::COMMAND_HANDLED;
300                         }
301
302                         if (selected == A_DELETE)
303                         {
304                                 VQuestion* v = new VQuestion(this);
305                                 v->setSize(260, 180);
306                                 v->createBuffer();
307                                 v->setTitleBarColour(DrawStyle::DANGER);
308                                 v->setTitleBarOn(1);
309                                 v->setBorderOn(1);
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)
314                                 {
315                                         v->setPosition(230, 160);
316                                 }
317                                 else
318                                 {
319                                         v->setPosition(220, 140);
320                                 }
321
322                                 v->draw();
323                                 BoxStack::getInstance()->add(v);
324                                 BoxStack::getInstance()->update(v);
325                 return BoxStack::COMMAND_HANDLED;
326                         }
327                 }
328                 }
329         } else {
330                 // Pass to tabbar
331                 int retval = tabbar.handleCommand(command);
332                 if (retval == 1)
333                 {
334                         BoxStack::getInstance()->update(this);
335             return BoxStack::COMMAND_HANDLED;
336                 }
337                 else if (retval == 2)
338                 {
339                         // command was taken and actively ignored
340                         if (command==Input::LEFT || command==Input::RIGHT)
341                         {
342                                 buttons=true;
343                                 button[selected].setActive(1);
344                                 tabbar.activateFocus(false);
345                                 button[selected].draw();
346                                 tabbar.draw();
347                                 BoxStack::getInstance()->update(this);
348                         }
349             return BoxStack::COMMAND_HANDLED;
350                 }
351         }
352
353
354         // stop command getting to any more views
355     return BoxStack::ABANDON_COMMAND;
356 }
357
358 void VRecording::moveCursor(Direction direction)
359 {
360   button[selected].setActive(0);
361   button[selected].draw();
362   if (direction == RIGHT)
363   { 
364     if (++selected == last) selected = PLAY;
365   }
366   else
367   {
368     if (--selected < 0) selected = last - 1;
369   }
370   button[selected].setActive(1);
371   button[selected].draw();
372   BoxStack::getInstance()->update(this, &buttonRegion);
373 }
374
375 void VRecording::processMessage(Message* m)
376 {
377   if (m->message == Message::MOUSE_MOVE)
378   {
379     for (int i = PLAY; i < last; i++)
380     {
381       if (button[i].mouseMove(m->parameter - getScreenX(), m->tag - getScreenY()))
382       {
383         for (int j = PLAY; j < last; j++)
384           button[j].setActive(0);
385         button[i].setActive(1);
386         tabbar.activateFocus(false);
387         buttons = true;
388         selected=i;
389         draw();
390         BoxStack::getInstance()->update(this);
391         break;
392       }
393     }
394         if (tabbar.mouseMove(m->parameter - getScreenX(), m->tag - getScreenY()))
395         {
396                 BoxStack::getInstance()->update(this);
397                 return;
398         }
399   }
400   else if (m->message == Message::MOUSE_SCROLL)
401   {
402           if (tabbar.mouseAndroidScroll(m->parameter - getScreenX(), m->tag - getScreenY(), 0, reinterpret_cast<ULONG>(m->data)))
403           {
404                   BoxStack::getInstance()->update(this);
405                   return;
406           }
407   }
408   else if (m->message == Message::MOUSE_LBDOWN)
409   {
410     int cancel = true;
411     for (int i = PLAY; i < last; i++)
412     {
413       if (button[i].mouseLBDOWN(m->parameter - getScreenX(), m->tag - getScreenY()))
414       {
415         Input::sendInputKey(Input::OK);
416                 buttons = true;
417         cancel = false;
418         break;
419       }
420     }
421         if (cancel && tabbar.mouseLBDOWN(m->parameter - getScreenX(), m->tag - getScreenY()))
422         {
423                 buttons = false;
424                 button[selected].setActive(0);
425
426                 BoxStack::getInstance()->update(this);
427                 cancel = false;
428         }
429     if (cancel)
430     {
431       if (coordsOutsideBox(m))
432       {
433         Input::sendInputKey(Input::BACK);
434       }
435     }
436   }
437   else if (m->message == Message::QUESTION_YES)
438   {
439     if (selected == A_DELETE)
440     {
441       Message* m2 = new Message(); // Delete self
442       m2->from = this;
443       m2->p_to = Message::BOXSTACK;
444       m2->message = Message::CLOSE_ME;
445       MessageQueue::getInstance()->postMessage(m2);
446
447       m2 = new Message(); // OK. Want this to delete before this message does its job
448       m2->from = this;
449       m2->to = vRecList;
450       m2->message = Message::DELETE_SELECTED_RECORDING;
451       MessageQueue::getInstance()->postMessage(m2);
452     }
453   }
454   else if (m->message == Message::MOVE_RECORDING)
455   {
456     Message* m2 = new Message(); // Delete self
457     m2->from = this;
458     m2->p_to = Message::BOXSTACK;
459     m2->message = Message::CLOSE_ME;
460     MessageQueue::getInstance()->postMessage(m2);
461
462     m2 = new Message();
463     m2->from = this;
464     m2->to = vRecList;
465     m2->message = Message::MOVE_RECORDING;
466     m2->parameter = m->parameter;
467     MessageQueue::getInstance()->postMessage(m2);
468   }
469 }
470