From 8c98eb914c52f958e7c0e382193f298d0206fa4d Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Sun, 13 Jul 2014 14:21:29 +0200 Subject: [PATCH] Add tvscraper support and other image handling stuff to vomp --- boxx.cc | 40 +++++- boxx.h | 6 +- command.cc | 13 ++ eventdispatcher.cc | 6 +- eventdispatcher.h | 2 +- message.h | 1 + movieinfo.cc | 46 +++++++ movieinfo.h | 56 ++++++++ objects.mk | 4 +- osd.h | 2 + osdopenvg.cc | 89 +++++++++++-- osdopenvg.h | 7 + osdvector.cc | 212 +++++++++++++++++++++++++++++- osdvector.h | 175 ++++++++++++++++++++----- recinfo.cc | 4 + recinfo.h | 2 + recording.cc | 41 +++++- recording.h | 7 + seriesinfo.cc | 49 +++++++ seriesinfo.h | 70 ++++++++++ surfacevector.cc | 51 ++++++-- surfacevector.h | 5 + tvmedia.cc | 91 +++++++++++++ tvmedia.h | 76 +++++++++++ vconnect.cc | 8 +- vdr.cc | 255 ++++++++++++++++++++++++++++++++++-- vdr.h | 15 ++- vdrcommand.h | 4 + vdrresponsepacket.cc | 15 ++- vdrresponsepacket.h | 4 +- videoomx.cc | 9 +- vrecording.cc | 300 +++++++++++++++++++++++++++++-------------- vrecording.h | 5 +- wmovieview.cc | 84 ++++++++++++ wmovieview.h | 44 +++++++ woptionpane.cc | 2 +- wpictureview.cc | 247 +++++++++++++++++++++++++++++++++++ wpictureview.h | 87 +++++++++++++ wseriesview.cc | 73 +++++++++++ wseriesview.h | 43 +++++++ wtabbar.cc | 25 ++++ wtabbar.h | 1 + wtextbox.cc | 49 ++++++- wtextbox.h | 5 + 44 files changed, 2135 insertions(+), 195 deletions(-) create mode 100644 movieinfo.cc create mode 100644 movieinfo.h create mode 100644 seriesinfo.cc create mode 100644 seriesinfo.h create mode 100644 tvmedia.cc create mode 100644 tvmedia.h create mode 100644 wmovieview.cc create mode 100644 wmovieview.h create mode 100644 wpictureview.cc create mode 100644 wpictureview.h create mode 100644 wseriesview.cc create mode 100644 wseriesview.h diff --git a/boxx.cc b/boxx.cc index dd12024..2222086 100644 --- a/boxx.cc +++ b/boxx.cc @@ -26,6 +26,7 @@ #include "osd.h" #include "boxx.h" +#include "surfacevector.h" char Boxx::numBoxxes = 0; Boxx::Boxx() @@ -241,7 +242,7 @@ void Boxx::fillColour(const DrawStyle& colour) rectangle(0, 0, area.w, area.h, colour); } -void Boxx::drawPara(const char* text, int x, int y, const DrawStyle& colour) +int Boxx::drawPara(const char* text, int x, int y, const DrawStyle& colour,unsigned int skiplines) { char line[256]; int lineHeight = getFontHeight() + paraVSpace; @@ -252,6 +253,9 @@ void Boxx::drawPara(const char* text, int x, int y, const DrawStyle& colour) int linePos; int ypos; int printLine; + int leftlines=0; + + int drawLinePos=-skiplines; textPos = 0; ypos = y; @@ -308,15 +312,22 @@ void Boxx::drawPara(const char* text, int x, int y, const DrawStyle& colour) if (printLine || (linePos > 1)) // if some text was put in line { - drawText(line, x, ypos, colour); - ypos += lineHeight; - if (ypos > (int)(area.h - lineHeight)) break; + if (ypos <= (int)(area.h - lineHeight + paraVSpace)) { + if (drawLinePos >= 0) { + drawText(line, x, ypos, colour); + ypos += lineHeight; + } + } else { + leftlines++; + } + drawLinePos++; } else { break; } } + return leftlines; } void Boxx::rectangle(Region& region, const DrawStyle& colour) @@ -411,6 +422,27 @@ void Boxx::drawMonoBitmap(UCHAR*base, int dx, int dy, unsigned int height,unsign else if (surface) surface->drawMonoBitmap(base, dx,dy, height, width, nextColour); } +void Boxx::drawTVMedia(TVMediaInfo & tvmedia,float x, float y, float width, float height, Corner corner) +{ + if (parent) parent->drawTVMedia(tvmedia,area.x + x,area.y + y,width, height, corner); + else if (surface) { + SurfaceVector * surfacevector=dynamic_cast(surface); + if (surfacevector) surfacevector->drawTVMedia(tvmedia,x, y,width, height, corner); + else surface->fillblt(x, y, width, height, DrawStyle::RED); // Signal that something went wrong + } + +} + +void Boxx::drawClippingRectangle(float x, float y, float w, float h) +{ + if (parent) parent->drawClippingRectangle(area.x + x, area.y + y, w, h); + else if (surface) { + SurfaceVector * surfacevector=dynamic_cast(surface); + if (surfacevector) surfacevector->drawClippingRectangle(x, y, w, h); + + } +} + int Boxx::getFontHeight() { if (parent) return parent->getFontHeight(); diff --git a/boxx.h b/boxx.h index a90a070..1b76866 100644 --- a/boxx.h +++ b/boxx.h @@ -32,6 +32,8 @@ using namespace std; #include "surface.h" +#include "tvmedia.h" +#include "osdvector.h" class Bitmap; @@ -91,7 +93,7 @@ class Boxx // Drawing functions level 1 void fillColour(const DrawStyle & colour); - void drawPara(const char* text, int x, int y, const DrawStyle& colour); + int drawPara(const char* text, int x, int y, const DrawStyle& colour, unsigned int skiplines=0); // Drawing functions level 0 void rectangle(UINT x, UINT y, UINT w, UINT h, const DrawStyle& colour); @@ -106,6 +108,8 @@ class Boxx void drawBitmap(UINT x, UINT y, const Bitmap& bm, const DisplayRegion & region); //Now deprecated // void drawPixelAlpha(UINT x, UINT y, const Colour& colour,bool fastdraw=false); + void drawTVMedia(TVMediaInfo & tvmedia,float x, float y, float width, float height, Corner corner=TopLeft); + void drawClippingRectangle(float x, float y, float w, float h); int getFontHeight(); void drawJpeg(const char *fileName,int x, int y,int *width, int *height); diff --git a/command.cc b/command.cc index 8288d2f..b942f2c 100644 --- a/command.cc +++ b/command.cc @@ -445,6 +445,18 @@ void Command::processMessage(Message* m) break; } + case Message::PICTURES_ARRIVED: + { + Log::getInstance()->log("Command", Log::DEBUG, "TVMedia Pictures arrived"); + OsdVector *osdv=dynamic_cast(Osd::getInstance()); + if (osdv) { + osdv->processReceivedPictures(); + /* if (osdv->processReceivedPictures()) { + Log::getInstance()->log("Command", Log::DEBUG, "TVMedia Boxstack update triggered"); + boxstack->update(NULL,NULL); + }*/ + } + } break; } } else @@ -595,6 +607,7 @@ void Command::doPowerOff() void Command::doFromTheTop(bool which) { + if (isStandby) return; if (which) { if (connLost) diff --git a/eventdispatcher.cc b/eventdispatcher.cc index eba132a..dd1692b 100644 --- a/eventdispatcher.cc +++ b/eventdispatcher.cc @@ -60,8 +60,9 @@ bool EventDispatcher::edFindAndCall(void* userTag) } edr->callinprogress = true; - edUnlock(); - bool edrType = edr->call(userTag); + edUnlock(); + bool edr_delete=false; + bool edrType = edr->call(userTag,edr_delete); edLock(); edr->callinprogress = false; @@ -97,6 +98,7 @@ bool EventDispatcher::edFindAndCall(void* userTag) #else SetEvent(edr->cond); #endif + if (edr_delete) delete edr; } edUnlock(); diff --git a/eventdispatcher.h b/eventdispatcher.h index 3b0a5ee..500ec59 100644 --- a/eventdispatcher.h +++ b/eventdispatcher.h @@ -44,7 +44,7 @@ class EDReceiver //(implementation in eventdispatcher.cc) virtual ~EDReceiver(); protected: - virtual bool call(void* userTag)=0; // Implementor must override this and do the actual call + virtual bool call(void* userTag, bool & deleteme)=0; // Implementor must override this and do the actual call // return true to have EventDispatcher remove receiver from list after call bool nomorecalls; bool callinprogress; diff --git a/message.h b/message.h index b53018a..1494129 100644 --- a/message.h +++ b/message.h @@ -77,6 +77,7 @@ class Message const static ULONG TELETEXTUPDATEFIRSTLINE = 33; const static ULONG SUBTITLE_CHANGE_CHANNEL = 34; const static ULONG MOUSE_ANDROID_SCROLL = 35; + const static ULONG PICTURES_ARRIVED = 36; }; #endif diff --git a/movieinfo.cc b/movieinfo.cc new file mode 100644 index 0000000..2513c18 --- /dev/null +++ b/movieinfo.cc @@ -0,0 +1,46 @@ +/* + Copyright 2014 Marten Richter + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "movieinfo.h" + +MovieInfo::MovieInfo() +{ + id=0; + title=""; + originalTitle=""; + tagline=""; + overview=""; + adult=0; + collectionName=""; + + budget=0; + revenue=0; + genres=""; + homepage=""; + releaseDate=""; + runtime=0; + popularity=0.f; + voteAverage=0.f; + + + +} + + diff --git a/movieinfo.h b/movieinfo.h new file mode 100644 index 0000000..31c3358 --- /dev/null +++ b/movieinfo.h @@ -0,0 +1,56 @@ +/* + Copyright 2014 Marten Richter + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef MOVIEINFO_H +#define MOVIEINFO_H + +#include "tvmedia.h" + +class MovieInfo { +public: + MovieInfo(); + + int id; + + std::string title; + std::string originalTitle; + std::string tagline; + std::string overview; + UCHAR adult; + std::string collectionName; + + int budget; + int revenue; + std::string genres; + std::string homepage; + std::string releaseDate; + int runtime; + float popularity; + float voteAverage; + + TVMedia poster; + TVMedia fanart; + TVMedia collectionPoster; + TVMedia collectionFanart; + Actors actors; +}; + + +#endif diff --git a/objects.mk b/objects.mk index 5ecff89..e27f749 100644 --- a/objects.mk +++ b/objects.mk @@ -24,5 +24,7 @@ OBJECTS1 = command.o tcp.o dsock.o thread.o timers.o i18n.o \ imagereader.o mediaoptions.o mediaplayer.o \ serialize.o localmediafile.o playermedia.o \ demuxermedia.o tfeed.o vteletextview.o teletextdecodervbiebu.o \ - teletxt/txtfont.o mediafile.o + teletxt/txtfont.o mediafile.o movieinfo.o seriesinfo.o wmovieview.o wseriesview.o tvmedia.o \ + wpictureview.o + diff --git a/osd.h b/osd.h index 5b96e68..0f87900 100644 --- a/osd.h +++ b/osd.h @@ -49,6 +49,8 @@ class Osd virtual int getFontNames(const char *** names,const char *** names_keys){ return 0;}; virtual void setFont(const char * fontname){}; + virtual float getPixelAspect() {return 1.f;}; + protected: static Osd* instance; int initted; diff --git a/osdopenvg.cc b/osdopenvg.cc index d11c0d9..207063a 100644 --- a/osdopenvg.cc +++ b/osdopenvg.cc @@ -304,6 +304,12 @@ int OsdOpenVG::init(void* device) return 1; } +void OsdOpenVG::getScreenSize(int &width, int &height) +{ + width=BACKBUFFER_WIDTH; + height=BACKBUFFER_HEIGHT; +} + void OsdOpenVG::initPaths() { @@ -798,6 +804,8 @@ void OsdOpenVG::drawSetTrans(SurfaceCommands & sc) vgLoadIdentity(); vgScale(((float)BACKBUFFER_WIDTH)/720.f, -((float)BACKBUFFER_HEIGHT)/576.f); vgTranslate(0.f+sc.x,-576.f+sc.y); + clip_shift_x=sc.x; + clip_shift_y=sc.y; @@ -829,15 +837,14 @@ void OsdOpenVG::executeDrawCommand(SVGCommand & command) case DrawImage: { vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); vgGetMatrix(save_matrix); - vgTranslate(command.x,command.y); - - + VGfloat imagewidth=vgGetParameteri((VGImage) command.target.image, VG_IMAGE_WIDTH); + VGfloat imageheight=vgGetParameteri((VGImage) command.target.image, VG_IMAGE_HEIGHT); //vgScale(command.w,command.h); - VGfloat imagewidth=vgGetParameteri((VGImage) command.target.image, VG_IMAGE_WIDTH); - VGfloat imageheight=vgGetParameteri((VGImage) command.target.image, VG_IMAGE_HEIGHT); + if (command.reference) { //special behaviout for bw images they act as a mask on the current paint + vgTranslate(command.x,command.y); vgSetPaint((VGPaint) command.reference,VG_FILL_PATH); vgSetPaint((VGPaint) command.reference,VG_STROKE_PATH); vgSeti(VG_IMAGE_MODE,VG_DRAW_IMAGE_STENCIL); @@ -851,6 +858,33 @@ void OsdOpenVG::executeDrawCommand(SVGCommand & command) //vgScale(720.f/((float)BACKBUFFER_WIDTH), 576.f/((float)BACKBUFFER_HEIGHT)); float scalex=command.w/imagewidth; float scaley=command.h/imageheight; + if (scalex==0.f && scaley==0.f) { + scalex=aspect_correction; + scaley=1.f; + } else if (scalex==0.f) { + scalex=scaley*aspect_correction; + } else if (scaley==0.f) { + scaley=scalex/aspect_correction; + } + float tx=command.x; + float ty=command.y; + + if (command.corner == BottomRight || command.corner == BottomLeft || command.corner == BottomMiddle) + { + ty-=imageheight * scaley; + } + + if (command.corner == BottomRight || command.corner == TopRight) + { + tx-=imagewidth * scalex; + } + + if (command.corner == BottomMiddle || command.corner == TopMiddle) + { + tx-=imagewidth * scalex *0.5f; + } + + vgTranslate(tx,ty); //vgScale(command.w/imagewidth,command.h/imageheight); vgScale(scalex,scaley); vgSeti(VG_IMAGE_MODE,VG_DRAW_IMAGE_NORMAL); @@ -950,6 +984,17 @@ void OsdOpenVG::executeDrawCommand(SVGCommand & command) vgSeti(VG_BLEND_MODE, VG_BLEND_SRC); }break; + case DrawClipping: { + VGint coords[4]={0,0,0,0}; + coords[0]= ((command.x+clip_shift_x)*((float)BACKBUFFER_WIDTH)/720.f); + coords[1]= ((576.f-command.y-clip_shift_y-command.h)*((float)BACKBUFFER_HEIGHT)/576.f); + coords[2]= ((command.w-1.f)*((float)BACKBUFFER_WIDTH)/720.f); + coords[3]= ((command.h-1.f)*((float)BACKBUFFER_HEIGHT)/576.f); + vgSetiv(VG_SCISSOR_RECTS, 4,coords); + if (command.w==0.f && command.h==0.f) + vgSeti(VG_SCISSORING,VG_FALSE); + else vgSeti(VG_SCISSORING,VG_TRUE); + } break; } } @@ -995,8 +1040,7 @@ unsigned int OsdOpenVG::handleTask(OpenVGCommand& command) } break; case OVGcreateMonoBitmap: { VGImage handle=vgCreateImage(VG_A_1,command.param1, command.param2, - VG_IMAGE_QUALITY_NONANTIALIASED| - VG_IMAGE_QUALITY_FASTER|VG_IMAGE_QUALITY_BETTER); + VG_IMAGE_QUALITY_FASTER); //Log::getInstance()->log("OSD", Log::DEBUG, "Draw create mono %d %d %x %d",command.param1,command.param2,vgGetError(),handle); unsigned int buffer_len=(command.param1*command.param2)>>3; unsigned char * buffer=(unsigned char*)malloc(buffer_len); @@ -1025,12 +1069,11 @@ unsigned int OsdOpenVG::handleTask(OpenVGCommand& command) handle=vgCreateImage(VG_sXBGR_8888,imagefile->columns(),imagefile->rows(), - VG_IMAGE_QUALITY_NONANTIALIASED| - VG_IMAGE_QUALITY_FASTER|VG_IMAGE_QUALITY_BETTER); - // Log::getInstance()->log("OSD", Log::DEBUG, "Draw create image details %d %d %x mark1",imagefile->columns(),imagefile->rows(),*(unsigned int*)imageblob.data()); + VG_IMAGE_QUALITY_BETTER); + //Log::getInstance()->log("OSD", Log::DEBUG, "Draw create image details %d %d %x mark1",imagefile->columns(),imagefile->rows(),(unsigned int*)imageblob.data()); vgImageSubData(handle,imageblob.data(),imagefile->columns()*4, VG_sXBGR_8888,0,0,imagefile->columns(),imagefile->rows()); - // Log::getInstance()->log("OSD", Log::DEBUG, "Draw create image details %d %d %x mark2",imagefile->columns(),imagefile->rows(),*(unsigned int*)imageblob.data()); + //Log::getInstance()->log("OSD", Log::DEBUG, "Draw create image details %d %d %x mark2",imagefile->columns(),imagefile->rows(),(unsigned int*)imageblob.data()); delete imagefile; }catch( Exception &error_ ) { @@ -1248,6 +1291,30 @@ ImageIndex OsdOpenVG::createJpeg(const char* fileName, int *width,int *height) return putOpenVGCommand(comm,true); } +ImageIndex OsdOpenVG::createPicture(unsigned char *data, unsigned int length) +{ + Image* magicimage=NULL; + bool mem=false; + struct OpenVGCommand comm; + comm.task=OVGcreateImageFile; + + try{ + // Now figure out, if it is a special case + //Log::getInstance()->log("OSD", Log::DEBUG, "createPicture"); + magicimage=new Image(Blob(data,length)); // fix me this is an unnecessary memcpy + free(data); + }catch( Exception &error_ ) + { + Log::getInstance()->log("OSD", Log::DEBUG, "Libmagick: %s",error_.what()); + + return 0; + } + comm.data=magicimage; + return putOpenVGCommand(comm,true); +} + + + ImageIndex OsdOpenVG::createMonoBitmap(void *base,int width,int height) { struct OpenVGCommand comm; diff --git a/osdopenvg.h b/osdopenvg.h index baf6c0c..051e173 100644 --- a/osdopenvg.h +++ b/osdopenvg.h @@ -90,6 +90,8 @@ class OsdOpenVG : public OsdVector, public Thread_TYPE virtual void setFont(const char * fontname); + virtual float getPixelAspect() {return aspect_correction;}; + protected: /*osd vector implementation*/ @@ -97,6 +99,7 @@ protected: ImageIndex createJpeg(const char* fileName, int *width,int *height); ImageIndex createMonoBitmap(void *base,int width,int height); ImageIndex createImagePalette(int width,int height,const unsigned char *image_data,const unsigned int*palette_data); + ImageIndex createPicture(unsigned char *data, unsigned int length); void destroyStyleRef(unsigned int index); unsigned int createStyleRef(const DrawStyle &c); unsigned int createColorRef(const Colour &c); @@ -109,6 +112,7 @@ protected: VGPath std_paths[Point+1]; long long lastrendertime; void InternalRendering(); + void getScreenSize(int &width, int &height); @@ -136,6 +140,9 @@ protected: vector fontnames_keys; char * cur_fontname; + int clip_shift_x; + int clip_shift_y; + unsigned int loadTTchar(cTeletextChar c); map tt_font_chars; diff --git a/osdvector.cc b/osdvector.cc index 457cd80..8012ff6 100644 --- a/osdvector.cc +++ b/osdvector.cc @@ -20,10 +20,15 @@ #include "osdvector.h" #include "surfacevector.h" +#include "vdr.h" +#include "vdrresponsepacket.h" +#include "command.h" +#include "message.h" OsdVector::OsdVector() { setlocale(LC_CTYPE,"C.UTF-8"); + picture_update=true; } OsdVector::~OsdVector() @@ -108,6 +113,8 @@ void OsdVector::drawSurfaces() } itty1++; } + int swidth,sheight; + getScreenSize(swidth,sheight); //Now go through all surfaces and draw them list::iterator curdraw=todraw.begin(); while (curdraw!=todraw.end()) { @@ -115,7 +122,21 @@ void OsdVector::drawSurfaces() list::iterator commands=(*(*curdraw)).commands.begin(); list::iterator end=(*(*curdraw)).commands.end(); while (commands!=end) { - executeDrawCommand(*commands); + // update any images loaded in the mean time + if ((*commands).instr==DrawImageLoading) { + LoadIndex loadindex=(*commands).target.loadindex; + if (tvmedias_loaded.find(loadindex)!=tvmedias_loaded.end()) { + (*commands).instr=DrawImage; + (*commands).target.image=tvmedias_loaded[loadindex];; + incImageRef((*commands).target.image); + removeLoadIndexRef(loadindex); + } + + } + // Now check if the command is on screen! + if (!(*commands).Outside(0,0,swidth,sheight)) { + executeDrawCommand(*commands); + } commands++; } curdraw++; @@ -124,7 +145,6 @@ void OsdVector::drawSurfaces() surfaces_mutex.Unlock(); } - void OsdVector::updateOrAddSurface(const SurfaceVector *surf,float x,float y,float height,float width, list& commands) { @@ -149,6 +169,25 @@ void OsdVector::updateOrAddSurface(const SurfaceVector *surf,float x,float y,flo new_sc.h=height; itty=scommands.insert(itty,new_sc); } + // update any images loaded in the mean time + list::iterator ilitty=commands.begin(); + + while (ilitty!=commands.end()) + { + if ((*ilitty).instr==DrawImageLoading) { + LoadIndex loadindex=(*ilitty).target.loadindex; + if (tvmedias_loaded.find(loadindex)!=tvmedias_loaded.end()) { + + (*ilitty).instr=DrawImage; + (*ilitty).target.image=tvmedias_loaded[loadindex]; + incImageRef((*ilitty).target.image); + removeLoadIndexRef(loadindex); + } + } + ilitty++; + } + + // then clear and copy (*itty).commands.clear(); (*itty).commands=commands; @@ -159,6 +198,8 @@ void OsdVector::updateOrAddSurface(const SurfaceVector *surf,float x,float y,flo incStyleRef((*sitty).getRef()); ImageIndex ii=(*sitty).getImageIndex(); if (ii) incImageRef(ii); + LoadIndex li=(*sitty).getLoadIndex(); + if (li) incLoadIndexRef(li); sitty++; } cleanupOrphanedRefs(); @@ -192,6 +233,8 @@ void OsdVector::dereferenceSVGCommand(list& commands ) removeStyleRef((*sitty).getRef()); ImageIndex ii = (*sitty).getImageIndex(); if (ii) removeImageRef(ii); + LoadIndex li=(*sitty).getLoadIndex(); + if (li) removeLoadIndexRef(li); sitty++; } } @@ -204,10 +247,13 @@ void OsdVector::referenceSVGCommand(list& commands ) incStyleRef((*sitty).getRef()); ImageIndex ii=(*sitty).getImageIndex(); if (ii) incImageRef(ii); + LoadIndex li=(*sitty).getLoadIndex(); + if (li) incLoadIndexRef(li); sitty++; } } + void OsdVector::incImageRef(ImageIndex index) { if (images_ref.find(index)==images_ref.end()) { @@ -222,6 +268,39 @@ void OsdVector::removeImageRef(const ImageIndex ref) images_ref[ref]--; } +unsigned int OsdVector::getLoadIndexRef(LoadIndex index) +{ + if (loadindex_ref.find(index)==loadindex_ref.end()) { + return -1; + } else { + return loadindex_ref[index]; + } +} + +void OsdVector::incLoadIndexRef(LoadIndex index) +{ + if (loadindex_ref.find(index)==loadindex_ref.end()) { + loadindex_ref[index]=1; + } else { + loadindex_ref[index]++; + } +} + +void OsdVector::removeLoadIndexRef(const LoadIndex ref) +{ + loadindex_ref[ref]--; + if (loadindex_ref[ref]==0) { + //now check, if it is already loaded + map::iterator itty=tvmedias_loaded.find(ref); + if ( itty != tvmedias_loaded.end()) { + removeImageRef((*itty).second); // remove lock + } + tvmedias_loaded.erase(ref); + tvmedias_load.erase(tvmedias_load_inv[ref]); + tvmedias_load_inv.erase(ref); + } +} + void OsdVector::cleanupOrphanedRefs() { // Do some garbage collection @@ -249,6 +328,20 @@ void OsdVector::cleanupOrphanedRefs() } else ++jitty; } + map::iterator titty=tvmedias.begin(); + while (titty!=tvmedias.end()) { + map::iterator curitty=images_ref.find((*titty).second); + int count=(*curitty).second; + if (count==0) { + + Log::getInstance()->log("OsdVector", Log::DEBUG, "TVMedia destroy Picture"); + ImageIndex ref=(*curitty).first; + tvmedias.erase(titty++); + images_ref.erase(curitty++); + destroyImageRef(ref); + } else ++titty; + } + map,unsigned int>::iterator sitty=styles.begin(); while (sitty!=styles.end()) { @@ -333,6 +426,68 @@ unsigned int OsdVector::getStyleRef(unsigned int index) } } +LoadIndex OsdVector::getTVMediaRef(TVMediaInfo& tvmedia, ImageIndex& image) +{ + ImageIndex image_handle=0; + LoadIndex loadindex=0; + if (tvmedias.find(tvmedia)==tvmedias.end()) + { + loadindex=loadTVMedia(tvmedia); + } else { + image_handle=tvmedias[tvmedia]; + if (images_ref.find(image_handle)==images_ref.end()) { + //invalid handle recreate + loadindex=loadTVMedia(tvmedia); + image_handle=0; + } else { + incImageRef(image_handle); + } + } + /*tvmedias[tvmedia]=createTVMedia(tvmedia,width,height); + incImageRef(image_handle);*/ + image=image_handle; + return loadindex; +} + +LoadIndex OsdVector::loadTVMedia(TVMediaInfo& tvmedia) +{ + LoadIndex index=0; + if (tvmedias_load.find(tvmedia)==tvmedias_load.end()) + { + index=VDR::getInstance()->loadTVMedia(tvmedia); + tvmedias_load[tvmedia]=index; + tvmedias_load_inv[index]=tvmedia; + } else { + index=tvmedias_load[tvmedia]; + } + + incLoadIndexRef(index); + + return index; +} + +void OsdVector::setTVMedia(LoadIndex index, unsigned char * buffer, unsigned int length) +{ + //Beware for thread safety + ImageIndex image_index=0; + + TVMediaInfo tvmedia=tvmedias_load_inv[index]; + Log::getInstance()->log("OsdVector", Log::DEBUG, "TVMedia Picture for request id %d arrived",index); + if (buffer) { + if (getLoadIndexRef(index)<1) { + // we do not want the picture anymore . Really... + } else { + image_index=tvmedias[tvmedia]=createPicture(buffer,length); + tvmedias_loaded[index]=image_index; + incImageRef(image_index); // hold one index until all loadings refs are gone; + } + } + + +} + + + ImageIndex OsdVector::getJpegRef(const char* fileName, int *width,int *height) { ImageIndex image_handle=0; @@ -376,3 +531,56 @@ ImageIndex OsdVector::getImagePalette(int width,int height,const unsigned char incImageRef(image_handle); return image_handle; } + +void OsdVector::receivePicture(VDR_ResponsePacket *vresp) +{ + pict_lock_incoming.Lock(); + pict_incoming.push(vresp); + pict_lock_incoming.Unlock(); + //Log::getInstance()->log("OsdVector", Log::DEBUG, "TVMedia Pictures arrived"); + if (picture_update) { + Message* m = new Message(); + // This is incoming from VDR, we do not want to block gui so send a message to ourself to switch to gui thread + m->message=Message::PICTURES_ARRIVED; + m->from=this; + m->to=Command::getInstance(); + picture_update=false; + Command::getInstance()->postMessageFromOuterSpace(m); // inform command about new picture + } +} + +bool OsdVector::processReceivedPictures() +{ + bool ret=false; + pict_lock_incoming.Lock(); + int i=0; + long long time1 = getTimeMS(); + long long cur_time =time1; + while (pict_incoming.size() && (time1-cur_time)<100) { + VDR_ResponsePacket *vresp=pict_incoming.front(); + pict_incoming.pop(); + pict_lock_incoming.Unlock(); + if (vresp->getFlag() != 2) { + setTVMedia(vresp->getStreamID(), vresp->getUserData(), vresp->getUserDataLength()); + ret=true; + } + else setTVMedia(vresp->getStreamID(), NULL, 0); + delete vresp; + cur_time = getTimeMS(); + pict_lock_incoming.Lock(); + } + if (pict_incoming.size()==0) picture_update=true; + pict_lock_incoming.Unlock(); + + + if (!picture_update) { + Message* m = new Message(); + // We have remaing pictures! send a message to ourself to switch to gui thread + m->message=Message::PICTURES_ARRIVED; + m->from=this; + m->to=Command::getInstance(); + picture_update=false; + Command::getInstance()->postMessageNoLock(m); // inform command about new picture + } + return ret; +} diff --git a/osdvector.h b/osdvector.h index b9474f1..6221ae5 100644 --- a/osdvector.h +++ b/osdvector.h @@ -25,15 +25,21 @@ #include "colour.h" #include #include +#include #include +#include "tvmedia.h" +#include "vdr.h" #include "teletextdecodervbiebu.h" enum SVGCommandInstr { + DrawNoop, DrawPath, DrawGlyph, DrawImage, - DrawTTchar + DrawTTchar, + DrawClipping, + DrawImageLoading }; enum PathIndex { HorzLine, @@ -42,50 +48,108 @@ enum PathIndex { Point }; +enum Corner{ + TopLeft, + TopRight, + BottomLeft, + BottomRight, + TopMiddle, + BottomMiddle +}; + typedef unsigned int ImageIndex; +typedef unsigned int LoadIndex; class SVGCommand { public: - SVGCommand(float ix, float iy,float iw,float ih,PathIndex path,unsigned int ref) + SVGCommand() + { + instr=DrawNoop; + x=y=w=h=reference=0; + }; + + static SVGCommand PaintPath(float ix, float iy,float iw,float ih,PathIndex path,unsigned int ref) + { + SVGCommand nc; + nc.instr=DrawPath; + nc.x=ix; + nc.y=iy; + nc.w=iw; + nc.h=ih; + nc.target.path_index=path; + nc.reference=ref; + return nc; + }; + + static SVGCommand PaintImageLoading(LoadIndex load_in,float ix, float iy,float iw,float ih,unsigned int ref, Corner corner=TopLeft) + { + SVGCommand nc; + nc.instr=DrawImageLoading; + nc.x=ix; + nc.y=iy; + nc.w=iw; + nc.h=ih; + nc.target.loadindex=load_in; + nc.reference=ref; + nc.corner=corner; + return nc; + }; + + static SVGCommand PaintImage(float ix, float iy,float iw,float ih,ImageIndex image_in,unsigned int ref, Corner corner=TopLeft) { - instr=DrawPath; - x=ix; - y=iy; - w=iw; - h=ih; - target.path_index=path; - reference=ref; + SVGCommand nc; + nc.instr=DrawImage; + nc.x=ix; + nc.y=iy; + nc.w=iw; + nc.h=ih; + nc.target.image=image_in; + nc.reference=ref; + nc.corner=corner; + return nc; }; - SVGCommand(float ix, float iy,float iw,float ih,ImageIndex image_in,unsigned int ref) + + + + static SVGCommand PaintTTchar(float ix, float iy,float iw,float ih,unsigned int ttchar_in) { - instr=DrawImage; - x=ix; - y=iy; - w=iw; - h=ih; - target.image=image_in; - reference=ref; + SVGCommand nc; + nc.instr=DrawTTchar; + nc.x=ix; + nc.y=iy; + nc.w=iw; + nc.h=ih; + nc.reference=0; + nc.target.ttchar=ttchar_in; + nc.corner=TopLeft; + return nc; }; - SVGCommand(float ix, float iy,float iw,float ih,unsigned int ttchar_in) + static SVGCommand PaintClipping(float ix, float iy,float iw,float ih) { - instr=DrawTTchar; - x=ix; - y=iy; - w=iw; - h=ih; - reference=0; - target.ttchar=ttchar_in; + SVGCommand nc; + nc.instr=DrawClipping; + nc.x=ix; + nc.y=iy; + nc.w=iw; + nc.h=ih; + nc.reference=0; + nc.target.ttchar=0; + return nc; }; - SVGCommand(float ix, float iy,wchar_t char_in,unsigned int ref) + + + static SVGCommand PaintGlyph(float ix, float iy,wchar_t char_in,unsigned int ref) { - instr=DrawGlyph; - x=ix; - y=iy; - w=0; - h=0; - reference=ref; - target.textchar=char_in; + SVGCommand nc; + nc.instr=DrawGlyph; + nc.x=ix; + nc.y=iy; + nc.w=0; + nc.h=0; + nc.reference=ref; + nc.target.textchar=char_in; + return nc; }; bool Test(float tx,float ty,float tw, float th) @@ -96,11 +160,21 @@ public: { return (x==tox) && (toy==y) && (w==tx) && (h==ty); } + bool Outside(float tx,float ty,float tw, float th) + { + return ((x+w) images_ref; map monobitmaps; map jpegs; + map tvmedias; + + + + void setTVMedia(LoadIndex index, unsigned char * buffer, unsigned int length); + Mutex pict_lock_incoming; //locks + std::queue pict_incoming; + bool picture_update; + + + map loadindex_ref; + map tvmedias_load; + map tvmedias_load_inv; + map tvmedias_loaded; void incStyleRef(unsigned int index); unsigned int getStyleRef(ImageIndex index); diff --git a/recinfo.cc b/recinfo.cc index 92cb205..66ff677 100644 --- a/recinfo.cc +++ b/recinfo.cc @@ -33,6 +33,8 @@ RecInfo::RecInfo() types = NULL; languages = NULL; descriptions = NULL; + + title = NULL; } RecInfo::~RecInfo() @@ -58,6 +60,8 @@ RecInfo::~RecInfo() delete[] types; } + if (title) delete [] title; + timerStart = 0; timerEnd = 0; resumePoint = 0; diff --git a/recinfo.h b/recinfo.h index 260bd5f..27844d4 100644 --- a/recinfo.h +++ b/recinfo.h @@ -44,6 +44,8 @@ class RecInfo char** languages; char** descriptions; + char *title; + void setNumComponents(ULONG); void addComponent(ULONG componentNum, UCHAR tstream, UCHAR ttype, char* tlanguage, char* tdescription); // addComponent accepts a pointer to a buffer that RecInfo will free, not the caller diff --git a/recording.cc b/recording.cc index d173cae..5bec001 100644 --- a/recording.cc +++ b/recording.cc @@ -26,9 +26,13 @@ #include "demuxer.h" #include "demuxerts.h" #include "command.h" +#include "seriesinfo.h" +#include "movieinfo.h" Recording* Recording::recInfoFor = NULL; RecInfo* Recording::recInfo = NULL; +MovieInfo* Recording::movieInfo = NULL; +SeriesInfo* Recording::seriesInfo = NULL; Recording::Recording() { @@ -41,6 +45,9 @@ Recording::Recording() fileName = NULL; index = -1; markList = NULL; + movieID = 0; + seriesID = 0; + episodeID = 0; } Recording::~Recording() @@ -112,7 +119,34 @@ void Recording::loadRecInfo() recInfo = vdr->getRecInfo(fileName); Log::getInstance()->log("Recording", Log::DEBUG, "Recording has loaded recInfo %p", recInfo); - if (!VDR::getInstance()->isConnected()) Command::getInstance()->connectionLost(); + if (!vdr->isConnected()) Command::getInstance()->connectionLost(); + + if (movieInfo) delete movieInfo; + if (seriesInfo) delete seriesInfo; + + movieInfo = NULL; + seriesInfo = NULL; + + vdr->getScraperEventType(fileName, movieID, seriesID, episodeID); + Log::getInstance()->log("Recording", Log::DEBUG, "Got Scraper EventType %d %d %d", + movieID, seriesID, episodeID); + + if (!vdr->isConnected()) Command::getInstance()->connectionLost(); + + if (movieID != 0) + { + movieInfo = vdr->getScraperMovieInfo(movieID); + Log::getInstance()->log("Recording", Log::DEBUG, "Got Scraper MovieInfo "); + } + else if (seriesID != 0) + { + seriesInfo = vdr->getScraperSeriesInfo(seriesID, episodeID); + Log::getInstance()->log("Recording", Log::DEBUG, "Got Scraper SeriesInfo "); + } + + + if (!vdr->isConnected()) Command::getInstance()->connectionLost(); + } void Recording::dropRecInfo() @@ -120,6 +154,11 @@ void Recording::dropRecInfo() if (recInfo) delete recInfo; recInfo = NULL; recInfoFor = NULL; + if (movieInfo) delete movieInfo; + if (seriesInfo) delete seriesInfo; + + movieInfo = NULL; + seriesInfo = NULL; } void Recording::loadMarks() diff --git a/recording.h b/recording.h index be72734..745d7a0 100644 --- a/recording.h +++ b/recording.h @@ -58,7 +58,13 @@ class Recording bool hasMarks(); MarkList* getMarkList(); + int movieID; + int seriesID; + int episodeID; + static RecInfo* recInfo; + static MovieInfo* movieInfo; + static SeriesInfo* seriesInfo; private: Log* logger; @@ -74,6 +80,7 @@ class Recording // else delete recInfo and reload for this recording static Recording* recInfoFor; + MarkList* markList; }; diff --git a/seriesinfo.cc b/seriesinfo.cc new file mode 100644 index 0000000..cd866d5 --- /dev/null +++ b/seriesinfo.cc @@ -0,0 +1,49 @@ +/* + Copyright 2014 Marten Richter + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "seriesinfo.h" + + +EpisodeInfo::EpisodeInfo() { + name=""; + firstAired=""; + guestStars=""; + overview=""; + + rating=0.; + season=0; + episodeid=0; + number=0; +} + +EpisodeInfo::~EpisodeInfo() { + +} + +SeriesInfo::SeriesInfo() +{ + id=0; + + + +} + + + diff --git a/seriesinfo.h b/seriesinfo.h new file mode 100644 index 0000000..adea749 --- /dev/null +++ b/seriesinfo.h @@ -0,0 +1,70 @@ +/* + Copyright 2014 Marten Richter + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef SERIESINFO_H +#define SERIESINFO_H + +#include "tvmedia.h" +#include + +class EpisodeInfo { +public: + EpisodeInfo(); + ~EpisodeInfo(); + + int episodeid; + int number; + int season; + std::string name; + std::string firstAired; + std::string guestStars; + std::string overview; + float rating ; + TVMedia image; + + +}; + +class SeriesInfo { +public: + SeriesInfo(); + + int id; + + + std::string name; + std::string overview; + std::string firstAired; + std::string network; + std::string genre; + double rating; + std::string status; + EpisodeInfo episode; // Image 0 + + + + + Actors actors; // Image 1 + TVMedias posters; // Image 2 + TVMedias banners; // Image 3 + TVMedias fanart; // Image 4 + TVMedia seasonposter; // Image 5 +}; +#endif diff --git a/surfacevector.cc b/surfacevector.cc index fa9659f..dff3432 100644 --- a/surfacevector.cc +++ b/surfacevector.cc @@ -37,7 +37,11 @@ SurfaceVector::~SurfaceVector() { osd->removeStyleRef((*itty).getRef()); // We remove the Style reference, so that osd can free stuff ImageIndex ii=(*itty).getImageIndex(); - if (ii) osd->removeImageRef(ii); + if (ii) { + osd->removeImageRef(ii); + } + LoadIndex li=(*itty).getLoadIndex(); + if (li) osd->removeLoadIndexRef(li); itty++; } } @@ -98,7 +102,7 @@ int SurfaceVector::drawText(const char* text, int x, int y, int width, const Dra while (num_bytes!=((size_t) -1) && num_bytes!=((size_t) -2) && length>0) { unsigned int ref=osd->getStyleRef(c); - commands.push_back(SVGCommand(x+shift,y,*tempo,ref)); + commands.push_back(SVGCommand::PaintGlyph(x+shift,y,*tempo,ref)); shift+=osd->getCharWidth(*tempo); length -= num_bytes; run += num_bytes; @@ -158,7 +162,30 @@ void SurfaceVector::drawJpeg(const char *fileName,int x, int y,int *width, int * { command_mutex.Lock(); ImageIndex image=osd->getJpegRef(fileName,width,height); - commands.push_back(SVGCommand(x,y,*width,*height,image,0)); + commands.push_back(SVGCommand::PaintImage(x,y,*width,*height,image,0)); + command_mutex.Unlock(); +} + +void SurfaceVector::drawTVMedia(TVMediaInfo & tvmedia,float x, float y, float width, float height, Corner corner) +{ + command_mutex.Lock(); + ImageIndex image=0; + LoadIndex load_index=osd->getTVMediaRef(tvmedia,image); + if (image) { + //Log::getInstance()->log("SurfaceVector", Log::DEBUG, "TVMedia Add instru image %d %d", load_index,image); + commands.push_back(SVGCommand::PaintImage(x,y,width,height,image,0,corner)); + } else { + + commands.push_back(SVGCommand::PaintImageLoading(load_index,x,y,width,height,0,corner)); + //Log::getInstance()->log("SurfaceVector", Log::DEBUG, "TVMedia Add instru image loading %d %d", load_index,image); + } + command_mutex.Unlock(); +} + +void SurfaceVector::drawClippingRectangle(float x, float y, float w, float h) +{ + command_mutex.Lock(); + commands.push_back(SVGCommand::PaintClipping((float)x,(float)y,(float)w,(float)h)); command_mutex.Unlock(); } @@ -178,7 +205,7 @@ int SurfaceVector::fillblt(int x, int y, int width, int height, const DrawStyle& command_mutex.Lock(); removeCommands(x,y,width,height); // remove commands below the box unsigned int ref=osd->getStyleRef(c); - commands.push_back(SVGCommand(x,y,width,height,Rectangle,ref)); + commands.push_back(SVGCommand::PaintPath(x,y,width,height,Rectangle,ref)); command_mutex.Unlock(); return 1; @@ -187,14 +214,14 @@ void SurfaceVector::drawHorzLine(int x1, int x2, int y, const DrawStyle& c) { command_mutex.Lock(); unsigned int ref=osd->getStyleRef(c); - commands.push_back(SVGCommand(x1,y,x2-x1,1,HorzLine,ref)); + commands.push_back(SVGCommand::PaintPath(x1,y,x2-x1,1,HorzLine,ref)); command_mutex.Unlock(); } void SurfaceVector::drawVertLine(int x, int y1, int y2, const DrawStyle& c){ command_mutex.Lock(); unsigned int ref=osd->getStyleRef(c); - commands.push_back(SVGCommand(x,y1,1,y2-y1,VertLine,ref)); + commands.push_back(SVGCommand::PaintPath(x,y1,1,y2-y1,VertLine,ref)); command_mutex.Unlock(); } @@ -224,7 +251,7 @@ void SurfaceVector::drawBitmap(int x, int y, const Bitmap& bm,const DisplayRegio ty*=scaley; tw*=scalex; th*=scaley; - SVGCommand temp=SVGCommand(tx,ty,tw,th,image,0); + SVGCommand temp=SVGCommand::PaintImage(tx,ty,tw,th,image,0); commands.push_back(temp); command_mutex.Unlock(); } @@ -232,7 +259,7 @@ void SurfaceVector::drawBitmap(int x, int y, const Bitmap& bm,const DisplayRegio void SurfaceVector::drawPoint(int x, int y, DrawStyle& c, bool fastdraw){ if (!fastdraw) command_mutex.Lock(); unsigned int ref=osd->getStyleRef(c); - commands.push_back(SVGCommand(x,y,1,1,Point,ref)); + commands.push_back(SVGCommand::PaintPath(x,y,1,1,Point,ref)); if (!fastdraw) command_mutex.Unlock(); } void SurfaceVector::drawMonoBitmap(UCHAR* base, int dx, int dy, unsigned int height,unsigned int width, DrawStyle& nextColour) @@ -240,7 +267,7 @@ void SurfaceVector::drawMonoBitmap(UCHAR* base, int dx, int dy, unsigned int hei command_mutex.Lock(); ImageIndex image=osd->getMonoBitmapRef(base,width,height); unsigned int ref=osd->getStyleRef(nextColour); - commands.push_back(SVGCommand(dx,dy,height,width,image,ref)); + commands.push_back(SVGCommand::PaintImage(dx,dy,height,width,image,ref)); command_mutex.Unlock(); } @@ -251,10 +278,12 @@ int SurfaceVector::removeCommands(float x,float y,float width,float height) list::iterator itty=commands.begin(); while (itty!=commands.end()) { - if ((*itty).Test(x,y,width,height) ) { + if ((*itty).Test(x,y,width,height) && (*itty).instr != DrawClipping) { osd->removeStyleRef((*itty).getRef()); // We remove the Style reference, so that osd can free stuff ImageIndex ii=(*itty).getImageIndex(); if (ii) osd->removeImageRef(ii); + LoadIndex li=(*itty).getLoadIndex(); + if (li) osd->removeLoadIndexRef(li); itty=commands.erase(itty); } else { itty++; @@ -296,6 +325,6 @@ void SurfaceVector::drawTTChar(int ox, int oy,int x, int y, cTeletextChar c) itty++; } } - commands.push_back(SVGCommand(ox,oy,x,y,c.getInternal())); + commands.push_back(SVGCommand::PaintTTchar(ox,oy,x,y,c.getInternal())); command_mutex.Unlock(); } diff --git a/surfacevector.h b/surfacevector.h index 519abcd..fb31b17 100644 --- a/surfacevector.h +++ b/surfacevector.h @@ -43,6 +43,11 @@ class SurfaceVector : public Surface int drawTextCentre(const char* text, int x, int y, const DrawStyle& c); void drawJpeg(const char *fileName,int x, int y,int *width, int *height); + // set width and height to zero, if the original size is wanted, if one index is non zero, + // the images is scaled with correct aspect ratio, if both are non zero both are scaled + void drawTVMedia(TVMediaInfo & tvmedia,float x, float y, float width, float height, Corner corner=TopLeft); + // set w and h to 0, for unsetting clipping, use correct x and y parameter so that cleanup of commands works + void drawClippingRectangle(float x, float y, float w, float h); int create(UINT width, UINT height); void display(); diff --git a/tvmedia.cc b/tvmedia.cc new file mode 100644 index 0000000..8460b56 --- /dev/null +++ b/tvmedia.cc @@ -0,0 +1,91 @@ +/* + Copyright 2014 Marten Richter + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "tvmedia.h" +#include "movieinfo.h" +#include "seriesinfo.h" + + +TVMediaInfo::TVMediaInfo() +{ + type=2; // movie or series + primary_id=0; //movie or series_id + secondary_id=0; //0 or episode id + type_pict=-1; // 0 full info, 1 poster, 2 poster banner, 3 poster thumb + container=-1; // indices the dataelements with picture in movieinfo or seriesinfo + container_member=-1; // index into the container +} + + + +TVMediaInfo::TVMediaInfo(const TVMediaInfo& info) +{ + type=info.type; // movie or series + primary_id=info.primary_id; //movie or series_id + secondary_id=info.secondary_id; //0 or episode id + type_pict=info.type_pict; // 0 full info, 1 poster, 2 poster banner, 3 poster thumb + container=info.container; // indices the dataelements with picture in movieinfo or seriesinfo + container_member=info.container_member; // index into the container + +} + +void TVMediaInfo::setMovieInfo(const MovieInfo * mi) +{ + type=1; // movie or series + primary_id=mi->id; //movie or series_id + secondary_id=0; //0 or episode id +} + +void TVMediaInfo::setSeriesInfo(const SeriesInfo * si) +{ + type=0; // movie or series + primary_id=si->id; //movie or series_id + secondary_id=si->episode.episodeid; //0 or episode id +} + +bool operator<(const TVMediaInfo& rhs, const TVMediaInfo& lhs) +{ + if (rhs.type==lhs.type) { + if (rhs.primary_id==lhs.primary_id) { + if (rhs.secondary_id==lhs.secondary_id) { + if (rhs.type_pict==lhs.type_pict) { + if (rhs.container==lhs.container) { + return rhs.container_member +#include + +class MovieInfo; +class SeriesInfo; + +class TVMediaInfo +{ +friend class VDR; +public: + TVMediaInfo(); + TVMediaInfo(const TVMediaInfo& info); + + friend bool operator<(const TVMediaInfo& rhs, const TVMediaInfo& lhs); + + void setSeasonThumb() { type_pict=2; container=0; container_member=0;}; + void setPosterThumb() { type_pict=1; container=0; container_member=0;}; + void setElement(int cont,int memb) { type_pict=0; container=cont; container_member=memb;}; + void setMovieInfo(const MovieInfo * mi); + void setSeriesInfo(const SeriesInfo * si); + +private: + int type; // movie or series + int primary_id; //movie or series_id + int secondary_id; //0 or episode id + int type_pict; // 0 full info, 1 poster thumb, 2 season thumb + int container; // indices the dataelements with picture in movieinfo or seriesinfo + int container_member; // index into the container +}; + +struct TVMedia +{ + unsigned int width; + unsigned int height; + + // no filename, file handling is only on the server + TVMediaInfo info; + +}; + +typedef std::vector TVMedias; + +struct Actor +{ + std::string name; + std::string role; + TVMedia thumb; +}; + +typedef std::vector Actors; + +#endif diff --git a/vconnect.cc b/vconnect.cc index e923665..7755073 100644 --- a/vconnect.cc +++ b/vconnect.cc @@ -162,15 +162,15 @@ void VConnect::threadMethod() if (success) { logger->log("VConnect", Log::DEBUG, "Connected ok, doing login"); - unsigned int version_server,version_client; - success = vdr->doLogin(&version_server,&version_client); + unsigned int version_server_min,version_server_max,version_client; + success = vdr->doLogin(&version_server_min,&version_server_max,&version_client); if (!success) { vdr->disconnect(); - if (version_server!=version_client) { + if (version_server_min >version_client || version_client > version_server_max) { char buffer[1024]; - sprintf(buffer,"Protocoll mismatch s: %x c: %x",version_server,version_client); + sprintf(buffer,"Protocol mismatch s min: %x s max: %x c: %x",version_server_min,version_server_max,version_client); setOneLiner(buffer); } else { setOneLiner(tr("Login failed")); diff --git a/vdr.cc b/vdr.cc index bb2d4d3..e8d7043 100644 --- a/vdr.cc +++ b/vdr.cc @@ -37,8 +37,11 @@ #include "vdrcommand.h" #include "video.h" #include "osd.h" +#include "movieinfo.h" +#include "seriesinfo.h" -#define VOMP_PROTOCOLL_VERSION 0x00000301 + +#define VOMP_PROTOCOLL_VERSION 0x00000302 VDR* VDR::instance = NULL; //prepare a request @@ -348,7 +351,7 @@ void VDR::threadMethod() // Data was read channelID = ntohl(channelID); - + if (channelID == CHANNEL_REQUEST_RESPONSE) { if (!tcp->readData((UCHAR*)&requestID, sizeof(ULONG))) break; @@ -375,7 +378,7 @@ void VDR::threadMethod() delete vresp; } } - else if (channelID == CHANNEL_STREAM) + else if (channelID == CHANNEL_STREAM || channelID == CHANNEL_TVMEDIA) { if (!tcp->readData((UCHAR*)&streamID, sizeof(ULONG))) break; streamID = ntohl(streamID); @@ -394,8 +397,8 @@ void VDR::threadMethod() } vresp = new VDR_ResponsePacket(); - vresp->setStream(streamID, flag, userData, userDataLength); -// logger->log("VDR", Log::DEBUG, "Rxd a stream packet, streamID=%lu, flag=%lu, len=%lu", streamID, flag, userDataLength); + vresp->setStream(streamID, flag, userData, userDataLength, channelID); + //logger->log("VDR", Log::DEBUG, "Rxd a stream packet, streamID=%lu, flag=%lu, len=%lu", streamID, flag, userDataLength); if (!edFindAndCall(vresp)) // makes ED lock, find receiver for vresp (using ed_cb_find() ) and then call (using ed_cb_call() ) { @@ -466,10 +469,10 @@ void VDR::connectionDied() } edLock(); } - else if (vdrpr->receiverChannel == CHANNEL_STREAM) + else if (vdrpr->receiverChannel == CHANNEL_STREAM || vdrpr->receiverChannel == CHANNEL_TVMEDIA) { vresp = new VDR_ResponsePacket(); - vresp->setStream(vdrpr->streamID, 2 /* connection-lost flag */ , NULL, 0); + vresp->setStream(vdrpr->streamID, 2 /* connection-lost flag */ , NULL, 0, vdrpr->receiverChannel); logger->log("VDR", Log::DEBUG, "Timeouts: created blank response packet for streamid %lu", vdrpr->streamID); edUnlock(); if (!edFindAndCall(vresp)) // makes ED lock, find receiver for vresp (using ed_cb_find() ) and then call (using ed_cb_call() ) @@ -503,6 +506,7 @@ bool VDR::ed_cb_find(EDReceiver* edr, void* userTag) // Is vresp for vdrpr ? ULONG packetChannel = vresp->getChannelID(); + //logger->log("VDR", Log::DEBUG, "TVMedia debug %d %d %x", vdrpr->receiverChannel,packetChannel,vdrpr); if (vdrpr->receiverChannel != packetChannel) return false; if (packetChannel == CHANNEL_REQUEST_RESPONSE) @@ -512,6 +516,9 @@ bool VDR::ed_cb_find(EDReceiver* edr, void* userTag) else if (packetChannel == CHANNEL_STREAM) { if (vdrpr->streamID == vresp->getStreamID()) return true; + } else if (packetChannel == CHANNEL_TVMEDIA) + { //We want them all + return true; } return false; @@ -584,7 +591,7 @@ bool VDR::sendKA(ULONG timeStamp) // Here VDR takes a break for the VDR_PacketReceiver helper class -bool VDR_PacketReceiver::call(void* userTag) +bool VDR_PacketReceiver::call(void* userTag, bool & deleteme) { if (receiverChannel == VDR::CHANNEL_REQUEST_RESPONSE) { @@ -592,6 +599,7 @@ bool VDR_PacketReceiver::call(void* userTag) // VDR::RequestResponse will be blocking waiting for this to happen. // That function has a pointer to this object and can read save_vresp. save_vresp = (VDR_ResponsePacket*)userTag; + deleteme=false; return true; // Signals ED to remove edr from receivers and wake up edr thread } @@ -601,15 +609,28 @@ bool VDR_PacketReceiver::call(void* userTag) VDR_ResponsePacket* vresp = (VDR_ResponsePacket*)userTag; streamReceiver->streamReceive(vresp->getFlag(), vresp->getUserData(), vresp->getUserDataLength()); delete vresp; + deleteme=false; return false; } + if (receiverChannel == VDR::CHANNEL_TVMEDIA) + { + // It's TVMedia + VDR_ResponsePacket* vresp = (VDR_ResponsePacket*)userTag; + Log::getInstance()->log("VDR", Log::DEBUG, "TVMedia Pictures arrived VDR"); + OsdVector *osd=dynamic_cast(Osd::getInstance()); + if (osd) osd->receivePicture(vresp); + else delete vresp; //nonsense + deleteme=false; + return true; + } + abort(); // unknown receiverChannel, should not happen } ///////////////////////////////////////////////////////////////////////////// -int VDR::doLogin(unsigned int* v_server,unsigned int* v_client) +int VDR::doLogin(unsigned int* v_server_min, unsigned int* v_server_max, unsigned int* v_client) { VDR_RequestPacket vrp; if (!vrp.init(VDR_LOGIN, true, 6)) return 0; @@ -626,14 +647,17 @@ int VDR::doLogin(unsigned int* v_server,unsigned int* v_client) long vdrTimeOffset = vresp->extractLONG(); logger->log("VDR", Log::DEBUG, "offset = %i", vdrTimeOffset); - unsigned int version=vresp->extractULONG(); + unsigned int version_min=vresp->extractULONG(); - *v_server=version; + *v_server_min=version_min; + unsigned int version_max=vresp->extractULONG(); + *v_server_max=version_max; *v_client=VOMP_PROTOCOLL_VERSION; delete vresp; - if (version!=VOMP_PROTOCOLL_VERSION) { + if ((version_min > VOMP_PROTOCOLL_VERSION) + || (version_max < VOMP_PROTOCOLL_VERSION) ) { return 0; @@ -1190,6 +1214,7 @@ RecInfo* VDR::getRecInfo(char* fileName) } } recInfo->fps=vresp->extractdouble(); + recInfo->title=vresp->extractString(); recInfo->print(); @@ -1566,3 +1591,209 @@ void VDR::shutdownVDR() logger->log("VDR", Log::DEBUG, "VDR shutdown"); } + +void VDR::getScraperEventType(char * fileName, int & movieID, + int & seriesID, int & episodeID ) +{ + movieID = 0; + seriesID = 0; + episodeID = 0; + VDR_RequestPacket vrp; + if (!vrp.init(VDR_GETRECSCRAPEREVENTTYPE, true, strlen(fileName) + 1)) return; + if (!vrp.addString(fileName)) return ; + Log::getInstance()->log("Recording", Log::DEBUG, "Before Response "); + VDR_ResponsePacket* vresp = RequestResponse(&vrp); + Log::getInstance()->log("Recording", Log::DEBUG, "After Response "); + if (vresp->noResponse()) { delete vresp; return ; } + int type = vresp->extractUCHAR(); + if (type == 0) //serie + { + seriesID = vresp->extractLONG(); + episodeID = vresp->extractLONG(); + } else if (type == 1) //movie + { + movieID = vresp->extractLONG(); + } + delete vresp; + +} + +MovieInfo *VDR::getScraperMovieInfo(int movieID) +{ + VDR_RequestPacket vrp; + if (!vrp.init(VDR_GETSCRAPERMOVIEINFO, false, 0)) return NULL; + if (!vrp.addULONG(movieID)) return NULL; + VDR_ResponsePacket* vresp = RequestResponse(&vrp); + if (vresp->noResponse()) { delete vresp; return NULL; } + MovieInfo * movieinf= new MovieInfo(); + + movieinf->id=movieID; + movieinf->title = vresp->extractStdString(); + movieinf->originalTitle = vresp->extractStdString(); + movieinf->tagline = vresp->extractStdString(); + movieinf->overview = vresp->extractStdString(); + movieinf->adult = vresp->extractUCHAR(); + movieinf->collectionName = vresp->extractStdString(); + + movieinf->budget = vresp->extractLONG(); + movieinf->revenue = vresp->extractLONG(); + movieinf->genres = vresp->extractStdString(); + movieinf->homepage = vresp->extractStdString(); + movieinf->releaseDate = vresp->extractStdString(); + movieinf->runtime = vresp->extractLONG(); + movieinf->popularity = vresp->extractdouble(); + movieinf->voteAverage = vresp->extractdouble(); + movieinf->poster.width = vresp->extractULONG(); + movieinf->poster.height = vresp->extractULONG(); + movieinf->poster.info.setMovieInfo(movieinf); + movieinf->poster.info.setElement(0,0); + movieinf->fanart.width = vresp->extractULONG(); + movieinf->fanart.height = vresp->extractULONG(); + movieinf->fanart.info.setMovieInfo(movieinf); + movieinf->fanart.info.setElement(1,0); + movieinf->collectionPoster.width = vresp->extractULONG(); + movieinf->collectionPoster.height = vresp->extractULONG(); + movieinf->collectionPoster.info.setMovieInfo(movieinf); + movieinf->collectionPoster.info.setElement(2,0); + movieinf->collectionFanart.width = vresp->extractULONG(); + movieinf->collectionFanart.height = vresp->extractULONG(); + movieinf->collectionFanart.info.setMovieInfo(movieinf); + movieinf->collectionFanart.info.setElement(3,0); + ULONG num_actors = vresp->extractULONG(); + movieinf->actors.clear(); + movieinf->actors.reserve(num_actors); + for (ULONG acty=0; acty < num_actors; acty++) { + Actor new_act; + new_act.name = vresp->extractStdString(); + new_act.role = vresp->extractStdString(); + new_act.thumb.width = vresp->extractULONG(); + new_act.thumb.height = vresp->extractULONG(); + new_act.thumb.info.setMovieInfo(movieinf); + new_act.thumb.info.setElement(4,acty); + movieinf->actors.push_back(new_act); + } + + + delete vresp; + return movieinf; + +} + +SeriesInfo *VDR::getScraperSeriesInfo(int seriesID, int episodeID) +{ + VDR_RequestPacket vrp; + if (!vrp.init(VDR_GETSCRAPERSERIESINFO, false, 0)) return NULL; + if (!vrp.addULONG(seriesID)) return NULL; + if (!vrp.addULONG(episodeID)) return NULL; + + VDR_ResponsePacket* vresp = RequestResponse(&vrp); + if (vresp->noResponse()) { delete vresp; return 0; } + SeriesInfo * seriesinf= new SeriesInfo(); + + seriesinf->id=seriesID; + + + seriesinf->name = vresp->extractStdString(); + seriesinf->overview = vresp->extractStdString(); + seriesinf->firstAired = vresp->extractStdString(); + seriesinf->network = vresp->extractStdString(); + seriesinf->genre = vresp->extractStdString(); + seriesinf->rating = vresp->extractdouble(); + seriesinf->status = vresp->extractStdString(); + + + seriesinf->episode.episodeid=episodeID; + seriesinf->episode.number = vresp->extractLONG(); + seriesinf->episode.season = vresp->extractLONG(); + seriesinf->episode.name = vresp->extractStdString(); + seriesinf->episode.firstAired = vresp->extractStdString(); + seriesinf->episode.guestStars = vresp->extractStdString(); + seriesinf->episode.overview = vresp->extractStdString(); + seriesinf->episode.rating = vresp->extractdouble(); + seriesinf->episode.image.width = vresp->extractULONG(); + seriesinf->episode.image.height = vresp->extractULONG(); + seriesinf->episode.image.info.setSeriesInfo(seriesinf); + seriesinf->episode.image.info.setElement(0,0); + + + ULONG num_actors = vresp->extractULONG(); + seriesinf->actors.clear(); + seriesinf->actors.reserve(num_actors); + for (ULONG acty=0; acty < num_actors; acty++) { + Actor new_act; + new_act.name = vresp->extractStdString(); + new_act.role = vresp->extractStdString(); + new_act.thumb.width = vresp->extractULONG(); + new_act.thumb.height = vresp->extractULONG(); + new_act.thumb.info.setSeriesInfo(seriesinf); + new_act.thumb.info.setElement(1,acty); + seriesinf->actors.push_back(new_act); + } + ULONG num_posters = vresp->extractULONG(); + for (ULONG medias = 0; medias < num_posters; medias++ ) { + TVMedia media; + media.info.setSeriesInfo(seriesinf); + media.info.setElement(2,medias); + media.width = vresp->extractULONG(); + media.height = vresp->extractULONG(); + seriesinf->posters.push_back(media); + } + + ULONG num_banners = vresp->extractULONG(); + for (ULONG medias = 0; medias < num_banners; medias++ ) { + TVMedia media; + media.info.setSeriesInfo(seriesinf); + media.info.setElement(3,medias); + media.width = vresp->extractULONG(); + media.height = vresp->extractULONG(); + seriesinf->banners.push_back(media); + } + ULONG num_fanarts = vresp->extractULONG(); + for (ULONG medias = 0; medias < num_fanarts; medias++ ) { + TVMedia media; + media.info.setSeriesInfo(seriesinf); + media.info.setElement(4,medias); + media.width = vresp->extractULONG(); + media.height = vresp->extractULONG(); + seriesinf->fanart.push_back(media); + } + seriesinf->seasonposter.width = vresp->extractULONG(); + seriesinf->seasonposter.height = vresp->extractULONG(); + seriesinf->seasonposter.info.setSeriesInfo(seriesinf); + seriesinf->seasonposter.info.setElement(5,0); + + delete vresp; + return seriesinf; + +} + +ULONG VDR::loadTVMedia(TVMediaInfo& tvmedia) +{ + + VDR_RequestPacket vrp; + + if (!vrp.init(VDR_LOADTVMEDIA, false, 0)) return -1; + if (!vrp.addULONG(tvmedia.type)) return -1; + if (!vrp.addULONG(tvmedia.primary_id)) return -1; + if (!vrp.addULONG(tvmedia.secondary_id)) return -1; + if (!vrp.addULONG(tvmedia.type_pict)) return -1; + if (!vrp.addULONG(tvmedia.container)) return -1; + if (!vrp.addULONG(tvmedia.container_member)) return -1; + Log::getInstance()->log("VDR", Log::DEBUG, "TVMedia with ID %d %d; %d %d %d %d;%d", + tvmedia.primary_id,tvmedia.secondary_id,tvmedia.type,tvmedia.type_pict, + tvmedia.container,tvmedia.container_member,vrp.getSerial()); + + + VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver(); + vdrpr->receiverChannel = VDR::CHANNEL_TVMEDIA; + vdrpr->streamID = vrp.getSerial(); + vdrpr->streamReceiver = NULL; + edRegister(vdrpr); + + + VDR_ResponsePacket* vresp = RequestResponse(&vrp); + //if (vresp->noResponse()) { delete vresp; return -1; } + delete vresp; + + return vrp.getSerial(); +} diff --git a/vdr.h b/vdr.h index c406115..f322051 100644 --- a/vdr.h +++ b/vdr.h @@ -40,6 +40,7 @@ #include "eventdispatcher.h" #include "i18n.h" #include "log.h" +#include "osdvector.h" class TCP; class Log; @@ -49,6 +50,9 @@ class Channel; class VDR_RequestPacket; class VDR_ResponsePacket; class SerializeBuffer; +class MovieInfo; +class SeriesInfo; + using namespace std; @@ -92,7 +96,7 @@ class StreamReceiver class VDR_PacketReceiver : public EDReceiver // implementation in vdr.cc { public: - virtual bool call(void* userTag); + virtual bool call(void* userTag, bool & deleteme); friend class VDR; protected: @@ -119,6 +123,7 @@ class VDR : public Thread_TYPE, public EventDispatcher, public MediaProvider, pu const static ULONG CHANNEL_STREAM = 2; const static ULONG CHANNEL_KEEPALIVE = 3; const static ULONG CHANNEL_NETLOG = 4; + const static ULONG CHANNEL_TVMEDIA = 5; VDR(); ~VDR(); @@ -158,7 +163,7 @@ class VDR : public Thread_TYPE, public EventDispatcher, public MediaProvider, pu // configSave // setEventTimer - int doLogin(unsigned int* v_server,unsigned int* v_client); + int doLogin(unsigned int* v_server_min, unsigned int* v_server_max, unsigned int* v_client); bool getRecordingsList(RecMan* recman); RecInfo* getRecInfo(char* fileName); int deleteRecording(char* fileName); @@ -199,6 +204,12 @@ class VDR : public Thread_TYPE, public EventDispatcher, public MediaProvider, pu virtual int getMediaInfo(ULONG channel, struct MediaInfo * result); virtual int closeMediaChannel(ULONG channel); + //TV Scraper support + void getScraperEventType(char * fileName, int & movieID, int & seriesID, int & episodeID); + MovieInfo *getScraperMovieInfo(int movieID); + SeriesInfo *getScraperSeriesInfo(int seriesID, int episodeID); + ULONG loadTVMedia(TVMediaInfo& tvmedia); + I18n::lang_code_list getLanguageList(); int getLanguageContent(const string code, I18n::trans_table&); diff --git a/vdrcommand.h b/vdrcommand.h index 33b9352..d0a8af8 100644 --- a/vdrcommand.h +++ b/vdrcommand.h @@ -69,6 +69,10 @@ const static ULONG VDR_OPENMEDIA = 31; const static ULONG VDR_GETMEDIABLOCK = 32; const static ULONG VDR_GETMEDIAINFO = 35; const static ULONG VDR_CLOSECHANNEL = 36; +const static ULONG VDR_GETRECSCRAPEREVENTTYPE = 38; +const static ULONG VDR_GETSCRAPERMOVIEINFO = 39; +const static ULONG VDR_GETSCRAPERSERIESINFO = 40; +const static ULONG VDR_LOADTVMEDIA = 41; const static ULONG VDR_SHUTDOWN = 666; class VDR_Command : public SerializableList { diff --git a/vdrresponsepacket.cc b/vdrresponsepacket.cc index 37b2be5..41ff522 100644 --- a/vdrresponsepacket.cc +++ b/vdrresponsepacket.cc @@ -53,9 +53,9 @@ void VDR_ResponsePacket::setResponse(ULONG trequestID, UCHAR* tuserData, ULONG t userDataLength = tuserDataLength; } -void VDR_ResponsePacket::setStream(ULONG tstreamID, ULONG tflag, UCHAR* tuserData, ULONG tuserDataLength) +void VDR_ResponsePacket::setStream(ULONG tstreamID, ULONG tflag, UCHAR* tuserData, ULONG tuserDataLength, ULONG tchannelID) { - channelID = VDR::CHANNEL_STREAM; + channelID = tchannelID; streamID = tstreamID; flag = tflag; userData = tuserData; @@ -78,6 +78,17 @@ int VDR_ResponsePacket::serverError() else return 0; } +std::string VDR_ResponsePacket::extractStdString() +{ + if (serverError()) return NULL; + + int length = strlen((char*)&userData[packetPos]); + if ((packetPos + length) > userDataLength) return std::string(""); + const char * dest_str=(char*)&userData[packetPos]; + packetPos += length + 1; + return dest_str; +} + char* VDR_ResponsePacket::extractString() { if (serverError()) return NULL; diff --git a/vdrresponsepacket.h b/vdrresponsepacket.h index 0d60be0..25abedf 100644 --- a/vdrresponsepacket.h +++ b/vdrresponsepacket.h @@ -29,6 +29,7 @@ #include #include +#include #include "defines.h" @@ -39,7 +40,7 @@ class VDR_ResponsePacket ~VDR_ResponsePacket(); void setResponse(ULONG requestID, UCHAR* packet, ULONG packetLength); - void setStream(ULONG streamID, ULONG flag, UCHAR* packet, ULONG packetLength); + void setStream(ULONG streamID, ULONG flag, UCHAR* packet, ULONG packetLength, ULONG tchannelID); bool noResponse() { return (userData == NULL); }; int serverError(); @@ -51,6 +52,7 @@ class VDR_ResponsePacket ULONG getFlag() { return flag; } char* extractString(); + std::string extractStdString(); UCHAR extractUCHAR(); ULONG extractULONG(); ULLONG extractULLONG(); diff --git a/videoomx.cc b/videoomx.cc index fd8a133..33ce840 100644 --- a/videoomx.cc +++ b/videoomx.cc @@ -1208,7 +1208,7 @@ int VideoOMX::AllocateCodecsOMX() } - Log::getInstance()->log("Video", Log::DEBUG, "mark2 "); + if (!ChangeComponentState(omx_vid_sched,OMX_StateIdle)) { Log::getInstance()->log("Video", Log::DEBUG, "vid_sched idle ChangeComponentState"); clock_mutex.Unlock(); @@ -1218,7 +1218,7 @@ int VideoOMX::AllocateCodecsOMX() - Log::getInstance()->log("Video", Log::DEBUG, "mark1 "); + if ( !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_clock_port)) { clock_mutex.Unlock(); DeAllocateCodecsOMX(); @@ -1228,7 +1228,7 @@ int VideoOMX::AllocateCodecsOMX() - Log::getInstance()->log("Video", Log::DEBUG, "mark1 special "); + if ( !CommandFinished(omx_clock,OMX_CommandPortEnable,omx_clock_output_port)) { clock_mutex.Unlock(); DeAllocateCodecsOMX(); @@ -1237,9 +1237,6 @@ int VideoOMX::AllocateCodecsOMX() - Log::getInstance()->log("Video", Log::DEBUG, "mark1b "); - - /* error=OMX_SendCommand(omx_vid_dec,OMX_CommandStateSet,OMX_StateIdle,0); if (error!=OMX_ErrorNone){ Log::getInstance()->log("Video", Log::DEBUG, "vid_dec Send Command to OMX State Idle %x", error); diff --git a/vrecording.cc b/vrecording.cc index 6ebb45c..f9e2eca 100644 --- a/vrecording.cc +++ b/vrecording.cc @@ -36,63 +36,111 @@ #include "recording.h" #include "message.h" #include "log.h" +#include "wmovieview.h" +#include "wseriesview.h" +#include "wpictureview.h" VRecording::VRecording(RecMan* trecman, Recording* trec) { rec = trec; recman = trecman; + buttons = true; Log::getInstance()->log("VRecording", Log::DEBUG, "%s", rec->getProgName()); rec->loadRecInfo(); Log::getInstance()->log("VRecording", Log::DEBUG, "%s", rec->getProgName()); - setSize(570, 420); - createBuffer(); + if (Video::getInstance()->getFormat() == Video::PAL) { - setPosition(80, 70); + setSize(640, 500); + createBuffer(); } else { - setPosition(70, 35); + setSize(560, 400); + createBuffer(); } + setPosition(40, 40); setTitleBarOn(1); setBorderOn(1); - setTitleText(rec->getProgName()); + if (rec->recInfo && strlen(rec->recInfo->title)) + setTitleText(rec->recInfo->title); + else + setTitleText(rec->getProgName()); setTitleBarColour(DrawStyle::TITLEBARBACKGROUND); - summary.setPosition(10, 30 + 5); - summary.setSize(area.w - 20, area.h - 30 - 15 - 50); - summary.setParaMode(true); + tabbar.setPosition(10+130+10, 30 + 5); + tabbar.setSize(area.w - 20-10-130, area.h - 30 - 10); + add(&tabbar); + + + - if (rec->recInfo &&strlen(rec->recInfo->summary)) - summary.setText(rec->recInfo->summary); + WTextbox * summary=new WTextbox(); + summary->setParaMode(true); + + if (rec->recInfo && strlen(rec->recInfo->summary)) + summary->setText(rec->recInfo->summary); else - summary.setText(tr("Summary unavailable")); + summary->setText(tr("Summary unavailable")); + + OsdVector *osdv=dynamic_cast(Osd::getInstance()); + + tabbar.addTab(tr("EPG"), summary); + if (rec->movieInfo) { + WMovieView *movieview = new WMovieView(rec->movieInfo); + movieview->setParaMode(true); + tabbar.addTab(tr("TheTVDB Info"), movieview); + if (osdv) { + if (rec->movieInfo->actors.size() > 0 && osdv) + { + WActorGallery *gallery= new WActorGallery(rec->movieInfo->actors); + tabbar.addTab(tr("Cast"),gallery); + } + WArtworkGallery *artgallery= new WArtworkGallery(*rec->movieInfo); + tabbar.addTab(tr("Gallery"),artgallery); + } + } else if (rec->seriesInfo) { + WSeriesView *seriesview = new WSeriesView(rec->seriesInfo); + seriesview->setParaMode(true); + tabbar.addTab(tr("TheTVDB Info"), seriesview); + if (osdv) { + if (rec->seriesInfo->actors.size() > 0 && osdv) + { + WActorGallery *gallery= new WActorGallery(rec->seriesInfo->actors); + tabbar.addTab(tr("Cast"),gallery); + } + WArtworkGallery *artgallery= new WArtworkGallery(*rec->seriesInfo); + tabbar.addTab(tr("Gallery"),artgallery); + } + + } + - add(&summary); int sfh = getFontHeight(); buttonRegion.x = 10; - buttonRegion.y = area.h - 40; - buttonRegion.w = 550; - buttonRegion.h = sfh; + buttonRegion.y = 10+30; + buttonRegion.w = 130; + buttonRegion.h = sfh*2*last; button[PLAY].setText(tr("Play")); button[RESUME].setText(tr("Resume")); button[MOVE].setText(tr("Move")); button[A_DELETE].setText(tr("Delete")); - for (int i=PLAY, hor=10; i(Osd::getInstance()); + if (osdv) { + TVMedia poster; + if (rec->movieInfo) { + poster=rec->movieInfo->poster; + } + if (rec->seriesInfo) { + if (rec->seriesInfo->seasonposter.height) { + poster=rec->seriesInfo->seasonposter; + } + else + if (rec->seriesInfo->posters.size()) { + poster=rec->seriesInfo->posters[0]; + } + } + if (poster.height) { + // float aspect=((float)poster.height)/((float)poster.width)/Osd::getInstance()->getPixelAspect(); + drawTVMedia(poster.info,buttonRegion.x, + buttonRegion.y+buttonRegion.h, + buttonRegion.w,/*buttonRegion.w*aspect*/0.f); + } + } + } int VRecording::handleCommand(int command) { - switch(command) - { - case Remote::LEFT: - case Remote::DF_LEFT: - case Remote::DF_UP: - case Remote::UP: - { - moveCursor(LEFT); - return 2; - } - case Remote::RIGHT: - case Remote::DF_RIGHT: - case Remote::DF_DOWN: - case Remote::DOWN: - { - moveCursor(RIGHT); - return 2; - } - case Remote::OK: - { + if (command==Remote::BACK) { + return 4; + } + if (buttons) { + switch(command) + { + case Remote::DF_UP: + case Remote::UP: + { + moveCursor(LEFT); + return 2; + } - if (selected == PLAY) - { - Message* m = new Message(); // Must be done after this view deleted - m->from = this; - m->to = vRecList; - m->message = Message::PLAY_SELECTED_RECORDING; - Command::getInstance()->postMessageNoLock(m); - return 4; - } + case Remote::DF_DOWN: + case Remote::DOWN: + { + moveCursor(RIGHT); + return 2; + } + case Remote::LEFT: + case Remote::DF_LEFT: + case Remote::RIGHT: + case Remote::DF_RIGHT: + { + buttons = false; + button[selected].setActive(0); + tabbar.activateFocus(true); + button[selected].draw(); + tabbar.draw(); + BoxStack::getInstance()->update(this); + return 2; + } + case Remote::OK: + { - if (selected == RESUME) - { - Message* m = new Message(); // Must be done after this view deleted - m->from = this; - m->to = vRecList; - m->message = Message::RESUME_SELECTED_RECORDING; - Command::getInstance()->postMessageNoLock(m); - return 4; - } + if (selected == PLAY) + { + Message* m = new Message(); // Must be done after this view deleted + m->from = this; + m->to = vRecList; + m->message = Message::PLAY_SELECTED_RECORDING; + Command::getInstance()->postMessageNoLock(m); + return 4; + } - if (selected == MOVE) - { - VRecMove* vrm = new VRecMove(recman); - vrm->setParent(this); - vrm->draw(); - BoxStack::getInstance()->add(vrm); - BoxStack::getInstance()->update(vrm); - return 2; - } + if (selected == RESUME) + { + Message* m = new Message(); // Must be done after this view deleted + m->from = this; + m->to = vRecList; + m->message = Message::RESUME_SELECTED_RECORDING; + Command::getInstance()->postMessageNoLock(m); + return 4; + } - if (selected == A_DELETE) - { - VQuestion* v = new VQuestion(this); - v->setSize(260, 180); - v->createBuffer(); - v->setTitleBarColour(DrawStyle::DANGER); - v->setTitleBarOn(1); - v->setBorderOn(1); - v->setTitleText(tr("Delete recording")); - v->setMainText(tr("Are you sure you want to delete this recording?")); - v->setDefault(VQuestion::NO); - if (Video::getInstance()->getFormat() == Video::PAL) - { - v->setPosition(230, 160); - } - else - { - v->setPosition(220, 140); - } - - v->draw(); - BoxStack::getInstance()->add(v); - BoxStack::getInstance()->update(v); - return 2; - } - } + if (selected == MOVE) + { + VRecMove* vrm = new VRecMove(recman); + vrm->setParent(this); + vrm->draw(); + BoxStack::getInstance()->add(vrm); + BoxStack::getInstance()->update(vrm); + return 2; + } - case Remote::BACK: - { - return 4; - } - } - // stop command getting to any more views - return 1; + if (selected == A_DELETE) + { + VQuestion* v = new VQuestion(this); + v->setSize(260, 180); + v->createBuffer(); + v->setTitleBarColour(DrawStyle::DANGER); + v->setTitleBarOn(1); + v->setBorderOn(1); + v->setTitleText(tr("Delete recording")); + v->setMainText(tr("Are you sure you want to delete this recording?")); + v->setDefault(VQuestion::NO); + if (Video::getInstance()->getFormat() == Video::PAL) + { + v->setPosition(230, 160); + } + else + { + v->setPosition(220, 140); + } + + v->draw(); + BoxStack::getInstance()->add(v); + BoxStack::getInstance()->update(v); + return 2; + } + } + } + } else { + // Pass to tabbar + int retval = tabbar.handleCommand(command); + if (retval == 1) + { + BoxStack::getInstance()->update(this); + return 2; + } + else if (retval == 2) + { + // command was taken and actively ignored + if (command==Remote::LEFT || command==Remote::DF_LEFT + || command==Remote::RIGHT || command==Remote::DF_RIGHT) + { + buttons=true; + button[selected].setActive(1); + tabbar.activateFocus(false); + button[selected].draw(); + tabbar.draw(); + BoxStack::getInstance()->update(this); + } + return 2; + } + } + + + // stop command getting to any more views + return 1; } void VRecording::moveCursor(Direction direction) diff --git a/vrecording.h b/vrecording.h index 10394c2..ca5eac1 100644 --- a/vrecording.h +++ b/vrecording.h @@ -27,6 +27,7 @@ #include "tbboxx.h" #include "wbutton.h" #include "wtextbox.h" +#include "wtabbar.h" class VRecordingList; class RecMan; @@ -49,8 +50,7 @@ class VRecording : public TBBoxx RecMan* recman; VRecordingList* vRecList; Recording* rec; - - WTextbox summary; + WTabBar tabbar; enum Action { PLAY=0, RESUME, MOVE, A_DELETE, last }; WButton button[last]; @@ -61,6 +61,7 @@ class VRecording : public TBBoxx int selected; Region buttonRegion; + bool buttons; enum Direction { LEFT, RIGHT }; void moveCursor(Direction direction); diff --git a/wmovieview.cc b/wmovieview.cc new file mode 100644 index 0000000..9e5ed6e --- /dev/null +++ b/wmovieview.cc @@ -0,0 +1,84 @@ +/* + Copyright 2014 Marten Richter + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "wmovieview.h" +#include "i18n.h" +#include + + +WMovieView::WMovieView(MovieInfo* movie): +WTextbox(NULL) +{ + // portions from nopacity plugin by Louis Braun + if (movie) + { + std::stringstream info; + info << tr("TheMovieDB Information") << ":\n\n"; + if (!movie->originalTitle.empty()){ + info << tr("Original Title") << ": " << movie->originalTitle << "\n\n"; + } + if (!movie->tagline.empty()){ + info << tr("Tagline") << ": " << movie->tagline << "\n\n"; + } + if (!movie->overview.empty()){ + info << tr("Overview") << ": " << movie->overview << "\n\n"; + } + const char* strAdult = (movie->adult)?(tr("yes")):(tr("no")); + info << tr("Adult") << ": " << strAdult << "\n\n"; + if (!movie->collectionName.empty()){ + info << tr("Collection") << ": " << movie->collectionName << "\n\n"; + } + if (movie->budget > 0 ){ + info << tr("Budget") << ": " << movie->budget << "$\n\n"; + } + if (movie->revenue > 0 ){ + info << tr("Revenue") << ": " << movie->revenue << "$\n\n"; + } + if (!movie->genres.empty() ){ + info << tr("Genre") << ": " << movie->genres << "\n\n"; + } + if (!movie->homepage.empty()){ + info << tr("Homepage") << ": " << movie->homepage << "\n\n"; + } + if (!movie->releaseDate.empty()){ + info << tr("Release Date") << ": " << movie->releaseDate << "\n\n"; + } + if (movie->runtime > 0 ){ + info << tr("Runtime") << ": " << movie->runtime << " " << tr("minutes") << "\n\n"; + } + if (movie->popularity > 0 ){ + info << tr("TheMovieDB Popularity") << ": " << movie->popularity << "\n\n"; + } + if (movie->voteAverage > 0 ){ + info << tr("TheMovieDB Vote Average") << ": " << movie->voteAverage << "\n\n"; + } + setText(info.str().c_str()); + } else { + setText("This is a bug!"); + } + +} + +void WMovieView::draw() +{ + WTextbox::draw(); + + +} diff --git a/wmovieview.h b/wmovieview.h new file mode 100644 index 0000000..ef04c75 --- /dev/null +++ b/wmovieview.h @@ -0,0 +1,44 @@ +/* + Copyright 2014 Marten Richter + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef WMOVIEVIEW_H +#define WMOVIEVIEW_H + +#include +#include + +#include "defines.h" +#include "wtextbox.h" +#include "movieinfo.h" + +class Colour; + +class WMovieView : public WTextbox +{ + public: + WMovieView(MovieInfo* movinfo); + void draw(); + + + private: + +}; + +#endif diff --git a/woptionpane.cc b/woptionpane.cc index 690ab79..fb5b456 100644 --- a/woptionpane.cc +++ b/woptionpane.cc @@ -68,7 +68,7 @@ void WOptionPane::addOptionLine(Option* option) WTextbox* tb = new WTextbox(); tb->setPosition(4, 4 + (numOptions * 30)); - tb->setSize(300, fontHeight); + tb->setSize(300, fontHeight + 6); tb->setText(tr(option->displayText)); tb->setTextPos(0, 0); add(tb); diff --git a/wpictureview.cc b/wpictureview.cc new file mode 100644 index 0000000..5418a2d --- /dev/null +++ b/wpictureview.cc @@ -0,0 +1,247 @@ +/* + Copyright 2005 Brian Walton (WTextBox) + Copyright 2014 Marten Richter (WPictureView) + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "wpictureview.h" + +#include "colour.h" +#include "remote.h" +#include "osd.h" +#include "movieinfo.h" +#include "seriesinfo.h" +#include + +WPictureView::WPictureView(): +foreColour(DrawStyle::LIGHTTEXT) +{ + cur_scroll_line=0; + rem_scroll_line=0; + const_height=0; +} + +WPictureView::~WPictureView() +{ +} + + + +void WPictureView::setForegroundColour(const DrawStyle& fcolour) +{ + foreColour = fcolour; +} + +void WPictureView::draw() +{ + Boxx::draw(); + int fontHeight = getFontHeight(); + float ypos = cur_scroll_line * (fontHeight*8.f); + ypos = -ypos; + float height = 0; + + drawClippingRectangle(1,1,area.w-1,area.h-1); + + list::iterator itty=pictures.begin(); + while (itty!=pictures.end()) + { + // We now calculate the pictures in one row + list cur_pict; + float cur_width=0; + float max_height=const_height; + + + while (itty != pictures.end()) + { + if ((((*itty).w + cur_width+ 10.f) > area.w || const_height) && cur_pict.size() > 0) break; + cur_width += 10 + (*itty).w; + if (!const_height) max_height = max(max_height,(*itty).h); + cur_pict.push_back(&(*itty)); + itty++; + } + // ok now we have a list of pictures, let's draw them + list::iterator citty=cur_pict.begin(); + float xpos= (area.w - cur_width)*0.5f; + if (xpos < 0) xpos=0; + while (citty!=cur_pict.end()) + { + if (!const_height) { + drawTVMedia((*citty)->media, + xpos, ypos + max_height /*- (*citty)->h*/, + (*citty)->w, + /*(*citty)->h*/0.f,BottomLeft); + } else { + if (!(*citty)->banner) { + drawTVMedia((*citty)->media, + xpos+area.w*0.5f, ypos, + 0.f, + const_height,TopMiddle); + } else { + drawTVMedia((*citty)->media, + xpos+area.w*0.5f, ypos, + area.w-2.f, + 0.f,TopMiddle); + } + } + xpos += (*citty)->w + 10.f; + citty++; + } + ypos += max_height; + height += max_height; + bool caption1=false; + bool caption2=false; + + citty=cur_pict.begin(); + xpos= (area.w - cur_width)*0.5f; + if (xpos < 0) xpos=0; + while (citty!=cur_pict.end()) + { + if (!(*citty)->caption.empty()) + { + drawTextCentre((*citty)->caption.c_str(), xpos + (*citty)->w*0.5f, ypos, foreColour); + caption1 = true; + } + if (!(*citty)->caption2.empty()) + { + drawTextCentre((*citty)->caption2.c_str(), xpos + (*citty)->w*0.5f, ypos + fontHeight*1.f, foreColour); + caption2 = true; + } + xpos += (*citty)->w + 10.f; + citty++; + } + if (caption1) { + ypos +=fontHeight*1.f; + height += fontHeight*1.f; + } + if (caption2) { + ypos +=fontHeight*1.f; + height += fontHeight*1.f; + } + ypos +=fontHeight*1.f; + height += fontHeight*1.f; + + } + rem_scroll_line = ceil((height - area.h -cur_scroll_line * fontHeight*8.f)/fontHeight/8.f); + // Log::getInstance()->log("WActorGallery", Log::DEBUG, "TVMedia rml %d",rem_scroll_line); + drawClippingRectangle(0,0,0,0); + +} + +void WPictureView::addPicture(TVMediaInfo& pict, float pwidth, float pheight , bool banner, std::string caption, std::string caption2) +{ + pictures.push_back(Picture(pict,pwidth,pheight, banner, caption,caption2)); +} + +int WPictureView::handleCommand(int command) +{ + switch(command) + { + case Remote::DF_UP: + case Remote::UP: + { + if (cur_scroll_line > 0) + { + cur_scroll_line--; + rem_scroll_line++; + return 1; + } + else + { + return 4; // Signal return control to parent + } + } + case Remote::DF_DOWN: + case Remote::DOWN: + { + if (rem_scroll_line > 0) + { + cur_scroll_line++; + rem_scroll_line--; + return 1; + } else { + return 4; + } + } + case Remote::LEFT: + case Remote::RIGHT: + case Remote::DF_LEFT: + case Remote::DF_RIGHT: + { + return 5; + } + + } + + return 0; +} + +WActorGallery::WActorGallery(Actors& actors) +{ + Actors::iterator itty=actors.begin(); + float pixelaspect=Osd::getInstance()->getPixelAspect(); + while (itty!= actors.end()) + { + float aspect=((float)(*itty).thumb.height)/((float)(*itty).thumb.width)/pixelaspect; + float width= 100; + float height= aspect*width; + + //Log::getInstance()->log("WActorGallery", Log::DEBUG, "TVMedia %d %d %g", (*itty).thumb.width,(*itty).thumb.height,aspect); + addPicture((*itty).thumb.info, width, height, false,(*itty).name,"\""+(*itty).role+"\""); + itty++; + } +} + +WArtworkGallery::WArtworkGallery(MovieInfo& movie) +{ + float pixelaspect=Osd::getInstance()->getPixelAspect(); + addTVMedia(movie.fanart); + addTVMedia(movie.collectionFanart); + addTVMedia(movie.collectionPoster); + addTVMedia(movie.poster); + const_height=400; +} + +WArtworkGallery::WArtworkGallery(SeriesInfo& series) +{ + addTVMedia(series.seasonposter); + addTVMedia(series.episode.image); + + addTVMedias(series.banners, true); + addTVMedias(series.fanart); + addTVMedias(series.posters); + const_height=400; +} + +void WArtworkGallery::addTVMedias(TVMedias& medias, bool banner) +{ + if (medias.size()) { + TVMedias::iterator titty=medias.begin(); + while (titty!=medias.end()) + { + addTVMedia(*titty, banner); + titty++; + } + + } +} + +void WArtworkGallery::addTVMedia(TVMedia& media, bool banner) +{ + if (media.width) + addPicture(media.info, media.width, media.height, banner); +} diff --git a/wpictureview.h b/wpictureview.h new file mode 100644 index 0000000..272299a --- /dev/null +++ b/wpictureview.h @@ -0,0 +1,87 @@ +/* + Copyright 2005 Brian Walton (WTextBox) + Copyright 2014 Marten Richter (WPictureView) + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef WPICTUREVIEW_H +#define WPICTUREVIEW_H + +#include +#include +#include + +#include "defines.h" +#include "boxx.h" + +class Colour; + +class WPictureView : public Boxx +{ + public: + WPictureView(); + virtual ~WPictureView(); + void addPicture(TVMediaInfo& pict, float width, float height,bool banner=false, std::string caption ="", std::string caption2 =""); + void draw(); + void setForegroundColour(const DrawStyle& fcolour); + + + // if added as a pane + int handleCommand(int command); + + protected: + class Picture { + public: + Picture(TVMediaInfo tmedia,float width, float height, bool tbanner, std::string tcaption, std::string tcaption2){ + media=tmedia; caption=tcaption;caption2=tcaption2;w=width; h=height; banner=tbanner; + } + + TVMediaInfo media; + std::string caption; + std::string caption2; + float w; + float h; + bool banner; + }; + list pictures; + + DrawStyle foreColour; + unsigned int cur_scroll_line; + unsigned int rem_scroll_line; + unsigned int const_height; // if set only one per line +}; + +class WActorGallery : public WPictureView +{ +public: + WActorGallery(Actors& actors); + +}; + +class WArtworkGallery : public WPictureView +{ +public: + WArtworkGallery(MovieInfo& movie); + WArtworkGallery(SeriesInfo& series); +protected: + void addTVMedias(TVMedias& medias, bool banner=false); + void addTVMedia(TVMedia& media, bool banner=false); + +}; + +#endif diff --git a/wseriesview.cc b/wseriesview.cc new file mode 100644 index 0000000..4a28d3e --- /dev/null +++ b/wseriesview.cc @@ -0,0 +1,73 @@ +/* + Copyright 2014 Marten Richter + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "wseriesview.h" +#include "i18n.h" +#include + + +WSeriesView::WSeriesView(SeriesInfo* series): +WTextbox(NULL) +{ + // portions from nopacity plugin by Louis Braun + if (series) + { + std::stringstream info; + info << tr("TheTVDB Information") << ":\n\n"; + + if (!series->episode.name.empty()) { + info << tr("Episode") << ": " << series->episode.name << " (" << tr("Season") << " " << series->episode.season << ", " << tr("Episode") << " " << series->episode.number << ")\n\n"; + } + if (!series->episode.overview.empty()) { + info << tr("Episode Overview") << ": " << series->episode.overview << "\n\n"; + } + if (!series->episode.firstAired.empty()) { + info << tr("First aired") << ": " << series->episode.firstAired << "\n\n"; + } + if (!series->episode.guestStars.empty()) { + info << tr("Guest Stars") << ": " << series->episode.guestStars << "\n\n"; + } + if (series->episode.rating > 0) { + info << tr("TheMovieDB Rating") << ": " << series->episode.rating << "\n\n"; + } + if (!series->overview.empty()) { + info << tr("Series Overview") << ": " << series->overview << "\n\n"; + } + if (!series->firstAired.empty()) { + info << tr("First aired") << ": " << series->firstAired << "\n\n"; + } + if (!series->genre.empty()) { + info << tr("Genre") << ": " << series->genre << "\n\n"; + } + if (!series->network.empty()) { + info << tr("Network") << ": " << series->network << "\n\n"; + } + if (series->rating > 0) { + info << tr("TheMovieDB Rating") << ": " << series->rating << "\n\n"; + } + if (!series->status.empty()) { + info << tr("Status") << ": " << series->status << "\n\n"; + } + setText(info.str().c_str()); + } else { + setText("This is a bug!"); + } + +} diff --git a/wseriesview.h b/wseriesview.h new file mode 100644 index 0000000..0b9f715 --- /dev/null +++ b/wseriesview.h @@ -0,0 +1,43 @@ +/* + Copyright 2014 Marten Richter + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef WSERIESVIEW_H +#define WSERIESIEW_H + +#include +#include + +#include "defines.h" +#include "wtextbox.h" +#include "seriesinfo.h" + +class Colour; + +class WSeriesView : public WTextbox +{ + public: + WSeriesView(SeriesInfo* seriesinfo); + + + private: + +}; + +#endif diff --git a/wtabbar.cc b/wtabbar.cc index a33bae7..044a90a 100644 --- a/wtabbar.cc +++ b/wtabbar.cc @@ -108,6 +108,7 @@ int WTabBar::handleCommand(int command) // 0 - not handled // 1 - handled - stop command here // 4 - handled - pane is returning control to here + // 5 - activate button bar and let button process the call, this for simple up and down scroll views // FIXME standardise these int paneRetCode = tabs[visiblePane].pane->handleCommand(command); @@ -128,6 +129,14 @@ int WTabBar::handleCommand(int command) if (visiblePane != tabs.size() - 1) symbolRight.nextColour = DrawStyle::SELECTHIGHLIGHT; draw(); return 1; + } else if (paneRetCode == 5) + { + buttonBarActive = true; + tabs[visiblePane].button->setActive(true); + if (visiblePane != 0) symbolLeft.nextColour = DrawStyle::SELECTHIGHLIGHT; + if (visiblePane != tabs.size() - 1) symbolRight.nextColour = DrawStyle::SELECTHIGHLIGHT; + draw(); + // no return! } } @@ -149,6 +158,8 @@ int WTabBar::handleCommand(int command) draw(); return 1; } + case Remote::UP: + case Remote::DF_UP: case Remote::DOWN: case Remote::DF_DOWN: { @@ -305,3 +316,17 @@ bool WTabBar::mouseLBDOWN(int x, int y) { return false; } +void WTabBar::activateFocus(bool active) +{ + if (active) + { + tabs[visiblePane].button->setActive(true); + buttonBarActive = true; + + } else { + tabs[visiblePane].button->setActive(false); + buttonBarActive = false; + + } +} + diff --git a/wtabbar.h b/wtabbar.h index db70ccd..bfd8d70 100644 --- a/wtabbar.h +++ b/wtabbar.h @@ -45,6 +45,7 @@ class WTabBar : public Boxx int handleCommand(int command); bool mouseMove(int x, int y) ; bool mouseLBDOWN(int x, int y); + void activateFocus(bool active); private: bool left(); diff --git a/wtextbox.cc b/wtextbox.cc index 048bec0..7cb6045 100644 --- a/wtextbox.cc +++ b/wtextbox.cc @@ -21,6 +21,7 @@ #include "wtextbox.h" #include "colour.h" +#include "remote.h" WTextbox::WTextbox(const char* ttext): foreColour(DrawStyle::LIGHTTEXT) @@ -37,6 +38,9 @@ foreColour(DrawStyle::LIGHTTEXT) paraMode = true; if (ttext) setText(ttext); + + cur_scroll_line=0; + rem_scroll_line=0; } WTextbox::~WTextbox() @@ -67,7 +71,7 @@ void WTextbox::draw() Boxx::draw(); if (text) { - if (paraMode) drawPara(text, textX, textY, foreColour); + if (paraMode) rem_scroll_line=drawPara(text, textX, textY, foreColour,cur_scroll_line); else drawText(text, textX, textY, foreColour); } } @@ -77,3 +81,46 @@ void WTextbox::setTextPos(int x, int y) textX = x; textY = y; } + +int WTextbox::handleCommand(int command) +{ + switch(command) + { + case Remote::DF_UP: + case Remote::UP: + { + if (cur_scroll_line > 0) + { + cur_scroll_line--; + rem_scroll_line++; + return 1; + } + else + { + return 4; // Signal return control to parent + } + } + case Remote::DF_DOWN: + case Remote::DOWN: + { + if (rem_scroll_line > 0) + { + cur_scroll_line++; + rem_scroll_line--; + return 1; + } else { + return 4; + } + } + case Remote::LEFT: + case Remote::RIGHT: + case Remote::DF_LEFT: + case Remote::DF_RIGHT: + { + return 5; + } + + } + + return 0; +} diff --git a/wtextbox.h b/wtextbox.h index cc80935..5003157 100644 --- a/wtextbox.h +++ b/wtextbox.h @@ -40,6 +40,9 @@ class WTextbox : public Boxx void setTextPos(int x, int y); // optional void setParaMode(bool mode); + // if added as a pane + int handleCommand(int command); + private: char* text; @@ -47,6 +50,8 @@ class WTextbox : public Boxx int textX; int textY; bool paraMode; + unsigned int cur_scroll_line; + unsigned int rem_scroll_line; }; #endif -- 2.39.2