]> git.vomp.tv Git - vompclient.git/blob - osdvector.cc
Add recording option to VEpgSummary
[vompclient.git] / osdvector.cc
1 /*
2     Copyright 2012 Marten Richter
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21 #include "osdvector.h"
22 #include "surfacevector.h"
23 #include "vdr.h"
24 #include "vdrresponsepacket.h"
25 #include "command.h"
26 #include "message.h"
27
28 // The next section is activated, if the magick++ PictureReader is provided, it should be available for many POSIX platforms
29 #ifdef PICTURE_DECODER_MAGICK
30 #include <Magick++.h>
31
32 using namespace Magick;
33
34 class MagickDecoder: public OsdVector::PictureDecoder {
35 public:
36         MagickDecoder(OsdVector::PictureReader* treader): OsdVector::PictureDecoder(treader) {pictInfValid=false;};
37
38         bool decodePicture(LoadIndex index, unsigned char * buffer, unsigned int length, bool freemem);
39
40     bool getDecodedPicture( struct OsdVector::PictureInfo& pict_inf);
41
42     void freeReference(void * ref);
43
44 protected:
45     OsdVector::PictureInfo pictInf;
46         bool pictInfValid;
47 };
48
49 bool MagickDecoder::decodePicture(LoadIndex index, unsigned char * buffer, unsigned int length, bool freemem)
50 {
51         if (pictInfValid) return false; // does support only one image at a Time;
52         Image magicimage;
53         Blob *imageblob = new Blob();
54
55         try{
56                 Log::getInstance()->log("MagickDecoder", Log::DEBUG, "decodePicture");
57                 Blob myblob;
58                 if (freemem) myblob.updateNoCopy(buffer,length,Blob::MallocAllocator);
59                 else myblob.update(buffer,length);
60                 magicimage.read(myblob);
61
62                 magicimage.write(imageblob,"RGBA");
63
64         }catch( Exception &error_ )
65         {
66                 Log::getInstance()->log("MagickDecoder", Log::DEBUG, "Libmagick: %s",error_.what());
67                 delete imageblob;
68
69                 return false;
70         }
71         pictInf.reference = (void*) imageblob;
72         pictInf.width = magicimage.columns();
73         pictInf.height = magicimage.rows();
74         pictInf.image = imageblob->data();
75         pictInf.decoder = this;
76         pictInf.type = OsdVector::PictureInfo::RGBAMemBlock;
77         pictInf.lindex = index;
78         pictInfValid = true;
79
80
81
82         // I can handle everything, so the return value is always true
83         return true;
84 }
85 void MagickDecoder::freeReference(void * ref)
86 {
87         Blob *todelete = (Blob*) ref;
88         delete todelete;
89 }
90
91 bool MagickDecoder::getDecodedPicture(struct OsdVector::PictureInfo& pict_inf)
92 {
93         if (!pictInfValid) return false;
94         pict_inf=pictInf;
95         pictInfValid = false;
96         return true;
97 }
98
99
100 #endif
101
102 OsdVector::OsdVector()
103 {
104         setlocale(LC_CTYPE,"C.UTF-8");
105 #ifdef PICTURE_DECODER_MAGICK
106         reader.addDecoder(new MagickDecoder(&reader));
107 #endif
108
109 }
110
111 OsdVector::~OsdVector()
112 {
113 }
114
115
116 int OsdVector::getFD()
117 {
118         return 0;
119 }
120
121 void OsdVector::screenShot(const char* fileName)
122 {
123         //Do nothing,
124 }
125
126 Surface * OsdVector::createNewSurface()
127 {
128         return new SurfaceVector(this);
129 }
130
131 void OsdVector::BeginPainting()
132 {
133         surfaces_mutex.Lock();
134 }
135 void OsdVector::EndPainting()
136 {
137         surfaces_mutex.Unlock();
138 }
139
140 void OsdVector::Blank()
141 {
142         // do nothing? remove this one?
143 }
144
145 int OsdVector::restore()
146 {
147         // First clear the contents of all registered surfaces
148         surfaces_mutex.Lock();
149
150         //Now go through all surfaces and draw them
151         list<SurfaceCommands>::iterator curdraw=scommands.begin();
152         while (curdraw!=scommands.end()) {
153                 (*curdraw).commands.clear();
154                 curdraw++;
155         }
156         //also clear all handles, they are now invalid, no need to release them
157         images_ref.clear();
158         monobitmaps.clear();
159         //jpegs.clear();
160         styles.clear();
161         styles_ref.clear();
162
163         tvmedias.clear();
164         loadindex_ref.clear();
165         tvmedias_load.clear();
166         tvmedias_load_inv.clear();
167         tvmedias_loaded.clear();
168
169         surfaces_mutex.Unlock();
170         return 1;
171 }
172
173 void OsdVector::drawSurfaces()
174 {
175         surfaces_mutex.Lock();
176         list<SurfaceCommands*> todraw; //First figure out if a surfaces is below another surface
177         list<SurfaceCommands>::iterator itty1=scommands.begin();
178         while (itty1!=scommands.end()) {
179                 list<SurfaceCommands>::iterator itty2=itty1;
180                 itty2++;
181                 bool hidden=false;
182                 while (itty2!=scommands.end()) {
183                         SurfaceCommands & ref1=*itty1;
184                         SurfaceCommands & ref2=*itty2;
185                         if (ref1.x>=ref2.x && ref1.y>=ref2.y
186                                         && (ref1.x+ref1.w) <= (ref2.x+ref2.w)
187                                         && (ref1.y+ref1.h) <= (ref2.y+ref2.h) ) {
188                                 hidden=true;
189                                 break;
190                         }
191                         itty2++;
192                 }
193                 if (!hidden) { // we are not hidden, perfect
194                         todraw.push_back(&(*itty1));
195                 }
196                 itty1++;
197         }
198         int swidth,sheight;
199         getScreenSize(swidth,sheight);
200         //Now go through all surfaces and draw them
201         list<SurfaceCommands*>::iterator curdraw=todraw.begin();
202         while (curdraw!=todraw.end()) {
203                 drawSetTrans(*(*curdraw));
204                 list<SVGCommand>::iterator commands=(*(*curdraw)).commands.begin();
205                 list<SVGCommand>::iterator end=(*(*curdraw)).commands.end();
206                 while (commands!=end) {
207                         // update any images loaded in the mean time
208                         if ((*commands).instr==DrawImageLoading) {
209                                 LoadIndex loadindex=(*commands).target.loadindex;
210                                 if (tvmedias_loaded.find(loadindex)!=tvmedias_loaded.end()) {
211                                         (*commands).instr=DrawImage;
212                                         (*commands).target.image=tvmedias_loaded[loadindex];;
213                                         incImageRef((*commands).target.image);
214                                         removeLoadIndexRef(loadindex);
215                                 }
216
217                         }
218                         // Now check if the command is on screen!
219                         if  (!(*commands).Outside(0,0,swidth,sheight)) {
220                                 executeDrawCommand(*commands);
221                         }
222                         commands++;
223                 }
224                 curdraw++;
225         }
226
227         surfaces_mutex.Unlock();
228 }
229
230 void OsdVector::updateOrAddSurface(const SurfaceVector *surf,float x,float y,float height,float width,
231                         list<SVGCommand>& commands)
232 {
233         surfaces_mutex.Lock();
234         //First determine it is already in our system
235         list<SurfaceCommands>::iterator itty=scommands.begin();
236         while (itty!=scommands.end()) {
237                 if ((*itty).surf==surf) {
238                         //decrease the references
239                         dereferenceSVGCommand((*itty).commands);
240                         break;
241                 }
242                 itty++;
243         }
244         // if not insert it
245         if (itty==scommands.end()) {
246                 SurfaceCommands new_sc;
247                 new_sc.surf=surf;
248                 new_sc.x=x;
249                 new_sc.y=y;
250                 new_sc.w=width;
251                 new_sc.h=height;
252                 itty=scommands.insert(itty,new_sc);
253         }
254         // update any images loaded in the mean time
255         list<SVGCommand>::iterator ilitty=commands.begin();
256
257         while (ilitty!=commands.end())
258         {
259                 if ((*ilitty).instr==DrawImageLoading) {
260                         LoadIndex loadindex=(*ilitty).target.loadindex;
261                         if (tvmedias_loaded.find(loadindex)!=tvmedias_loaded.end()) {
262
263                                 (*ilitty).instr=DrawImage;
264                                 (*ilitty).target.image=tvmedias_loaded[loadindex];
265                                 incImageRef((*ilitty).target.image);
266                                 removeLoadIndexRef(loadindex);
267                         }
268                 }
269                 ilitty++;
270         }
271
272
273         // then clear and copy
274         (*itty).commands.clear();
275         (*itty).commands=commands;
276         //increase the references
277         referenceSVGCommand((*itty).commands);
278         cleanupOrphanedRefs();
279
280         surfaces_mutex.Unlock();
281 }
282
283 void OsdVector::removeSurface(const SurfaceVector *surf)
284 {
285         surfaces_mutex.Lock();
286         //First determine it is already in our system
287         list<SurfaceCommands>::iterator itty=scommands.begin();
288         while (itty!=scommands.end()) {
289                 if ((*itty).surf==surf) {
290                         dereferenceSVGCommand((*itty).commands);
291                         (*itty).commands.clear();
292                         scommands.erase(itty);
293                         break;
294                 }
295                 itty++;
296         }
297         surfaces_mutex.Unlock();
298
299 }
300
301 void OsdVector::dereferenceSVGCommand(list<SVGCommand>& commands )
302 {
303
304         list<SVGCommand>::iterator sitty = commands.begin();
305         while (sitty != commands.end()) {
306                 removeStyleRef((*sitty).getRef());
307                 ImageIndex ii = (*sitty).getImageIndex();
308                 if (ii) removeImageRef(ii);
309                 LoadIndex li=(*sitty).getLoadIndex();
310                 if (li) removeLoadIndexRef(li);
311                 sitty++;
312         }
313 }
314
315 void OsdVector::referenceSVGCommand(list<SVGCommand>& commands )
316 {
317         list<SVGCommand>::iterator sitty=commands.begin();
318         while (sitty!=commands.end())
319         {
320                 incStyleRef((*sitty).getRef());
321                 ImageIndex ii=(*sitty).getImageIndex();
322                 if (ii) incImageRef(ii);
323                 LoadIndex li=(*sitty).getLoadIndex();
324                 if (li) incLoadIndexRef(li);
325                 sitty++;
326         }
327 }
328
329
330 void OsdVector::incImageRef(ImageIndex index)
331 {
332         if (images_ref.find(index)==images_ref.end()) {
333                 images_ref[index]=1;
334         } else {
335                 images_ref[index]++;
336         }
337 }
338
339 void OsdVector::removeImageRef(const ImageIndex ref)
340 {
341         images_ref[ref]--;
342 }
343
344 int OsdVector::getLoadIndexRef(LoadIndex index)
345 {
346         if (loadindex_ref.find(index)==loadindex_ref.end()) {
347                 return -1;
348         } else {
349                 return loadindex_ref[index];
350         }
351 }
352
353 void OsdVector::incLoadIndexRef(LoadIndex index)
354 {
355         if (loadindex_ref.find(index)==loadindex_ref.end()) {
356                 loadindex_ref[index]=1;
357         } else {
358                 loadindex_ref[index]++;
359         }
360 }
361
362 void OsdVector::removeLoadIndexRef(const LoadIndex ref)
363 {
364         loadindex_ref[ref]--;
365         if (loadindex_ref[ref]==0) {
366                 //now check, if it is already loaded
367                 map<LoadIndex,ImageIndex>::iterator itty=tvmedias_loaded.find(ref);
368                 if ( itty != tvmedias_loaded.end()) {
369                         removeImageRef((*itty).second); // remove lock
370                 }
371                 tvmedias_loaded.erase(ref);
372                 tvmedias_load.erase(tvmedias_load_inv[ref]);
373                 tvmedias_load_inv.erase(ref);
374
375                 reader.invalidateLoadIndex(ref);
376
377
378         }
379 }
380
381
382
383 void OsdVector::cleanupOrphanedRefs()
384 { // Do some garbage collection
385
386         map<void *,ImageIndex>::iterator mitty=monobitmaps.begin();
387         while (mitty!=monobitmaps.end()) {
388                 map<ImageIndex,int>::iterator curitty=images_ref.find((*mitty).second);
389                 int count=(*curitty).second;
390                 if (count==0) {
391                         ImageIndex ref=(*curitty).first;
392                         monobitmaps.erase(mitty++);
393                         images_ref.erase(curitty++);
394                         destroyImageRef(ref);
395                 } else ++mitty;
396         }
397
398         /*map<string,ImageIndex>::iterator jitty=jpegs.begin();
399         while (jitty!=jpegs.end()) {
400                 map<ImageIndex,int>::iterator curitty=images_ref.find((*jitty).second);
401                 int count=(*curitty).second;
402                 if (count==0) {
403                         ImageIndex ref=(*curitty).first;
404                         jpegs.erase(jitty++);
405                         images_ref.erase(curitty++);
406                         destroyImageRef(ref);
407                 } else ++jitty;
408         }*/
409
410         map<TVMediaInfo,ImageIndex>::iterator titty=tvmedias.begin();
411         while (titty!=tvmedias.end()) {
412                 map<ImageIndex,int>::iterator curitty=images_ref.find((*titty).second);
413                 int count=(*curitty).second;
414                 if (count==0) {
415                         ImageIndex ref=(*curitty).first;
416                         tvmedias.erase(titty++);
417                         images_ref.erase(curitty);
418                         destroyImageRef(ref);
419                 } else ++titty;
420         }
421
422
423         map<TVMediaInfo,LoadIndex>::iterator litty=tvmedias_load.begin();
424         while (litty!=tvmedias_load.end()) {
425                 map<LoadIndex,int>::iterator curitty=loadindex_ref.find((*litty).second);
426                 int count=(*curitty).second;
427                 if (count==0) {
428                         tvmedias_load_inv.erase((*litty).second);
429                         tvmedias_loaded.erase((*litty).second);
430                         tvmedias_load.erase(litty++);
431                 } else ++litty;
432         }
433
434
435         map<pair<Colour*,unsigned int>,unsigned int>::iterator sitty=styles.begin();
436         while (sitty!=styles.end()) {
437                 map<unsigned int,int>::iterator curitty=styles_ref.find((*sitty).second);
438                 int count=(*curitty).second;
439                 if (count==0) {
440                         unsigned int ref=(*curitty).first;
441                         styles.erase(sitty++);
442                         styles_ref.erase(curitty++);
443                         destroyStyleRef(ref);
444
445                 } else ++sitty;
446
447         }
448 }
449
450
451 int OsdVector::getImageRef(ImageIndex index)
452 {
453         if (images_ref.find(index)==images_ref.end()) {
454                 return -1;
455         } else {
456                 return images_ref[index];
457         }
458 }
459
460 void OsdVector::incStyleRef(unsigned int index)
461 {
462         if (styles_ref.find(index)==styles_ref.end()) {
463                 styles_ref[index]=1;
464         } else {
465                 styles_ref[index]++;
466         }
467 }
468
469 void OsdVector::removeStyleRef(unsigned int index)
470 {
471         styles_ref[index]--;
472 }
473
474 unsigned int OsdVector::getStyleRef(const DrawStyle &c)
475 {
476         unsigned int style_handle=0;
477         if (styles.find(pair<Colour*,unsigned int>((Colour*)&c,c.rgba()))==styles.end())
478         {
479                 style_handle=styles[pair<Colour*,unsigned int>((Colour*)&c,c.rgba())]=createStyleRef(c);
480         } else {
481                 style_handle=styles[pair<Colour*,unsigned int>((Colour*)&c,c.rgba())];
482                 //Now check if the handle is valid
483                 if (styles_ref.find(style_handle)==styles_ref.end()) {
484                         //invalid handle recreate
485                         style_handle=styles[pair<Colour*,unsigned int>((Colour*)&c,c.rgba())]=createStyleRef(c);
486                 }
487         }
488         incStyleRef(style_handle);
489         return style_handle;
490 }
491
492 unsigned int OsdVector::getColorRef(const Colour &c)
493 {
494         unsigned int style_handle=0;
495         if (styles.find(pair<Colour*,unsigned int>((Colour*)&c,c.rgba()))==styles.end())
496         {
497                 style_handle=styles[pair<Colour*,unsigned int>((Colour*)&c,c.rgba())]=createColorRef(c);
498         } else {
499                 style_handle=styles[pair<Colour*,unsigned int>((Colour*)&c,c.rgba())];
500                 if (styles_ref.find(style_handle)==styles_ref.end()) {
501                         //invalid handle recreate
502                         style_handle=styles[pair<Colour*,unsigned int>((Colour*)&c,c.rgba())]=createColorRef(c);
503                 }
504         }
505         incStyleRef(style_handle);
506         return style_handle;
507 }
508
509 int OsdVector::getStyleRef(unsigned int index)
510 {
511         if (styles_ref.find(index)==styles_ref.end()) {
512                 return -1;
513         } else {
514                 return styles_ref[index];
515         }
516 }
517
518 LoadIndex OsdVector::getTVMediaRef(TVMediaInfo& tvmedia, ImageIndex& image)
519 {
520         ImageIndex image_handle=0;
521         LoadIndex loadindex=0;
522         if (tvmedias.find(tvmedia)==tvmedias.end())
523         {
524                 loadindex=loadTVMedia(tvmedia);
525         } else {
526                 image_handle=tvmedias[tvmedia];
527                 if (images_ref.find(image_handle)==images_ref.end()) {
528                         //invalid handle recreate
529                         loadindex=loadTVMedia(tvmedia);
530                         image_handle=0;
531                 } else {
532                         incImageRef(image_handle);
533                 }
534         }
535         /*tvmedias[tvmedia]=createTVMedia(tvmedia,width,height);
536         incImageRef(image_handle);*/
537         image=image_handle;
538         return loadindex;
539 }
540
541 LoadIndex OsdVector::loadTVMedia(TVMediaInfo& tvmedia)
542 {
543         LoadIndex index=0;
544         if (tvmedias_load.find(tvmedia)==tvmedias_load.end())
545         {
546                 switch (tvmedia.getType()) {
547                 case 3:
548                         index=VDR::getInstance()->loadTVMediaRecThumb(tvmedia);
549                         break;
550                 case 4: {
551                         index = ((long long) tvmedia.getPrimaryID()) << 32LL;
552                         reader.addStaticImage(tvmedia.getPrimaryID());
553                 } break;
554                 default:
555                         index=VDR::getInstance()->loadTVMedia(tvmedia);
556                         break;
557                 }
558
559                 tvmedias_load[tvmedia]=index;
560                 tvmedias_load_inv[index]=tvmedia;
561         } else {
562
563                 index=tvmedias_load[tvmedia];
564         }
565
566         incLoadIndexRef(index);
567
568         return index;
569 }
570
571
572
573 void OsdVector::informPicture(LoadIndex index, ImageIndex imageIndex)
574 {
575         //Beware for thread safety
576         ImageIndex image_index=0;
577
578         TVMediaInfo tvmedia=tvmedias_load_inv[index];
579           Log::getInstance()->log("OsdVector", Log::DEBUG, "TVMedia Picture for request id %llx arrived %d",index, imageIndex);
580         if (imageIndex) {
581                 image_index=tvmedias[tvmedia]=imageIndex;
582                 tvmedias_loaded[index]=image_index;
583                 if (getLoadIndexRef(index) < 1) {
584                         // we do not want the picture anymore . Really...
585                         // fill images_ref in to not irritate the garbage collector
586                         if (getImageRef(image_index) < 0) {
587                                 images_ref[image_index]=0;
588                         }
589                 } else {
590
591                         incImageRef(image_index); // hold one index until all loadings refs are gone;
592                 }
593         }
594
595
596 }
597
598
599
600
601 /*
602 ImageIndex OsdVector::getJpegRef(const char* fileName, int *width,int *height)
603 {
604         ImageIndex image_handle=0;
605         if (jpegs.find(fileName)==jpegs.end())
606         {
607                 image_handle=jpegs[fileName]=createJpeg(fileName,width,height);
608         } else {
609                 image_handle=jpegs[fileName];
610                 *width=0;
611                 *height=0;
612                 if (images_ref.find(image_handle)==images_ref.end()) {
613                         //invalid handle recreate
614                         image_handle=jpegs[fileName]=createJpeg(fileName,width,height);
615                 }
616         }
617         incImageRef(image_handle);
618         return image_handle;
619 }
620 */
621
622 ImageIndex OsdVector::getMonoBitmapRef(void *base,int width,int height)
623 {
624         ImageIndex image_handle;
625         if (monobitmaps.find(base)==monobitmaps.end())
626         {
627                 image_handle=monobitmaps[base]=createMonoBitmap(base,width,height);
628         } else {
629                 image_handle=monobitmaps[base];
630                 if (images_ref.find(image_handle)==images_ref.end()) {
631                         //invalid handle recreate
632                         image_handle=monobitmaps[base]=createMonoBitmap(base,width,height);
633                 }
634         }
635         incImageRef(image_handle);
636         return image_handle;
637 }
638
639 ImageIndex  OsdVector::getImagePalette(int width,int height,const unsigned char *image_data,const unsigned int*palette_data)
640 {
641         ImageIndex image_handle;
642         image_handle=createImagePalette(width,height,image_data,palette_data);
643         incImageRef(image_handle);
644         return image_handle;
645 }
646
647 OsdVector::PictureReader::~PictureReader()
648 {
649         decoders_lock.Lock();
650         while ( decoders.size()) {
651                 PictureDecoder* dec=decoders.front();
652                 decoders.pop_front();
653                 delete dec;
654         }
655
656         decoders_lock.Unlock();
657 }
658
659 void OsdVector::PictureReader::init()
660 {
661         threadStart();
662 }
663
664 void OsdVector::PictureReader::shutdown()
665 {
666         threadStop();
667
668
669 }
670
671 void OsdVector::PictureReader::addDecoder(PictureDecoder* decoder)
672 {
673         decoders_lock.Lock();
674         decoder->init();
675         decoders.push_front(decoder);
676         decoders_lock.Unlock();
677 }
678
679 void OsdVector::PictureReader::removeDecoder(PictureDecoder* decoder)
680 {
681         decoders_lock.Lock();
682         std::list<PictureDecoder*>::iterator itty=decoders.begin();
683         while (itty!=decoders.end()) {
684                 if ((*itty) == decoder)
685                 {
686                         decoders.erase(itty);
687                         break;
688                 }
689                 itty++;
690         }
691         Log::getInstance()->log("OsdVector", Log::DEBUG, "removeDecoder");
692         decoder->shutdown();
693         delete decoder;
694         decoders_lock.Unlock();
695 }
696
697 void OsdVector::PictureReader::threadMethod()
698 {
699         OsdVector *osdvector = dynamic_cast<OsdVector*>(Osd::getInstance());
700         Log::getInstance()->log("OsdVector", Log::DEBUG, "TVMedia Start Picture Reader");
701         while (true) {
702                 if (!threadIsActive()) {
703                         Log::getInstance()->log("OsdVector", Log::DEBUG, "TVMedia End Picture Reader");
704                         threadCheckExit();
705                 }
706
707                 bool todos=true;
708                 while (todos)
709                 {
710                         todos=false;
711                         PictureInfo pictinf;
712                         decoders_lock.Lock();
713                         std::list<PictureDecoder*>::iterator itty=decoders.begin();
714
715                         while (itty!=decoders.end()) {
716                                 if ((*itty)->getDecodedPicture(pictinf)) {
717                                         todos = true;
718                                         osdvector->createPicture(pictinf);
719                                 }
720
721                                 itty++;
722                         }
723                         if (processReceivedPictures())
724                         {
725                                 todos = true;
726                         }
727
728                         decoders_lock.Unlock();
729                 }
730                 //Log::getInstance()->log("OsdVector", Log::DEBUG, "TVMedia Sleep Picture Reader");
731
732                 threadLock();
733                 threadWaitForSignal();
734                 threadUnlock();
735                 //Log::getInstance()->log("OsdVector", Log::DEBUG, "TVMedia Sleep end Picture Reader");
736         }
737 }
738
739 void OsdVector::PictureReader::threadPostStopCleanup()
740 {
741
742 }
743
744 void OsdVector::PictureReader::invalidateLoadIndex(LoadIndex index)
745 {
746         pict_lock_incoming.Lock();
747         invalid_loadindex.insert(index);
748         pict_lock_incoming.Unlock();
749 }
750
751 void OsdVector::PictureReader::receivePicture(VDR_ResponsePacket *vresp)
752 {
753         pict_lock_incoming.Lock();
754         pict_incoming.push(vresp);
755         pict_lock_incoming.Unlock();
756         threadSignal();
757 }
758
759
760 void OsdVector::PictureReader::addStaticImage(unsigned int id)
761 {
762         pict_lock_incoming.Lock();
763         pict_incoming_static.push(id);
764         invalid_loadindex.erase(((long long) id) << 32LL);
765         pict_lock_incoming.Unlock();
766         threadSignal();
767 }
768
769 bool OsdVector::PictureReader::processReceivedPictures()
770 {
771         bool decoded = false;
772         bool valid = true;
773         pict_lock_incoming.Lock();
774     if (pict_incoming.size()) {
775                 VDR_ResponsePacket *vresp=pict_incoming.front();
776                 pict_incoming.pop();
777                 set<LoadIndex>::iterator setpos = invalid_loadindex.find(vresp->getStreamID());
778                 if (setpos != invalid_loadindex.end()) {
779                         valid = false;
780                         invalid_loadindex.erase(setpos);
781                 }
782                 pict_lock_incoming.Unlock();
783                 if (!valid) { // we do not want it anymore skip it;
784                         delete vresp;
785                         return true;
786                 }
787                 if (vresp->getFlag() != 2) {
788                         UCHAR *userdata=vresp->getUserData();
789                         ULONG length=vresp->getUserDataLength();
790                         std::list<PictureDecoder*>::iterator itty=decoders.begin();
791                         while (itty!=decoders.end()) {
792                                 if ((*itty)->decodePicture(vresp->getStreamID(),
793                                         userdata, length)){
794                                         decoded=true;
795                                         break;
796                                 }
797                                 itty++;
798                         }
799                         if (!decoded ){
800                                 free(vresp->getUserData());
801                         }
802                 }
803                 //else  osd->informPicture(vresp->getStreamID(), 0);
804                 delete vresp;
805         } else if (pict_incoming_static.size()){
806                 unsigned int static_id = pict_incoming_static.front();
807                 pict_incoming_static.pop();
808                 set<LoadIndex>::iterator setpos = invalid_loadindex.find(((long long) static_id) << 32LL);
809                 if (setpos != invalid_loadindex.end()) {
810                         valid = false;
811                         invalid_loadindex.erase(setpos);
812                 }
813                 pict_lock_incoming.Unlock();
814                 if (!valid) { // we do not want it anymore skip it;
815                         return true;
816                 }
817
818                 UCHAR *userdata;
819                 ULONG length;
820                 if (((OsdVector*)Osd::getInstance())->getStaticImageData(static_id, &userdata, &length))
821                 {
822                         std::list<PictureDecoder*>::iterator itty=decoders.begin();
823                         while (itty!=decoders.end()) {
824                                 if ((*itty)->decodePicture(((long long) static_id) << 32LL,userdata, length, false)){
825                                         decoded=true;
826                                         break;
827                                 }
828                                 itty++;
829                         }
830                 }
831         } else {
832                 pict_lock_incoming.Unlock();
833         }
834
835
836         return decoded;
837 }