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