]> git.vomp.tv Git - vompclient.git/blob - vpicture.cc
Switch trunk code to new boxes
[vompclient.git] / vpicture.cc
1 /*
2     Copyright 2004-2005 Chris Tallon, Andreas Vogel
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 <time.h>
22
23 #include "vpicture.h"
24
25 #include "vpicturebanner.h"
26 #include "timers.h"
27 #include "boxx.h"
28 #include "wselectlist.h"
29 #include "remote.h"
30 #include "wsymbol.h"
31 #include "boxstack.h"
32 #include "vdr.h"
33 #include "media.h"
34 #include "vvideolive.h"
35 #include "video.h"
36 #include "vinfo.h"
37 #include "i18n.h"
38 #include "message.h"
39 #include "command.h"
40
41 Colour VPicture::pictureBack=Colour(140,140,140);
42 Colour VPicture::infoBack=Colour(110,110,110);
43 //the jpeg reader
44
45 class VPreader : public JpegReader {
46   private:
47     VPicture * parent;
48   public:
49   VPreader(VPicture *p){
50      parent=p;};
51   virtual ULONG readChunk(ULONG offset,ULONG len,char ** buf) {
52      Log::getInstance()->log("VPicture::jpegReader", Log::DEBUG, "read chunk o=%d,len=%d,buf=%p",
53         offset,len,*buf);
54      UINT numrec=0;
55      *buf=(char *)VDR::getInstance()->getImageBlock(offset,(UINT)len,&numrec);
56      Log::getInstance()->log("VPicture::jpegReader", Log::DEBUG, "got n=%d,buf=%p",
57         numrec,*buf);
58      return numrec;
59      }
60   virtual ULONG initRead(const char *filename) {
61      Log::getInstance()->log("VPicture::jpegReader", Log::DEBUG, "load image %s",filename);
62      Video* video = Video::getInstance();
63      ULONG size=VDR::getInstance()->loadImage(filename,video->getScreenWidth(), video->getScreenHeight());
64      Log::getInstance()->log("VPicture::jpegReader", Log::DEBUG, "load image %s returned %d",filename,size);
65      return size;
66      }
67 };
68
69 VPicture::VPicture(VMediaList *p)
70 {
71   parent=p;
72   reader=new VPreader(this);
73   needDraw=false;
74   Video* video = Video::getInstance();
75   setSize(video->getScreenWidth(), video->getScreenHeight());
76   createBuffer();
77   jpeg.setSurface(surface);
78         jpeg.setDimensions(area.w,area.h);
79   banner=NULL;
80   fullname=NULL;
81   filename=NULL;
82   ftime=0;
83   slideshow=false;
84   showtime=INITIAL_SHOWTIME;
85   mediaError=NULL;
86   currentMedia=NULL;
87   shortBanner=false;
88   rotate=0;
89   info=NULL;
90   jpeg.setBackgroundColour(pictureBack);
91   add(&jpeg);
92 }
93
94 VPicture::~VPicture()
95 {
96   delete reader;
97   if (banner) BoxStack::getInstance()->remove(banner);
98   if (fullname) delete fullname;
99   if (filename) delete filename;
100   Timers::getInstance()->cancelTimer(this,1);
101   Timers::getInstance()->cancelTimer(this,2);
102   Timers::getInstance()->cancelTimer(this,3);
103   destroyInfo();
104   
105 }
106
107 void VPicture::draw()
108 {
109   Log::getInstance()->log("VPicture::draw", Log::DEBUG, "needDraw=%d,p=%p",
110         needDraw,this);
111 //  View::draw();
112   if (mediaError) {
113     drawText(mediaError,20,area.h-10,Colour::LIGHTTEXT);
114     return;
115     }
116   if (needDraw) {
117     jpeg.draw();
118     }
119 }
120
121
122 int VPicture::handleCommand(int command)
123 {
124   Timers::getInstance()->cancelTimer(this,1);
125   int rt=1;
126   switch(command)
127   {
128     case Remote::DF_UP:
129     case Remote::UP:
130     case Remote::SKIPBACK:
131       showPicture(VMediaList::MV_PREV);
132       BoxStack::getInstance()->update(this);
133       rt= 2;
134       break;
135     case Remote::FORWARD:
136       if (showtime > 1) showtime--;
137       updateBanner(true);
138       break;
139     case Remote::DF_DOWN:
140     case Remote::DOWN:
141     case Remote::SKIPFORWARD:
142       showPicture(VMediaList::MV_NEXT);
143       BoxStack::getInstance()->update(this);
144       rt= 2;
145       break;
146     case Remote::REVERSE:
147       if (showtime < 50 ) showtime++;
148       updateBanner(true);
149       break;
150     case Remote::OK:
151     {
152       if (banner) {
153         destroyBanner();
154         destroyInfo();
155         }
156       else showBanner();
157       rt= 2;
158     }
159     break;
160     case Remote::PLAY:
161     {
162       slideshow=true;
163       showPicture(VMediaList::MV_NEXT);
164       BoxStack::getInstance()->update(this);
165       rt= 2;
166     }
167     break;
168     case Remote::PAUSE:
169       slideshow=false;
170       updateBanner();
171       rt= 2;
172       break;
173     case Remote::STOP:
174       slideshow=false;
175       showtime=INITIAL_SHOWTIME;
176       updateBanner();
177       rt= 2;
178       break;
179     case Remote::RED:
180       switch(rotate) {
181         case WJpeg::ROT_0:
182           rotate=WJpeg::ROT_90;
183           break;
184         case WJpeg::ROT_90:
185           rotate=WJpeg::ROT_180;
186           break;
187         case WJpeg::ROT_180:
188           rotate=WJpeg::ROT_270;
189           break;
190         case WJpeg::ROT_270:
191           rotate=WJpeg::ROT_0;
192           break;
193         }
194       showPicture(VMediaList::MV_NONE,rotate);
195       BoxStack::getInstance()->update(this);
196       rt=2;
197       break;
198     case Remote::GREEN:
199       if (info) destroyInfo();
200       else showInfo();
201       rt=2;
202       break;
203     case Remote::BACK:
204     {
205       rt= 4;
206     }
207     break;
208   }
209   if (slideshow) startSlideshow();
210   // stop command getting to any more views
211   return rt;
212 }
213
214 void VPicture::processMessage(Message* m)
215 {
216   if (m->message == Message::MOUSE_MOVE)
217   {
218     ;
219   }
220   else if (m->message == Message::MOUSE_LBDOWN)
221   {
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::getInstance()->handleCommand(Remote::BACK); //simulate cancel press
229     }
230   }
231 }
232
233 VPicture * VPicture::createViewer(VMediaList * mparent, bool bslideshow) {
234    Log::getInstance()->log("VPicture::createViewer", Log::DEBUG, "p=%p",
235         mparent);
236    VPicture *vmn=new VPicture(mparent);
237    BoxStack::getInstance()->add(vmn);
238    BoxStack::getInstance()->update(vmn);
239    vmn->showPicture();
240    if (bslideshow) vmn->startSlideshow();
241    vmn->showBanner();
242    BoxStack::getInstance()->update(vmn);
243    return vmn;
244 }
245
246 void VPicture::startSlideshow() {
247    slideshow=true;
248    Timers::getInstance()->setTimerD(this,1,showtime);
249 }
250
251 void VPicture::showPicture(ULONG move, int rt) {
252   rotate=rt;
253   currentMedia=parent->getMedia(MEDIA_TYPE_PICTURE,move);
254   load(currentMedia);
255   if (mediaError || jpeg.hasError()) destroyInfo();
256   else updateInfo();
257   BoxStack::getInstance()->update(this);
258 }
259
260
261 int VPicture::load(Media *md) {
262   jpeg.init(NULL,false,NULL);
263   mediaError=tr("No media found");
264   needDraw=false;
265   if (! md) return 1;
266   const char *fname=md->getFileName();
267   ftime=md->getTime();
268   int len=strlen(fname)+2+strlen(parent->getDirname());
269   if (fullname) {
270      delete fullname;
271      fullname=NULL;
272      }
273   fullname=new char[len];
274   sprintf(fullname,"%s/%s",parent->getDirname(),fname);
275   if (filename) delete filename;
276   len=strlen(fname)+1;
277   filename=new char[len];
278   strcpy(filename,fname);
279   Log::getInstance()->log("VPicture::load", Log::DEBUG, "filename=%s,p=%p",
280         fullname,this);
281   VDR* vdr=VDR::getInstance();
282   //do we have a banner?
283   bool haveBanner=banner!=NULL && ! shortBanner;
284   if (vdr->isConnected()) {
285      showBanner(true);
286      jpeg.init(fullname,false,reader);
287      jpeg.setRotate(rotate);
288      needDraw=true;
289      mediaError=NULL;
290      draw();
291      //only show the banner if it was there before
292      if (haveBanner) showBanner();
293      else {
294         if(banner) destroyBanner();
295         }
296      Log::getInstance()->log("VPicture::load", Log::DEBUG, "success: filename=%s,p=%p",
297         fullname,this);
298      return 0;
299   }
300   else {
301     mediaError=tr("no VDR connection");
302     }
303   return 1;
304 }
305
306 void VPicture::showBanner(bool loading,int shortDisplay) {
307   //if the loading flag is set,
308         //we are in the main thread - so we can (and must) safely hard destroy/create the banner
309   Timers::getInstance()->cancelTimer(this,2);
310   if (! filename || ! currentMedia) {
311     //hmm...
312     destroyBanner(!loading);
313     return;
314     }
315   if (banner) destroyBanner(!loading);
316   banner= new VPictureBanner(this, loading, slideshow);
317   banner->fillColour(infoBack);
318   if (! loading) {
319     int len=strlen(filename)+Media::TIMEBUFLEN+20;
320     char buf[len];
321     char tbuf[Media::TIMEBUFLEN];
322     snprintf(buf,len,"%c%02ds%c %s %s ",
323       slideshow?' ':'[',
324       showtime,
325       slideshow?' ':']',
326       currentMedia->getTimeString(tbuf),
327       filename);
328     banner->setText(buf);
329   }
330   else {
331     banner->setText(filename);
332   }
333   banner->draw();
334   if (shortDisplay != 0) shortBanner=true;
335   if (! slideshow && shortDisplay == 0) shortDisplay=8;
336   //OK we start timer if we don't load and either shortDisplay or no slideshow
337   if (! loading && shortDisplay != 0)   Timers::getInstance()->setTimerD(this,2,shortDisplay);
338   if (! loading) ;  /*sendViewMsg(banner,false); upgrade to boxx */
339         else {
340                 BoxStack::getInstance()->add(banner);
341                 BoxStack::getInstance()->update(banner);
342         }
343
344   }
345
346 void VPicture::destroyBanner(bool fromTimer) {
347   shortBanner=false;
348   if (banner) {
349     if (fromTimer) ;/* sendViewMsg(banner,true); upgrade to boxx*/
350                 else BoxStack::getInstance()->remove(banner);
351     banner=NULL;
352     if (! fromTimer) Timers::getInstance()->cancelTimer(this,2);
353     }
354 }
355 void VPicture::updateBanner(bool shortDisplay) {
356   if (banner && ! shortBanner) {
357     showBanner(false);
358     }
359   else if (shortDisplay) {
360     showBanner(false,2);
361     }
362 }
363 void VPicture::timercall(int clientref) {
364    switch(clientref)
365    {
366       case 1:
367         if (! slideshow) return;
368         Log::getInstance()->log("VPicture::timercall", Log::DEBUG, "slideshow");
369                                 sendCommandMsg(Remote::PLAY);
370         break;
371       case 2:
372         destroyBanner(true);
373         break;
374       case 3:
375         destroyInfo(true);
376         break;
377     }
378    
379   }
380
381 #define INFOBUF 1000
382 void VPicture::showInfo(){
383   if (info) destroyInfo();
384   if (! currentMedia) return;
385
386   info=new VInfo();
387   info->setTitleText(currentMedia->getFileName());
388   info->setDropThrough();
389   info->setSize(500, 300);
390   info->createBuffer();
391   info->setBorderOn(1);
392   info->setTitleBarOn(1);
393
394   if (Video::getInstance()->getFormat() == Video::PAL)
395         info->setPosition(100, 180);
396   else
397         info->setPosition(100, 150);
398   char buf[INFOBUF];
399   char tbuf[Media::TIMEBUFLEN];
400   snprintf(buf,INFOBUF,"%s= %s\n%s= %ld x %ld\n%s= %ld kBytes\n%s= %s\n%s= %ld\n%s= 1/%ld",
401      tr("Directory"), parent->getDirname(),
402      tr("Format(px)"),jpeg.getJpegInfo(WJpeg::JPEG_WIDTH),jpeg.getJpegInfo(WJpeg::JPEG_HEIGHT),
403      tr("Filesize"),jpeg.getJpegInfo(WJpeg::JPEG_SIZE)/1000,
404      tr("Time"),currentMedia->getTimeString(tbuf),
405      tr("Rotation"),90*jpeg.getJpegInfo(WJpeg::JPEG_ROTATE),
406      tr("Scale"),jpeg.getJpegInfo(WJpeg::JPEG_SCALE));
407   info->setMainText(buf);
408   info->draw();
409   sendViewMsg(info,false);
410   Timers::getInstance()->setTimerD(this,3,8);
411 }
412 void VPicture::updateInfo(){
413   if (info) {
414     showInfo();
415     }
416 }
417 void VPicture::destroyInfo(bool fromTimer){
418   if (info) {
419     sendViewMsg(info,true);
420     info=NULL;
421     }
422   if (! fromTimer) Timers::getInstance()->cancelTimer(this,3);
423 }
424
425 void VPicture::sendViewMsg(Boxx *v,bool vdestroy) {
426         Message* m = new Message(); 
427   m->message = vdestroy?Message::CLOSE_ME:Message::ADD_VIEW;
428   m->to = BoxStack::getInstance();
429   m->from = v;
430         m->parameter=(ULONG)v;
431   Command::getInstance()->postMessageFromOuterSpace(m);
432 }
433 void VPicture::sendCommandMsg(int command) {
434         Message* m = new Message(); 
435   m->message = Message::UDP_BUTTON;
436   m->to = Command::getInstance();
437   m->from = this;
438         m->parameter=command;
439   Command::getInstance()->postMessageFromOuterSpace(m);
440 }