source: titan/titan/subtitle.h @ 24101

Last change on this file since 24101 was 23286, checked in by nit, 11 years ago

[titan] cleanup

File size: 42.0 KB
Line 
1#ifndef SUBTITLE_H
2#define SUBTITLE_H
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                                m_lock(&status.accelfbmutex, 16);
167                                for(y = 0; y < regnode->height; y++)
168                                {
169                                        for(x = 0; x < regnode->width; x++)
170                                        {
171                                                if(regnode->buf[y * regnode->width + x] != 0)
172                                                        drawpixelfb(accelfb, (regnode->width * y) + x, 0, palette[regnode->buf[y * regnode->width + x]]);
173                                                else
174                                                        drawpixelfb(accelfb, (regnode->width * y) + x, 0, 0);
175                                        }
176                                }
177                                blitscale(posx, posy, regnode->width, regnode->height, regnode->scalewidth, regnode->scaleheight, 0);
178                                m_unlock(&status.accelfbmutex, 16);
179                        }
180                        else
181                        {
182                                if(regnode->scalewidth != regnode->width || regnode->scaleheight != regnode->height)
183                                {
184                                        scalebuf = scale(regnode->buf, regnode->width, regnode->height, 1, regnode->scalewidth, regnode->scaleheight, 1);
185                                        if(scalebuf != NULL) regnode->buf = scalebuf;
186                                }
187                                else
188                                        scalebuf = regnode->buf;
189/*
190                                //only for test no scale
191                                posx = pageregnode->reghorizontaladdress;
192                                posy = pageregnode->regverticaladdress;
193                                pageregnode->scaleposx = posx;
194                                pageregnode->scaleposy = posy;
195                                regnode->scalewidth = regnode->width;
196                                regnode->scaleheight = regnode->height;
197*/
198
199                                for(y = 0; y < regnode->scaleheight; y++)
200                                {
201                                        for(x = 0; x < regnode->scalewidth; x++)
202                                        {
203                                                if(regnode->buf[y * regnode->scalewidth + x] != 0)
204                                                {
205                                                        drawpixel(posx + x, posy + y, palette[regnode->buf[y * regnode->scalewidth + x]]);
206                                                }
207                                        }
208                                }
209                        }
210                }
211                pageregnode = pageregnode->next;
212        }
213        if(stat == 1) blitfb(0);
214}
215
216void subcalc(int pageid, unsigned long long pts)
217{
218        int i, clutsize = 0;
219        struct subpage *page = subpage;
220
221        while(page != NULL)
222        {
223                if(page->pageid == pageid) break;
224                page = page->next;
225        }
226
227        if(page == NULL) return;
228
229        struct subpagereg *pagereg = page->pageregions;
230
231        for(; pagereg; pagereg = pagereg->next)
232        {
233                struct subreg *reg = page->regions;
234                while(reg != NULL)
235                {
236                        if(reg->regid == pagereg->regid) break;
237                        reg = reg->next;
238                }
239                if(reg != NULL)
240                {
241                        if(reg->committed) continue;
242
243                        int posx = pagereg->reghorizontaladdress;
244                        int posy = pagereg->regverticaladdress;
245
246                        if(posx < 0 || posy < 0) continue;
247
248                        /* find corresponding clut */
249                        struct subclut *clut = page->cluts;
250                        while(clut != NULL)
251                        {
252                                if(clut->clutid == reg->clutid) break;
253                                clut = clut->next;
254                        }
255
256                        if(reg->depth == 1)
257                        {
258                                clutsize = 4;
259                                reg->palette = (struct rgba*)malloc(clutsize * sizeof(struct rgba));
260                        }
261                        if(reg->depth == 2)
262                        {
263                                clutsize = 16;
264                                reg->palette = (struct rgba*)malloc(clutsize * sizeof(struct rgba));
265                        }
266                        if(reg->depth == 3)
267                        {
268                                clutsize = 256;
269                                reg->palette = (struct rgba*)malloc(clutsize * sizeof(struct rgba));
270                        }
271
272                        struct subclutentry *entries = NULL;
273                        switch(reg->depth)
274                        {
275                                case 1:
276                                {
277                                        if(clut != NULL)
278                                                entries = clut->entries2bit;
279                                        memset(reg->palette, 0, 4 * sizeof(struct rgba));
280                                        reg->palette[0].a = 0xFF;
281                                        reg->palette[2].r = reg->palette[2].g = reg->palette[2].b = 0xFF;
282                                        reg->palette[3].r = reg->palette[3].g = reg->palette[3].b = 0x80;
283                                        break;
284                                }
285                                case 2:
286                                {
287                                        if(clut != NULL)
288                                                entries = clut->entries4bit;
289                                        memset(reg->palette, 0, 16 * sizeof(struct rgba));
290                                        for(i = 0; i < 16; ++i)
291                                        {
292                                                if(!i)
293                                                        reg->palette[i].a = 0xFF;
294                                                else if(i & 8)
295                                                {
296                                                        if(i & 1) reg->palette[i].r = 0x80;
297                                                        if(i & 2) reg->palette[i].g = 0x80;
298                                                        if(i & 4) reg->palette[i].b = 0x80;
299                                                }
300                                                else
301                                                {
302                                                        if(i & 1) reg->palette[i].r = 0xFF;
303                                                        if(i & 2) reg->palette[i].g = 0xFF;
304                                                        if(i & 4) reg->palette[i].b = 0xFF;
305                                                }
306                                        }
307                                        break;
308                                }
309                                case 3:
310                                {
311                                        if(clut != NULL)
312                                                entries = clut->entries8bit;
313                                        memset(reg->palette, 0, 256 * sizeof(struct rgba));
314                                        for(i = 0; i < 256; ++i)
315                                        {
316                                                switch(i & 17)
317                                                {
318                                                        case 0:
319                                                        {
320                                                                if(!(i & 14))
321                                                                {
322                                                                        if(!(i & 224))
323                                                                                reg->palette[i].a = 0xFF;
324                                                                        else
325                                                                        {
326                                                                                if(i & 128) reg->palette[i].r = 0xFF;
327                                                                                if (i & 64) reg->palette[i].g = 0xFF;
328                                                                                if(i & 32) reg->palette[i].b = 0xFF;
329                                                                                reg->palette[i].a = 0xBF;
330                                                                        }
331                                                                        break;
332                                                                }
333                                                        }
334                                                        case 16:
335                                                        {
336                                                                if(i & 128) reg->palette[i].r = 0x55;
337                                                                if(i & 64) reg->palette[i].g = 0x55;
338                                                                if(i & 32) reg->palette[i].b = 0x55;
339                                                                if(i & 8) reg->palette[i].r += 0xAA;
340                                                                if(i & 4) reg->palette[i].g += 0xAA;
341                                                                if(i & 2) reg->palette[i].b += 0xAA;
342                                                                if(i & 16) reg->palette[i].a = 0x80;
343                                                                break;
344                                                        }
345                                                        case 1:
346                                                        {
347                                                                reg->palette[i].r = 0x80;
348                                                                reg->palette[i].g = 0x80;
349                                                                reg->palette[i].b = 0x80;
350                                                        }
351                                                        case 17:
352                                                        {
353                                                                if(i & 128) reg->palette[i].r += 0x2A;
354                                                                if(i & 64) reg->palette[i].g += 0x2A;
355                                                                if(i & 32) reg->palette[i].b += 0x2A;
356                                                                if(i & 8) reg->palette[i].r += 0x55;
357                                                                if(i & 4) reg->palette[i].g += 0x55;
358                                                                if(i & 2) reg->palette[i].b += 0x55;
359                                                                break;
360                                                        }
361
362                                                }
363                                                break;
364                                        }
365                                }
366                        }
367
368                        for(i = 0; i < clutsize; ++i)
369                        {
370                                if(entries && entries[i].valid)
371                                {
372                                        int y = entries[i].Y;
373                                        int cr = entries[i].Cr;
374                                        int cb = entries[i].Cb;
375
376                                        if(y > 0)
377                                        {
378                                                y -= 16;
379                                                cr -= 128;
380                                                cb -= 128;
381                                                reg->palette[i].r = OMAX(OMIN(((298 * y            + 460 * cr) / 256), 255), 0);
382                                                reg->palette[i].g = OMAX(OMIN(((298 * y -  55 * cb - 137 * cr) / 256), 255), 0);
383                                                reg->palette[i].b = OMAX(OMIN(((298 * y + 543 * cb           ) / 256), 255), 0);
384                                                //reg->palette[i].a = (entries[i].T) & 0xFF;
385                                                reg->palette[i].a = 0xFF;
386                                        }
387                                        else
388                                        {
389                                                reg->palette[i].r = 0;
390                                                reg->palette[i].g = 0;
391                                                reg->palette[i].b = 0;
392                                                reg->palette[i].a = 0xFF;
393                                        }
394                                }
395                        }
396
397                        reg->committed = 1;
398                }
399        }
400        page->pagetimeout += time(NULL);
401        subdraw(pts, page);
402        subfree(0);
403        oldsubpage = subpage;
404        subpage = NULL;
405}
406
407void subcalcall(unsigned long long pts)
408{
409#if 1
410        struct subpage *page = subpage;
411
412        while(page != NULL)
413        {
414                if(page->state != 0)
415                        subcalc(page->pageid, pts);
416                page = page->next;
417        }
418#else
419        struct subpage *page = subpage;
420
421        debug(300, "end of display set");
422        debug(300, "active pages:");
423        while(page != NULL)
424        {
425                debug(300, "page_id %02x", page->pageid);
426                debug(300, "page_version_number: %d", page->pageversionnumber);
427                debug(300, "active regions:");
428                {
429                        subpagereg *reg = page->pageregions;
430                        while(reg != NULL)
431                        {
432                                debug(300, "region_id: %04x", reg->regid);
433                                debug(300, "region_horizontal_address: %d", reg->reghorizontaladdress);
434                                debug(300, "region_vertical_address: %d", reg->regverticaladdress);
435
436                                reg = reg->next;
437                        }
438                }
439
440                subcalc(page->pageid);
441
442                debug(300, "defined regions:");
443                struct subregion *reg = page->regions;
444                while(reg != NULL)
445                {
446                        debug("region_id %04x, version %d, %dx%d", reg->regid, reg->versionnumber, reg->width, reg->height);
447
448                        struct subregobj *obj = reg->objects;
449                        while(object != NULL)
450                        {
451                                debug(300, "object %02x, type %d, %d:%d", obj->objid, obj->objtype, obj->objhorizontalpos, obj->objverticalpos);
452                                obj = obj->next;
453                        }
454                        reg = reg->next;
455                }
456                page = page->next;
457        }
458#endif
459}
460
461void bitstreaminit(struct bitstream *bit, const void *buf, int size)
462{
463        bit->data = (unsigned char*) buf;
464        bit->size = size;
465        bit->avail = 8;
466        bit->consumed = 0;
467}
468
469int bitstreamget(struct bitstream *bit)
470{
471        int val;
472        bit->avail -= bit->size;
473        val = ((*bit->data) >> bit->avail) & ((1 << bit->size) - 1);
474        if(!bit->avail)
475        {
476                bit->data++;
477                bit->consumed++;
478                bit->avail = 8;
479        }
480        return val;
481}
482
483int verifysubpes(unsigned char* pkt)
484{
485        int substart, pktlen;
486
487        if(pkt == NULL)
488        {
489                debug(300, "NULL Paket");
490                return 1;
491        }
492
493        /* Packet header == 0x000001 */
494        if(pkt[0] != 0x00 || pkt[1] != 0x00 || pkt[2] != 0x01)
495        {
496                debug(300, "Invalid header");
497                return 1;
498        }
499
500        /* stream_id == private_stream_1 */
501        if(pkt[3] != 0xbd)
502        {
503                debug(300, "Not a private_stream_1 stream (%x)\n", pkt[3]);
504                return 1;
505        }
506
507        /* data_alignment_indicator == 1 */
508        if((pkt[6] & 0x04) == 0)
509        {
510                debug(300, "Data alignment indicator == 0");
511                return 1;
512        }
513
514        /* PTS is present */
515        if((pkt[7] & 0x80) == 0)
516        {
517                debug(300, "No PTS");
518                return 1;
519        }
520
521        substart = 9 + pkt[8];
522        pktlen = ((uint16_t)pkt[4] << 8) + pkt[5] + 6;
523
524        /* data_identifier == 0x20, subtitle_stream_id == 0x00,
525        end_of_PES_data_field_marker == 0xff */
526        if(pkt[substart] != 0x20)
527        {
528                debug(300, "Data identifier != 0x20");
529                return 1;
530        }
531
532        if(pkt[substart + 1] != 0x00)
533        {
534                debug(300, "Subtitle stream ID %x != 0x00\n", pkt[substart + 1]);
535                return 1;
536        }
537
538        if(pkt[pktlen - 1] != 0xff)
539        {
540                debug(300, "Wrong packet length");
541                return 1;
542        }
543
544        return 0;
545}
546
547int subgetpts(unsigned long long *pts, unsigned char *pkt)
548{
549        pkt += 7;
550        int flags = *pkt++;
551
552        pkt++; // header length
553
554        if(flags & 0x80) /* PTS present? */
555        {
556                *pts = ((unsigned long long)(((pkt[0] >> 1) & 7))) << 30;
557                *pts |= pkt[1] << 22;
558                *pts |= (pkt[2] >> 1) << 15;
559                *pts |= pkt[3] << 7;
560                *pts |= (pkt[5] >> 1);
561
562                return 0;
563        } else
564                return 1;
565}
566
567void subline(struct subreg *reg, struct subregobj *obj, int line, unsigned char *data, int len)
568{
569        int x = obj->objhorizontalpos;
570        int y = obj->objverticalpos + line;
571
572        if(x + len > reg->width) len = reg->width - x;
573        if(len < 0) return;
574        if(y >= reg->height) return;
575
576        memcpy(reg->buf + reg->width * y + x, data, len);
577}
578
579int subpixeldata(struct subreg *reg, struct subregobj *obj, int *linenr, int *linep, unsigned char *data)
580{
581        int datatype = *data++, i = 0;
582        static unsigned char line[1920];
583        struct bitstream bit;
584
585        bit.size = 0;
586        switch(datatype)
587        {
588                case 0x10: // 2bit pixel data
589                {
590                        bitstreaminit(&bit, data, 2);
591                        while(1)
592                        {
593                                int len = 0, col = 0;
594                                int code = bitstreamget(&bit);
595
596                                if(code)
597                                {
598                                        col = code;
599                                        len = 1;
600                                }
601                                else
602                                {
603                                        code = bitstreamget(&bit);
604                                        if(!code)
605                                        {
606                                                code = bitstreamget(&bit);
607                                                if(code == 1)
608                                                {
609                                                        col = 0;
610                                                        len = 2;
611                                                }
612                                                else if(code == 2)
613                                                {
614                                                        len = bitstreamget(&bit) << 2;
615                                                        len |= bitstreamget(&bit);
616                                                        len += 12;
617                                                        col = bitstreamget(&bit);
618                                                }
619                                                else if(code == 3)
620                                                {
621                                                        len = bitstreamget(&bit) << 6;
622                                                        len |= bitstreamget(&bit) << 4;
623                                                        len |= bitstreamget(&bit) << 2;
624                                                        len |= bitstreamget(&bit);
625                                                        len += 29;
626                                                        col = bitstreamget(&bit);
627                                                }
628                                                else
629                                                        break;
630                                        }
631                                        else if(code==1)
632                                        {
633                                                col = 0;
634                                                len = 1;
635                                        }
636                                        else if(code & 2)
637                                        {
638                                                if(code & 1)
639                                                        len = 3 + 4 + bitstreamget(&bit);
640                                                else
641                                                        len = 3 + bitstreamget(&bit);
642                                                col = bitstreamget(&bit);
643                                        }
644                                }
645
646                                uint8_t c = reg->depth == 1 ? map2to4bit[col] : reg->depth == 2 ? map2to8bit[col] : col;
647                                while(len && ((*linep) < subdisplaywidth))
648                                {
649                                        line[(*linep)++] = c;
650                                        len--;
651                                }
652                        }
653                        while(bit.avail != 8)
654                                bitstreamget(&bit);
655                        return bit.consumed + 1;
656                }
657                case 0x11: // 4bit pixel data
658                {
659                        bitstreaminit(&bit, data, 4);
660                        while(1)
661                        {
662                                int len = 0, col = 0;
663                                int code = bitstreamget(&bit);
664                                if(code)
665                                {
666                                        col = code;
667                                        len = 1;
668                                }
669                                else
670                                {
671                                        code = bitstreamget(&bit);
672                                        if(!code)
673                                                break;
674                                        else if(code == 0xC)
675                                        {
676                                                col = 0;
677                                                len = 1;
678                                        }
679                                        else if(code == 0xD)
680                                        {
681                                                col = 0;
682                                                len = 2;
683                                        }
684                                        else if(code < 8)
685                                        {
686                                                col = 0;
687                                                len = (code & 7) + 2;
688                                        }
689                                        else if((code & 0xC) == 0x8)
690                                        {
691                                                col = bitstreamget(&bit);
692                                                len = (code & 3) + 4;
693                                        }
694                                        else if(code == 0xE)
695                                        {
696                                                len = bitstreamget(&bit) + 9;
697                                                col = bitstreamget(&bit);
698                                        }
699                                        else if(code == 0xF)
700                                        {
701                                                len = bitstreamget(&bit) << 4;
702                                                len |= bitstreamget(&bit);
703                                                len += 25;
704                                                col = bitstreamget(&bit);
705                                        }
706                                }
707                                uint8_t c = reg->depth == 3 ? map4to8bit[col] : col;
708                                while(len && ((*linep) < subdisplaywidth))
709                                {
710                                        line[(*linep)++] = c;
711                                        len--;
712                                }
713                        }
714                        while(bit.avail != 8)
715                                bitstreamget(&bit);
716                        return bit.consumed + 1;
717                }
718                case 0x12: // 8bit pixel data
719                {
720                        bitstreaminit(&bit, data, 8);
721                        while(1)
722                        {
723                                int len = 0, col = 0;
724                                int code = bitstreamget(&bit);
725                                if(code)
726                                {
727                                        col = code;
728                                        len = 1;
729                                }
730                                else
731                                {
732                                        code = bitstreamget(&bit);
733                                        if((code & 0x80) == 0x80)
734                                        {
735                                                len = code & 0x7F;
736                                                col = bitstreamget(&bit);
737                                        }
738                                        else if(code & 0x7F)
739                                        {
740                                                len = code & 0x7F;
741                                                col = 0;
742                                        }
743                                        else
744                                                break;
745                                }
746                                while(len && ((*linep) < subdisplaywidth))
747                                {
748                                        line[(*linep)++] = col;
749                                        len--;
750                                }
751                        }
752                        return bit.consumed + 1;
753                }
754                case 0x20:
755                {
756                        bitstreaminit(&bit, data, 4);
757                        for(i = 0; i < 4; ++i)
758                                map2to4bit[i] = bitstreamget(&bit);
759                        return bit.consumed + 1;
760                }
761                case 0x21:
762                {
763                        bitstreaminit(&bit, data, 8);
764                        for(i = 0; i < 4; ++i)
765                                map2to8bit[i] = bitstreamget(&bit);
766                        return bit.consumed + 1;
767                }
768                case 0x22:
769                {
770                        bitstreaminit(&bit, data, 8);
771                        for(i = 0; i < 16; ++i)
772                        map4to8bit[i] = bitstreamget(&bit);
773                        return bit.consumed + 1;
774                }
775                case 0xF0:
776                {
777                        subline(reg, obj, *linenr, line, *linep);
778                        (*linenr) += 2; // interlaced
779                        *linep = 0;
780                        return 1;
781                }
782                default:
783                {
784                        debug(300, "subtitle_process_pixel_data: invalid data_type %02x", datatype);
785                        return -1;
786                }
787        }
788        return 0;
789}
790
791int subsegment(unsigned char *seg, int id1, int id2, unsigned long long pts)
792{
793        int segtype, pageid, seglen, proclen;
794
795        if(*seg++ != 0x0F)
796        {
797                debug(300, "segment out of sync");
798                return -1;
799        }
800
801        segtype = *seg++;
802        pageid  = *seg++ << 8;
803        pageid |= *seg++;
804        seglen = *seg++ << 8;
805        seglen |= *seg++;
806
807        if(segtype == 0xFF) return seglen + 6;
808
809        if(pageid != id1 && pageid != id2)
810                return seglen + 6;
811
812        struct subpage *page = subpage, **ppage = &subpage;
813
814        while(page != NULL)
815        {
816                if(page->pageid == pageid) break;
817                page = page->next;
818        }
819
820        proclen = 0;
821
822        switch(segtype)
823        {
824                case 0x10: // page composition segment
825                {
826                        int pagetimeout = *seg++; proclen++;
827                        int pageversionnumber = *seg >> 4;
828                        int pagestate = (*seg >> 2) & 0x3;
829                        seg++;
830                        proclen++;
831
832                        if(page == NULL)
833                        {
834                                page = malloc(sizeof(struct subpage));
835                                if(page == NULL)
836                                {
837                                        err("no mem");
838                                        break;
839                                }
840                                memset(page, 0, sizeof(struct subpage));
841                                page->pageid = pageid;
842                                *ppage = page;
843                        }
844                        else
845                        {
846                                if(page->pcssize != seglen)
847                                        page->pageversionnumber = -1;
848                                // if no update, just skip this data.
849                                if(page->pageversionnumber == pageversionnumber)
850                                        break;
851                        }
852
853                        page->state = pagestate;
854
855                        if((pagestate == 1) || (pagestate == 2))
856                        {
857                                while(page->pageregions != NULL)
858                                {
859                                        struct subpagereg *p = page->pageregions->next;
860                                        free(page->pageregions);
861                                        page->regions = NULL;
862                                        page->pageregions = p;
863                                }
864                                while(page->regions)
865                                {
866                                        struct subreg *p = page->regions->next;
867                                        while(page->regions->objects)
868                                        {
869                                                struct subregobj *obj = page->regions->objects->next;
870                                                free(page->regions->objects);
871                                                page->regions->objects = NULL;
872                                                page->regions->objects = obj;
873                                        }
874                                        free(page->regions);
875                                        page->regions = NULL;
876                                        page->regions = p;
877                                }
878
879                        }
880
881                        page->pagetimeout = pagetimeout;
882                        page->pageversionnumber = pageversionnumber;
883
884                        struct subpagereg **reg = &page->pageregions;
885
886                        while(*reg != NULL) reg = &(*reg)->next;
887
888                        if(proclen == seglen && !page->pageregions)
889                        {
890                                debug(300, "no regions in page.. clear screen!!");
891                                //TODO: ??
892                                //subcalc(page->pageid);
893                        }
894
895                        while(proclen < seglen)
896                        {
897                                struct subpagereg *preg;
898
899                                // append new entry to list
900                                preg = malloc(sizeof(struct subpagereg));
901                                if(preg == NULL)
902                                {
903                                        err("no mem");
904                                        proclen += 6;
905                                        continue;
906                                }
907                                memset(preg, 0, sizeof(struct subpagereg));
908                                *reg = preg;
909                                reg = &preg->next;
910
911                                preg->regid = *seg++; proclen++;
912                                seg++; proclen++;
913
914                                preg->reghorizontaladdress = *seg++ << 8;
915                                preg->reghorizontaladdress |= *seg++;
916                                proclen += 2;
917
918                                preg->regverticaladdress = *seg++ << 8;
919                                preg->regverticaladdress |= *seg++;
920                                proclen += 2;
921                        }
922
923                        if(proclen != seglen)
924                                debug(300, "proclen %d != seglen %d", proclen, seglen);
925                        break;
926                }
927                case 0x11: // region composition segment
928                {
929                        int regid = *seg++; proclen++;
930                        int versionnumber = *seg >> 4;
931                        int regfillflag = (*seg >> 3) & 1;
932                        seg++; proclen++;
933
934                        if(page == NULL)
935                        {
936                                debug(300, "ignoring region %x, since page %02x doesn't yet exist.", regid, pageid);
937                                break;
938                        }
939
940                        struct subreg *reg = page->regions, **preg = &page->regions;
941
942                        while(reg != NULL)
943                        {
944                                if(reg->regid == regid) break;
945                                preg = &reg->next;
946                                reg = reg->next;
947                        }
948
949                        if(reg == NULL)
950                        {
951                                *preg = reg = malloc(sizeof(struct subreg));
952                                if(reg == NULL)
953                                {
954                                        err("no mem");
955                                        break;
956                                }
957                                memset(reg, 0, sizeof(struct subreg));
958                                reg->committed = 0;
959                        }
960                        else if(reg->versionnumber != versionnumber)
961                        {
962                                struct subregobj *obj = reg->objects;
963                                while(obj != NULL)
964                                {
965                                        struct subregobj *n = obj->next;
966                                        free(obj); obj = NULL;
967                                        obj = n;
968                                }
969                                free(reg->buf);
970                                reg->buf = NULL;
971                                free(reg->palette);
972                                reg->palette = NULL;
973
974                                reg->committed = 0;
975                        }
976                        else
977                                break;
978
979                        reg->regid = regid;
980                        reg->versionnumber = versionnumber;
981
982                        reg->width = *seg++ << 8;
983                        reg->width |= *seg++;
984                        proclen += 2;
985
986                        reg->height = *seg++ << 8;
987                        reg->height |= *seg++;
988                        proclen += 2;
989
990                        reg->buf = malloc(reg->width * reg->height);
991                        if(reg->buf == NULL)
992                        {
993                                err("no mem");
994                                break;
995                        }
996                        memset(reg->buf, 0, reg->width * reg->height);
997
998                        //int reglevelofcompatibility = (*seg >> 5) & 7;
999
1000                        reg->depth = (*seg++ >> 2) & 7;
1001                        proclen++;
1002
1003                        reg->clutid = *seg++; proclen++;
1004
1005                        int reg8bitpixel = *seg++; proclen++;
1006                        int reg4bitpixel = *seg >> 4;
1007                        int reg2bitpixel = (*seg++ >> 2) & 3;
1008                        proclen++;
1009
1010                        if(regfillflag == 0)
1011                        {
1012                                reg2bitpixel = reg4bitpixel = reg8bitpixel = 0;
1013                                regfillflag = 1;
1014                        }
1015
1016                        if(regfillflag != 0)
1017                        {
1018                                if(reg->depth == 1)
1019                                        memset(reg->buf, reg2bitpixel, reg->height * reg->width);
1020                                else if(reg->depth == 2)
1021                                        memset(reg->buf, reg4bitpixel, reg->height * reg->width);
1022                                else if(reg->depth == 3)
1023                                        memset(reg->buf, reg8bitpixel, reg->height * reg->width);
1024                                else
1025                                        debug(300, "invalid depth");
1026                        }
1027
1028                        reg->objects = 0;
1029                        struct subregobj **pobj = &reg->objects;
1030
1031                        while(proclen < seglen)
1032                        {
1033                                struct subregobj *obj;
1034
1035                                obj = malloc(sizeof(struct subregobj));
1036                                if(obj == NULL)
1037                                {
1038                                        err("no mem");
1039                                        proclen += 8;
1040                                        continue;
1041                                }
1042                                memset(obj, 0, sizeof(struct subregobj));
1043
1044                                *pobj = obj;
1045                                pobj = &obj->next;
1046
1047                                obj->objid = *seg++ << 8;
1048                                obj->objid |= *seg++; proclen += 2;
1049
1050                                obj->objtype = *seg >> 6;
1051                                obj->objproviderflag = (*seg >> 4) & 3;
1052                                obj->objhorizontalpos = (*seg++ & 0xF) << 8;
1053                                obj->objhorizontalpos |= *seg++;
1054                                proclen += 2;
1055
1056                                obj->objverticalpos = *seg++ << 8;
1057                                obj->objverticalpos |= *seg++ ;
1058                                proclen += 2;
1059
1060                                if((obj->objtype == 1) || (obj->objtype == 2))
1061                                {
1062                                        obj->foregroundpixel = *seg++;
1063                                        obj->backgroundpixel = *seg++;
1064                                        proclen += 2;
1065                                }
1066                        }
1067
1068                        if(proclen != seglen)
1069                                debug(300, "too less data! (%d < %d)", seglen, proclen);
1070
1071                        break;
1072                }
1073                case 0x12: // CLUT definition segment
1074                {
1075                        int clutid, clutversionnumber;
1076                        struct subclut *clut, **pclut;
1077
1078                        if(page == NULL) break;
1079
1080                        clutid = *seg++;
1081                        clutversionnumber = *seg++ >> 4;
1082                        proclen += 2;
1083
1084                        clut = page->cluts; pclut = &page->cluts;
1085
1086                        while(clut != NULL)
1087                        {
1088                                if(clut->clutid == clutid) break;
1089                                pclut = &clut->next;
1090                                clut = clut->next;
1091                        }
1092
1093                        if(clut == NULL)
1094                        {
1095                                *pclut = clut = malloc(sizeof(struct subclut));
1096                                if(clut == NULL)
1097                                {
1098                                        err("no mem");
1099                                        break;
1100                                }
1101                                memset(clut, 0, sizeof(struct subclut));
1102                                clut->clutid = clutid;
1103                        }
1104                        else if(clut->clutversionnumber == clutversionnumber)
1105                                break;
1106
1107                        clut->clutversionnumber = clutversionnumber;
1108
1109                        memset(clut->entries2bit, 0, sizeof(clut->entries2bit));
1110                        memset(clut->entries4bit, 0, sizeof(clut->entries4bit));
1111                        memset(clut->entries8bit, 0, sizeof(clut->entries8bit));
1112
1113                        while(proclen < seglen)
1114                        {
1115                                int clutentryid, entryclutflag, fullrange;
1116                                int Y, Cr, Cb, T;
1117
1118                                clutentryid = *seg++;
1119                                fullrange = *seg & 1;
1120                                entryclutflag = (*seg++ & 0xE0) >> 5;
1121                                proclen += 2;
1122
1123                                if(fullrange)
1124                                {
1125                                        Y = *seg++;
1126                                        Cr = *seg++;
1127                                        Cb = *seg++;
1128                                        T = *seg++;
1129                                        proclen += 4;
1130                                }
1131                                else
1132                                {
1133                                        Y = *seg & 0xFC;
1134                                        Cr = (*seg++ & 3) << 6;
1135                                        Cr |= (*seg & 0xC0) >> 2;
1136                                        Cb = (*seg & 0x3C) << 2;
1137                                        T = (*seg++ & 3) << 6;
1138                                        proclen += 2;
1139                                }
1140
1141                                if(entryclutflag & 1) // 8bit
1142                                {
1143                                        clut->entries8bit[clutentryid].Y = Y;
1144                                        clut->entries8bit[clutentryid].Cr = Cr;
1145                                        clut->entries8bit[clutentryid].Cb = Cb;
1146                                        clut->entries8bit[clutentryid].T = T;
1147                                        clut->entries8bit[clutentryid].valid = 1;
1148                                }
1149                                if(entryclutflag & 2) // 4bit
1150                                {
1151                                        if(clutentryid < 16)
1152                                        {
1153                                                clut->entries4bit[clutentryid].Y = Y;
1154                                                clut->entries4bit[clutentryid].Cr = Cr;
1155                                                clut->entries4bit[clutentryid].Cb = Cb;
1156                                                clut->entries4bit[clutentryid].T = T;
1157                                                clut->entries4bit[clutentryid].valid = 1;
1158                                        }
1159                                        else
1160                                                debug(300, "CLUT entry marked as 4 bit with id %d (>15)", clutentryid);
1161                                }
1162                                if(entryclutflag & 4) // 2bit
1163                                {
1164                                        if(clutentryid < 4)
1165                                        {
1166                                                clut->entries2bit[clutentryid].Y = Y;
1167                                                clut->entries2bit[clutentryid].Cr = Cr;
1168                                                clut->entries2bit[clutentryid].Cb = Cb;
1169                                                clut->entries2bit[clutentryid].T = T;
1170                                                clut->entries2bit[clutentryid].valid = 1;
1171                                        }
1172                                        else
1173                                                debug(300, "CLUT entry marked as 2 bit with id %d (>3)", clutentryid);
1174                                }
1175                        }
1176                        break;
1177                }
1178                case 0x13: // object data segment
1179                {
1180                        int objid, objversionnumber, objcodingmethod, nonmodifyingcolorflag;
1181
1182                        if(page == NULL)
1183                        {
1184                                debug(300, "no page for object data found");
1185                                break;
1186                        }
1187
1188                        objid = *seg++ << 8;
1189                        objid |= *seg++;
1190                        proclen += 2;
1191
1192                        objversionnumber = *seg >> 4;
1193                        objcodingmethod = (*seg >> 2) & 3;
1194                        nonmodifyingcolorflag = (*seg++ >> 1) & 1;
1195                        proclen++;
1196
1197                        struct subreg *reg = page->regions;
1198                        while(reg != NULL)
1199                        {
1200                                struct subregobj *obj = reg->objects;
1201                                while(obj != NULL)
1202                                {
1203                                        if(obj->objid == objid)
1204                                        {
1205                                                if(objcodingmethod == 0)
1206                                                {
1207                                                        int topfielddatablocklen, bottomfielddatablocklen;
1208                                                        int i = 1, line, linep;
1209
1210                                                        topfielddatablocklen = *seg++ << 8;
1211                                                        topfielddatablocklen |= *seg++;
1212                                                        bottomfielddatablocklen = *seg++ << 8;
1213                                                        bottomfielddatablocklen |= *seg++;
1214                                                        proclen += 4;
1215
1216                                                        map2to4bit[0] = 0;
1217                                                        map2to4bit[1] = 8;
1218                                                        map2to4bit[2] = 7;
1219                                                        map2to4bit[3] = 15;
1220
1221                                                        // this map is realy untested...
1222                                                        map2to8bit[0] = 0;
1223                                                        map2to8bit[1] = 0x88;
1224                                                        map2to8bit[2] = 0x77;
1225                                                        map2to8bit[3] = 0xff;
1226
1227                                                        map4to8bit[0] = 0;
1228                                                        for(; i < 16; ++i)
1229                                                                map4to8bit[i] = i * 0x11;
1230       
1231                                                        i = 0; line = 0; linep = 0;
1232                                                        while(i < topfielddatablocklen)
1233                                                        {
1234                                                                int len;
1235                                                                len = subpixeldata(reg, obj, &line, &linep, seg);
1236                                                                if(len < 0) return -1;
1237                                                                seg += len;
1238                                                                proclen += len;
1239                                                                i += len;
1240                                                        }
1241
1242                                                        line = 1; linep = 0;
1243                                                        if(bottomfielddatablocklen)
1244                                                        {
1245                                                                i = 0;
1246                                                                while(i < bottomfielddatablocklen)
1247                                                                {
1248                                                                        int len;
1249                                                                        len = subpixeldata(reg, obj, &line, &linep, seg);
1250                                                                        if(len < 0) return -1;
1251                                                                        seg += len;
1252                                                                        proclen += len;
1253                                                                        i += len;
1254                                                                }
1255                                                        }
1256                                                        else if(topfielddatablocklen)
1257                                                                debug(300, "unimplemented: no bottom field! (%d : %d)", topfielddatablocklen, bottomfielddatablocklen);
1258       
1259                                                        if((topfielddatablocklen + bottomfielddatablocklen) & 1)
1260                                                        {
1261                                                                seg++; proclen++;
1262                                                        }
1263                                                }
1264                                                else if(objcodingmethod == 1)
1265                                                        debug(300, "object_coding_method 1 unsupported!");
1266                                        }
1267                                        obj = obj->next;
1268                                }
1269                                reg = reg->next;
1270                        }
1271                        break;
1272                }
1273                case 0x14: // display definition segment
1274                {
1275                        if(seglen > 4)
1276                        {
1277                                //int ddsversionnumber = seg[0] >> 4;
1278                                int displaywindowflag = (seg[0] >> 3) & 1;
1279                                int displaywidth = (seg[1] << 8) | (seg[2]);
1280                                int displayheight = (seg[3] << 8) | (seg[4]);
1281
1282                                proclen += 5;
1283                                subdisplaywidth = displaywidth + 1;
1284                                subdisplayheight = displayheight +1;
1285
1286                                if(displaywindowflag)
1287                                {
1288                                        if(seglen > 12)
1289                                        {
1290                                                //int displaywindowhorizontalposmin = (seg[4] << 8) | seg[5];
1291                                                //int displaywindowhorizontalposmax = (seg[6] << 8) | seg[7];
1292                                                //int displaywindowverticalposmin = (seg[8] << 8) | seg[9];
1293                                                //int displaywindowverticalposmax = (seg[10] << 8) | seg[11];
1294                                                proclen += 8;
1295                                        }
1296                                        else
1297                                                debug(300, "display window flag set but display definition segment to short %d!", seglen);
1298                                }
1299                        }
1300                        else
1301                                debug(300, "display definition segment to short %d!", seglen);
1302                        break;
1303                }
1304                case 0x80: // end of display set segment
1305                {
1306                        subcalcall(pts);
1307                }
1308                case 0xFF: // stuffing
1309                        break;
1310                default:
1311                        debug(300, "unhandled segment type %02x", segtype);
1312        }
1313
1314        return seglen + 6;
1315}
1316
1317void subpes(unsigned char *pkt, int len, int id1, int id2)
1318{
1319        int ret = 0;
1320        unsigned long long pts = 0;
1321
1322        ret = verifysubpes(pkt);
1323        if(ret != 0) return;
1324
1325        ret = subgetpts(&pts, pkt);
1326        if(ret == 0)
1327        {
1328                pkt += 6; len -= 6;
1329                // skip PES header
1330                pkt++; len--;
1331                pkt++; len--;
1332
1333                int hdrlen = *pkt++; len--;
1334                pkt += hdrlen; len -= hdrlen;
1335
1336                pkt++; len--; // data identifier
1337                pkt++; len--; // stream id;
1338
1339                if(len <= 0) return;
1340
1341                while(len && *pkt == 0x0F)
1342                {
1343                        int l = subsegment(pkt, id1, id2, pts);
1344                        if(l < 0) break;
1345                        pkt += l;
1346                        len -= l;
1347                }
1348
1349                if(len && *pkt != 0xFF) debug(300, "strange data at the end");
1350
1351                subcalcall(pts);
1352        }
1353}
1354
1355void* subthreadfunc(void *param)
1356{
1357        struct dvbdev* dmxsubnode = NULL;
1358        int count = 0, len = 0, packlen = 0;
1359        unsigned char* buf = NULL;
1360
1361        struct subtitle* subnode = (struct subtitle*)param;
1362
1363        if(subnode == NULL || subnode->pid < 1)
1364        {
1365                err("NULL detect");
1366                pthread_exit(NULL);
1367        }
1368
1369        dmxsubnode = dmxopen(status.aktservice->fedev);
1370        if(dmxsubnode == NULL)
1371        {
1372                err("no demux dev");
1373                pthread_exit(NULL);
1374        }
1375        dmxsetbuffersize(dmxsubnode,  128 * 1024);
1376        if(status.aktservice->fedev != NULL)
1377                dmxsetsource(dmxsubnode, status.aktservice->fedev->fedmxsource);
1378        else
1379                err("NULL detect");
1380        dmxsetpesfilter(dmxsubnode, subnode->pid, -1, DMX_OUT_TAP, DMX_PES_OTHER, 0);
1381
1382#ifdef SIMULATE
1383        int fd = open("simulate/dvbsubtitle.ts", O_RDONLY);
1384        if(fd == -1)
1385        {
1386                perr("open simulate/dvbsubtitle.ts");
1387                pthread_exit(NULL);
1388        }
1389#endif
1390
1391        buf = malloc(16);
1392        if(buf == NULL)
1393        {
1394                err("no mem");
1395                pthread_exit(NULL);
1396        }
1397
1398        status.aktservice->dmxsubtitledev = dmxsubnode;
1399
1400        debug(300, "start subtitle thread");
1401        status.subthreadstatus = ACTIVE;
1402        while(status.subthreadaktion != STOP)
1403        {
1404                if(status.subthreadaktion == PAUSE)
1405                {
1406                        status.subthreadstatus = INPAUSE;
1407                        usleep(100000);
1408                        continue;
1409                }
1410                status.subthreadstatus = ACTIVE;
1411                count = 0;
1412                while(status.subthreadaktion != STOP && status.subthreadaktion != PAUSE)
1413                {
1414                        debug(300, "sync subtitle");
1415#ifdef SIMULATE
1416                        len = TEMP_FAILURE_RETRY(read(fd, &buf[count], 3 - count));
1417#else
1418                        len = dvbread(dmxsubnode, &buf[count], 0, 3 - count, 100 * 1000);
1419#endif
1420                        subclear(1);
1421                        if(len < 0) continue;
1422                        if(len == 3 - count)
1423                        {
1424                                if(buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x01)
1425                                {
1426                                        count = 3;
1427                                        break;
1428                                }
1429                                buf[0] = buf[1];
1430                                buf[1] = buf[2];
1431                                count = 2;
1432                                continue;
1433                        }
1434                        count = count + len;
1435                }
1436
1437                while(status.subthreadaktion != STOP && status.subthreadaktion != PAUSE && count < 6)
1438                {
1439#ifdef SIMULATE
1440                        len = TEMP_FAILURE_RETRY(read(fd, &buf[count], 6 - count));
1441#else
1442                        len = dvbread(dmxsubnode, &buf[count], 0, 6 - count, 100 * 1000);
1443#endif
1444                        subclear(1);
1445                        if(len < 0) continue;
1446                        count = count + len;
1447                }
1448                debug(300, "subtitle read peslen len=%d", len);
1449
1450                packlen = (((uint16_t)buf[4] << 8) | buf[5]) + 6;
1451                buf = realloc(buf, packlen);
1452
1453                while(status.subthreadaktion != STOP && status.subthreadaktion != PAUSE && count < packlen)
1454                {
1455#ifdef SIMULATE
1456                        len = TEMP_FAILURE_RETRY(read(fd, &buf[count], packlen - count));
1457#else
1458                        len = dvbread(dmxsubnode, &buf[count], 0, packlen - count, 100 * 1000);
1459#endif
1460                        subclear(1);
1461                        if(len <= 0) continue;
1462                        count = count + len;
1463
1464                        if(count == packlen)
1465                        {
1466                                debug(300, "decode subtile len=%d", count);
1467                                subpes(buf, count, subnode->id1, subnode->id2);
1468                        }
1469                }
1470        }
1471
1472        debug(300, "end subtitle thread");
1473       
1474        dmxclose(status.aktservice->dmxsubtitledev, -1);
1475        status.aktservice->dmxsubtitledev = NULL;
1476
1477        free(buf);
1478
1479#ifdef SIMULATE
1480        close(fd);
1481#endif
1482
1483        status.subthreadstatus = DEACTIVE;
1484        subfree(0);
1485        subfree(1);
1486
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        struct lastsubtitle* lsnode = NULL;
1593
1594        listbox->aktline = 1;
1595        listbox->aktpage = -1;
1596
1597        if(status.aktservice->channel != NULL)
1598        {
1599                m_lock(&status.subtitlemutex, 8);
1600                node = status.aktservice->channel->subtitle;
1601                while(node != NULL)
1602                {
1603                        tmp = addlistbox(subtitle, listbox, tmp, 1);
1604                        if(tmp != NULL)
1605                        {
1606                                changetext(tmp, _(node->name));
1607                                tmp->type = CHOICEBOX;
1608                                tmp->del = 1;
1609                                tmp->handle = (char*)node;
1610
1611                                if(node->pid == status.subthreadpid)
1612                                {
1613                                        changeinput(tmp, _("running"));
1614                                        treffer = 1;
1615                                }
1616                                else
1617                                        changeinput(tmp, "");
1618
1619                                if(treffer == 0) listbox->aktline++;
1620                        }
1621                        node = node->next;
1622                }       
1623                m_unlock(&status.subtitlemutex, 8);
1624        }
1625
1626        if(treffer == 0) listbox->aktline = 1;
1627
1628        drawscreen(subtitle, 0, 0);
1629        addscreenrc(subtitle, listbox);
1630
1631        while(1)
1632        {
1633                rcret = waitrc(subtitle, 0, 0);
1634       
1635                if(rcret == getrcconfigint("rcexit", NULL)) break;
1636                if(rcret == getrcconfigint("rcok", NULL))
1637                {
1638                        if(listbox->select != NULL && listbox->select->handle != NULL)
1639                        {
1640                                subtitlestop(1);
1641                                m_lock(&status.subtitlemutex, 8);
1642
1643                                if(status.autosubtitle == 1 && status.aktservice->channel != NULL)
1644                                {
1645                                        lsnode = getlastsubtitle(status.aktservice->channel->transponderid, status.aktservice->channel->serviceid);
1646                                        dellastsubtitle(lsnode);
1647                                        lsnode = NULL;
1648                                }
1649                               
1650                                if(checksubtitle(status.aktservice->channel, (struct subtitle*)listbox->select->handle) != NULL)
1651                                {
1652                                        if(((struct subtitle*)listbox->select->handle)->pid != status.subthreadpid)
1653                                        {
1654                                                clearscreen(subtitle);
1655                                                drawscreen(skin, 0, 0);
1656                                                if(subtitlestart((struct subtitle*)listbox->select->handle) == 0)
1657                                                        status.subthreadpid = ((struct subtitle*)listbox->select->handle)->pid;
1658
1659                                                if(status.autosubtitle == 1 && status.aktservice->channel != NULL)
1660                                                {
1661                                                        lsnode = getlastsubtitle(status.aktservice->channel->transponderid, status.aktservice->channel->serviceid);
1662                                                        if(lsnode == NULL)
1663                                                        {
1664                                                                char* tmpstr = NULL;
1665                                                                tmpstr = ostrcat(ollutoa(status.aktservice->channel->transponderid), "#", 1, 0);
1666                                                                tmpstr = ostrcat(tmpstr, oitoa(status.aktservice->channel->serviceid), 1, 1);
1667                                                                tmpstr = ostrcat(tmpstr, "#", 1, 0);
1668                                                                tmpstr = ostrcat(tmpstr, oitoa(((struct subtitle*)listbox->select->handle)->pid), 1, 1);
1669                                                                addlastsubtitle(tmpstr, 1, NULL);
1670                                                                free(tmpstr); tmpstr = NULL;
1671                                                        }
1672                                                        else
1673                                                                changelastsubtitle(lsnode, ((struct subtitle*)listbox->select->handle)->pid);
1674                                                }
1675
1676                                        }
1677                                        else
1678                                                status.subthreadpid = 0;
1679                                }
1680                                else
1681                                        status.subthreadpid = 0;
1682                                m_unlock(&status.subtitlemutex, 8);
1683                        }
1684                        break;
1685                }
1686        }
1687
1688        delmarkedscreennodes(subtitle, 1);
1689        delownerrc(subtitle);
1690        clearscreen(subtitle);
1691}
1692
1693struct subtitle* addsubtitle(struct channel* chnode, int subtype, char* langdesc, int pid, int type, int id1, int id2, struct subtitle* last)
1694{
1695        struct subtitle *newnode = NULL, *prev = NULL, *node = NULL;
1696        char *tmpstr = NULL, *tmpnr = NULL;
1697
1698        if(chnode == NULL)
1699        {
1700                err("NULL detect");
1701                return NULL;
1702        }
1703
1704        newnode = (struct subtitle*)malloc(sizeof(struct subtitle));   
1705        if(newnode == NULL)
1706        {
1707                err("no memory");
1708                return NULL;
1709        }
1710
1711        memset(newnode, 0, sizeof(struct subtitle));
1712
1713        newnode->pid = pid;
1714        newnode->type = type;
1715        newnode->id1 = id1;
1716        newnode->id2 = id2;
1717
1718        if(ostrcmp(langdesc, "und") == 0)
1719                tmpstr = ostrcat(tmpstr, _("undefined"), 1, 0);
1720        else
1721                tmpstr = ostrcat(tmpstr, _(langdesc), 1, 0);
1722        if(subtype == 1)
1723        {
1724                tmpstr = ostrcat(tmpstr, " (", 1, 0);
1725                tmpstr = ostrcat(tmpstr, "TXT Subtitle", 1, 0);
1726                tmpstr = ostrcat(tmpstr, " - ", 1, 0);
1727                tmpnr = oitoa(id2);
1728                tmpstr = ostrcat(tmpstr, tmpnr, 1, 1);
1729                tmpstr = ostrcat(tmpstr, ")", 1, 0);
1730        }
1731        if(subtype == 2)
1732        {
1733                tmpstr = ostrcat(tmpstr, " (", 1, 0);
1734                tmpstr = ostrcat(tmpstr, "DVB Subtitle", 1, 0);
1735                tmpstr = ostrcat(tmpstr, ")", 1, 0);
1736        }
1737        newnode->name = tmpstr;
1738
1739        m_lock(&status.subtitlemutex, 8);
1740        node = chnode->subtitle;
1741        if(last == NULL)
1742        {
1743                while(node != NULL)
1744                {
1745                        prev = node;
1746                        node = node->next;
1747                }
1748        }
1749        else
1750        {
1751                prev = last;
1752                node = last->next;
1753        }
1754
1755        if(prev == NULL)
1756                chnode->subtitle = newnode;
1757        else
1758                prev->next = newnode;
1759
1760        newnode->next = node;
1761
1762        m_unlock(&status.subtitlemutex, 8);
1763        return newnode;
1764}
1765
1766void freesubtitle(struct channel* chnode)
1767{
1768        struct subtitle *node = NULL, *prev = NULL;
1769
1770        if(chnode == NULL)
1771        {
1772                err("NULL detect");
1773                return;
1774        }
1775
1776        m_lock(&status.subtitlemutex, 8);
1777        node = chnode->subtitle;
1778        prev = chnode->subtitle;
1779
1780        while(node != NULL)
1781        {
1782                prev = node;
1783                node = node->next;
1784                chnode->subtitle = node;
1785
1786                free(prev->name);
1787                prev->name = NULL;
1788
1789                free(prev);
1790                prev = NULL;
1791
1792        }
1793        m_unlock(&status.subtitlemutex, 8);
1794}
1795
1796int subtitlestartlast()
1797{
1798        int ret = 1;
1799        struct subtitle* node = NULL;
1800        struct lastsubtitle* lsnode = NULL;
1801       
1802        if(status.aktservice->channel != NULL)
1803        {
1804                m_lock(&status.subtitlemutex, 8);
1805                node = status.aktservice->channel->subtitle;
1806                lsnode = getlastsubtitle(status.aktservice->channel->transponderid, status.aktservice->channel->serviceid);
1807               
1808                if(lsnode != NULL)
1809                {
1810                        while(node != NULL)
1811                        {
1812                                if(node->pid == lsnode->subtitlepid)
1813                                        break;
1814                                node = node->next;
1815                        }
1816               
1817                        if(node != NULL)
1818                        {
1819                                if(subtitlestart(node) == 0)
1820                                {
1821                                        status.subthreadpid = node->pid;
1822                                        ret = 0;
1823                                }
1824                        }
1825                }
1826                m_unlock(&status.subtitlemutex, 8);
1827        }
1828        return ret;
1829}
1830
1831void changelastsubtitle(struct lastsubtitle* lsnode, int pid)
1832{
1833        if(lsnode == NULL) return;
1834
1835        if(lsnode->subtitlepid != pid)
1836        {
1837                lsnode->subtitlepid = pid;
1838                status.writelastsubtitle = 1;
1839        }
1840}
1841
1842struct lastsubtitle* getlastsubtitle(uint64_t transponderid, int serviceid)
1843{
1844        struct lastsubtitle *node = lastsubtitle;
1845
1846        while(node != NULL)
1847        {
1848                if(node->transponderid == transponderid && node->serviceid == serviceid)
1849                        break;
1850                node = node->next;
1851        }
1852       
1853        return node;
1854}
1855
1856struct lastsubtitle* addlastsubtitle(char* line, int count, struct lastsubtitle* last)
1857{
1858        struct lastsubtitle *newnode = NULL, *prev = NULL, *node = lastsubtitle;
1859        int ret = 0;
1860
1861        if(line == NULL) return NULL;
1862
1863        newnode = (struct lastsubtitle*)calloc(1, sizeof(struct lastsubtitle));
1864        if(newnode == NULL)
1865        {
1866                err("no memory");
1867                return NULL;
1868        }
1869
1870        ret = sscanf(line, "%llu#%d#%"SCNu16"", &newnode->transponderid, &newnode->serviceid, &newnode->subtitlepid);
1871        if(ret != 3)
1872        {
1873                if(count > 0)
1874                {
1875                        err("lastsubtitle line %d not ok", count);
1876                }
1877                else
1878                {
1879                        err("add lastsubtitle");
1880                }
1881                free(newnode);
1882                return NULL;
1883        }
1884
1885        status.writelastsubtitle = 1;
1886       
1887        if(last == NULL)
1888        {
1889                while(node != NULL)
1890                {
1891                        prev = node;
1892                        node = node->next;
1893                }
1894        }
1895        else
1896        {
1897                prev = last;
1898                node = last->next;
1899        }
1900
1901        if(prev == NULL)
1902                lastsubtitle = newnode;
1903        else
1904                prev->next = newnode;
1905        newnode->next = node;
1906
1907        return newnode;
1908}
1909
1910int readlastsubtitle(const char* filename)
1911{
1912        FILE *fd = NULL;
1913        char *fileline = NULL;
1914        int linecount = 0, len = 0;
1915        struct lastsubtitle* last = NULL, *tmplast = NULL;
1916
1917        fileline = malloc(MINMALLOC);
1918        if(fileline == NULL)
1919        {
1920                err("no memory");
1921                return 1;
1922        }
1923
1924        fd = fopen(filename, "r");
1925        if(fd == NULL)
1926        {
1927                perr("can't open %s", filename);
1928                free(fileline);
1929                return 1;
1930        }
1931
1932        while(fgets(fileline, MINMALLOC, fd) != NULL)
1933        {
1934                if(fileline[0] == '#' || fileline[0] == '\n')
1935                        continue;
1936                len = strlen(fileline) - 1;
1937                if(len >= 0 && fileline[len] == '\n')
1938                        fileline[len] = '\0';
1939                len--;
1940                if(len >= 0 && fileline[len] == '\r')
1941                        fileline[len] = '\0';
1942
1943                linecount++;
1944               
1945                if(last == NULL) last = tmplast;
1946                last = addlastsubtitle(fileline, linecount, last);
1947                if(last != NULL) tmplast = last;
1948        }
1949
1950        status.writelastsubtitle = 0;
1951        free(fileline);
1952        fclose(fd);
1953        return 0;
1954}
1955
1956void dellastsubtitle(struct lastsubtitle* lsnode)
1957{
1958        struct lastsubtitle *node = lastsubtitle, *prev = lastsubtitle;
1959
1960        while(node != NULL)
1961        {
1962                if(node == lsnode)
1963                {
1964                        status.writelastsubtitle = 1;
1965                        if(node == lastsubtitle)
1966                                lastsubtitle = node->next;
1967                        else
1968                                prev->next = node->next;
1969
1970                        free(node);
1971                        node = NULL;
1972                        break;
1973                }
1974
1975                prev = node;
1976                node = node->next;
1977        }
1978}
1979
1980void freelastsubtitle()
1981{
1982        struct lastsubtitle *node = lastsubtitle, *prev = lastsubtitle;
1983
1984        while(node != NULL)
1985        {
1986                prev = node;
1987                node = node->next;
1988                if(prev != NULL)
1989                        dellastsubtitle(prev);
1990        }
1991}
1992
1993int writelastsubtitle(const char *filename)
1994{
1995        FILE *fd = NULL;
1996        struct lastsubtitle *node = lastsubtitle;
1997        int ret = 0;
1998
1999        fd = fopen(filename, "w");
2000        if(fd == NULL)
2001        {
2002                perr("can't open %s", filename);
2003                return 1;
2004        }
2005
2006        while(node != NULL)
2007        {
2008                ret = fprintf(fd, "%llu#%d#%d\n", node->transponderid, node->serviceid, node->subtitlepid);
2009                if(ret < 0)
2010                {
2011                        perr("writting file %s", filename);
2012                }
2013                node = node->next;
2014        }
2015
2016        fclose(fd);
2017        return 0;
2018}
2019
2020#endif
Note: See TracBrowser for help on using the repository browser.