]> git.vomp.tv Git - vompserver.git/blob - picturereader.c
Add VDR_GETRECINFO2 call to return additional rec info
[vompserver.git] / picturereader.c
1 #include "picturereader.h"
2 #include <vdr/plugin.h>
3 #include <vdr/channels.h>
4 #include <sstream>
5 #include <algorithm>
6
7
8 PictureReader::PictureReader(VompClient *client)
9 {
10   logger = Log::getInstance();
11   inittedOK = 0;
12   tcp = NULL;
13   x = client;
14
15   pthread_mutex_init(&pictureLock, NULL);
16 }  
17
18 int PictureReader::init(TCP* ttcp)
19 {
20   tcp = ttcp;
21   threadStart();
22
23   return inittedOK;
24 }
25
26 PictureReader::~PictureReader()
27 {
28    threadStop();
29 }
30
31 void PictureReader::addTVMediaRequest(TVMediaRequest& req)
32 {
33     logger->log("PictRead",Log::DEBUG,"Got TVMediaRequest, signal thread!");
34
35     pthread_mutex_lock(&pictureLock);
36     pictures.push(req);
37     threadSignal(); // Signal, that we have something to do!!!
38     pthread_mutex_unlock(&pictureLock);
39 }
40
41 bool PictureReader::epgImageExists(int event)
42 {
43     if (x->imageDir) {
44         std::ostringstream file;
45         file<< std::string(x->imageDir)<< event << std::string(".jpg");
46         if (!access(file.str().c_str() ,F_OK))
47         {
48             return true;
49         }
50
51         std::ostringstream file2;
52         file2 << std::string(x->imageDir) << event << std::string("_0.jpg");
53         if (!access(file2.str().c_str() ,F_OK))
54         {
55             return true;
56         }
57     } else if (x->cacheDir) {
58
59         std::ostringstream file;
60         file<<std::string(x->cacheDir)<<std::string("/../epgimages/")
61                 << event << std::string(".jpg");
62         if (!access(file.str().c_str() ,F_OK))
63         {
64             return true;
65         }
66         std::ostringstream file2;
67         file2<<std::string(x->cacheDir)<<std::string("/../epgimages/")<<
68              event <<std::string("_0.jpg");
69         if (!access(file2.str().c_str() ,F_OK))
70         {
71             return true;
72         }
73     }
74     return false; 
75 }
76
77 std::string PictureReader::getPictName(TVMediaRequest & req)
78 {
79    logger->log("PictRead",Log::DEBUG,
80         "Request %d %d;  %d %d %d %d",req.primary_id,req.secondary_id,
81          req.type,req.type_pict,
82         req.container,req.container_member);
83
84    switch (req.type) {
85    case 0: { //serie
86       if (series.seriesId != (int)req.primary_id ||
87           series.episodeId != (int)req.secondary_id) {
88           series.actors.clear();
89           series.posters.clear();
90           series.banners.clear();
91           series.fanarts.clear();
92
93           series.seriesId = req.primary_id;
94           series.episodeId = req.secondary_id;
95           x->scraper->Service("GetSeries",&series);
96       }
97       if (req.type_pict == 0) {
98         switch (req.container) {
99         case 0: {
100            return series.episode.episodeImage.path;
101         } break;
102         case 1: {
103           if (series.actors.size()>req.container_member) {
104                 return series.actors[req.container_member].actorThumb.path;
105           }
106         } break;
107         case 2: {
108           if (series.posters.size()>req.container_member) {
109                 return series.posters[req.container_member].path;
110           }
111         } break;
112         case 3: {
113           if (series.banners.size()>req.container_member) {
114                 return series.banners[req.container_member].path;
115           }
116         } break;
117         case 4: {
118           if (series.fanarts.size()>req.container_member) {
119                 return series.fanarts[req.container_member].path;
120           }
121         } break;
122         case 5: {
123            return series.seasonPoster.path;
124         } break;
125         default: {
126            return std::string("");
127            } break;
128         };
129       } else if (req.type_pict == 1 && series.posters.size()) { //poster
130            std::string str=series.posters[0].path;
131            size_t  pos=str.rfind('/');
132            if (pos!=std::string::npos) {
133               str.resize(pos);
134               str=str+"poster_thumb.jpg";
135               return str;
136            }
137         } else if (req.type_pict == 2) { //poster
138            std::string str=series.seasonPoster.path;
139            size_t  pos=str.rfind('/');
140            if (pos!=std::string::npos) {
141               str.resize(pos);
142               std::ostringstream out;
143               out << str << "season_" <<series.episode.season <<"_thumb.jpg";
144               return out.str();
145            }
146         } 
147        return std::string("");
148    } break;
149    case 1: { //movie
150       if (movie.movieId != (int)req.primary_id ) {
151           movie.actors.clear();
152           movie.movieId = req.primary_id;
153           x->scraper->Service("GetMovie",&movie);
154       }
155       if (req.type_pict == 0) {
156
157         switch (req.container) {
158         case 0: {
159            return movie.poster.path;
160         } break;
161         case 1: {
162            return movie.fanart.path;
163         } break;
164         case 2: {
165            return movie.collectionPoster.path;
166         } break;
167         case 3: {
168            return movie.collectionFanart.path;
169         } break;
170         case 4: {
171           if (movie.actors.size()>req.container_member) {
172                 return movie.actors[req.container_member].actorThumb.path;
173           }
174         } break;
175         default: {
176            return std::string("");
177            } break;
178         };
179     } else if (req.type_pict == 1) { //poster
180         std::string str=movie.poster.path;
181         size_t  pos=str.rfind('/');
182         if (pos!=std::string::npos) {
183            str.resize(pos);
184            str=str+"poster_thumb.jpg";
185            return str;
186         }
187     } 
188     return std::string("");
189       
190    
191    } break;
192    case 3: { // I do not know
193    // First get the recording
194 #if VDRVERSNUM >= 20301
195       LOCK_RECORDINGS_READ;
196       const cRecordings* tRecordings = Recordings;
197 #else
198       cThreadLock RecordingsLock(&Recordings);
199       cRecordings* tRecordings = &Recordings;
200 #endif
201       const cRecording *recording = tRecordings->GetByName((char*) req.primary_name.c_str());
202       ScraperGetPosterThumb getter;
203       getter.recording = recording;
204       getter.event = NULL;
205       if (x->scraper && recording) {
206         x->scraper->Service("GetPosterThumb",&getter);
207         return getter.poster.path;
208       } else {
209          return std::string("");
210       }
211    }; break;
212    case 4: { // I do not know
213    // First get the schedules
214
215 #if VDRVERSNUM >= 20301
216   LOCK_CHANNELS_READ;
217   const cChannels* tChannels = Channels;
218 #else
219   cChannels* tChannels = &Channels;
220 #endif
221
222
223 #if VDRVERSNUM < 10300
224       cMutexLock MutexLock;
225       const cSchedules *tSchedules = cSIProcessor::Schedules(MutexLock);
226 #elif VDRVERSNUM < 20301
227       cSchedulesLock MutexLock;
228       const cSchedules *tSchedules = cSchedules::Schedules(MutexLock);
229 #else
230       LOCK_SCHEDULES_READ;
231       const cSchedules *tSchedules = Schedules;
232 #endif
233
234       const cSchedule *Schedule = NULL;
235       if (tSchedules)
236       {
237         const cChannel* channel = tChannels->GetByChannelID(tChannelID::FromString(req.primary_name.c_str()));
238         Schedule = tSchedules->GetSchedule(channel);
239       }
240       const cEvent *event = NULL;
241       if (Schedule) event=Schedule->GetEvent(req.primary_id);
242       ScraperGetPosterThumb getter;
243       getter.event = event;
244       getter.recording = NULL;
245
246       if (x->scraper && event) {
247         x->scraper->Service("GetPosterThumb",&getter);
248         if (getter.poster.width) return getter.poster.path;
249       }
250       if (x->imageDir) {
251         std::ostringstream file;
252         file<< std::string(x->imageDir)<< req.primary_id << std::string(".jpg");
253         if (!access(file.str().c_str() ,F_OK))
254         {
255             return file.str();
256         }
257
258         std::ostringstream file2;
259         file2 << std::string(x->imageDir) << req.primary_id << std::string("_0.jpg");
260         if (!access(file2.str().c_str() ,F_OK))
261         {
262             return file2.str();
263         }
264       } else if (x->cacheDir) {
265
266         std::ostringstream file;
267         file<<std::string(x->cacheDir)<<std::string("/../epgimages/")
268                 <<req.primary_id << std::string(".jpg");
269         if (!access(file.str().c_str() ,F_OK))
270         {
271             return file.str();
272         }
273         std::ostringstream file2;
274         file2<<std::string(x->cacheDir)<<std::string("/../epgimages/")<<
275              req.primary_id<<std::string("_0.jpg");
276         if (!access(file2.str().c_str() ,F_OK))
277         {
278             return file2.str();
279         }
280       } 
281       return std::string("");
282    }; break;
283    case 5: { // Channel logo
284         std::transform(req.primary_name.begin(),req.primary_name.end(),
285             req.primary_name.begin(),::tolower);
286         if (x->logoDir) {
287            std::string file=std::string(x->logoDir)+req.primary_name+std::string(".png");
288            if (!access(file.c_str() ,F_OK))
289            {
290               return file;
291            }
292         }
293         // if noopacity is there steal the logos
294         if (x->resourceDir) {
295             std::string file=std::string(x->resourceDir)
296                                 +std::string("/skinnopacity/logos/")+req.primary_name+std::string(".png");
297             if (!access(file.c_str() ,F_OK))
298             {
299                 return file;
300             }
301         }
302         return std::string("");
303
304    
305    }; break;
306    default:
307      return std::string("");
308      break;
309    };
310    return std::string("");
311    
312 }
313
314
315 void PictureReader::threadMethod()
316 {
317   ULONG *p;
318   ULONG headerLength = sizeof(ULONG) * 4;
319   UCHAR buffer[headerLength];
320
321 //   threadSetKillable(); ??
322
323   logger->log("PictRead",Log::DEBUG,"PictureReaderThread started");
324   while(1)
325   {
326     threadLock();
327     threadWaitForSignal();
328     threadUnlock();
329     threadCheckExit();
330     bool newpicture;
331     logger->log("PictRead",Log::DEBUG,"Thread was signaled, wake up");
332
333     do
334     {
335       newpicture = false;
336       TVMediaRequest req;
337       pthread_mutex_lock(&pictureLock);
338       if (!pictures.empty()) {
339          newpicture = true;
340          req = pictures.front();
341          pictures.pop();
342       }
343       pthread_mutex_unlock(&pictureLock);
344       if (!newpicture) break;
345       std::string pictname = getPictName(req);
346       UCHAR * mem = NULL;
347       ULONG memsize = 0;
348       ULONG flag = 2;
349       logger->log("PictRead",Log::DEBUG,"Load Pict %s",pictname.c_str());
350
351       
352       if (pictname.length()) {
353          struct stat st;
354          ULONG filesize = 0 ;
355
356          stat(pictname.c_str(), &st);
357          filesize = st.st_size;
358          memsize = filesize + headerLength;
359
360          if (memsize && memsize < 1000000) { // No pictures over 1 MB
361             mem = (UCHAR*)malloc(memsize);
362             if (mem) {
363                 FILE * file=fopen(pictname.c_str(),"r");
364
365                 if (file) {
366                     size_t size=fread(mem+headerLength,1,filesize,file);
367
368                     fclose(file);
369                     if (size!=filesize) memsize=headerLength; // error
370                     else flag = 0;
371                 }
372              }
373            } 
374        } 
375        if (!mem) {
376           mem = buffer;
377        }
378
379          
380     
381       p = (ULONG*)&mem[0]; *p = htonl(5); // stream channel
382       p = (ULONG*)&mem[4]; *p = htonl(req.streamID);
383       p = (ULONG*)&mem[8]; *p = htonl(flag); // here insert flag: 0 = ok, data follows
384       p = (ULONG*)&mem[12]; *p = htonl(memsize);
385
386       if (!tcp->sendPacket(mem, memsize + headerLength)) {
387           logger->log("PictRead",Log::DEBUG,"Sending Picture failed");
388       }
389
390       if (mem != buffer && mem) free(mem);
391
392     } while (newpicture);
393   }
394   logger->log("PictRead",Log::DEBUG,"PictureReaderThread ended");
395   
396 }
397