]> git.vomp.tv Git - vompclient-marten.git/blob - vrecordinglist.cc
End of line normalization
[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(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   // 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 //NMT does not like this too!
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, DrawStyle::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, DrawStyle::LIGHTTEXT);
158     // Symbols
159
160     WSymbol w;
161     TEMPADD(&w);
162     w.nextSymbol = WSymbol::UP;
163     w.setPosition(20, 385);
164     w.draw();
165     w.nextSymbol = WSymbol::DOWN;
166     w.setPosition(50, 385);
167     w.draw();
168     w.nextSymbol = WSymbol::SKIPBACK;
169     w.setPosition(85, 385);
170     w.draw();
171     w.nextSymbol = WSymbol::SKIPFORWARD;
172     w.setPosition(115, 385);
173     w.draw();
174     w.nextSymbol = WSymbol::PLAY;
175     w.setPosition(150, 385);
176     w.draw();
177     drawTextRJ(tr("[ok] = menu"), 560, 385, DrawStyle::LIGHTTEXT);
178
179     // All static stuff done
180     drawData(doIndexPop);
181   }
182 }
183
184 void VRecordingList::doShowingBar()
185 {
186   int topOption = sl.getTopOption() + 1;
187   if (sl.getNumOptions() == 0) topOption = 0;
188
189   rectangle(220, 385, 180, 25, DrawStyle::VIEWBACKGROUND);
190   char showing[200];
191   sprintf(showing, tr("%i to %i of %i"), topOption, sl.getBottomOption(), sl.getNumOptions());
192   drawText(showing, 220, 385, DrawStyle::LIGHTTEXT);
193 }
194
195 void VRecordingList::processMessage(Message* m)
196 {
197   Log::getInstance()->log("VRecordingList", Log::DEBUG, "Got message value %lu", m->message);
198
199   if (m->message == Message::MOUSE_MOVE)
200   {
201     if (sl.mouseMove((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY()))
202     {
203       sl.draw();
204       doShowingBar();
205       boxstack->update(this);
206     }
207   }
208   else if (m->message == Message::MOUSE_LBDOWN)
209   {
210     if (sl.mouseLBDOWN((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY()))
211     {
212       boxstack->handleCommand(Remote::OK); //simulate OK press
213     }
214     else
215     {
216       //check if press is outside this view! then simulate cancel
217       int x=(m->parameter>>16)-getScreenX();
218       int y=(m->parameter&0xFFFF)-getScreenY();
219       if (x<0 || y <0 || x>(int)getWidth() || y>(int)getHeight())
220       {
221         boxstack->handleCommand(Remote::BACK); //simulate cancel press
222       }
223     }
224   }
225   else if (m->message == Message::DELETE_SELECTED_RECORDING)
226   {
227     Log::getInstance()->log("VRecordingList", Log::DEBUG, "Doing delete selected");
228     doDeleteSelected();
229   }
230   else if (m->message == Message::MOVE_RECORDING)
231   {
232     Log::getInstance()->log("VRecordingList", Log::DEBUG, "Doing move recording");
233     doMoveRecording((Directory*)m->parameter);
234   }
235   else if (m->message == Message::PLAY_SELECTED_RECORDING)
236   {
237     doPlay(false);
238   }
239   else if (m->message == Message::RESUME_SELECTED_RECORDING)
240   {
241     doPlay(true);
242   }
243 }
244
245 void VRecordingList::doDeleteSelected()
246 {
247   Recording* toDelete = getCurrentOptionRecording();
248
249   if (!toDelete) return;
250
251   Log::getInstance()->log("VRecordingList", Log::DEBUG, "FOUND: %i %s %s", toDelete->index, toDelete->getProgName(), toDelete->getFileName());
252
253   int success = recman->deleteRecording(toDelete);
254   if (!VDR::getInstance()->isConnected())
255   {
256     Command::getInstance()->connectionLost();
257     return;
258   }
259
260   if (success != 1)
261   {
262     VInfo* vi = new VInfo();
263     vi->setSize(360, 200);
264     vi->createBuffer();
265     if (Video::getInstance()->getFormat() == Video::PAL)
266       vi->setPosition(190, 170);
267     else
268       vi->setPosition(180, 120);
269     vi->setOneLiner(tr("Failed to delete recording"));
270     vi->setExitable();
271     vi->setBorderOn(1);
272     vi->setTitleBarColour(DrawStyle::DANGER);
273     vi->okButton();
274     vi->draw();
275     boxstack->add(vi);
276     boxstack->update(vi);
277   }
278   else
279   {
280     draw();
281     boxstack->update(this);
282   }
283
284 }
285
286 void VRecordingList::doMoveRecording(Directory* toDir)
287 {
288   Recording* toMove = getCurrentOptionRecording();
289   if (!toMove || !toDir) return;
290
291   Log::getInstance()->log("VRecordingList", Log::DEBUG, "MOVE: %s %s", toMove->getProgName(), toDir->name);
292
293   int success = recman->moveRecording(toMove, toDir);
294   if (!VDR::getInstance()->isConnected())
295   {
296     Command::getInstance()->connectionLost();
297     return;
298   }
299
300   if (success != 1)
301   {
302     VInfo* vi = new VInfo();
303     vi->setSize(360, 200);
304     vi->createBuffer();
305     if (Video::getInstance()->getFormat() == Video::PAL)
306       vi->setPosition(190, 170);
307     else
308       vi->setPosition(180, 120);
309     vi->setOneLiner(tr("Failed to move recording"));
310     vi->setExitable();
311     vi->setBorderOn(1);
312     vi->setTitleBarColour(DrawStyle::DANGER);
313     vi->okButton();
314     vi->draw();
315     boxstack->add(vi);
316     boxstack->update(vi);
317   }
318   else
319   {
320     draw();
321     boxstack->update(this);
322   }
323 }
324
325 int VRecordingList::doPlay(bool resume)
326 {
327   Recording* toPlay = getCurrentOptionRecording();
328   if (toPlay)
329   {
330     toPlay->loadRecInfo(); // check if still need this
331     toPlay->loadMarks();
332         bool ish264;
333
334     bool isRadio = toPlay->isRadio(ish264);
335
336     if (isRadio)
337     {
338       VRadioRec* radrec = new VRadioRec(toPlay);
339       radrec->draw();
340       boxstack->add(radrec);
341       boxstack->update(radrec);
342       radrec->go();
343     }
344     else
345     {
346                 if (ish264 && !Video::getInstance()->supportsh264()) {
347                         VInfo* vi = new VInfo();
348                         vi->setSize(360, 200);
349                         vi->createBuffer();
350                         if (Video::getInstance()->getFormat() == Video::PAL)
351                                 vi->setPosition(190, 170);
352                         else
353                                 vi->setPosition(180, 120);
354                         vi->setOneLiner(tr("H264 video not supported"));
355                         vi->setExitable();
356                         vi->setBorderOn(1);
357                         vi->setTitleBarColour(DrawStyle::DANGER);
358                         vi->okButton();
359                         vi->draw();
360                         boxstack->add(vi);
361                         boxstack->update(vi);
362                         
363                 } else {
364                         VVideoRec* vidrec = new VVideoRec(toPlay, ish264);
365                         vidrec->draw();
366                         boxstack->add(vidrec);
367                         boxstack->update(vidrec);
368                         vidrec->go(resume);
369                 }
370     }
371     return 1;
372   }
373   // should not get to here
374   return 0;
375 }
376
377 Recording* VRecordingList::getCurrentOptionRecording()
378 {
379   Recording* currentRec;
380   RecordingList::iterator j;
381   RecordingList* recList = recman->getRecordings();
382   for (j = recList->begin(); j != recList->end(); j++)
383   {
384     currentRec = *j;
385     if (currentRec->index == sl.getCurrentOption()) return currentRec;
386   }
387
388   return NULL;
389 }
390
391 int VRecordingList::handleCommand(int command)
392 {
393   switch(command)
394   {
395     case Remote::DF_UP:
396     case Remote::UP:
397     {
398       sl.up();
399       sl.draw();
400
401       doShowingBar();
402       boxstack->update(this);
403       return 2;
404     }
405     case Remote::DF_DOWN:
406     case Remote::DOWN:
407     {
408       sl.down();
409       sl.draw();
410
411       doShowingBar();
412       boxstack->update(this);
413       return 2;
414     }
415     case Remote::SKIPBACK:
416     {
417       sl.pageUp();
418       sl.draw();
419
420       doShowingBar();
421       boxstack->update(this);
422       return 2;
423     }
424     case Remote::SKIPFORWARD:
425     {
426       sl.pageDown();
427       sl.draw();
428
429       doShowingBar();
430       boxstack->update(this);
431       return 2;
432     }
433     case Remote::OK:
434     {
435       if (sl.getNumOptions() == 0) return 2;
436
437       // Check to see if it is a sub directory
438       Directory* currentSubDir;
439       DirectoryList::iterator i;
440       DirectoryList* dirList = recman->getDirectories();
441       for (i = dirList->begin(); i != dirList->end(); i++)
442       {
443         currentSubDir = *i;
444         if (currentSubDir->index == sl.getCurrentOption())
445         {
446           if (recman->down(currentSubDir))
447           {
448             slIndexStack.push(sl.getCurrentOption());
449             sl.clear();
450             draw();
451             boxstack->update(this);
452           }
453           return 2;
454         }
455       }
456
457       // check to see if it's a recording
458       Recording* current = getCurrentOptionRecording();
459       if (current)
460       {
461         Log::getInstance()->log("VRecordingList", Log::DEBUG, "Found the option you pointed at. %s %s", current->getProgName(), current->getFileName());
462
463 /*
464         VRecordingMenu* v = new VRecordingMenu(recman);
465         v->setParent(this);
466         v->setRecording(current);
467         v->draw();
468         boxstack->add(v);
469         boxstack->update(v);
470 */        
471         VRecording* vr = new VRecording(recman, current);
472         vr->setParent(this);
473         vr->draw();
474         boxstack->add(vr);
475         boxstack->update(vr);
476         
477         return 2;
478       }
479       // should not get to here
480       return 1;
481     }
482     case Remote::BACK:
483     {
484       if (recman->isSubDir())
485       {
486         recman->up();
487         sl.clear();
488         draw(true);
489         boxstack->update(this);
490         return 2;
491       }
492       else
493       {
494         return 4;
495       }
496     }
497     case Remote::PLAYPAUSE:
498     case Remote::PLAY:
499     {
500       if (doPlay(true)) return 2;
501       return 1;
502     }
503     case Remote::LEFT:
504     case Remote::RIGHT:
505     case Remote::ZERO:
506     {
507       reSort();
508       return 2;
509     }
510   }
511   // stop command getting to any more views
512   return 1;
513 }
514
515 bool VRecordingList::load()
516 {
517   VDR* vdr = VDR::getInstance();
518
519   recman = new RecMan();
520
521   bool success = vdr->getRecordingsList(recman);
522
523   if (success)
524   {
525     loading = false;
526     char* defaultSortOrder = vdr->configLoad("General", "Recordings Sort Order");
527     if (defaultSortOrder)
528     {
529       if (!STRCASECMP(defaultSortOrder, "Chronological")) recman->setSortOrderChron();
530       delete[] defaultSortOrder;
531     }
532     recman->sort();
533     draw();
534     boxstack->update(this);
535   }
536
537   return success;
538 }
539
540 void VRecordingList::reSort()
541 {
542   recman->toggleSortOrder();
543   recman->sort();
544   sl.clear();
545   draw();
546   boxstack->update(this);
547 }
548