]> git.vomp.tv Git - vompserver.git/blob - picturereader.c
Raise recording playback get-block limit to 1MB
[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 != req.primary_id ||
87           series.episodeId != 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 != 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   int amountReceived;
299
300 //   threadSetKillable(); ??
301
302   logger->log("PictRead",Log::DEBUG,"PictureReaderThread started");
303   while(1)
304   {
305     threadLock();
306     threadWaitForSignal();
307     threadUnlock();
308     threadCheckExit();
309     bool newpicture;
310     logger->log("PictRead",Log::DEBUG,"Thread was signaled, wake up");
311
312     do
313     {
314       newpicture = false;
315       TVMediaRequest req;
316       pthread_mutex_lock(&pictureLock);
317       if (!pictures.empty()) {
318          newpicture = true;
319          req = pictures.front();
320          pictures.pop();
321       }
322       pthread_mutex_unlock(&pictureLock);
323       if (!newpicture) break;
324       std::string pictname = getPictName(req);
325       UCHAR * mem = NULL;
326       ULONG memsize = 0;
327       ULONG flag = 2;
328       logger->log("PictRead",Log::DEBUG,"Load Pict %s",pictname.c_str());
329
330       
331       if (pictname.length()) {
332          struct stat st;
333          ULONG filesize = 0 ;
334
335          stat(pictname.c_str(), &st);
336          filesize = st.st_size;
337          memsize = filesize + headerLength;
338
339          if (memsize && memsize < 1000000) { // No pictures over 1 MB
340             mem = (UCHAR*)malloc(memsize);
341             if (mem) {
342                 FILE * file=fopen(pictname.c_str(),"r");
343
344                 if (file) {
345                     size_t size=fread(mem+headerLength,1,filesize,file);
346
347                     fclose(file);
348                     if (size!=filesize) memsize=headerLength; // error
349                     else flag = 0;
350                 }
351              }
352            } 
353        } 
354        if (!mem) {
355           mem = buffer;
356        }
357
358          
359     
360       p = (ULONG*)&mem[0]; *p = htonl(5); // stream channel
361       p = (ULONG*)&mem[4]; *p = htonl(req.streamID);
362       p = (ULONG*)&mem[8]; *p = htonl(flag); // here insert flag: 0 = ok, data follows
363       p = (ULONG*)&mem[12]; *p = htonl(memsize);
364
365       if (!tcp->sendPacket(mem, memsize + headerLength)) {
366           logger->log("PictRead",Log::DEBUG,"Sending Picture failed");
367       }
368
369       if (mem != buffer && mem) free(mem);
370
371     } while (newpicture);
372   }
373   logger->log("PictRead",Log::DEBUG,"PictureReaderThread ended");
374   
375 }
376