2 Copyright 2021 Chris Tallon
3 Portions Copyright 2014 Marten Richter
5 This file is part of VOMP.
7 VOMP is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 VOMP is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with VOMP. If not, see <https://www.gnu.org/licenses/>.
25 * The new Image system, 2021.
27 * There are several image types that the client deals with:
28 * * Static images - these are built into the binary and are mostly small PNG icons
30 * * Recording thumbnails (and ones for folders)
32 * * "Generic" images loaded for the larger event display(?)
34 * The Image base class represents all these and is to be used in and around Views
35 * to refer to images. __An Image object (via the derived classes) describes a
36 * particular image to display, but does not hold actual image data__.
38 * Each Image type above has a derived class to hold information specific about that
39 * type of image. E.g. a recording thumbnail image stores the recording filename.
41 * Future work: Investigate removing WSymbol and all related stuff, maybe including
42 * the DrawBitmap stuff in OsdVector. Surely this is all there to support the very
43 * basic bitmap symbols - this call all be replaced with PNGs.
45 * Image objects may only be instantiated by calling a ImageLoader::create___
46 * method. ImageLoader caches all existing Image objects and if an exact duplicate
47 * would be created by a create method then the existing Image object will be
48 * returned instead. This is normally done by returning a copy of the existing
49 * Image. However, if the request is unique but the VDR load fails, and the Image
50 * has a static-artwork fallback, then either:
51 * * The existing static-artwork is still waiting to be decoded - your Image object
52 * will contain Image.otherImage pointing to the first image which requested that
54 * * The existing static-artwork is ready - your Image object will have a normal
55 * OsdImage object (which will be a copy of the first one) - see later.
57 * The "Image" type is actually a shared_ptr<CImage> so as many Image object
58 * copies can be made as necessary, there will only ever be one real CImage object
59 * per unique image description.
63 * An OsdImage represents a real image held in hardware / graphics memory / whatever
64 * layer is actually providing graphics. Derived classes from OsdImage contain
65 * the real hardware handles for each type of OSD - e.g. OsdOpenVG OsdImage objects
68 * Tye "OsdImage" is actually a shared_ptr<OsdImageBase> so as many copies can
69 * be made as necessary, there will only ever be one copy of the image data held
70 * in the real graphics layer.
72 * The link between Image objects and OsdImage objects:
74 * An Image object without a contained OsdImage object is waiting for it to be
75 * loaded from VDR or to be decoded locally.
77 * An Image object with an OsdImage object may have a unique OsdImage or it may
78 * be shared between many Image objects. ImageLoader will assign the Image an
79 * appropriate OsdImage when it is downloaded and/or decoded.
83 * All Image objects have their first copy in mImages in ImageLoader. All OsdImages
84 * have their first copy in images in Osd. OsdVector::cleanupOrphanedRefs() calls
85 * ImageLoader::garbageCollect() to delete Images, and it calls
86 * Osd::garbageCollectOsdImages() to delete OsdImages - this should be overridden
87 * by the actual Osd implementation e.g. OsdOpenVG as it will know how to destroy
88 * the underlying hardware reference. Both garbage collectors delete any Image /
89 * OsdImage object that has a use-count of 1 (their first/master copy).
91 * Reasons for the upgrade:
93 * The new system allows failed VDR loads to fallback to static images and to use
94 * pre-existing static images. This vastly speeds up the recordingslist for example,
95 * where VDR holds no images for recordings.
97 * Code readability - The ref-counting system in OsdVector was very manual and
98 * difficult to follow. This is now all handled by shared_ptrs.
100 * TVMedia objects before were deep-copied and deep-compared. Now the actual
101 * objects are unique and have multiple shared_ptrs for them.
103 * Should be more extendable for new Image types in future if needed.
105 * Other Osd implementations:
107 * Will need significant updating to the new system, but the hope is it should
108 * be simpler and more logical.
122 class CImageRecFolder;
123 class CImageRecThumb;
124 class CImageEventThumb;
125 class CImageChannelLogo;
126 using Image = std::shared_ptr<CImage>;
127 using ImageStatic = std::shared_ptr<CImageStatic>;
128 using ImageGeneric = std::shared_ptr<CImageGeneric>;
129 using ImageRecFolder = std::shared_ptr<CImageRecFolder>;
130 using ImageRecThumb = std::shared_ptr<CImageRecThumb>;
131 using ImageEventThumb = std::shared_ptr<CImageEventThumb>;
132 using ImageChannelLogo = std::shared_ptr<CImageChannelLogo>;
134 // FIXME - Is there much point having the shared_ptr system for the derived objects?
135 // See OsdImage which doesn't do this.
139 friend class ImageLoader;
142 enum ImageType { INVALID, STATIC, GENERIC, RECFOLDER, RECTHUMB, EVENTTHUMB, CHANNELLOGO };
144 ImageType getType() { return type; }
145 bool isReady() { return ready; }
146 OsdImage getOsdImage() { return osdImage; }
149 ImageType type{INVALID};
151 std::mutex stateLock;
155 bool usingFallback{};
156 int staticArtworkID{-1};
157 u4 serverLoadingRef{};
159 Image otherImage; // If set, this image will use otherImage's osdImage when it is ready
162 class CImageStatic : public CImage
164 friend class ImageLoader;
169 class CImageGeneric : public CImage
171 friend class ImageLoader;
175 void setSeriesInfo(const SeriesInfo* si);
176 void setMovieInfo(const MovieInfo* mi);
177 void setElement(int cont, int memb) { type_pict = 0; container = cont; container_member = memb; }
182 int type{2}; // 1 = movie, 2 = series
183 int type_pict{-1}; // 0 full info, 1 poster thumb, 2 season thumb - OR -
184 // 0 full info, 1 poster, 2 poster banner, 3 poster thumb -- BUT which is true?!
185 int container{-1}; // indices the dataelements with picture in movieinfo or seriesinfo
186 int container_member{-1}; // index into the container
189 class CImageRecFolder : public CImage
191 friend class ImageLoader;
194 std::string fileName;
197 class CImageRecThumb : public CImage
199 friend class ImageLoader;
202 const char* getFileName() { return fileName.c_str(); }
203 void setServerLoadingRef(u4 slr) { serverLoadingRef = slr; }
206 std::string fileName;
209 class CImageEventThumb : public CImage
211 friend class ImageLoader;
214 u4 getChannel() { return channel; }
215 u4 getEvent() { return event; }
216 void setServerLoadingRef(u4 slr) { serverLoadingRef = slr; }
223 class CImageChannelLogo : public CImage
225 friend class ImageLoader;
228 u4 getChannelID() { return channel; }
229 void setServerLoadingRef(u4 slr) { serverLoadingRef = slr; }
235 ////////////////////////////////////////////////////////////////////////////////////////
237 struct TVMediaStruct // FIXME Hopefully roll this in above
239 unsigned int width{};
240 unsigned int height{};
251 typedef std::vector<Actor> Actors;
253 typedef std::vector<TVMediaStruct> TVMedias;
260 Old TVMedia types information:
263 1 | - "movie or series"
265 3 poster thumb (char* recname)
267 5 poster thumb (channel, eventid)
270 const static u4 VDR_LOADTVMEDIA = 41; 0,1,2
271 const static u4 VDR_LOADTVMEDIARECTHUMB = 42; 3
272 const static u4 VDR_LOADTVMEDIAEVENTTHUMB = 44; 5
273 const static u4 VDR_LOADCHANNELLOGO = 45; 6
275 Types 3, 4, 5, 6 are handled by create*() methods in ImageLoader.
276 Types 0, 1, 2 (though probably only 2 of these) are created with ImageLoader::createGeneric().
278 After a createGeneric() only, caller must fill the Image with more information and then call
279 imageLoader->ensureLoaded(image) to kick off loading the image from VDR.