+
/*
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";
typedef std::list<Region> RegionList;
typedef std::stack<std::pair<Boxx*,VideoDisplay> > VideoDisplayStack;
+class Osd;
+
class BoxStack : public MessageReceiver
{
public:
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
}
}
#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;
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();
#include "config.h"
#include "vvideolivetv.h"
#include "channel.h"
+#include "imageloader.h"
#ifdef VOMP_PLATFORM_RASPBERRY
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;
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)
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
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();
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();
class VConnect;
class Message;
class InputMan;
+class ImageLoader;
class Boxx;
class BoxStack;
class LogNT;
Video* video{};
Audio* audio{};
VDR* vdr{};
+ ImageLoader* imageLoader{};
BoxStack* boxstack{};
SleepTimer* sleepTimer{};
Wol* wol{};
#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
--- /dev/null
+/*
+ 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
+}
--- /dev/null
+/*
+ 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.
+
+*/
--- /dev/null
+/*
+ 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);
+ }
+ }
+}
--- /dev/null
+/*
+ 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
static const char* TAG = "ImageOMX";
-ImageOMX::ImageOMX(OsdVector::PictureReader * treader):OsdVector::PictureDecoder(treader)
+ImageOMX::ImageOMX()
{
initted = 0;
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;
}
-bool ImageOMX::getDecodedPicture(struct OsdVector::PictureInfo& pict_inf)
+bool ImageOMX::getDecodedPicture(struct PictureInfo& pict_inf)
{
if (!pictInfValid) return false;
pict_inf=pictInf;
-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:
char L_VPE_OMX_EGL_REND[128];
protected:
- OsdVector::PictureInfo pictInf;
+ PictureInfo pictInf;
bool pictInfValid;
};
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;
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
}
}
-bool ImageOMX2::getDecodedPicture(struct OsdVector::PictureInfo& pict_inf)
+bool ImageOMX2::getDecodedPicture(struct PictureInfo& pict_inf)
{
if (!currentDecodeValid) return false;
pict_inf = currentDecode;
#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:
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
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
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;
#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;
-
-
-
-}
-
-
/*
- 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
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 \
/*
- Copyright 2004-2005 Chris Tallon
+ Copyright 2004-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/>.
*/
#include "osd.h"
{
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());
+}
/*
- 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
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; };
// 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
along with VOMP. If not, see <https://www.gnu.org/licenses/>.
*/
+#include <algorithm>
#include <chrono>
#include <sys/syscall.h>
#include <fontconfig/fontconfig.h>
EXTERNAL_PICTS
#undef EXTERNALPICTURE
+
+ MessageQueue::getInstance()->addReceiver(this);
}
OsdOpenVG::~OsdOpenVG()
{
+ MessageQueue::getInstance()->removeReceiver(this);
+
if (initted) shutdown();
if (cur_fontname) free(cur_fontname);
{
if (initted) return 0;
- reader.init();
+ OsdVector::init();
//First get connection to egl
egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
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;
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
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()
{
* 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.
}
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);
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);
//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)
{
}
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;
}
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;
{
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;
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
}
}
-bool OsdOpenVG::getEGLPicture(struct OsdVector::PictureInfo& info, EGLDisplay* display)
+bool OsdOpenVG::getEGLPicture(struct PictureInfo& info, EGLDisplay* display)
{
struct OpenVGCommand comm;
info.type = PictureInfo::EGLImage;
#include "defines.h"
#include "osdvector.h"
#include "videoomx.h"
+#include "messagequeue.h"
#include "staticartwork.h"
#ifdef PICTURE_DECODER_OMX
//#include "imageomx.h"
#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
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
// 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);
uint8_t* static_artwork_end[sa_MAX];
#ifdef PICTURE_DECODER_OMX
- //ImageOMX* imageomx;
ImageOMX2* imageomx2;
#endif
};
/*
- 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"
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;
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;
}
delete todelete;
}
-bool MagickDecoder::getDecodedPicture(struct OsdVector::PictureInfo& pict_inf)
+bool MagickDecoder::getDecodedPicture(struct PictureInfo& pict_inf)
{
if (!pictInfValid) return false;
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)
}
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_ )
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;
}
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!
}
// 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);
}
}
}
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);
}
}
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);
}
}
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()
} 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())
else ++citty;
}
-
std::map<DrawStyle, VectorHandle>::iterator sitty = drawstyleHandles.begin();
while (sitty != drawstyleHandles.end())
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)
{
}
#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)
{
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;
-}
/*
- 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;
DrawImage,
DrawTTchar,
DrawClipping,
- DrawImageLoading
+ DrawImageLoading,
+ DrawBitmap
};
enum PathIndex
PIPoint
};
-enum Corner
-{
- TopLeft,
- TopRight,
- BottomLeft,
- BottomRight,
- TopMiddle,
- BottomMiddle,
- TopLeftLimited
-};
-
-typedef VectorHandle VectorHandleImage;
-typedef unsigned long long LoadingIndex;
-
class SVGCommand
{
public:
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;
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;
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};
{
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;
float x, y, w, h;
};
-class OsdVector : public Osd, public MessageReceiver
+class OsdVector : public Osd
{
public:
void dumpImages();
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);
// 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;
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{};
std::list<SurfaceInfo> surfaces;
using SurfacesIterator = std::list<SurfaceInfo>::iterator;
std::mutex surfaces_mutex;
-
};
#endif
--- /dev/null
+/*
+ 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
#ifndef SERIESINFO_H
#define SERIESINFO_H
-#include "tvmedia.h"
#include <string>
+#include "image.h"
+
class EpisodeInfo {
public:
EpisodeInfo();
std::string guestStars;
std::string overview;
double rating;
- TVMedia image;
+ TVMediaStruct image;
};
TVMedias posters; // Image 2
TVMedias banners; // Image 3
TVMedias fanart; // Image 4
- TVMedia seasonposter; // Image 5
+ TVMediaStruct seasonposter; // Image 5
};
#endif
#ifndef SURFACE_H
#define SURFACE_H
-#include <stdio.h>
#include "defines.h"
#include "colour.h"
#include <math.h>
#include "bitmap.h"
#include "staticartwork.h"
+#include "imageloader.h"
+
#include "surfacevector.h"
const static char* TAG = "SurfaceVector";
{
logger = LogNT::getInstance();
osd = vosd;
+ imageLoader = ImageLoader::getInstance();
commands.reserve(2048);
}
SurfaceVector::~SurfaceVector()
{
-
osd->removeSurface(this);
for (SVGCommand& command : commands)
VectorHandleImage handle = command.getImageHandle();
if (handle) osd->removeImageRef(handle);
-
- LoadingIndex li = command.getLoadingIndex();
- if (li) osd->removeLoadingIndexRef(li);
}
}
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);
}
}
{
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();
}
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)
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();
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();
}
//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;
#include "surface.h"
#include "osdvector.h"
+#include "image.h"
+#include "imageloader.h"
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);
protected:
LogNT* logger{};
+ ImageLoader* imageLoader{};
int removeCommands(float x, float y, float width, float height);
/*
- Copyright 2007 Chris Tallon
+ Copyright 2007-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/>.
*/
#include "tbboxx.h"
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)
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)
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)
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
#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
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
+++ /dev/null
-/*
- 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;
-}
-
-
+++ /dev/null
-/*
- 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
#include "boxstack.h"
#include "vchannelselect.h"
#include "staticartwork.h"
+#include "image.h"
+#include "imageloader.h"
static const char* TAG = "VChannelList";
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);
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;
}
}
class Channel;
class BoxStack;
+class ImageLoader;
class VChannelList : public TBBoxx, public MessageReceiver
{
void draw();
private:
+ ImageLoader* imageLoader;
BoxStack* boxstack;
std::shared_ptr<ChannelList> chanList;
#include "movieinfo.h"
#include "seriesinfo.h"
#include "osdvector.h"
-#include "tvmedia.h"
+#include "image.h"
+#include "imageloader.h"
#include "vdr.h"
// 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)
}
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;
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)
+SeriesInfo* VDR::getScraperSeriesInfo(int seriesID, int episodeID)
{
- VDR_RequestPacket vrp;
- if (!vrp.init(VDR_GETSCRAPERSERIESINFO, false, 0)) return NULL;
- if (!vrp.addULONG(seriesID)) return NULL;
- if (!vrp.addULONG(episodeID)) return NULL;
+ 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;
}
#include "i18n.h"
#include "control.h"
#include "tcp.h"
+#include "image.h"
class RecInfo;
class Event;
#endif
class MovieInfo;
class SeriesInfo;
-class TVMediaInfo;
typedef std::vector<Event*> EventList;
typedef std::vector<Channel*> ChannelList;
//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&);
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()
{
#include "channel.h"
#include "i18n.h"
#include "log.h"
+#include "osd.h"
#include "vepg.h"
#include "vepgsettimer.h"
#include "vepg.h"
#include "staticartwork.h"
+#include "image.h"
+#include "imageloader.h"
#include "vepglistadvanced.h"
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);
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);
}
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);
}
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);
}
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;
}
}
eventText = fmt::format("\n{}", chan->name);
}
- TVMediaInfo* info = new TVMediaInfo();
if ((*chanList)[listIndex]->number == channelNumber)
{
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;
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);
description << toShow->subtitle << "\n";
description << toShow->description;
- TVMedia poster;
+ TVMediaStruct poster;
poster.height = 0;
if (toShow->movieInfo)
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
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
#include "wmovieview.h"
#include "wseriesview.h"
#include "wpictureview.h"
+#include "imageloader.h"
#include "vepgsummary.h"
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;
}
}
if (poster.height) {
- epgTVmedia.setTVMedia(poster.info, WTVMedia::ZoomHorizontal);
+ epgTVmedia.setImage(poster.image, WTVMedia::ZoomHorizontal);
epgTVmedia.setVisible(true);
} else {
epgTVmedia.setVisible(false);
#include "message.h"
#include "control.h"
#include "staticartwork.h"
+#include "imageloader.h"
#ifdef VOMP_PLATTFORM_MVP
#include "mediaoptions.h"
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();
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) {
}
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);
}
}
#include "movieinfo.h"
#include "seriesinfo.h"
#include "staticartwork.h"
+#include "image.h"
+#include "imageloader.h"
+#include "osd.h"
#include "vrecordinglistadvanced.h"
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);
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;
}
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;
}
description << tr("Summary unavailable");
}
- TVMedia poster;
+ TVMediaStruct poster;
poster.height=0;
if (toShow->movieInfo) {
poster=toShow->movieInfo->poster;
}
}
if (poster.height) {
- epgTVmedia.setTVMedia(poster.info, WTVMedia::ZoomHorizontal);
+ epgTVmedia.setImage(poster.image, WTVMedia::ZoomHorizontal);
epgTVmedia.setVisible(true);
} else {
epgTVmedia.setVisible(false);
#include "vquestion.h"
#include "messagequeue.h"
#include "staticartwork.h"
+#include "imageloader.h"
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);
}
#include "vinfo.h"
#include "log.h"
#include "staticartwork.h"
+#include "imageloader.h"
#include "vtimerlist.h"
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);
#include "staticartwork.h"
#include "demuxer.h"
#include "messagequeue.h"
+#include "imageloader.h"
#include "vvideolivetv.h"
// 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);
}
//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;
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);
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);
}
}
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())
if (toShow)
{
- TVMedia poster;
+ TVMediaStruct poster;
poster.height=0;
bool posterscale=true;
if (toShow->movieInfo) {
}
}
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);
#include "control.h"
#include "osd.h"
+#include "osdvector.h"
#include "wsymbol.h"
#include "audio.h"
#include "vdr.h"
createBuffer();
setBackgroundColour(DrawStyle::TRANSPARENT);
- OsdVector* osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
+ OsdVector* osdv = dynamic_cast<OsdVector*>(Osd::getInstance());
if (osdv)
{
osdv->updateBackgroundColor(DrawStyle::BLACK);
#include "boxstack.h"
#include "vopts.h"
#include "staticartwork.h"
+#include "image.h"
+#include "imageloader.h"
#include "vwelcome.h"
#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
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);
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);
}
-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)
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++;
}
}
}
}
-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);
}
#include "defines.h"
#include "boxx.h"
+#include "image.h"
+#include "imageloader.h"
class Colour;
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);
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;
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);
};
#include "boxx.h"
#include "wselectlist.h"
-class Input;
+class InputMan;
class Message;
class WRemoteConfig : public Boxx
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;
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;
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;
}
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;
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;
}
#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
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; }
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;
/*
- 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);
+}
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
{
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