]> git.vomp.tv Git - vompclient.git/blob - src/image.h
Type updates:
[vompclient.git] / src / image.h
1 /*
2     Copyright 2021 Chris Tallon
3     Portions Copyright 2014 Marten Richter
4
5     This file is part of VOMP.
6
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.
11
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.
16
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/>.
19 */
20
21 #ifndef IMAGE_H
22 #define IMAGE_H
23
24 /*
25  * The new Image system, 2021.
26  *
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
29  * * Channel logos
30  * * Recording thumbnails (and ones for folders)
31  * * Event thumbnails
32  * * "Generic" images loaded for the larger event display(?)
33  *
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__.
37  *
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.
40  *
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.
44  *
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
53  *   static-artwork.
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.
56  *
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.
60  *
61  * OsdImages
62  *
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
66  * contain a VGImage.
67  *
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.
71  *
72  * The link between Image objects and OsdImage objects:
73  *
74  * An Image object without a contained OsdImage object is waiting for it to be
75  * loaded from VDR or to be decoded locally.
76  *
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.
80  *
81  * Deletion
82  *
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).
90  *
91  * Reasons for the upgrade:
92  *
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.
96  *
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.
99  *
100  * TVMedia objects before were deep-copied and deep-compared. Now the actual
101  * objects are unique and have multiple shared_ptrs for them.
102  *
103  * Should be more extendable for new Image types in future if needed.
104  *
105  * Other Osd implementations:
106  *
107  * Will need significant updating to the new system, but the hope is it should
108  * be simpler and more logical.
109 */
110
111 #include <memory>
112 #include <mutex>
113 #include <string>
114 #include <vector>
115
116 #include "defines.h"
117 #include "osd.h"
118
119 class CImage;
120 class CImageStatic;
121 class CImageGeneric;
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>;
133
134 // FIXME - Is there much point having the shared_ptr system for the derived objects?
135 // See OsdImage which doesn't do this.
136
137 class CImage
138 {
139   friend class ImageLoader;
140
141   public:
142     enum ImageType { INVALID, STATIC, GENERIC, RECFOLDER, RECTHUMB, EVENTTHUMB, CHANNELLOGO };
143
144     ImageType getType() { return type; }
145     bool isReady() { return ready; }
146     OsdImage getOsdImage() { return osdImage; }
147
148   protected:
149     ImageType type{INVALID};
150
151     std::mutex stateLock;
152     bool ready{};
153     bool loading{};
154     bool failed{};
155     bool usingFallback{};
156     int staticArtworkID{-1};
157     u4 serverLoadingRef{};
158     OsdImage osdImage;
159     Image otherImage; // If set, this image will use otherImage's osdImage when it is ready
160 };
161
162 class CImageStatic : public CImage
163 {
164   friend class ImageLoader;
165 };
166
167 class SeriesInfo;
168 class MovieInfo;
169 class CImageGeneric : public CImage
170 {
171   friend class ImageLoader;
172   friend class VDR;
173
174   public:
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; }
178
179   private:
180     int primary_id{};
181     int secondary_id{};
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
187 };
188
189 class CImageRecFolder : public CImage
190 {
191   friend class ImageLoader;
192
193   private:
194     std::string fileName;
195 };
196
197 class CImageRecThumb : public CImage
198 {
199   friend class ImageLoader;
200
201   public:
202     const char* getFileName() { return fileName.c_str(); }
203     void setServerLoadingRef(u4 slr) { serverLoadingRef = slr; }
204
205   private:
206     std::string fileName;
207 };
208
209 class CImageEventThumb : public CImage
210 {
211   friend class ImageLoader;
212
213   public:
214     u4 getChannel() { return channel; }
215     u4 getEvent() { return event; }
216     void setServerLoadingRef(u4 slr) { serverLoadingRef = slr; }
217   private:
218     u4 channel{};
219     u4 event{};
220
221 };
222
223 class CImageChannelLogo : public CImage
224 {
225   friend class ImageLoader;
226
227   public:
228     u4 getChannelID() { return channel; }
229     void setServerLoadingRef(u4 slr) { serverLoadingRef = slr; }
230   private:
231     u4 channel{};
232 };
233
234
235 ////////////////////////////////////////////////////////////////////////////////////////
236
237 struct TVMediaStruct     // FIXME Hopefully roll this in above
238 {
239   unsigned int width{};
240   unsigned int height{};
241   Image image;
242 };
243
244 struct Actor
245 {
246   std::string name;
247   std::string role;
248   TVMediaStruct thumb;
249 };
250
251 typedef std::vector<Actor> Actors;
252
253 typedef std::vector<TVMediaStruct> TVMedias;
254
255
256 #endif
257
258 /*
259
260 Old TVMedia types information:
261
262 0 \
263 1 | - "movie or series"
264 2 /
265 3 poster thumb (char* recname)
266 4 static
267 5 poster thumb (channel, eventid)
268 6 channel logo
269
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
274
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().
277
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.
280
281 */