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