trunk 20080912
[gitenigma.git] / lib / dvb / subtitle.cpp
blob543c1d07617d5184d8a01d3bb2d214f34e1743dc
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <fcntl.h>
4 #include <memory.h>
5 #include <time.h>
7 #include <asm/types.h>
8 #include <lib/dvb/subtitle.h>
9 #include <lib/base/eerror.h>
10 #include <lib/gdi/fb.h>
12 void bitstream_init(struct bitstream *bit, void *buffer, int size)
14 bit->data = (__u8*) buffer;
15 bit->size = size;
16 bit->avail = 8;
17 bit->consumed = 0;
20 int bitstream_get(struct bitstream *bit)
22 int val;
23 bit->avail -= bit->size;
24 val = ((*bit->data) >> bit->avail) & ((1<<bit->size) - 1);
25 if (!bit->avail)
27 bit->data++;
28 bit->consumed++;
29 bit->avail = 8;
31 return val;
34 void subtitle_process_line(struct subtitle_ctx *sub, struct subtitle_page *page, int object_id, int line, __u8 *data, int len)
36 struct subtitle_region *region = page->regions;
37 // eDebug("line for %d:%d", page->page_id, object_id);
38 while (region)
40 struct subtitle_region_object *object = region->region_objects;
41 while (object)
43 if (object->object_id == object_id)
45 int x = object->object_horizontal_position;
46 int y = object->object_vertical_position + line;
47 if (x + len > region->region_width)
49 //eDebug("[SUB] !!!! XCLIP %d + %d > %d", x, len, region->region_width);
50 len = region->region_width - x;
52 if (len < 0)
53 break;
54 if (y >= region->region_height)
56 //eDebug("[SUB] !!!! YCLIP %d >= %d", y, region->region_height);
57 break;
59 // //eDebug("inserting %d bytes (into region %d)", len, region->region_id);
60 memcpy(region->region_buffer + region->region_width * y + x, data, len);
62 object = object->next;
64 region = region->next;
68 static int map_2_to_4_bit_table[4] = { 0, 8, 7, 15 };
70 int subtitle_process_pixel_data(struct subtitle_ctx *sub, struct subtitle_page *page, int object_id, int *linenr, int *linep, __u8 *data)
72 int data_type = *data++;
73 static __u8 line[720];
74 struct bitstream bit;
75 bit.size=0;
76 switch (data_type)
78 case 0x10: // 2bit pixel data
79 bitstream_init(&bit, data, 2);
80 while (1)
82 int len=0, col=0;
83 int code = bitstream_get(&bit);
84 if (code)
86 col = code;
87 len = 1;
88 } else
90 code = bitstream_get(&bit);
91 if (!code)
93 code = bitstream_get(&bit);
94 if (code == 1)
96 col = 0;
97 len = 2;
98 } else if (code == 2)
100 len = bitstream_get(&bit) << 2;
101 len |= bitstream_get(&bit);
102 len += 12;
103 col = bitstream_get(&bit);
104 } else if (code == 3)
106 len = bitstream_get(&bit) << 6;
107 len |= bitstream_get(&bit) << 4;
108 len |= bitstream_get(&bit) << 2;
109 len |= bitstream_get(&bit);
110 len += 29;
111 col = bitstream_get(&bit);
112 } else
113 break;
114 } else if (code==1)
116 col = 0;
117 len = 1;
118 } else if (code&2)
120 if (code&1)
121 len = 3 + 4 + bitstream_get(&bit);
122 else
123 len = 3 + bitstream_get(&bit);
124 col = bitstream_get(&bit);
127 col = map_2_to_4_bit_table[col];
128 while (len && ((*linep) < 720))
130 line[(*linep)++] = col | 0xF0;
131 len--;
134 while (bit.avail != 8)
135 bitstream_get(&bit);
136 return bit.consumed + 1;
137 case 0x11: // 4bit pixel data
138 bitstream_init(&bit, data, 4);
139 while (1)
141 int len=0, col=0;
142 int code = bitstream_get(&bit);
143 if (code)
145 col = code;
146 len = 1;
147 } else
149 code = bitstream_get(&bit);
150 if (!code)
151 break;
152 else if (code == 0xC)
154 col = 0;
155 len = 1;
156 } else if (code == 0xD)
158 col = 0;
159 len = 2;
160 } else if (code < 8)
162 col = 0;
163 len = (code & 7) + 2;
164 } else if ((code & 0xC) == 0x8)
166 col = bitstream_get(&bit);
167 len = (code & 3) + 4;
168 } else if (code == 0xE)
170 len = bitstream_get(&bit) + 9;
171 col = bitstream_get(&bit);
172 } else if (code == 0xF)
174 len = bitstream_get(&bit) << 4;
175 len |= bitstream_get(&bit);
176 len += 25;
177 col = bitstream_get(&bit);
180 while (len && ((*linep) < 720))
182 line[(*linep)++] = col | 0xF0;
183 len--;
186 while (bit.avail != 8)
187 bitstream_get(&bit);
188 return bit.consumed + 1;
189 case 0x12: // 8bit pixel data
190 bitstream_init(&bit, data, 8);
191 while(1)
193 int len=0, col=0;
194 int code = bitstream_get(&bit);
195 if (code)
197 col = code;
198 len = 1;
199 } else
201 code = bitstream_get(&bit);
202 if ((code & 0x80) == 0x80)
204 len = code&0x7F;
205 col = bitstream_get(&bit);
206 } else if (code&0x7F)
208 len = code&0x7F;
209 col = 0;
210 } else
211 break;
213 col >>= 4; // 8 -> 4 bit reduction
214 while (len && ((*linep) < 720))
216 line[(*linep)++] = col | 0xF0;
217 len--;
220 return bit.consumed + 1;
221 case 0x20: // 2 -> 4bit map table
222 bitstream_init(&bit, data, 4);
223 for ( int i=0; i < 4; ++i )
224 map_2_to_4_bit_table[i] = bitstream_get(&bit);
225 break;
226 case 0x21: // ignore 2 -> 8bit map table
227 bitstream_init(&bit, data, 8);
228 for ( int i=0; i < 4; ++i )
229 bitstream_get(&bit);
230 break;
231 case 0x22: // ignore 4 -> 8bit map table
232 bitstream_init(&bit, data, 8);
233 for ( int i=0; i < 16; ++i )
234 bitstream_get(&bit);
235 break;
236 case 0xF0:
237 // recreate default map
238 map_2_to_4_bit_table[0] = 0;
239 map_2_to_4_bit_table[1] = 8;
240 map_2_to_4_bit_table[2] = 7;
241 map_2_to_4_bit_table[3] = 15;
242 subtitle_process_line(sub, page, object_id, *linenr, line, *linep);
243 /* {
244 int i;
245 for (i=0; i<720; ++i)
246 //eDebugNoNewLine("%d ", line[i]);
247 //eDebug("");
248 } */
249 (*linenr)+=2; // interlaced
250 *linep = 0;
251 // //eDebug("[SUB] EOL");
252 return 1;
253 default:
254 eDebug("subtitle_process_pixel_data: invalid data_type %02x", data_type);
255 return -1;
257 return 0;
260 int subtitle_process_segment(struct subtitle_ctx *sub, __u8 *segment)
262 int segment_type, page_id, segment_length, processed_length;
263 if (*segment++ != 0x0F)
265 eDebug("out of sync.");
266 return -1;
268 segment_type = *segment++;
269 page_id = *segment++ << 8;
270 page_id |= *segment++;
271 segment_length = *segment++ << 8;
272 segment_length |= *segment++;
273 if (segment_type == 0xFF)
274 return segment_length + 6;
275 // //eDebug("have %d bytes of segment data", segment_length);
277 // //eDebug("page_id %d, segtype %02x", page_id, segment_type);
279 struct subtitle_page *page, **ppage;
281 page = sub->pages; ppage = &sub->pages;
283 while (page)
285 if (page->page_id == page_id)
286 break;
287 ppage = &page->next;
288 page = page->next;
291 processed_length = 0;
293 switch (segment_type)
295 case 0x10: // page composition segment
297 int page_time_out = *segment++; processed_length++;
298 int page_version_number = *segment >> 4;
299 int page_state = (*segment >> 2) & 0x3;
300 //eDebug("pcs with %d bytes data (%d:%d:%d)", segment_length, page_id, page_version_number, page_state);
301 segment++;
302 processed_length++;
304 //eDebug("page time out: %d", page_time_out);
305 //eDebug("page_version_number: %d" ,page_version_number);
306 //eDebug("page_state: %d", page_state);
308 if (!page)
310 //eDebug("page not found");
311 page = new subtitle_page;
312 page->page_regions = 0;
313 page->regions = 0;
314 page->page_id = page_id;
315 page->cluts = 0;
316 page->next = 0;
317 *ppage = page;
318 } else
320 if (page->pcs_size != segment_length)
321 page->page_version_number = -1;
322 // if no update, just skip this data.
323 if (page->page_version_number == page_version_number)
325 eDebug("skip data... ");
326 break;
330 // eDebug("page updated: old: %d, new: %d", page->page_version_number, page_version_number);
331 // when acquisition point or mode change: remove all displayed pages.
332 if ((page_state == 1) || (page_state == 2))
334 while (page->page_regions)
336 struct subtitle_page_region *p = page->page_regions->next;
337 delete page->page_regions;
338 page->page_regions = p;
340 while (page->regions)
342 struct subtitle_region *p = page->regions->next;
343 while(page->regions->region_objects)
345 subtitle_region_object *ob = page->regions->region_objects->next;
346 delete page->regions->region_objects;
347 page->regions->region_objects = ob;
349 delete [] page->regions->region_buffer;
350 delete page->regions;
351 page->regions = p;
355 // eDebug("new page.. (%d)", page_state);
357 page->page_time_out = page_time_out;
359 page->page_version_number = page_version_number;
362 only display regions mentioned in this segment
363 => remove all previous region references from this page
364 (at least if I understand ETSI EN 300 743 V1.2.1 (2002-10) Chapter 5.1.3 correctly)
366 while (page->page_regions)
368 struct subtitle_page_region *p = page->page_regions->next;
369 delete page->page_regions;
370 page->page_regions = p;
373 struct subtitle_page_region **r = &page->page_regions;
375 //eDebug("%d / %d data left", processed_length, segment_length);
377 // go to last entry
378 while (*r)
379 r = &(*r)->next;
381 if (processed_length == segment_length && !page->page_regions)
383 // eDebug("no regions in page.. clear screen!!");
384 if (sub->screen_enabled)
385 subtitle_redraw_all(sub);
388 while (processed_length < segment_length)
390 struct subtitle_page_region *pr;
392 // append new entry to list
393 pr = new subtitle_page_region;
394 pr->next = 0;
395 *r = pr;
396 r = &pr->next;
398 pr->region_id = *segment++; processed_length++;
399 segment++; processed_length++;
401 pr->region_horizontal_address = *segment++ << 8;
402 pr->region_horizontal_address |= *segment++;
403 processed_length += 2;
405 pr->region_vertical_address = *segment++ << 8;
406 pr->region_vertical_address |= *segment++;
407 processed_length += 2;
409 //eDebug("appended active region");
412 if (processed_length != segment_length)
413 eDebug("%d != %d", processed_length, segment_length);
414 break;
416 case 0x11: // region composition segment
418 int region_id = *segment++; processed_length++;
419 int region_version_number = *segment >> 4;
420 int region_fill_flag = (*segment >> 3) & 1;
421 segment++; processed_length++;
423 // if we didn't yet received the pcs for this page, drop the region
424 if (!page)
426 eDebug("ignoring region %x, since page %02x doesn't yet exist.", region_id, page_id);
427 break;
430 struct subtitle_region *region, **pregion;
432 region = page->regions; pregion = &page->regions;
434 while (region)
436 fflush(stdout);
437 if (region->region_id == region_id)
438 break;
439 pregion = &region->next;
440 region = region->next;
443 if (!region)
445 *pregion = region = new subtitle_region;
446 region->next = 0;
448 else if (region->region_version_number != region_version_number)
450 struct subtitle_region_object *objects = region->region_objects;
451 while (objects)
453 struct subtitle_region_object *n = objects->next;
454 delete objects;
455 objects = n;
457 delete [] region->region_buffer;
459 else
460 break;
462 //eDebug("region %d:%d update", page_id, region_id);
464 region->region_id = region_id;
465 region->region_version_number = region_version_number;
467 region->region_width = *segment++ << 8;
468 region->region_width |= *segment++;
469 processed_length += 2;
471 region->region_height = *segment++ << 8;
472 region->region_height |= *segment++;
473 processed_length += 2;
475 region->region_buffer = new __u8[region->region_height * region->region_width];
477 int region_level_of_compatibility, region_depth;
479 region_level_of_compatibility = (*segment >> 5) & 7;
480 region_depth = (*segment++ >> 2) & 7;
481 processed_length++;
483 int CLUT_id;
484 CLUT_id = *segment++; processed_length++;
486 region->clut_id = CLUT_id;
488 int region_8bit_pixel_code, region_4bit_pixel_code, region_2bit_pixel_code;
489 region_8bit_pixel_code = *segment++; processed_length++;
490 region_4bit_pixel_code = *segment >> 4;
491 region_2bit_pixel_code = (*segment++ >> 2) & 3;
492 processed_length++;
494 if (!region_fill_flag)
496 region_2bit_pixel_code = region_4bit_pixel_code = region_8bit_pixel_code = 0;
497 region_fill_flag = 1;
500 if (region_fill_flag)
502 if (region_depth == 1)
503 memset(region->region_buffer, region_2bit_pixel_code, region->region_height * region->region_width);
504 else if (region_depth == 2)
505 memset(region->region_buffer, region_4bit_pixel_code, region->region_height * region->region_width);
506 else if (region_depth == 3)
507 memset(region->region_buffer, region_8bit_pixel_code, region->region_height * region->region_width);
508 else
509 eDebug("!!!! invalid depth");
512 //eDebug("region %02x, version %d, %dx%d", region->region_id, region->region_version_number, region->region_width, region->region_height);
514 region->region_objects = 0;
515 struct subtitle_region_object **pobject = &region->region_objects;
517 while (processed_length < segment_length)
520 struct subtitle_region_object *object;
522 object = new subtitle_region_object;
524 *pobject = object;
525 object->next = 0;
526 pobject = &object->next;
528 object->object_id = *segment++ << 8;
529 object->object_id |= *segment++; processed_length += 2;
531 object->object_type = *segment >> 6;
532 object->object_provider_flag = (*segment >> 4) & 3;
533 object->object_horizontal_position = (*segment++ & 0xF) << 8;
534 object->object_horizontal_position |= *segment++;
535 processed_length += 2;
537 object->object_vertical_position = *segment++ << 8;
538 object->object_vertical_position |= *segment++ ;
539 processed_length += 2;
541 if ((object->object_type == 1) || (object->object_type == 2))
543 object->foreground_pixel_value = *segment++;
544 object->background_pixel_value = *segment++;
545 processed_length += 2;
549 if (processed_length != segment_length)
550 eDebug("too less data! (%d < %d)", segment_length, processed_length);
552 break;
554 case 0x12: // CLUT definition segment
556 int CLUT_id, CLUT_version_number;
557 struct subtitle_clut *clut, **pclut;
559 if (!page)
560 break;
562 //eDebug("CLUT: %02x", *segment);
563 CLUT_id = *segment++;
565 CLUT_version_number = *segment++ >> 4;
566 processed_length += 2;
568 //eDebug("page %d, CLUT %02x, version %d", page->page_id, CLUT_id, CLUT_version_number);
570 clut = page->cluts; pclut = &page->cluts;
572 while (clut)
574 if (clut->clut_id == CLUT_id)
575 break;
576 pclut = &clut->next;
577 clut = clut->next;
580 if (!clut)
582 *pclut = clut = new subtitle_clut;
583 clut->next = 0;
584 } else if (clut->CLUT_version_number == CLUT_version_number)
585 break;
587 clut->clut_id = CLUT_id;
589 /* invalidate CLUT if updated. */
590 if ((sub->current_clut_page_id == page_id) && (sub->current_clut_id == CLUT_id))
591 sub->current_clut_id = -1;
593 clut->size = 0;
595 //eDebug("new clut");
596 while (processed_length < segment_length)
598 int CLUT_entry_id, entry_CLUT_flag, full_range;
599 int v_Y, v_Cr, v_Cb, v_T;
601 CLUT_entry_id = *segment++;
602 entry_CLUT_flag = *segment >> 5;
603 if (!(entry_CLUT_flag & 6)) // if no 4 or 16 color entry, skip it
605 eDebug("skipped 8bit CLUT entry");
606 continue;
608 full_range = *segment++ & 1;
609 processed_length += 2;
611 if (full_range)
613 v_Y = *segment++;
614 v_Cr = *segment++;
615 v_Cb = *segment++;
616 v_T = *segment++;
617 processed_length += 4;
618 } else
620 v_Y = *segment & 0xFC;
621 v_Cr = (*segment++ & 3) << 6;
622 v_Cr |= (*segment & 0xC0) >> 2;
623 v_Cb = (*segment & 0x3C) << 2;
624 v_T = (*segment++ & 3) << 6;
625 processed_length += 2;
628 clut->entries[CLUT_entry_id].Y = v_Y;
629 clut->entries[CLUT_entry_id].Cr = v_Cr;
630 clut->entries[CLUT_entry_id].Cb = v_Cb;
631 clut->entries[CLUT_entry_id].T = v_T;
632 clut->size++;
633 //eDebug(" %04x %02x %02x %02x %02x", CLUT_entry_id, v_Y, v_Cb, v_Cr, v_T);
635 break;
637 case 0x13: // object data segment
639 int object_id, object_version_number, object_coding_method, non_modifying_color_flag;
641 object_id = *segment++ << 8;
642 object_id |= *segment++;
643 processed_length += 2;
645 object_version_number = *segment >> 4;
646 object_coding_method = (*segment >> 2) & 3;
647 non_modifying_color_flag = (*segment++ >> 1) & 1;
648 processed_length++;
650 //eDebug("object id %04x, version %d, object_coding_method %d (page_id %d)", object_id, object_version_number, object_coding_method, page_id);
652 if (object_coding_method == 0)
654 int top_field_data_blocklength, bottom_field_data_blocklength;
655 int i, line, linep;
657 top_field_data_blocklength = *segment++ << 8;
658 top_field_data_blocklength |= *segment++;
660 bottom_field_data_blocklength = *segment++ << 8;
661 bottom_field_data_blocklength |= *segment++;
662 //eDebug("%d / %d bytes", top_field_data_blocklength, bottom_field_data_blocklength);
663 processed_length += 4;
665 i = 0;
666 line = 0;
667 linep = 0;
668 while (i < top_field_data_blocklength)
670 int len;
671 len = subtitle_process_pixel_data(sub, page, object_id, &line, &linep, segment);
672 if (len < 0)
673 return -1;
674 segment += len;
675 processed_length += len;
676 i += len;
679 line = 1;
680 linep = 0;
682 if (bottom_field_data_blocklength)
684 i = 0;
685 while (i < bottom_field_data_blocklength)
687 int len;
688 len = subtitle_process_pixel_data(sub, page, object_id, &line, &linep, segment);
689 if (len < 0)
690 return -1;
691 segment += len;
692 processed_length += len;
693 i += len;
696 else if (top_field_data_blocklength)
697 eDebug("!!!! unimplemented: no bottom field! (%d : %d)", top_field_data_blocklength, bottom_field_data_blocklength);
699 if ((top_field_data_blocklength + bottom_field_data_blocklength) & 1)
701 segment++; processed_length++;
704 else if (object_coding_method == 1)
705 eDebug("---- object_coding_method 1 unsupported!");
707 break;
709 case 0x80: // end of display set segment
711 // eDebug("end of display set segment");
712 if (sub->screen_enabled)
713 subtitle_redraw_all(sub);
714 break;
716 case 0xFF: // stuffing
717 break;
718 default:
719 eDebug("unhandled segment type %02x", segment_type);
722 return segment_length + 6;
725 void subtitle_process_pes(struct subtitle_ctx *sub, void *buffer, int len)
727 __u8 *pkt = (__u8*)buffer;
728 if (pkt[0] || pkt[1] || (pkt[2] != 1))
730 //eDebug("%s: invalid startcode %02x %02x %02x", __FUNCTION__, pkt[0], pkt[1], pkt[2]);
731 return;
733 if (pkt[3] != 0xBD)
735 //eDebug("%s: invalid stream_id %02x", __FUNCTION__, pkt[3]);
736 return;
738 pkt += 6; len -= 6;
739 // skip PES header
740 pkt++; len--;
741 pkt++; len--;
743 int hdr_len = *pkt++; len--;
745 pkt+=hdr_len; len-=hdr_len;
747 if (*pkt != 0x20)
749 //eDebug("data identifier is 0x%02x, but not 0x20", *pkt);
750 return;
752 pkt++; len--; // data identifier
753 *pkt++; len--; // stream id;
755 if (len <= 0)
757 //eDebug("no data left (%d)", len);
758 return;
761 while (len && *pkt == 0x0F)
763 int l = subtitle_process_segment(sub, pkt);
764 if (l < 0)
765 break;
766 pkt += l;
767 len -= l;
769 // if (len && *pkt != 0xFF)
770 // eDebug("strange data at the end");
773 void subtitle_clear_screen(struct subtitle_ctx *sub)
775 /* clear bbox */
776 int y;
778 //eDebug("BBOX clear %d:%d -> %d:%d", sub->bbox_left, sub->bbox_top, sub->bbox_right, sub->bbox_bottom);
780 // do not draw when anyone has locked the
781 // framebuffer ( non enigma plugins... )
782 sub->bbox_right = 720;
783 if (sub->bbox_right > sub->bbox_left && !fbClass::getInstance()->islocked())
784 for (y=sub->bbox_top; y < sub->bbox_bottom; ++y)
785 memset(sub->screen_buffer + y * sub->screen_width, 0, sub->bbox_right - sub->bbox_left);
787 sub->bbox_right = 0;
788 sub->bbox_left = sub->screen_width;
789 sub->bbox_top = sub->screen_height;
790 sub->bbox_bottom = 0;
793 void subtitle_redraw_all(struct subtitle_ctx *sub)
795 #if 1
796 struct subtitle_page *page = sub->pages;
797 if ( page )
798 subtitle_clear_screen(sub);
799 while(page)
801 subtitle_redraw(sub, page->page_id);
802 page = page->next;
804 #else
805 struct subtitle_page *page = sub->pages;
806 if ( page )
807 subtitle_clear_screen(sub);
808 //eDebug("----------- end of display set");
809 //eDebug("active pages:");
810 while (page)
812 //eDebug(" page_id %02x", page->page_id);
813 //eDebug(" page_version_number: %d", page->page_version_number);
814 //eDebug(" active regions:");
816 struct subtitle_page_region *region = page->page_regions;
817 while (region)
819 //eDebug(" region_id: %04x", region->region_id);
820 //eDebug(" region_horizontal_address: %d", region->region_horizontal_address);
821 //eDebug(" region_vertical_address: %d", region->region_vertical_address);
823 region = region->next;
827 subtitle_redraw(sub, page->page_id);
828 //eDebug("defined regions:");
829 struct subtitle_region *region = page->regions;
830 while (region)
832 //eDebug(" region_id %04x, version %d, %dx%d", region->region_id, region->region_version_number, region->region_width, region->region_height);
834 struct subtitle_region_object *object = region->region_objects;
835 while (object)
837 //eDebug(" object %02x, type %d, %d:%d", object->object_id, object->object_type, object->object_horizontal_position, object->object_vertical_position);
838 object = object->next;
841 region = region->next;
843 page = page->next;
845 #endif
848 void subtitle_reset(struct subtitle_ctx *sub)
850 while (struct subtitle_page *page = sub->pages)
852 /* free page regions */
853 while (page->page_regions)
855 struct subtitle_page_region *p = page->page_regions->next;
856 delete page->page_regions;
857 page->page_regions = p;
859 /* free regions */
860 while (page->regions)
862 struct subtitle_region *region = page->regions;
864 while (region->region_objects)
866 struct subtitle_region_object *obj = region->region_objects;
867 region->region_objects = obj->next;
868 delete obj;
871 delete [] region->region_buffer;
873 page->regions = region->next;
874 delete region;
877 /* free CLUTs */
878 while (page->cluts)
880 struct subtitle_clut *clut = page->cluts;
881 page->cluts = clut->next;
882 delete clut;
885 sub->pages = page->next;
886 delete page;
890 void subtitle_redraw(struct subtitle_ctx *sub, int page_id)
892 struct subtitle_page *page = sub->pages;
893 int main_clut_id = -1;
895 //eDebug("displaying page id %d", page_id);
897 while (page)
899 if (page->page_id == page_id)
900 break;
901 page = page->next;
903 if (!page)
905 //eDebug("page not found");
906 return;
909 //eDebug("iterating regions..");
910 /* iterate all regions in this pcs */
911 struct subtitle_page_region *region = page->page_regions;
912 while (region)
914 //eDebug("region %d", region->region_id);
915 /* find corresponding region */
916 struct subtitle_region *reg = page->regions;
917 while (reg)
919 if (reg->region_id == region->region_id)
920 break;
921 reg = reg->next;
923 if (reg)
925 int y;
926 int clut_id = reg->clut_id;
927 //eDebug("clut %d, %d", clut_id, main_clut_id);
928 if (main_clut_id != -1)
930 if (main_clut_id != clut_id)
932 eDebug("MULTIPLE CLUTS IN USE! prepare for pixelmuell!");
933 // exit(0);
936 main_clut_id = clut_id;
938 int x0 = region->region_horizontal_address;
939 int y0 = region->region_vertical_address;
940 int x1 = x0 + reg->region_width;
941 int y1 = y0 + reg->region_height;
943 //eDebug("copy region %d to %d, %d, size %d %d", region->region_id, x0, y0, x1, y1);
945 if ((x0 < 0) || (y0 < 0) || (x0 > sub->screen_width) || (x0 > sub->screen_height))
946 continue;
948 /* adjust bbox */
949 if (x0 < sub->bbox_left)
950 sub->bbox_left = x0;
951 if (y0 < sub->bbox_top)
952 sub->bbox_top = y0;
953 if (x1 > sub->bbox_right)
954 sub->bbox_right = x1;
955 if (y1 > sub->bbox_bottom)
956 sub->bbox_bottom = y1;
958 // start timeout...
959 sub->timeout_timer->start(page->page_time_out*1000, true);
961 // do not draw when anyone has locked the
962 // framebuffer ( non enigma plugins... )
963 if ( !fbClass::getInstance()->islocked() )
964 /* copy to screen */
965 for (y=0; y < reg->region_height; ++y)
967 memcpy(sub->screen_buffer +
968 sub->screen_width * (y + region->region_vertical_address) +
969 region->region_horizontal_address,
970 reg->region_buffer + reg->region_width * y, reg->region_width);
973 else
974 eDebug("region not found");
975 region = region->next;
977 //eDebug("schon gut.");
979 if (main_clut_id == -1)
980 return; /* most probably no display active */
982 if ((sub->current_clut_id == main_clut_id) && (sub->current_clut_page_id == page_id))
983 return;
985 //eDebug("updating clut..");
986 /* find corresponding clut */
987 struct subtitle_clut *clut = page->cluts;
988 while (clut)
990 //eDebug("have %d, want %d", clut->clut_id, main_clut_id);
991 if (clut->clut_id == main_clut_id)
992 break;
993 clut = clut->next;
995 if (clut)
997 // do not change color palette when anyone has
998 // locked the framebuffer ( non enigma plugins )
999 if (!fbClass::getInstance()->islocked())
1000 sub->set_palette(clut);
1002 else
1004 if (!fbClass::getInstance()->islocked())
1005 sub->set_palette(0);
1009 void subtitle_screen_enable(struct subtitle_ctx *sub, int enable)
1011 if (sub->screen_enabled == enable)
1012 return;
1013 sub->screen_enabled = enable;
1014 if (enable)
1015 subtitle_redraw_all(sub);
1016 else
1017 subtitle_clear_screen(sub);