]> git.vomp.tv Git - vompserver.git/blob - picturereader.c
Fix calls to VDRs Channels.GetByNumber
[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       cRecordings Recordings;
195       Recordings.Load();
196       cRecording *recording = Recordings.GetByName((char*) req.primary_name.c_str());
197       ScraperGetPosterThumb getter;
198       getter.recording = recording;
199       getter.event = NULL;
200       if (x->scraper && recording) {
201         x->scraper->Service("GetPosterThumb",&getter);
202         return getter.poster.path;
203       } else {
204          return std::string("");
205       }
206    }; break;
207    case 4: { // I do not know
208    // First get the schedules
209       cSchedulesLock MutexLock;
210       const cSchedules *Schedules = cSchedules::Schedules(MutexLock);
211       const cSchedule *Schedule = NULL;
212       if (Schedules)
213       {
214         cChannel * channel = Channels.GetByChannelID(
215                        tChannelID::FromString(req.primary_name.c_str()));
216         Schedule = Schedules->GetSchedule(channel);
217       }
218       const cEvent *event = NULL;
219       if (Schedule) event=Schedule->GetEvent(req.primary_id);
220       ScraperGetPosterThumb getter;
221       getter.event = event;
222       getter.recording = NULL;
223
224       if (x->scraper && event) {
225         x->scraper->Service("GetPosterThumb",&getter);
226         if (getter.poster.width) return getter.poster.path;
227       }
228       if (x->imageDir) {
229         std::ostringstream file;
230         file<< std::string(x->imageDir)<< req.primary_id << std::string(".jpg");
231         if (!access(file.str().c_str() ,F_OK))
232         {
233             return file.str();
234         }
235
236         std::ostringstream file2;
237         file2 << std::string(x->imageDir) << req.primary_id << std::string("_0.jpg");
238         if (!access(file2.str().c_str() ,F_OK))
239         {
240             return file2.str();
241         }
242       } else if (x->cacheDir) {
243
244         std::ostringstream file;
245         file<<std::string(x->cacheDir)<<std::string("/../epgimages/")
246                 <<req.primary_id << std::string(".jpg");
247         if (!access(file.str().c_str() ,F_OK))
248         {
249             return file.str();
250         }
251         std::ostringstream file2;
252         file2<<std::string(x->cacheDir)<<std::string("/../epgimages/")<<
253              req.primary_id<<std::string("_0.jpg");
254         if (!access(file2.str().c_str() ,F_OK))
255         {
256             return file2.str();
257         }
258       } 
259       return std::string("");
260    }; break;
261    case 5: { // Channel logo
262         std::transform(req.primary_name.begin(),req.primary_name.end(),
263             req.primary_name.begin(),::tolower);
264         if (x->logoDir) {
265            std::string file=std::string(x->logoDir)+req.primary_name+std::string(".png");
266            if (!access(file.c_str() ,F_OK))
267            {
268               return file;
269            }
270         }
271         // if noopacity is there steal the logos
272         if (x->resourceDir) {
273             std::string file=std::string(x->resourceDir)
274                                 +std::string("/skinnopacity/logos/")+req.primary_name+std::string(".png");
275             if (!access(file.c_str() ,F_OK))
276             {
277                 return file;
278             }
279         }
280         return std::string("");
281
282    
283    }; break;
284    default:
285      return std::string("");
286      break;
287    };
288    return std::string("");
289    
290 }
291
292
293 void PictureReader::threadMethod()
294 {
295   ULONG *p;
296   ULONG headerLength = sizeof(ULONG) * 4;
297   UCHAR buffer[headerLength];
298
299 //   threadSetKillable(); ??
300
301   logger->log("PictRead",Log::DEBUG,"PictureReaderThread started");
302   while(1)
303   {
304     threadLock();
305     threadWaitForSignal();
306     threadUnlock();
307     threadCheckExit();
308     bool newpicture;
309     logger->log("PictRead",Log::DEBUG,"Thread was signaled, wake up");
310
311     do
312     {
313       newpicture = false;
314       TVMediaRequest req;
315       pthread_mutex_lock(&pictureLock);
316       if (!pictures.empty()) {
317          newpicture = true;
318          req = pictures.front();
319          pictures.pop();
320       }
321       pthread_mutex_unlock(&pictureLock);
322       if (!newpicture) break;
323       std::string pictname = getPictName(req);
324       UCHAR * mem = NULL;
325       ULONG memsize = 0;
326       ULONG flag = 2;
327       logger->log("PictRead",Log::DEBUG,"Load Pict %s",pictname.c_str());
328
329       
330       if (pictname.length()) {
331          struct stat st;
332          ULONG filesize = 0 ;
333
334          stat(pictname.c_str(), &st);
335          filesize = st.st_size;
336          memsize = filesize + headerLength;
337
338          if (memsize && memsize < 1000000) { // No pictures over 1 MB
339             mem = (UCHAR*)malloc(memsize);
340             if (mem) {
341                 FILE * file=fopen(pictname.c_str(),"r");
342
343                 if (file) {
344                     size_t size=fread(mem+headerLength,1,filesize,file);
345
346                     fclose(file);
347                     if (size!=filesize) memsize=headerLength; // error
348                     else flag = 0;
349                 }
350              }
351            } 
352        } 
353        if (!mem) {
354           mem = buffer;
355        }
356
357          
358     
359       p = (ULONG*)&mem[0]; *p = htonl(5); // stream channel
360       p = (ULONG*)&mem[4]; *p = htonl(req.streamID);
361       p = (ULONG*)&mem[8]; *p = htonl(flag); // here insert flag: 0 = ok, data follows
362       p = (ULONG*)&mem[12]; *p = htonl(memsize);
363
364       if (!tcp->sendPacket(mem, memsize + headerLength)) {
365           logger->log("PictRead",Log::DEBUG,"Sending Picture failed");
366       }
367
368       if (mem != buffer && mem) free(mem);
369
370     } while (newpicture);
371   }
372   logger->log("PictRead",Log::DEBUG,"PictureReaderThread ended");
373   
374 }
375