]> git.vomp.tv Git - vompclient.git/commitdiff
Replace TVMedia & OsdVector refcounting with new Image system
authorChris Tallon <chris@vomp.tv>
Wed, 29 Dec 2021 18:33:32 +0000 (18:33 +0000)
committerChris Tallon <chris@vomp.tv>
Wed, 29 Dec 2021 18:33:32 +0000 (18:33 +0000)
See image.h for details
Still need regression testing

57 files changed:
boxstack.cc
boxstack.h
boxx.cc
boxx.h
control.cc
control.h
eglpicturecreator.h
image.cc [new file with mode: 0644]
image.h [new file with mode: 0644]
imageloader.cc [new file with mode: 0644]
imageloader.h [new file with mode: 0644]
imageomx.cc
imageomx.h
imageomx2.cc
imageomx2.h
message.h
movieinfo.cc
movieinfo.h
objects.mk
osd.cc
osd.h
osdopenvg.cc
osdopenvg.h
osdvector.cc
osdvector.h
osdvectortypes.h [new file with mode: 0644]
seriesinfo.h
surface.h
surfacevector.cc
surfacevector.h
tbboxx.cc
tbboxx.h
tvmedia.cc [deleted file]
tvmedia.h [deleted file]
vchannellist.cc
vchannellist.h
vdr.cc
vdr.h
vdrresponsepacket.cc
vepg.cc
vepglistadvanced.cc
vepgsummary.cc
vopts.cc
vrecording.cc
vrecordinglistadvanced.cc
vtimeredit.cc
vtimerlist.cc
vvideolivetv.cc
vvideorec.cc
vwelcome.cc
wpictureview.cc
wpictureview.h
wremoteconfig.h
wselectlist.cc
wselectlist.h
wtvmedia.cc
wtvmedia.h

index 95774758fcf04c41803b1937615f478bea5e1af9..afd76ef15cfda3257e7e5aabb22e3a2dacbcd70b 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
     Copyright 2004-2020 Chris Tallon
 
     along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
 */
 
-#include "boxstack.h"
-
+#include "log.h"
 #include "messagequeue.h"
 #include "input.h"
-#include "log.h"
+#include "osd.h"
+
+#include "boxstack.h"
 
 static const char* TAG = "BoxStack";
 
index e930c1d534cd28adf3206e7695b7bb9470df20c1..fcc36f10318d48bff54d164c2f7defa0ae6e2e47 100644 (file)
@@ -34,6 +34,8 @@
 typedef std::list<Region> RegionList;
 typedef std::stack<std::pair<Boxx*,VideoDisplay> > VideoDisplayStack;
 
+class Osd;
+
 class BoxStack : public MessageReceiver
 {
   public:
diff --git a/boxx.cc b/boxx.cc
index 37362493ed651697b4ea42dc272ceb2dc047506c..d5e63428cd0b729ccef480b021613c27e4e3c616 100644 (file)
--- a/boxx.cc
+++ b/boxx.cc
@@ -532,13 +532,13 @@ void Boxx::drawMonoBitmap(UCHAR* base, int dx, int dy, unsigned int height,unsig
   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)
+void Boxx::drawImage(Image& image, float x, float y, float width, float height, Corner corner)
 {
-  if (parent) parent->drawTVMedia(tvmedia, static_cast<float>(area.x) + x, static_cast<float>(area.y) + y, width, height, corner);
+  if (parent) parent->drawImage(image, static_cast<float>(area.x) + x, static_cast<float>(area.y) + y, width, height, corner);
   else if (surface)
   {
     SurfaceVector* surfacevector = dynamic_cast<SurfaceVector*>(surface);
-    if (surfacevector) surfacevector->drawTVMedia(tvmedia, x, y, width, height, corner);
+    if (surfacevector) surfacevector->drawImage(image, x, y, width, height, corner);
     else surface->fillblt(static_cast<int>(x), static_cast<int>(y), static_cast<int>(width), static_cast<int>(height), DrawStyle::RED); // Signal that something went wrong
   }
 }
diff --git a/boxx.h b/boxx.h
index 0c1b216019ab24e280fe136814391c285fddb107..6f8f52197220a3bf078c9739c96c9eaf45fe92ae 100644 (file)
--- a/boxx.h
+++ b/boxx.h
 
 #include <vector>
 
-#include "osdvector.h"
 #include "bitmap.h"
 #include "colour.h"
 #include "region.h"
 #include "video.h"
-#include "tvmedia.h"
+#include "image.h"
+#include "teletextdecodervbiebu.h"
+
+#include "osdvectortypes.h" // FIXME Only included for enum Corner. Fix this one day.
 
 class Bitmap;
 class Message;
@@ -111,7 +113,7 @@ 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 drawImage(Image& image, float x, float y, float width, float height, Corner corner=TopLeft);
     void drawClippingRectangle(float x, float y, float w, float h);
     int getFontHeight();
 
index 47f6e40c1bb9dcbacdb8d1446132dcd199061397..d413498a6096b508afccf9d579aa76a7ac690fd1 100644 (file)
@@ -62,6 +62,7 @@
 #include "config.h"
 #include "vvideolivetv.h"
 #include "channel.h"
+#include "imageloader.h"
 
 
 #ifdef VOMP_PLATFORM_RASPBERRY
@@ -115,6 +116,9 @@ bool Control::init(bool tcrashed)
 
   SkinFactory::InitSkin(0);
 
+  // FIXME All constructors first which do very little & don't rely on presence of other objects.
+  // Then all inits. Inits retrieve pointers to other objects.
+
   try
   {
     led = new Led_TYPE();                     if (!led) throw 10;
@@ -129,21 +133,24 @@ bool Control::init(bool tcrashed)
     audio = new Audio_TYPE();                 if (!audio) throw 40;
     if (!audio->init(Audio::MPEG2_PES))       throw 41;
 
-    osd = new Osd_TYPE();                     if (!osd) throw 50;
-    if (!osd->init())                         throw 51;
+    imageLoader = new ImageLoader();          if (!imageLoader) throw 50;
+    if (!imageLoader->init())                 throw 51;
+
+    osd = new Osd_TYPE();                     if (!osd) throw 60;
+    if (!osd->init())                         throw 61;
 
-    vdr = new VDR();                          if (!vdr) throw 60;
-    if (!vdr->init())                         throw 61;
+    vdr = new VDR();                          if (!vdr) throw 70;
+    if (!vdr->init())                         throw 71;
 
-    boxstack = new BoxStack();                if (!boxstack) throw 70;
-    if (!boxstack->init())                    throw 71;
+    boxstack = new BoxStack();                if (!boxstack) throw 80;
+    if (!boxstack->init())                    throw 81;
 
-    sleepTimer = new SleepTimer();            if (!sleepTimer) throw 80;
+    sleepTimer = new SleepTimer();            if (!sleepTimer) throw 90;
 
-    wol = new Wol();                          if (!wol) throw 90;
+    wol = new Wol();                          if (!wol) throw 100;
 
-    inputMan = new InputMan();                if (!inputMan) throw 100;
-    if (!inputMan->init())                    throw 101;
+    inputMan = new InputMan();                if (!inputMan) throw 110;
+    if (!inputMan->init())                    throw 111;
 
   }
   catch (int e)
@@ -156,52 +163,61 @@ bool Control::init(bool tcrashed)
     else if (e == 31) logger->crit(TAG, "Video module failed to initialise");
     else if (e == 40) logger->crit(TAG, "Audio module failed to create");
     else if (e == 41) logger->crit(TAG, "Audio module failed to initialise");
-    else if (e == 50) logger->crit(TAG, "OSD module failed to create");
-    else if (e == 51) logger->crit(TAG, "OSD module failed to initialise");
-    else if (e == 60) logger->crit(TAG, "VDR module failed to create");
-    else if (e == 61) logger->crit(TAG, "VDR module failed to initialise");
-    else if (e == 70) logger->crit(TAG, "BoxStack module failed to create");
-    else if (e == 71) logger->crit(TAG, "BoxStack module failed to initialise");
-    else if (e == 80) logger->crit(TAG, "SleepTimer module failed to create");
-    else if (e == 90) logger->crit(TAG, "WOL module failed to create");
-    else if (e == 100) logger->crit(TAG, "InputMan module failed to create");
-    else if (e == 101) logger->crit(TAG, "InputMan module failed to initialise");
+    else if (e == 50) logger->crit(TAG, "ImageLoader module failed to create");
+    else if (e == 51) logger->crit(TAG, "ImageLoader module failed to initialise");
+    else if (e == 60) logger->crit(TAG, "OSD module failed to create");
+    else if (e == 61) logger->crit(TAG, "OSD module failed to initialise");
+    else if (e == 70) logger->crit(TAG, "VDR module failed to create");
+    else if (e == 71) logger->crit(TAG, "VDR module failed to initialise");
+    else if (e == 80) logger->crit(TAG, "BoxStack module failed to create");
+    else if (e == 81) logger->crit(TAG, "BoxStack module failed to initialise");
+    else if (e == 90) logger->crit(TAG, "SleepTimer module failed to create");
+    else if (e == 100) logger->crit(TAG, "WOL module failed to create");
+    else if (e == 110) logger->crit(TAG, "InputMan module failed to create");
+    else if (e == 111) logger->crit(TAG, "InputMan module failed to initialise");
 
     switch(e)
     {
-      case 101:
+      case 111:
         delete inputMan;
         inputMan = NULL;
         FALLTHROUGH
-      case 100:
+      case 110:
         delete wol;
         wol = NULL;
         FALLTHROUGH
-      case 90:
+      case 100:
         delete sleepTimer;
         sleepTimer = NULL;
         FALLTHROUGH
-      case 80:
+      case 90:
         boxstack->shutdown();
         FALLTHROUGH
-      case 71:
+      case 81:
         delete boxstack;
         boxstack = NULL;
         FALLTHROUGH
-      case 70:
+      case 80:
         vdr->shutdown();
         FALLTHROUGH
-      case 61:
+      case 71:
         delete vdr;
         vdr = NULL;
         FALLTHROUGH
-      case 60:
+      case 70:
         osd->shutdown();
         FALLTHROUGH
-      case 51:
+      case 61:
         delete osd;
         osd = NULL;
         FALLTHROUGH
+      case 60:
+        imageLoader->shutdown();
+        FALLTHROUGH
+      case 51:
+        delete imageLoader;
+        imageLoader = NULL;
+        FALLTHROUGH
       case 50:
         audio->shutdown();
         FALLTHROUGH
@@ -292,6 +308,14 @@ void Control::shutdown()
     logger->info(TAG, "OSD module shut down");
   }
 
+  if (imageLoader)
+  {
+    imageLoader->shutdown();
+    delete imageLoader;
+    imageLoader = NULL;
+    logger->info(TAG, "ImageLoader shut down");
+  }
+
   if (audio)
   {
     audio->shutdown();
@@ -408,8 +432,8 @@ void Control::run()
 
   inputMan->start();
 
-//  logger->debug(TAG, "Setting log trace only mode");
-//  logger->setTraceOnlyMode(true);
+  //logger->debug(TAG, "Setting log trace only mode");
+  //logger->setTraceOnlyMode(false);
 
   messageLoopRun = true;
   messageLoop();
index 68ca368fa43410328bc6670c92687e5fa87a00ad..fc0ab74b89a4283ce48d474b3f13c59f2393b3dd 100644 (file)
--- a/control.h
+++ b/control.h
@@ -30,6 +30,7 @@ class VDR;
 class VConnect;
 class Message;
 class InputMan;
+class ImageLoader;
 class Boxx;
 class BoxStack;
 class LogNT;
@@ -79,6 +80,7 @@ class Control : public MessageQueue
     Video* video{};
     Audio* audio{};
     VDR* vdr{};
+    ImageLoader* imageLoader{};
     BoxStack* boxstack{};
     SleepTimer* sleepTimer{};
     Wol* wol{};
index ffe0556bc6ec4d475d10335e73122dfb1a46db19..9e38f2bd3c3bccdff9b36b091df54daa4b3d5bf1 100644 (file)
 #ifndef EGLPICTURECREATOR_H
 #define EGLPICTURECREATOR_H
 
+#include "osdvectortypes.h"
+
 class EGLPictureCreator
 {
   public:
-    virtual bool getEGLPicture(struct OsdVector::PictureInfo& pictureInfo, EGLDisplay* display)=0;
+    virtual bool getEGLPicture(struct PictureInfo& pictureInfo, EGLDisplay* display)=0;
 };
 
 #endif
diff --git a/image.cc b/image.cc
new file mode 100644 (file)
index 0000000..5e04d2b
--- /dev/null
+++ b/image.cc
@@ -0,0 +1,37 @@
+/*
+    Copyright 2014 Marten Richter, 2021 Chris Tallon
+
+    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, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "seriesinfo.h"
+#include "movieinfo.h"
+
+#include "image.h"
+
+void CImageGeneric::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
+}
+
+void CImageGeneric::setMovieInfo(const MovieInfo* mi)
+{
+  type = 1; // movie or series
+  primary_id = mi->id; //movie or series_id
+  secondary_id = 0; //0 or episode id
+}
diff --git a/image.h b/image.h
new file mode 100644 (file)
index 0000000..f3afe5a
--- /dev/null
+++ b/image.h
@@ -0,0 +1,281 @@
+/*
+    Copyright 2021 Chris Tallon
+    Portions 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef IMAGE_H
+#define IMAGE_H
+
+/*
+ * The new Image system, 2021.
+ *
+ * There are several image types that the client deals with:
+ * * Static images - these are built into the binary and are mostly small PNG icons
+ * * Channel logos
+ * * Recording thumbnails (and ones for folders)
+ * * Event thumbnails
+ * * "Generic" images loaded for the larger event display(?)
+ *
+ * The Image base class represents all these and is to be used in and around Views
+ * to refer to images. __An Image object (via the derived classes) describes a
+ * particular image to display, but does not hold actual image data__.
+ *
+ * Each Image type above has a derived class to hold information specific about that
+ * type of image. E.g. a recording thumbnail image stores the recording filename.
+ *
+ * Future work: Investigate removing WSymbol and all related stuff, maybe including
+ * the DrawBitmap stuff in OsdVector. Surely this is all there to support the very
+ * basic bitmap symbols - this call all be replaced with PNGs.
+ *
+ * Image objects may only be instantiated by calling a ImageLoader::create___
+ * method. ImageLoader caches all existing Image objects and if an exact duplicate
+ * would be created by a create method then the existing Image object will be
+ * returned instead. This is normally done by returning a copy of the existing
+ * Image. However, if the request is unique but the VDR load fails, and the Image
+ * has a static-artwork fallback, then either:
+ * * The existing static-artwork is still waiting to be decoded - your Image object
+ *   will contain Image.otherImage pointing to the first image which requested that
+ *   static-artwork.
+ * * The existing static-artwork is ready - your Image object will have a normal
+ *   OsdImage object (which will be a copy of the first one) - see later.
+ *
+ * The "Image" type is actually a shared_ptr<CImage> so as many Image object
+ * copies can be made as necessary, there will only ever be one real CImage object
+ * per unique image description.
+ *
+ * OsdImages
+ *
+ * An OsdImage represents a real image held in hardware / graphics memory / whatever
+ * layer is actually providing graphics. Derived classes from OsdImage contain
+ * the real hardware handles for each type of OSD - e.g. OsdOpenVG OsdImage objects
+ * contain a VGImage.
+ *
+ * Tye "OsdImage" is actually a shared_ptr<OsdImageBase> so as many copies can
+ * be made as necessary, there will only ever be one copy of the image data held
+ * in the real graphics layer.
+ *
+ * The link between Image objects and OsdImage objects:
+ *
+ * An Image object without a contained OsdImage object is waiting for it to be
+ * loaded from VDR or to be decoded locally.
+ *
+ * An Image object with an OsdImage object may have a unique OsdImage or it may
+ * be shared between many Image objects. ImageLoader will assign the Image an
+ * appropriate OsdImage when it is downloaded and/or decoded.
+ *
+ * Deletion
+ *
+ * All Image objects have their first copy in mImages in ImageLoader. All OsdImages
+ * have their first copy in images in Osd. OsdVector::cleanupOrphanedRefs() calls
+ * ImageLoader::garbageCollect() to delete Images, and it calls
+ * Osd::garbageCollectOsdImages() to delete OsdImages - this should be overridden
+ * by the actual Osd implementation e.g. OsdOpenVG as it will know how to destroy
+ * the underlying hardware reference. Both garbage collectors delete any Image /
+ * OsdImage object that has a use-count of 1 (their first/master copy).
+ *
+ * Reasons for the upgrade:
+ *
+ * The new system allows failed VDR loads to fallback to static images and to use
+ * pre-existing static images. This vastly speeds up the recordingslist for example,
+ * where VDR holds no images for recordings.
+ *
+ * Code readability - The ref-counting system in OsdVector was very manual and
+ * difficult to follow. This is now all handled by shared_ptrs.
+ *
+ * TVMedia objects before were deep-copied and deep-compared. Now the actual
+ * objects are unique and have multiple shared_ptrs for them.
+ *
+ * Should be more extendable for new Image types in future if needed.
+ *
+ * Other Osd implementations:
+ *
+ * Will need significant updating to the new system, but the hope is it should
+ * be simpler and more logical.
+*/
+
+#include <memory>
+#include <mutex>
+#include <string>
+#include <vector>
+
+#include "defines.h"
+#include "osd.h"
+
+class CImage;
+class CImageStatic;
+class CImageGeneric;
+class CImageRecFolder;
+class CImageRecThumb;
+class CImageEventThumb;
+class CImageChannelLogo;
+using Image = std::shared_ptr<CImage>;
+using ImageStatic = std::shared_ptr<CImageStatic>;
+using ImageGeneric = std::shared_ptr<CImageGeneric>;
+using ImageRecFolder = std::shared_ptr<CImageRecFolder>;
+using ImageRecThumb = std::shared_ptr<CImageRecThumb>;
+using ImageEventThumb = std::shared_ptr<CImageEventThumb>;
+using ImageChannelLogo = std::shared_ptr<CImageChannelLogo>;
+
+// FIXME - Is there much point having the shared_ptr system for the derived objects?
+// See OsdImage which doesn't do this.
+
+class CImage
+{
+  friend class ImageLoader;
+
+  public:
+    enum ImageType { INVALID, STATIC, GENERIC, RECFOLDER, RECTHUMB, EVENTTHUMB, CHANNELLOGO };
+
+    ImageType getType() { return type; }
+    bool isReady() { return ready; }
+    OsdImage getOsdImage() { return osdImage; }
+
+  protected:
+    ImageType type{INVALID};
+
+    std::mutex stateLock;
+    bool ready{};
+    bool loading{};
+    bool failed{};
+    bool usingFallback{};
+    int staticArtworkID{-1};
+    ULONG serverLoadingRef{};
+    OsdImage osdImage;
+    Image otherImage; // If set, this image will use otherImage's osdImage when it is ready
+};
+
+class CImageStatic : public CImage
+{
+  friend class ImageLoader;
+};
+
+class SeriesInfo;
+class MovieInfo;
+class CImageGeneric : public CImage
+{
+  friend class ImageLoader;
+  friend class VDR;
+
+  public:
+    void setSeriesInfo(const SeriesInfo* si);
+    void setMovieInfo(const MovieInfo* mi);
+    void setElement(int cont, int memb) { type_pict = 0; container = cont; container_member = memb; }
+
+  private:
+    int primary_id{};
+    int secondary_id{};
+    int type{2};               // 1 = movie, 2 = series
+    int type_pict{-1};         // 0 full info, 1 poster thumb, 2 season thumb - OR -
+                               // 0 full info, 1 poster, 2 poster banner, 3 poster thumb -- BUT which is true?!
+    int container{-1};         // indices the dataelements with picture in movieinfo or seriesinfo
+    int container_member{-1};  // index into the container
+};
+
+class CImageRecFolder : public CImage
+{
+  friend class ImageLoader;
+
+  private:
+    std::string fileName;
+};
+
+class CImageRecThumb : public CImage
+{
+  friend class ImageLoader;
+
+  public:
+    const char* getFileName() { return fileName.c_str(); }
+    void setServerLoadingRef(ULONG slr) { serverLoadingRef = slr; }
+
+  private:
+    std::string fileName;
+};
+
+class CImageEventThumb : public CImage
+{
+  friend class ImageLoader;
+
+  public:
+    ULONG getChannel() { return channel; }
+    ULONG getEvent() { return event; }
+    void setServerLoadingRef(ULONG slr) { serverLoadingRef = slr; }
+  private:
+    ULONG channel{};
+    ULONG event{};
+
+};
+
+class CImageChannelLogo : public CImage
+{
+  friend class ImageLoader;
+
+  public:
+    ULONG getChannelID() { return channel; }
+    void setServerLoadingRef(ULONG slr) { serverLoadingRef = slr; }
+  private:
+    ULONG channel{};
+};
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+
+struct TVMediaStruct     // FIXME Hopefully roll this in above
+{
+  unsigned int width{};
+  unsigned int height{};
+  Image image;
+};
+
+struct Actor
+{
+  std::string name;
+  std::string role;
+  TVMediaStruct thumb;
+};
+
+typedef std::vector<Actor> Actors;
+
+typedef std::vector<TVMediaStruct> TVMedias;
+
+
+#endif
+
+/*
+
+Old TVMedia types information:
+
+0 \
+1 | - "movie or series"
+2 /
+3 poster thumb (char* recname)
+4 static
+5 poster thumb (channel, eventid)
+6 channel logo
+
+const static ULONG VDR_LOADTVMEDIA = 41;                   0,1,2
+const static ULONG VDR_LOADTVMEDIARECTHUMB = 42;           3
+const static ULONG VDR_LOADTVMEDIAEVENTTHUMB = 44;         5
+const static ULONG VDR_LOADCHANNELLOGO = 45;               6
+
+Types 3, 4, 5, 6 are handled by create*() methods in ImageLoader.
+Types 0, 1, 2 (though probably only 2 of these) are created with ImageLoader::createGeneric().
+
+After a createGeneric() only, caller must fill the Image with more information and then call
+imageLoader->ensureLoaded(image) to kick off loading the image from VDR.
+
+*/
diff --git a/imageloader.cc b/imageloader.cc
new file mode 100644 (file)
index 0000000..2f5e322
--- /dev/null
@@ -0,0 +1,632 @@
+/*
+    Copyright 2021 Chris Tallon
+    Portions Copyright 2012 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "log.h"
+#include "vdr.h"
+#include "vdrresponsepacket.h"
+#include "staticartwork.h"
+
+#include "imageloader.h"
+
+const static char* TAG = "ImageLoader";
+
+ImageLoader* ImageLoader::instance = NULL;
+
+ImageLoader::ImageLoader()
+{
+  instance = this;
+  logger = LogNT::getInstance();
+}
+
+ImageLoader::~ImageLoader()
+{
+  instance = NULL;
+
+  decoders_lock.lock();
+  while (decoders.size())
+  {
+    PictureDecoder* dec = decoders.front();
+    decoders.pop_front();
+    delete dec;
+  }
+  decoders_lock.unlock();
+}
+
+ImageLoader* ImageLoader::getInstance()
+{
+  return instance;
+}
+
+bool ImageLoader::init()
+{
+  // Start picture reader thread
+  pictureReaderCondSigtex.lock(); // misuse condsigtex here
+  pictureReaderThread = std::thread( [this]
+  {
+    pictureReaderCondSigtex.lock();
+    pictureReaderCondSigtex.unlock();
+    pictureReaderThreadMethod();
+  });
+  pictureReaderCondSigtex.unlock();
+
+  return true;
+}
+
+void ImageLoader::shutdown()
+{
+  std::unique_lock<std::mutex> lg(pictureReaderCondSigtex);
+
+  if (pictureReaderThread.joinable())
+  {
+    pictureReaderThreadQuit = true;
+    pictureReaderThreadCond.notify_one();
+    lg.unlock();
+    pictureReaderThread.join();
+  }
+}
+
+void ImageLoader::addDecoder(PictureDecoder* decoder)
+{
+  decoders_lock.lock();
+  logger->debug(TAG, "addDecoder {}", static_cast<void*>(decoder));
+  decoder->init();
+  decoders.push_front(decoder);
+  decoders_lock.unlock();
+}
+
+void ImageLoader::removeDecoder(PictureDecoder* decoder)
+{
+  decoders_lock.lock();
+  std::list<PictureDecoder*>::iterator itty = decoders.begin();
+
+  while (itty != decoders.end())
+  {
+    if ((*itty) == decoder)
+    {
+      decoders.erase(itty);
+      break;
+    }
+
+    itty++;
+  }
+
+  logger->debug(TAG, "removeDecoder");
+  decoder->shutdown();
+  delete decoder;
+  decoders_lock.unlock();
+}
+
+void ImageLoader::garbageCollect()
+{
+  mImagesLock.lock();
+  auto it = std::remove_if(mImages.begin(), mImages.end(), [](Image& i) { return i.use_count() == 1; });
+  mImages.erase(it, mImages.end());
+  mImagesLock.unlock();
+}
+
+void ImageLoader::dumpImages()
+{
+  logger->trace(TAG, "Num Images: {}", mImages.size());
+}
+
+ImageStatic ImageLoader::createStatic(int sa_id)
+{
+  ImageStatic staticImage = std::make_shared<CImageStatic>();
+  staticImage->type = CImage::STATIC;
+  staticImage->staticArtworkID = sa_id;
+  Image image = staticImage;
+
+  mImagesLock.lock();
+  mImages.push_back(image);
+  mImagesLock.unlock();
+
+  ensureLoaded(image);
+  return staticImage;
+}
+
+// For the old TVMedia types 0,1,2, though I suspect one of these doesn't exist
+// I think there's only SeriesInfo and MovieInfo that uses this now
+ImageGeneric ImageLoader::createGeneric()
+{
+  ImageGeneric genericImage = std::make_shared<CImageGeneric>();
+  genericImage->type = CImage::GENERIC;
+  Image image = genericImage;
+
+  mImagesLock.lock();
+  mImages.push_back(image);
+  mImagesLock.unlock();
+
+  // Generic Images do not have ensureLoaded called on them
+  // It is the callers responsibility to fill the generic with
+  // extra information and then call ImageLoader::ensureLoaded(image)
+  return genericImage;
+}
+
+// FIXME use unique_lock, lock around add as well, unlock before ensureLoaded
+
+ImageRecFolder ImageLoader::createRecFolder(const char* recName)
+{
+  // Does this image already exist?
+  {
+    std::lock_guard<std::mutex> lg(mImagesLock);
+    for(Image& mImage : mImages)
+    {
+      if (mImage->type == CImage::RECFOLDER)
+      {
+        ImageRecFolder i = std::static_pointer_cast<CImageRecFolder>(mImage);
+        if (i->fileName == recName) return i;
+      }
+    }
+  }
+
+  ImageRecFolder recFolderImage = std::make_shared<CImageRecFolder>();
+  recFolderImage->type = CImage::RECFOLDER;
+  recFolderImage->fileName = recName;
+  recFolderImage->staticArtworkID = sa_recfolder; // For fallback
+  Image image = recFolderImage;
+
+  mImagesLock.lock();
+  mImages.push_back(image);
+  mImagesLock.unlock();
+
+  ensureLoaded(image);
+  return recFolderImage;
+}
+
+ImageRecThumb ImageLoader::createRecThumb(const char* recName)
+{
+  // Does this image already exist?
+  {
+    std::lock_guard<std::mutex> lg(mImagesLock);
+    for(Image& mImage : mImages)
+    {
+      if (mImage->type == CImage::RECTHUMB)
+      {
+        ImageRecThumb i = std::static_pointer_cast<CImageRecThumb>(mImage);
+        if (i->fileName == recName) return i;
+      }
+    }
+  }
+
+  ImageRecThumb recThumbImage = std::make_shared<CImageRecThumb>();
+  recThumbImage->type = CImage::RECTHUMB;
+  recThumbImage->fileName = recName;
+  recThumbImage->staticArtworkID = sa_recording; // For fallback
+  Image image = recThumbImage;
+
+  mImagesLock.lock();
+  mImages.push_back(image);
+  mImagesLock.unlock();
+
+  ensureLoaded(image);
+  return recThumbImage;
+}
+
+ImageEventThumb ImageLoader::createEventThumb(ULONG channel, ULONG event)
+{
+  // Does this image already exist?
+  {
+    std::lock_guard<std::mutex> lg(mImagesLock);
+    for(Image& mImage : mImages)
+    {
+      if (mImage->type == CImage::EVENTTHUMB)
+      {
+        ImageEventThumb i = std::static_pointer_cast<CImageEventThumb>(mImage);
+        if ((i->channel == channel) && (i->event == event)) return i;
+      }
+    }
+  }
+
+  ImageEventThumb eventThumbImage = std::make_shared<CImageEventThumb>();
+  eventThumbImage->type = CImage::EVENTTHUMB;
+  eventThumbImage->channel = channel;
+  eventThumbImage->event = event;
+  eventThumbImage->staticArtworkID = sa_defposter; // For fallback
+  Image image = eventThumbImage;
+
+  mImagesLock.lock();
+  mImages.push_back(image);
+  mImagesLock.unlock();
+
+  ensureLoaded(image);
+  return eventThumbImage;
+}
+
+ImageChannelLogo ImageLoader::createChannelLogo(ULONG channel, int sa_id)
+{
+  // Does this image already exist?
+  {
+    std::lock_guard<std::mutex> lg(mImagesLock);
+    for(Image& mImage : mImages)
+    {
+      if (mImage->type == CImage::CHANNELLOGO)
+      {
+        ImageChannelLogo i = std::static_pointer_cast<CImageChannelLogo>(mImage);
+        if ((i->channel == channel) && (i->staticArtworkID == sa_id)) return i;
+      }
+    }
+  }
+
+  logger->trace(TAG, "createChannelLogo said = {}", sa_id);
+
+  ImageChannelLogo channelLogoImage = std::make_shared<CImageChannelLogo>();
+  channelLogoImage->type = CImage::CHANNELLOGO;
+  channelLogoImage->channel = channel;
+  channelLogoImage->staticArtworkID = sa_id;
+
+  Image image = channelLogoImage;
+
+  mImagesLock.lock();
+  mImages.push_back(image);
+  mImagesLock.unlock();
+
+  ensureLoaded(image);
+  return channelLogoImage;
+}
+
+void ImageLoader::ensureLoaded(ImageGeneric& ig)
+{
+  Image image = ig;
+  ensureLoaded(image);
+}
+
+void ImageLoader::ensureLoaded(Image& image)
+{
+  image->stateLock.lock();                                                                  ///////// LOCK
+
+  if (!image->ready && !image->loading) // needs loading
+  {
+    switch (image->getType())
+    {
+      case CImage::STATIC:
+      {
+        decodeStatic(image);
+        break;
+      }
+      case CImage::GENERIC:
+      {
+        ImageGeneric ign = std::static_pointer_cast<CImageGeneric>(image);
+        VDR::getInstance()->loadImageGeneric(ign);
+        break;
+      }
+      case CImage::RECFOLDER:
+      case CImage::RECTHUMB:
+      {
+        ImageRecThumb irt = std::static_pointer_cast<CImageRecThumb>(image);
+        VDR::getInstance()->loadImageRecThumb(irt);
+        break;
+      }
+      case CImage::EVENTTHUMB:
+      {
+        ImageEventThumb iet = std::static_pointer_cast<CImageEventThumb>(image);
+        VDR::getInstance()->loadImageEventThumb(iet);
+        break;
+      }
+      case CImage::CHANNELLOGO:
+      {
+        ImageChannelLogo icl = std::static_pointer_cast<CImageChannelLogo>(image);
+        VDR::getInstance()->loadImageChannelLogo(icl);
+        break;
+      }
+    }
+
+    image->loading = true;
+  }
+
+  image->stateLock.unlock();                                                                  ///////// UNLOCK
+}
+
+void ImageLoader::downloadDone(VDR_ResponsePacket* vresp)
+{
+  // This is VDR's reception thread, don't delay
+  // Take the incoming vresp and add it to an incoming queue. Then signal the processor thread
+
+  // TODO reimplement index-map
+
+  PictureReaderWorkItem p;
+  p.vresp = vresp;
+
+  pictureReaderWorkLock.lock();
+  pictureReaderWork.push(p);
+  pictureReaderWorkLock.unlock();
+
+
+  // Now do most minimal lock & signal. Uses separate lock to the work vector.
+  // This split mechanism guarantees work won't be missed at the expense of possibly
+  // waking the thread unnecessarily.
+  pictureReaderCondSigtex.lock();
+  pictureReaderThreadRun = true;
+  pictureReaderThreadCond.notify_one();
+  pictureReaderCondSigtex.unlock();
+}
+
+bool ImageLoader::pictureRendered(LoadingIndex index, OsdImage& oimage)
+{
+  // This is called form OsdVector after it is notified from the actual gfx layer
+  // that an image has been loaded into the graphics system and is ready for use
+
+  logger->trace(TAG, "pictureRendered: li {}", static_cast<void*>(index));
+
+  Image image = loadingIndexToImage(index);
+
+  if (!image)
+  {
+    // An image has been loaded but we don't know anything about it.
+    // Probably a slow load for something already dropped off screen.
+    return false;
+  }
+
+  // prob want to lock the whole thing ot update other images waiting for the same oimage
+  std::lock_guard<std::mutex> lg1(mImagesLock);
+
+  std::lock_guard<std::mutex> lg(image->stateLock);
+  image->loading = false;
+  image->ready = true;
+  image->osdImage = oimage;
+
+  logger->trace(TAG, "pictureRendered: {}", static_cast<void*>(image.get()));
+
+  // Are there any images waiting for this one?
+  for(auto mImage : mImages)
+  {
+    if ((mImage->ready == false) && (mImage->otherImage == image))
+    {
+      mImage->osdImage = image->osdImage;
+      mImage->loading = false;
+      mImage->ready = true;
+      // FIXME ?? Clear mImage->otherImage?
+    }
+  }
+
+  return true;
+}
+
+Image ImageLoader::loadingIndexToImage(LoadingIndex index)
+{
+  std::lock_guard<std::mutex> lg(mImagesLock);
+
+  for(Image& i : mImages)
+  {
+    //logger->trace(TAG, "li2I {} {}", (void*)index, (void*)i.get());
+    if (i.get() == static_cast<CImage*>(index)) return i;
+  }
+
+  // It is only possible to get to here calling from pictureRendered, but the Image
+  // has already been discarded (went off screen before it ever loaded)
+
+  Image dead;
+  return dead;
+}
+
+void ImageLoader::decodeStatic(Image& image)
+{
+  PictureReaderWorkItem p;
+  p.image = image;
+  pictureReaderWorkLock.lock();
+  pictureReaderWork.push(p);
+  pictureReaderWorkLock.unlock();
+
+  // Same split as above, separate locks for vector and signal
+
+  pictureReaderCondSigtex.lock();
+  pictureReaderThreadRun = true;
+  pictureReaderThreadCond.notify_one();
+  pictureReaderCondSigtex.unlock();
+}
+
+
+void ImageLoader::pictureReaderThreadMethod()
+{
+  std::unique_lock<std::mutex> ul(pictureReaderCondSigtex); // Lock for most minimal time
+  while (true)
+  {
+    pictureReaderThreadCond.wait(ul, [this]{ return pictureReaderThreadQuit || pictureReaderThreadRun; });
+    // locked
+    if (pictureReaderThreadQuit) return; // unlock
+    pictureReaderThreadRun = false;
+    ul.unlock();
+
+    // unlocked while we work
+
+    bool miniRunAgain;
+    do
+    {
+      miniRunAgain = false;
+
+      PictureInfo pictinf;
+      decoders_lock.lock();
+      std::list<PictureDecoder*>::iterator itty = decoders.begin();
+
+      while (itty != decoders.end())
+      {
+        if ((*itty)->getDecodedPicture(pictinf)) // pictinf now contains handle (vgImage) and reference (a EGLImageKHR)
+        {
+          miniRunAgain = true;
+          // logger->trace(TAG, "got decoded pic {}", (void*)pictinf.lindex );
+
+          OsdVector* osdvector = dynamic_cast<OsdVector*>(Osd::getInstance()); // put this here, osdvector is not created yet when tihs method starts
+          osdvector->createPicture(pictinf); // This goes into OsdOpenVG which generates Message::NEW_PICTURE
+        }
+        itty++;
+      }
+
+      pictureReaderProcessOne();
+
+      decoders_lock.unlock();
+
+      if (pictureReaderWork.size()) miniRunAgain = true;
+
+    } while(miniRunAgain);
+
+    ul.lock();
+  }
+}
+
+void ImageLoader::pictureReaderProcessOne()
+{
+  OsdVector* osdvector = dynamic_cast<OsdVector*>(Osd::getInstance());
+
+  pictureReaderWorkLock.lock();
+  if (pictureReaderWork.empty())
+  {
+    pictureReaderWorkLock.unlock();
+    return;
+  }
+
+  PictureReaderWorkItem pwi;
+  pwi = pictureReaderWork.front();
+  pictureReaderWork.pop();
+  pictureReaderWorkLock.unlock();
+
+
+  // Either pwi has a image or a vresp. If it's a image then it's a static artwork decode
+  // If it's a vresp then it's a server download done
+
+  // Set up the common variables
+  Image image;
+  bool free_it = false;
+  UCHAR* imageData{};
+  ULONG length{};
+
+
+  if (pwi.vresp)
+  {
+    // Now find the Image with this vresp->getStreamID() == image.serverLoadingRef
+    mImagesLock.lock();
+
+    //      logger->trace(TAG, "mImages size: {}", mImages.size());
+    //     for(Image& i : mImages)
+    //     {
+    //       logger->trace(TAG, "Image said: {} {}", (void*)i.get(), i->staticArtworkID);
+    //     }
+
+    for(Image& i : mImages)
+    {
+      if (i->serverLoadingRef == pwi.vresp->getStreamID())
+      {
+        image = i;
+        break;
+      }
+    }
+    mImagesLock.unlock();
+
+
+    if (!image)
+    {
+      logger->trace(TAG, "Could not find Image for VRESP in download-done!!");
+      abort();
+    }
+
+    std::lock_guard<std::mutex> lg(image->stateLock);
+
+    if (pwi.vresp->getFlag() != 2)  // Server image success
+    {
+      imageData = pwi.vresp->getUserData();
+      length = pwi.vresp->getUserDataLength();
+      free_it = true;
+    }
+    else
+    {
+      image->serverLoadingRef = 0;
+      image->usingFallback = true;
+      logger->trace(TAG, "Fallback for {}", static_cast<void*>(image.get()));
+    }
+
+    delete pwi.vresp;
+  }
+  else
+  {
+    image = pwi.image;
+  }
+
+  // vresp is gone. Now we have a Image which might have some downloaded data
+
+  // Before we go on, does anyone still want this image?
+  if (image.use_count() == 2) return; // It's only in the mImages and here
+
+  //logger->trace(TAG, "Still needed {} {}", (void*)image.get(), image->staticArtworkID);
+
+  // Set up a static decode?
+  if (      (image->getType() == CImage::STATIC)
+        || ((image->usingFallback == true) && (image->staticArtworkID != -1))
+     )
+  {
+    //logger->trace(TAG, "Do static {}", (void*)image.get());
+
+    // Do we already have this static decoded?
+    mImagesLock.lock();
+    for(Image& i : mImages)
+    {
+      if (i == image) continue;
+
+      //logger->trace(TAG, "Image said: {} {}", (void*)i.get(), i->staticArtworkID);
+
+      if (    ((i->getType() == CImage::STATIC) || (i->usingFallback == true))
+          &&  (i->staticArtworkID == image->staticArtworkID)
+          &&  (!i->otherImage) // Don't link to another image which is already linked to another image
+         )
+      {
+        if (i->ready) // Link osdImage, set ready, done.
+        {
+          image->osdImage = i->osdImage;
+          image->ready = true;
+          image->loading = false;
+          mImagesLock.unlock();
+          return;
+        }
+        else // Link to the other image file and wait for it to be ready
+        {
+          image->otherImage = i;
+          mImagesLock.unlock();
+          return;
+        }
+      }
+    }
+    mImagesLock.unlock();
+
+    // Continue with a new decode
+
+    osdvector->getStaticImageData(image->staticArtworkID, &imageData, &length);
+  }
+
+  // Now decode.
+
+  if (imageData)
+  {
+    //logger->trace(TAG, "Doing decode {}", (void*)image.get());
+
+    std::list<PictureDecoder*>::iterator it = decoders.begin();
+
+    while (it != decoders.end())
+    {
+      imageData = (*it)->decodePicture(image.get(), imageData, length, free_it);
+      //logger->trace(TAG, "Doing decode done {} {}", (void*)image.get(), (void*) imageData);
+
+      if (!imageData) break;
+      it++;
+    }
+
+    if (imageData)
+    {
+      image->failed = true;
+      if (free_it) free(imageData);
+    }
+  }
+}
diff --git a/imageloader.h b/imageloader.h
new file mode 100644 (file)
index 0000000..7aa206b
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+    Copyright 2021 Chris Tallon
+
+    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, see <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef IMAGELOADER_H
+#define IMAGELOADER_H
+
+#include <memory>
+#include <vector>
+#include <queue>
+#include <list>
+#include <mutex>
+#include <thread>
+#include <condition_variable>
+
+#include "defines.h"
+#include "osdvectortypes.h"
+#include "osdvector.h"
+
+#include "image.h"
+
+
+class LogNT;
+class VDR_ResponsePacket;
+
+class PictureReader;
+class PictureDecoder
+{
+  public:
+    PictureDecoder() {}
+    virtual ~PictureDecoder() {}
+
+    // its is always guaranted, that after getDecodedPicture a call to decodePicture follows, if the return value was true;
+    virtual unsigned char* decodePicture(LoadingIndex index, unsigned char* buffer, unsigned int length, bool freemem = true) = 0;
+
+    virtual bool getDecodedPicture(struct PictureInfo& pict_inf) = 0;
+    virtual void freeReference(void* ref) = 0;
+
+    virtual void init() {};
+    virtual void shutdown() {};
+};
+
+class ImageLoader
+{
+  public:
+    ImageStatic createStatic(int sa_id);
+    ImageGeneric createGeneric();
+    ImageRecFolder createRecFolder(const char* recFileName);
+    ImageRecThumb createRecThumb(const char* recFileName);
+    ImageEventThumb createEventThumb(ULONG channel, ULONG event);
+    ImageChannelLogo createChannelLogo(ULONG channel, int sa_id = -1);
+
+    ImageLoader();
+    ~ImageLoader();
+    static ImageLoader* getInstance();
+
+    bool init();
+    void shutdown();
+    void ensureLoaded(Image& image);
+    void ensureLoaded(ImageGeneric& imageGeneric);
+    void decodeStatic(Image& t);
+    void downloadDone(VDR_ResponsePacket* vresp);
+    bool pictureRendered(LoadingIndex index, OsdImage& oimage);
+    void garbageCollect();
+
+    void addDecoder(PictureDecoder* decoder);
+    void removeDecoder(PictureDecoder* decoder);
+
+    void dumpImages();
+
+  private:
+    static ImageLoader* instance;
+
+    LogNT* logger{};
+
+    std::vector<Image> mImages;  // Master vector of Image objects
+    std::mutex mImagesLock;
+
+    struct PictureReaderWorkItem
+    {
+      VDR_ResponsePacket* vresp{};
+      // or
+      Image image;
+    };
+
+    std::queue<PictureReaderWorkItem> pictureReaderWork;
+    std::mutex pictureReaderWorkLock;
+
+    void pictureReaderThreadMethod();
+    std::mutex pictureReaderThreadMutex;
+    std::thread pictureReaderThread;
+    bool pictureReaderThreadRun{};
+    bool pictureReaderThreadQuit{};
+    std::condition_variable pictureReaderThreadCond;
+    std::mutex pictureReaderCondSigtex; // Careful with this, lock for minimal time
+
+    std::mutex decoders_lock;
+    std::list<PictureDecoder*> decoders;
+
+    Image loadingIndexToImage(LoadingIndex index);
+    void pictureReaderProcessOne();
+};
+
+#endif
index 6be066e03616150d1ad712daa7e96ebab1f1fa7c..27d13fc9c35630f07ccaf99e823014e1ab95d048 100644 (file)
@@ -31,7 +31,7 @@
 
 static const char* TAG = "ImageOMX";
 
-ImageOMX::ImageOMX(OsdVector::PictureReader * treader):OsdVector::PictureDecoder(treader)
+ImageOMX::ImageOMX()
 {
   initted = 0;
 
@@ -481,7 +481,7 @@ bool ImageOMX::intDecodePicture(LoadingIndex index, unsigned char* /* buffer */,
        pictInf.width = port_def_type.format.image.nFrameWidth;
        pictInf.height = port_def_type.format.image.nFrameHeight;
        pictInf.decoder = this;
-       pictInf.type = OsdVector::PictureInfo::RGBAMemBlock;
+       pictInf.type = PictureInfo::RGBAMemBlock;
        pictInf.lindex = index;
 
 
@@ -646,7 +646,7 @@ bool ImageOMX::intDecodePicture(LoadingIndex index, unsigned char* /* buffer */,
 
 }
 
-bool ImageOMX::getDecodedPicture(struct OsdVector::PictureInfo& pict_inf)
+bool ImageOMX::getDecodedPicture(struct PictureInfo& pict_inf)
 {
        if (!pictInfValid) return false;
        pict_inf=pictInf;
index ce722aab5509f5bdbb0e9f16e497ba00af81f62b..0fe4021e3eb82adb05438b923b661d63e93d90d9 100644 (file)
 
 
 
-class ImageOMX : public OsdVector::PictureDecoder
+class ImageOMX : public PictureDecoder
 {
   friend class VideoOMX;
   public:
-    ImageOMX(OsdVector::PictureReader * treader);
+    ImageOMX();
     virtual ~ImageOMX();
 
     void init();
     void shutdown();
 
     unsigned char* decodePicture(LoadingIndex index, unsigned char * buffer, unsigned int length, bool freemem);
-    bool getDecodedPicture(struct OsdVector::PictureInfo& pict_inf);
+    bool getDecodedPicture(struct PictureInfo& pict_inf);
     void freeReference(void * ref);
 
   private:
@@ -107,7 +107,7 @@ class ImageOMX : public OsdVector::PictureDecoder
     char L_VPE_OMX_EGL_REND[128];
 
   protected:
-    OsdVector::PictureInfo pictInf;
+    PictureInfo pictInf;
     bool pictInfValid;
 
 };
index 2601bdfd0b8b04376a52362c0f161fe9b72895dc..7f1057ec11d7487ed49bee89b89c9a181943631c 100644 (file)
     along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
 */
 
-#include "osdvector.h"
+#include <vector>
 
+#include "log.h"
 #include "omx/omximagedecode.h"
 #include "omx/omxeglrender.h"
+#include "eglpicturecreator.h"
+#include "imageloader.h"
 
 #include "imageomx2.h"
 
-#include "eglpicturecreator.h"
-
 const static char* TAG = "ImageOMX2";
 
 ImageOMX2::ImageOMX2(/*EGLDisplay t_egl_display*/)
-: OsdVector::PictureDecoder(NULL)
 {
   log = LogNT::getInstance();
   //egl_display = t_egl_display;
@@ -91,7 +91,7 @@ unsigned char* ImageOMX2::decodePicture(LoadingIndex index, unsigned char* buffe
 
     currentDecode.lindex = index;
     currentDecode.decoder = this;
-    currentDecode.type = OsdVector::PictureInfo::RGBAMemBlock;
+    currentDecode.type = PictureInfo::RGBAMemBlock;
     //currentDecode.image/handle =   // filled during render
     //currentDecode.reference =      // filled during render
 
@@ -151,7 +151,7 @@ unsigned char* ImageOMX2::decodePicture(LoadingIndex index, unsigned char* buffe
   }
 }
 
-bool ImageOMX2::getDecodedPicture(struct OsdVector::PictureInfo& pict_inf)
+bool ImageOMX2::getDecodedPicture(struct PictureInfo& pict_inf)
 {
   if (!currentDecodeValid) return false;
   pict_inf = currentDecode;
index ef85a755caf381ea45ce8d0d84854a9d575c47bd..28e00eddc679aaca75432a5d1e11491b6b947386 100644 (file)
@@ -47,14 +47,13 @@ with VideoOMX?)
 #ifndef IMAGEOMX2_H
 #define IMAGEOMX2_H
 
-#include "osdvector.h"
-#include "osdopenvg.h"
+#include "osdvectortypes.h"
 
 class LogNT;
 class OMX_Image_Decode;
 class OMX_EGL_Render;
 
-class ImageOMX2 : public OsdVector::PictureDecoder
+class ImageOMX2 : public PictureDecoder
 {
 // PictureDecoder Interface
   public:
@@ -65,7 +64,7 @@ class ImageOMX2 : public OsdVector::PictureDecoder
     void shutdown();
 
     unsigned char* decodePicture(LoadingIndex index, unsigned char* buffer, unsigned int length, bool freemem) noexcept;
-    bool getDecodedPicture(struct OsdVector::PictureInfo& pict_inf);
+    bool getDecodedPicture(struct PictureInfo& pict_inf);
     void freeReference(void*) {};
 
 // Internal stuff
@@ -77,7 +76,7 @@ class ImageOMX2 : public OsdVector::PictureDecoder
     OMX_EGL_Render* omx_eglrender{};
 
     // State data for the decode
-    struct OsdVector::PictureInfo currentDecode{}; // There's only one user so no locking required
+    struct PictureInfo currentDecode{}; // There's only one user so no locking required
     bool currentDecodeValid{};
 
     // Internal functions
index 4abaeb7888f64a87c930e6ae70d85effd9b71e6b..be72b04fb4f556cda809b0c4d37428a4cd534a77 100644 (file)
--- a/message.h
+++ b/message.h
@@ -84,7 +84,6 @@ class Message
     const static int SUBTITLE_CHANGE_CHANNEL       = 34;
     const static int MOUSE_SCROLL                  = 35;
     const static int NEW_PICTURE                   = 36;
-    const static int NEW_PICTURE_STATIC            = 37;
     const static int REDRAW                        = 38;
     const static int SHUTDOWN                      = 39;
 
index 2513c18ece7c1f20ed5677efe5e4ae4060f761e5..191d0c224c53c89cd54cba1f692559d40fd2ee0e 100644 (file)
 
 #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;
-
-
-
-}
-
-
index 31c335822298e334dad7b0fc647041ca9192a8db..65f31d01a314f7aa0c2b6ed9d4c9232e9c674c73 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2014 Marten Richter
+    Copyright 2014 Marten Richter, 2021 Chris Tallon
 
     This file is part of VOMP.
 
     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.
+    along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
 */
 
 #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;
+#include <string>
+
+#include "image.h"
+
+struct 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{};
+
+  TVMediaStruct poster;
+  TVMediaStruct fanart;
+  TVMediaStruct collectionPoster;
+  TVMediaStruct collectionFanart;
+  Actors actors;
 };
 
-
 #endif
index b6370b9909dbb182a05c5703e79b7439cce35e1f..2037b9d8827d59213f4c495e52346981dcc77bf7 100644 (file)
@@ -17,9 +17,10 @@ OBJ_COMMON = util.o control.o thread.o timers.o i18n.o udp4.o udp6.o vdpc.o tcp.
              vdrresponsepacket.o vvideolivetv.o sleeptimer.o                       \
              wprogressbar.o bitmap.o dvbsubtitles.o tfeed.o vteletextview.o        \
              teletextdecodervbiebu.o teletxt/txtfont.o movieinfo.o seriesinfo.o    \
-             wmovieview.o wseriesview.o tvmedia.o wtvmedia.o wpictureview.o        \
+             wmovieview.o wseriesview.o wtvmedia.o wpictureview.o                  \
              osdvector.o surfacevector.o buffer.o config.o log.o                   \
-             playervideorec.o playervideolive.o playerradiolive.o playerradiorec.o
+             playervideorec.o playervideolive.o playerradiolive.o playerradiorec.o \
+             imageloader.o image.o
 
 OBJ_RASPBERRY = main.o threadp.o osdopenvg.o                                       \
                 ledraspberry.o videoomx.o audioomx.o imageomx.o                    \
diff --git a/osd.cc b/osd.cc
index e497911a28c34405cd14a5e9a4b0a8f5c29b6359..2976d883fd3ad5f4b5cebf4e3eaec303ffb78181 100644 (file)
--- a/osd.cc
+++ b/osd.cc
@@ -1,5 +1,5 @@
 /*
-    Copyright 2004-2005 Chris Tallon
+    Copyright 2004-2021 Chris Tallon
 
     This file is part of VOMP.
 
@@ -14,8 +14,7 @@
     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.
+    along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
 */
 
 #include "osd.h"
@@ -42,3 +41,14 @@ Osd* Osd::getInstance()
 {
   return instance;
 }
+
+void Osd::addOsdImage(OsdImage& o)
+{
+  images.push_back(o);
+  //LogNT::getInstance()->trace("OsdImage", "ADDED HW IMAGE: {}", images.size());
+}
+
+void Osd::dumpImages()
+{
+  //LogNT::getInstance()->trace("OsdImage", "Num OsdImages: {}", images.size());
+}
diff --git a/osd.h b/osd.h
index 804d571b83f35c59cace16439f4a56ceedadfd25..2754a1cc8bce43335707d9a8ffc4be1e75fd70db 100644 (file)
--- a/osd.h
+++ b/osd.h
@@ -1,5 +1,5 @@
 /*
-    Copyright 2004-2005 Chris Tallon
+    Copyright 2004-2021 Chris Tallon
 
     This file is part of VOMP.
 
 #ifndef OSD_H
 #define OSD_H
 
+#include <memory>
+#include <mutex>
+#include <vector>
+
+// See image.h for docs
+
+class OsdImageBase;
+using OsdImage = std::shared_ptr<OsdImageBase>;
+class OsdImageBase {};
+
 class Surface;
 
 class Osd
@@ -34,7 +44,7 @@ class Osd
     virtual int restore() { return 1; };
     virtual int stopUpdate() { return 1; };
 
-    virtual Surface * createNewSurface()=0; // For Boxx
+    virtual Surface* createNewSurface()=0; // For Boxx
     virtual int charSet() { return 1; };
 
     bool isInitted() { return initted; };
@@ -49,11 +59,22 @@ class Osd
     // OSDOVG-ROD-EXPERIMENT
     virtual void doRender() { };
 
+    // Images
+    OsdImage createOsdImage();
+    virtual void garbageCollectOsdImages()=0;
+
+    void dumpImages();
+
   protected:
     static Osd* instance;
     bool initted{};
-    Surface* screen;
-    int fdOsd;
+    Surface* screen{};
+    int fdOsd{};
+
+    // Images
+    void addOsdImage(OsdImage& oImage);
+    std::vector<OsdImage> images;
+    std::mutex imagesLock;
 };
 
 #endif
index 7b6b9806aa7a4ad7578be878f893ea51fbcf3e02..171984a6db3e55235eb4589d09f8f3c9d06d3334 100644 (file)
@@ -17,6 +17,7 @@
     along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
 */
 
+#include <algorithm>
 #include <chrono>
 #include <sys/syscall.h>
 #include <fontconfig/fontconfig.h>
@@ -63,10 +64,14 @@ OsdOpenVG::OsdOpenVG()
   EXTERNAL_PICTS
 
 #undef EXTERNALPICTURE
+
+  MessageQueue::getInstance()->addReceiver(this);
 }
 
 OsdOpenVG::~OsdOpenVG()
 {
+  MessageQueue::getInstance()->removeReceiver(this);
+
   if (initted) shutdown();
 
   if (cur_fontname) free(cur_fontname);
@@ -84,7 +89,7 @@ int OsdOpenVG::init()
 {
   if (initted) return 0;
 
-  reader.init();
+  OsdVector::init();
 
   //First get connection to egl
   egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
@@ -314,12 +319,10 @@ int OsdOpenVG::init()
   taskmutex.unlock();
   vgmutex.unlock();
 
-#ifdef PICTURE_DECODER_OMX
- // imageomx = new ImageOMX(&reader);
- // reader.addDecoder(imageomx);
 
+#ifdef PICTURE_DECODER_OMX
   imageomx2 = new ImageOMX2(/*egl_display*/);
-  reader.addDecoder(imageomx2);
+  ImageLoader::getInstance()->addDecoder(imageomx2);
 #endif
 
   return 1;
@@ -345,12 +348,8 @@ int OsdOpenVG::stopUpdate()
 
 int OsdOpenVG::shutdown()
 {
-  reader.shutdown();
-
 #ifdef PICTURE_DECODER_OMX
-//   if (imageomx) reader.removeDecoder(imageomx);
-//   imageomx = NULL;
-  if (imageomx2) reader.removeDecoder(imageomx2);
+  if (imageomx2) ImageLoader::getInstance()->removeDecoder(imageomx2);
   imageomx2 = NULL;
 #endif
 
@@ -419,6 +418,48 @@ int OsdOpenVG::shutdown()
   return 1;
 }
 
+void OsdOpenVG::processMessage(Message* m)
+{
+  if (m->message == Message::NEW_PICTURE)
+  {
+    logger->debug(TAG, "NEW_PICTURE");
+
+    OsdImageBase* newImageOVG = new OsdImageOpenVG(reinterpret_cast<VGImage>(m->data));
+    OsdImage oImage(newImageOVG);
+
+    addOsdImage(oImage);
+
+    ImageLoader::getInstance()->pictureRendered(reinterpret_cast<LoadingIndex>(m->tag), oImage);
+    // The above returns false if it does not accept the OsdImage
+    // We just drop out here and leave the only reference to it in Osd::images
+    // It will be deleted properly on the next garbage collection run
+
+    // OSDOVG-ROD-EXPERIMENT
+    logger->trace(TAG, "EXPERIMENT - call doRender");
+    doRender();
+  }
+}
+
+void OsdOpenVG::garbageCollectOsdImages()
+{
+  // Only use references into images
+  // Therefore if use_count == 1 the only copy of the OsdImage is in images and therefore is dead
+
+  imagesLock.lock();
+  for(auto& oi : images)
+  {
+    if (oi.use_count() == 1)
+      destroyImageRef(std::static_pointer_cast<OsdImageOpenVG>(oi)->getVGImage());
+  }
+
+  auto it = std::remove_if(images.begin(), images.end(), [](OsdImage& oi) { return oi.use_count() == 1; });
+  images.erase(it, images.end());
+
+  // C++20:  std::erase_if(images, [](OsdImage oi) { return oi.use_count() == 1; });
+
+  imagesLock.unlock();
+}
+
 // OSDOVG-ROD-EXPERIMENT - temp hack to allow OsdVector to signal the thread in OsdOpenVG
 void OsdOpenVG::doRender()
 {
@@ -439,7 +480,7 @@ void OsdOpenVG::doRender()
  * Pros:
  *   More responsive OSD
  *   Cuts 5% constant CPU usage
- *   Seems to have tickled the GFX corruption bug, might make it easier to find that
+ *   Seems to have tickled the GFX corruption bug, might make it easier to find that - update: found and fixed!!
  *
  * Cons:
  *   There's a comment about video tearing if render is called too often.
@@ -636,13 +677,6 @@ void OsdOpenVG::purgeAllReferences()
        }
        jpegs.clear();* /
 
-       map<TVMediaInfo,VectorHandleImage>::iterator titty=tvmedias.begin();
-       while (titty!=tvmedias.end()) {
-               vgDestroyImage((VGImage)(*titty).second);
-               titty++;
-       }
-       tvmedias.clear();
-
        map<pair<Colour*,unsigned int>,unsigned int>::iterator sitty=drawstyleHandles.begin();
        while (sitty!=drawstyleHandles.end()) {
                vgDestroyPaint((VGPaint)(*sitty).second);
@@ -1138,15 +1172,30 @@ void OsdOpenVG::executeDrawCommand(SVGCommand& command)
       break;
     }
     case DrawImage:
+    case DrawBitmap:
     {
+      VGImage vgimage;
+      if (command.instr == DrawBitmap) vgimage = static_cast<VGImage>(command.target.bitmap);
+      else if (command.instr == DrawImage)
+      {
+        // FIXME use shared_ptr for OsdImageOpenVG objects?
+        // -or-
+        // Don't use shared_ptrs for all those CImage types, are they needed?
+        // Preferring the second option at the moment
+
+        OsdImage oi = command.image->getOsdImage();
+        OsdImageOpenVG* oiovg = std::static_pointer_cast<OsdImageOpenVG>(oi).get();
+        vgimage = oiovg->getVGImage();
+      }
+
       vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
       vgGetMatrix(save_matrix);
-      VGfloat imagewidth = vgGetParameteri(static_cast<VGImage>(command.target.image), VG_IMAGE_WIDTH);
-      VGfloat imageheight = vgGetParameteri(static_cast<VGImage>(command.target.image), VG_IMAGE_HEIGHT);
+      VGfloat imagewidth = vgGetParameteri(vgimage, VG_IMAGE_WIDTH);
+      VGfloat imageheight = vgGetParameteri(vgimage, VG_IMAGE_HEIGHT);
 
       //vgScale(command.w,command.h);
 
-      if (command.handle)   //special behaviout for bw images they act as a mask on the current paint
+      if (command.handle)   //special behaviour for bw images they act as a mask on the current paint
       {
         vgTranslate(command.x, command.y);
         vgSetPaint(static_cast<VGPaint>(command.handle), VG_FILL_PATH);
@@ -1227,9 +1276,9 @@ void OsdOpenVG::executeDrawCommand(SVGCommand& command)
       //vgTranslate(200.f,500.f);
       //vgScale(100.f,100.f);
 
-      vgDrawImage(static_cast<VGImage>(command.target.image));
+      vgDrawImage(vgimage);
 
-      //LogNT::getInstance()->debug(TAG, "Draw Image {} {:#x} {} {} {} {} {:#x}",command.handle,command.target.image,command.x,command.y,command.w,command.h,
+      //LogNT::getInstance()->debug(TAG, "Draw Image {} {:#x} {} {} {} {} {:#x}",command.handle,vgimage,command.x,command.y,command.w,command.h,
       //               vgGetError());
       if (command.handle)
       {
@@ -1356,7 +1405,7 @@ unsigned int OsdOpenVG::handleOpenVGCommand(OpenVGCommand& command)
     }
     case OVGdestroyImageRef:  //imcount--;
     {
-      //LogNT::getInstance()->debug(TAG, "TVMedia Draw Image Destroy {:#x} {}",command.param1,imcount);
+      //LogNT::getInstance()->debug(TAG, "OsdImage Destroy vgDestroyImage {:#x}",command.param1);
       vgDestroyImage(static_cast<VGImage>(command.param1));
       return 0;
     }
@@ -1449,26 +1498,13 @@ unsigned int OsdOpenVG::handleOpenVGCommand(OpenVGCommand& command)
                      VG_sABGR_8888, 0, 0, info->width, info->height);
       info->decoder->freeReference(info->reference);
 
-      bool static_image = true;
-
-      if (info->lindex & 0xffffffff) static_image = false;
-
-      Message* m = new  Message();
       // We have a pictures! send a message to ourself, to switch to gui thread
+      Message* m = new Message();
       m->from = this;
       m->to = this;
       m->data = reinterpret_cast<void*>(handle);
-
-      if (!static_image)
-      {
-        m->message = Message::NEW_PICTURE;
-        m->tag = info->lindex;
-      }
-      else
-      {
-        m->message = Message::NEW_PICTURE_STATIC;
-        m->tag = info->lindex >> 32LL;
-      }
+      m->message = Message::NEW_PICTURE;
+      m->tag = reinterpret_cast<ULONG>(info->lindex);
       MessageQueue::getInstance()->postMessage(m);
 
       delete info;
@@ -1494,25 +1530,13 @@ unsigned int OsdOpenVG::handleOpenVGCommand(OpenVGCommand& command)
     {
       PictureInfo* info = const_cast<PictureInfo*>(static_cast<const PictureInfo*>(command.data));
       eglDestroyImageKHR(egl_display, info->reference);
-      bool static_image = true;
-
-      if (info->lindex & 0xffffffff) static_image = false;
 
       Message* m = new  Message();
       m->from = this;
       m->to = this;
       m->data = reinterpret_cast<void*>(info->handle);
-
-      if (!static_image)
-      {
-        m->message = Message::NEW_PICTURE;
-        m->tag = info->lindex;
-      }
-      else
-      {
-        m->message = Message::NEW_PICTURE_STATIC;
-        m->tag = info->lindex >> 32LL;
-      }
+      m->message = Message::NEW_PICTURE;
+      m->tag = reinterpret_cast<ULONG>(info->lindex);
       MessageQueue::getInstance()->postMessage(m); // inform command about new picture
 
       delete info;
@@ -1620,13 +1644,13 @@ void OsdOpenVG::createPicture(struct PictureInfo& pict_inf)
   if (pict_inf.type == PictureInfo::RGBAMemBlock)
   {
     comm.task = OVGcreateImageMemory;
-    comm.data =  new PictureInfo(pict_inf);
+    comm.data =  new PictureInfo(pict_inf);   // deleted in the commands processor
     putOpenVGCommand(comm, false);
   }
   else if (pict_inf.type == PictureInfo::EGLImage)
   {
     comm.task = OVGreadyEGLImage;
-    comm.data =  new PictureInfo(pict_inf);
+    comm.data =  new PictureInfo(pict_inf);   // deleted in the commands processor
     putOpenVGCommand(comm, false);
   }
   else
@@ -1636,7 +1660,7 @@ void OsdOpenVG::createPicture(struct PictureInfo& pict_inf)
   }
 }
 
-bool OsdOpenVG::getEGLPicture(struct OsdVector::PictureInfo& info, EGLDisplay* display)
+bool OsdOpenVG::getEGLPicture(struct PictureInfo& info, EGLDisplay* display)
 {
   struct OpenVGCommand comm;
   info.type = PictureInfo::EGLImage;
index 4ccb079f69e829ddf15ed94cc51013e7f0dbce54..84f4402437f1dd01fe86e99b477a20f9c134af6f 100644 (file)
@@ -34,6 +34,7 @@
 #include "defines.h"
 #include "osdvector.h"
 #include "videoomx.h"
+#include "messagequeue.h"
 #include "staticartwork.h"
 #ifdef PICTURE_DECODER_OMX
   //#include "imageomx.h"
@@ -79,8 +80,19 @@ class ImageOMX2;
 
 #include "eglpicturecreator.h"
 
+class OsdImageOpenVG : public OsdImageBase
+{
+  friend class OsdOpenVG;
+  private:
+    OsdImageOpenVG(VGImage vgi)
+    : vgimage(vgi) {}
+
+    VGImage getVGImage() { return vgimage; }
 
-class OsdOpenVG : public OsdVector
+    VGImage vgimage;
+};
+
+class OsdOpenVG : public OsdVector, public MessageReceiver
 #ifdef PICTURE_DECODER_OMX
   , public EGLPictureCreator
 #endif
@@ -104,10 +116,16 @@ class OsdOpenVG : public OsdVector
 
     virtual float getPixelAspect() {return aspect_correction;};
 
-    bool getEGLPicture(struct OsdVector::PictureInfo& info, EGLDisplay* display);
+    bool getEGLPicture(struct PictureInfo& info, EGLDisplay* display);
 
     void updateBackgroundColor(DrawStyle bg);
 
+    void createPicture(struct PictureInfo& pict_inf);
+
+    void processMessage(Message* m);
+
+    void garbageCollectOsdImages();
+
   protected:
 
     // OSDOVG-ROD-EXPERIMENT
@@ -118,7 +136,6 @@ class OsdOpenVG : public OsdVector
     // VectorHandleImage createJpeg(const char* fileName, int *width,int *height);
     VectorHandleImage createMonoBitmap(void* base, int width, int height);
     VectorHandleImage createImagePalette(int width, int height, const unsigned char* image_data, const unsigned int* palette_data);
-    void createPicture(struct PictureInfo& pict_inf);
     void destroyDrawStyleHandle(VectorHandle index);
     VectorHandle createDrawStyleHandle(const DrawStyle& c);
     bool getStaticImageData(unsigned int static_id, UCHAR** userdata, ULONG* length);
@@ -190,7 +207,6 @@ class OsdOpenVG : public OsdVector
     uint8_t* static_artwork_end[sa_MAX];
 
 #ifdef PICTURE_DECODER_OMX
-    //ImageOMX* imageomx;
     ImageOMX2* imageomx2;
 #endif
 };
index 990072c20f5e05fe701188953427475700fcc2ab..ab8a138f1420ba94dc7b4f5bffac808d871f1fac 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2012 Marten Richter, 2020 Chris Tallon
+    Copyright 2012 Marten Richter, 2021 Chris Tallon
 
     This file is part of VOMP.
 
     along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
 */
 
-// FIXME It doesn't seem like the LoadingIndex entries in loadindex_ref ever get deleted
-
 #include "log.h"
 #include "surfacevector.h"
-#include "vdr.h"
 #include "vdrresponsepacket.h"
 #include "control.h"
-#include "message.h"
+#include "imageloader.h"
 
 #include "osdvector.h"
 
@@ -38,27 +35,27 @@ using namespace Magick;
 
 static const char* TAG = "OsdVector";
 
-class MagickDecoder: public OsdVector::PictureDecoder
+class MagickDecoder: public PictureDecoder
 {
   public:
-    MagickDecoder(OsdVector::PictureReader* treader): OsdVector::PictureDecoder(treader) {pictInfValid = false;};
+    MagickDecoder() {}
 
     unsigned char* decodePicture(LoadingIndex index, unsigned char* buffer, unsigned int length, bool freemem);
 
-    bool getDecodedPicture( struct OsdVector::PictureInfo& pict_inf);
+    bool getDecodedPicture(struct PictureInfo& pict_inf);
 
     void freeReference(void* ref);
 
   protected:
-    OsdVector::PictureInfo pictInf;
-    bool pictInfValid;
+    PictureInfo pictInf;
+    bool pictInfValid{};
 };
 
 unsigned char* MagickDecoder::decodePicture(LoadingIndex index, unsigned char* buffer, unsigned int length, bool freemem)
 {
   if (pictInfValid) return buffer; // does support only one image at a Time;
 
-  Image magicimage;
+  Magick::Image magicimage;
   Blob* imageblob = new Blob();
   Blob myblob;
 
@@ -89,12 +86,10 @@ unsigned char* MagickDecoder::decodePicture(LoadingIndex index, unsigned char* b
   pictInf.height = magicimage.rows();
   pictInf.image = imageblob->data();
   pictInf.decoder = this;
-  pictInf.type = OsdVector::PictureInfo::RGBAMemBlock;
+  pictInf.type = PictureInfo::RGBAMemBlock;
   pictInf.lindex = index;
   pictInfValid = true;
 
-
-
   // I can handle everything, so the return value is always true
   return NULL;
 }
@@ -104,7 +99,7 @@ void MagickDecoder::freeReference(void* ref)
   delete todelete;
 }
 
-bool MagickDecoder::getDecodedPicture(struct OsdVector::PictureInfo& pict_inf)
+bool MagickDecoder::getDecodedPicture(struct PictureInfo& pict_inf)
 {
   if (!pictInfValid) return false;
 
@@ -113,23 +108,27 @@ bool MagickDecoder::getDecodedPicture(struct OsdVector::PictureInfo& pict_inf)
   return true;
 }
 
-
 #endif
 
+
+
 OsdVector::OsdVector()
 {
   logger = LogNT::getInstance();
 
   setlocale(LC_CTYPE, "C.UTF-8");
+}
+
+int OsdVector::init()
+{
 #ifdef PICTURE_DECODER_MAGICK
-  reader.addDecoder(new MagickDecoder(&reader));
+  ImageLoader::getInstance()->addDecoder(new MagickDecoder());
 #endif
-  MessageQueue::getInstance()->addReceiver(this);
+  return 1;
 }
 
 OsdVector::~OsdVector()
 {
-  MessageQueue::getInstance()->removeReceiver(this);
 }
 
 bool OsdVector::screenShot(const char* fileName)
@@ -153,7 +152,7 @@ bool OsdVector::screenShot(const char* fileName)
     }
 
     myblob.updateNoCopy(mem, length, Blob::MallocAllocator);
-    Image image(myblob, Geometry(width, height), 8, "RGBA");
+    Magick::Image image(myblob, Geometry(width, height), 8, "RGBA");
     image.write(fileName);
   }
   catch ( Exception& error_ )
@@ -198,12 +197,6 @@ int OsdVector::restore()
   drawstyleHandles_lastit_valid = drawstyleHandlesRefCounts_lastit_valid = false;
   palettepics.clear();
 
-  tvmedias.clear();
-  loadindex_ref.clear();
-  tvmedias_load.clear();
-  tvmedias_load_inv.clear();
-  tvmedias_loaded.clear();
-
   surfaces_mutex.unlock();
   return 1;
 }
@@ -258,18 +251,12 @@ void OsdVector::drawSurfaces()
     while (commands != end)
     {
       // update any images loaded in the mean time
-      if ((*commands).instr == DrawImageLoading)
+      if (commands->instr == DrawImageLoading)
       {
-        LoadingIndex loadindex = (*commands).target.loadindex;
-
-        if (tvmedias_loaded.find(loadindex) != tvmedias_loaded.end())
+        if (commands->image->isReady())
         {
-          (*commands).instr = DrawImage;
-          (*commands).target.image = tvmedias_loaded[loadindex];;
-          incImageRef((*commands).target.image);
-          removeLoadingIndexRef(loadindex);
+          commands->instr = DrawImage;
         }
-
       }
 
       // Now check if the command is on screen!
@@ -322,19 +309,13 @@ void OsdVector::updateOrAddSurface(const SurfaceVector* surf, float x, float y,
   }
 
   // update any images loaded in the mean time
-
   for (SVGCommand& command : commands)
   {
     if (command.instr == DrawImageLoading)
     {
-      LoadingIndex loadindex = command.target.loadindex;
-
-      if (tvmedias_loaded.find(loadindex) != tvmedias_loaded.end())
+      if (command.image->isReady())
       {
         command.instr = DrawImage;
-        command.target.image = tvmedias_loaded[loadindex];
-        incImageRef(command.target.image);
-        removeLoadingIndexRef(loadindex);
       }
     }
   }
@@ -378,11 +359,8 @@ void OsdVector::decrementAllRefCounts(std::vector<SVGCommand>& commands)
     if (handle != 0) // command might not have a handle
       decrementDrawStyleHandleRefCount(handle);
 
-    VectorHandleImage imageHandle = command.getImageHandle();
-    if (imageHandle) removeImageRef(imageHandle);
-
-    LoadingIndex li = command.getLoadingIndex();
-    if (li) removeLoadingIndexRef(li);
+   VectorHandleImage imageHandle = command.getImageHandle();
+   if (imageHandle) removeImageRef(imageHandle);
   }
 }
 
@@ -394,11 +372,8 @@ void OsdVector::incrementAllRefCounts(std::vector<SVGCommand>& commands)
     if (handle != 0) // command might not have a handle
       incrementDrawStyleHandleRefCount(handle);
 
-    VectorHandleImage imageHandle = command.getImageHandle();
-    if (imageHandle) incImageRef(imageHandle);
-
-    LoadingIndex li = command.getLoadingIndex();
-    if (li) incLoadingIndexRef(li);
+   VectorHandleImage imageHandle = command.getImageHandle();
+   if (imageHandle) incImageRef(imageHandle);
   }
 }
 
@@ -419,88 +394,31 @@ void OsdVector::removeImageRef(const VectorHandleImage handle)
   vhi_refcounts[handle]--;
 }
 
-int OsdVector::getLoadingIndexRef(LoadingIndex index)
-{
-  surfaces_mutex.lock();
-
-  if (loadindex_ref.find(index) == loadindex_ref.end())
-  {
-    return -1;
-  }
-  else
-  {
-    return loadindex_ref[index];
-  }
-
-  surfaces_mutex.unlock();
-}
-
-void OsdVector::incLoadingIndexRef(LoadingIndex index)
-{
-  if (loadindex_ref.find(index) == loadindex_ref.end())
-  {
-    loadindex_ref[index] = 1;
-  }
-  else
-  {
-    loadindex_ref[index]++;
-  }
-}
-
-void OsdVector::removeLoadingIndexRef(const LoadingIndex ref)
-{
-  loadindex_ref[ref]--;
-
-  if (loadindex_ref[ref] == 0)
-  {
-    //now check, if it is already loaded
-    std::map<LoadingIndex, VectorHandleImage>::iterator itty = tvmedias_loaded.find(ref);
-
-    if ( itty != tvmedias_loaded.end())
-    {
-      removeImageRef((*itty).second); // remove lock
-
-      /* Update - not this? Re-enabled. */
-
-      /*
-       * I'm not sure exactly how all this works but removing this line of code prevents
-       * reference counts in vhi_refcounts from going negative. Therefore I suspect the above
-       * line is wrong. Will test for a while.
-       */
-    }
-
-    tvmedias_loaded.erase(ref);
-    //         logger->debug(TAG, "TVMedia removeLoadIndexRef {} {:#x}",tvmedias_load.size(),ref);
-    tvmedias_load.erase(tvmedias_load_inv[ref]);
-    tvmedias_load_inv.erase(ref);
-
-    reader.invalidateLoadingIndex(ref);
-  }
-}
-
 void OsdVector::dumpImages()
 {
    // surfaces_mutex.lock();
 
-  printf("tvmedias.size = %i\n", tvmedias.size());
+//   printf("vhi_refcounts\n");
+//   // std::map<ImageIndex, int> vhi_refcounts;
+//   // ImageIndex is a VectorHandle. VectorHandle is an unsigned int
+//   for(auto& a : vhi_refcounts)
+//   {
+//     printf("ImageIndex: %u int: %i\n", a.first, a.second);
+//   }
+
+//   printf("loadingindex_ref\n");
+//   // std::map<LoadingIndex, int> loadindex_ref;
+//   // LoadingIndex is a unsigned long long
+//   for(auto& a : loadindex_ref)
+//   {
+//     printf("LoadingIndex: %llu (%llu) int: %i\n", a.first, a.first >> 32, a.second);
+//   }
 
-  printf("vhi_refcounts\n");
-  // std::map<ImageIndex, int> vhi_refcounts;
-  // ImageIndex is a VectorHandle. VectorHandle is an unsigned int
-  for(auto& a : vhi_refcounts)
-  {
-    printf("ImageIndex: %u int: %i\n", a.first, a.second);
-  }
+  // surfaces_mutex.unlock();
 
-  printf("loadingindex_ref\n");
-  // std::map<LoadingIndex, int> loadindex_ref;
-  // LoadingIndex is a unsigned long long
-  for(auto& a : loadindex_ref)
-  {
-    printf("LoadingIndex: %llu (%llu) int: %i\n", a.first, a.first >> 32, a.second);
-  }
 
-  // surfaces_mutex.unlock();
+  ImageLoader::getInstance()->dumpImages();
+  Osd::dumpImages();
 }
 
 void OsdVector::cleanupOrphanedRefs()
@@ -536,40 +454,6 @@ void OsdVector::cleanupOrphanedRefs()
        } else ++jitty;
   }*/
 
-  std::map<TVMediaInfo, VectorHandleImage>::iterator titty = tvmedias.begin();
-
-  while (titty != tvmedias.end())
-  {
-    std::map<VectorHandleImage, int>::iterator curitty = vhi_refcounts.find((*titty).second);
-    int count = (*curitty).second;
-
-    if (count == 0)
-    {
-      VectorHandleImage handle = (*curitty).first;
-      tvmedias.erase(titty++);
-      vhi_refcounts.erase(curitty);
-      destroyImageRef(handle);
-    }
-    else ++titty;
-  }
-
-
-  std::map<TVMediaInfo, LoadingIndex>::iterator litty = tvmedias_load.begin();
-
-  while (litty != tvmedias_load.end())
-  {
-    std::map<LoadingIndex, int>::iterator curitty = loadindex_ref.find((*litty).second);
-    int count = (*curitty).second;
-
-    if (count == 0)
-    {
-      tvmedias_load_inv.erase((*litty).second);
-      tvmedias_loaded.erase((*litty).second);
-      tvmedias_load.erase(litty++);
-    }
-    else ++litty;
-  }
-
   std::list<VectorHandleImage>::iterator pitty = palettepics.begin();
 
   while (pitty != palettepics.end())
@@ -602,7 +486,6 @@ void OsdVector::cleanupOrphanedRefs()
     else ++citty;
   }
 
-
   std::map<DrawStyle, VectorHandle>::iterator sitty = drawstyleHandles.begin();
 
   while (sitty != drawstyleHandles.end())
@@ -622,23 +505,10 @@ void OsdVector::cleanupOrphanedRefs()
     else ++sitty;
 
   }
-}
 
-//int OsdVector::getImageRef(VectorHandleImage handle)
-//{
-//  surfaces_mutex.lock();
-//
-//  if (vhi_refcounts.find(handle) == vhi_refcounts.end())
-//  {
-//    return -1;
-//  }
-//  else
-//  {
-//    return vhi_refcounts[handle];
-//  }
-//
-//  surfaces_mutex.unlock();
-//}
+  ImageLoader::getInstance()->garbageCollect();
+  garbageCollectOsdImages(); // Call this on self - derived object knows how to destroy them
+}
 
 void OsdVector::incrementDrawStyleHandleRefCount(VectorHandle index)
 {
@@ -740,144 +610,6 @@ void OsdVector::dumpStyles()
 }
 #endif
 
-LoadingIndex OsdVector::getTVMediaRef(TVMediaInfo& tvmedia, VectorHandleImage& handle)
-{
-  VectorHandleImage localHandle = 0;
-  LoadingIndex loadindex = 0;
-  surfaces_mutex.lock();
-
-  if (tvmedias.find(tvmedia) == tvmedias.end())   // if not found, return a loadIndex from loadTVMedia(tvmedia)
-  {
-    loadindex = loadTVMedia(tvmedia);
-  }
-  else   // if found, return a real imageIndex. incImageRef(localHandle). EXCEPT: If it's not found in vhi_refcounts (???) in which case do same as above.
-  {
-    localHandle = tvmedias[tvmedia];
-
-    if (vhi_refcounts.find(localHandle) == vhi_refcounts.end())
-    {
-      //invalid handle recreate
-      loadindex = loadTVMedia(tvmedia);
-      localHandle = 0;
-    }
-    else
-    {
-      incImageRef(localHandle);
-    }
-  }
-
-  /*tvmedias[tvmedia]=createTVMedia(tvmedia,width,height);
-  incImageRef(localHandle);*/
-  handle = localHandle;
-  surfaces_mutex.unlock();
-  return loadindex;
-}
-
-LoadingIndex OsdVector::loadTVMedia(TVMediaInfo& tvmedia)          // insert a tvmedia for loading
-{
-  LoadingIndex index = 0;
-
-  if (tvmedias_load.find(tvmedia) == tvmedias_load.end())        // if not found in tvmedias_load
-  {
-    switch (tvmedia.getType())
-    {
-      case 3:
-        index = VDR::getInstance()->loadTVMediaRecThumb(tvmedia);
-        break;
-
-      case 4:
-      {
-        index = ((long long) tvmedia.getPrimaryID()) << 32LL;
-        reader.addStaticImage(tvmedia.getPrimaryID());
-      } break;
-
-      case 5:
-        index = VDR::getInstance()->loadTVMediaEventThumb(tvmedia);
-        break;
-
-      case 6:
-        index = VDR::getInstance()->loadChannelLogo(tvmedia);
-        break;
-
-      default:
-        index = VDR::getInstance()->loadTVMedia(tvmedia);
-        break;
-    }
-
-    if (tvmedia.getType() != 4 && tvmedia.getStaticFallback() > -1)
-    {
-      reader.informFallback(index, tvmedia.getStaticFallback());
-    }
-
-    tvmedias_load[tvmedia] = index;
-    tvmedias_load_inv[index] = tvmedia;
-  }
-  else
-  {
-    index = tvmedias_load[tvmedia];
-  }
-
-  incLoadingIndexRef(index);
-
-  return index;
-}
-
-void OsdVector::informPicture(LoadingIndex index, VectorHandleImage handle)
-{
-  //Beware for thread safety
-  VectorHandleImage localHandle = 0;
-
-  logger->debug(TAG, "TVMedia Picture for load-id {:#x} arrived index {:#x}", index, handle);
-  surfaces_mutex.lock();
-  TVMediaInfo tvmedia = tvmedias_load_inv[index];
-
-  if (handle)
-  {
-    std::map<LoadingIndex, int>::iterator itty = loadindex_ref.find(index);
-    localHandle = tvmedias[tvmedia] = handle;
-    tvmedias_loaded[index] = localHandle;
-
-    if (itty == loadindex_ref.end() || (*itty).second == 0)
-    {
-      // we do not want the picture anymore . Really...
-      // fill vhi_refcounts in to not irritate the garbage collector
-      if (vhi_refcounts.find(localHandle) == vhi_refcounts.end())
-      {
-        vhi_refcounts[localHandle] = 0;
-      }
-    }
-    else
-    {
-      incImageRef(localHandle); // hold one index until all loadings refs are gone;
-    }
-  }
-
-  surfaces_mutex.unlock();
-
-  // OSDOVG-ROD-EXPERIMENT
-  logger->trace(TAG, "EXPERIMENT - call doRender");
-  doRender();
-}
-
-void OsdVector::processMessage(Message* m)
-{
-  switch(m->message)
-  {
-    case Message::NEW_PICTURE:
-    {
-      //logger->debug(TAG, "TVMedia NEW_PICTURE");
-      informPicture(m->tag, reinterpret_cast<VectorHandleImage>(m->data));
-      break;
-    }
-    case Message::NEW_PICTURE_STATIC:
-    {
-      //logger->debug(TAG, "TVMedia NEW_PICTURE {:#x} {:#x}", m->tag, m->parameter);
-      informPicture(static_cast<unsigned long long>(m->tag) << 32LL, reinterpret_cast<VectorHandleImage>(m->data));
-      break;
-    }
-  }
-}
-
 /*
 VectorHandleImage OsdVector::getJpegRef(const char* fileName, int *width,int *height)
 {
@@ -940,319 +672,3 @@ VectorHandleImage OsdVector::getImagePalette(int width, int height, const unsign
   surfaces_mutex.unlock();
   return image_handle;
 }
-
-/// PictureReader Class
-
-OsdVector::PictureReader::~PictureReader()
-{
-  threadMutex.lock();
-  if (readerThread.joinable())
-  {
-    threadReqQuit = true;
-    threadCond.notify_one();
-    threadMutex.unlock();
-    readerThread.join();
-  }
-  else
-    threadMutex.unlock();
-
-
-  decoders_lock.lock();
-  while (decoders.size())
-  {
-    PictureDecoder* dec = decoders.front();
-    decoders.pop_front();
-    delete dec;
-  }
-  decoders_lock.unlock();
-}
-
-void OsdVector::PictureReader::init()
-{
-  threadMutex.lock();
-  readerThread = std::thread( [this]
-  {
-    threadMutex.lock();
-    threadMutex.unlock();
-    threadMethod();
-  });
-  threadMutex.unlock();
-}
-
-void OsdVector::PictureReader::shutdown()
-{
-  std::unique_lock<std::mutex> lg(threadMutex);
-
-  if (readerThread.joinable())
-  {
-    threadReqQuit = true;
-    threadCond.notify_one();
-    lg.unlock();
-    readerThread.join();
-  }
-}
-
-void OsdVector::PictureReader::addDecoder(PictureDecoder* decoder)
-{
-  decoders_lock.lock();
-  decoder->init();
-  decoders.push_front(decoder);
-  decoders_lock.unlock();
-}
-
-void OsdVector::PictureReader::removeDecoder(PictureDecoder* decoder)
-{
-  decoders_lock.lock();
-  std::list<PictureDecoder*>::iterator itty = decoders.begin();
-
-  while (itty != decoders.end())
-  {
-    if ((*itty) == decoder)
-    {
-      decoders.erase(itty);
-      break;
-    }
-
-    itty++;
-  }
-
-  LogNT::getInstance()->debug("PictureReader", "removeDecoder");
-  decoder->shutdown();
-  delete decoder;
-  decoders_lock.unlock();
-}
-
-void OsdVector::PictureReader::threadMethod()
-{
-  OsdVector* osdvector = dynamic_cast<OsdVector*>(Osd::getInstance());
-//   LogNT::getInstance()->debug("PictureReader", "TVMedia Start Picture Reader");
-
-  std::unique_lock<std::mutex> ul(threadMutex); // locked
-
-  while (true)
-  {
-    threadCond.wait(ul, [this]{ return threadReqQuit || runLoop; });
-    // locked
-    if (threadReqQuit) return; // unlock
-//     LogNT::getInstance()->debug("PictureReader", "Running loop");
-    runLoop = false;
-    ul.unlock();
-
-    // unlocked while we work
-
-    bool miniRunAgain;
-    do
-    {
-      miniRunAgain = false;
-
-      PictureInfo pictinf;
-      decoders_lock.lock();
-      std::list<PictureDecoder*>::iterator itty = decoders.begin();
-
-      while (itty != decoders.end())
-      {
-        if ((*itty)->getDecodedPicture(pictinf))    // FIXME somewhere around here?, or in getDecodedPicture, try SA optimisation
-        {
-          miniRunAgain = true;
-          osdvector->createPicture(pictinf);
-        }
-        itty++;
-      }
-
-      if (processReceivedPictures()) miniRunAgain = true;
-      decoders_lock.unlock();
-
-//       LogNT::getInstance()->debug("PictureReader", "miniRunAgain = true...");
-
-    } while(miniRunAgain);
-
-    ul.lock();
-  }
-}
-
-void OsdVector::PictureReader::invalidateLoadingIndex(LoadingIndex index)
-{
-  pict_lock_incoming.lock();
-  invalid_loadindex.insert(index);
-  pict_lock_incoming.unlock();
-
-  // From conversion to std::thread
-  // The thread used to spin every 10ms, now it only waits on the cond
-  // This method does not signal the main thread, does it need to now?
-  // Doesn't look like it, but if it does get the 4 lines below
-}
-
-void OsdVector::PictureReader::informFallback(LoadingIndex index, int fallback)
-{
-  pict_lock_incoming.lock();
-  inform_fallback[index] = fallback;
-  pict_lock_incoming.unlock();
-  // Also here, does this need to signal the thread?
-}
-
-void OsdVector::PictureReader::receivePicture(VDR_ResponsePacket* vresp)
-{
-  pict_lock_incoming.lock();
-  pict_incoming.push(vresp);
-  pict_lock_incoming.unlock();
-
-  // These 4 lines to signal the thread
-  threadMutex.lock();
-  runLoop = true;
-  threadCond.notify_one();
-  threadMutex.unlock();
-}
-
-void OsdVector::PictureReader::addStaticImage(unsigned int id)
-{
-  pict_lock_incoming.lock();
-  pict_incoming_static.push(id);
-  invalid_loadindex.erase(((long long) id) << 32LL);
-  pict_lock_incoming.unlock();
-
-  threadMutex.lock();
-  runLoop = true;
-  threadCond.notify_one();
-  threadMutex.unlock();
-}
-
-#if WIN32
-  // FIXME win pragma
-  #pragma warning(disable : 4703)
-#endif
-
-bool OsdVector::PictureReader::processReceivedPictures()
-{
-  bool decoded = false;
-  bool valid = true;
-  pict_lock_incoming.lock();
-
-  if (pict_incoming.size())
-  {
-    VDR_ResponsePacket* vresp = pict_incoming.front();
-    pict_incoming.pop();
-    std::set<LoadingIndex>::iterator setpos = invalid_loadindex.find(vresp->getStreamID());
-
-    if (setpos != invalid_loadindex.end())
-    {
-      valid = false;
-      invalid_loadindex.erase(setpos);
-    }
-
-    pict_lock_incoming.unlock();
-
-    if (!valid)   // we do not want it anymore skip it;
-    {
-      delete vresp;
-      return true;
-    }
-
-    // LogNT::getInstance()->debug("PictureReader", "TVMedia Pictures arrived VDR {:#x} {} {}",
-    // vresp->getStreamID(),vresp->getUserDataLength(),vresp->getFlag());
-    bool decode = false;
-    bool freed = false;
-    UCHAR* userdata;
-    ULONG length;
-
-    if (vresp->getFlag() != 2)
-    {
-      userdata = vresp->getUserData();
-      length = vresp->getUserDataLength();
-      decode = true;
-      freed = true;
-    }
-    else
-    {
-      int fallback = -1;
-      pict_lock_incoming.lock();
-
-      if (inform_fallback.find(vresp->getStreamID()) != inform_fallback.end())
-      {
-        fallback = inform_fallback[vresp->getStreamID()];
-      }
-
-      pict_lock_incoming.unlock();
-
-      if (fallback >= 0 && ((OsdVector*)Osd::getInstance())->getStaticImageData(fallback, &userdata, &length))
-      {
-        decode = true;
-        freed = false;
-      }
-    }
-
-    if (decode)
-    {
-      std::list<PictureDecoder*>::iterator itty = decoders.begin();
-
-      while (itty != decoders.end())
-      {
-        userdata = (*itty)->decodePicture(vresp->getStreamID(), userdata, length, freed);
-
-        if (!userdata)
-        {
-          decoded = true;
-          break;
-        }
-
-        itty++;
-      }
-
-      if (!decoded && userdata && freed)
-      {
-        free(userdata);
-      }
-    }
-
-    pict_lock_incoming.lock();
-    inform_fallback.erase(vresp->getStreamID());
-    pict_lock_incoming.unlock();
-    //else  osd->informPicture(vresp->getStreamID(), 0);
-    delete vresp;
-  }
-  else if (pict_incoming_static.size())
-  {
-    unsigned int static_id = pict_incoming_static.front();
-    pict_incoming_static.pop();
-    std::set<LoadingIndex>::iterator setpos = invalid_loadindex.find(((long long) static_id) << 32LL);
-
-    if (setpos != invalid_loadindex.end())
-    {
-      valid = false;
-      invalid_loadindex.erase(setpos);
-    }
-
-    pict_lock_incoming.unlock();
-
-    if (!valid)   // we do not want it anymore skip it;
-    {
-      return true;
-    }
-
-    UCHAR* userdata;
-    ULONG length;
-
-    if (((OsdVector*)Osd::getInstance())->getStaticImageData(static_id, &userdata, &length))
-    {
-      std::list<PictureDecoder*>::iterator itty = decoders.begin();
-
-      while (itty != decoders.end())
-      {
-        if (!(*itty)->decodePicture(((long long) static_id) << 32LL, userdata, length, false))
-        {
-          decoded = true;
-          break;
-        }
-
-        itty++;
-      }
-    }
-  }
-  else
-  {
-    pict_lock_incoming.unlock();
-  }
-
-  if (pict_incoming.size() || pict_incoming_static.size()) return true;
-
-  return decoded;
-}
index 8bf73986bd3e4492d9ef0034c76659c9f84d379f..80e99cb142f001ab23007bdfe34579febe48f924 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2004-2005 Chris Tallon, 2006,2011-2012 Marten Richter
+    Copyright 2004-2005,2021 Chris Tallon, 2006,2011-2012 Marten Richter
 
     This file is part of VOMP.
 
 #include <condition_variable>
 
 #include "defines.h"
-#include "messagequeue.h"
+#include "osdvectortypes.h"
 #include "osd.h"
 #include "colour.h"
-#include "tvmedia.h"
-#include "vdr.h"
+#include "image.h"
+#include "imageloader.h"
 #include "teletextdecodervbiebu.h"
 
 class LogNT;
@@ -48,7 +48,8 @@ enum SVGCommandInstr
   DrawImage,
   DrawTTchar,
   DrawClipping,
-  DrawImageLoading
+  DrawImageLoading,
+  DrawBitmap
 };
 
 enum PathIndex
@@ -59,20 +60,6 @@ enum PathIndex
   PIPoint
 };
 
-enum Corner
-{
-  TopLeft,
-  TopRight,
-  BottomLeft,
-  BottomRight,
-  TopMiddle,
-  BottomMiddle,
-  TopLeftLimited
-};
-
-typedef VectorHandle VectorHandleImage;
-typedef unsigned long long LoadingIndex;
-
 class SVGCommand
 {
   public:
@@ -89,7 +76,7 @@ class SVGCommand
       return nc;
     };
 
-    inline static SVGCommand PaintImageLoading(LoadingIndex load_in, float ix, float iy, float iw, float ih, Corner corner = TopLeft)
+    inline static SVGCommand PaintImageLoading(Image& image, float ix, float iy, float iw, float ih, Corner corner = TopLeft)
     {
       SVGCommand nc;
       nc.instr = DrawImageLoading;
@@ -97,26 +84,43 @@ class SVGCommand
       nc.y = iy;
       nc.w = iw;
       nc.h = ih;
-      nc.target.loadindex = load_in;
       nc.handle = 0; // not valid for PaintImageLoading
       nc.corner = corner;
+
+      nc.image = image;
+
       return nc;
     };
 
-    inline static SVGCommand PaintImage(float ix, float iy, float iw, float ih, VectorHandleImage handle, VectorHandle ref, Corner corner = TopLeft)
+    inline static SVGCommand PaintBitmap(float ix, float iy, float iw, float ih,
+                                        VectorHandleImage handle, VectorHandle ref, Corner corner = TopLeft)
     {
       SVGCommand nc;
-      nc.instr = DrawImage;
+      nc.instr = DrawBitmap;
       nc.x = ix;
       nc.y = iy;
       nc.w = iw;
       nc.h = ih;
-      nc.target.image = handle;
+      nc.target.bitmap = handle;
       nc.handle = ref; // can be 0 (no handle) or can be an Drawstyle nandle
       nc.corner = corner;
       return nc;
     };
 
+    inline static SVGCommand PaintImage(float ix, float iy, float iw, float ih,
+                                        Image& image, Corner corner = TopLeft)
+    {
+      SVGCommand nc;
+      nc.instr = DrawImage;
+      nc.x = ix;
+      nc.y = iy;
+      nc.w = iw;
+      nc.h = ih;
+      nc.image = image;
+      nc.corner = corner;
+      return nc;
+    };
+
     inline static SVGCommand PaintTTchar(float ix, float iy, float iw, float ih, unsigned int ttchar_in)
     {
       SVGCommand nc;
@@ -170,21 +174,15 @@ class SVGCommand
       return ((x + w) < tx) || ((y + h) < ty) || ((tx + tw) < x) || ((ty + th) < y);
     }
 
-    VectorHandle getHandle()
+    VectorHandle getHandle()        // Is this DrawStyle references?
     {
       return handle;
     };
 
     VectorHandleImage getImageHandle()
     {
-      if (instr != DrawImage) return 0;
-      else return target.image;
-    };
-
-    LoadingIndex getLoadingIndex()
-    {
-      if (instr != DrawImageLoading) return 0;
-      else return target.loadindex;
+      if (instr != DrawBitmap) return 0;
+      else return target.bitmap;
     };
 
     SVGCommandInstr instr{DrawNoop};
@@ -195,10 +193,11 @@ class SVGCommand
     {
       PathIndex path_index;
       wchar_t textchar;
-      VectorHandleImage image;
+      VectorHandleImage bitmap;
       unsigned int ttchar;
-      LoadingIndex loadindex;
     } target;
+
+    Image image; // This would be in the union but it's a non-trivial type
 };
 
 class SurfaceVector;
@@ -211,7 +210,7 @@ struct SurfaceInfo
   float x, y, w, h;
 };
 
-class OsdVector : public Osd, public MessageReceiver
+class OsdVector : public Osd
 {
   public:
     void dumpImages();
@@ -219,6 +218,9 @@ class OsdVector : public Osd, public MessageReceiver
     OsdVector();
     virtual ~OsdVector();
 
+    // FIXME switch to bool
+    virtual int init(); // Derived classes overriding init() must call this base init()
+
     int restore();
 
     bool screenShot(const char* fileName);
@@ -243,119 +245,25 @@ class OsdVector : public Osd, public MessageReceiver
 
     // Used only by OsdVector and SurfaceVector
     void removeImageRef(const VectorHandleImage ref);
-    void removeLoadingIndexRef(const LoadingIndex ref);
     VectorHandle getDrawStyleHandle(const DrawStyle& c);
     void decrementDrawStyleHandleRefCount(VectorHandle ref);
-    LoadingIndex getTVMediaRef(TVMediaInfo& tvmedia, VectorHandleImage& handle);
     //virtual VectorHandleImage getJpegRef(const char* fileName, int *width,int *height);
     virtual VectorHandleImage getMonoBitmapRef(void* base, int width, int height);
     virtual VectorHandleImage getImagePalette(int width, int height, const unsigned char* image_data, const unsigned int* palette_data);
 
-
-    // should be only called from control thread
-    void informPicture(LoadingIndex index, VectorHandleImage handle);
-    void processMessage(Message* m);
-
-
     int charSet() {return 2;}; //UTF-8
 
-
-    class PictureDecoder;
-    struct PictureInfo
-    {
-      enum PictType
-      {
-        RGBAMemBlock,
-        EGLImage,
-        D2DBitmap
-      };
-      PictType type;
-      ULONG width;
-      ULONG height;
-      LoadingIndex lindex;
-      union
-      {
-        const void* image;
-        unsigned int handle;
-      };
-      void* reference;
-      PictureDecoder* decoder;
-    };
-
-
-    class PictureReader;
-
-    class PictureDecoder
-    {
-      public:
-        PictureDecoder(PictureReader* /*treader*/) {/* reader = treader; */};
-        virtual ~PictureDecoder() {};
-
-        // its is always guaranted, that after getDecodedPicture a call to decodePicture follows, if the return value was true;
-        virtual unsigned char* decodePicture(LoadingIndex index, unsigned char* buffer, unsigned int length, bool freemem = true) = 0;
-
-        virtual bool getDecodedPicture(struct PictureInfo& pict_inf) = 0;
-        virtual void freeReference(void* ref) = 0;
-
-        virtual void init() {};
-        virtual void shutdown() {};
-
-      protected:
-        //PictureReader* reader;
-    };
-
-    class PictureReader
-    {
-      public:
-        ~PictureReader();
-        void init();
-        void addDecoder(PictureDecoder*);
-        void removeDecoder(PictureDecoder*);
-        void shutdown();
-        bool processReceivedPictures();
-
-        // should be called from control thread
-        void receivePicture(VDR_ResponsePacket* vresp);
-
-        void addStaticImage(unsigned int id);
-        void invalidateLoadingIndex(LoadingIndex index);
-        void informFallback(LoadingIndex index, int fallback);
-
-      protected:
-
-        void threadMethod();
-        std::mutex threadMutex;
-        std::thread readerThread;
-        bool threadReqQuit{};
-        std::condition_variable threadCond;
-        bool runLoop{};
-
-        std::mutex pict_lock_incoming; //locks
-        std::mutex decoders_lock;
-        std::queue<VDR_ResponsePacket*> pict_incoming;
-        std::queue<unsigned int> pict_incoming_static;
-        std::list<PictureDecoder*> decoders;
-        std::map<LoadingIndex, int> inform_fallback;
-        std::set<LoadingIndex> invalid_loadindex;
-
-        bool picture_update;
-    };
-
-    PictureReader* getPictReader() { return &reader; };
+    virtual void createPicture(struct PictureInfo& pict_inf) = 0;
+    virtual void destroyImageRef(VectorHandleImage handle) = 0;
 
   protected:
     LogNT* logger{};
 
-    PictureReader reader;
-
     float byte_char_width[256]{};
 
-
-    virtual void destroyImageRef(VectorHandleImage handle) = 0;
     //virtual VectorHandleImage createJpeg(const char* fileName, int *width,int *height)=0;
     virtual VectorHandleImage createMonoBitmap(void* base, int width, int height) = 0;
     virtual VectorHandleImage createImagePalette(int width, int height, const unsigned char* image_data, const unsigned int* palette_data) = 0;
-    virtual void createPicture(struct PictureInfo& pict_inf) = 0;
     virtual VectorHandle createDrawStyleHandle(const DrawStyle& c) = 0;
     virtual void destroyDrawStyleHandle(VectorHandle index) = 0;
     virtual void drawSetTrans(SurfaceInfo& sc) = 0;
@@ -367,38 +275,21 @@ class OsdVector : public Osd, public MessageReceiver
     void dumpStyles();
     #endif
 
-  // See what we can make private in OsdVector
   private:
-
     // Methods that only seem to be called internally
     void incImageRef(VectorHandleImage handle);
-    void incLoadingIndexRef(LoadingIndex index);
-    int getLoadingIndexRef(LoadingIndex index);
     void decrementAllRefCounts(std::vector<SVGCommand>& commands);
     void incrementAllRefCounts(std::vector<SVGCommand>& commands);
     void cleanupOrphanedRefs();
     void incrementDrawStyleHandleRefCount(VectorHandle index);
-    LoadingIndex loadTVMedia(TVMediaInfo& tvmedia);
-
-    // int getImageRef(VectorHandleImage handle); // Not used anywhere
-
-
 
     // All the below are data structures only touched by this base class OsdVector
 
-    std::map<TVMediaInfo, VectorHandleImage> tvmedias;
     std::map<void*, VectorHandleImage> monobitmaps;
     //map<string,VectorHandleImage> jpegs;
     std::list<VectorHandleImage> palettepics;
-
     std::map<VectorHandleImage, int> vhi_refcounts;   // This appears to cover all 3 (4) of the above types
 
-    std::map<LoadingIndex, int> loadindex_ref;
-    std::map<TVMediaInfo, LoadingIndex> tvmedias_load;
-    std::map<LoadingIndex, TVMediaInfo> tvmedias_load_inv;
-    std::map<LoadingIndex, VectorHandleImage> tvmedias_loaded;
-
-
     std::map<DrawStyle, VectorHandle> drawstyleHandles;
     std::map<DrawStyle, VectorHandle>::iterator drawstyleHandles_lastit;
     bool drawstyleHandles_lastit_valid{};
@@ -410,7 +301,6 @@ class OsdVector : public Osd, public MessageReceiver
     std::list<SurfaceInfo> surfaces;
     using SurfacesIterator = std::list<SurfaceInfo>::iterator;
     std::mutex surfaces_mutex;
-
 };
 
 #endif
diff --git a/osdvectortypes.h b/osdvectortypes.h
new file mode 100644 (file)
index 0000000..18d846c
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+    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, see <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef OSDVECTORTYPES_H
+#define OSDVECTORTYPES_H
+
+#include "defines.h"
+
+typedef void* LoadingIndex;
+typedef VectorHandle VectorHandleImage;
+
+class PictureDecoder;
+struct PictureInfo
+{
+  enum PictType
+  {
+    RGBAMemBlock,
+    EGLImage,
+    D2DBitmap
+  };
+  PictType type;
+  ULONG width;
+  ULONG height;
+  LoadingIndex lindex;
+  union
+  {
+    const void* image;
+    unsigned int handle;
+  };
+  void* reference;
+  PictureDecoder* decoder;
+};
+
+enum Corner
+{
+  TopLeft,
+  TopRight,
+  BottomLeft,
+  BottomRight,
+  TopMiddle,
+  BottomMiddle,
+  TopLeftLimited
+};
+
+#endif
index ab68a1bda6100ab10d966ea8985e7783bcc67f97..e3aadd94004fa323dcf81d2ba4ccb49f8f1cfeaa 100644 (file)
 #ifndef SERIESINFO_H
 #define SERIESINFO_H
 
-#include "tvmedia.h"
 #include <string>
 
+#include "image.h"
+
 class EpisodeInfo {
 public:
        EpisodeInfo();
@@ -37,7 +38,7 @@ public:
        std::string guestStars;
        std::string overview;
        double rating;
-       TVMedia image;
+       TVMediaStruct image;
 
 
 };
@@ -65,6 +66,6 @@ public:
        TVMedias posters; // Image 2
        TVMedias banners; // Image 3
        TVMedias fanart; // Image 4
-       TVMedia seasonposter; // Image 5
+       TVMediaStruct seasonposter; // Image 5
 };
 #endif
index 561c28ed187f00668a4afd8ba8b652bc90185682..ab79e4f70ec46365473a0e093ce791c4ef7257a2 100644 (file)
--- a/surface.h
+++ b/surface.h
@@ -20,7 +20,6 @@
 #ifndef SURFACE_H
 #define SURFACE_H
 
-#include <stdio.h>
 #include "defines.h"
 #include "colour.h"
 
index a01bbad004ac9b2f2305f2a57e032989cf5d1261..ca199e5246f85f016f73eddf681b04bd5a95bb50 100644 (file)
@@ -22,6 +22,8 @@
 #include <math.h>
 #include "bitmap.h"
 #include "staticartwork.h"
+#include "imageloader.h"
+
 #include "surfacevector.h"
 
 const static char* TAG = "SurfaceVector";
@@ -30,12 +32,12 @@ SurfaceVector::SurfaceVector(OsdVector* vosd)
 {
   logger = LogNT::getInstance();
   osd = vosd;
+  imageLoader = ImageLoader::getInstance();
   commands.reserve(2048);
 }
 
 SurfaceVector::~SurfaceVector()
 {
-
   osd->removeSurface(this);
 
   for (SVGCommand& command : commands)
@@ -44,9 +46,6 @@ SurfaceVector::~SurfaceVector()
 
     VectorHandleImage handle = command.getImageHandle();
     if (handle) osd->removeImageRef(handle);
-
-    LoadingIndex li = command.getLoadingIndex();
-    if (li) osd->removeLoadingIndexRef(li);
   }
 }
 
@@ -242,9 +241,9 @@ void SurfaceVector::drawJpeg(const char* fileName, int x, int y, int* width, int
 
   if (index != sa_MAX)
   {
-    TVMediaInfo info;
-    info.setStaticArtwork(index);
-    drawTVMedia(info, x, y, *width, *height, TopLeft);
+    ImageStatic image = imageLoader->createStatic(index);
+    Image toDraw = image;
+    drawImage(toDraw, x, y, *width, *height, TopLeft);
   }
 }
 
@@ -253,32 +252,29 @@ void SurfaceVector::drawJpeg(const char *fileName,int x, int y,int *width, int *
 {
        command_mutex.lock();
        VectorHandleImage handle=osd->getJpegRef(fileName,width,height);
-       commands.push_back(SVGCommand::PaintImage(x,y,*width,*height,handle,0));
+       commands.push_back(SVGCommand::PaintImage(x,y,*width,*height,image));
        command_mutex.unlock();
 }
 */
 
-void SurfaceVector::drawTVMedia(TVMediaInfo& tvmedia, float x, float y, float  width, float height, Corner corner)
+void SurfaceVector::drawImage(Image& image, float x, float y, float  width, float height, Corner corner)
 {
   command_mutex.lock();
-  VectorHandleImage handle = 0;
-  LoadingIndex load_index = osd->getTVMediaRef(tvmedia, handle); // This is where you can get a cache hit
-
 
   if (width != 0 && height != 0)
   {
     removeCommands(x, y, width, height);
   }
 
-  if (handle)
+  if (image->isReady())
   {
-    logger->trace(TAG, "drawTVMedia: i=true, Add instr PaintImage load_index={} handle={}", load_index, handle);
-    commands.push_back(SVGCommand::PaintImage(x, y, width, height, handle, 0, corner));
+    logger->trace(TAG, "drawImage: READY, Add instr PaintImage for {}", static_cast<void*>(image.get()));
+    commands.push_back(SVGCommand::PaintImage(x, y, width, height, image, corner));
   }
   else
   {
-    logger->trace(TAG, "drawTVMedia: i=false, Add instr PaintImageLoading {} {}", load_index, handle);
-    commands.push_back(SVGCommand::PaintImageLoading(load_index, x, y, width, height, corner));
+    logger->trace(TAG, "drawImage: NOT_READY, Add instr PaintImageLoading {} LI {}", static_cast<void*>(image.get()), reinterpret_cast<void*>(image.get()));
+    commands.push_back(SVGCommand::PaintImageLoading(image, x, y, width, height, corner));
   }
 
   command_mutex.unlock();
@@ -299,7 +295,7 @@ int SurfaceVector::create(UINT width, UINT height)
 }
 void SurfaceVector::display()
 {
-  //nothing this is really mvp specific  // FIXME remove?
+  //nothing this is really mvp specific  // FIXME remove? -- yes, only surfacedirectfb has some commented out code in display()
 }
 
 int SurfaceVector::fillblt(int x, int y, int width, int height, const DrawStyle& c)
@@ -354,7 +350,7 @@ void SurfaceVector::drawBitmap(int x, int y, const Bitmap& bm, const DisplayRegi
   ty *= scaley;
   tw *= scalex;
   th *= scaley;
-  SVGCommand temp = SVGCommand::PaintImage(tx, ty, tw, th, handle, 0);
+  SVGCommand temp = SVGCommand::PaintBitmap(tx, ty, tw, th, handle, 0);
   removeCommands(tx, ty, tw, th);
   commands.push_back(temp);
   command_mutex.unlock();
@@ -376,7 +372,7 @@ void SurfaceVector::drawMonoBitmap(UCHAR* base, int dx, int dy, unsigned int hei
   VectorHandleImage handle = osd->getMonoBitmapRef(base, width, height);
   VectorHandle ref = osd->getDrawStyleHandle(nextColour);
   removeCommands(dx, dy, width, height);
-  commands.push_back(SVGCommand::PaintImage(dx, dy, height, width, handle, ref)); // FIXME BUG height and width wrong way around?
+  commands.push_back(SVGCommand::PaintBitmap(dx, dy, height, width, handle, ref)); // FIXME BUG height and width wrong way around?
   command_mutex.unlock();
 }
 
@@ -401,14 +397,10 @@ int SurfaceVector::removeCommands(float x, float y, float width, float height)
       //Log::getInstance()->log("OSD", Log::DEBUG, "Remove command %d %g %g %g %g %d %d",(*itty).instr,
       //(*itty).x,(*itty).y,(*itty).w,(*itty).h,(*itty).handle,(*itty).target.image);
       osd->decrementDrawStyleHandleRefCount((*itty).getHandle()); // We remove the Style reference, so that osd can free stuff // FIXME BUG BUG BUG
-      VectorHandleImage handle = (*itty).getImageHandle();
 
+      VectorHandleImage handle = (*itty).getImageHandle();
       if (handle) osd->removeImageRef(handle);
 
-      LoadingIndex li = (*itty).getLoadingIndex();
-
-      if (li) osd->removeLoadingIndexRef(li);
-
       if (!remove)
       {
         remstart = itty;
index 57f9cfaac2bbf30b53a78fb0c56f85434cd45a70..17b4ade66fae579c435a829838d4fc1af62ebadd 100644 (file)
@@ -25,6 +25,8 @@
 
 #include "surface.h"
 #include "osdvector.h"
+#include "image.h"
+#include "imageloader.h"
 
 class SurfaceVector : public Surface
 {
@@ -43,7 +45,7 @@ class SurfaceVector : public Surface
     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);
+    void drawImage(Image& image, 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);
 
@@ -69,6 +71,7 @@ class SurfaceVector : public Surface
 
   protected:
     LogNT* logger{};
+    ImageLoader* imageLoader{};
 
     int removeCommands(float x, float y, float width, float height);
 
index 857388d78f775eb7f2d08f14dc1fefbc39f23755..603325de64239f1590247a70765de35a41dfa2d2 100644 (file)
--- a/tbboxx.cc
+++ b/tbboxx.cc
@@ -1,5 +1,5 @@
 /*
-    Copyright 2007 Chris Tallon
+    Copyright 2007-2021 Chris Tallon
 
     This file is part of VOMP.
 
@@ -14,8 +14,7 @@
     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.
+    along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
 */
 
 #include "tbboxx.h"
@@ -26,13 +25,11 @@ TBBoxx::TBBoxx()
   borderOn = 0;
   titleText = NULL;
   titleBarTextWidth = 0;
-  icon = NULL;
 }
 
 TBBoxx::~TBBoxx()
 {
   if (titleText) delete[] titleText;
-  if (icon) delete icon;
 }
 
 void TBBoxx::setTitleText(const char* takeText, int width)
@@ -60,9 +57,10 @@ void TBBoxx::draw()
     rectangle(0, 0, area.w, 30, titleBarColour);
     int xpos = 5;
 #ifdef GRADIENT_DRAWING
-    if (icon) {
-       drawTVMedia(*icon, static_cast<float>(xpos), 0,30,30,TopLeftLimited);
-       xpos+=5+30;
+    if (tbIcon)
+    {
+      drawImage(tbIcon, static_cast<float>(xpos), 0, 30, 30, TopLeftLimited);
+      xpos += 5 + 30;
     }
 #endif
     if (titleText)
@@ -80,10 +78,9 @@ void TBBoxx::setTitleBarColour(const DrawStyle& Tcolour)
   titleBarColour = Tcolour;
 }
 
-void TBBoxx::setTitleBarIcon(TVMediaInfo * ticon)
+void TBBoxx::setTitleBarIcon(Image& ticon)
 {
-       if (icon) delete icon;
-       icon = ticon;
+  tbIcon = ticon;
 }
 
 void TBBoxx::setTitleBarOn(UCHAR on)
index 73edb1df872dba4a775bf0096714ea1c951abda8..8c82fe0682f3b41f950b58bd1c792d67d6a75ec1 100644 (file)
--- a/tbboxx.h
+++ b/tbboxx.h
@@ -14,8 +14,7 @@
     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.
+    along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
 */
 
 #ifndef TBBOXX_H
@@ -26,6 +25,7 @@
 #include "boxx.h"
 #include "defines.h"
 #include "colour.h"
+#include "image.h"
 
 // Note! Do not use setBackgroundColour on a TBBoxx or anything derived from it -
 // it will screw up the display
@@ -42,18 +42,18 @@ class TBBoxx : public Boxx
     void setTitleText(const char* title, int width=0);
 
     void setTitleBarColour(const DrawStyle& colour);
-    void setTitleBarIcon(TVMediaInfo * icon);
+    void setTitleBarIcon(Image& icon);
     char* getTitleText() { return titleText; };
 
   private:
     char* titleText;
     UCHAR borderOn;
     int titleBarTextWidth;
+    Image tbIcon;
 
   protected:
     DrawStyle titleBarColour;
     UCHAR titleBarOn;
-    TVMediaInfo *icon;
 };
 
 #endif
diff --git a/tvmedia.cc b/tvmedia.cc
deleted file mode 100644 (file)
index fd6968e..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
-    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
-       primary_name="";
-       static_fallback = -1; // fallback if not available
-}
-
-
-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
-       primary_name=info.primary_name;
-       static_fallback = info.static_fallback;
-
-}
-
-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
-}
-
-void TVMediaInfo::setPosterThumb(const char* recname)
-{
-       type=3;
-       primary_name=recname;
-}
-
-void TVMediaInfo::setStaticArtwork(int id)
-{
-       type=4;
-       primary_id=id;
-}
-
-void TVMediaInfo::setStaticFallback(int id)
-{
-       static_fallback=id;
-}
-
-
-
-void TVMediaInfo::setPosterThumb(int channel, int eventid)
-{
-       type=5;
-       primary_id=channel;
-       secondary_id=eventid;
-}
-
-void TVMediaInfo::setChannelLogo(int channel)
-{
-       type=6;
-       primary_id=channel;
-}
-
-
diff --git a/tvmedia.h b/tvmedia.h
deleted file mode 100644 (file)
index 5349e73..0000000
--- a/tvmedia.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
-    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 TVMEDIA_H
-#define TVMEDIA_H
-
-#include "defines.h"
-#include <vector>
-#include <string>
-
-class MovieInfo;
-class SeriesInfo;
-
-
-class TVMediaInfo
-{
-friend class VDR;
-public:
-       TVMediaInfo();
-       TVMediaInfo(const TVMediaInfo& info);
-
-       friend bool operator<(const TVMediaInfo& rhs, const TVMediaInfo& lhs);
-       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);
-       void setPosterThumb(const char* recname);
-       void setPosterThumb(int channel, int eventid);
-       void setChannelLogo(int channel);
-       void setStaticArtwork(int artwork);
-       void setStaticFallback(int fallback);
-       int getType() {return type;};
-       int getPrimaryID() {return primary_id;};
-       int getSecondaryID() {return secondary_id;};
-       int getStaticFallback() {return static_fallback;};
-
-private:
-       int type; // 1 movie or 2 series or 3 unknown recording or 4 static artwork
-       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
-       std::string primary_name;
-       int static_fallback; // id of static replacement in case resource is not available
-};
-
-struct TVMedia
-{
-       unsigned int width{};
-       unsigned int height{};
-
-       // no filename, file handling is only on the server
-       TVMediaInfo info;
-
-};
-
-typedef std::vector<TVMedia> TVMedias;
-
-struct Actor
-{
-       std::string name;
-       std::string role;
-       TVMedia thumb;
-};
-
-typedef std::vector<Actor> Actors;
-
-
-inline bool operator<(const TVMediaInfo& rhs, const TVMediaInfo& lhs)
-{
-       if (rhs.type==lhs.type) {
-               if (rhs.primary_id==lhs.primary_id) {
-                       if (rhs.static_fallback==lhs.static_fallback) {
-                               if (rhs.secondary_id==lhs.secondary_id) {
-                                       if (rhs.type_pict==lhs.type_pict) {
-                                               if (rhs.container==lhs.container) {
-                                                       if (rhs.primary_name== lhs.primary_name) {
-                                                               return rhs.container_member < lhs.container_member;
-                                                       } else {
-                                                               return rhs.primary_name < lhs.primary_name;
-                                                       }
-                                               } else {
-                                                       return rhs.container<lhs.container;
-                                               }
-
-
-                                       } else {
-                                               return rhs.type_pict<lhs.type_pict;
-                                       }
-
-                               } else {
-                                       return rhs.secondary_id<lhs.secondary_id;
-                               }
-                       } else {
-                               return rhs.static_fallback<lhs.static_fallback;
-                       }
-
-               } else {
-                       return rhs.primary_id<lhs.primary_id;
-               }
-
-
-       } else {
-               return rhs.type < lhs.type;
-       }
-}
-
-inline bool operator==(const TVMediaInfo& rhs, const TVMediaInfo& lhs)
-{
-       return (rhs.type==lhs.type)  && (rhs.primary_id==lhs.primary_id) && (rhs.static_fallback==lhs.static_fallback)  &&
-            (rhs.secondary_id==lhs.secondary_id) && (rhs.type_pict==lhs.type_pict) &&
-               (rhs.container==lhs.container)  && (rhs.primary_name== lhs.primary_name)
-                                               && (rhs.container_member == lhs.container_member);
-}
-
-#endif
index 3061fd3129072927fcd2ebf69313f6e7b8f9fa5b..5f9dfdb6291c2c75f1e16bd68b41c24759f6787e 100644 (file)
@@ -31,6 +31,8 @@
 #include "boxstack.h"
 #include "vchannelselect.h"
 #include "staticartwork.h"
+#include "image.h"
+#include "imageloader.h"
 
 static const char* TAG = "VChannelList";
 
@@ -50,20 +52,20 @@ VChannelList::VChannelList(ULONG ttype)
 
   setTitleBarOn(1);
 
+  imageLoader = ImageLoader::getInstance();
+
   type = ttype;
   if (type == VDR::VIDEO)
   {
     setTitleText(tr("Channels"));
-    TVMediaInfo *info= new TVMediaInfo();
-    info->setStaticArtwork(sa_tv);
-    setTitleBarIcon(info);
+    Image icon = imageLoader->createStatic(sa_tv);
+    setTitleBarIcon(icon);
   }
   else if (type == VDR::RADIO)
   {
     setTitleText(tr("Radio Stations"));
-    TVMediaInfo *info= new TVMediaInfo();
-    info->setStaticArtwork(sa_radio);
-    setTitleBarIcon(info);
+    Image icon = imageLoader->createStatic(sa_radio);
+    setTitleBarIcon(icon);
   }
 
   setTitleBarColour(DrawStyle::TITLEBARBACKGROUND);
@@ -97,17 +99,20 @@ void VChannelList::setList(std::shared_ptr<ChannelList> tlist)
     for (UINT i = 0; i < chanList->size(); i++)
     {
       chan = (*chanList)[i];
-      //sprintf(str, "%lu\t%s", chan->number, chan->name);
       std::ostringstream os;
       os << chan->number << '\t' << chan->name;
-      TVMediaInfo *info=NULL;
-      if (osdv) {
-         info= new TVMediaInfo();
-         info->setChannelLogo((*chanList)[i]->number);
-         if (type == VDR::VIDEO) info->setStaticFallback(sa_tv);
-         else info->setStaticFallback(sa_radio);
+      if (osdv)
+      {
+        int sa_id = -1;
+        if (type == VDR::VIDEO) sa_id = sa_tv;
+        else if (type == VDR::RADIO) sa_id = sa_radio;
+        Image icon = imageLoader->createChannelLogo((*chanList)[i]->number, sa_id);
+
+        chan->index = sl.addOption(os.str(), chan, first, icon);
       }
-      chan->index = sl.addOption(os.str(), chan, first, info);
+      else
+        chan->index = sl.addOption(os.str(), chan, first);
+
       first = 0;
     }
   }
index 6074801c7e3eaa3087884ff6d3f904516c84521b..c5775706bf7d09585ed24324b8f089a97cf6206c 100644 (file)
@@ -34,6 +34,7 @@
 
 class Channel;
 class BoxStack;
+class ImageLoader;
 
 class VChannelList : public TBBoxx, public MessageReceiver
 {
@@ -48,6 +49,7 @@ class VChannelList : public TBBoxx, public MessageReceiver
     void draw();
 
   private:
+    ImageLoader* imageLoader;
     BoxStack* boxstack;
     std::shared_ptr<ChannelList> chanList;
 
diff --git a/vdr.cc b/vdr.cc
index 9705686cf9ec49fcdd551f5c5284fb61732cab39..fd711e5ef5d613d06616cb09b8b7dd6252a0742e 100644 (file)
--- a/vdr.cc
+++ b/vdr.cc
@@ -37,7 +37,8 @@
 #include "movieinfo.h"
 #include "seriesinfo.h"
 #include "osdvector.h"
-#include "tvmedia.h"
+#include "image.h"
+#include "imageloader.h"
 
 #include "vdr.h"
 
@@ -496,7 +497,7 @@ bool VDR::ed_cb_find(EDReceiver* edr, void* userTag)
   // Is vresp for vdrpr ?
   
   ULONG packetChannel = vresp->getChannelID();
-  //logger->debug(TAG, "TVMedia debug {} {} {:#x}", vdrpr->receiverChannel,packetChannel,vdrpr);
+  //logger->debug(TAG, "Image debug {} {} {:#x}", vdrpr->receiverChannel,packetChannel,vdrpr);
   if (vdrpr->receiverChannel != packetChannel) return false;
 
   if (packetChannel == CHANNEL_REQUEST_RESPONSE)
@@ -609,16 +610,17 @@ void VDR_PacketReceiver::call(void* userTag, bool& r_deregisterEDR, bool& r_wake
   }
   else if (receiverChannel == VDR::CHANNEL_TVMEDIA)
   {
-    // It's TVMedia
+    // It's Image
     // Pass off the vresp object to OSDVector
     // This used to return true which would signal the cond (wake the thread)
     // but am going to try setting this to false because I don't know that there is a thread to signal
     // delete the EDR. It's made once per media requested and wasn't owned/deleted by anything before
 
     VDR_ResponsePacket* vresp = reinterpret_cast<VDR_ResponsePacket*>(userTag);
-    LogNT::getInstance()->debug(TAG, "TVMedia Pictures arrived VDR {:#x}", vresp->getStreamID());
-    OsdVector *osd=dynamic_cast<OsdVector*>(Osd::getInstance());
-    if (osd) osd->getPictReader()->receivePicture(vresp);
+    LogNT::getInstance()->debug(TAG, "Image Pictures arrived VDR {:#x}", vresp->getStreamID());
+    ImageLoader::getInstance()->downloadDone(vresp);
+    //OsdVector *osd=dynamic_cast<OsdVector*>(Osd::getInstance());
+    //if (osd) osd->getPictReader()->receivePicture(vresp);
     // else delete vresp; //nonsense // only rpi does CHANNEL_TVMEDIA, rpi has osdvector. therefore, can't get here.
 
     r_deregisterEDR = true;
@@ -1689,249 +1691,288 @@ void VDR::getScraperEventType(UINT channelid, UINT eventid, int & movieID,
 
 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);
-       }
+  ImageLoader* imageLoader = ImageLoader::getInstance();
 
+  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;
+
+  ImageGeneric imageGeneric1 = imageLoader->createGeneric();
+  movieinf->poster.image = imageGeneric1;
+
+  ImageGeneric imageGeneric2 = imageLoader->createGeneric();
+  movieinf->fanart.image = imageGeneric2;
+
+  ImageGeneric imageGeneric3 = imageLoader->createGeneric();
+  movieinf->collectionPoster.image = imageGeneric3;
+
+  ImageGeneric imageGeneric4 = imageLoader->createGeneric();
+  movieinf->collectionFanart.image = imageGeneric4;
+
+  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();
+  imageGeneric1->setMovieInfo(movieinf);
+  imageGeneric1->setElement(0,0);
+  movieinf->fanart.width = vresp->extractULONG();
+  movieinf->fanart.height = vresp->extractULONG();
+  imageGeneric2->setMovieInfo(movieinf);
+  imageGeneric2->setElement(1,0);
+  movieinf->collectionPoster.width = vresp->extractULONG();
+  movieinf->collectionPoster.height = vresp->extractULONG();
+  imageGeneric3->setMovieInfo(movieinf);
+  imageGeneric3->setElement(2,0);
+  movieinf->collectionFanart.width = vresp->extractULONG();
+  movieinf->collectionFanart.height = vresp->extractULONG();
+  imageGeneric4->setMovieInfo(movieinf);
+  imageGeneric4->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;
+    ImageGeneric newActImageGeneric = imageLoader->createGeneric();
+    new_act.thumb.image = newActImageGeneric;
+
+    new_act.name =  vresp->extractStdString();
+    new_act.role =  vresp->extractStdString();
+    new_act.thumb.width = vresp->extractULONG();
+    new_act.thumb.height = vresp->extractULONG();
+    newActImageGeneric->setMovieInfo(movieinf);
+    newActImageGeneric->setElement(4,acty);
+    movieinf->actors.push_back(new_act);
+    imageLoader->ensureLoaded(newActImageGeneric);
+  }
 
-       delete vresp;
-       return movieinf;
+  imageLoader->ensureLoaded(imageGeneric1);
+  imageLoader->ensureLoaded(imageGeneric2);
+  imageLoader->ensureLoaded(imageGeneric3);
+  imageLoader->ensureLoaded(imageGeneric4);
 
+  delete vresp;
+  return movieinf;
 }
 
-SeriesInfo *VDR::getScraperSeriesInfo(int seriesID, int episodeID)
+SeriesInfoVDR::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;
+  ImageLoader* imageLoader = ImageLoader::getInstance();
 
-       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);
-       }
+  VDR_RequestPacket vrp;
+  if (!vrp.init(VDR_GETSCRAPERSERIESINFO, false, 0)) return NULL;
+  if (!vrp.addULONG(seriesID)) return NULL;
+  if (!vrp.addULONG(episodeID)) return NULL;
 
-       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);
+  VDR_ResponsePacket* vresp = RequestResponse(&vrp);
+  if (vresp->noResponse()) { delete vresp; return 0; }
+  SeriesInfo* seriesinf = new SeriesInfo();
+
+  ImageGeneric imageGeneric1 = imageLoader->createGeneric();
+  Image imageBase1 = imageGeneric1;
+  seriesinf->episode.image.image = imageBase1;
+
+  ImageGeneric imageGeneric2 = imageLoader->createGeneric();
+  Image imageBase2 = imageGeneric2;
+  seriesinf->seasonposter.image = imageBase2;
+
+  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();
+  imageGeneric1->setSeriesInfo(seriesinf);
+  imageGeneric1->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();
+
+      ImageGeneric actorIG = imageLoader->createGeneric();
+      new_act.thumb.image = actorIG;
+      actorIG->setSeriesInfo(seriesinf);
+      actorIG->setElement(1,acty);
+      seriesinf->actors.push_back(new_act);
+
+      imageLoader->ensureLoaded(actorIG);
+  }
+  ULONG num_posters =  vresp->extractULONG();
+  for (ULONG medias = 0; medias < num_posters; medias++ ) {
+      TVMediaStruct media;
+      ImageGeneric mediaIG = imageLoader->createGeneric();
+      media.image = mediaIG;
+      mediaIG->setSeriesInfo(seriesinf);
+      mediaIG->setElement(2, medias);
+      media.width =  vresp->extractULONG();
+      media.height = vresp->extractULONG();
+      seriesinf->posters.push_back(media);
+
+      imageLoader->ensureLoaded(mediaIG);
+  }
 
-       delete vresp;
-       return seriesinf;
+  ULONG num_banners =  vresp->extractULONG();
+  for (ULONG medias = 0; medias < num_banners; medias++ ) {
+      TVMediaStruct media;
+      ImageGeneric mediaIG = imageLoader->createGeneric();
+      media.image = mediaIG;
+      mediaIG->setSeriesInfo(seriesinf);
+      mediaIG->setElement(3,medias);
+      media.width =  vresp->extractULONG();
+      media.height = vresp->extractULONG();
+      seriesinf->banners.push_back(media);
+
+      imageLoader->ensureLoaded(mediaIG);
+  }
+  ULONG num_fanarts =  vresp->extractULONG();
+  for (ULONG medias = 0; medias < num_fanarts; medias++ ) {
+      TVMediaStruct media;
+      ImageGeneric mediaIG = imageLoader->createGeneric();
+      media.image = mediaIG;
+      mediaIG->setSeriesInfo(seriesinf);
+      mediaIG->setElement(4,medias);
+      media.width =  vresp->extractULONG();
+      media.height = vresp->extractULONG();
+      seriesinf->fanart.push_back(media);
+
+      imageLoader->ensureLoaded(mediaIG);
+  }
+  seriesinf->seasonposter.width = vresp->extractULONG();
+  seriesinf->seasonposter.height = vresp->extractULONG();
+  imageGeneric2->setSeriesInfo(seriesinf);
+  imageGeneric2->setElement(5,0);
 
+  imageLoader->ensureLoaded(imageGeneric1);
+  imageLoader->ensureLoaded(imageGeneric2);
+
+  delete vresp;
+  return seriesinf;
 }
 
-ULONG VDR::loadTVMedia(TVMediaInfo& tvmedia)
+bool VDR::loadImageGeneric(ImageGeneric& image)
 {
-       VDR_RequestPacket vrp;
-
-       if (!vrp.init(VDR_LOADTVMEDIA, false, 0)) return ULONG_MAX;
-       if (!vrp.addULONG(tvmedia.type)) return ULONG_MAX;
-       if (!vrp.addULONG(tvmedia.primary_id)) return ULONG_MAX;
-       if (!vrp.addULONG(tvmedia.secondary_id)) return ULONG_MAX;
-       if (!vrp.addULONG(tvmedia.type_pict)) return ULONG_MAX;
-       if (!vrp.addULONG(tvmedia.container)) return ULONG_MAX;
-       if (!vrp.addULONG(tvmedia.container_member)) return ULONG_MAX;
-/*     logger->debug(TAG, "TVMedia with ID {} {}; {} {} {} {};{}",
-                       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_RequestPacket vrp;
 
-       VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-       //if (vresp->noResponse()) { delete vresp; return ULONG_MAX; }
-       delete vresp;
+  if (!vrp.init(VDR_LOADTVMEDIA, false, 0)) return false;
+  if (!vrp.addULONG(image->getType())) return false;
+  if (!vrp.addULONG(image->primary_id)) return false;
+  if (!vrp.addULONG(image->secondary_id)) return false;
+  if (!vrp.addULONG(image->type_pict)) return false;
+  if (!vrp.addULONG(image->container)) return false;
+  if (!vrp.addULONG(image->container_member)) return false;
+  logger->debug(TAG, "Image with ID {} {}; {} {} {} {};{}",
+          image->primary_id,image->secondary_id,image->type,image->type_pict,
+          image->container,image->container_member,vrp.getSerial());
+
+// FIXME - ImageLoader should register itself as a permenant stream receiver instead of making temporary ones like this
+  VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
+  vdrpr->receiverChannel = VDR::CHANNEL_TVMEDIA;
+  vdrpr->streamID = vrp.getSerial();
+  vdrpr->streamReceiver = NULL;
+  edRegister(vdrpr);
 
-       return vrp.getSerial();
+  VDR_ResponsePacket* vresp = RequestResponse(&vrp);
+  bool ret = !vresp->noResponse();
+  delete vresp;
+  return ret;
 }
 
-ULONG VDR::loadTVMediaRecThumb(TVMediaInfo & media)
+bool VDR::loadImageRecThumb(ImageRecThumb& image) // FIXME convert return to bool
 {
+  VDR_RequestPacket vrp;
 
-       VDR_RequestPacket vrp;
-
-       if (!vrp.init(VDR_LOADTVMEDIARECTHUMB, false, 0)) return ULONG_MAX;
-       if (!vrp.addString(media.primary_name.c_str())) return ULONG_MAX;
-
-       VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
-       vdrpr->receiverChannel = VDR::CHANNEL_TVMEDIA;
-       vdrpr->streamID = vrp.getSerial();
-       vdrpr->streamReceiver = NULL;
-       edRegister(vdrpr);
-
+  if (!vrp.init(VDR_LOADTVMEDIARECTHUMB, false, 0)) return false;
+  if (!vrp.addString(image->getFileName())) return false;
+  image->setServerLoadingRef(vrp.getSerial());
 
-       VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-       //if (vresp->noResponse()) { delete vresp; return ULONG_MAX; }
-       delete vresp;
+  VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
+  vdrpr->receiverChannel = VDR::CHANNEL_TVMEDIA;
+  vdrpr->streamID = vrp.getSerial();
+  vdrpr->streamReceiver = NULL;
+  edRegister(vdrpr);
 
-       return vrp.getSerial();
+  VDR_ResponsePacket* vresp = RequestResponse(&vrp);
+  bool ret = !vresp->noResponse();
+  delete vresp;
+  return ret;
 }
 
-ULONG VDR::loadTVMediaEventThumb(TVMediaInfo & media)
+bool VDR::loadImageEventThumb(ImageEventThumb& image)
 {
+  VDR_RequestPacket vrp;
 
-       VDR_RequestPacket vrp;
-
-       if (!vrp.init(VDR_LOADTVMEDIAEVENTTHUMB, false, 0)) return ULONG_MAX;
-       if (!vrp.addULONG(media.primary_id)) return ULONG_MAX;
-       if (!vrp.addULONG(media.secondary_id)) return ULONG_MAX;
-
-       VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
-       vdrpr->receiverChannel = VDR::CHANNEL_TVMEDIA;
-       vdrpr->streamID = vrp.getSerial();
-       vdrpr->streamReceiver = NULL;
-       edRegister(vdrpr);
-
+  if (!vrp.init(VDR_LOADTVMEDIAEVENTTHUMB, false, 0)) return false;
+  if (!vrp.addULONG(image->getChannel())) return false;
+  if (!vrp.addULONG(image->getEvent())) return false;
+  image->setServerLoadingRef(vrp.getSerial());
 
-       VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-       //if (vresp->noResponse()) { delete vresp; return ULONG_MAX; }
-       delete vresp;
+  VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
+  vdrpr->receiverChannel = VDR::CHANNEL_TVMEDIA;
+  vdrpr->streamID = vrp.getSerial();
+  vdrpr->streamReceiver = NULL;
+  edRegister(vdrpr);
 
-       return vrp.getSerial();
+  VDR_ResponsePacket* vresp = RequestResponse(&vrp);
+  bool ret = !vresp->noResponse();
+  delete vresp;
+  return ret;
 }
 
-ULONG VDR::loadChannelLogo(TVMediaInfo & media)
+bool VDR::loadImageChannelLogo(ImageChannelLogo& image)
 {
+  VDR_RequestPacket vrp;
 
-       VDR_RequestPacket vrp;
-
-       if (!vrp.init(VDR_LOADCHANNELLOGO, false, 0)) return ULONG_MAX;
-       if (!vrp.addULONG(media.primary_id)) return ULONG_MAX;
-
-       VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
-       vdrpr->receiverChannel = VDR::CHANNEL_TVMEDIA;
-       vdrpr->streamID = vrp.getSerial();
-       vdrpr->streamReceiver = NULL;
-       edRegister(vdrpr);
-
+  if (!vrp.init(VDR_LOADCHANNELLOGO, false, 0)) return false;
+  if (!vrp.addULONG(image->getChannelID())) return false;
+  image->setServerLoadingRef(vrp.getSerial());
 
-       VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-       //if (vresp->noResponse()) { delete vresp; return ULONG_MAX; }
-       delete vresp;
-
-//     logger->debug(TAG, "TVMedia Channel Logo {} {:#x}",
-//                             media.primary_id,vrp.getSerial());
+  VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
+  vdrpr->receiverChannel = VDR::CHANNEL_TVMEDIA;
+  vdrpr->streamID = vrp.getSerial();
+  vdrpr->streamReceiver = NULL;
+  edRegister(vdrpr);
 
-       return vrp.getSerial();
+  VDR_ResponsePacket* vresp = RequestResponse(&vrp);
+  bool ret = !vresp->noResponse();
+  delete vresp;
+  return ret;
 }
diff --git a/vdr.h b/vdr.h
index adb6178fe73c9558f034a0a919522ebe7a63865b..ef29c67674c76079ed10aa1fcec9830ae8a1f0b7 100644 (file)
--- a/vdr.h
+++ b/vdr.h
@@ -44,6 +44,7 @@
 #include "i18n.h"
 #include "control.h"
 #include "tcp.h"
+#include "image.h"
 
 class RecInfo;
 class Event;
@@ -55,7 +56,6 @@ class SerializeBuffer;
 #endif
 class MovieInfo;
 class SeriesInfo;
-class TVMediaInfo;
 
 typedef std::vector<Event*> EventList;
 typedef std::vector<Channel*> ChannelList;
@@ -201,14 +201,13 @@ public ExternLogger
     //TV Scraper support
     void getScraperEventType(char * fileName, int & movieID, int & seriesID, int & episodeID);
     void getScraperEventType(UINT eventid, UINT channelid, int & movieID, int & seriesID, int & episodeID, int & epgImage);
-    MovieInfo *getScraperMovieInfo(int movieID);
-    SeriesInfo *getScraperSeriesInfo(int seriesID, int episodeID);
-    ULONG loadTVMedia(TVMediaInfo& tvmedia);
-    ULONG loadTVMediaRecThumb(TVMediaInfo& tvmedia);
-    ULONG loadTVMediaEventThumb(TVMediaInfo& tvmedia);
-    ULONG loadChannelLogo(TVMediaInfo& tvmedia);
-    void invalidateTVMedia(ULONG loadindex);
+    MovieInfo* getScraperMovieInfo(int movieID);
+    SeriesInfo* getScraperSeriesInfo(int seriesID, int episodeID);
 
+    bool loadImageGeneric(ImageGeneric& image);
+    bool loadImageRecThumb(ImageRecThumb& image);
+    bool loadImageEventThumb(ImageEventThumb& image);
+    bool loadImageChannelLogo(ImageChannelLogo& image);
 
     I18n::lang_code_list getLanguageList();
     int           getLanguageContent(const std::string code, I18n::trans_table&);
index 83713c1290d8be5c90573c0997bbb24c796012d0..aaf8aaae548be022f44533966d7c33387a1e9e50 100644 (file)
     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
 
-// FIXME
-
-#include "vdrresponsepacket.h"
-
+#include "util.h"
 #include "vdr.h"
 
-#include "util.h"
+#include "vdrresponsepacket.h"
 
 VDR_ResponsePacket::VDR_ResponsePacket()
 {
diff --git a/vepg.cc b/vepg.cc
index f0a11a8cfebf6fa10629599278f8ae5b395b16f0..150faa269c915d3e034981c15ae7c97261bc7b89 100644 (file)
--- a/vepg.cc
+++ b/vepg.cc
@@ -43,6 +43,7 @@
 #include "channel.h"
 #include "i18n.h"
 #include "log.h"
+#include "osd.h"
 
 #include "vepg.h"
 
index dea8b6bb11ae3f1fd18ce307c363e0fc4ef9dc2e..3b81ebf78732cdf64768a998b79ff276c72e507a 100644 (file)
@@ -37,6 +37,8 @@
 #include "vepgsettimer.h"
 #include "vepg.h"
 #include "staticartwork.h"
+#include "image.h"
+#include "imageloader.h"
 
 #include "vepglistadvanced.h"
 
@@ -58,10 +60,8 @@ VEpgListAdvanced::VEpgListAdvanced(MessageReceiver* tvideolive, std::shared_ptr<
 
   setTitleBarOn(1);
   setTitleBarColour(DrawStyle::TITLEBARBACKGROUND);
-  TVMediaInfo* info = new TVMediaInfo();
-  info->setChannelLogo(channelNumber);
-  info->setStaticFallback(sa_tv);
-  setTitleBarIcon(info);
+  Image icon = ImageLoader::getInstance()->createChannelLogo(channelNumber, sa_tv);
+  setTitleBarIcon(icon);
 
   sl.setPosition(10, 30 + 5);
   sl.setSize(area.w * 42 / 100 - 20, area.h - 30 - 15 - 30);
@@ -236,9 +236,8 @@ void VEpgListAdvanced::doNext()
   mode = Next;
   updateEpgDataNowNext(true);
   setButtonText();
-  TVMediaInfo* info = new TVMediaInfo();
-  info->setStaticArtwork(sa_tv);
-  setTitleBarIcon(info);
+  Image icon = ImageLoader::getInstance()->createStatic(sa_tv);
+  setTitleBarIcon(icon);
   draw(true);
   boxstack->update(this);
 }
@@ -257,9 +256,8 @@ void VEpgListAdvanced::doNow()
   mode = Now;
   updateEpgDataNowNext(true);
   setButtonText();
-  TVMediaInfo* info = new TVMediaInfo();
-  info->setStaticArtwork(sa_tv);
-  setTitleBarIcon(info);
+  Image icon = ImageLoader::getInstance()->createStatic(sa_tv);
+  setTitleBarIcon(icon);
   draw(true);
   boxstack->update(this);
 }
@@ -273,10 +271,8 @@ void VEpgListAdvanced::doProgramm()
   channelNumber = chan->number;
   updateEpgDataChannel();
   setButtonText();
-  TVMediaInfo* info = new TVMediaInfo();
-  info->setChannelLogo(channelNumber);
-  info->setStaticFallback(sa_tv);
-  setTitleBarIcon(info);
+  Image icon = ImageLoader::getInstance()->createChannelLogo(channelNumber, sa_tv);
+  setTitleBarIcon(icon);
   draw(true);
   boxstack->update(this);
 }
@@ -513,12 +509,8 @@ void VEpgListAdvanced::drawDataChannel(bool doIndexPop)
       strftime(endTimeStr, 16, "%H:%M", &btime);
       std::string eventText = fmt::format("\t {}\n \t \t{} - {}", currentEvent->title, startTimeStr, endTimeStr);
 
-      // New TVMedia stuff
-      TVMediaInfo* info = new TVMediaInfo();
-      info->setPosterThumb(channelNumber, currentEvent->id);
-      info->setStaticFallback(sa_defposter);
-
-      currentEvent->index = sl.addOption(eventText, reinterpret_cast<void*>(currentEvent->id), first, info);
+      Image icon = ImageLoader::getInstance()->createEventThumb(channelNumber, currentEvent->id);
+      currentEvent->index = sl.addOption(eventText, reinterpret_cast<void*>(currentEvent->id), first, icon);
       first = 0;
     }
   }
@@ -590,7 +582,6 @@ void VEpgListAdvanced::drawDataNowNext(bool next, bool doIndexPop)
       eventText = fmt::format("\n{}", chan->name);
     }
 
-    TVMediaInfo* info = new TVMediaInfo();
 
     if ((*chanList)[listIndex]->number == channelNumber)
     {
@@ -598,9 +589,8 @@ void VEpgListAdvanced::drawDataNowNext(bool next, bool doIndexPop)
       setcurrenthelper = listIndex;
     }
 
-    info->setChannelLogo((*chanList)[listIndex]->number);
-    info->setStaticFallback(sa_tv);
-    int index = sl.addOption(eventText, reinterpret_cast<void*>(listIndex), first, info);
+    Image icon = ImageLoader::getInstance()->createChannelLogo((*chanList)[listIndex]->number, sa_tv);
+    int index = sl.addOption(eventText, reinterpret_cast<void*>(listIndex), first, icon);
 
     if (currentEvent) currentEvent->index = index;
 
@@ -729,10 +719,8 @@ void VEpgListAdvanced::updateSelection()
 
   if (mode == OneChannel)
   {
-    TVMediaInfo* info = new TVMediaInfo();
-    info->setChannelLogo(channelNumber);
-    info->setStaticFallback(sa_tv);
-    setTitleBarIcon(info);
+    Image icon = ImageLoader::getInstance()->createChannelLogo(channelNumber, sa_tv);
+    setTitleBarIcon(icon);
   }
 
   Event* toShow = getCurrentOptionEvent(channel);
@@ -746,7 +734,7 @@ void VEpgListAdvanced::updateSelection()
     description << toShow->subtitle << "\n";
     description << toShow->description;
 
-    TVMedia poster;
+    TVMediaStruct poster;
     poster.height = 0;
 
     if (toShow->movieInfo)
@@ -768,23 +756,21 @@ void VEpgListAdvanced::updateSelection()
 
     if (poster.height)
     {
-      epgTVmedia.setTVMedia(poster.info, WTVMedia::ZoomHorizontal);
+      epgTVmedia.setImage(poster.image, WTVMedia::ZoomHorizontal);
       epgTVmedia.setVisible(true);
     }
     else
     {
       if (toShow->epgImage)
       {
-        TVMediaInfo info;
-        info.setPosterThumb(channel, toShow->id);
-        epgTVmedia.setTVMedia(info, WTVMedia::ZoomHorizontal);
+        Image icon = ImageLoader::getInstance()->createEventThumb(channel, toShow->id);
+        epgTVmedia.setImage(icon, WTVMedia::ZoomHorizontal);
         epgTVmedia.setVisible(true);
       }
       else if (mode != OneChannel)
       {
-        TVMediaInfo info;
-        info.setChannelLogo(channel);
-        epgTVmedia.setTVMedia(info, WTVMedia::ZoomHorizontal);
+        Image icon = ImageLoader::getInstance()->createChannelLogo(channel);
+        epgTVmedia.setImage(icon, WTVMedia::ZoomHorizontal);
         epgTVmedia.setVisible(true);
       }
       else
@@ -801,9 +787,8 @@ void VEpgListAdvanced::updateSelection()
 
     if (mode != OneChannel)
     {
-      TVMediaInfo info;
-      info.setChannelLogo(channel);
-      epgTVmedia.setTVMedia(info, WTVMedia::ZoomHorizontal);
+      Image icon = ImageLoader::getInstance()->createChannelLogo(channel);
+      epgTVmedia.setImage(icon, WTVMedia::ZoomHorizontal);
       epgTVmedia.setVisible(true);
     }
     else
index 6d61eecb6a1cc6328dc6376270e226eb40fc50b0..8dd54365f8657a47bb29389fb835e711fb18c962 100644 (file)
@@ -36,6 +36,7 @@
 #include "wmovieview.h"
 #include "wseriesview.h"
 #include "wpictureview.h"
+#include "imageloader.h"
 
 #include "vepgsummary.h"
 
@@ -131,7 +132,7 @@ VEpgSummary::VEpgSummary(Event *tevent, Channel* tchannel)
   summary->add(&epgTVmedia);
   if (movieview) movieview->add(&epgTVmedia);
   if (seriesview) seriesview->add(&epgTVmedia);
-  TVMedia poster;
+  TVMediaStruct poster;
   poster.height=0;
   if (event->movieInfo) {
          poster=event->movieInfo->poster;
@@ -146,7 +147,7 @@ VEpgSummary::VEpgSummary(Event *tevent, Channel* tchannel)
                  }
   }
   if (poster.height) {
-         epgTVmedia.setTVMedia(poster.info, WTVMedia::ZoomHorizontal);
+         epgTVmedia.setImage(poster.image, WTVMedia::ZoomHorizontal);
          epgTVmedia.setVisible(true);
   } else {
          epgTVmedia.setVisible(false);
index f396694325db14a421cbe19c22a1f7a7bf765bad..8efed3ae5ae2e585cc13374ab0bac4f0785ef329 100644 (file)
--- a/vopts.cc
+++ b/vopts.cc
@@ -34,6 +34,7 @@
 #include "message.h"
 #include "control.h"
 #include "staticartwork.h"
+#include "imageloader.h"
 
 #ifdef VOMP_PLATTFORM_MVP
 #include "mediaoptions.h"
@@ -48,9 +49,8 @@ VOpts::VOpts()
   setTitleBarOn(1);
   setTitleBarColour(DrawStyle::TITLEBARBACKGROUND);
   setTitleText(tr("Options"));
-  TVMediaInfo *info= new TVMediaInfo();
-  info->setStaticArtwork(sa_properties);
-  setTitleBarIcon(info);
+  Image icon = ImageLoader::getInstance()->createStatic(sa_properties);
+  setTitleBarIcon(icon);
 
   setSize(520, 360);
   createBuffer();
index 366fff8c75566a38a911f85759dd96389df20777..fd30f3c8e72d9a484d95c40ec609c86eb38e570b 100644 (file)
@@ -163,9 +163,9 @@ void VRecording::draw()
   TBBoxx::draw();
   OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
   if (osdv) {
-         TVMedia poster;
+         TVMediaStruct poster;       // does not need any image creation, it's copying from an already made Movie/SeriesInfo object
          if (rec->movieInfo) {
-                 poster=rec->movieInfo->poster;
+                 poster = rec->movieInfo->poster;
          }
          if (rec->seriesInfo) {
                  if (rec->seriesInfo->seasonposter.height) {
@@ -178,7 +178,7 @@ void VRecording::draw()
          }
          if (poster.height) {
                 // float aspect=((float)poster.height)/((float)poster.width)/Osd::getInstance()->getPixelAspect();
-                 drawTVMedia(poster.info, static_cast<float>(buttonRegion.x), static_cast<float>(tabbar.getY2() - 3),
+                 drawImage(poster.image, static_cast<float>(buttonRegion.x), static_cast<float>(tabbar.getY2() - 3),
                                                static_cast<float>(buttonRegion.w), /*buttonRegion.w*aspect*/ 0.f, BottomLeft);
          }
   }
index 25be5e02be8e8d08a9bf975c9aac3ccb852cf100..bdee168861fee6b985a1eabfe5cec0ddb408d220 100644 (file)
@@ -42,6 +42,9 @@
 #include "movieinfo.h"
 #include "seriesinfo.h"
 #include "staticartwork.h"
+#include "image.h"
+#include "imageloader.h"
+#include "osd.h"
 
 #include "vrecordinglistadvanced.h"
 
@@ -55,9 +58,9 @@ VRecordingListAdvanced::VRecordingListAdvanced()
 
   setTitleBarOn(1);
   setTitleBarColour(DrawStyle::TITLEBARBACKGROUND);
-  TVMediaInfo* info = new TVMediaInfo();
-  info->setStaticArtwork(sa_recordings);
-  setTitleBarIcon(info);
+
+  Image icon = ImageLoader::getInstance()->createStatic(sa_recordings);
+  setTitleBarIcon(icon);
 
   sl.setPosition(10, 30 + 5);
   sl.setSize(area.w*42/100 - 20, area.h - 30 - 15 - 30);
@@ -105,15 +108,12 @@ void VRecordingListAdvanced::drawData(bool doIndexPop)
     currentSubDir = *i;
     std::string dirString = fmt::format("\t{} \n \t <dir> {}/{}", currentSubDir->name, currentSubDir->getNumNewRecordings(), currentSubDir->getNumRecordings());
 
-    TVMediaInfo *info=new TVMediaInfo();
+    Image icon;
     if (currentSubDir->recList.begin() != currentSubDir->recList.end())
     {
-       info->setPosterThumb((*currentSubDir->recList.begin())->getFileName());
-       info->setStaticFallback(sa_recfolder);
-    } else {
-       info->setStaticArtwork(sa_recfolder);
+      icon = ImageLoader::getInstance()->createRecFolder((*currentSubDir->recList.begin())->getFileName());
     }
-    currentSubDir->index = sl.addOption(dirString, 0, first, info);
+    currentSubDir->index = sl.addOption(dirString, 0, first, icon);
     first = 0;
 
   }
@@ -130,11 +130,8 @@ void VRecordingListAdvanced::drawData(bool doIndexPop)
     strftime(timeString, 16, "%d/%m/%y %H:%M", &btime);
     std::string fileString = fmt::format("{}\t{}\n \t{}", (currentRec->getNew() ? '*': ' '), currentRec->getProgName(), timeString);
 
-    // New TVMedia stuff
-    TVMediaInfo *info= new TVMediaInfo();
-    info->setPosterThumb(currentRec->getFileName());
-    info->setStaticFallback(sa_recording);
-    currentRec->index = sl.addOption(fileString, 0, first, info);
+    Image icon = ImageLoader::getInstance()->createRecThumb(currentRec->getFileName());
+    currentRec->index = sl.addOption(fileString, 0, first, icon);
     first = 0;
   }
 
@@ -233,7 +230,7 @@ void VRecordingListAdvanced::updateSelection()
                        description << tr("Summary unavailable");
 
                }
-               TVMedia poster;
+               TVMediaStruct poster;
                poster.height=0;
                if (toShow->movieInfo) {
                        poster=toShow->movieInfo->poster;
@@ -248,7 +245,7 @@ void VRecordingListAdvanced::updateSelection()
                                }
                }
                if (poster.height) {
-                       epgTVmedia.setTVMedia(poster.info, WTVMedia::ZoomHorizontal);
+                       epgTVmedia.setImage(poster.image, WTVMedia::ZoomHorizontal);
                        epgTVmedia.setVisible(true);
                } else {
                        epgTVmedia.setVisible(false);
index c11c2824fe06b86ad54421e317e41c4497d1e96a..c075133af58a600e144e886501b3dde6978a5727 100644 (file)
@@ -29,6 +29,7 @@
 #include "vquestion.h"
 #include "messagequeue.h"
 #include "staticartwork.h"
+#include "imageloader.h"
 
 VTimerEdit::VTimerEdit(RecTimer* trt)
 {
@@ -56,9 +57,8 @@ VTimerEdit::VTimerEdit(RecTimer* trt)
   setTitleBarOn(1);
   setTitleText(tr("Edit Timer"));
   setTitleBarColour(DrawStyle::TITLEBARBACKGROUND);
-  TVMediaInfo *info= new TVMediaInfo();
-  info->setStaticArtwork(sa_timers);
-  setTitleBarIcon(info);
+  Image icon = ImageLoader::getInstance()->createStatic(sa_timers);
+  setTitleBarIcon(icon);
   MessageQueue::getInstance()->addReceiver(this);
 }
 
index f5886204d0aa9a139da19f7a0dfb31fef50885f6..87c59e65a28120486f9c02c92a6ca18c565c49ed 100644 (file)
@@ -34,6 +34,7 @@
 #include "vinfo.h"
 #include "log.h"
 #include "staticartwork.h"
+#include "imageloader.h"
 
 #include "vtimerlist.h"
 
@@ -66,9 +67,8 @@ VTimerList::VTimerList()
   setTitleBarOn(1);
   setTitleText(tr("Timers"));
   setTitleBarColour(DrawStyle::TITLEBARBACKGROUND);
-  TVMediaInfo *info= new TVMediaInfo();
-  info->setStaticArtwork(sa_timers);
-  setTitleBarIcon(info);
+  Image icon = ImageLoader::getInstance()->createStatic(sa_timers);
+  setTitleBarIcon(icon);
 
   sl.setPosition(30, 30 + 5);
   sl.setSize(area.w - 40, area.h - 30 - 15 - 30);
index cde08e4cb72484bfcb1065fe107a7f94baf59da3..837334a3ee4ef3587e85d86219150bd83996a640 100644 (file)
@@ -46,6 +46,7 @@
 #include "staticartwork.h"
 #include "demuxer.h"
 #include "messagequeue.h"
+#include "imageloader.h"
 
 #include "vvideolivetv.h"
 
@@ -112,14 +113,13 @@ VVideoLiveTV::VVideoLiveTV(std::shared_ptr<ChannelList> tchanList, ULONG initial
   // This is only used on old remotes to stop up/down buttons being used for osd-epg scrolling
   okTriggeredOSD = false;
 
-  TVMediaInfo info;
-  info.setChannelLogo(initialChannelNumber);
+  Image icon = ImageLoader::getInstance()->createChannelLogo(initialChannelNumber);
 
   if (osdv && streamType == VDR::RADIO) {
          radioChannelLogo.setPosition(video->getScreenWidth()/4,video->getScreenHeight()/4);
          radioChannelLogo.setSize(video->getScreenWidth()/2,video->getScreenHeight()/2);
          radioChannelLogo.setVisible(true);
-         radioChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
+         radioChannelLogo.setImage(icon, WTVMedia::ZoomVertical);
          add(&radioChannelLogo);
   }
 
@@ -142,7 +142,7 @@ VVideoLiveTV::VVideoLiveTV(std::shared_ptr<ChannelList> tchanList, ULONG initial
     //osdChannelLogo.setBackgroundColour(DrawStyle::OSDBACKGROUND);
     osdChannelLogo.setPosition(30,5);
     osdChannelLogo.setSize(60,60);
-    osdChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
+    osdChannelLogo.setImage(icon, WTVMedia::ZoomVertical);
     osd.add(&osdChannelLogo);
     channellogomove = 30-5;
     boxdiff = 145;
@@ -235,23 +235,24 @@ VVideoLiveTV::VVideoLiveTV(std::shared_ptr<ChannelList> tchanList, ULONG initial
   
   if (osdv)
   {
-    TVMediaInfo ninfo;
-    ninfo.setStaticArtwork(sa_txtoff);
+    Image sIcon;
+
+    sIcon = ImageLoader::getInstance()->createStatic(sa_txtoff);
     txtlogo.setPosition(54+4*boxdiff,104);
     txtlogo.setSize(22,20);
-    txtlogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
+    txtlogo.setImage(sIcon, WTVMedia::ZoomVertical);
     osd.add(&txtlogo);
 
-    ninfo.setStaticArtwork(sa_dolbyoff);
+    sIcon = ImageLoader::getInstance()->createStatic(sa_dolbyoff);
     dolbylogo.setPosition(54+4*boxdiff+15,104);
     dolbylogo.setSize(22,20);
-    dolbylogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
+    dolbylogo.setImage(sIcon, WTVMedia::ZoomVertical);
     osd.add(&dolbylogo);
 
-    ninfo.setStaticArtwork(sa_sd576i);
+    sIcon = ImageLoader::getInstance()->createStatic(sa_sd576i);
     reslogo.setPosition(54+4*boxdiff+30,104);
     reslogo.setSize(22,20);
-    reslogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
+    reslogo.setImage(sIcon, WTVMedia::ZoomVertical);
     osd.add(&reslogo);
 
     reslogo.setVisible(false);
@@ -990,17 +991,16 @@ bool VVideoLiveTV::channelChange(UCHAR changeType, UINT newData)
 
   if (osdv)
   {
-    TVMediaInfo info;
     Channel* currentChannel = (*chanList)[currentChannelIndex];
     if (currentChannel)
     {
-      info.setChannelLogo(currentChannel->number);
+      Image icon = ImageLoader::getInstance()->createChannelLogo(currentChannel->number);
       if (streamType == VDR::RADIO)
       {
-        radioChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
+        radioChannelLogo.setImage(icon, WTVMedia::ZoomVertical);
         radioChannelLogo.setVisible(true);
       }
-      osdChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
+      osdChannelLogo.setImage(icon, WTVMedia::ZoomVertical);
     }
   }
 
@@ -1206,56 +1206,66 @@ void VVideoLiveTV::doAudioChannelSymbol()
   Channel* currentChannel = (*chanList)[osdChannelIndex];
     
   bool multiAudio = false;
-  if (Audio::getInstance()->supportsAc3()) {
-         if ((currentChannel->numDPids+currentChannel->numAPids) > 1) multiAudio = true;
+  if (Audio::getInstance()->supportsAc3())
+  {
+    if ((currentChannel->numDPids+currentChannel->numAPids) > 1) multiAudio = true;
   }
   if (currentChannel->numAPids > 1) multiAudio = true;
   
   // draw the doobery
-  if (!osdv) {
-         if (multiAudio) sAudioChannels.nextSymbol = WSymbol::MULTIAUDIO;
-         else            sAudioChannels.nextSymbol = WSymbol::SINGLEAUDIO;
-         sAudioChannels.setVisible(true);
+  if (!osdv)
+  {
+    if (multiAudio) sAudioChannels.nextSymbol = WSymbol::MULTIAUDIO;
+    else            sAudioChannels.nextSymbol = WSymbol::SINGLEAUDIO;
+    sAudioChannels.setVisible(true);
   }
   if (osdv)
   {
-         dolbylogo.setVisible(true);
-         txtlogo.setVisible(true);
-         TVMediaInfo info;
-         if (currentChannel->tpid!=0) info.setStaticArtwork(sa_txton);
-         else info.setStaticArtwork(sa_txtoff);
-         txtlogo.setTVMedia(info, WTVMedia::ZoomVertical);
-
-
-         if (Audio::getInstance()->supportsAc3() && currentChannel->numDPids>1)
-                 info.setStaticArtwork(sa_dolbyon);
-         else info.setStaticArtwork(sa_dolbyoff);
-         dolbylogo.setTVMedia(info, WTVMedia::ZoomVertical);
-
-        Demuxer* demux=Demuxer::getInstance();
-        if (demux) {
-                int vertical_size=demux->getVerticalSize();
-                LogNT::getInstance()->debug(TAG, "TVMedia vertical size {}", vertical_size);
-                reslogo.setVisible(true);
-                switch (vertical_size) {
-                case 576:
-                        info.setStaticArtwork(sa_sd576i);
-                        reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
-                case 720:
-                        info.setStaticArtwork(sa_hd720p);
-                        reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
-                case 1080:
-                        info.setStaticArtwork(sa_hd1080i);
-                        reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
-                default: // we assume sd
-                        reslogo.setVisible(false);
-                };
-
-        } else {
-                reslogo.setVisible(false);
-        }
+    dolbylogo.setVisible(true);
+    txtlogo.setVisible(true);
+    Image icon;
+    int sa_id;
+
+    if (currentChannel->tpid!=0) sa_id = sa_txton;
+    else sa_id = sa_txtoff;
+    icon = ImageLoader::getInstance()->createStatic(sa_id);
+    txtlogo.setImage(icon, WTVMedia::ZoomVertical);
+
+    if (Audio::getInstance()->supportsAc3() && currentChannel->numDPids>1)
+      sa_id = sa_dolbyon;
+    else
+      sa_id = sa_dolbyoff;
+    icon = ImageLoader::getInstance()->createStatic(sa_id);
+    dolbylogo.setImage(icon, WTVMedia::ZoomVertical);
 
+    Demuxer* demux=Demuxer::getInstance();
+    if (demux)
+    {
+      int vertical_size = demux->getVerticalSize();
+      LogNT::getInstance()->debug(TAG, "TVMedia vertical size {}", vertical_size);
 
+      reslogo.setVisible(true);
+      switch (vertical_size)
+      {
+        case 576:
+          icon = ImageLoader::getInstance()->createStatic(sa_sd576i);
+          reslogo.setImage(icon, WTVMedia::ZoomVertical);
+          break;
+        case 720:
+          icon = ImageLoader::getInstance()->createStatic(sa_hd720p);
+          reslogo.setImage(icon, WTVMedia::ZoomVertical);
+          break;
+        case 1080:
+          icon = ImageLoader::getInstance()->createStatic(sa_hd1080i);
+          reslogo.setImage(icon, WTVMedia::ZoomVertical);
+          break;
+        default: // we assume sd
+          reslogo.setVisible(false);
+      }
+
+    } else {
+        reslogo.setVisible(false);
+    }
   }
   
   if (osd.getVisible())
@@ -1318,7 +1328,7 @@ void VVideoLiveTV::updatePosterBanner()
 
        if (toShow)
        {
-               TVMedia poster;
+               TVMediaStruct poster;
                poster.height=0;
                bool posterscale=true;
                if (toShow->movieInfo) {
@@ -1335,7 +1345,7 @@ void VVideoLiveTV::updatePosterBanner()
                        }
                }
                if (poster.height) {
-                       osdposterbanner.setTVMedia(poster.info, posterscale ? WTVMedia::ZoomVertical : WTVMedia::ZoomHorizontal);
+                       osdposterbanner.setImage(poster.image, posterscale ? WTVMedia::ZoomVertical : WTVMedia::ZoomHorizontal);
                        osdposterbanner.setVisible(true);
                } else {
                        osdposterbanner.setVisible(false);
index a2b9a4ccaff2dedb5054de3dc065cac3d2e185fd..5e7db3f9aeab537f56acc2b10f52d86bb5743f69 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "control.h"
 #include "osd.h"
+#include "osdvector.h"
 #include "wsymbol.h"
 #include "audio.h"
 #include "vdr.h"
@@ -89,7 +90,7 @@ VVideoRec::VVideoRec(Recording* rec, bool ish264)
   createBuffer();
   setBackgroundColour(DrawStyle::TRANSPARENT);
 
-  OsdVector* osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
+  OsdVector* osdv = dynamic_cast<OsdVector*>(Osd::getInstance());
   if (osdv)
   {
     osdv->updateBackgroundColor(DrawStyle::BLACK);
index 8a94fdfce6441343dddf0feb5b641bf194e9e159..e076273a278b4738462ba459f553049d4c224eba 100644 (file)
@@ -35,6 +35,8 @@
 #include "boxstack.h"
 #include "vopts.h"
 #include "staticartwork.h"
+#include "image.h"
+#include "imageloader.h"
 
 #include "vwelcome.h"
 
@@ -79,9 +81,11 @@ VWelcome::VWelcome()
 #else
   vdr.setPosition(250, 65);
   vdr.setSize(180, 160);
-  TVMediaInfo sinfo;
-  sinfo.setStaticArtwork(sa_vdrlogo);
-  vdr.setTVMedia(sinfo, WTVMedia::ZoomHorizontal);
+
+  ImageLoader* loader = ImageLoader::getInstance();
+
+  Image vdrImage = loader->createStatic(sa_vdrlogo);
+  vdr.setImage(vdrImage, WTVMedia::ZoomHorizontal);
   add(&vdr);
 
 #endif
@@ -99,37 +103,32 @@ VWelcome::VWelcome()
 
   setTitleText(tr("Welcome"));
 
+  Image icon;
 
-  TVMediaInfo *info= new TVMediaInfo();
-  info->setStaticArtwork(sa_tv);
-  sl.addOption(tr("1. Live TV"), reinterpret_cast<void*>(1), 1, info);
+  icon = loader->createStatic(sa_tv);
+  sl.addOption(tr("1. Live TV"), reinterpret_cast<void*>(1), 1, icon);
 
-  info= new TVMediaInfo();
-  info->setStaticArtwork(sa_radio);
-  sl.addOption(tr("2. Radio"), reinterpret_cast<void*>(2), 0, info);
+  icon = loader->createStatic(sa_radio);
+  sl.addOption(tr("2. Radio"), reinterpret_cast<void*>(2), 0, icon);
 
-  info= new TVMediaInfo();
-  info->setStaticArtwork(sa_recordings);
-  sl.addOption(tr("3. Recordings"), reinterpret_cast<void*>(3), 0, info);
+  icon = loader->createStatic(sa_recordings);
+  sl.addOption(tr("3. Recordings"), reinterpret_cast<void*>(3), 0, icon);
 
-  info= new TVMediaInfo();
-  info->setStaticArtwork(sa_timers);
-  sl.addOption(tr("4. Timers"), reinterpret_cast<void*>(4), 0, info);
+  icon = loader->createStatic(sa_timers);
+  sl.addOption(tr("4. Timers"), reinterpret_cast<void*>(4), 0, icon);
 #ifdef VOMP_PLATTFORM_MVP
   sl.addOption(tr("5. MediaPlayer"), reinterpret_cast<void*>(5), 0);
 #endif
 
-  info= new TVMediaInfo();
-  info->setStaticArtwork(sa_properties);
-  sl.addOption(tr("6. Options"), reinterpret_cast<void*>(6), 0,info);
+  icon = loader->createStatic(sa_properties);
+  sl.addOption(tr("6. Options"), reinterpret_cast<void*>(6), 0, icon);
 
-  info= new TVMediaInfo();
-  info->setStaticArtwork(sa_restart);
+  icon = loader->createStatic(sa_restart);
   // NCONFIG
 #ifndef VOMP_HAS_EXIT
-  sl.addOption(tr("7. Reboot"), reinterpret_cast<void*>(7), 0,info);
+  sl.addOption(tr("7. Reboot"), reinterpret_cast<void*>(7), 0, icon);
 #else
-  sl.addOption(tr("7. Exit"), reinterpret_cast<void*>(7), 0,info);
+  sl.addOption(tr("7. Exit"), reinterpret_cast<void*>(7), 0, icon);
 #endif
 
   MessageQueue::getInstance()->addReceiver(this);
index a0c876cabe81afba9c45efaf884b823a467d0c55..ddaa453aa5f689085938f51d8d720d299e55b4ae 100644 (file)
@@ -80,18 +80,18 @@ void WPictureView::draw()
          while (citty!=cur_pict.end())
          {
                  if (!const_height) {
-                         drawTVMedia((*citty)->media,
+                         drawImage((*citty)->media,
                                          xpos, ypos + max_height /*- (*citty)->h*/,
                                          (*citty)->w,
                                          /*(*citty)->h*/0.f,BottomLeft);
                  } else {
                          if (!(*citty)->banner) {
-                                 drawTVMedia((*citty)->media,
+                                 drawImage((*citty)->media,
                                                  xpos+area.w*0.5f, ypos,
                                                  0.f,
                                                  const_height,TopMiddle);
                          } else {
-                                 drawTVMedia((*citty)->media,
+                                 drawImage((*citty)->media,
                                                xpos+area.w*0.5f, ypos,
                                                area.w-2.f,
                                                0.f,TopMiddle);
@@ -141,9 +141,9 @@ void WPictureView::draw()
 
 }
 
-void WPictureView::addPicture(TVMediaInfo& pict,  float pwidth, float pheight , bool banner, std::string caption, std::string caption2)
+void WPictureView::addPicture(Image& pict, float pwidth, float pheight , bool banner, std::string caption, std::string caption2)
 {
-       pictures.push_back(Picture(pict,pwidth,pheight, banner, caption,caption2));
+  pictures.push_back(Picture(pict, pwidth, pheight, banner, caption, caption2));
 }
 
 int WPictureView::handleCommand(int command)
@@ -219,7 +219,7 @@ WActorGallery::WActorGallery(Actors& actors)
                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+"\"");
+               addPicture((*itty).thumb.image, width, height, false,(*itty).name,"\""+(*itty).role+"\"");
                itty++;
        }
 }
@@ -258,8 +258,8 @@ void WArtworkGallery::addTVMedias(TVMedias& medias, bool banner)
        }
 }
 
-void WArtworkGallery::addTVMedia(TVMedia& media, bool banner)
+void WArtworkGallery::addTVMedia(TVMediaStruct& media, bool banner)
 {
        if (media.width)
-               addPicture(media.info, media.width, media.height, banner);
+               addPicture(media.image, media.width, media.height, banner);
 }
index 84e5032a7abb80578d96e326a339bb8b97afa9f0..01b98ea589bc9b1109875304d792d7cede309c70 100644 (file)
@@ -28,6 +28,8 @@
 
 #include "defines.h"
 #include "boxx.h"
+#include "image.h"
+#include "imageloader.h"
 
 class Colour;
 
@@ -36,7 +38,7 @@ 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 addPicture(Image& pict, float width, float height,bool banner=false, std::string caption ="", std::string caption2 ="");
     void draw();
     void setForegroundColour(const DrawStyle& fcolour);
 
@@ -48,11 +50,12 @@ class WPictureView : public Boxx
   protected:
     class Picture {
     public:
-       Picture(TVMediaInfo tmedia,float width, float height, bool tbanner, std::string tcaption,  std::string tcaption2){
+       Picture(Image& 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;
+       Image media;
        std::string caption;
        std::string caption2;
        float w;
@@ -81,7 +84,7 @@ public:
        WArtworkGallery(SeriesInfo& series);
 protected:
        void addTVMedias(TVMedias& medias, bool banner=false);
-       void addTVMedia(TVMedia& media, bool banner=false);
+       void addTVMedia(TVMediaStruct& media, bool banner=false);
 
 };
 
index 764e4765bf1cd5132d6a42477e689615ab8680c1..23d9170cc47f8c986a61438a49b4590cc19b06d2 100644 (file)
@@ -24,7 +24,7 @@
 #include "boxx.h"
 #include "wselectlist.h"
 
-class Input;
+class InputMan;
 class Message;
 
 class WRemoteConfig : public Boxx
index 21381fe65e725d955c041c29bb1fcf629da5c600..5ed2252a83ee7dcf510130b7a79c9b9d2db49721 100644 (file)
@@ -36,11 +36,6 @@ WSelectList::~WSelectList()
 
 void WSelectList::clear()
 {
-  int vsize = options.size();
-  for (int i = 0; i < vsize; i++)
-  {
-    if (options[i].pict) delete options[i].pict;
-  }
   options.clear();
 
   selectedOption = 0;
@@ -70,27 +65,51 @@ void WSelectList::hintSetTop(int idx)
   topOption = idx;
 }
 
-int WSelectList::addOption(const char* text, void* data, int selected, TVMediaInfo* pict)
+int WSelectList::addOption(const char* text, void* data, int selected)
+{
+  int thisNewOption = options.size();
+
+  wsloption wslo;
+  wslo.text = text;
+  wslo.data = data;
+  options.push_back(wslo);
+  if (selected) selectedOption = thisNewOption;
+  return thisNewOption;
+}
+
+int WSelectList::addOption(const std::string& text, void* data, int selected)
+{
+  int thisNewOption = options.size();
+
+  wsloption wslo;
+  wslo.text = text;
+  wslo.data = data;
+  options.push_back(wslo);
+  if (selected) selectedOption = thisNewOption;
+  return thisNewOption;
+}
+
+int WSelectList::addOption(const char* text, void* data, int selected, Image& icon)
 {
   int thisNewOption = options.size();
 
   wsloption wslo;
   wslo.text = text;
   wslo.data = data;
-  wslo.pict = pict;
+  wslo.image = icon;
   options.push_back(wslo);
   if (selected) selectedOption = thisNewOption;
   return thisNewOption;
 }
 
-int WSelectList::addOption(const std::string& text, void* data, int selected, TVMediaInfo* pict)
+int WSelectList::addOption(const std::string& text, void* data, int selected, Image& icon)
 {
   int thisNewOption = options.size();
 
   wsloption wslo;
   wslo.text = text;
   wslo.data = data;
-  wslo.pict = pict;
+  wslo.image = icon;
   options.push_back(wslo);
   if (selected) selectedOption = thisNewOption;
   return thisNewOption;
@@ -124,12 +143,12 @@ void WSelectList::draw()
     if (i == selectedOption && showseloption)
     {
       rectangle(0, ypos, area.w, static_cast<UINT>(static_cast<float>(fontHeight) * linesPerOption) - 1, darkseloption ? DrawStyle::SELECTDARKHIGHLIGHT : DrawStyle::SELECTHIGHLIGHT);
-      drawOptionLine(options[i].text, 5, ypos, area.w - 5, DrawStyle::DARKTEXT, options[i].pict);
+      drawOptionLine(options[i].text, 5, ypos, area.w - 5, DrawStyle::DARKTEXT, options[i].image);
     }
     else
     {
       rectangle(0, ypos, area.w, static_cast<UINT>(static_cast<float>(fontHeight) * linesPerOption) - 1, DrawStyle::SELECTBACKGROUND);
-      drawOptionLine(options[i].text, 5, ypos, area.w - 5, DrawStyle::LIGHTTEXT, options[i].pict);
+      drawOptionLine(options[i].text, 5, ypos, area.w - 5, DrawStyle::LIGHTTEXT, options[i].image);
     }
     ypos += ySeparation;
   }
@@ -147,7 +166,7 @@ int WSelectList::getColumn(int x)
   return columns[x];
 }
 
-void WSelectList::drawOptionLine(const std::string& text, int xpos, int ypos, int width, const DrawStyle& colour, TVMediaInfo* pict)
+void WSelectList::drawOptionLine(const std::string& text, int xpos, int ypos, int width, const DrawStyle& colour, Image& image)
 {
   UINT curline = 0;
   UINT taboffset = 0;
@@ -157,10 +176,10 @@ void WSelectList::drawOptionLine(const std::string& text, int xpos, int ypos, in
   int imagewidth = 0;
   int xposmod = xpos;
   if (numColumns > 1) imagewidth = columns[1] - columns[0];
-  if (pict)
+  if (image)
   {
-    drawTVMedia(*pict, static_cast<float>(xpos), static_cast<float>(ypos), static_cast<float>(imagewidth),
-                static_cast<float>(fontHeight) * linesPerOption, TopLeftLimited);
+    drawImage(image, static_cast<float>(xpos), static_cast<float>(ypos), static_cast<float>(imagewidth),
+              static_cast<float>(fontHeight) * linesPerOption, TopLeftLimited);
     taboffset++;
     xposmod += xpos;
   }
index a76a9a15d0a6348ec097461ac5d5e782d7c38cce..14b122f7fa0b8d309140c9a230b8349fe01c5bff 100644 (file)
 #include <vector>
 
 #include "defines.h"
+#include "image.h"
 #include "boxx.h"
 
 typedef struct
 {
   std::string text;
   void* data;
-  TVMediaInfo* pict;
+  Image image;
 } wsloption;
 
 class WSelectList : public Boxx
@@ -45,8 +46,11 @@ class WSelectList : public Boxx
     void setNoLoop();
     void setShowSelOption(bool set) { showseloption = set; }
     void setDarkSelOption(bool set) { darkseloption = set; }
-    int addOption(const char* text, void* data, int selected, TVMediaInfo* pict = NULL);
-    int addOption(const std::string& text, void* data, int selected, TVMediaInfo* pict = NULL);
+    // FIXME 4 versions !
+    int addOption(const char* text, void* data, int selected);
+    int addOption(const std::string& text, void* data, int selected);
+    int addOption(const char* text, void* data, int selected, Image& icon);
+    int addOption(const std::string& text, void* data, int selected, Image& icon);
     void draw();
     void setBackgroundColour(const DrawStyle& colour);
     void setLinesPerOption(float lines) { linesPerOption = lines; }
@@ -71,7 +75,7 @@ class WSelectList : public Boxx
     virtual bool mouseAndroidScroll(int x, int y, int sx, int sy);
 
   private:
-    void drawOptionLine(const std::string& text, int xpos, int ypos, int width, const DrawStyle& colour, TVMediaInfo* pict);
+    void drawOptionLine(const std::string& text, int xpos, int ypos, int width, const DrawStyle& colour, Image& icon);
     int getMouseLine(int x, int y);
 
     DrawStyle backgroundColour;
index a6815c212f519a60c0ef73147841ffb58e9f38b3..14ad82d640b1c2ce65af473e67f5122351453596 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2004-2005 Chris Tallon, 2014 Marten Richter
+    Copyright 2004-2005,2021 Chris Tallon, 2014 Marten Richter
 
     This file is part of VOMP.
 
     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.
+    along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
 */
-#include "boxx.h"
-#include "wtvmedia.h"
-
-
-
-
- WTVMedia::WTVMedia()
- {
-        media = false;
-        scale=NoZoom;
- }
-
- WTVMedia::~WTVMedia()
- {
 
- }
-
-
-
- void WTVMedia::setTVMedia(TVMediaInfo & ninfo, Scaling nscale)
- {
-        info = ninfo;
-        scale = nscale;
-        media =true;
- }
-
- void  WTVMedia::draw()
- {
-        //Boxx::draw();
-        if (!media) return;
-        float w=0;
-        float h=0;
-        switch (scale)
-        {
-        case ZoomHorizontal:
-                w = static_cast<float>(area.w);
-         break;
-        case ZoomVertical:
-                h = static_cast<float>(area.h);
-         break;
-        case ZoomBoth:
-                w = static_cast<float>(area.w);
-                h = static_cast<float>(area.h);
-         break;
+#include "boxx.h"
 
-        case NoZoom:
-          ; // ?
-        }
-        drawTVMedia(info,0.f,0.f,w,h,TopLeft);
+#include "wtvmedia.h"
 
- }
+WTVMedia::WTVMedia()
+{
+  media = false;
+  scale = NoZoom;
+}
+
+WTVMedia::~WTVMedia()
+{
+}
+
+void WTVMedia::setImage(Image& tImage, Scaling nscale)
+{
+  image = tImage;
+  scale = nscale;
+  media = true;
+}
+
+void WTVMedia::draw()
+{
+  //Boxx::draw();
+  if (!media) return;
+  float w=0;
+  float h=0;
+  switch (scale)
+  {
+    case ZoomHorizontal:
+      w = static_cast<float>(area.w);
+      break;
+    case ZoomVertical:
+      h = static_cast<float>(area.h);
+      break;
+    case ZoomBoth:
+      w = static_cast<float>(area.w);
+      h = static_cast<float>(area.h);
+      break;
+    case NoZoom:
+    ; // ?
+  }
+  drawImage(image,0.f,0.f,w,h,TopLeft);
+}
index 17708beed5868f35261ff39266e91beb11aef99c..ebf10b6af8bddbb7f7b58e2627ec738e7c6ebbe3 100644 (file)
     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.
+    along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
 */
 
 #ifndef WTVMEDIA_H
 #define WTVMEDIA_H
 
-#include <stdio.h>
-#include <malloc.h>
 #include "boxx.h"
-
-
-
+#include "image.h"
 
 class WTVMedia : public Boxx
 {
@@ -34,22 +29,21 @@ class WTVMedia : public Boxx
     WTVMedia();
     virtual ~WTVMedia();
 
-    enum Scaling {
-               NoZoom,
-               ZoomHorizontal,
-               ZoomVertical,
-               ZoomBoth
+    enum Scaling
+    {
+      NoZoom,
+      ZoomHorizontal,
+      ZoomVertical,
+      ZoomBoth
     };
 
-    void setTVMedia(TVMediaInfo & info, Scaling scale);
+    void setImage(Image& image, Scaling scale);
     void draw();
 
   protected:
-    TVMediaInfo info;
+    Image image;
     Scaling scale;
     bool media;
 };
 
-
-
 #endif