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