]> git.vomp.tv Git - vompclient.git/blob - vvideorec.cc
Switch trunk code to new boxes
[vompclient.git] / vvideorec.cc
1 /*
2     Copyright 2004-2005 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "vvideorec.h"
22
23 #include "command.h"
24 #include "osd.h"
25 #include "wsymbol.h"
26 #include "audio.h"
27 #include "vdr.h"
28 #include "video.h"
29 #include "timers.h"
30 #include "player.h"
31 #include "recording.h"
32 #include "vaudioselector.h"
33 #include "message.h"
34 #include "remote.h"
35 #include "boxstack.h"
36 #include "vinfo.h"
37 #include "i18n.h"
38
39 VVideoRec::VVideoRec(Recording* rec)
40 {
41   boxstack = BoxStack::getInstance();
42   vdr = VDR::getInstance();
43   video = Video::getInstance();
44   timers = Timers::getInstance();
45   vas = NULL;
46   vsummary = NULL;
47
48   player = new Player(Command::getInstance(), this, true);
49   player->init();
50
51   videoMode = video->getMode();
52   myRec = rec;
53
54   playing = false;
55
56   startMargin = 0;
57   endMargin = 0;
58   char* cstartMargin = vdr->configLoad("Timers", "Start margin");
59   char* cendMargin = vdr->configLoad("Timers", "End margin");
60   if (!cstartMargin)
61   {
62     startMargin = 300; // 5 mins default
63   }
64   else
65   {
66     startMargin = atoi(cstartMargin) * 60;
67     delete[] cstartMargin;
68   }
69
70   if (!cendMargin)
71   {
72     endMargin = 300; // 5 mins default
73   }
74   else
75   {
76     endMargin = atoi(cendMargin) * 60;
77     delete[] cendMargin;
78   }
79
80   Log::getInstance()->log("VVideoRec", Log::DEBUG, "SM: %u EM: %u", startMargin, endMargin);
81
82   setSize(video->getScreenWidth(), video->getScreenHeight());
83   createBuffer();
84   transparent.set(0, 0, 0, 0);
85   setBackgroundColour(transparent);
86
87   barRegion.x = 0;
88   barRegion.y = video->getScreenHeight() - 58;   // FIXME, need to be - 1? and below?
89   barRegion.w = video->getScreenWidth();
90   barRegion.h = 58;
91
92   clocksRegion.x = barRegion.x + 140;
93   clocksRegion.y = barRegion.y + 12;
94   clocksRegion.w = 170;
95   clocksRegion.h = surface->getFontHeight();
96
97
98   barBlue.set(0, 0, 150, 150);
99
100   barShowing = false;
101   barGenHold = false;
102   barScanHold = false;
103   barVasHold = false;
104
105   dowss = false;
106   char* optionWSS = vdr->configLoad("General", "WSS");
107   if (optionWSS)
108   {
109     if (strstr(optionWSS, "Yes")) dowss = true;
110     delete[] optionWSS;
111   }
112   Log::getInstance()->log("VVideoRec", Log::DEBUG, "Do WSS: %u", dowss);
113
114   wss.setFormat(video->getFormat());
115   wss.setWide(true);
116   add(&wss);
117
118   wssRegion.x = 0;
119   wssRegion.y = 0;
120   wssRegion.w = video->getScreenWidth();
121   wssRegion.h = 300;
122 }
123
124 VVideoRec::~VVideoRec()
125 {
126   Log::getInstance()->log("VVideoRec", Log::DEBUG, "Entering vvideorec destructor");
127
128   if (vas)
129   {
130     boxstack->remove(vas);
131     vas = NULL;
132   }
133
134   if (vsummary) delete vsummary;
135
136   if (playing) stopPlay();
137   video->setDefaultAspect();
138
139   timers->cancelTimer(this, 1);
140   timers->cancelTimer(this, 2);
141
142   // kill recInfo in case resumePoint has changed (likely)
143   myRec->dropRecInfo();
144   // FIXME - do this properly - save the resume point back to the server manually and update
145   // rec->recInfo->resumePoint - this will fix the ~10s offset problem as well
146 }
147
148 void VVideoRec::go(bool resume)
149 {
150   ULONG startFrameNum;
151   if (resume)
152     startFrameNum = myRec->recInfo->resumePoint;
153   else
154     startFrameNum = 0;
155
156   Log::getInstance()->log("VVideoRec", Log::DEBUG, "Starting stream: %s at frame: %lu", myRec->getFileName(), startFrameNum);
157   ULONG lengthFrames = 0;
158   ULLONG lengthBytes = vdr->streamRecording(myRec->getFileName(), &lengthFrames);
159   if (lengthBytes)
160   {
161     player->setLengthBytes(lengthBytes);
162     player->setLengthFrames(lengthFrames);
163     player->setStartFrame(startFrameNum);
164     player->play();
165     playing = true;
166     doBar(0);
167   }
168   else
169   {
170     stopPlay(); // clean up
171
172     if (!vdr->isConnected())
173     {
174       Command::getInstance()->connectionLost();
175       return;
176     }
177
178     Message* m = new Message();
179     m->message = Message::CLOSE_ME;
180     m->from = this;
181     m->to = boxstack;
182     Command::getInstance()->postMessageNoLock(m);
183
184     VInfo* vi = new VInfo();
185     vi->setSize(400, 150);
186     vi->createBuffer();
187     if (video->getFormat() == Video::PAL)
188       vi->setPosition(170, 200);
189     else
190       vi->setPosition(160, 150);
191     vi->setExitable();
192     vi->setBorderOn(1);
193     vi->setTitleBarOn(0);
194     vi->setOneLiner(tr("Error playing recording"));
195     vi->draw();
196
197     m = new Message();
198     m->message = Message::ADD_VIEW;
199     m->to = boxstack;
200     m->parameter = (ULONG)vi;
201     Command::getInstance()->postMessageNoLock(m);
202   }
203 }
204
205 int VVideoRec::handleCommand(int command)
206 {
207   switch(command)
208   {
209     case Remote::PLAY:
210     {
211       player->play();
212       doBar(0);
213       return 2;
214     }
215
216     case Remote::BACK:
217     {
218       if (vsummary)
219       {
220         removeSummary();
221         return 2;
222       }
223     } // DROP THROUGH
224     case Remote::STOP:
225     case Remote::MENU:
226     {
227       if (playing) stopPlay();
228
229       return 4;
230     }
231     case Remote::PAUSE:
232     {
233       player->pause();
234       doBar(0);
235       return 2;
236     }
237     case Remote::SKIPFORWARD:
238     {
239       doBar(3);
240       player->skipForward(60);
241       return 2;
242     }
243     case Remote::SKIPBACK:
244     {
245       doBar(4);
246       player->skipBackward(60);
247       return 2;
248     }
249     case Remote::FORWARD:
250     {
251       player->fastForward();
252       doBar(0);
253       return 2;
254     }
255     case Remote::REVERSE:
256     {
257       player->fastBackward();
258       doBar(0);
259       return 2;
260     }
261     case Remote::RED:
262     {
263       if (vsummary) removeSummary();
264       else doSummary();
265       return 2;
266     }
267     case Remote::GREEN:
268     {
269       doAudioSelector();
270       return 2;
271     }
272     case Remote::YELLOW:
273     {
274       if (myRec->hasMarks())
275       {
276         // skip to previous mark
277         Log* logger = Log::getInstance();
278         int currentFrame = (player->getCurrentFrameNum()); // get current Frame
279         currentFrame -= 5 * video->getFPS(); // subtrack 5 seconds, else you cannot skip more than once back ..
280
281         int prevMark = myRec->getPrevMark(currentFrame); // find previous Frame
282         if (prevMark)
283         {
284           logger->log("VVideoRec", Log::NOTICE, "jump back from pos %i to mark at %i",currentFrame,prevMark);
285           player->jumpToMark(prevMark);
286         }
287         doBar(4);
288       }
289       else
290       {
291         doBar(2);
292         player->skipBackward(10);
293       }
294       return 2;
295     }
296     case Remote::BLUE:
297     {
298       if (myRec->hasMarks())
299       {
300         // skip to next mark
301         Log* logger = Log::getInstance();
302         int currentFrame = (player->getCurrentFrameNum());
303
304         int nextMark = myRec->getNextMark(currentFrame);
305
306         if (nextMark)
307         {
308           logger->log("VVideoRec", Log::NOTICE, "jump forward from pos %i to mark at %i",currentFrame,nextMark);
309           player->jumpToMark(nextMark);
310         }
311         doBar(3);
312       }
313       else
314       {
315         doBar(1);
316         player->skipForward(10);
317       }
318       return 2;
319     }
320     case Remote::STAR:
321     {
322       doBar(2);
323       player->skipBackward(10);
324       return 2;
325     }
326     case Remote::HASH:
327     {
328       doBar(1);
329       player->skipForward(10);
330       return 2;
331     }
332     case Remote::FULL:
333     case Remote::TV:
334     {
335       toggleChopSides();
336       return 2;
337     }
338
339     case Remote::OK:
340     {
341       if (vsummary)
342       {
343         removeSummary();
344         return 2;
345       }
346       
347       if (barShowing) removeBar();
348       else doBar(0);
349       return 2;
350     }
351
352     case Remote::ZERO:  player->jumpToPercent(0);  doBar(0);  return 2;
353     case Remote::ONE:   player->jumpToPercent(10); doBar(0);  return 2;
354     case Remote::TWO:   player->jumpToPercent(20); doBar(0);  return 2;
355     case Remote::THREE: player->jumpToPercent(30); doBar(0);  return 2;
356     case Remote::FOUR:  player->jumpToPercent(40); doBar(0);  return 2;
357     case Remote::FIVE:  player->jumpToPercent(50); doBar(0);  return 2;
358     case Remote::SIX:   player->jumpToPercent(60); doBar(0);  return 2;
359     case Remote::SEVEN: player->jumpToPercent(70); doBar(0);  return 2;
360     case Remote::EIGHT: player->jumpToPercent(80); doBar(0);  return 2;
361     case Remote::NINE:  player->jumpToPercent(90); doBar(0);  return 2;
362
363 #ifdef DEV
364 //    case Remote::RED:
365 //    {
366       //Don't use RED for anything. It will eventually be recording summary
367
368       //player->test1();
369
370
371       /*
372       // for testing EPG in NTSC with a NTSC test video
373       Video::getInstance()->setMode(Video::QUARTER);
374       Video::getInstance()->setPosition(170, 5);
375       VEpg* vepg = new VEpg(NULL, 0);
376       vepg->draw();
377       BoxStack::getInstance()->add(vepg);
378       BoxStack::getInstance()->update(vepg);
379       */
380
381 //      return 2;
382 //    }
383
384 #endif
385
386   }
387
388   return 1;
389 }
390
391 void VVideoRec::processMessage(Message* m)
392 {
393   Log::getInstance()->log("VVideoRec", Log::DEBUG, "Message received");
394
395   if (m->message == Message::MOUSE_LBDOWN)
396   {
397     UINT x = (m->parameter>>16) - getScreenX();
398     UINT y = (m->parameter&0xFFFF) - getScreenY();
399
400     if (!barShowing)
401     {
402       BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
403     }
404     else if (barRegion.x<=x && barRegion.y<=y && (barRegion.x+barRegion.w)>=x && (barRegion.y+barRegion.h)>=y)
405     {
406       int progBarXbase = barRegion.x + 300;
407       if (myRec->hasMarks())
408       {
409         MarkList* markList = myRec->getMarkList();
410         MarkList::iterator i;
411         Mark* loopMark = NULL;
412         int posPix;
413         ULONG lengthFrames;
414         if (myRec->recInfo->timerEnd > time(NULL))
415         {
416           // chasing playback
417           // Work out an approximate length in frames (good to 1s...)
418           lengthFrames = (myRec->recInfo->timerEnd - myRec->recInfo->timerStart) * video->getFPS();
419         }
420         else
421         {
422           lengthFrames = player->getLengthFrames();
423         }
424         for(i = markList->begin(); i != markList->end(); i++)
425         {
426           loopMark = *i;
427           if (loopMark->pos)
428           {
429             posPix = 302 * loopMark->pos / lengthFrames;
430             rectangle(barRegion.x + progBarXbase + 2 + posPix, barRegion.y + 12 - 2, 3, 28, Colour::DANGER);
431             if (x>=barRegion.x + progBarXbase + 2 + posPix
432                 && x<=barRegion.x + progBarXbase + 2 + posPix+3
433                 && y>=barRegion.y + 12 - 2
434                 && y<=barRegion.y + 12 - 2+28)
435             {
436               player->jumpToMark(loopMark->pos);
437               doBar(3);
438               return;
439             }
440           }
441         }
442       }
443
444       if (x>=barRegion.x + progBarXbase + 24
445           && x<=barRegion.x + progBarXbase + 4 + 302
446           && y>=barRegion.y + 12 - 2
447           && y<=barRegion.y + 12 - 2+28)
448       {
449         int cx=x-(barRegion.x + progBarXbase + 4);
450         double percent=((double)cx)/302.*100.;
451         player->jumpToPercent(percent);
452         doBar(3);
453         return;
454         //  int progressWidth = 302 * currentFrameNum / lengthFrames;
455         //  rectangle(barRegion.x + progBarXbase + 4, barRegion.y + 16, progressWidth, 16, Colour::SELECTHIGHLIGHT);
456       }
457     }
458     else
459     {
460       BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
461     }
462   }
463   else if (m->from == player)
464   {
465     if (m->message != Message::PLAYER_EVENT) return;
466     switch(m->parameter)
467     {
468       case Player::CONNECTION_LOST: // connection lost detected
469       {
470         // I can't handle this, send it to command
471         Message* m2 = new Message();
472         m2->to = Command::getInstance();
473         m2->message = Message::CONNECTION_LOST;
474         Command::getInstance()->postMessageNoLock(m2);
475         break;
476       }
477       case Player::STOP_PLAYBACK:
478       {
479         // FIXME Obselete ish - improve this
480         Message* m2 = new Message(); // Must be done after this thread finishes, and must break into master mutex
481         m2->to = Command::getInstance();
482         m2->message = Message::STOP_PLAYBACK;
483         Command::getInstance()->postMessageNoLock(m2);
484         break;
485       }
486       case Player::ASPECT43:
487       {
488         if (dowss)
489         {
490           Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 43");
491           wss.setWide(false);
492           wss.draw();
493           boxstack->update(this, &wssRegion);
494         }
495         break;
496       }
497       case Player::ASPECT169:
498       {
499         if (dowss)
500         {
501           Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 169");
502           wss.setWide(true);
503           wss.draw();
504           boxstack->update(this, &wssRegion);
505         }
506         break;
507       }
508     }
509   }
510   else if (m->message == Message::AUDIO_CHANGE_CHANNEL)
511   {
512     Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received change audio channel to %i", m->parameter);
513     player->setAudioChannel(m->parameter);
514   }
515   else if (m->message == Message::CHILD_CLOSE)
516   {
517     if (m->from == vas)
518     {
519       vas = NULL;
520       barVasHold = false;
521       if (!barGenHold && !barScanHold && !barVasHold) removeBar();
522     }
523   }
524 }
525
526 void VVideoRec::stopPlay()
527 {
528   Log::getInstance()->log("VVideoRec", Log::DEBUG, "Pre stopPlay");
529
530   // FIXME work out a better soln for this
531   // Fix a problem to do with thread sync here
532   // because the bar gets a timer every 0.2s and it seems to take up to 0.1s,
533   // (or maybe just the wrong thread being selected?) for the main loop to lock and process
534   // the video stop message it is possible for a bar message to stack up after a stop message
535   // when the bar message is finally processed the prog crashes because this is deleted by then
536   removeBar();
537   //
538
539   player->stop();
540   vdr->stopStreaming();
541   delete player;
542
543   playing = false;
544
545   if (!vdr->isConnected()) { Command::getInstance()->connectionLost(); return; }
546   Log::getInstance()->log("VVideoRec", Log::DEBUG, "Post stopPlay");
547 }
548
549 void VVideoRec::toggleChopSides()
550 {
551   if (video->getTVsize() == Video::ASPECT16X9) return; // Means nothing for 16:9 TVs
552
553   if (videoMode == Video::NORMAL)
554   {
555     videoMode = Video::LETTERBOX;
556     video->setMode(Video::LETTERBOX);
557   }
558   else
559   {
560     videoMode = Video::NORMAL;
561     video->setMode(Video::NORMAL);
562   }
563 }
564
565 void VVideoRec::doAudioSelector()
566 {
567   bool* availableMpegAudioChannels = player->getDemuxerMpegAudioChannels();
568   bool* availableAc3AudioChannels = 0;
569   int currentAudioChannel = player->getCurrentAudioChannel();
570   if (Audio::getInstance()->supportsAc3())
571   {
572       availableAc3AudioChannels = player->getDemuxerAc3AudioChannels();
573   }
574
575   vas = new VAudioSelector(this, availableMpegAudioChannels, availableAc3AudioChannels, currentAudioChannel, myRec->recInfo);
576   vas->setBackgroundColour(barBlue);
577   vas->setPosition(0, barRegion.y - 120);
578
579 // pal 62, ntsc 57
580
581   barVasHold = true;
582   doBar(0);
583
584   vas->draw();
585   boxstack->add(vas);
586   boxstack->update(vas);
587 }
588
589 void VVideoRec::doBar(int action)
590 {
591   barShowing = true;
592
593   rectangle(barRegion, barBlue);
594
595   /* Work out what to display - choices:
596
597   Playing  >
598   Paused   ||
599   FFwd     >>
600   FBwd     <<
601
602   Specials, informed by parameter
603
604   Skip forward 10s    >|
605   Skip backward 10s   |<
606   Skip forward 1m     >>|
607   Skip backward 1m    |<<
608
609   */
610
611   WSymbol w;
612   TEMPADD(&w);
613   w.nextSymbol = 0;
614   w.setPosition(barRegion.x + 66, barRegion.y + 16);
615
616   UCHAR playerState = 0;
617
618   if (action)
619   {
620     if (action == 1)       w.nextSymbol = WSymbol::SKIPFORWARD;
621     else if (action == 2)  w.nextSymbol = WSymbol::SKIPBACK;
622     else if (action == 3)  w.nextSymbol = WSymbol::SKIPFORWARD2;
623     else if (action == 4)  w.nextSymbol = WSymbol::SKIPBACK2;
624   }
625   else
626   {
627     playerState = player->getState();
628     if (playerState == Player::S_PAUSE_P)      w.nextSymbol = WSymbol::PAUSE;
629     else if (playerState == Player::S_PAUSE_I) w.nextSymbol = WSymbol::PAUSE;
630     else if (playerState == Player::S_FFWD)    w.nextSymbol = WSymbol::FFWD;
631     else if (playerState == Player::S_FBWD)    w.nextSymbol = WSymbol::FBWD;
632     else                                       w.nextSymbol = WSymbol::PLAY;
633   }
634
635   w.draw();
636
637   if ((playerState == Player::S_FFWD) || (playerState == Player::S_FBWD))
638   {
639     // draw blips to show how fast the scan is
640     UCHAR scanrate = player->getIScanRate();
641     if (scanrate >= 2)
642     {
643       char text[5];
644       SNPRINTF(text, 5, "%ux", scanrate);
645       drawText(text, barRegion.x + 102, barRegion.y + 12, Colour::LIGHTTEXT);
646     }
647   }
648
649   drawBarClocks();
650
651   boxstack->update(this, &barRegion);
652
653   timers->cancelTimer(this, 1);
654
655
656   if ((playerState == Player::S_FFWD) || (playerState == Player::S_FBWD)) barScanHold = true;
657   else barScanHold = false;
658
659   if (!barGenHold && !barScanHold && !barVasHold) timers->setTimerD(this, 1, 4);
660
661   timers->setTimerD(this, 2, 0, 200000000);
662 }
663
664 void VVideoRec::timercall(int clientReference)
665 {
666   switch(clientReference)
667   {
668     case 1:
669     {
670       // Remove bar
671       removeBar();
672       break;
673     }
674     case 2:
675     {
676       // Update clock
677       if (!barShowing) break;
678       drawBarClocks();
679       Message* m = new Message();
680       m->message = Message::REDRAW;
681       m->to = BoxStack::getInstance();
682       m->from = this;
683       m->parameter = (ULONG)&barRegion;
684       Command::getInstance()->postMessageFromOuterSpace(m);
685       timers->setTimerD(this, 2, 0, 200000000);
686       break;
687     }
688   }
689 }
690
691 void VVideoRec::drawBarClocks()
692 {
693   if (barScanHold)
694   {
695     UCHAR playerState = player->getState();
696     // sticky bar is set if we are in ffwd/fbwd mode
697     // if player has gone to S_PLAY then kill stickyBar, and run doBar(0) which
698     // will repaint all the bar (it will call this function again, but
699     // this section won't run because stickyBarF will then == false)
700
701     if ((playerState != Player::S_FFWD) && (playerState != Player::S_FBWD))
702     {
703       barScanHold = false;
704       doBar(0);
705       return; // doBar will call this function and do the rest
706     }
707   }
708
709   Log* logger = Log::getInstance();
710   logger->log("VVideoRec", Log::DEBUG, "Draw bar clocks");
711
712   // Draw RTC
713   // Blank the area first
714   rectangle(barRegion.x + 624, barRegion.y + 12, 60, 30, barBlue);
715   char timeString[20];
716   time_t t;
717   time(&t);
718   struct tm* tms = localtime(&t);
719   strftime(timeString, 19, "%H:%M", tms);
720   drawText(timeString, barRegion.x + 624, barRegion.y + 12, Colour::LIGHTTEXT);
721
722   // Draw clocks
723
724   rectangle(clocksRegion, barBlue);
725
726   ULONG currentFrameNum = player->getCurrentFrameNum();
727   ULONG lengthFrames;
728   if (myRec->recInfo->timerEnd > time(NULL))
729   {
730     // chasing playback
731     // Work out an approximate length in frames (good to 1s...)
732     lengthFrames = (myRec->recInfo->timerEnd - myRec->recInfo->timerStart) * video->getFPS();
733   }
734   else
735   {
736     lengthFrames = player->getLengthFrames();
737   }
738
739   hmsf currentFrameHMSF = video->framesToHMSF(currentFrameNum);
740   hmsf lengthHMSF = video->framesToHMSF(lengthFrames);
741
742   char buffer[100];
743   if (currentFrameNum >= lengthFrames)
744   {
745     strcpy(buffer, "-:--:-- / -:--:--");
746   }
747   else
748   {
749     SNPRINTF(buffer, 99, "%01i:%02i:%02i / %01i:%02i:%02i", currentFrameHMSF.hours, currentFrameHMSF.minutes, currentFrameHMSF.seconds, lengthHMSF.hours, lengthHMSF.minutes, lengthHMSF.seconds);
750     logger->log("VVideoRec", Log::DEBUG, buffer);
751   }
752
753   drawText(buffer, clocksRegion.x, clocksRegion.y, Colour::LIGHTTEXT);
754
755
756
757
758
759
760
761   // Draw progress bar
762   int progBarXbase = barRegion.x + 300;
763
764   rectangle(barRegion.x + progBarXbase, barRegion.y + 12, 310, 24, Colour::LIGHTTEXT);
765   rectangle(barRegion.x + progBarXbase + 2, barRegion.y + 14, 306, 20, barBlue);
766
767   if (currentFrameNum > lengthFrames) return;
768   if (lengthFrames == 0) return;
769
770   // Draw yellow portion
771   int progressWidth = 302 * currentFrameNum / lengthFrames;
772   rectangle(barRegion.x + progBarXbase + 4, barRegion.y + 16, progressWidth, 16, Colour::SELECTHIGHLIGHT);
773
774   if (myRec->recInfo->timerEnd > time(NULL)) // if chasing
775   {
776     int nrWidth = (int)(302 * ((double)(lengthFrames - player->getLengthFrames()) / lengthFrames));
777
778     Log::getInstance()->log("GVASDF", Log::DEBUG, "Length Frames: %lu", lengthFrames);
779     Log::getInstance()->log("GVASDF", Log::DEBUG, "Player lf: %lu", player->getLengthFrames());
780     Log::getInstance()->log("GVASDF", Log::DEBUG, "NR WDITH: %i", nrWidth);
781     rectangle(barRegion.x + progBarXbase + 4 + 302 - nrWidth, barRegion.y + 16, nrWidth, 16, Colour::RED);
782   }
783
784   int posPix;
785   // Now calc position for blips
786
787   if (myRec->hasMarks())
788   {
789     // Draw blips where there are cut marks
790     MarkList* markList = myRec->getMarkList();
791     MarkList::iterator i;
792     Mark* loopMark = NULL;
793
794     for(i = markList->begin(); i != markList->end(); i++)
795     {
796       loopMark = *i;
797       if (loopMark->pos)
798       {
799         logger->log("VVideoRec", Log::DEBUG, "Drawing mark at frame %i", loopMark->pos);
800         posPix = 302 * loopMark->pos / lengthFrames;
801         rectangle(barRegion.x + progBarXbase + 2 + posPix, barRegion.y + 12 - 2, 3, 28, Colour::DANGER);
802       }
803     }
804   }
805   else
806   {
807     // Draw blips where start and end margins probably are
808
809     posPix = 302 * startMargin * video->getFPS() / lengthFrames;
810
811     rectangle(barRegion.x + progBarXbase + 2 + posPix, barRegion.y + 12 - 2, 2, 2, Colour::LIGHTTEXT);
812     rectangle(barRegion.x + progBarXbase + 2 + posPix, barRegion.y + 12 + 24, 2, 2, Colour::LIGHTTEXT);
813
814     posPix = 302 * (lengthFrames - endMargin * video->getFPS()) / lengthFrames;
815
816     rectangle(barRegion.x + progBarXbase + 2 + posPix, barRegion.y + 12 - 2, 2, 2, Colour::LIGHTTEXT);
817     rectangle(barRegion.x + progBarXbase + 2 + posPix, barRegion.y + 12 + 24, 2, 2, Colour::LIGHTTEXT);
818   }
819 }
820
821 void VVideoRec::removeBar()
822 {
823   if (!barShowing) return;
824   timers->cancelTimer(this, 2);
825   barShowing = false;
826   barGenHold = false;
827   barScanHold = false;
828   barVasHold = false;
829   rectangle(barRegion, transparent);
830
831   Message* m = new Message();
832   m->message = Message::REDRAW;
833   m->to = BoxStack::getInstance();
834   m->from = this;
835   m->parameter = (ULONG)&barRegion;
836   Command::getInstance()->postMessageFromOuterSpace(m);
837 }
838
839 void VVideoRec::doSummary()
840 {
841   vsummary = new VInfo();
842   vsummary->setTitleText(myRec->getProgName());
843   vsummary->setBorderOn(1);
844   vsummary->setExitable();
845   if (myRec->recInfo->summary) vsummary->setMainText(myRec->recInfo->summary);
846   else vsummary->setMainText(tr("Summary unavailable"));
847   if (Video::getInstance()->getFormat() == Video::PAL)
848   {
849     vsummary->setPosition(120, 130);
850   }
851   else
852   {
853     vsummary->setPosition(110, 90);
854   }
855   vsummary->setSize(510, 270);
856   add(vsummary);
857   vsummary->draw();
858
859   BoxStack::getInstance()->update(this);
860 }
861
862 void VVideoRec::removeSummary()
863 {
864   if (vsummary)
865   {
866     remove(vsummary);
867     delete vsummary;
868     vsummary = NULL;
869     draw();
870     BoxStack::getInstance()->update(this);
871   }
872 }
873