source: titan/titan/subtitle.h @ 14611

Last change on this file since 14611 was 14082, checked in by nit, 12 years ago

[titan] first step anim screens

File size: 37.2 KB
Line 
1#ifndef SUBTITLE_H
2#define SUBTITLE
3
4int subdisplaywidth = 720;
5int subdisplayheight = 576;
6
7static int map2to4bit[4];
8static int map2to8bit[4];
9static int map4to8bit[16];
10
11//flag 0 = free oldsubpage
12//flag 1 = free subpage
13void subfree(int flag)
14{
15        struct subpage* page = NULL;
16        struct subpage* tmppage = NULL;
17
18        if(flag == 0) page = oldsubpage;
19        if(flag == 1) page = subpage;
20
21        while(page != NULL)
22        {
23                while(page->pageregions != NULL)
24                {
25                        struct subpagereg *p = page->pageregions->next;
26                        free(page->pageregions);
27                        page->pageregions = p;
28                }
29                while(page->regions != NULL)
30                {
31                        struct subreg *reg = page->regions;
32
33                        while(reg->objects != NULL)
34                        {
35                                struct subregobj *obj = reg->objects;
36                                reg->objects = obj->next;
37                                free(obj);
38                        }
39
40                        free(reg->buf);
41                        reg->buf = NULL;
42                        free(reg->palette);
43                        reg->palette = NULL;
44
45                        page->regions = reg->next;
46                        free(reg);
47                }
48                while(page->cluts != NULL)
49                {
50                        struct subclut *clut = page->cluts;
51                        page->cluts = clut->next;
52                        free(clut);
53                }
54
55                tmppage = page->next;
56                free(page);
57                if(flag == 0) oldsubpage = NULL;
58                if(flag == 1) subpage = NULL;
59                page = tmppage;
60        }
61}
62
63void subclear(int ontimeout)
64{
65        struct subpage* subnode = oldsubpage;
66        struct subpagereg* pageregnode = NULL;
67        time_t sec = 0;
68        int stat = 0;
69
70        if(subnode != NULL)
71        {
72                if(ontimeout == 1)
73                {
74                        if(subnode->pagetimeout == 0) return;
75                        sec = time(NULL);
76                        if(subnode->pagetimeout >= sec) return;
77                }
78
79                pageregnode = subnode->pageregions;
80                while(pageregnode != NULL)
81                {
82                        struct subreg *regnode = subnode->regions;
83                        while(regnode != NULL)
84                        {
85                                if(regnode->regid == pageregnode->regid) break;
86                                regnode = regnode->next;
87                        }
88                        if(regnode != NULL)
89                        {
90                                stat = 1;
91                                int posx = pageregnode->scaleposx;
92                                int posy = pageregnode->scaleposy;
93
94                                if(posx < 0 || posy < 0) continue;
95                                clearrect(posx, posy, regnode->scalewidth, regnode->scaleheight);
96                        }
97                        pageregnode = pageregnode->next;
98                }
99       
100                if(stat == 1) blitfb(0);
101                subfree(0);
102        }
103}
104
105void subdraw(unsigned long long subpts, struct subpage* page)
106{
107        debug(300, "subtitle draw");
108        struct subpagereg* pageregnode = NULL;
109        int y, x, stat = 0;
110        uint64_t pts = 0;
111        unsigned char* scalebuf = NULL;
112
113        if(page == NULL) return;
114
115        //wait for subtitle to display
116#ifndef SIMULATE
117        videogetpts(status.aktservice->videodev, &pts);
118#else
119        pts = 8275201296;
120#endif
121        debug(300, "pts = %lld, subpts = %lld", pts, subpts);
122        while(status.subthreadaktion != STOP && status.subthreadaktion != PAUSE && subpts >= pts)
123        {
124                subclear(1);
125                usleep(100000);
126#ifndef SIMULATE
127                videogetpts(status.aktservice->videodev, &pts);
128#else
129                pts += 100000;
130#endif
131        }
132        if(status.subthreadaktion == STOP || status.subthreadaktion == PAUSE)
133                return;
134        debug(300, "pts = %lld, subpts = %lld", pts, subpts);
135
136        subclear(0);
137
138        pageregnode = page->pageregions;
139        while(pageregnode != NULL)
140        {
141
142                struct subreg *regnode = page->regions;
143                while(regnode != NULL)
144                {
145                        if(regnode->regid == pageregnode->regid) break;
146                        regnode = regnode->next;
147                }
148                if(regnode != NULL && regnode->buf != NULL)
149                {
150
151                        stat = 1;
152                        int posx = pageregnode->reghorizontaladdress * skinfb->width / subdisplaywidth;
153                        int posy = pageregnode->regverticaladdress * skinfb->height / subdisplayheight;
154                        unsigned long *palette = (unsigned long*)regnode->palette;
155
156                        pageregnode->scaleposx = posx;
157                        pageregnode->scaleposy = posy;
158
159                        //scale
160                        regnode->scalewidth = regnode->width * skinfb->width / subdisplaywidth;
161                        regnode->scaleheight = regnode->height * skinfb->height / subdisplayheight;
162
163                        if(accelfb != NULL && accelfb->varfbsize >= regnode->width * regnode->height * 4)
164                        {
165
166                                for(y = 0; y < regnode->height; y++)
167                                {
168                                        for(x = 0; x < regnode->width; x++)
169                                        {
170                                                if(regnode->buf[y * regnode->width + x] != 0)
171                                                        drawpixelfb(accelfb, (regnode->width * y) + x, 0, palette[regnode->buf[y * regnode->width + x]]);
172                                                else
173                                                        drawpixelfb(accelfb, (regnode->width * y) + x, 0, 0);
174                                        }
175                                }
176                                blitscale(posx, posy, regnode->width, regnode->height, regnode->scalewidth, regnode->scaleheight);
177                        }
178                        else
179                        {
180                                if(regnode->scalewidth != regnode->width || regnode->scaleheight != regnode->height)
181                                {
182                                        scalebuf = scale(regnode->buf, regnode->width, regnode->height, 1, regnode->scalewidth, regnode->scaleheight, 1);
183                                        if(scalebuf != NULL) regnode->buf = scalebuf;
184                                }
185                                else
186                                        scalebuf = regnode->buf;
187/*
188                                //only for test no scale
189                                posx = pageregnode->reghorizontaladdress;
190                                posy = pageregnode->regverticaladdress;
191                                pageregnode->scaleposx = posx;
192                                pageregnode->scaleposy = posy;
193                                regnode->scalewidth = regnode->width;
194                                regnode->scaleheight = regnode->height;
195*/
196
197                                for(y = 0; y < regnode->scaleheight; y++)
198                                {
199                                        for(x = 0; x < regnode->scalewidth; x++)
200                                        {
201                                                if(regnode->buf[y * regnode->scalewidth + x] != 0)
202                                                {
203                                                        drawpixel(posx + x, posy + y, palette[regnode->buf[y * regnode->scalewidth + x]]);
204                                                }
205                                        }
206                                }
207                        }
208                }
209                pageregnode = pageregnode->next;
210        }
211        if(stat == 1) blitfb(0);
212}
213
214void subcalc(int pageid, unsigned long long pts)
215{
216        int i, clutsize = 0;
217        struct subpage *page = subpage;
218
219        while(page != NULL)
220        {
221                if(page->pageid == pageid) break;
222                page = page->next;
223        }
224
225        if(page == NULL) return;
226
227        struct subpagereg *pagereg = page->pageregions;
228
229        for(; pagereg; pagereg = pagereg->next)
230        {
231                struct subreg *reg = page->regions;
232                while(reg != NULL)
233                {
234                        if(reg->regid == pagereg->regid) break;
235                        reg = reg->next;
236                }
237                if(reg != NULL)
238                {
239                        if(reg->committed) continue;
240
241                        int posx = pagereg->reghorizontaladdress;
242                        int posy = pagereg->regverticaladdress;
243
244                        if(posx < 0 || posy < 0) continue;
245
246                        /* find corresponding clut */
247                        struct subclut *clut = page->cluts;
248                        while(clut != NULL)
249                        {
250                                if(clut->clutid == reg->clutid) break;
251                                clut = clut->next;
252                        }
253
254                        if(reg->depth == 1)
255                        {
256                                clutsize = 4;
257                                reg->palette = (struct rgba*)malloc(clutsize * sizeof(struct rgba));
258                        }
259                        if(reg->depth == 2)
260                        {
261                                clutsize = 16;
262                                reg->palette = (struct rgba*)malloc(clutsize * sizeof(struct rgba));
263                        }
264                        if(reg->depth == 3)
265                        {
266                                clutsize = 256;
267                                reg->palette = (struct rgba*)malloc(clutsize * sizeof(struct rgba));
268                        }
269
270                        struct subclutentry *entries = NULL;
271                        switch(reg->depth)
272                        {
273                                case 1:
274                                {
275                                        if(clut != NULL)
276                                                entries = clut->entries2bit;
277                                        memset(reg->palette, 0, 4 * sizeof(struct rgba));
278                                        reg->palette[0].a = 0xFF;
279                                        reg->palette[2].r = reg->palette[2].g = reg->palette[2].b = 0xFF;
280                                        reg->palette[3].r = reg->palette[3].g = reg->palette[3].b = 0x80;
281                                        break;
282                                }
283                                case 2:
284                                {
285                                        if(clut != NULL)
286                                                entries = clut->entries4bit;
287                                        memset(reg->palette, 0, 16 * sizeof(struct rgba));
288                                        for(i = 0; i < 16; ++i)
289                                        {
290                                                if(!i)
291                                                        reg->palette[i].a = 0xFF;
292                                                else if(i & 8)
293                                                {
294                                                        if(i & 1) reg->palette[i].r = 0x80;
295                                                        if(i & 2) reg->palette[i].g = 0x80;
296                                                        if(i & 4) reg->palette[i].b = 0x80;
297                                                }
298                                                else
299                                                {
300                                                        if(i & 1) reg->palette[i].r = 0xFF;
301                                                        if(i & 2) reg->palette[i].g = 0xFF;
302                                                        if(i & 4) reg->palette[i].b = 0xFF;
303                                                }
304                                        }
305                                        break;
306                                }
307                                case 3:
308                                {
309                                        if(clut != NULL)
310                                                entries = clut->entries8bit;
311                                        memset(reg->palette, 0, 256 * sizeof(struct rgba));
312                                        for(i = 0; i < 256; ++i)
313                                        {
314                                                switch(i & 17)
315                                                {
316                                                        case 0:
317                                                        {
318                                                                if(!(i & 14))
319                                                                {
320                                                                        if(!(i & 224))
321                                                                                reg->palette[i].a = 0xFF;
322                                                                        else
323                                                                        {
324                                                                                if(i & 128) reg->palette[i].r = 0xFF;
325                                                                                if (i & 64) reg->palette[i].g = 0xFF;
326                                                                                if(i & 32) reg->palette[i].b = 0xFF;
327                                                                                reg->palette[i].a = 0xBF;
328                                                                        }
329                                                                        break;
330                                                                }
331                                                        }
332                                                        case 16:
333                                                        {
334                                                                if(i & 128) reg->palette[i].r = 0x55;
335                                                                if(i & 64) reg->palette[i].g = 0x55;
336                                                                if(i & 32) reg->palette[i].b = 0x55;
337                                                                if(i & 8) reg->palette[i].r += 0xAA;
338                                                                if(i & 4) reg->palette[i].g += 0xAA;
339                                                                if(i & 2) reg->palette[i].b += 0xAA;
340                                                                if(i & 16) reg->palette[i].a = 0x80;
341                                                                break;
342                                                        }
343                                                        case 1:
344                                                        {
345                                                                reg->palette[i].r = 0x80;
346                                                                reg->palette[i].g = 0x80;
347                                                                reg->palette[i].b = 0x80;
348                                                        }
349                                                        case 17:
350                                                        {
351                                                                if(i & 128) reg->palette[i].r += 0x2A;
352                                                                if(i & 64) reg->palette[i].g += 0x2A;
353                                                                if(i & 32) reg->palette[i].b += 0x2A;
354                                                                if(i & 8) reg->palette[i].r += 0x55;
355                                                                if(i & 4) reg->palette[i].g += 0x55;
356                                                                if(i & 2) reg->palette[i].b += 0x55;
357                                                                break;
358                                                        }
359
360                                                }
361                                                break;
362                                        }
363                                }
364                        }
365
366                        for(i = 0; i < clutsize; ++i)
367                        {
368                                if(entries && entries[i].valid)
369                                {
370                                        int y = entries[i].Y;
371                                        int cr = entries[i].Cr;
372                                        int cb = entries[i].Cb;
373
374                                        if(y > 0)
375                                        {
376                                                y -= 16;
377                                                cr -= 128;
378                                                cb -= 128;
379                                                reg->palette[i].r = OMAX(OMIN(((298 * y            + 460 * cr) / 256), 255), 0);
380                                                reg->palette[i].g = OMAX(OMIN(((298 * y -  55 * cb - 137 * cr) / 256), 255), 0);
381                                                reg->palette[i].b = OMAX(OMIN(((298 * y + 543 * cb           ) / 256), 255), 0);
382                                                //reg->palette[i].a = (entries[i].T) & 0xFF;
383                                                reg->palette[i].a = 0xFF;
384                                        }
385                                        else
386                                        {
387                                                reg->palette[i].r = 0;
388                                                reg->palette[i].g = 0;
389                                                reg->palette[i].b = 0;
390                                                reg->palette[i].a = 0xFF;
391                                        }
392                                }
393                        }
394
395                        reg->committed = 1;
396                }
397        }
398        page->pagetimeout += time(NULL);
399        subdraw(pts, page);
400        subfree(0);
401        oldsubpage = subpage;
402        subpage = NULL;
403}
404
405void subcalcall(unsigned long long pts)
406{
407#if 1
408        struct subpage *page = subpage;
409
410        while(page != NULL)
411        {
412                if(page->state != 0)
413                        subcalc(page->pageid, pts);
414                page = page->next;
415        }
416#else
417        struct subpage *page = subpage;
418
419        debug(300, "end of display set");
420        debug(300, "active pages:");
421        while(page != NULL)
422        {
423                debug(300, "page_id %02x", page->pageid);
424                debug(300, "page_version_number: %d", page->pageversionnumber);
425                debug(300, "active regions:");
426                {
427                        subpagereg *reg = page->pageregions;
428                        while(reg != NULL)
429                        {
430                                debug(300, "region_id: %04x", reg->regid);
431                                debug(300, "region_horizontal_address: %d", reg->reghorizontaladdress);
432                                debug(300, "region_vertical_address: %d", reg->regverticaladdress);
433
434                                reg = reg->next;
435                        }
436                }
437
438                subcalc(page->pageid);
439
440                debug(300, "defined regions:");
441                struct subregion *reg = page->regions;
442                while(reg != NULL)
443                {
444                        debug("region_id %04x, version %d, %dx%d", reg->regid, reg->versionnumber, reg->width, reg->height);
445
446                        struct subregobj *obj = reg->objects;
447                        while(object != NULL)
448                        {
449                                debug(300, "object %02x, type %d, %d:%d", obj->objid, obj->objtype, obj->objhorizontalpos, obj->objverticalpos);
450                                obj = obj->next;
451                        }
452                        reg = reg->next;
453                }
454                page = page->next;
455        }
456#endif
457}
458
459void bitstreaminit(struct bitstream *bit, const void *buf, int size)
460{
461        bit->data = (unsigned char*) buf;
462        bit->size = size;
463        bit->avail = 8;
464        bit->consumed = 0;
465}
466
467int bitstreamget(struct bitstream *bit)
468{
469        int val;
470        bit->avail -= bit->size;
471        val = ((*bit->data) >> bit->avail) & ((1 << bit->size) - 1);
472        if(!bit->avail)
473        {
474                bit->data++;
475                bit->consumed++;
476                bit->avail = 8;
477        }
478        return val;
479}
480
481int verifysubpes(unsigned char* pkt)
482{
483        int substart, pktlen;
484
485        if(pkt == NULL)
486        {
487                debug(300, "NULL Paket");
488                return 1;
489        }
490
491        /* Packet header == 0x000001 */
492        if(pkt[0] != 0x00 || pkt[1] != 0x00 || pkt[2] != 0x01)
493        {
494                debug(300, "Invalid header");
495                return 1;
496        }
497
498        /* stream_id == private_stream_1 */
499        if(pkt[3] != 0xbd)
500        {
501                debug(300, "Not a private_stream_1 stream (%x)\n", pkt[3]);
502                return 1;
503        }
504
505        /* data_alignment_indicator == 1 */
506        if((pkt[6] & 0x04) == 0)
507        {
508                debug(300, "Data alignment indicator == 0");
509                return 1;
510        }
511
512        /* PTS is present */
513        if((pkt[7] & 0x80) == 0)
514        {
515                debug(300, "No PTS");
516                return 1;
517        }
518
519        substart = 9 + pkt[8];
520        pktlen = ((uint16_t)pkt[4] << 8) + pkt[5] + 6;
521
522        /* data_identifier == 0x20, subtitle_stream_id == 0x00,
523        end_of_PES_data_field_marker == 0xff */
524        if(pkt[substart] != 0x20)
525        {
526                debug(300, "Data identifier != 0x20");
527                return 1;
528        }
529
530        if(pkt[substart + 1] != 0x00)
531        {
532                debug(300, "Subtitle stream ID %x != 0x00\n", pkt[substart + 1]);
533                return 1;
534        }
535
536        if(pkt[pktlen - 1] != 0xff)
537        {
538                debug(300, "Wrong packet length");
539                return 1;
540        }
541
542        return 0;
543}
544
545int subgetpts(unsigned long long *pts, unsigned char *pkt)
546{
547        pkt += 7;
548        int flags = *pkt++;
549
550        pkt++; // header length
551
552        if(flags & 0x80) /* PTS present? */
553        {
554                *pts = ((unsigned long long)(((pkt[0] >> 1) & 7))) << 30;
555                *pts |= pkt[1] << 22;
556                *pts |= (pkt[2] >> 1) << 15;
557                *pts |= pkt[3] << 7;
558                *pts |= (pkt[5] >> 1);
559
560                return 0;
561        } else
562                return 1;
563}
564
565void subline(struct subreg *reg, struct subregobj *obj, int line, unsigned char *data, int len)
566{
567        int x = obj->objhorizontalpos;
568        int y = obj->objverticalpos + line;
569
570        if(x + len > reg->width) len = reg->width - x;
571        if(len < 0) return;
572        if(y >= reg->height) return;
573
574        memcpy(reg->buf + reg->width * y + x, data, len);
575}
576
577int subpixeldata(struct subreg *reg, struct subregobj *obj, int *linenr, int *linep, unsigned char *data)
578{
579        int datatype = *data++, i = 0;
580        static unsigned char line[1920];
581        struct bitstream bit;
582
583        bit.size = 0;
584        switch(datatype)
585        {
586                case 0x10: // 2bit pixel data
587                {
588                        bitstreaminit(&bit, data, 2);
589                        while(1)
590                        {
591                                int len = 0, col = 0;
592                                int code = bitstreamget(&bit);
593
594                                if(code)
595                                {
596                                        col = code;
597                                        len = 1;
598                                }
599                                else
600                                {
601                                        code = bitstreamget(&bit);
602                                        if(!code)
603                                        {
604                                                code = bitstreamget(&bit);
605                                                if(code == 1)
606                                                {
607                                                        col = 0;
608                                                        len = 2;
609                                                }
610                                                else if(code == 2)
611                                                {
612                                                        len = bitstreamget(&bit) << 2;
613                                                        len |= bitstreamget(&bit);
614                                                        len += 12;
615                                                        col = bitstreamget(&bit);
616                                                }
617                                                else if(code == 3)
618                                                {
619                                                        len = bitstreamget(&bit) << 6;
620                                                        len |= bitstreamget(&bit) << 4;
621                                                        len |= bitstreamget(&bit) << 2;
622                                                        len |= bitstreamget(&bit);
623                                                        len += 29;
624                                                        col = bitstreamget(&bit);
625                                                }
626                                                else
627                                                        break;
628                                        }
629                                        else if(code==1)
630                                        {
631                                                col = 0;
632                                                len = 1;
633                                        }
634                                        else if(code & 2)
635                                        {
636                                                if(code & 1)
637                                                        len = 3 + 4 + bitstreamget(&bit);
638                                                else
639                                                        len = 3 + bitstreamget(&bit);
640                                                col = bitstreamget(&bit);
641                                        }
642                                }
643
644                                uint8_t c = reg->depth == 1 ? map2to4bit[col] : reg->depth == 2 ? map2to8bit[col] : col;
645                                while(len && ((*linep) < subdisplaywidth))
646                                {
647                                        line[(*linep)++] = c;
648                                        len--;
649                                }
650                        }
651                        while(bit.avail != 8)
652                                bitstreamget(&bit);
653                        return bit.consumed + 1;
654                }
655                case 0x11: // 4bit pixel data
656                {
657                        bitstreaminit(&bit, data, 4);
658                        while(1)
659                        {
660                                int len = 0, col = 0;
661                                int code = bitstreamget(&bit);
662                                if(code)
663                                {
664                                        col = code;
665                                        len = 1;
666                                }
667                                else
668                                {
669                                        code = bitstreamget(&bit);
670                                        if(!code)
671                                                break;
672                                        else if(code == 0xC)
673                                        {
674                                                col = 0;
675                                                len = 1;
676                                        }
677                                        else if(code == 0xD)
678                                        {
679                                                col = 0;
680                                                len = 2;
681                                        }
682                                        else if(code < 8)
683                                        {
684                                                col = 0;
685                                                len = (code & 7) + 2;
686                                        }
687                                        else if((code & 0xC) == 0x8)
688                                        {
689                                                col = bitstreamget(&bit);
690                                                len = (code & 3) + 4;
691                                        }
692                                        else if(code == 0xE)
693                                        {
694                                                len = bitstreamget(&bit) + 9;
695                                                col = bitstreamget(&bit);
696                                        }
697                                        else if(code == 0xF)
698                                        {
699                                                len = bitstreamget(&bit) << 4;
700                                                len |= bitstreamget(&bit);
701                                                len += 25;
702                                                col = bitstreamget(&bit);
703                                        }
704                                }
705                                uint8_t c = reg->depth == 3 ? map4to8bit[col] : col;
706                                while(len && ((*linep) < subdisplaywidth))
707                                {
708                                        line[(*linep)++] = c;
709                                        len--;
710                                }
711                        }
712                        while(bit.avail != 8)
713                                bitstreamget(&bit);
714                        return bit.consumed + 1;
715                }
716                case 0x12: // 8bit pixel data
717                {
718                        bitstreaminit(&bit, data, 8);
719                        while(1)
720                        {
721                                int len = 0, col = 0;
722                                int code = bitstreamget(&bit);
723                                if(code)
724                                {
725                                        col = code;
726                                        len = 1;
727                                }
728                                else
729                                {
730                                        code = bitstreamget(&bit);
731                                        if((code & 0x80) == 0x80)
732                                        {
733                                                len = code & 0x7F;
734                                                col = bitstreamget(&bit);
735                                        }
736                                        else if(code & 0x7F)
737                                        {
738                                                len = code & 0x7F;
739                                                col = 0;
740                                        }
741                                        else
742                                                break;
743                                }
744                                while(len && ((*linep) < subdisplaywidth))
745                                {
746                                        line[(*linep)++] = col;
747                                        len--;
748                                }
749                        }
750                        return bit.consumed + 1;
751                }
752                case 0x20:
753                {
754                        bitstreaminit(&bit, data, 4);
755                        for(i = 0; i < 4; ++i)
756                                map2to4bit[i] = bitstreamget(&bit);
757                        return bit.consumed + 1;
758                }
759                case 0x21:
760                {
761                        bitstreaminit(&bit, data, 8);
762                        for(i = 0; i < 4; ++i)
763                                map2to8bit[i] = bitstreamget(&bit);
764                        return bit.consumed + 1;
765                }
766                case 0x22:
767                {
768                        bitstreaminit(&bit, data, 8);
769                        for(i = 0; i < 16; ++i)
770                        map4to8bit[i] = bitstreamget(&bit);
771                        return bit.consumed + 1;
772                }
773                case 0xF0:
774                {
775                        subline(reg, obj, *linenr, line, *linep);
776                        (*linenr) += 2; // interlaced
777                        *linep = 0;
778                        return 1;
779                }
780                default:
781                {
782                        debug(300, "subtitle_process_pixel_data: invalid data_type %02x", datatype);
783                        return -1;
784                }
785        }
786        return 0;
787}
788
789int subsegment(unsigned char *seg, int id1, int id2, unsigned long long pts)
790{
791        int segtype, pageid, seglen, proclen;
792
793        if(*seg++ != 0x0F)
794        {
795                debug(300, "segment out of sync");
796                return -1;
797        }
798
799        segtype = *seg++;
800        pageid  = *seg++ << 8;
801        pageid |= *seg++;
802        seglen = *seg++ << 8;
803        seglen |= *seg++;
804
805        if(segtype == 0xFF) return seglen + 6;
806
807        if(pageid != id1 && pageid != id2)
808                return seglen + 6;
809
810        struct subpage *page = subpage, **ppage = &subpage;
811
812        while(page != NULL)
813        {
814                if(page->pageid == pageid) break;
815                page = page->next;
816        }
817
818        proclen = 0;
819
820        switch(segtype)
821        {
822                case 0x10: // page composition segment
823                {
824                        int pagetimeout = *seg++; proclen++;
825                        int pageversionnumber = *seg >> 4;
826                        int pagestate = (*seg >> 2) & 0x3;
827                        seg++;
828                        proclen++;
829
830                        if(page == NULL)
831                        {
832                                page = malloc(sizeof(struct subpage));
833                                if(page == NULL)
834                                {
835                                        err("no mem");
836                                        break;
837                                }
838                                memset(page, 0, sizeof(struct subpage));
839                                page->pageid = pageid;
840                                *ppage = page;
841                        }
842                        else
843                        {
844                                if(page->pcssize != seglen)
845                                        page->pageversionnumber = -1;
846                                // if no update, just skip this data.
847                                if(page->pageversionnumber == pageversionnumber)
848                                        break;
849                        }
850
851                        page->state = pagestate;
852
853                        if((pagestate == 1) || (pagestate == 2))
854                        {
855                                while(page->pageregions != NULL)
856                                {
857                                        struct subpagereg *p = page->pageregions->next;
858                                        free(page->pageregions);
859                                        page->regions = NULL;
860                                        page->pageregions = p;
861                                }
862                                while(page->regions)
863                                {
864                                        struct subreg *p = page->regions->next;
865                                        while(page->regions->objects)
866                                        {
867                                                struct subregobj *obj = page->regions->objects->next;
868                                                free(page->regions->objects);
869                                                page->regions->objects = NULL;
870                                                page->regions->objects = obj;
871                                        }
872                                        free(page->regions);
873                                        page->regions = NULL;
874                                        page->regions = p;
875                                }
876
877                        }
878
879                        page->pagetimeout = pagetimeout;
880                        page->pageversionnumber = pageversionnumber;
881
882                        struct subpagereg **reg = &page->pageregions;
883
884                        while(*reg != NULL) reg = &(*reg)->next;
885
886                        if(proclen == seglen && !page->pageregions)
887                        {
888                                debug(300, "no regions in page.. clear screen!!");
889                                //TODO: ??
890                                //subcalc(page->pageid);
891                        }
892
893                        while(proclen < seglen)
894                        {
895                                struct subpagereg *preg;
896
897                                // append new entry to list
898                                preg = malloc(sizeof(struct subpagereg));
899                                if(preg == NULL)
900                                {
901                                        err("no mem");
902                                        proclen += 6;
903                                        continue;
904                                }
905                                memset(preg, 0, sizeof(struct subpagereg));
906                                *reg = preg;
907                                reg = &preg->next;
908
909                                preg->regid = *seg++; proclen++;
910                                seg++; proclen++;
911
912                                preg->reghorizontaladdress = *seg++ << 8;
913                                preg->reghorizontaladdress |= *seg++;
914                                proclen += 2;
915
916                                preg->regverticaladdress = *seg++ << 8;
917                                preg->regverticaladdress |= *seg++;
918                                proclen += 2;
919                        }
920
921                        if(proclen != seglen)
922                                debug(300, "proclen %d != seglen %d", proclen, seglen);
923                        break;
924                }
925                case 0x11: // region composition segment
926                {
927                        int regid = *seg++; proclen++;
928                        int versionnumber = *seg >> 4;
929                        int regfillflag = (*seg >> 3) & 1;
930                        seg++; proclen++;
931
932                        if(page == NULL)
933                        {
934                                debug(300, "ignoring region %x, since page %02x doesn't yet exist.", regid, pageid);
935                                break;
936                        }
937
938                        struct subreg *reg = page->regions, **preg = &page->regions;
939
940                        while(reg != NULL)
941                        {
942                                if(reg->regid == regid) break;
943                                preg = &reg->next;
944                                reg = reg->next;
945                        }
946
947                        if(reg == NULL)
948                        {
949                                *preg = reg = malloc(sizeof(struct subreg));
950                                if(reg == NULL)
951                                {
952                                        err("no mem");
953                                        break;
954                                }
955                                memset(reg, 0, sizeof(struct subreg));
956                                reg->committed = 0;
957                        }
958                        else if(reg->versionnumber != versionnumber)
959                        {
960                                struct subregobj *obj = reg->objects;
961                                while(obj != NULL)
962                                {
963                                        struct subregobj *n = obj->next;
964                                        free(obj); obj = NULL;
965                                        obj = n;
966                                }
967                                free(reg->buf);
968                                reg->buf = NULL;
969                                free(reg->palette);
970                                reg->palette = NULL;
971
972                                reg->committed = 0;
973                        }
974                        else
975                                break;
976
977                        reg->regid = regid;
978                        reg->versionnumber = versionnumber;
979
980                        reg->width = *seg++ << 8;
981                        reg->width |= *seg++;
982                        proclen += 2;
983
984                        reg->height = *seg++ << 8;
985                        reg->height |= *seg++;
986                        proclen += 2;
987
988                        reg->buf = malloc(reg->width * reg->height);
989                        if(reg->buf == NULL)
990                        {
991                                err("no mem");
992                                break;
993                        }
994                        memset(reg->buf, 0, reg->width * reg->height);
995
996                        //int reglevelofcompatibility = (*seg >> 5) & 7;
997
998                        reg->depth = (*seg++ >> 2) & 7;
999                        proclen++;
1000
1001                        reg->clutid = *seg++; proclen++;
1002
1003                        int reg8bitpixel = *seg++; proclen++;
1004                        int reg4bitpixel = *seg >> 4;
1005                        int reg2bitpixel = (*seg++ >> 2) & 3;
1006                        proclen++;
1007
1008                        if(regfillflag == 0)
1009                        {
1010                                reg2bitpixel = reg4bitpixel = reg8bitpixel = 0;
1011                                regfillflag = 1;
1012                        }
1013
1014                        if(regfillflag != 0)
1015                        {
1016                                if(reg->depth == 1)
1017                                        memset(reg->buf, reg2bitpixel, reg->height * reg->width);
1018                                else if(reg->depth == 2)
1019                                        memset(reg->buf, reg4bitpixel, reg->height * reg->width);
1020                                else if(reg->depth == 3)
1021                                        memset(reg->buf, reg8bitpixel, reg->height * reg->width);
1022                                else
1023                                        debug(300, "invalid depth");
1024                        }
1025
1026                        reg->objects = 0;
1027                        struct subregobj **pobj = &reg->objects;
1028
1029                        while(proclen < seglen)
1030                        {
1031                                struct subregobj *obj;
1032
1033                                obj = malloc(sizeof(struct subregobj));
1034                                if(obj == NULL)
1035                                {
1036                                        err("no mem");
1037                                        proclen += 8;
1038                                        continue;
1039                                }
1040                                memset(obj, 0, sizeof(struct subregobj));
1041
1042                                *pobj = obj;
1043                                pobj = &obj->next;
1044
1045                                obj->objid = *seg++ << 8;
1046                                obj->objid |= *seg++; proclen += 2;
1047
1048                                obj->objtype = *seg >> 6;
1049                                obj->objproviderflag = (*seg >> 4) & 3;
1050                                obj->objhorizontalpos = (*seg++ & 0xF) << 8;
1051                                obj->objhorizontalpos |= *seg++;
1052                                proclen += 2;
1053
1054                                obj->objverticalpos = *seg++ << 8;
1055                                obj->objverticalpos |= *seg++ ;
1056                                proclen += 2;
1057
1058                                if((obj->objtype == 1) || (obj->objtype == 2))
1059                                {
1060                                        obj->foregroundpixel = *seg++;
1061                                        obj->backgroundpixel = *seg++;
1062                                        proclen += 2;
1063                                }
1064                        }
1065
1066                        if(proclen != seglen)
1067                                debug(300, "too less data! (%d < %d)", seglen, proclen);
1068
1069                        break;
1070                }
1071                case 0x12: // CLUT definition segment
1072                {
1073                        int clutid, clutversionnumber;
1074                        struct subclut *clut, **pclut;
1075
1076                        if(page == NULL) break;
1077
1078                        clutid = *seg++;
1079                        clutversionnumber = *seg++ >> 4;
1080                        proclen += 2;
1081
1082                        clut = page->cluts; pclut = &page->cluts;
1083
1084                        while(clut != NULL)
1085                        {
1086                                if(clut->clutid == clutid) break;
1087                                pclut = &clut->next;
1088                                clut = clut->next;
1089                        }
1090
1091                        if(clut == NULL)
1092                        {
1093                                *pclut = clut = malloc(sizeof(struct subclut));
1094                                if(clut == NULL)
1095                                {
1096                                        err("no mem");
1097                                        break;
1098                                }
1099                                memset(clut, 0, sizeof(struct subclut));
1100                                clut->clutid = clutid;
1101                        }
1102                        else if(clut->clutversionnumber == clutversionnumber)
1103                                break;
1104
1105                        clut->clutversionnumber = clutversionnumber;
1106
1107                        memset(clut->entries2bit, 0, sizeof(clut->entries2bit));
1108                        memset(clut->entries4bit, 0, sizeof(clut->entries4bit));
1109                        memset(clut->entries8bit, 0, sizeof(clut->entries8bit));
1110
1111                        while(proclen < seglen)
1112                        {
1113                                int clutentryid, entryclutflag, fullrange;
1114                                int Y, Cr, Cb, T;
1115
1116                                clutentryid = *seg++;
1117                                fullrange = *seg & 1;
1118                                entryclutflag = (*seg++ & 0xE0) >> 5;
1119                                proclen += 2;
1120
1121                                if(fullrange)
1122                                {
1123                                        Y = *seg++;
1124                                        Cr = *seg++;
1125                                        Cb = *seg++;
1126                                        T = *seg++;
1127                                        proclen += 4;
1128                                }
1129                                else
1130                                {
1131                                        Y = *seg & 0xFC;
1132                                        Cr = (*seg++ & 3) << 6;
1133                                        Cr |= (*seg & 0xC0) >> 2;
1134                                        Cb = (*seg & 0x3C) << 2;
1135                                        T = (*seg++ & 3) << 6;
1136                                        proclen += 2;
1137                                }
1138
1139                                if(entryclutflag & 1) // 8bit
1140                                {
1141                                        clut->entries8bit[clutentryid].Y = Y;
1142                                        clut->entries8bit[clutentryid].Cr = Cr;
1143                                        clut->entries8bit[clutentryid].Cb = Cb;
1144                                        clut->entries8bit[clutentryid].T = T;
1145                                        clut->entries8bit[clutentryid].valid = 1;
1146                                }
1147                                if(entryclutflag & 2) // 4bit
1148                                {
1149                                        if(clutentryid < 16)
1150                                        {
1151                                                clut->entries4bit[clutentryid].Y = Y;
1152                                                clut->entries4bit[clutentryid].Cr = Cr;
1153                                                clut->entries4bit[clutentryid].Cb = Cb;
1154                                                clut->entries4bit[clutentryid].T = T;
1155                                                clut->entries4bit[clutentryid].valid = 1;
1156                                        }
1157                                        else
1158                                                debug(300, "CLUT entry marked as 4 bit with id %d (>15)", clutentryid);
1159                                }
1160                                if(entryclutflag & 4) // 2bit
1161                                {
1162                                        if(clutentryid < 4)
1163                                        {
1164                                                clut->entries2bit[clutentryid].Y = Y;
1165                                                clut->entries2bit[clutentryid].Cr = Cr;
1166                                                clut->entries2bit[clutentryid].Cb = Cb;
1167                                                clut->entries2bit[clutentryid].T = T;
1168                                                clut->entries2bit[clutentryid].valid = 1;
1169                                        }
1170                                        else
1171                                                debug(300, "CLUT entry marked as 2 bit with id %d (>3)", clutentryid);
1172                                }
1173                        }
1174                        break;
1175                }
1176                case 0x13: // object data segment
1177                {
1178                        int objid, objversionnumber, objcodingmethod, nonmodifyingcolorflag;
1179
1180                        if(page == NULL)
1181                        {
1182                                debug(300, "no page for object data found");
1183                                break;
1184                        }
1185
1186                        objid = *seg++ << 8;
1187                        objid |= *seg++;
1188                        proclen += 2;
1189
1190                        objversionnumber = *seg >> 4;
1191                        objcodingmethod = (*seg >> 2) & 3;
1192                        nonmodifyingcolorflag = (*seg++ >> 1) & 1;
1193                        proclen++;
1194
1195                        struct subreg *reg = page->regions;
1196                        while(reg != NULL)
1197                        {
1198                                struct subregobj *obj = reg->objects;
1199                                while(obj != NULL)
1200                                {
1201                                        if(obj->objid == objid)
1202                                        {
1203                                                if(objcodingmethod == 0)
1204                                                {
1205                                                        int topfielddatablocklen, bottomfielddatablocklen;
1206                                                        int i = 1, line, linep;
1207
1208                                                        topfielddatablocklen = *seg++ << 8;
1209                                                        topfielddatablocklen |= *seg++;
1210                                                        bottomfielddatablocklen = *seg++ << 8;
1211                                                        bottomfielddatablocklen |= *seg++;
1212                                                        proclen += 4;
1213
1214                                                        map2to4bit[0] = 0;
1215                                                        map2to4bit[1] = 8;
1216                                                        map2to4bit[2] = 7;
1217                                                        map2to4bit[3] = 15;
1218
1219                                                        // this map is realy untested...
1220                                                        map2to8bit[0] = 0;
1221                                                        map2to8bit[1] = 0x88;
1222                                                        map2to8bit[2] = 0x77;
1223                                                        map2to8bit[3] = 0xff;
1224
1225                                                        map4to8bit[0] = 0;
1226                                                        for(; i < 16; ++i)
1227                                                                map4to8bit[i] = i * 0x11;
1228       
1229                                                        i = 0; line = 0; linep = 0;
1230                                                        while(i < topfielddatablocklen)
1231                                                        {
1232                                                                int len;
1233                                                                len = subpixeldata(reg, obj, &line, &linep, seg);
1234                                                                if(len < 0) return -1;
1235                                                                seg += len;
1236                                                                proclen += len;
1237                                                                i += len;
1238                                                        }
1239
1240                                                        line = 1; linep = 0;
1241                                                        if(bottomfielddatablocklen)
1242                                                        {
1243                                                                i = 0;
1244                                                                while(i < bottomfielddatablocklen)
1245                                                                {
1246                                                                        int len;
1247                                                                        len = subpixeldata(reg, obj, &line, &linep, seg);
1248                                                                        if(len < 0) return -1;
1249                                                                        seg += len;
1250                                                                        proclen += len;
1251                                                                        i += len;
1252                                                                }
1253                                                        }
1254                                                        else if(topfielddatablocklen)
1255                                                                debug(300, "unimplemented: no bottom field! (%d : %d)", topfielddatablocklen, bottomfielddatablocklen);
1256       
1257                                                        if((topfielddatablocklen + bottomfielddatablocklen) & 1)
1258                                                        {
1259                                                                seg++; proclen++;
1260                                                        }
1261                                                }
1262                                                else if(objcodingmethod == 1)
1263                                                        debug(300, "object_coding_method 1 unsupported!");
1264                                        }
1265                                        obj = obj->next;
1266                                }
1267                                reg = reg->next;
1268                        }
1269                        break;
1270                }
1271                case 0x14: // display definition segment
1272                {
1273                        if(seglen > 4)
1274                        {
1275                                //int ddsversionnumber = seg[0] >> 4;
1276                                int displaywindowflag = (seg[0] >> 3) & 1;
1277                                int displaywidth = (seg[1] << 8) | (seg[2]);
1278                                int displayheight = (seg[3] << 8) | (seg[4]);
1279
1280                                proclen += 5;
1281                                subdisplaywidth = displaywidth + 1;
1282                                subdisplayheight = displayheight +1;
1283
1284                                if(displaywindowflag)
1285                                {
1286                                        if(seglen > 12)
1287                                        {
1288                                                //int displaywindowhorizontalposmin = (seg[4] << 8) | seg[5];
1289                                                //int displaywindowhorizontalposmax = (seg[6] << 8) | seg[7];
1290                                                //int displaywindowverticalposmin = (seg[8] << 8) | seg[9];
1291                                                //int displaywindowverticalposmax = (seg[10] << 8) | seg[11];
1292                                                proclen += 8;
1293                                        }
1294                                        else
1295                                                debug(300, "display window flag set but display definition segment to short %d!", seglen);
1296                                }
1297                        }
1298                        else
1299                                debug(300, "display definition segment to short %d!", seglen);
1300                        break;
1301                }
1302                case 0x80: // end of display set segment
1303                {
1304                        subcalcall(pts);
1305                }
1306                case 0xFF: // stuffing
1307                        break;
1308                default:
1309                        debug(300, "unhandled segment type %02x", segtype);
1310        }
1311
1312        return seglen + 6;
1313}
1314
1315void subpes(unsigned char *pkt, int len, int id1, int id2)
1316{
1317        int ret = 0;
1318        unsigned long long pts = 0;
1319
1320        ret = verifysubpes(pkt);
1321        if(ret != 0) return;
1322
1323        ret = subgetpts(&pts, pkt);
1324        if(ret == 0)
1325        {
1326                pkt += 6; len -= 6;
1327                // skip PES header
1328                pkt++; len--;
1329                pkt++; len--;
1330
1331                int hdrlen = *pkt++; len--;
1332                pkt += hdrlen; len -= hdrlen;
1333
1334                pkt++; len--; // data identifier
1335                pkt++; len--; // stream id;
1336
1337                if(len <= 0) return;
1338
1339                while(len && *pkt == 0x0F)
1340                {
1341                        int l = subsegment(pkt, id1, id2, pts);
1342                        if(l < 0) break;
1343                        pkt += l;
1344                        len -= l;
1345                }
1346
1347                if(len && *pkt != 0xFF) debug(300, "strange data at the end");
1348
1349                subcalcall(pts);
1350        }
1351}
1352
1353void* subthreadfunc(void *param)
1354{
1355        debug(1000, "in");
1356        struct dvbdev* dmxsubnode = NULL;
1357        int count = 0, len = 0, packlen = 0;
1358        unsigned char* buf = NULL;
1359
1360        struct subtitle* subnode = (struct subtitle*)param;
1361
1362        if(subnode == NULL || subnode->pid < 1)
1363        {
1364                debug(1000, "out -> NULL detect");
1365                pthread_exit(NULL);
1366        }
1367
1368        dmxsubnode = dmxopen(status.aktservice->fedev);
1369        if(dmxsubnode == NULL)
1370        {
1371                err("no demux dev");
1372                pthread_exit(NULL);
1373        }
1374        dmxsetbuffersize(dmxsubnode,  128 * 1024);
1375        if(status.aktservice->fedev != NULL)
1376                dmxsetsource(dmxsubnode, status.aktservice->fedev->fedmxsource);
1377        else
1378                err("NULL detect");
1379        dmxsetpesfilter(dmxsubnode, subnode->pid, -1, DMX_OUT_TAP, DMX_PES_OTHER, 0);
1380
1381#ifdef SIMULATE
1382        int fd = open("simulate/dvbsubtitle.ts", O_RDONLY);
1383        if(fd == -1)
1384        {
1385                perr("open simulate/dvbsubtitle.ts");
1386                pthread_exit(NULL);
1387        }
1388#endif
1389
1390        buf = malloc(16);
1391        if(buf == NULL)
1392        {
1393                err("no mem");
1394                pthread_exit(NULL);
1395        }
1396
1397        status.aktservice->dmxsubtitledev = dmxsubnode;
1398
1399        debug(300, "start subtitle thread");
1400        status.subthreadstatus = ACTIVE;
1401        while(status.subthreadaktion != STOP)
1402        {
1403                if(status.subthreadaktion == PAUSE)
1404                {
1405                        status.subthreadstatus = INPAUSE;
1406                        usleep(100000);
1407                        continue;
1408                }
1409                status.subthreadstatus = ACTIVE;
1410                count = 0;
1411                while(status.subthreadaktion != STOP && status.subthreadaktion != PAUSE)
1412                {
1413                        debug(300, "sync subtitle");
1414#ifdef SIMULATE
1415                        len = TEMP_FAILURE_RETRY(read(fd, &buf[count], 3 - count));
1416#else
1417                        len = dvbread(dmxsubnode, &buf[count], 0, 3 - count, 100 * 1000);
1418#endif
1419                        subclear(1);
1420                        if(len < 0) continue;
1421                        if(len == 3 - count)
1422                        {
1423                                if(buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x01)
1424                                {
1425                                        count = 3;
1426                                        break;
1427                                }
1428                                buf[0] = buf[1];
1429                                buf[1] = buf[2];
1430                                count = 2;
1431                                continue;
1432                        }
1433                        count = count + len;
1434                }
1435
1436                while(status.subthreadaktion != STOP && status.subthreadaktion != PAUSE && count < 6)
1437                {
1438#ifdef SIMULATE
1439                        len = TEMP_FAILURE_RETRY(read(fd, &buf[count], 6 - count));
1440#else
1441                        len = dvbread(dmxsubnode, &buf[count], 0, 6 - count, 100 * 1000);
1442#endif
1443                        subclear(1);
1444                        if(len < 0) continue;
1445                        count = count + len;
1446                }
1447                debug(300, "subtitle read peslen len=%d", len);
1448
1449                packlen = (((uint16_t)buf[4] << 8) | buf[5]) + 6;
1450                buf = realloc(buf, packlen);
1451
1452                while(status.subthreadaktion != STOP && status.subthreadaktion != PAUSE && count < packlen)
1453                {
1454#ifdef SIMULATE
1455                        len = TEMP_FAILURE_RETRY(read(fd, &buf[count], packlen - count));
1456#else
1457                        len = dvbread(dmxsubnode, &buf[count], 0, packlen - count, 100 * 1000);
1458#endif
1459                        subclear(1);
1460                        if(len <= 0) continue;
1461                        count = count + len;
1462
1463                        if(count == packlen)
1464                        {
1465                                debug(300, "decode subtile len=%d", count);
1466                                subpes(buf, count, subnode->id1, subnode->id2);
1467                        }
1468                }
1469        }
1470
1471        debug(300, "end subtitle thread");
1472       
1473        dmxclose(status.aktservice->dmxsubtitledev, -1);
1474        status.aktservice->dmxsubtitledev = NULL;
1475
1476        free(buf);
1477
1478#ifdef SIMULATE
1479        close(fd);
1480#endif
1481
1482        status.subthreadstatus = DEACTIVE;
1483        subfree(0);
1484        subfree(1);
1485
1486        debug(1000, "out");
1487        pthread_exit(NULL);
1488}
1489
1490int subtitlestart(struct subtitle* node)
1491{
1492        int ret;
1493
1494        if(status.subthreadstatus != DEACTIVE)
1495        {
1496                err("subtitle thread in use");
1497                return 1;
1498        }
1499
1500        status.subthreadaktion = START;
1501        pthread_attr_destroy(&status.subthreadattr);
1502        pthread_attr_init(&status.subthreadattr);
1503        pthread_attr_setstacksize(&status.subthreadattr, 50000);
1504        pthread_attr_setdetachstate(&status.subthreadattr, PTHREAD_CREATE_JOINABLE);
1505        ret = pthread_create(&status.subthread, &status.subthreadattr, subthreadfunc, node);
1506        if(ret)
1507        {
1508                err("create subtitle thread");
1509                return 1;
1510        }
1511
1512        return 0;
1513}
1514
1515int subtitlepause(int flag)
1516{
1517        int i = 0;
1518
1519        if(flag == 0)
1520        {
1521                if(status.subthreadstatus == INPAUSE)
1522                        status.subthreadaktion = START;
1523        }
1524        else if(status.subthreadstatus == ACTIVE)
1525        {
1526                status.subthreadaktion = PAUSE;
1527                while(status.subthreadstatus != INPAUSE)
1528                {
1529                        usleep(100000);
1530                        i++; if(i > 20) break;
1531                }
1532                if(i > 20)
1533                        err("detect hanging subthread");
1534                subclear(0);
1535        }
1536
1537        return 0;
1538}
1539
1540int subtitlestop(int flag)
1541{
1542        void* threadstatus;
1543        int i = 0;
1544
1545        status.subthreadaktion = STOP;
1546        while(status.subthreadstatus != DEACTIVE)
1547        {
1548                usleep(100000);
1549                i++; if(i > 20) break;
1550        }
1551        subclear(0);
1552       
1553        if(i > 20)
1554        {
1555                err("detect hanging subthread");
1556        }
1557        else if(status.subthread != 0)
1558                pthread_join(status.subthread, &threadstatus);
1559
1560        status.subthread = 0;
1561        pthread_attr_destroy(&status.subthreadattr);
1562        if(flag == 0)
1563                status.subthreadpid = 0;
1564
1565        return 0;
1566}
1567
1568struct subtitle* checksubtitle(struct channel* chnode, struct subtitle* strack)
1569{
1570        struct subtitle* node = NULL;
1571
1572        if(chnode != NULL)
1573        {
1574                node = chnode->subtitle;
1575                while(node != NULL)
1576                {
1577                        if(node == strack)
1578                                return node;
1579                        node = node->next;
1580                }
1581        }
1582        return NULL;
1583}
1584
1585void screensubtitle()
1586{
1587        int rcret = 0, treffer = 0;
1588        struct skin* subtitle = getscreen("subtitle");
1589        struct skin* listbox = getscreennode(subtitle, "listbox");
1590        struct skin* tmp = NULL;
1591        struct subtitle* node = NULL;
1592
1593        listbox->aktline = 1;
1594        listbox->aktpage = -1;
1595
1596        if(status.aktservice->channel != NULL)
1597        {
1598                m_lock(&status.subtitlemutex, 8);
1599                node = status.aktservice->channel->subtitle;
1600                while(node != NULL)
1601                {
1602                        tmp = addlistbox(subtitle, listbox, tmp, 1);
1603                        if(tmp != NULL)
1604                        {
1605                                changetext(tmp, _(node->name));
1606                                tmp->type = CHOICEBOX;
1607                                tmp->del = 1;
1608                                tmp->handle = (char*)node;
1609
1610                                if(node->pid == status.subthreadpid)
1611                                {
1612                                        changeinput(tmp, _("running"));
1613                                        treffer = 1;
1614                                }
1615                                else
1616                                        changeinput(tmp, "");
1617
1618                                if(treffer == 0) listbox->aktline++;
1619                        }
1620                        node = node->next;
1621                }       
1622                m_unlock(&status.subtitlemutex, 8);
1623        }
1624
1625        if(treffer == 0) listbox->aktline = 1;
1626
1627        drawscreen(subtitle, 0);
1628        addscreenrc(subtitle, listbox);
1629
1630        while(1)
1631        {
1632                rcret = waitrc(subtitle, 0, 0);
1633       
1634                if(rcret == getrcconfigint("rcexit", NULL)) break;
1635                if(rcret == getrcconfigint("rcok", NULL))
1636                {
1637                        if(listbox->select != NULL && listbox->select->handle != NULL)
1638                        {
1639                                subtitlestop(1);
1640                                m_lock(&status.subtitlemutex, 8);
1641                                if(checksubtitle(status.aktservice->channel, (struct subtitle*)listbox->select->handle) != NULL)
1642                                {
1643                                        if(((struct subtitle*)listbox->select->handle)->pid != status.subthreadpid)
1644                                        {
1645                                                clearscreen(subtitle);
1646                                                drawscreen(skin, 0);
1647                                                if(subtitlestart((struct subtitle*)listbox->select->handle) == 0)
1648                                                        status.subthreadpid = ((struct subtitle*)listbox->select->handle)->pid;
1649                                        }
1650                                        else
1651                                                status.subthreadpid = 0;
1652                                }
1653                                else
1654                                        status.subthreadpid = 0;
1655                                m_unlock(&status.subtitlemutex, 8);
1656                        }
1657                        break;
1658                }
1659        }
1660
1661        delmarkedscreennodes(subtitle, 1);
1662        delownerrc(subtitle);
1663        clearscreen(subtitle);
1664}
1665
1666struct subtitle* addsubtitle(struct channel* chnode, int subtype, char* langdesc, int pid, int type, int id1, int id2, struct subtitle* last)
1667{
1668        debug(1000, "in");
1669        struct subtitle *newnode = NULL, *prev = NULL, *node = NULL;
1670        char *tmpstr = NULL, *tmpnr = NULL;
1671
1672        if(chnode == NULL)
1673        {
1674                debug(1000, "out -> NULL detect");
1675                return NULL;
1676        }
1677
1678        newnode = (struct subtitle*)malloc(sizeof(struct subtitle));   
1679        if(newnode == NULL)
1680        {
1681                err("no memory");
1682                return NULL;
1683        }
1684
1685        memset(newnode, 0, sizeof(struct subtitle));
1686
1687        newnode->pid = pid;
1688        newnode->type = type;
1689        newnode->id1 = id1;
1690        newnode->id2 = id2;
1691
1692        if(ostrcmp(langdesc, "und") == 0)
1693                tmpstr = ostrcat(tmpstr, _("undefined"), 1, 0);
1694        else
1695                tmpstr = ostrcat(tmpstr, _(langdesc), 1, 0);
1696        if(subtype == 1)
1697        {
1698                tmpstr = ostrcat(tmpstr, " (", 1, 0);
1699                tmpstr = ostrcat(tmpstr, "TXT Subtitle", 1, 0);
1700                tmpstr = ostrcat(tmpstr, " - ", 1, 0);
1701                tmpnr = oitoa(id2);
1702                tmpstr = ostrcat(tmpstr, tmpnr, 1, 1);
1703                tmpstr = ostrcat(tmpstr, ")", 1, 0);
1704        }
1705        if(subtype == 2)
1706        {
1707                tmpstr = ostrcat(tmpstr, " (", 1, 0);
1708                tmpstr = ostrcat(tmpstr, "DVB Subtitle", 1, 0);
1709                tmpstr = ostrcat(tmpstr, ")", 1, 0);
1710        }
1711        newnode->name = tmpstr;
1712
1713        m_lock(&status.subtitlemutex, 8);
1714        node = chnode->subtitle;
1715        if(last == NULL)
1716        {
1717                while(node != NULL)
1718                {
1719                        prev = node;
1720                        node = node->next;
1721                }
1722        }
1723        else
1724        {
1725                prev = last;
1726                node = last->next;
1727        }
1728
1729        if(prev == NULL)
1730                chnode->subtitle = newnode;
1731        else
1732                prev->next = newnode;
1733
1734        newnode->next = node;
1735
1736        m_unlock(&status.subtitlemutex, 8);
1737        debug(1000, "out");
1738        return newnode;
1739}
1740
1741void freesubtitle(struct channel* chnode)
1742{
1743        debug(1000, "in");
1744        struct subtitle *node = NULL, *prev = NULL;
1745
1746        if(chnode == NULL)
1747        {
1748                debug(1000, "out -> NULL detect");
1749                return;
1750        }
1751
1752        m_lock(&status.subtitlemutex, 8);
1753        node = chnode->subtitle;
1754        prev = chnode->subtitle;
1755
1756        while(node != NULL)
1757        {
1758                prev = node;
1759                node = node->next;
1760                chnode->subtitle = node;
1761
1762                free(prev->name);
1763                prev->name = NULL;
1764
1765                free(prev);
1766                prev = NULL;
1767
1768        }
1769        m_unlock(&status.subtitlemutex, 8);
1770        debug(1000, "out");
1771}
1772
1773#endif
Note: See TracBrowser for help on using the repository browser.