]> git.vomp.tv Git - vompclient-marten.git/blob - vrecordinglist.cc
dvbsubtitles fixup part 2
[vompclient-marten.git] / vrecordinglist.cc
1 /*
2     Copyright 2004-2007 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, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21 #include "vrecordinglist.h"
22
23 #include "recman.h"
24 #include "directory.h"
25 #include "recording.h"
26 #include "remote.h"
27 #include "wsymbol.h"
28 #include "boxstack.h"
29 #include "vrecordingmenu.h"
30 #include "vrecording.h"
31 #include "vdr.h"
32 #include "vvideorec.h"
33 #include "vradiorec.h"
34 #include "colour.h"
35 #include "video.h"
36 #include "i18n.h"
37 #include "command.h"
38 #include "vinfo.h"
39 #include "log.h"
40
41 VRecordingList::VRecordingList()
42 {
43   boxstack = BoxStack::getInstance();
44   recman = NULL;
45   loading = true;
46
47   setSize(570, 420);
48   createBuffer();
49   if (Video::getInstance()->getFormat() == Video::PAL)
50   {
51     setPosition(80, 70);
52   }
53   else
54   {
55     setPosition(70, 35);
56   }
57
58   setTitleBarOn(1);
59   setTitleBarColour(DrawStyle::TITLEBARBACKGROUND);
60
61   sl.setPosition(10, 30 + 5);
62   sl.setSize(area.w - 20, area.h - 30 - 15 - 30);
63   add(&sl);
64 }
65
66 VRecordingList::~VRecordingList()
67 {
68   delete recman;
69 }
70
71 void VRecordingList::drawData(bool doIndexPop)
72 {
73   int saveIndex = sl.getCurrentOption();
74   int saveTop = sl.getTopOption();
75   sl.clear();
76   sl.addColumn(0);
77   sl.addColumn(102);
78   sl.addColumn(118);
79
80   int first = 1;
81
82   char tempA[300]; // FIXME  this is guesswork!
83   char tempB[300]; // FIXME
84   struct tm* btime;
85
86   Directory* currentSubDir;
87   DirectoryList::iterator i;
88   DirectoryList* dirList = recman->getDirectories();
89   for (i = dirList->begin(); i != dirList->end(); i++)
90   {
91     currentSubDir = *i;
92     SNPRINTF(tempA, 299, tr("<dir> %lu/%lu\t \t%s"), currentSubDir->getNumNewRecordings(), currentSubDir->getNumRecordings(), currentSubDir->name);
93     currentSubDir->index = sl.addOption(tempA, 0, first);
94     first = 0;
95   }
96   // FIXME convert the whole program to time_t's
97
98   Recording* currentRec;
99   RecordingList::iterator j;
100   RecordingList* recList = recman->getRecordings();
101   for (j = recList->begin(); j != recList->end(); j++)
102   {
103     currentRec = *j;
104     time_t recStartTime = (time_t)currentRec->getStartTime();
105     btime = localtime(&recStartTime);
106 //NMT does not like this too!
107         //#ifndef _MSC_VER
108 //    strftime(tempA, 299, "%0d/%0m %0H:%0M ", btime);
109 //#else
110     strftime(tempA, 299, "%d/%m %H:%M ", btime);
111 //#endif
112     sprintf(tempB, "%s\t%c\t%s", tempA, (currentRec->getNew() ? '*': ' '), currentRec->getProgName());
113       
114     currentRec->index = sl.addOption(tempB, 0, first);
115     first = 0;
116   }
117
118   if (doIndexPop)
119   {
120     sl.hintSetCurrent(slIndexStack.top());
121     slIndexStack.pop();
122   }
123   else
124   {
125     sl.hintSetCurrent(saveIndex);
126     sl.hintSetTop(saveTop);
127   }
128   sl.draw();
129   doShowingBar();
130 }
131
132 void VRecordingList::draw(bool doIndexPop)
133 {
134   if (!loading)
135   {
136     if (recman->isSubDir())
137     {
138       char title[300];
139       SNPRINTF(title, 299, tr("Recordings - %s"), recman->getCurDirName());
140       setTitleText(title, 364);
141     }
142     else
143     {
144       setTitleText(tr("Recordings"));
145     }
146   }
147
148   TBBoxx::draw();
149
150   if (loading)
151   {
152     drawText(tr("Loading..."), 240, 180, DrawStyle::LIGHTTEXT);
153   }
154   else
155   {
156     char freeSpace[50];
157     int gigFree = recman->getFreeSpace() / 1024;
158     SNPRINTF(freeSpace, 49, tr("%lu%% used, %iGB free"), recman->getUsedPercent(), gigFree);
159     drawTextRJ(freeSpace, 560, 5, DrawStyle::LIGHTTEXT);
160     // Symbols
161
162     WSymbol w;
163     TEMPADD(&w);
164     w.nextSymbol = WSymbol::UP;
165     w.setPosition(20, 385);
166     w.draw();
167     w.nextSymbol = WSymbol::DOWN;
168     w.setPosition(50, 385);
169     w.draw();
170     w.nextSymbol = WSymbol::SKIPBACK;
171     w.setPosition(85, 385);
172     w.draw();
173     w.nextSymbol = WSymbol::SKIPFORWARD;
174     w.setPosition(115, 385);
175     w.draw();
176     w.nextSymbol = WSymbol::PLAY;
177     w.setPosition(150, 385);
178     w.draw();
179     drawTextRJ(tr("[ok] = menu"), 560, 385, DrawStyle::LIGHTTEXT);
180
181     // All static stuff done
182     drawData(doIndexPop);
183   }
184 }
185
186 void VRecordingList::doShowingBar()
187 {
188   int topOption = sl.getTopOption() + 1;
189   if (sl.getNumOptions() == 0) topOption = 0;
190
191   rectangle(220, 385, 180, 25, DrawStyle::VIEWBACKGROUND);
192   char showing[200];
193   sprintf(showing, tr("%i to %i of %i"), topOption, sl.getBottomOption(), sl.getNumOptions());
194   drawText(showing, 220, 385, DrawStyle::LIGHTTEXT);
195 }
196
197 void VRecordingList::processMessage(Message* m)
198 {
199   Log::getInstance()->log("VRecordingList", Log::DEBUG, "Got message value %lu", m->message);
200
201   if (m->message == Message::MOUSE_MOVE)
202   {
203     if (sl.mouseMove((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY()))
204     {
205       sl.draw();
206       doShowingBar();
207       boxstack->update(this);
208     }
209   }
210   else if (m->message == Message::MOUSE_LBDOWN)
211   {
212     if (sl.mouseLBDOWN((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY()))
213     {
214       boxstack->handleCommand(Remote::OK); //simulate OK press
215     }
216     else
217     {
218       //check if press is outside this view! then simulate cancel
219       int x=(m->parameter>>16)-getScreenX();
220       int y=(m->parameter&0xFFFF)-getScreenY();
221       if (x<0 || y <0 || x>(int)getWidth() || y>(int)getHeight())
222       {
223         boxstack->handleCommand(Remote::BACK); //simulate cancel press
224       }
225     }
226   }
227   else if (m->message == Message::DELETE_SELECTED_RECORDING)
228   {
229     Log::getInstance()->log("VRecordingList", Log::DEBUG, "Doing delete selected");
230     doDeleteSelected();
231   }
232   else if (m->message == Message::MOVE_RECORDING)
233   {
234     Log::getInstance()->log("VRecordingList", Log::DEBUG, "Doing move recording");
235     doMoveRecording((Directory*)m->parameter);
236   }
237   else if (m->message == Message::PLAY_SELECTED_RECORDING)
238   {
239     doPlay(false);
240   }
241   else if (m->message == Message::RESUME_SELECTED_RECORDING)
242   {
243     doPlay(true);
244   }
245 }
246
247 void VRecordingList::doDeleteSelected()
248 {
249   Recording* toDelete = getCurrentOptionRecording();
250
251   if (!toDelete) return;
252
253   Log::getInstance()->log("VRecordingList", Log::DEBUG, "FOUND: %i %s %s", toDelete->index, toDelete->getProgName(), toDelete->getFileName());
254
255   int success = recman->deleteRecording(toDelete);
256   if (!VDR::getInstance()->isConnected())
257   {
258     Command::getInstance()->connectionLost();
259     return;
260   }
261
262   if (success != 1)
263   {
264     VInfo* vi = new VInfo();
265     vi->setSize(360, 200);
266     vi->createBuffer();
267     if (Video::getInstance()->getFormat() == Video::PAL)
268       vi->setPosition(190, 170);
269     else
270       vi->setPosition(180, 120);
271     vi->setOneLiner(tr("Failed to delete recording"));
272     vi->setExitable();
273     vi->setBorderOn(1);
274     vi->setTitleBarColour(DrawStyle::DANGER);
275     vi->okButton();
276     vi->draw();
277     boxstack->add(vi);
278     boxstack->update(vi);
279   }
280   else
281   {
282     draw();
283     boxstack->update(this);
284   }
285
286 }
287
288 void VRecordingList::doMoveRecording(Directory* toDir)
289 {
290   Recording* toMove = getCurrentOptionRecording();
291   if (!toMove || !toDir) return;
292
293   Log::getInstance()->log("VRecordingList", Log::DEBUG, "MOVE: %s %s", toMove->getProgName(), toDir->name);
294
295   int success = recman->moveRecording(toMove, toDir);
296   if (!VDR::getInstance()->isConnected())
297   {
298     Command::getInstance()->connectionLost();
299     return;
300   }
301
302   if (success != 1)
303   {
304     VInfo* vi = new VInfo();
305     vi->setSize(360, 200);
306     vi->createBuffer();
307     if (Video::getInstance()->getFormat() == Video::PAL)
308       vi->setPosition(190, 170);
309     else
310       vi->setPosition(180, 120);
311     vi->setOneLiner(tr("Failed to move recording"));
312     vi->setExitable();
313     vi->setBorderOn(1);
314     vi->setTitleBarColour(DrawStyle::DANGER);
315     vi->okButton();
316     vi->draw();
317     boxstack->add(vi);
318     boxstack->update(vi);
319   }
320   else
321   {
322     draw();
323     boxstack->update(this);
324   }
325 }
326
327 int VRecordingList::doPlay(bool resume)
328 {
329   Recording* toPlay = getCurrentOptionRecording();
330   if (toPlay)
331   {
332     toPlay->loadRecInfo(); // check if still need this
333     toPlay->loadMarks();
334     bool ish264;
335     bool isRadio = toPlay->isRadio(ish264);
336
337     if (isRadio)
338     {
339       VRadioRec* radrec = new VRadioRec(toPlay);
340       radrec->draw();
341       boxstack->add(radrec);
342       boxstack->update(radrec);
343       radrec->go();
344       
345       toPlay->setNew(false);
346       draw();
347       boxstack->update(this);
348     }
349     else
350     {
351       if (ish264 && !Video::getInstance()->supportsh264())
352       {
353         VInfo* vi = new VInfo();
354         vi->setSize(360, 200);
355         vi->createBuffer();
356         if (Video::getInstance()->getFormat() == Video::PAL)
357           vi->setPosition(190, 170);
358         else
359           vi->setPosition(180, 120);
360         vi->setOneLiner(tr("H264 video not supported"));
361         vi->setExitable();
362         vi->setBorderOn(1);
363         vi->setTitleBarColour(DrawStyle::DANGER);
364         vi->okButton();
365         vi->draw();
366         boxstack->add(vi);
367         boxstack->update(vi);
368       }
369       else if (!ish264 && !Video::getInstance()->supportsmpeg2())
370       {
371         VInfo* vi = new VInfo();
372         vi->setSize(360, 200);
373         vi->createBuffer();
374         if (Video::getInstance()->getFormat() == Video::PAL)
375           vi->setPosition(190, 170);
376         else
377           vi->setPosition(180, 120);
378         vi->setOneLiner(tr("Mpeg2 video not supported"));
379         vi->setExitable();
380         vi->setBorderOn(1);
381         vi->setTitleBarColour(DrawStyle::DANGER);
382         vi->okButton();
383         vi->draw();
384         boxstack->add(vi);
385         boxstack->update(vi);
386       }
387       else
388       {
389         VVideoRec* vidrec = new VVideoRec(toPlay, ish264);
390         vidrec->draw();
391         boxstack->add(vidrec);
392         boxstack->update(vidrec);
393         vidrec->go(resume);
394
395         toPlay->setNew(false);
396         draw();
397         boxstack->update(this);
398       }
399     }
400     return 1;
401   }
402   // should not get to here
403   return 0;
404 }
405
406 Recording* VRecordingList::getCurrentOptionRecording()
407 {
408   Recording* currentRec;
409   RecordingList::iterator j;
410   RecordingList* recList = recman->getRecordings();
411   for (j = recList->begin(); j != recList->end(); j++)
412   {
413     currentRec = *j;
414     if (currentRec->index == sl.getCurrentOption()) return currentRec;
415   }
416
417   return NULL;
418 }
419
420 int VRecordingList::handleCommand(int command)
421 {
422   switch(command)
423   {
424     case Remote::DF_UP:
425     case Remote::UP:
426     {
427       sl.up();
428       sl.draw();
429
430       doShowingBar();
431       boxstack->update(this);
432       return 2;
433     }
434     case Remote::DF_DOWN:
435     case Remote::DOWN:
436     {
437       sl.down();
438       sl.draw();
439
440       doShowingBar();
441       boxstack->update(this);
442       return 2;
443     }
444     case Remote::SKIPBACK:
445     {
446       sl.pageUp();
447       sl.draw();
448
449       doShowingBar();
450       boxstack->update(this);
451       return 2;
452     }
453     case Remote::SKIPFORWARD:
454     {
455       sl.pageDown();
456       sl.draw();
457
458       doShowingBar();
459       boxstack->update(this);
460       return 2;
461     }
462     case Remote::OK:
463     {
464       if (sl.getNumOptions() == 0) return 2;
465
466       // Check to see if it is a sub directory
467       Directory* currentSubDir;
468       DirectoryList::iterator i;
469       DirectoryList* dirList = recman->getDirectories();
470       for (i = dirList->begin(); i != dirList->end(); i++)
471       {
472         currentSubDir = *i;
473         if (currentSubDir->index == sl.getCurrentOption())
474         {
475           if (recman->down(currentSubDir))
476           {
477             slIndexStack.push(sl.getCurrentOption());
478             sl.clear();
479             draw();
480             boxstack->update(this);
481           }
482           return 2;
483         }
484       }
485
486       // check to see if it's a recording
487       Recording* current = getCurrentOptionRecording();
488       if (current)
489       {
490         Log::getInstance()->log("VRecordingList", Log::DEBUG, "Found the option you pointed at. %s %s", current->getProgName(), current->getFileName());
491
492 /*
493         VRecordingMenu* v = new VRecordingMenu(recman);
494         v->setParent(this);
495         v->setRecording(current);
496         v->draw();
497         boxstack->add(v);
498         boxstack->update(v);
499 */        
500         VRecording* vr = new VRecording(recman, current);
501         vr->setParent(this);
502         vr->draw();
503         boxstack->add(vr);
504         boxstack->update(vr);
505         
506         return 2;
507       }
508       // should not get to here
509       return 1;
510     }
511     case Remote::BACK:
512     {
513       if (recman->isSubDir())
514       {
515         recman->up();
516         sl.clear();
517         draw(true);
518         boxstack->update(this);
519         return 2;
520       }
521       else
522       {
523         return 4;
524       }
525     }
526     case Remote::PLAYPAUSE:
527     case Remote::PLAY:
528     {
529       if (doPlay(true)) return 2;
530       return 1;
531     }
532     case Remote::LEFT:
533     case Remote::RIGHT:
534     case Remote::ZERO:
535     {
536       reSort();
537       return 2;
538     }
539   }
540   // stop command getting to any more views
541   return 1;
542 }
543
544 bool VRecordingList::load()
545 {
546   VDR* vdr = VDR::getInstance();
547
548   recman = new RecMan();
549
550   bool success = vdr->getRecordingsList(recman);
551
552   if (success)
553   {
554     loading = false;
555     char* defaultSortOrder = vdr->configLoad("General", "Recordings Sort Order");
556     if (defaultSortOrder)
557     {
558       if (!STRCASECMP(defaultSortOrder, "Chronological")) recman->setSortOrderChron();
559       delete[] defaultSortOrder;
560     }
561     recman->sort();
562     draw();
563     boxstack->update(this);
564   }
565
566   return success;
567 }
568
569 void VRecordingList::reSort()
570 {
571   recman->toggleSortOrder();
572   recman->sort();
573   sl.clear();
574   draw();
575   boxstack->update(this);
576 }
577