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