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