source: titan/titan/subtitle.h @ 32089

Last change on this file since 32089 was 24617, checked in by obi, 10 years ago

fix build

File size: 43.5 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
1490//flag 0: start normal
1491//flag 1: start in pause
1492int subtitlestart(struct subtitle* node, int flag)
1493{
1494        int ret;
1495
1496        if(status.subthreadstatus != DEACTIVE)
1497        {
1498                err("subtitle thread in use");
1499                return 1;
1500        }
1501
1502        if(flag == 0)
1503                status.subthreadaktion = START;
1504        else
1505                status.subthreadaktion = PAUSE;
1506       
1507        pthread_attr_destroy(&status.subthreadattr);
1508        pthread_attr_init(&status.subthreadattr);
1509        pthread_attr_setstacksize(&status.subthreadattr, 50000);
1510        pthread_attr_setdetachstate(&status.subthreadattr, PTHREAD_CREATE_JOINABLE);
1511        ret = pthread_create(&status.subthread, &status.subthreadattr, subthreadfunc, node);
1512        if(ret)
1513        {
1514                err("create subtitle thread");
1515                return 1;
1516        }
1517
1518        return 0;
1519}
1520
1521int subtitlepause(int flag)
1522{
1523        int i = 0;
1524
1525        if(flag == 0)
1526        {
1527                if(status.subthreadstatus == INPAUSE)
1528                        status.subthreadaktion = START;
1529        }
1530        else if(status.subthreadstatus == ACTIVE)
1531        {
1532                status.subthreadaktion = PAUSE;
1533                while(status.subthreadstatus != INPAUSE)
1534                {
1535                        usleep(100000);
1536                        i++; if(i > 20) break;
1537                }
1538                if(i > 20)
1539                        err("detect hanging subthread");
1540                subclear(0);
1541        }
1542
1543        return 0;
1544}
1545
1546int subtitlestop(int flag)
1547{
1548        void* threadstatus;
1549        int i = 0;
1550
1551        status.subthreadaktion = STOP;
1552        while(status.subthreadstatus != DEACTIVE)
1553        {
1554                usleep(100000);
1555                i++; if(i > 20) break;
1556        }
1557        subclear(0);
1558       
1559        if(i > 20)
1560        {
1561                err("detect hanging subthread");
1562        }
1563        else if(status.subthread != 0)
1564                pthread_join(status.subthread, &threadstatus);
1565
1566        status.subthread = 0;
1567        pthread_attr_destroy(&status.subthreadattr);
1568        if(flag == 0)
1569        {
1570                status.subthreadpid = 0;
1571                status.subthreadid1 = 0;
1572                status.subthreadid2 = 0;
1573        }
1574
1575        return 0;
1576}
1577
1578struct subtitle* checksubtitle(struct channel* chnode, struct subtitle* strack)
1579{
1580        struct subtitle* node = NULL;
1581
1582        if(chnode != NULL)
1583        {
1584                node = chnode->subtitle;
1585                while(node != NULL)
1586                {
1587                        if(node == strack)
1588                                return node;
1589                        node = node->next;
1590                }
1591        }
1592        return NULL;
1593}
1594
1595void screensubtitle()
1596{
1597        int rcret = 0, treffer = 0;
1598        struct skin* subtitle = getscreen("subtitle");
1599        struct skin* listbox = getscreennode(subtitle, "listbox");
1600        struct skin* tmp = NULL;
1601        struct subtitle* node = NULL;
1602        struct lastsubtitle* lsnode = NULL;
1603
1604        listbox->aktline = 1;
1605        listbox->aktpage = -1;
1606
1607        if(status.aktservice->channel != NULL)
1608        {
1609                m_lock(&status.subtitlemutex, 8);
1610                node = status.aktservice->channel->subtitle;
1611                while(node != NULL)
1612                {
1613                        tmp = addlistbox(subtitle, listbox, tmp, 1);
1614                        if(tmp != NULL)
1615                        {
1616                                changetext(tmp, _(node->name));
1617                                tmp->type = CHOICEBOX;
1618                                tmp->del = 1;
1619                                tmp->handle = (char*)node;
1620
1621                                if(node->pid == status.subthreadpid)
1622                                {
1623                                        if(node->subtype == 2 || (node->subtype == 1 && node->id1 == status.subthreadid1 && node->id2 == status.subthreadid2))
1624                                        changeinput(tmp, _("running"));
1625                                        treffer = 1;
1626                                }
1627                                else
1628                                        changeinput(tmp, "");
1629
1630                                if(treffer == 0) listbox->aktline++;
1631                        }
1632                        node = node->next;
1633                }       
1634                m_unlock(&status.subtitlemutex, 8);
1635        }
1636
1637        if(treffer == 0) listbox->aktline = 1;
1638
1639        drawscreen(subtitle, 0, 0);
1640        addscreenrc(subtitle, listbox);
1641
1642        while(1)
1643        {
1644                rcret = waitrc(subtitle, 0, 0);
1645       
1646                if(rcret == getrcconfigint("rcexit", NULL)) break;
1647                if(rcret == getrcconfigint("rcok", NULL))
1648                {
1649                        if(listbox->select != NULL && listbox->select->handle != NULL)
1650                        {
1651                                subtitlestop(1);
1652                                m_lock(&status.subtitlemutex, 8);
1653
1654                                if(status.autosubtitle == 1 && status.aktservice->channel != NULL)
1655                                {
1656                                        lsnode = getlastsubtitle(status.aktservice->channel->transponderid, status.aktservice->channel->serviceid);
1657                                        dellastsubtitle(lsnode);
1658                                        lsnode = NULL;
1659                                }
1660                               
1661                                if(checksubtitle(status.aktservice->channel, (struct subtitle*)listbox->select->handle) != NULL)
1662                                {
1663                                        if(((struct subtitle*)listbox->select->handle)->pid != status.subthreadpid || ((struct subtitle*)listbox->select->handle)->id1 != status.subthreadid1 || ((struct subtitle*)listbox->select->handle)->id2 != status.subthreadid2)
1664                                        {
1665                                                clearscreen(subtitle);
1666                                                drawscreen(skin, 0, 0);
1667                                                if(subtitlestart((struct subtitle*)listbox->select->handle, 0) == 0)
1668                                                {
1669                                                        status.subthreadpid = ((struct subtitle*)listbox->select->handle)->pid;
1670                                                        status.subthreadid1 = ((struct subtitle*)listbox->select->handle)->id1;
1671                                                        status.subthreadid2 = ((struct subtitle*)listbox->select->handle)->id2;
1672                                                }
1673
1674                                                if(status.autosubtitle == 1 && status.aktservice->channel != NULL)
1675                                                {
1676                                                        lsnode = getlastsubtitle(status.aktservice->channel->transponderid, status.aktservice->channel->serviceid);
1677                                                        if(lsnode == NULL)
1678                                                        {
1679                                                                char* tmpstr = NULL;
1680                                                                tmpstr = ostrcat(ollutoa(status.aktservice->channel->transponderid), "#", 1, 0);
1681                                                                tmpstr = ostrcat(tmpstr, oitoa(status.aktservice->channel->serviceid), 1, 1);
1682                                                                tmpstr = ostrcat(tmpstr, "#", 1, 0);
1683                                                                tmpstr = ostrcat(tmpstr, oitoa(((struct subtitle*)listbox->select->handle)->pid), 1, 1);
1684                                                                tmpstr = ostrcat(tmpstr, "#", 1, 0);
1685                                                                tmpstr = ostrcat(tmpstr, oitoa(((struct subtitle*)listbox->select->handle)->id2), 1, 1);
1686                                                                addlastsubtitle(tmpstr, 1, NULL);
1687                                                                free(tmpstr); tmpstr = NULL;
1688                                                        }
1689                                                        else
1690                                                                changelastsubtitle(lsnode, ((struct subtitle*)listbox->select->handle)->pid, ((struct subtitle*)listbox->select->handle)->id1, ((struct subtitle*)listbox->select->handle)->id2);
1691                                                }
1692
1693                                        }
1694                                        else
1695                                        {
1696                                                status.subthreadpid = 0;
1697                                                status.subthreadid1 = 0;
1698                                                status.subthreadid2 = 0;
1699                                        }
1700                                }
1701                                else
1702                                {
1703                                        status.subthreadpid = 0;
1704                                        status.subthreadid1 = 0;
1705                                        status.subthreadid2 = 0;
1706                                }
1707                                m_unlock(&status.subtitlemutex, 8);
1708                        }
1709                        break;
1710                }
1711        }
1712
1713        delmarkedscreennodes(subtitle, 1);
1714        delownerrc(subtitle);
1715        clearscreen(subtitle);
1716}
1717
1718struct subtitle* addsubtitle(struct channel* chnode, int subtype, char* langdesc, int pid, int type, int id1, int id2, struct subtitle* last)
1719{
1720        struct subtitle *newnode = NULL, *prev = NULL, *node = NULL;
1721        char *tmpstr = NULL, *tmpnr = NULL;
1722
1723        if(chnode == NULL)
1724        {
1725                err("NULL detect");
1726                return NULL;
1727        }
1728
1729        newnode = (struct subtitle*)malloc(sizeof(struct subtitle));   
1730        if(newnode == NULL)
1731        {
1732                err("no memory");
1733                return NULL;
1734        }
1735
1736        memset(newnode, 0, sizeof(struct subtitle));
1737
1738  newnode->subtype = subtype;
1739        newnode->pid = pid;
1740        newnode->type = type;
1741        newnode->id1 = id1;
1742        newnode->id2 = id2;
1743
1744        if(ostrcmp(langdesc, "und") == 0)
1745                tmpstr = ostrcat(tmpstr, _("undefined"), 1, 0);
1746        else
1747                tmpstr = ostrcat(tmpstr, _(langdesc), 1, 0);
1748        if(subtype == 1)
1749        {
1750                tmpstr = ostrcat(tmpstr, " (", 1, 0);
1751                tmpstr = ostrcat(tmpstr, "TXT Subtitle", 1, 0);
1752                tmpstr = ostrcat(tmpstr, " - ", 1, 0);
1753                tmpnr = oitoa(id2);
1754                tmpstr = ostrcat(tmpstr, tmpnr, 1, 1);
1755                tmpstr = ostrcat(tmpstr, ")", 1, 0);
1756        }
1757        if(subtype == 2)
1758        {
1759                tmpstr = ostrcat(tmpstr, " (", 1, 0);
1760                tmpstr = ostrcat(tmpstr, "DVB Subtitle", 1, 0);
1761                tmpstr = ostrcat(tmpstr, ")", 1, 0);
1762        }
1763        newnode->name = tmpstr;
1764
1765        m_lock(&status.subtitlemutex, 8);
1766        node = chnode->subtitle;
1767        if(last == NULL)
1768        {
1769                while(node != NULL)
1770                {
1771                        prev = node;
1772                        node = node->next;
1773                }
1774        }
1775        else
1776        {
1777                prev = last;
1778                node = last->next;
1779        }
1780
1781        if(prev == NULL)
1782                chnode->subtitle = newnode;
1783        else
1784                prev->next = newnode;
1785
1786        newnode->next = node;
1787
1788        m_unlock(&status.subtitlemutex, 8);
1789        return newnode;
1790}
1791
1792void freesubtitle(struct channel* chnode)
1793{
1794        struct subtitle *node = NULL, *prev = NULL;
1795
1796        if(chnode == NULL)
1797        {
1798                err("NULL detect");
1799                return;
1800        }
1801
1802        m_lock(&status.subtitlemutex, 8);
1803        node = chnode->subtitle;
1804        prev = chnode->subtitle;
1805
1806        while(node != NULL)
1807        {
1808                prev = node;
1809                node = node->next;
1810                chnode->subtitle = node;
1811
1812                free(prev->name);
1813                prev->name = NULL;
1814
1815                free(prev);
1816                prev = NULL;
1817
1818        }
1819        m_unlock(&status.subtitlemutex, 8);
1820}
1821
1822int subtitlestartlast()
1823{
1824        int ret = 1;
1825        struct subtitle* node = NULL;
1826        struct lastsubtitle* lsnode = NULL;
1827       
1828        if(status.aktservice->channel != NULL)
1829        {
1830                m_lock(&status.subtitlemutex, 8);
1831                node = status.aktservice->channel->subtitle;
1832                lsnode = getlastsubtitle(status.aktservice->channel->transponderid, status.aktservice->channel->serviceid);
1833               
1834                if(lsnode != NULL)
1835                {
1836                        while(node != NULL)
1837                        {
1838                                if(node->pid == lsnode->subtitlepid && node->id1 == lsnode->subtitleid1 && node->id2 == lsnode->subtitleid2)
1839                                        break;
1840                                node = node->next;
1841                        }
1842               
1843                        if(node != NULL)
1844                        {
1845                                if(subtitlestart(node, 1) == 0)
1846                                {
1847                                        status.subthreadpid = node->pid;
1848                                        status.subthreadid1 = node->id1;
1849                                        status.subthreadid2 = node->id2;
1850                                        ret = 0;
1851                                }
1852                        }
1853                }
1854                m_unlock(&status.subtitlemutex, 8);
1855        }
1856        return ret;
1857}
1858
1859void changelastsubtitle(struct lastsubtitle* lsnode, int pid, int id1, int id2)
1860{
1861        if(lsnode == NULL) return;
1862
1863        if(lsnode->subtitlepid != pid || lsnode->subtitleid1 != id2 || lsnode->subtitleid2 != id2)
1864        {
1865                lsnode->subtitlepid = pid;
1866                lsnode->subtitleid1 = id1;
1867                lsnode->subtitleid2 = id2;
1868                status.writelastsubtitle = 1;
1869        }
1870}
1871
1872struct lastsubtitle* getlastsubtitle(uint64_t transponderid, int serviceid)
1873{
1874        struct lastsubtitle *node = lastsubtitle;
1875
1876        while(node != NULL)
1877        {
1878                if(node->transponderid == transponderid && node->serviceid == serviceid)
1879                        break;
1880                node = node->next;
1881        }
1882       
1883        return node;
1884}
1885
1886struct lastsubtitle* addlastsubtitle(char* line, int count, struct lastsubtitle* last)
1887{
1888        struct lastsubtitle *newnode = NULL, *prev = NULL, *node = lastsubtitle;
1889        int ret = 0;
1890
1891        if(line == NULL) return NULL;
1892
1893        newnode = (struct lastsubtitle*)calloc(1, sizeof(struct lastsubtitle));
1894        if(newnode == NULL)
1895        {
1896                err("no memory");
1897                return NULL;
1898        }
1899
1900        ret = sscanf(line, "%llu#%d#%"SCNu16"#%"SCNu16"#%"SCNu16"", &newnode->transponderid, &newnode->serviceid, &newnode->subtitlepid, &newnode->subtitleid1, &newnode->subtitleid2);
1901        if(ret != 5)
1902        {
1903                if(count > 0)
1904                {
1905                        err("lastsubtitle line %d not ok", count);
1906                }
1907                else
1908                {
1909                        err("add lastsubtitle");
1910                }
1911                free(newnode);
1912                return NULL;
1913        }
1914
1915        status.writelastsubtitle = 1;
1916       
1917        if(last == NULL)
1918        {
1919                while(node != NULL)
1920                {
1921                        prev = node;
1922                        node = node->next;
1923                }
1924        }
1925        else
1926        {
1927                prev = last;
1928                node = last->next;
1929        }
1930
1931        if(prev == NULL)
1932                lastsubtitle = newnode;
1933        else
1934                prev->next = newnode;
1935        newnode->next = node;
1936
1937        return newnode;
1938}
1939
1940int readlastsubtitle(const char* filename)
1941{
1942        FILE *fd = NULL;
1943        char *fileline = NULL;
1944        int linecount = 0, len = 0;
1945        struct lastsubtitle* last = NULL, *tmplast = NULL;
1946
1947        fileline = malloc(MINMALLOC);
1948        if(fileline == NULL)
1949        {
1950                err("no memory");
1951                return 1;
1952        }
1953
1954        fd = fopen(filename, "r");
1955        if(fd == NULL)
1956        {
1957                perr("can't open %s", filename);
1958                free(fileline);
1959                return 1;
1960        }
1961
1962        while(fgets(fileline, MINMALLOC, fd) != NULL)
1963        {
1964                if(fileline[0] == '#' || fileline[0] == '\n')
1965                        continue;
1966                len = strlen(fileline) - 1;
1967                if(len >= 0 && fileline[len] == '\n')
1968                        fileline[len] = '\0';
1969                len--;
1970                if(len >= 0 && fileline[len] == '\r')
1971                        fileline[len] = '\0';
1972
1973                linecount++;
1974               
1975                if(last == NULL) last = tmplast;
1976                last = addlastsubtitle(fileline, linecount, last);
1977                if(last != NULL) tmplast = last;
1978        }
1979
1980        status.writelastsubtitle = 0;
1981        free(fileline);
1982        fclose(fd);
1983        return 0;
1984}
1985
1986void dellastsubtitle(struct lastsubtitle* lsnode)
1987{
1988        struct lastsubtitle *node = lastsubtitle, *prev = lastsubtitle;
1989
1990        while(node != NULL)
1991        {
1992                if(node == lsnode)
1993                {
1994                        status.writelastsubtitle = 1;
1995                        if(node == lastsubtitle)
1996                                lastsubtitle = node->next;
1997                        else
1998                                prev->next = node->next;
1999
2000                        free(node);
2001                        node = NULL;
2002                        break;
2003                }
2004
2005                prev = node;
2006                node = node->next;
2007        }
2008}
2009
2010void freelastsubtitle()
2011{
2012        struct lastsubtitle *node = lastsubtitle, *prev = lastsubtitle;
2013
2014        while(node != NULL)
2015        {
2016                prev = node;
2017                node = node->next;
2018                if(prev != NULL)
2019                        dellastsubtitle(prev);
2020        }
2021}
2022
2023int writelastsubtitle(const char *filename)
2024{
2025        FILE *fd = NULL;
2026        struct lastsubtitle *node = lastsubtitle;
2027        int ret = 0;
2028
2029        fd = fopen(filename, "w");
2030        if(fd == NULL)
2031        {
2032                perr("can't open %s", filename);
2033                return 1;
2034        }
2035
2036        while(node != NULL)
2037        {
2038                ret = fprintf(fd, "%llu#%d#%d#%d#%d\n", node->transponderid, node->serviceid, node->subtitlepid, node->subtitleid1, node->subtitleid2);
2039                if(ret < 0)
2040                {
2041                        perr("writting file %s", filename);
2042                }
2043                node = node->next;
2044        }
2045
2046        fclose(fd);
2047        return 0;
2048}
2049
2050#endif
Note: See TracBrowser for help on using the repository browser.