disable debug code
[libdreamdvd.git] / main.c
1 /*
2  * DreamDVD V0.9 - DVD-Player for Dreambox
3  * Copyright (C) 2007 by Seddi
4  *
5  * This DVD Player is based upon the great work from the libdvdnav project,
6  * a52dec library, ffmpeg and the knowledge from all the people who made
7  * watching DVD within linux possible.
8  *
9  * DreamDVD is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * DreamDVD is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
22  *
23  * part of libdreamdvd
24  */
25
26 #include "main.h"
27 #include "mpegaudioenc.h"
28 #include "a52dec.h"
29
30 /*
31  * local helper functions
32  */
33 static ssize_t safe_write(int fd, const void *buf, size_t count)
34 {
35         const uint8_t *ptr = buf;
36         size_t written = 0;
37         ssize_t n;
38
39         while (written < count) {
40                 n = write(fd, &ptr[written], count - written);
41                 if (n < 0) {
42                         if (errno != EINTR) {
43                                 perror("write");
44                                 return written ? written : -1;
45                         }
46                 } else {
47                         written += n;
48                 }
49         }
50
51         return written;
52 }
53
54 static void write_string(const char *filename, const char *string)
55 {
56         FILE *f;
57
58         f = fopen(filename, "w");
59         if (f == NULL) {
60                 perror(filename);
61                 return;
62         }
63
64         fputs(string, f);
65         fclose(f);
66 }
67
68 static int open_pipe(int fd[2])
69 {
70         int flags;
71
72         fd[0] = fd[1] = -1;
73
74         if (pipe(fd) < 0) {
75                 perror("pipe");
76                 goto err;
77         }
78
79         flags = fcntl(fd[0], F_GETFL);
80         if (flags < 0) {
81                 perror("F_GETFL");
82                 goto err;
83         }
84         if (fcntl(fd[0], F_SETFL, flags | O_NONBLOCK) < 0) {
85                 perror("F_SETFL");
86                 goto err;
87         }
88
89         return 0;
90
91 err:
92         if (fd[0] != -1) {
93                 close(fd[0]);
94                 fd[0] = -1;
95         }
96         if (fd[1] != -1) {
97                 close(fd[1]);
98                 fd[1] = -1;
99         }
100
101         return -1;
102 }
103
104 /*
105  * external functions
106  */
107
108 // create ddvd handle and set defaults
109 struct ddvd *ddvd_create(void)
110 {
111         struct ddvd *pconfig;
112
113         pconfig = malloc(sizeof(struct ddvd));
114         if (pconfig == NULL) {
115                 perror("malloc");
116                 return NULL;
117         }
118
119         memset(pconfig, 0, sizeof(struct ddvd));
120
121         // defaults
122         ddvd_set_ac3thru(pconfig, 0);
123         ddvd_set_language(pconfig, "en");
124         ddvd_set_dvd_path(pconfig, "/dev/cdroms/cdrom0");
125         ddvd_set_video(pconfig, DDVD_4_3, DDVD_LETTERBOX, DDVD_PAL);
126         ddvd_set_lfb(pconfig, NULL, 720, 576, 1, 720);
127         struct ddvd_resume resume_info;
128         resume_info.title=resume_info.chapter=resume_info.block=resume_info.audio_id=resume_info.audio_lock=resume_info.spu_id=resume_info.spu_lock=0;
129         ddvd_set_resume_pos(pconfig, resume_info);
130         pconfig->should_resume = 0;
131         pconfig->next_time_update = 0;
132         strcpy(pconfig->title_string, "");
133
134         // open pipes
135         if (open_pipe(pconfig->key_pipe) < 0) {
136                 ddvd_close(pconfig);
137                 return NULL;
138         }
139         if (open_pipe(pconfig->message_pipe) < 0) {
140                 ddvd_close(pconfig);
141                 return NULL;
142         }
143
144         return pconfig;
145 }
146
147 // destroy ddvd handle
148 void ddvd_close(struct ddvd *pconfig)
149 {
150         if (pconfig->message_pipe[0] != -1)
151                 close(pconfig->message_pipe[0]);
152         if (pconfig->message_pipe[1] != -1)
153                 close(pconfig->message_pipe[1]);
154         if (pconfig->key_pipe[0] != -1)
155                 close(pconfig->key_pipe[0]);
156         if (pconfig->key_pipe[1] != -1)
157                 close(pconfig->key_pipe[1]);
158         if (pconfig->dvd_path != NULL)
159                 free(pconfig->dvd_path);
160
161         free(pconfig);
162 }
163
164 // get message_pipe fd for polling functions in the host app
165 int ddvd_get_messagepipe_fd(struct ddvd *pconfig)
166 {
167         return pconfig->message_pipe[0];
168 }
169
170 // set resume postion
171 void ddvd_set_resume_pos(struct ddvd *pconfig, struct ddvd_resume resume_info)
172 {
173         pconfig->resume_title = resume_info.title;
174         pconfig->resume_chapter = resume_info.chapter;
175         pconfig->resume_block = resume_info.block;
176         pconfig->should_resume = 1;
177         pconfig->resume_audio_id = resume_info.audio_id;
178         pconfig->resume_audio_lock = resume_info.audio_lock;
179         pconfig->resume_spu_id = resume_info.spu_id;
180         pconfig->resume_spu_lock = resume_info.spu_lock;
181 }
182
183 // set framebuffer options
184 void ddvd_set_lfb(struct ddvd *pconfig, unsigned char *lfb, int xres, int yres, int bypp, int stride)
185 {
186         return ddvd_set_lfb_ex(pconfig, lfb, xres, yres, bypp, stride, 0);
187 }
188
189 void ddvd_set_lfb_ex(struct ddvd *pconfig, unsigned char *lfb, int xres, int yres, int bypp, int stride, int canscale)
190 {
191         pconfig->lfb = lfb;
192         pconfig->xres = xres;
193         pconfig->yres = yres;
194         pconfig->stride = stride;
195         pconfig->bypp = bypp;
196         pconfig->canscale = canscale;
197 }
198
199 // set path to dvd block device or file structure/iso
200 void ddvd_set_dvd_path(struct ddvd *pconfig, const char *path)
201 {
202         if (pconfig->dvd_path != NULL)
203                 free(pconfig->dvd_path);
204
205         pconfig->dvd_path = strdup(path);
206 }
207
208 // set language
209 void ddvd_set_language(struct ddvd *pconfig, const char lang[2])
210 {
211         memcpy(pconfig->language, lang, 2);
212 }
213
214 // set internal ac3 decoding (needs liba52 which will be dynamically loaded)
215 void ddvd_set_ac3thru(struct ddvd *pconfig, int ac3thru)
216 {
217         pconfig->ac3thru = ac3thru;
218 }
219
220 // set video options
221 void ddvd_set_video_ex(struct ddvd *pconfig, int aspect, int tv_mode, int tv_mode2, int tv_system)
222 {
223         pconfig->aspect = aspect;
224         pconfig->tv_mode = tv_mode;
225         pconfig->tv_mode2 = tv_mode2;
226         pconfig->tv_system = tv_system;
227 }
228
229 // set subtitle stream id
230 void ddvd_set_spu(struct ddvd *pconfig, int spu_id)
231 {
232         ddvd_send_key(pconfig, DDVD_SET_SUBTITLE);
233         ddvd_send_key(pconfig, spu_id);
234 }
235
236 // set audio stream id
237 void ddvd_set_audio(struct ddvd *pconfig, int audio_id)
238 {
239         ddvd_send_key(pconfig, DDVD_SET_AUDIO);
240         ddvd_send_key(pconfig, audio_id);
241 }
242
243 // set video options
244 void ddvd_set_video(struct ddvd *pconfig, int aspect, int tv_mode, int tv_system)
245 {
246         ddvd_set_video_ex(pconfig, aspect, tv_mode, tv_mode, tv_system);
247 }
248
249 // send commands/keys to the main player
250 void ddvd_send_key(struct ddvd *pconfig, int key)
251 {
252         safe_write(pconfig->key_pipe[1], &key, sizeof(int));
253 }
254
255 // skip n seconds in playing n>0 forward - n<0 backward
256 void ddvd_skip_seconds(struct ddvd *pconfig, int seconds)
257 {
258         if (seconds < 0)
259                 ddvd_send_key(pconfig, DDVD_SKIP_BWD);
260         else
261                 ddvd_send_key(pconfig, DDVD_SKIP_FWD);
262
263         ddvd_send_key(pconfig, seconds);
264 }
265
266 // jump to beginning of given title
267 void ddvd_set_title(struct ddvd *pconfig, int title)
268 {
269         ddvd_send_key(pconfig, DDVD_SET_TITLE);
270         ddvd_send_key(pconfig, title);
271 }
272
273 // jump to beginning of given chapter
274 void ddvd_set_chapter(struct ddvd *pconfig, int chapter)
275 {
276         ddvd_send_key(pconfig, DDVD_SET_CHAPTER);
277         ddvd_send_key(pconfig, chapter);
278 }
279
280 // get and process the next message from the main player
281 int ddvd_get_next_message(struct ddvd *pconfig, int blocked)
282 {
283         int res;
284         int i;
285
286         if (ddvd_readpipe(pconfig->message_pipe[0], &res, sizeof(int), blocked) != sizeof(int))
287                 res = DDVD_NULL;
288
289         switch (res)            // more data to process ?
290         {
291         case DDVD_COLORTABLE_UPDATE:
292                 for (i = 0; i < 4; i++)
293                         ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_col[i], sizeof(struct ddvd_color), 1);
294                 break;
295         case DDVD_SHOWOSD_TIME:
296                 ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_time, sizeof(pconfig->last_time), 1);
297                 break;
298         case DDVD_SHOWOSD_STATE_FFWD:
299                 ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_trickspeed, sizeof(pconfig->last_trickspeed), 1);
300                 ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_time, sizeof(pconfig->last_time), 1);
301                 break;
302         case DDVD_SHOWOSD_STATE_FBWD:
303                 ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_trickspeed, sizeof(pconfig->last_trickspeed), 1);
304                 ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_time, sizeof(pconfig->last_time), 1);
305                 break;
306         case DDVD_SHOWOSD_STRING:
307                 ddvd_readpipe(pconfig->message_pipe[0], pconfig->last_string, sizeof(pconfig->last_string), 1);
308                 break;
309         case DDVD_SHOWOSD_AUDIO:
310                 ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_audio_id, sizeof(int), 1);
311                 ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_audio_lang, sizeof(uint16_t), 1);
312                 ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_audio_type, sizeof(int), 1);
313                 break;
314         case DDVD_SHOWOSD_SUBTITLE:
315                 ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_spu_id, sizeof(int), 1);
316                 ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_spu_lang, sizeof(uint16_t), 1);
317                 break;
318         case DDVD_SCREEN_UPDATE:
319                 ddvd_readpipe(pconfig->message_pipe[0], &pconfig->blit_area, sizeof(pconfig->blit_area), 1);
320                 break;
321         case DDVD_SHOWOSD_ANGLE:
322                 ddvd_readpipe(pconfig->message_pipe[0], &pconfig->angle_current, sizeof(int), 1);
323                 ddvd_readpipe(pconfig->message_pipe[0], &pconfig->angle_num, sizeof(int), 1);
324                 break;
325         case DDVD_SIZE_CHANGED:
326                 ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_size, sizeof(struct ddvd_size_evt), 1);
327                 break;
328         case DDVD_PROGRESSIVE_CHANGED:
329                 ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_progressive, sizeof(struct ddvd_progressive_evt), 1);
330                 break;
331         case DDVD_FRAMERATE_CHANGED:
332                 ddvd_readpipe(pconfig->message_pipe[0], &pconfig->last_framerate, sizeof(struct ddvd_framerate_evt), 1);
333                 break;
334         default:
335                 break;
336         }
337         return res;
338 }
339
340 // get last blit area
341 void ddvd_get_last_blit_area(struct ddvd *pconfig, int *x_start, int *x_end, int *y_start, int *y_end)
342 {
343         struct ddvd_resize_return *ptr = &pconfig->blit_area;
344         memcpy(x_start, &ptr->x_start, sizeof(int));
345         memcpy(x_end, &ptr->x_end, sizeof(int));
346         memcpy(y_start, &ptr->y_start, sizeof(int));
347         memcpy(y_end, &ptr->y_end, sizeof(int));
348 }
349
350 void ddvd_get_blit_destination(struct ddvd *pconfig, int *x_offset, int *y_offset, int *width, int *height)
351 {
352         struct ddvd_resize_return *ptr = &pconfig->blit_area;
353
354         *x_offset = ptr->x_offset;
355         *y_offset = ptr->y_offset;
356         *width = ptr->width;
357         *height = ptr->height;
358 }
359
360 // get angle info
361 void ddvd_get_angle_info(struct ddvd*pconfig, int *current, int *num)
362 {
363         memcpy(current, &pconfig->angle_current, sizeof(pconfig->angle_current));
364         memcpy(num, &pconfig->angle_num, sizeof(pconfig->angle_num));
365 }
366
367 // get last colortable for 8bit mode (4 colors)
368 void ddvd_get_last_colortable(struct ddvd *pconfig, void *colortable)
369 {
370         memcpy(colortable, pconfig->last_col, sizeof(pconfig->last_col));
371 }
372
373 // get last received playing time as struct ddvd_time
374 void ddvd_get_last_time(struct ddvd *pconfig, void *timestamp)
375 {
376         memcpy(timestamp, &pconfig->last_time, sizeof(pconfig->last_time));
377 }
378
379 // get the actual trickspeed (2-64x) when in trickmode
380 void ddvd_get_last_trickspeed(struct ddvd *pconfig, void *trickspeed)
381 {
382         memcpy(trickspeed, &pconfig->last_trickspeed, sizeof(pconfig->last_trickspeed));
383 }
384
385 // get last text message from player
386 void ddvd_get_last_string(struct ddvd *pconfig, void *text)
387 {
388         memcpy(text, pconfig->last_string, sizeof(pconfig->last_string));
389 }
390
391 // get the number of available audio tracks
392 void ddvd_get_audio_count(struct ddvd *pconfig, void *count)
393 {
394         int c = 0;
395         int i;
396         for ( i = 0; i < MAX_AUDIO; i++)
397         {
398                 if ( pconfig->audio_format[i] != -1 )
399                         c++;
400         }
401         memcpy(count, &c, sizeof(int));
402 }
403
404 // get the active audio track
405 void ddvd_get_last_audio(struct ddvd *pconfig, void *id, void *lang, void *type)
406 {
407         memcpy(id, &pconfig->last_audio_id, sizeof(pconfig->last_audio_id));
408         memcpy(lang, &pconfig->last_audio_lang, sizeof(pconfig->last_audio_lang));
409         memcpy(type, &pconfig->last_audio_type, sizeof(pconfig->last_audio_type));
410 }
411
412 // get audio track details for given audio track id
413 void ddvd_get_audio_byid(struct ddvd *pconfig, int audio_id, void *lang, void *type)
414 {
415         int audio_id_logical;
416         uint16_t audio_lang = 0xFFFF;
417         audio_id_logical = dvdnav_get_audio_logical_stream(dvdnav, audio_id);
418         audio_lang = dvdnav_audio_stream_to_lang(dvdnav, audio_id_logical);
419         if (audio_lang == 0xFFFF)
420                 audio_lang = 0x2D2D;
421         memcpy(lang, &audio_lang, sizeof(uint16_t));
422         memcpy(type, &pconfig->audio_format[audio_id], sizeof(int));
423 }
424
425 // get the active SPU track
426 void ddvd_get_last_spu(struct ddvd *pconfig, void *id, void *lang)
427 {
428         memcpy(id, &pconfig->last_spu_id, sizeof(pconfig->last_spu_id));
429         memcpy(lang, &pconfig->last_spu_lang, sizeof(pconfig->last_spu_lang));
430 }
431
432 // get the number of available subtitle tracks
433 void ddvd_get_spu_count(struct ddvd *pconfig, void *count)
434 {
435         int c = 0;
436         int i;
437         for ( i = 0; i < MAX_SPU; i++)
438         {
439                 if ( pconfig->spu_map[i] != -1 )
440                         c++;
441         }
442         memcpy(count, &c, sizeof(int));
443 }
444
445 // get audio track details for given subtitle track id
446 void ddvd_get_spu_byid(struct ddvd *pconfig, int spu_id, void *lang)
447 {
448         uint16_t spu_lang = 0xFFFF;
449         if (spu_id < MAX_SPU & pconfig->spu_map[spu_id] > -1)
450                 spu_lang = dvdnav_spu_stream_to_lang(dvdnav, pconfig->spu_map[spu_id]);
451         memcpy(lang, &spu_lang, sizeof(uint16_t));
452 }
453
454 // get dvd title string
455 void ddvd_get_title_string(struct ddvd *pconfig, char *title_string)
456 {
457         memcpy(title_string, pconfig->title_string, sizeof(pconfig->title_string));
458 }
459
460 // get actual position for resuming
461 void ddvd_get_resume_pos(struct ddvd *pconfig, struct ddvd_resume *resume_info)
462 {
463         memcpy(&resume_info->title, &pconfig->resume_title, sizeof(pconfig->resume_title));
464         memcpy(&resume_info->chapter, &pconfig->resume_chapter, sizeof(pconfig->resume_chapter));
465         memcpy(&resume_info->block, &pconfig->resume_block, sizeof(pconfig->resume_block));
466         memcpy(&resume_info->audio_id, &pconfig->resume_audio_id, sizeof(pconfig->resume_audio_id));
467         memcpy(&resume_info->audio_lock, &pconfig->resume_audio_lock, sizeof(pconfig->resume_audio_lock));
468         memcpy(&resume_info->spu_id, &pconfig->resume_spu_id, sizeof(pconfig->resume_spu_id));
469         memcpy(&resume_info->spu_lock, &pconfig->resume_spu_lock, sizeof(pconfig->resume_spu_lock));
470 }
471
472 void ddvd_get_last_size(struct ddvd *pconfig, int *width, int *height, int *aspect)
473 {
474         *width = pconfig->last_size.width;
475         *height = pconfig->last_size.height;
476         *aspect = pconfig->last_size.aspect;
477 }
478
479 void ddvd_get_last_progressive(struct ddvd *pconfig, int *progressive)
480 {
481         *progressive = pconfig->last_progressive.progressive;
482 }
483
484 void ddvd_get_last_framerate(struct ddvd *pconfig, int *framerate)
485 {
486         *framerate = pconfig->last_framerate.framerate;
487 }
488
489 struct ddvd_spu_return merge(struct ddvd_spu_return a, struct ddvd_spu_return b)
490 {
491         struct ddvd_spu_return r;
492         r = b;
493         
494         if (a.x_start !=  a.x_end || a.y_start != a.y_end)
495         {
496                         /* union old and new area */
497                 if (a.x_start < r.x_start)
498                         r.x_start = a.x_start;
499                 if (a.y_start < r.y_start)
500                         r.y_start = a.y_start;
501                 if (a.x_end > r.x_end)
502                         r.x_end = a.x_end;
503                 if (a.y_end > r.y_end)
504                         r.y_end = a.y_end;
505         }
506         return r;
507 }
508
509 static int calc_x_scale_offset(int dvd_aspect, int tv_mode, int tv_mode2, int tv_aspect)
510 {
511         int x_offset=0;
512
513         if (dvd_aspect == 0 && tv_mode == DDVD_PAN_SCAN) {
514                 switch (tv_aspect) {
515                 case DDVD_16_10:
516                         x_offset = (ddvd_screeninfo_xres - ddvd_screeninfo_xres * 12 / 15) / 2;  // correct 16:10 (broadcom 15:9) panscan (pillarbox) overlay
517                         break;
518                 case DDVD_16_9:
519                         x_offset = (ddvd_screeninfo_xres - ddvd_screeninfo_xres * 3 / 4) / 2; // correct 16:9 panscan (pillarbox) overlay
520                 default:
521                         break;
522                 }
523         }
524
525         if (dvd_aspect >= 2 && tv_aspect == DDVD_4_3 && tv_mode == DDVD_PAN_SCAN)
526                 x_offset = -(ddvd_screeninfo_xres * 4 / 3 - ddvd_screeninfo_xres) / 2;
527
528         if (dvd_aspect >= 2 && tv_aspect == DDVD_16_10 && tv_mode2 == DDVD_PAN_SCAN)
529                 x_offset = -(ddvd_screeninfo_xres * 16 / 15 - ddvd_screeninfo_xres) / 2;
530
531         return x_offset;
532 }
533
534 static int calc_y_scale_offset(int dvd_aspect, int tv_mode, int tv_mode2, int tv_aspect)
535 {
536         int y_offset = 0;
537
538         if (dvd_aspect == 0 && tv_mode == DDVD_LETTERBOX) {
539                 switch (tv_aspect) {
540                 case DDVD_16_10:
541                         y_offset = (ddvd_screeninfo_yres * 15 / 12 - ddvd_screeninfo_yres) / 2; // correct 16:10 (broacom 15:9) letterbox overlay
542                         break;
543                 case DDVD_16_9:
544                         y_offset = (ddvd_screeninfo_yres * 4 / 3 - ddvd_screeninfo_yres) / 2; // correct 16:9 letterbox overlay
545                 default:
546                         break;
547                 }
548         }
549
550         if (dvd_aspect >= 2 && tv_aspect == DDVD_4_3 && tv_mode == DDVD_LETTERBOX)
551                 y_offset = -(ddvd_screeninfo_yres - ddvd_screeninfo_yres * 3 / 4) / 2;
552
553         if (dvd_aspect >= 2 && tv_aspect == DDVD_16_10 && tv_mode2 == DDVD_LETTERBOX)
554                 y_offset = -(ddvd_screeninfo_yres - ddvd_screeninfo_yres * 15 / 16) / 2;
555
556         return y_offset;
557 }
558
559 #if CONFIG_API_VERSION >= 3
560 static int readMpegProc(char *str, int decoder)
561 {
562         int val = -1;
563         char tmp[64];
564         sprintf(tmp, "/proc/stb/vmpeg/%d/%s", decoder, str);
565         FILE *f = fopen(tmp, "r");
566         if (f)
567         {
568                 fscanf(f, "%x", &val);
569                 fclose(f);
570         }
571         return val;
572 }
573
574 static int readApiSize(int fd, int *xres, int *yres, int *aspect)
575 {
576         video_size_t size;
577         if (!ioctl(fd, VIDEO_GET_SIZE, &size))
578         {
579                 *xres = size.w;
580                 *yres = size.h;
581                 *aspect = size.aspect_ratio == 0 ? 2 : 3;  // convert dvb api to etsi
582                 return 0;
583         }
584         return -1;
585 }
586
587 static int readApiFrameRate(int fd, int *framerate)
588 {
589         unsigned int frate;
590         if (!ioctl(fd, VIDEO_GET_FRAME_RATE, &frate))
591         {
592                 *framerate = frate;
593                 return 0;
594         }
595         return -1;
596 }
597 #endif
598
599 // the main player loop
600 enum ddvd_result ddvd_run(struct ddvd *playerconfig)
601 {
602         if (playerconfig->lfb == NULL) {
603                 printf("Frame/backbuffer not given to libdreamdvd. Will not start the player !\n");
604                 return DDVD_INVAL;
605         }
606
607         // we need to know the first vts_change and the next cell change for resuming a dvd
608         int first_vts_change = 1;
609         int next_cell_change = 0;
610         int ddvd_have_ntsc = -1;
611         
612         ddvd_screeninfo_xres = playerconfig->xres;
613         ddvd_screeninfo_yres = playerconfig->yres;
614         ddvd_screeninfo_stride = playerconfig->stride;
615         int ddvd_screeninfo_bypp = playerconfig->bypp;
616         int message_pipe = playerconfig->message_pipe[1];
617         int key_pipe = playerconfig->key_pipe[0];
618         unsigned char *p_lfb = playerconfig->lfb;
619         enum ddvd_result res = DDVD_OK;
620         int msg;
621         // try to load liba52.so.0 for softdecoding
622         int have_liba52 = ddvd_load_liba52();
623         
624         // decide which resize routine we should use
625         // on 4bpp mode we use bicubic resize for sd skins because we get much better results with subtitles and the speed is ok
626         // for hd skins we use nearest neighbor resize because upscaling to hd is too slow with bicubic resize
627         if (ddvd_screeninfo_bypp == 1)
628                 ddvd_resize_pixmap = ddvd_resize_pixmap_spu = &ddvd_resize_pixmap_1bpp;
629         else if (ddvd_screeninfo_xres > 720)
630                 ddvd_resize_pixmap = ddvd_resize_pixmap_spu = &ddvd_resize_pixmap_xbpp;
631         else
632         {
633                 ddvd_resize_pixmap = &ddvd_resize_pixmap_xbpp;
634                 ddvd_resize_pixmap_spu = &ddvd_resize_pixmap_xbpp_smooth;
635         }
636
637         uint8_t *last_iframe = NULL;
638         uint8_t *spu_buffer = NULL;
639         uint8_t *spu_backbuffer = NULL;
640
641         // init backbuffer (SPU)
642         ddvd_lbb = malloc(720 * 576);   // the spu backbuffer is always max DVD PAL 720x576 pixel (NTSC 720x480)
643         if (ddvd_lbb == NULL) {
644                 perror("SPU-Backbuffer <mem allocation failed>");
645                 res = DDVD_NOMEM;
646                 goto err_malloc;
647         }
648         ddvd_lbb2 = malloc(ddvd_screeninfo_xres * ddvd_screeninfo_yres * ddvd_screeninfo_bypp);
649         if (ddvd_lbb2 == NULL) {
650                 perror("SPU-Backbuffer <mem allocation failed>");
651                 res = DDVD_NOMEM;
652                 goto err_malloc;
653         }
654         
655         last_iframe = malloc(320 * 1024);
656         if (last_iframe == NULL) {
657                 perror("malloc");
658                 res = DDVD_NOMEM;
659                 goto err_malloc;
660         }
661
662         spu_buffer = malloc(2 * (128 * 1024));
663         if (spu_buffer == NULL) {
664                 perror("malloc");
665                 res = DDVD_NOMEM;
666                 goto err_malloc;
667         }
668
669         spu_backbuffer = malloc(NUM_SPU_BACKBUFFER * 2 * (128 * 1024));
670         if (spu_backbuffer == NULL) {
671                 perror("malloc");
672                 res = DDVD_NOMEM;
673                 goto err_malloc;
674         }
675
676         struct ddvd_resize_return blit_area;
677         
678         memset(ddvd_lbb, 0, 720 * 576);
679         memset(p_lfb, 0, ddvd_screeninfo_stride * ddvd_screeninfo_yres);        //clear screen                  
680         blit_area.x_start = blit_area.y_start = 0;
681         blit_area.x_end = ddvd_screeninfo_xres - 1;
682         blit_area.y_end = ddvd_screeninfo_yres - 1;
683         blit_area.x_offset = 0;
684         blit_area.y_offset = 0;
685         blit_area.width = ddvd_screeninfo_xres;
686         blit_area.height = ddvd_screeninfo_yres;
687         
688         msg = DDVD_SCREEN_UPDATE;
689         safe_write(message_pipe, &msg, sizeof(int));
690         safe_write(message_pipe, &blit_area, sizeof(struct ddvd_resize_return));
691         
692         printf("Opening output...\n");
693
694 #if CONFIG_API_VERSION == 1
695         ddvd_output_fd = open("/dev/video", O_WRONLY);
696         if (ddvd_output_fd == -1) {
697                 perror("/dev/video");
698                 res = DDVD_BUSY;
699                 goto err_open_output_fd;
700         }
701
702         ddvd_fdvideo = open("/dev/dvb/card0/video0", O_RDWR);
703         if (ddvd_fdvideo == -1) {
704                 perror("/dev/dvb/card0/video0");
705                 res = DDVD_BUSY;
706                 goto err_open_fdvideo;
707         }
708
709         ddvd_fdaudio = open("/dev/dvb/card0/audio0", O_RDWR);
710         if (ddvd_fdaudio == -1) {
711                 perror("/dev/dvb/card0/audio0");
712                 res = DDVD_BUSY;
713                 goto err_open_fdaudio;
714         }
715
716         ddvd_ac3_fd = open("/dev/sound/dsp1", O_RDWR);
717         if (ddvd_ac3_fd == -1) {
718                 perror("/dev/sound/dsp1");
719                 res = DDVD_BUSY;
720                 goto err_open_ac3_fd;
721         }
722
723         if (ioctl(ddvd_fdvideo, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY) < 0)
724                 perror("VIDEO_SELECT_SOURCE");
725         if (ioctl(ddvd_fdvideo, VIDEO_CLEAR_BUFFER) < 0)
726                 perror("VIDEO_CLEAR_BUFFER");
727         if (ioctl(ddvd_fdvideo, VIDEO_PLAY) < 0)
728                 perror("VIDEO_PLAY");
729
730         if (ioctl(ddvd_fdaudio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY) < 0)
731                 perror("AUDIO_SELECT_SOURCE");
732         if (ioctl(ddvd_fdaudio, AUDIO_CLEAR_BUFFER) < 0)
733                 perror("AUDIO_CLEAR_BUFFER");
734         if (ioctl(ddvd_fdaudio, AUDIO_PLAY) < 0)
735                 perror("AUDIO_PLAY");
736
737 #elif CONFIG_API_VERSION == 3
738         ddvd_output_fd = ddvd_fdvideo = open("/dev/dvb/adapter0/video0", O_RDWR);
739         if (ddvd_fdvideo == -1) {
740                 perror("/dev/dvb/adapter0/video0");
741                 res = DDVD_BUSY;
742                 goto err_open_fdvideo;
743         }
744
745         ddvd_ac3_fd = ddvd_fdaudio = open("/dev/dvb/adapter0/audio0", O_RDWR);
746         if (ddvd_fdaudio == -1) {
747                 perror("/dev/dvb/adapter0/audio0");
748                 res = DDVD_BUSY;
749                 goto err_open_ac3_fd;
750         }
751
752         if (ioctl(ddvd_fdvideo, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY) < 0)
753                 perror("VIDEO_SELECT_SOURCE");
754         if (ioctl(ddvd_fdvideo, VIDEO_CLEAR_BUFFER) < 0)
755                 perror("VIDEO_CLEAR_BUFFER");
756         if (ioctl(ddvd_fdvideo, VIDEO_SET_STREAMTYPE, 0) < 0)   // set mpeg2
757                 perror("VIDEO_SET_STREAMTYPE");
758         if (ioctl(ddvd_fdvideo, VIDEO_PLAY) < 0)
759                 perror("VIDEO_PLAY");
760
761         if (ioctl(ddvd_fdaudio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY) < 0)
762                 perror("AUDIO_SELECT_SOURCE");
763         if (ioctl(ddvd_fdaudio, AUDIO_CLEAR_BUFFER) < 0)
764                 perror("AUDIO_CLEAR_BUFFER");
765         if (ioctl(ddvd_fdaudio, AUDIO_PLAY) < 0)
766                 perror("AUDIO_PLAY");
767 #else
768 #error please define CONFIG_API_VERSION to be 1 or 3
769 #endif
770
771         int i;
772 // show startup screen
773 #if SHOW_START_SCREEN == 1
774 #if CONFIG_API_VERSION == 1
775         //that really sucks but there is no other way
776         for (i = 0; i < 10; i++)
777                 safe_write(ddvd_output_fd, ddvd_startup_logo, sizeof(ddvd_startup_logo));
778 #else
779         unsigned char pes_header[] = { 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x80, 0x00, 0x00 };
780         safe_write(ddvd_output_fd, pes_header, sizeof(pes_header));
781         safe_write(ddvd_output_fd, ddvd_startup_logo, sizeof(ddvd_startup_logo));
782 #endif
783 #endif
784
785         int audio_type = DDVD_UNKNOWN;
786
787 #if CONFIG_API_VERSION == 3
788         ddvd_set_pcr_offset();
789 #endif
790
791         uint8_t mem[DVD_VIDEO_LB_LEN];
792         uint8_t *buf = mem;
793         int result, event, len;
794
795         unsigned char lpcm_data[2048 * 6 * 6 /*4608 */ ];
796         int mpa_header_length;
797         int mpa_count, mpa_count2;
798         uint8_t mpa_data[2048 * 4];
799         int ac3_len;
800         int16_t ac3_tmp[2048 * 6 * 6];
801
802         ddvd_mpa_init(48000, 192000);   //init MPA Encoder with 48kHz and 192k Bitrate
803
804         int ac3thru = 1;
805         if (have_liba52) {
806                 state = a52_init(0);    //init AC3 Decoder 
807                 ac3thru = playerconfig->ac3thru;
808         }
809
810         char osdtext[512];
811         strcpy(osdtext, "");
812
813         int tv_aspect = playerconfig->aspect;   //0-> 4:3 lb 1-> 4:3 ps 2-> 16:9 3-> always 16:9
814         int tv_mode = playerconfig->tv_mode;
815         int tv_mode2 = playerconfig->tv_mode2; // just used when tv_aspect is 16:10 and dvd_aspect is 16:9
816         int dvd_aspect = 0;     //0-> 4:3 2-> 16:9
817         int dvd_scale_perm = 0;
818         int tv_scale = 0;       //0-> off 1-> letterbox 2-> panscan
819         int spu_active_id = -1;
820         int finished = 0;
821         int audio_id;
822         int report_audio_info = 0;
823
824         struct ddvd_spu_return last_spu_return;
825         struct ddvd_resize_return last_blit_area;
826         memcpy(&last_blit_area,&blit_area,sizeof(struct ddvd_resize_return));
827         last_spu_return.x_start = last_spu_return.y_start = 0;
828         last_spu_return.x_end = last_spu_return.y_end = 0;
829         
830         ddvd_trickmode = TOFF;
831         ddvd_trickspeed = 0;
832
833         int rccode;
834         int ismute = 0;
835
836         if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)
837                 perror("AUDIO_SET_AV_SYNC");
838 #if CONFIG_API_VERSION == 1     
839         // set video system
840         int pal_ntsc = playerconfig->tv_system;
841         int saa;
842         if (pal_ntsc == 1)
843                 saa = SAA_NTSC;
844         else
845                 saa = SAA_PAL;
846         int saafd = open("/dev/dbox/saa0", O_RDWR);
847         if (saafd >= 0) {
848                 if (ioctl(saafd, SAAIOSENC, &saa) < 0)
849                         perror("SAAIOSENC");
850                 close(saafd);
851         }
852 #else
853         {
854                 struct ddvd_size_evt evt;
855                 int msg = DDVD_SIZE_CHANGED;
856                 readApiSize(ddvd_fdvideo, &evt.width, &evt.height, &evt.aspect);
857                 safe_write(message_pipe, &msg, sizeof(int));
858                 safe_write(message_pipe, &evt, sizeof(evt));
859         }
860         {
861                 struct ddvd_framerate_evt evt;
862                 int msg = DDVD_FRAMERATE_CHANGED;
863                 readApiFrameRate(ddvd_fdvideo, &evt.framerate);
864                 safe_write(message_pipe, &msg, sizeof(int));
865                 safe_write(message_pipe, &evt, sizeof(evt));
866         }
867         {
868                 struct ddvd_progressive_evt evt;
869                 int msg = DDVD_PROGRESSIVE_CHANGED;
870                 evt.progressive = readMpegProc("progressive", 0);
871                 safe_write(message_pipe, &msg, sizeof(int));
872                 safe_write(message_pipe, &evt, sizeof(evt));
873         }
874 #endif
875         
876         /* open dvdnav handle */
877         printf("Opening DVD...%s\n", playerconfig->dvd_path);
878         if (dvdnav_open(&dvdnav, playerconfig->dvd_path) != DVDNAV_STATUS_OK) {
879                 printf("Error on dvdnav_open\n");
880                 sprintf(osdtext, "Error: Cant open DVD Source: %s", playerconfig->dvd_path);
881                 msg = DDVD_SHOWOSD_STRING;
882                 safe_write(message_pipe, &msg, sizeof(int));
883                 safe_write(message_pipe, &osdtext, sizeof(osdtext));
884                 res = DDVD_FAIL_OPEN;
885                 goto err_dvdnav_open;
886         }
887
888         /* set read ahead cache usage to no */
889         if (dvdnav_set_readahead_flag(dvdnav, 0) != DVDNAV_STATUS_OK) {
890                 printf("Error on dvdnav_set_readahead_flag: %s\n", dvdnav_err_to_string(dvdnav));
891                 res = DDVD_FAIL_PREFS;
892                 goto err_dvdnav;
893         }
894
895         /* set the language */
896         if (dvdnav_menu_language_select(dvdnav, playerconfig->language) != DVDNAV_STATUS_OK ||
897             dvdnav_audio_language_select(dvdnav, playerconfig->language) != DVDNAV_STATUS_OK ||
898             dvdnav_spu_language_select(dvdnav, playerconfig->language) != DVDNAV_STATUS_OK) {
899                 printf("Error on setting languages: %s\n", dvdnav_err_to_string(dvdnav));
900                 res = DDVD_FAIL_PREFS;
901                 goto err_dvdnav;
902         }
903
904         /* set the PGC positioning flag to have position information relatively to the
905          * whole feature instead of just relatively to the current chapter */
906         if (dvdnav_set_PGC_positioning_flag(dvdnav, 1) != DVDNAV_STATUS_OK) {
907                 printf("Error on dvdnav_set_PGC_positioning_flag: %s\n", dvdnav_err_to_string(dvdnav));
908                 res = DDVD_FAIL_PREFS;
909                 goto err_dvdnav;
910         }
911
912         int audio_lock = 0;
913         int spu_lock = 0;
914         for (i=0; i < MAX_AUDIO; i++)
915                 playerconfig->audio_format[i] = -1;
916
917         for (i=0; i < MAX_SPU; i++)
918                 playerconfig->spu_map[i] = -1;
919
920         unsigned long long vpts, apts, spts, pts;
921
922         audio_id = dvdnav_get_active_audio_stream(dvdnav);
923         ddvd_playmode = PLAY;
924
925         ddvd_lbb_changed = 0;
926
927         unsigned long long spu_backpts[NUM_SPU_BACKBUFFER];
928
929         ddvd_play_empty(FALSE);
930         ddvd_get_time();        //set timestamp
931
932         playerconfig->in_menu = 0;
933
934         const char *dvd_titlestring;
935         if (dvdnav_get_title_string(dvdnav, &dvd_titlestring) == DVDNAV_STATUS_OK)
936                 strcpy(playerconfig->title_string, dvd_titlestring);
937
938         msg = DDVD_SHOWOSD_TITLESTRING;
939         safe_write(message_pipe, &msg, sizeof(int));
940
941         /* the read loop which regularly calls dvdnav_get_next_block
942          * and handles the returned events */
943         int reached_eof = 0;
944         int reached_sof = 0;
945
946         while (!finished) {
947                 pci_t *pci = 0;
948                 dsi_t *dsi = 0;
949                 int buttonN = -1;
950                 int in_menu = 0;
951
952                 /* the main reading function */
953                 if (ddvd_playmode == PLAY) {    //skip when not in play mode
954                         // trickmode
955                         if (ddvd_trickmode) {
956                                 if (ddvd_trick_timer_end <= ddvd_get_time()) {
957                                         if (ddvd_trickmode == FASTBW) { //jump back ?
958                                                 uint32_t pos, len;
959                                                 dvdnav_get_position(dvdnav, &pos, &len);
960                                                 //90000 = 1 Sek. -> 45000 = 0.5 Sek. -> Speed Faktor=2
961                                                 int64_t posneu = ((pos * ddvd_lastCellEventInfo.pgc_length) / len) - (45000 * 2 * ddvd_trickspeed);
962                                                 int64_t posneu2 = posneu <= 0 ? 0 : (posneu * len) / ddvd_lastCellEventInfo.pgc_length;
963                                                 dvdnav_sector_search(dvdnav, posneu2, SEEK_SET);
964                                                 if (posneu < 0) {       // reached begin of movie
965                                                         reached_sof = 1;
966                                                         msg = DDVD_SHOWOSD_TIME;
967                                                 } else {
968                                                         msg = DDVD_SHOWOSD_STATE_FBWD;
969                                                 }
970                                         } else if (ddvd_trickmode == FASTFW) {  //jump forward ?
971                                                 uint32_t pos, len;
972                                                 dvdnav_get_position(dvdnav, &pos, &len);
973                                                 //90000 = 1 Sek. -> 22500 = 0.25 Sek. -> Speed Faktor=2
974                                                 int64_t posneu = ((pos * ddvd_lastCellEventInfo.pgc_length) / len) + (22500 * 2 * ddvd_trickspeed);
975                                                 int64_t posneu2 = (posneu * len) / ddvd_lastCellEventInfo.pgc_length;
976                                                 if (posneu2 && len && posneu2 >= len) { // reached end of movie
977                                                         posneu2 = len - 250;
978                                                         reached_eof = 1;
979                                                         msg = DDVD_SHOWOSD_TIME;
980                                                 } else {
981                                                         msg = DDVD_SHOWOSD_STATE_FFWD;
982                                                 }
983                                                 dvdnav_sector_search(dvdnav, posneu2, SEEK_SET);
984                                         }
985                                         ddvd_trick_timer_end = ddvd_get_time() + 300;
986                                         ddvd_lpcm_count = 0;
987                                 }
988                         }
989
990                         result = dvdnav_get_next_block(dvdnav, buf, &event, &len);
991                         if (result == DVDNAV_STATUS_ERR) {
992                                 printf("Error getting next block: %s\n", dvdnav_err_to_string(dvdnav));
993                                 sprintf(osdtext, "Error: Getting next block: %s", dvdnav_err_to_string(dvdnav));
994                                 msg = DDVD_SHOWOSD_STRING;
995                                 safe_write(message_pipe, &msg, sizeof(int));
996                                 safe_write(message_pipe, &osdtext, sizeof(osdtext));
997                                 res = DDVD_FAIL_READ;
998                                 goto err_dvdnav;
999                         }
1000
1001 send_message:
1002                         // send OSD Data
1003                         if (msg > 0) {
1004                                 struct ddvd_time info;
1005                                 switch (msg) {
1006                                 case DDVD_SHOWOSD_TIME:
1007                                         info = ddvd_get_osd_time(playerconfig);
1008                                         safe_write(message_pipe, &msg, sizeof(int));
1009                                         safe_write(message_pipe, &info, sizeof(struct ddvd_time));
1010                                         break;
1011                                 case DDVD_SHOWOSD_STATE_FFWD:
1012                                         info = ddvd_get_osd_time(playerconfig);
1013                                         safe_write(message_pipe, &msg, sizeof(int));
1014                                         safe_write(message_pipe, &ddvd_trickspeed, sizeof(int));
1015                                         safe_write(message_pipe, &info, sizeof(struct ddvd_time));
1016                                         break;
1017                                 case DDVD_SHOWOSD_STATE_FBWD:
1018                                         info = ddvd_get_osd_time(playerconfig);
1019                                         safe_write(message_pipe, &msg, sizeof(int));
1020                                         safe_write(message_pipe, &ddvd_trickspeed, sizeof(int));
1021                                         safe_write(message_pipe, &info, sizeof(struct ddvd_time));
1022                                         break;
1023                                 default:
1024                                         break;
1025                                 }
1026                                 msg = 0;
1027                         }
1028
1029                         if (reached_eof) {
1030                                 msg = DDVD_EOF_REACHED;
1031                                 safe_write(message_pipe, &msg, sizeof(int));
1032                                 reached_eof = 0;
1033                         }
1034
1035                         if (reached_sof) {
1036                                 msg = DDVD_SOF_REACHED;
1037                                 safe_write(message_pipe, &msg, sizeof(int));
1038                                 reached_sof = 0;
1039                         }
1040
1041                         if (ddvd_get_time() > playerconfig->next_time_update) {
1042                                 msg = DDVD_SHOWOSD_TIME;
1043                                 goto send_message;
1044                         }
1045                         // send iFrame
1046                         if (ddvd_iframesend < 0) {
1047 #if CONFIG_API_VERSION == 1
1048                                 ddvd_device_clear();
1049 #endif
1050                                 ddvd_iframesend = 0;
1051                         }
1052
1053                         if (ddvd_iframesend > 0) {
1054 #if CONFIG_API_VERSION == 1
1055                                 ddvd_device_clear();
1056 #endif
1057                                 if (ddvd_still_frame && ddvd_last_iframe_len) {
1058 #if 0
1059                                         static int ifnum = 0;
1060                                         static char ifname[255];
1061                                         snprintf(ifname, 255, "/tmp/dvd.iframe.%3.3d.asm.pes", ifnum++);
1062                                         FILE *f = fopen(ifname, "wb");
1063                                         fwrite(last_iframe, 1, ddvd_last_iframe_len, f);
1064                                         fclose(f);
1065 #endif
1066
1067 #if CONFIG_API_VERSION == 1
1068                                         //that really sucks but there is no other way
1069                                         int i;
1070                                         for (i = 0; i < 10; i++)
1071                                                 safe_write(ddvd_output_fd, last_iframe, ddvd_last_iframe_len);
1072 #else
1073                                         safe_write(ddvd_output_fd, last_iframe, ddvd_last_iframe_len);
1074 #endif
1075                                         //printf("Show iframe with size: %d\n",ddvd_last_iframe_len);
1076                                         ddvd_last_iframe_len = 0;
1077                                 }
1078
1079                                 ddvd_iframesend = -1;
1080                         }
1081                         // wait timer
1082                         if (ddvd_wait_timer_active) {
1083                                 if (ddvd_wait_timer_end <= ddvd_get_time()) {
1084                                         ddvd_wait_timer_active = 0;
1085                                         dvdnav_still_skip(dvdnav);
1086                                         //printf("wait timer done\n");
1087                                 }
1088                         }
1089                         // SPU timer
1090                         if (ddvd_spu_timer_active) {
1091                                 if (ddvd_spu_timer_end <= ddvd_get_time()) {
1092                                         ddvd_spu_timer_active = 0;
1093                                                 /* the last_spu bbox is still filled with the correct value, no need to blit full screen */
1094                                                 /* TODO: only clear part of backbuffer */
1095                                         memset(ddvd_lbb, 0, 720 * 576); //clear SPU backbuffer
1096                                         ddvd_lbb_changed = 1;
1097                                 }
1098                         }
1099
1100                         switch (event) {
1101                         case DVDNAV_BLOCK_OK:
1102                                 /* We have received a regular block of the currently playing MPEG stream.
1103                                  * So we do some demuxing and decoding. */
1104                                 {
1105
1106                                         // collect audio data
1107                                         int stream_type = buf[14 + buf[14 + 8] + 9];
1108                                         if (((buf[14 + 3]) & 0xF0) == 0xC0)
1109                                                 playerconfig->audio_format[(buf[14 + 3]) - 0xC0] = DDVD_MPEG;
1110                                         if ((buf[14 + 3]) == 0xBD && (stream_type & 0xF8) == 0x80)
1111                                                 playerconfig->audio_format[stream_type - 0x80] = DDVD_AC3;
1112                                         if ((buf[14 + 3]) == 0xBD && (stream_type & 0xF8) == 0x88)
1113                                                 playerconfig->audio_format[stream_type - 0x88] = DDVD_DTS;
1114                                         if ((buf[14 + 3]) == 0xBD && (stream_type & 0xF8) == 0xA0)
1115                                                 playerconfig->audio_format[stream_type - 0xA0] = DDVD_LPCM;
1116
1117                                         if ((buf[14 + 3] & 0xF0) == 0xE0) {     // video
1118                                                 int pes_len = ((buf[14+4]<<8)|buf[14+5]) + 6;
1119                                                 int padding = len - (14 + pes_len);
1120                                                 if (buf[14 + 7] & 128) {
1121                                                         /* damn gcc bug */
1122                                                         vpts = ((unsigned long long)(((buf[14 + 9] >> 1) & 7))) << 30;
1123                                                         vpts |= buf[14 + 10] << 22;
1124                                                         vpts |= (buf[14 + 11] >> 1) << 15;
1125                                                         vpts |= buf[14 + 12] << 7;
1126                                                         vpts |= (buf[14 + 13] >> 1);
1127                                                         //printf("VPTS? %X\n",(int)vpts);
1128                                                 }
1129 #if CONFIG_API_VERSION == 1
1130                                                 // Eliminate 00 00 01 B4 sequence error packet because it breaks the pallas mpeg decoder
1131                                                 // This is very strange because the 00 00 01 B4 is partly inside the header extension ...
1132                                                 if (buf[21] == 0x00 && buf[22] == 0x00 && buf[23] == 0x01 && buf[24] == 0xB4) {
1133                                                         buf[21] = 0x01;
1134                                                 }
1135                                                 if (buf[22] == 0x00 && buf[23] == 0x00 && buf[24] == 0x01 && buf[25] == 0xB4) {
1136                                                         buf[22] = 0x01;
1137                                                 }
1138 #endif
1139                                                 // if we have 16:9 Zoom Mode on the DVD and we use a "always 16:9" mode on tv we have
1140                                                 // to patch the mpeg header and the Sequence Display Extension inside the Stream in some cases
1141                                                 if (dvd_aspect == 3 && ((tv_aspect == DDVD_16_9 && (tv_mode == DDVD_PAN_SCAN || tv_mode == DDVD_LETTERBOX)) ||
1142                                                     (tv_aspect == DDVD_16_10 && (tv_mode2 == DDVD_PAN_SCAN || tv_mode2 == DDVD_LETTERBOX)))) {
1143                                                         int z=0;
1144                                                         for (z=0; z<2040; z++)
1145                                                         {
1146                                                                 if (buf[z] == 0x0 && buf[z+1] == 0x0 && buf[z+2] ==0x01 && buf[z+3] == 0xB5 && (buf[z+4] == 0x22 || buf[z+4] == 0x23))
1147                                                                 {
1148                                                                         buf[z+5]=0x22;
1149                                                                         buf[z+5]=0x0B;
1150                                                                         buf[z+6]=0x42;
1151                                                                         buf[z+7]=0x12;
1152                                                                         buf[z+8]=0x00;
1153                                                                 }
1154                                                         }
1155                                                         if (buf[33] == 0 && buf[33 + 1] == 0 && buf[33 + 2] == 1 && buf[33 + 3] == 0xB3) {
1156                                                                 buf[33 + 7] = (buf[33 + 7] & 0xF) + 0x30;
1157                                                         }
1158                                                         if (buf[36] == 0 && buf[36 + 1] == 0 && buf[36 + 2] == 1 && buf[36 + 3] == 0xB3) {
1159                                                                 buf[36 + 7] = (buf[36 + 7] & 0xF) + 0x30;
1160                                                         }
1161                                                 }
1162
1163                                                 // check yres for detecting ntsc/pal
1164                                                 if (ddvd_have_ntsc == -1) {
1165                                                         if ((buf[33] == 0 && buf[33 + 1] == 0 && buf[33 + 2] == 1 && buf[33 + 3] == 0xB3 && ((buf[33+5] & 0xF) << 8) + buf[33+6] == 0x1E0) 
1166                                                                 || (buf[36] == 0 && buf[36 + 1] == 0 && buf[36 + 2] == 1 && buf[36 + 3] == 0xB3 && ((buf[36+5] & 0xF) << 8) + buf[36+6] == 0x1E0))
1167                                                                 ddvd_have_ntsc = 1;
1168                                                         else
1169                                                                 ddvd_have_ntsc = 0;
1170                                                 }
1171
1172                                                 if (padding > 8) {
1173                                                         memcpy(buf+14+pes_len, "\x00\x00\x01\xE0\x00\x00\x80\x00\x00", 9);
1174                                                         pes_len += 9;
1175                                                 }
1176
1177                                                 safe_write(ddvd_output_fd, buf + 14, pes_len);
1178
1179                                                 if (padding && padding < 9)
1180                                                         safe_write(ddvd_output_fd, "\x00\x00\x01\xE0\x00\x00\x80\x00\x00", 9);
1181
1182                                                 // 14+8 header_length
1183                                                 // 14+(header_length)+3  -> start mpeg header
1184                                                 // buf[14+buf[14+8]+3] start mpeg header
1185
1186                                                 int datalen = (buf[19] + (buf[18] << 8) + 6) - buf[14 + 8];     // length mpeg packet
1187                                                 int data = buf[14 + buf[14 + 8] + 3];   // start mpeg packet(header)
1188
1189                                                 int do_copy = (ddvd_iframerun == 0x01) && !(buf[data] == 0 && buf[data + 1] == 0 && buf[data + 2] == 1) ? 1 : 0;
1190                                                 int have_pictureheader = 0;
1191                                                 int haveslice = 0;
1192                                                 int setrun = 0;
1193
1194                                                 while (datalen > 3) {
1195                                                         if (buf[data] == 0 && buf[data + 1] == 0 && buf[data + 2] == 1) {
1196                                                                 if (buf[data + 3] == 0x00 && datalen > 6) { //picture
1197                                                                         if (!setrun) {
1198                                                                                 ddvd_iframerun = ((buf[data + 5] >> 3) & 0x07);
1199                                                                                 setrun = 1;
1200                                                                         }
1201                                                                         if (ddvd_iframerun < 0x01 || 0x03 < ddvd_iframerun) {
1202                                                                                 data++;
1203                                                                                 datalen--;
1204                                                                                 continue;
1205                                                                         }
1206                                                                         have_pictureheader = 1;
1207                                                                         data += 5;
1208                                                                         datalen -= 5;
1209                                                                         datalen = 6;
1210                                                                 } else if (buf[data + 3] == 0xB3 && datalen >= 8) { //sequence header
1211                                                                         ddvd_last_iframe_len = 0;       // clear iframe buffer
1212                                                                         data += 7;
1213                                                                         datalen -= 7;
1214                                                                 } else if (buf[data + 3] == 0xBE) { //padding stream
1215                                                                         break;
1216                                                                 } else if (0x01 <= buf[data + 3] && buf[data + 3] <= 0xaf) { //slice ?
1217                                                                         if (!have_pictureheader && ddvd_last_iframe_len == 0)
1218                                                                                 haveslice = 1;
1219                                                                 }
1220                                                         }
1221                                                         data++;
1222                                                         datalen--;
1223                                                 }
1224                                                 if ((ddvd_iframerun <= 0x01 || do_copy) && ddvd_still_frame) {
1225                                                         if (haveslice)
1226                                                                 ddvd_iframerun = 0xFF;
1227                                                         else if (ddvd_last_iframe_len < (320 * 1024) - ((buf[19] + (buf[18] << 8) + 6) - buf[14 + 8])) {
1228                                                                 int len = buf[19] + (buf[18] << 8) + 6;
1229                                                                 int skip = buf[14+8] + 9; // skip complete pes header
1230                                                                 len -= skip;
1231                                                                 if (ddvd_last_iframe_len == 0) { // add simple pes header without pts
1232                                                                         memcpy(last_iframe, "\x00\x00\x01\xE0\x00\x00\x80\x00\x00", 9);
1233                                                                         ddvd_last_iframe_len += 9;
1234                                                                 }
1235                                                                 memcpy(last_iframe + ddvd_last_iframe_len, buf + 14 + skip, len);
1236                                                                 ddvd_last_iframe_len += len;
1237                                                         }
1238                                                 }
1239                                         } else if ((buf[14 + 3]) == 0xC0 + audio_id)    // mpeg audio
1240                                         {
1241                                                 if (audio_type != DDVD_MPEG) {
1242                                                         //printf("Switch to MPEG Audio\n");
1243                                                         if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)
1244                                                                 perror("AUDIO_SET_AV_SYNC");
1245                                                         if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 1) < 0)
1246                                                                 perror("AUDIO_SET_BYPASS_MODE");
1247                                                         audio_type = DDVD_MPEG;
1248                                                 }
1249
1250                                                 if (buf[14 + 7] & 128) {
1251                                                         /* damn gcc bug */
1252                                                         apts = ((unsigned long long)(((buf[14 + 9] >> 1) & 7))) << 30;
1253                                                         apts |= buf[14 + 10] << 22;
1254                                                         apts |= (buf[14 + 11] >> 1) << 15;
1255                                                         apts |= buf[14 + 12] << 7;
1256                                                         apts |= (buf[14 + 13] >> 1);
1257                                                         //printf("APTS? %X\n",(int)apts);
1258                                                 }
1259
1260                                                 safe_write(ddvd_ac3_fd, buf + 14, buf[19] + (buf[18] << 8) + 6);
1261                                         } else if ((buf[14 + 3]) == 0xBD && (buf[14 + buf[14 + 8] + 9]) == 0xA0 + audio_id)     // lpcm audio
1262                                         {
1263                                                 // autodetect bypass mode
1264                                                 static int lpcm_mode = -1;
1265                                                 if (lpcm_mode < 0) {
1266                                                         lpcm_mode = 6;
1267                                                         if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, lpcm_mode) < 0)
1268                                                                 lpcm_mode = 0;
1269                                                 }
1270
1271                                                 if (audio_type != DDVD_LPCM) {
1272                                                         //printf("Switch to LPCM Audio\n");
1273                                                         if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)
1274                                                                 perror("AUDIO_SET_AV_SYNC");
1275                                                         if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, lpcm_mode) < 0)
1276                                                                 perror("AUDIO_SET_BYPASS_MODE");
1277                                                         audio_type = DDVD_LPCM;
1278                                                         ddvd_lpcm_count = 0;
1279                                                 }
1280                                                 if (buf[14 + 7] & 128) {
1281                                                         /* damn gcc bug */
1282                                                         apts = ((unsigned long long)(((buf[14 + 9] >> 1) & 7))) << 30;
1283                                                         apts |= buf[14 + 10] << 22;
1284                                                         apts |= (buf[14 + 11] >> 1) << 15;
1285                                                         apts |= buf[14 + 12] << 7;
1286                                                         apts |= (buf[14 + 13] >> 1);
1287                                                         //printf("APTS? %X\n",(int)apts);
1288                                                 }
1289
1290                                                 if (lpcm_mode == 0) {
1291                                                         int i = 0;
1292                                                         char abuf[(((buf[18] << 8) | buf[19]) - buf[22] - 14)];
1293             #if BYTE_ORDER == BIG_ENDIAN
1294                                                         // just copy, byte order is correct on ppc machines
1295                                                         memcpy(abuf, buf + 14 + buf[14 + 8] + 9 + 7, (((buf[18] << 8) | buf[19]) - buf[22] - 14));
1296                                                         i = (((buf[18] << 8) | buf[19]) - buf[22] - 14);
1297             #else
1298                                                         // byte swapping .. we become the wrong byteorder on lpcm on the 7025
1299                                                         while (i < (((buf[18] << 8) | buf[19]) - buf[22] - 14)) {
1300                                                                 abuf[i + 0] = (buf[14 + buf[14 + 8] + 9 + 7 + i + 1]);
1301                                                                 abuf[i + 1] = (buf[14 + buf[14 + 8] + 9 + 7 + i + 0]);
1302                                                                 i += 2;
1303                                                         }
1304             #endif
1305                                                         // we will encode the raw lpcm data to mpeg audio and send them with pts
1306                                                         // information to the decoder to get a sync. playing the pcm data via
1307                                                         // oss will break the pic/sound sync. So believe it or not, this is the 
1308                                                         // smartest way to get a synced lpcm track ;-)
1309                                                         if (ddvd_lpcm_count == 0) {     // save mpeg header with pts
1310                                                                 memcpy(mpa_data, buf + 14, buf[14 + 8] + 9);
1311                                                                 mpa_header_length = buf[14 + 8] + 9;
1312                                                         }
1313                                                         if (ddvd_lpcm_count + i >= 4608) {      //we have to send 4608 bytes to the encoder
1314                                                                 memcpy(lpcm_data + ddvd_lpcm_count, abuf, 4608 - ddvd_lpcm_count);
1315                                                                 //encode
1316                                                                 mpa_count = ddvd_mpa_encode_frame(mpa_data + mpa_header_length, 4608, lpcm_data);
1317                                                                 //patch pes__packet_length
1318                                                                 mpa_count = mpa_count + mpa_header_length - 6;
1319                                                                 mpa_data[4] = mpa_count >> 8;
1320                                                                 mpa_data[5] = mpa_count & 0xFF;
1321                                                                 //patch header type to mpeg
1322                                                                 mpa_data[3] = 0xC0;
1323                                                                 //write
1324                                                                 safe_write(ddvd_ac3_fd, mpa_data, mpa_count + mpa_header_length);
1325                                                                 memcpy(lpcm_data, abuf + (4608 - ddvd_lpcm_count), i - (4608 - ddvd_lpcm_count));
1326                                                                 ddvd_lpcm_count = i - (4608 - ddvd_lpcm_count);
1327                                                                 memcpy(mpa_data, buf + 14, buf[14 + 8] + 9);
1328                                                                 mpa_header_length = buf[14 + 8] + 9;
1329                                                         } else {
1330                                                                 memcpy(lpcm_data + ddvd_lpcm_count, abuf, i);
1331                                                                 ddvd_lpcm_count += i;
1332                                                         }
1333                                                 } else {
1334                                                         safe_write(ddvd_ac3_fd, buf+14 , buf[19]+(buf[18]<<8)+6);
1335                                                 }
1336                                         } else if ((buf[14 + 3]) == 0xBD && (buf[14 + buf[14 + 8] + 9]) == 0x88 + audio_id) {   // dts audio
1337                                                 if (audio_type != DDVD_DTS) {
1338                                                         //printf("Switch to DTS Audio (thru)\n");
1339                                                         if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)
1340                                                                 perror("AUDIO_SET_AV_SYNC");
1341 #ifdef CONVERT_TO_DVB_COMPLIANT_DTS
1342                                                         if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 2) < 0)  // DTS (dvb compliant)
1343 #else
1344                                                         if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 5) < 0)  // DTS VOB
1345 #endif
1346                                                                 perror("AUDIO_SET_BYPASS_MODE");
1347                                                         audio_type = DDVD_DTS;
1348                                                 }
1349
1350                                                 if (buf[14 + 7] & 128) {
1351                                                         /* damn gcc bug */
1352                                                         apts = ((unsigned long long)(((buf[14 + 9] >> 1) & 7))) << 30;
1353                                                         apts |= buf[14 + 10] << 22;
1354                                                         apts |= (buf[14 + 11] >> 1) << 15;
1355                                                         apts |= buf[14 + 12] << 7;
1356                                                         apts |= (buf[14 + 13] >> 1);
1357                                                         //printf("APTS? %X\n",(int)apts);
1358                                                 }
1359
1360 #ifdef CONVERT_TO_DVB_COMPLIANT_DTS
1361                                                         unsigned short pes_len = (buf[14 + 4] << 8 | buf[14 + 5]);
1362                                                         pes_len -= 4;   // strip first 4 bytes of pes payload
1363                                                         buf[14 + 4] = pes_len >> 8;     // patch pes len
1364                                                         buf[15 + 4] = pes_len & 0xFF;
1365
1366                                                         safe_write(ddvd_ac3_fd, buf + 14, 9 + buf[14 + 8]);     // write pes_header
1367                                                         safe_write(ddvd_ac3_fd, buf + 14 + 9 + buf[14 + 8] + 4, pes_len - (3 + buf[14 + 8]));   // write pes_payload
1368 #else
1369                                                         safe_write(ddvd_ac3_fd, buf + 14, buf[19] + (buf[18] << 8) + 6);
1370 #endif
1371                                         } else if ((buf[14 + 3]) == 0xBD && (buf[14 + buf[14 + 8] + 9]) == 0x80 + audio_id) {   // ac3 audio
1372                                                 if (audio_type != DDVD_AC3) {
1373                                                         //printf("Switch to AC3 Audio\n");
1374                                                         if (ac3thru || !have_liba52) {  // !have_liba52 and !ac3thru should never happen, but who knows ;)
1375                                                                 if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)
1376                                                                         perror("AUDIO_SET_AV_SYNC");
1377 #ifdef CONVERT_TO_DVB_COMPLIANT_AC3
1378                                                                 if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 0) < 0)  // AC3 (dvb compliant)
1379 #else
1380                                                                 if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 3) < 0)  // AC3 VOB
1381 #endif
1382                                                                         perror("AUDIO_SET_BYPASS_MODE");
1383                                                         } else {
1384                                                                 if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)
1385                                                                         perror("AUDIO_SET_AV_SYNC");
1386                                                                 if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 1) < 0)
1387                                                                         perror("AUDIO_SET_BYPASS_MODE");
1388                                                         }
1389                                                         audio_type = DDVD_AC3;
1390                                                 }
1391
1392                                                 if (buf[14 + 7] & 128) {
1393                                                         /* damn gcc bug */
1394                                                         apts = ((unsigned long long)(((buf[14 + 9] >> 1) & 7))) << 30;
1395                                                         apts |= buf[14 + 10] << 22;
1396                                                         apts |= (buf[14 + 11] >> 1) << 15;
1397                                                         apts |= buf[14 + 12] << 7;
1398                                                         apts |= (buf[14 + 13] >> 1);
1399                                                         //printf("APTS? %X\n",(int)apts);
1400                                                 }
1401
1402                                                 if (ac3thru || !have_liba52) {  // !have_liba52 and !ac3thru should never happen, but who knows ;)
1403 #ifdef CONVERT_TO_DVB_COMPLIANT_AC3
1404                                                         unsigned short pes_len = (buf[14 + 4] << 8 | buf[14 + 5]);
1405                                                         pes_len -= 4;   // strip first 4 bytes of pes payload
1406                                                         buf[14 + 4] = pes_len >> 8;     // patch pes len
1407                                                         buf[15 + 4] = pes_len & 0xFF;
1408
1409                                                         safe_write(ddvd_ac3_fd, buf + 14, 9 + buf[14 + 8]);     // write pes_header
1410                                                         safe_write(ddvd_ac3_fd, buf + 14 + 9 + buf[14 + 8] + 4, pes_len - (3 + buf[14 + 8]));   // write pes_payload
1411 #else
1412                                                         safe_write(ddvd_ac3_fd, buf + 14, buf[19] + (buf[18] << 8) + 6);
1413 #endif
1414                                                         //fwrite(buf+buf[22]+27, 1, ((buf[18]<<8)|buf[19])-buf[22]-7, fac3); //debugwrite
1415                                                 } else {
1416                                                         // a bit more funny than lpcm sound, because we do a complete recoding here
1417                                                         // we will decode the ac3 data to plain lpcm and will then encode to mpeg
1418                                                         // audio and send them with pts information to the decoder to get a sync.
1419
1420                                                         // decode and convert ac3 to raw lpcm
1421                                                         ac3_len = ddvd_ac3_decode(buf + buf[22] + 27, ((buf[18] << 8) | buf[19]) - buf[22] - 7, ac3_tmp);
1422
1423                                                         // save the pes header incl. PTS
1424                                                         memcpy(mpa_data, buf + 14, buf[14 + 8] + 9);
1425                                                         mpa_header_length = buf[14 + 8] + 9;
1426
1427                                                         //apts-=(((unsigned long long)(ddvd_lpcm_count)*90)/192);
1428
1429                                                         //mpa_data[14]=(int)((apts<<1)&0xFF);
1430                                                         //mpa_data[12]=(int)((apts>>7)&0xFF);
1431                                                         //mpa_data[11]=(int)(((apts<<1)>>15)&0xFF);
1432                                                         //mpa_data[10]=(int)((apts>>22)&0xFF);
1433
1434                                                         // copy lpcm data into buffer for encoding
1435                                                         memcpy(lpcm_data + ddvd_lpcm_count, ac3_tmp, ac3_len);
1436                                                         ddvd_lpcm_count += ac3_len;
1437
1438                                                         // encode the whole packet to mpa
1439                                                         mpa_count2 = mpa_count = 0;
1440                                                         while (ddvd_lpcm_count >= 4608) {
1441                                                                 mpa_count = ddvd_mpa_encode_frame(mpa_data + mpa_header_length + mpa_count2, 4608, lpcm_data);
1442                                                                 mpa_count2 += mpa_count;
1443                                                                 ddvd_lpcm_count -= 4608;
1444                                                                 memcpy(lpcm_data, lpcm_data + 4608, ddvd_lpcm_count);
1445                                                         }
1446
1447                                                         // patch pes__packet_length
1448                                                         mpa_count = mpa_count2 + mpa_header_length - 6;
1449                                                         mpa_data[4] = mpa_count >> 8;
1450                                                         mpa_data[5] = mpa_count & 0xFF;
1451
1452                                                         // patch header type to mpeg
1453                                                         mpa_data[3] = 0xC0;
1454
1455                                                         // write to decoder
1456                                                         safe_write(ddvd_ac3_fd, mpa_data, mpa_count2 + mpa_header_length);
1457
1458                                                 }
1459                                         } else if ((buf[14 + 3]) == 0xBD && ((buf[14 + buf[14 + 8] + 9]) & 0xE0) == 0x20 && ((buf[14 + buf[14 + 8] + 9]) & 0x1F) == spu_active_id) {    // SPU packet
1460                                                 memcpy(spu_buffer + ddvd_spu_ptr, buf + buf[22] + 14 + 10, 2048 - (buf[22] + 14 + 10));
1461                                                 ddvd_spu_ptr += 2048 - (buf[22] + 14 + 10);
1462
1463                                                 if (buf[14 + 7] & 128) {
1464                                                         /* damn gcc bug */
1465                                                         spts = ((unsigned long long)(((buf[14 + 9] >> 1) & 7))) << 30;
1466                                                         spts |= buf[14 + 10] << 22;
1467                                                         spts |= (buf[14 + 11] >> 1) << 15;
1468                                                         spts |= buf[14 + 12] << 7;
1469                                                         spts |= (buf[14 + 13] >> 1);
1470 #if CONFIG_API_VERSION == 1
1471                                                         spts >>= 1;     // need a corrected "spts" because vulcan/pallas will give us a 32bit pts instead of 33bit
1472 #endif
1473                                                         //printf("SPTS? %X\n",(int)spts);
1474                                                 }
1475
1476                                                 if (ddvd_spu_ptr >= (spu_buffer[0] << 8 | spu_buffer[1]))       // SPU packet complete ?
1477                                                 {
1478                                                         if (ddvd_spu_backnr == NUM_SPU_BACKBUFFER)      // backbuffer already full ?
1479                                                         {
1480                                                                 printf("dropped SPU frame\n");
1481                                                                 int tmplen = (spu_backbuffer[0] << 8 | spu_backbuffer[1]);
1482                                                                 memcpy(spu_backbuffer, spu_backbuffer + tmplen, ddvd_spu_backptr - tmplen);     // delete oldest SPU packet
1483                                                                 int i;
1484                                                                 for (i = 0; i < NUM_SPU_BACKBUFFER - 1; ++i)
1485                                                                         spu_backpts[i] = spu_backpts[i + 1];
1486                                                                 ddvd_spu_backnr = NUM_SPU_BACKBUFFER - 1;
1487                                                                 ddvd_spu_backptr -= tmplen;
1488                                                         }
1489
1490                                                         memcpy(spu_backbuffer + ddvd_spu_backptr, spu_buffer, (spu_buffer[0] << 8 | spu_buffer[1]));    // copy into backbuffer
1491                                                         spu_backpts[ddvd_spu_backnr++] = spts;  // store pts
1492                                                         ddvd_spu_backptr += (spu_buffer[0] << 8 | spu_buffer[1]);       // increase ptr
1493
1494                                                         ddvd_spu_ptr = 0;
1495                                                 }
1496                                         }
1497                                 }
1498                                 break;
1499
1500                         case DVDNAV_NOP:
1501                                 /* Nothing to do here. */
1502                                 break;
1503
1504                         case DVDNAV_STILL_FRAME:
1505                                 /* We have reached a still frame. So we start a timer to wait
1506                                  * the amount of time specified by the still's length while still handling
1507                                  * user input to make menus and other interactive stills work.
1508                                  * A length of 0xff means an indefinite still which has to be skipped
1509                                  * indirectly by some user interaction. */
1510                                 {
1511                                         if (ddvd_iframesend == 0 && ddvd_last_iframe_len)
1512                                                 ddvd_iframesend = 1;
1513
1514                                         dvdnav_still_event_t *still_event = (dvdnav_still_event_t *) buf;
1515                                         if (still_event->length < 0xff) {
1516                                                 if (!ddvd_wait_timer_active) {
1517                                                         ddvd_wait_timer_active = 1;
1518                                                         ddvd_wait_timer_end = ddvd_get_time() + (still_event->length * 1000);   //ms
1519                                                 }
1520                                         } else
1521                                                 ddvd_wait_for_user = 1;
1522                                 }
1523                                 break;
1524
1525                         case DVDNAV_WAIT:
1526                                 /* We have reached a point in DVD playback, where timing is critical.
1527                                  * We dont use readahead, so we can simply skip the wait state. */
1528                                 dvdnav_wait_skip(dvdnav);
1529                                 break;
1530
1531                         case DVDNAV_SPU_CLUT_CHANGE:
1532                                 /* We received a new color lookup table so we read and store
1533                                  * it */
1534                                 {
1535                                         int i = 0, i2 = 0;
1536                                         uint8_t pal[16 * 4];
1537 #if BYTE_ORDER == BIG_ENDIAN
1538                                         memcpy(pal, buf, 16 * sizeof(uint32_t));
1539 #else
1540                                         for (; i < 16; ++i)
1541                                                 *(int *)(pal + i * 4) = htonl(*(int *)(buf + i * 4));
1542                                         i = 0;
1543 #endif
1544                                         // dump buf and pal tables for debug reasons
1545                                         //while (i < 16 * 4) {
1546                                         //      int y = buf[i + 1];
1547                                         //      signed char cr = buf[i + 2];    //v
1548                                         //      signed char cb = buf[i + 3];    //u
1549                                         //      printf("%d %d %d ->", y, cr, cb);
1550                                         //      y = pal[i + 1];
1551                                         //      cr = pal[i + 2];        //v
1552                                         //      cb = pal[i + 3];        //u
1553                                         //      printf(" %d %d %d\n", y, cr, cb);
1554                                         //      i += 4;
1555                                         //}
1556                                         //i = 0;
1557
1558                                         while (i < 16 * 4) {
1559                                                 int y = pal[i + 1];
1560                                                 signed char cr = pal[i + 2];    //v
1561                                                 signed char cb = pal[i + 3];    //u
1562
1563                                                 y = 76310 * (y - 16);   //yuv2rgb
1564                                                 cr -= 128;
1565                                                 cb -= 128;
1566                                                 int r = CLAMP((y + 104635 * cr) >> 16);
1567                                                 int g = CLAMP((y - 53294 * cr - 25690 * cb) >> 16);
1568                                                 int b = CLAMP((y + 132278 * cb) >> 16);
1569
1570                                                 ddvd_bl[i2] = b << 8;
1571                                                 ddvd_gn[i2] = g << 8;
1572                                                 ddvd_rd[i2] = r << 8;
1573                                                 i += 4;
1574                                                 i2++;
1575                                         }
1576                                         //CHANGE COLORMAP
1577                                 }
1578                                 break;
1579
1580                         case DVDNAV_SPU_STREAM_CHANGE:
1581                                 /* We received a new SPU stream ID */
1582                                 if (spu_lock)
1583                                         break;
1584
1585                                 dvdnav_spu_stream_change_event_t *ev = (dvdnav_spu_stream_change_event_t *) buf;
1586                                 switch (tv_scale) {
1587                                 case 0: //off
1588                                         spu_active_id = ev->physical_wide;
1589                                         break;
1590                                 case 1: //letterbox
1591                                         spu_active_id = ev->physical_letterbox;
1592                                         break;
1593                                 case 2: //panscan
1594                                         spu_active_id = ev->physical_pan_scan;
1595                                         break;
1596                                 default:        // should not happen
1597                                         spu_active_id = ev->physical_wide;
1598                                         break;
1599                                 }       
1600                                 uint16_t spu_lang = 0xFFFF;
1601                                 int spu_id_logical, count_tmp;
1602                                 spu_id_logical = -1;
1603                                 count_tmp = spu_active_id;
1604                                 while (count_tmp >= 0 && count_tmp < MAX_SPU)
1605                                 {
1606                                         spu_id_logical = playerconfig->spu_map[count_tmp];
1607                                         if (spu_id_logical >= 0)
1608                                                 count_tmp = 0;
1609                                         count_tmp--;
1610                                 }
1611                                 
1612                                 spu_lang = dvdnav_spu_stream_to_lang(dvdnav, (spu_id_logical >= 0 ? spu_id_logical : spu_active_id) & 0x1F);
1613                                 if (spu_lang == 0xFFFF) {
1614                                         spu_lang = 0x2D2D;      // SPU "off, unknown or maybe menuoverlays" 
1615                                         spu_id_logical = -1;
1616                                 }                                                       
1617                                 msg = DDVD_SHOWOSD_SUBTITLE;
1618                                 int report_spu = spu_id_logical > 31 ? -1 : spu_id_logical;
1619                                 safe_write(message_pipe, &msg, sizeof(int));
1620                                 safe_write(message_pipe, &report_spu, sizeof(int));
1621                                 safe_write(message_pipe, &spu_lang, sizeof(uint16_t));
1622                                 //printf("SPU Stream change: w %X l: %X p: %X active: %X\n",ev->physical_wide,ev->physical_letterbox,ev->physical_pan_scan,spu_active_id);
1623                                 break;
1624
1625                         case DVDNAV_AUDIO_STREAM_CHANGE:
1626                                 /* We received a new Audio stream ID  */
1627                                 if (!audio_lock)
1628                                 {
1629                                         audio_id = dvdnav_get_active_audio_stream(dvdnav);
1630                                         report_audio_info = 1;
1631                                 }
1632                                 break;
1633
1634                         case DVDNAV_HIGHLIGHT:
1635                                 /* Lets display some Buttons */
1636                                 if (ddvd_clear_buttons == 0) {
1637                                         dvdnav_highlight_event_t *highlight_event = (dvdnav_highlight_event_t *) buf;
1638
1639                                         pci = dvdnav_get_current_nav_pci(dvdnav);
1640                                         dsi = dvdnav_get_current_nav_dsi(dvdnav);
1641                                         dvdnav_highlight_area_t hl;
1642                                         
1643                                         memcpy(&blit_area,&last_blit_area,sizeof(struct ddvd_resize_return));
1644                                         memset(p_lfb, 0, ddvd_screeninfo_stride * ddvd_screeninfo_yres);        //clear backbuffer .. 
1645                                         msg = DDVD_SCREEN_UPDATE;       // wipe old highlight
1646                                         safe_write(message_pipe, &msg, sizeof(int));
1647                                         safe_write(message_pipe, &blit_area, sizeof(struct ddvd_resize_return));
1648                                         //printf("destination area to wipe: %d %d %d %d\n",blit_area.x_start,blit_area.x_end,blit_area.y_start,blit_area.y_end);
1649                                         
1650                                         //struct ddvd_resize_return blit_area;
1651                                         blit_area.x_start = blit_area.x_end = blit_area.y_start = blit_area.y_end = 0;
1652                                                 
1653                                         int libdvdnav_workaround = 0;
1654
1655                                         if (pci->hli.hl_gi.btngr_ns) {
1656                                                 int btns_per_group = 36 / pci->hli.hl_gi.btngr_ns;
1657                                                 btni_t *btni = NULL;
1658                                                 int modeMask = 1 << tv_scale;
1659
1660                                                 if (!btni && pci->hli.hl_gi.btngr_ns >= 1 && (pci->hli.hl_gi.btngr1_dsp_ty & modeMask)) {
1661                                                         btni = &pci->hli.btnit[0 * btns_per_group + highlight_event->buttonN - 1];
1662                                                 }
1663                                                 if (!btni && pci->hli.hl_gi.btngr_ns >= 2 && (pci->hli.hl_gi.btngr2_dsp_ty & modeMask)) {
1664                                                         btni = &pci->hli.btnit[1 * btns_per_group + highlight_event->buttonN - 1];
1665                                                 }
1666                                                 if (!btni && pci->hli.hl_gi.btngr_ns >= 3 && (pci->hli.hl_gi.btngr3_dsp_ty & modeMask)) {
1667                                                         btni = &pci->hli.btnit[2 * btns_per_group + highlight_event->buttonN - 1];
1668                                                 }
1669
1670                                                 if (btni && btni->btn_coln != 0) {
1671                                                         // get and set clut for actual button
1672                                                         unsigned char tmp, tmp2;
1673                                                         struct ddvd_color colneu;
1674                                                         int i;
1675                                                         msg = DDVD_COLORTABLE_UPDATE;
1676                                                         if (ddvd_screeninfo_bypp == 1)
1677                                                                 safe_write(message_pipe, &msg, sizeof(int));
1678                                                         for (i = 0; i < 4; i++) {
1679                                                                 tmp = ((pci->hli.btn_colit.btn_coli[btni->btn_coln - 1][0]) >> (16 + 4 * i)) & 0xf;
1680                                                                 tmp2 = ((pci->hli.btn_colit.btn_coli[btni->btn_coln - 1][0]) >> (4 * i)) & 0xf;
1681                                                                 colneu.blue = ddvd_bl[i + 252] = ddvd_bl[tmp];
1682                                                                 colneu.green = ddvd_gn[i + 252] = ddvd_gn[tmp];
1683                                                                 colneu.red = ddvd_rd[i + 252] = ddvd_rd[tmp];
1684                                                                 colneu.trans = ddvd_tr[i + 252] = (0xF - tmp2) * 0x1111;
1685                                                                 if (ddvd_screeninfo_bypp == 1)
1686                                                                         safe_write(message_pipe, &colneu, sizeof(struct ddvd_color));
1687                                                         }
1688                                                         msg = DDVD_NULL;
1689                                                         //CHANGE COLORMAP
1690
1691                                                         memset(ddvd_lbb2, 0, ddvd_screeninfo_stride * ddvd_screeninfo_yres);    //clear backbuffer ..
1692                                                         //copy button into screen
1693                                                         for (i = btni->y_start; i < btni->y_end; i++) {
1694                                                                 if (ddvd_screeninfo_bypp == 1)
1695                                                                         memcpy(ddvd_lbb2 + btni->x_start + 720 * (i),
1696                                                                                ddvd_lbb + btni->x_start + 720 * (i),
1697                                                                                btni->x_end - btni->x_start);
1698                                                                 else
1699                                                                         ddvd_blit_to_argb(ddvd_lbb2 + btni->x_start * ddvd_screeninfo_bypp +
1700                                                                                           720 * ddvd_screeninfo_bypp * i,
1701                                                                                           ddvd_lbb + btni->x_start + 720 * (i),
1702                                                                                           btni->x_end - btni->x_start);
1703                                                         }
1704                                                         blit_area.x_start = btni->x_start;
1705                                                         blit_area.x_end = btni->x_end;
1706                                                         blit_area.y_start = btni->y_start;
1707                                                         blit_area.y_end = btni->y_end;
1708                                                         libdvdnav_workaround = 1;
1709                                                 }
1710                                         }
1711                                         if (!libdvdnav_workaround && dvdnav_get_highlight_area(pci, highlight_event->buttonN, 0, &hl) == DVDNAV_STATUS_OK) {
1712                                                 // get and set clut for actual button
1713                                                 unsigned char tmp, tmp2;
1714                                                 struct ddvd_color colneu;
1715                                                 int i;
1716                                                 msg = DDVD_COLORTABLE_UPDATE;
1717                                                 if (ddvd_screeninfo_bypp == 1)
1718                                                         safe_write(message_pipe, &msg, sizeof(int));
1719                                                 for (i = 0; i < 4; i++) {
1720                                                         tmp = ((hl.palette) >> (16 + 4 * i)) & 0xf;
1721                                                         tmp2 = ((hl.palette) >> (4 * i)) & 0xf;
1722                                                         colneu.blue = ddvd_bl[i + 252] = ddvd_bl[tmp];
1723                                                         colneu.green = ddvd_gn[i + 252] = ddvd_gn[tmp];
1724                                                         colneu.red = ddvd_rd[i + 252] = ddvd_rd[tmp];
1725                                                         colneu.trans = ddvd_tr[i + 252] = (0xF - tmp2) * 0x1111;
1726                                                         if (ddvd_screeninfo_bypp == 1)
1727                                                                 safe_write(message_pipe, &colneu, sizeof(struct ddvd_color));
1728                                                 }
1729                                                 msg = DDVD_NULL;
1730                                                 //CHANGE COLORMAP
1731
1732                                                 memset(ddvd_lbb2, 0, ddvd_screeninfo_stride * ddvd_screeninfo_yres);    //clear backbuffer ..
1733                                                 //copy button into screen
1734                                                 for (i = hl.sy; i < hl.ey; i++) {
1735                                                         if (ddvd_screeninfo_bypp == 1)
1736                                                                 memcpy(ddvd_lbb2 + hl.sx + 720 * (i),
1737                                                                        ddvd_lbb + hl.sx + 720 * (i), hl.ex - hl.sx);
1738                                                         else
1739                                                                 ddvd_blit_to_argb(ddvd_lbb2 + hl.sx * ddvd_screeninfo_bypp + 720 * ddvd_screeninfo_bypp * i,
1740                                                                                   ddvd_lbb + hl.sx + 720 * (i), hl.ex - hl.sx);
1741                                                 }
1742                                                 blit_area.x_start = hl.sx;
1743                                                 blit_area.x_end = hl.ex;
1744                                                 blit_area.y_start = hl.sy;
1745                                                 blit_area.y_end = hl.ey;
1746                                                 libdvdnav_workaround = 1;
1747                                         }
1748                                         if (!libdvdnav_workaround)
1749                                                 memset(ddvd_lbb2, 0, ddvd_screeninfo_stride * ddvd_screeninfo_yres);    //clear backbuffer .. 
1750                                         else
1751                                         {
1752                                                 int y_source = ddvd_have_ntsc ? 480 : 576; // correct ntsc overlay
1753                                                 int x_offset = calc_x_scale_offset(dvd_aspect, tv_mode, tv_mode2, tv_aspect);
1754                                                 int y_offset = calc_y_scale_offset(dvd_aspect, tv_mode, tv_mode2, tv_aspect);
1755
1756                                                 uint64_t start=ddvd_get_time();
1757                                                 int resized = 0;
1758
1759                                                 if ((x_offset != 0 || y_offset != 0 || y_source != ddvd_screeninfo_yres || ddvd_screeninfo_xres != 720) && !playerconfig->canscale)
1760                                                 {
1761 //                                                      printf("resizing\n");
1762                                                         resized = 1;
1763                                                         blit_area = ddvd_resize_pixmap(ddvd_lbb2, 720, y_source, ddvd_screeninfo_xres, ddvd_screeninfo_yres, x_offset, y_offset, blit_area.x_start, blit_area.x_end, blit_area.y_start, blit_area.y_end, ddvd_screeninfo_bypp); // resize
1764                                                 }
1765
1766                                                 blit_area.width = ddvd_screeninfo_xres;
1767                                                 blit_area.height = ddvd_screeninfo_yres;
1768
1769                                                 if (resized)
1770                                                 {
1771                                                         blit_area.x_offset = 0;
1772                                                         blit_area.y_offset = 0;
1773                                                 } else
1774                                                 {
1775                                                         blit_area.x_offset = x_offset;
1776                                                         blit_area.y_offset = y_offset;
1777                                                 }
1778                                                 memcpy(p_lfb, ddvd_lbb2, ddvd_screeninfo_xres * ddvd_screeninfo_yres * ddvd_screeninfo_bypp); //copy backbuffer into screen
1779                                                 //printf("needed time for resizing: %d ms\n",(int)(ddvd_get_time()-start));
1780                                                 //printf("destination area to blit: %d %d %d %d\n",blit_area.x_start,blit_area.x_end,blit_area.y_start,blit_area.y_end);
1781                                                 msg = DDVD_SCREEN_UPDATE;
1782                                                 safe_write(message_pipe, &msg, sizeof(int));
1783                                                 safe_write(message_pipe, &blit_area, sizeof(struct ddvd_resize_return));
1784                                                 memcpy(&last_blit_area,&blit_area,sizeof(struct ddvd_resize_return)); // safe blit area for next wipe
1785                                         }
1786                                 } else {
1787                                         ddvd_clear_buttons = 0;
1788                                         //printf("clear buttons\n");
1789                                 }
1790                                 break;
1791
1792                         case DVDNAV_VTS_CHANGE:
1793                                 {
1794                                         /* Some status information like video aspect and video scale permissions do
1795                                          * not change inside a VTS. Therefore we will set it new at this place */
1796                                         ddvd_play_empty(FALSE);
1797                                         audio_lock = 0; // reset audio & spu lock
1798                                         spu_lock = 0;
1799                                         for ( i = 0; i < MAX_AUDIO; i++)
1800                                                 playerconfig->audio_format[i] = -1;
1801                                         // fill spu_map with data
1802                                         int count_tmp,spu_tmp;
1803                                         for (count_tmp = 0; count_tmp < MAX_SPU; count_tmp++)
1804                                                 playerconfig->spu_map[count_tmp] = -1;
1805                                         for (count_tmp = 0; count_tmp < MAX_SPU; count_tmp++)
1806                                         {
1807                                                 spu_tmp = dvdnav_get_spu_logical_stream(dvdnav, count_tmp);
1808                                                 if (spu_tmp >= 0 && spu_tmp < MAX_SPU)
1809                                                         playerconfig->spu_map[spu_tmp] = count_tmp;
1810                                         }
1811                                         
1812                                         dvd_aspect = dvdnav_get_video_aspect(dvdnav);
1813                                         dvd_scale_perm = dvdnav_get_video_scale_permission(dvdnav);
1814                                         tv_scale = ddvd_check_aspect(dvd_aspect, dvd_scale_perm, tv_aspect, tv_mode);
1815                                         //printf("DVD Aspect: %d TV Aspect: %d Scale: %d Allowed: %d\n",dvd_aspect,tv_aspect,tv_scale,dvd_scale_perm);
1816                                         
1817                                         // resuming a dvd ?
1818                                         if (playerconfig->should_resume && first_vts_change) {
1819                                                 first_vts_change = 0;
1820                                                 int title_numbers,part_numbers;
1821                                                 dvdnav_get_number_of_titles(dvdnav, &title_numbers);
1822                                                 dvdnav_get_number_of_parts(dvdnav, playerconfig->resume_title, &part_numbers);
1823                                                 if (playerconfig->resume_title <= title_numbers && playerconfig->resume_title > 0 && playerconfig->resume_chapter <= part_numbers && playerconfig->resume_chapter > 0) {
1824                                                         dvdnav_part_play(dvdnav, playerconfig->resume_title, playerconfig->resume_chapter);
1825                                                         next_cell_change = 1;
1826                                                 } else {
1827                                                         playerconfig->should_resume = 0;
1828                                                         playerconfig->resume_title = 0;
1829                                                         playerconfig->resume_chapter = 0;
1830                                                         playerconfig->resume_block = 0;
1831                                                         playerconfig->resume_audio_id = 0;
1832                                                         playerconfig->resume_audio_lock = 0;
1833                                                         playerconfig->resume_spu_id = 0;
1834                                                         playerconfig->resume_spu_lock = 0;                                                      
1835                                                         perror("DVD resuming failed");
1836                                                 }
1837                                                 
1838                                                 
1839                                         }
1840                                 }
1841                                 break;
1842
1843                         case DVDNAV_CELL_CHANGE:
1844                                 {
1845                                         /* Store new cell information */
1846                                         memcpy(&ddvd_lastCellEventInfo, buf, sizeof(dvdnav_cell_change_event_t));
1847
1848                                         if ((ddvd_still_frame & CELL_STILL) && ddvd_iframesend == 0 && ddvd_last_iframe_len)
1849                                                 ddvd_iframesend = 1;
1850
1851                                         ddvd_still_frame = (dvdnav_get_next_still_flag(dvdnav) != 0) ? CELL_STILL : 0;
1852                                         
1853                                         // resuming a dvd ?
1854                                         if (playerconfig->should_resume && next_cell_change) {
1855                                                 next_cell_change = 0;
1856                                                 playerconfig->should_resume = 0;
1857                                                 if (dvdnav_sector_search(dvdnav, playerconfig->resume_block, SEEK_SET) != DVDNAV_STATUS_OK)
1858                                                 {
1859                                                         perror("DVD resuming failed");
1860                                                 } else {
1861                                                         audio_id = playerconfig->resume_audio_id;
1862                                                         audio_lock = 1;//playerconfig->resume_audio_lock;
1863                                                         spu_active_id = playerconfig->resume_spu_id;
1864                                                         spu_lock = 1;//playerconfig->resume_spu_lock;
1865                                                         report_audio_info = 1;
1866                                                         uint16_t spu_lang = 0xFFFF;
1867                                                         int spu_id_logical, count_tmp;
1868                                                         count_tmp = spu_active_id;
1869                                                         while (count_tmp >= 0)
1870                                                         {
1871                                                                 spu_id_logical = playerconfig->spu_map[count_tmp];
1872                                                                 if (spu_id_logical >= 0)
1873                                                                         count_tmp = 0;
1874                                                                 count_tmp--;
1875                                                         }
1876                                                         spu_lang = dvdnav_spu_stream_to_lang(dvdnav, (spu_id_logical >= 0 ? spu_id_logical : spu_active_id) & 0x1F);
1877                                                         if (spu_lang == 0xFFFF) {
1878                                                                 spu_lang = 0x2D2D;      // SPU "off" 
1879                                                                 spu_active_id = -1;
1880                                                                 spu_id_logical = -1;
1881                                                         }
1882                                                         msg = DDVD_SHOWOSD_SUBTITLE;
1883                                                         int report_spu = spu_id_logical > 31 ? -1 : spu_id_logical;
1884                                                         safe_write(message_pipe, &msg, sizeof(int));
1885                                                         safe_write(message_pipe, &report_spu, sizeof(int));
1886                                                         safe_write(message_pipe, &spu_lang, sizeof(uint16_t));
1887                                                         msg = DDVD_SHOWOSD_TIME; // send new position to the frontend
1888                                                 }
1889                                                 playerconfig->resume_title = 0;
1890                                                 playerconfig->resume_chapter = 0;
1891                                                 playerconfig->resume_block = 0;
1892                                                 playerconfig->resume_audio_id = 0;
1893                                                 playerconfig->resume_audio_lock = 0;
1894                                                 playerconfig->resume_spu_id = 0;
1895                                                 playerconfig->resume_spu_lock = 0;
1896                                         }
1897                                         // multiple angels ?
1898                                         int num = 0, current = 0;
1899                                         dvdnav_get_angle_info(dvdnav, &current, &num);
1900                                         msg = DDVD_SHOWOSD_ANGLE;
1901                                         safe_write(message_pipe, &msg, sizeof(int));
1902                                         safe_write(message_pipe, &current, sizeof(int));
1903                                         safe_write(message_pipe, &num, sizeof(int));
1904                                 }
1905                                 break;
1906
1907                         case DVDNAV_NAV_PACKET:
1908                                 /* A NAV packet provides PTS discontinuity information, angle linking information and
1909                                  * button definitions for DVD menus. We have to handle some stilframes here */
1910                                 pci = dvdnav_get_current_nav_pci(dvdnav);
1911                                 dsi = dvdnav_get_current_nav_dsi(dvdnav);
1912
1913                                 if ((ddvd_still_frame & NAV_STILL) && ddvd_iframesend == 0 && ddvd_last_iframe_len)
1914                                         ddvd_iframesend = 1;
1915
1916                                 if (dsi->vobu_sri.next_video == 0xbfffffff)
1917                                         ddvd_still_frame |= NAV_STILL;  //|= 1;
1918                                 else
1919                                         ddvd_still_frame &= ~NAV_STILL; //&= 1;
1920                                 break;
1921
1922                         case DVDNAV_HOP_CHANNEL:
1923                                 /* This event is issued whenever a non-seamless operation has been executed.
1924                                  * So we drop our buffers */
1925                                 ddvd_play_empty(TRUE);
1926                                 break;
1927
1928                         case DVDNAV_STOP:
1929                                 /* Playback should end here. */
1930                                 printf("DVDNAV_STOP\n");
1931                                 playerconfig->resume_title = 0;
1932                                 playerconfig->resume_chapter = 0;
1933                                 playerconfig->resume_block = 0;
1934                                 playerconfig->resume_audio_id = 0;
1935                                 playerconfig->resume_audio_lock = 0;
1936                                 playerconfig->resume_spu_id = 0;
1937                                 playerconfig->resume_spu_lock = 0;
1938                                 finished = 1;
1939                                 break;
1940
1941                         default:
1942                                 printf("Unknown event (%i)\n", event);
1943                                 finished = 1;
1944                                 break;
1945                         }
1946                 }
1947                 // spu handling
1948 #if CONFIG_API_VERSION == 1
1949                 unsigned int tpts;
1950                 if (ioctl(ddvd_output_fd, VIDEO_GET_PTS, &tpts) < 0)
1951                         perror("VIDEO_GET_PTS");
1952                 pts = (unsigned long long)tpts;
1953                 signed long long diff = spu_backpts[0] - pts;
1954                 if (ddvd_spu_backnr > 0 && diff <= 0xFF)        // we only have a 32bit pts on vulcan/pallas (instead of 33bit) so we need some tolerance on syncing SPU for menus
1955                                                                                                         // so on non animated menus the buttons will be displayed to soon, but we we have to accept it
1956 #else
1957                 if (ioctl(ddvd_fdvideo, VIDEO_GET_PTS, &pts) < 0)
1958                         perror("VIDEO_GET_PTS");
1959 //              printf("pts %d, dvd_spu_backnr = %d, spu_backpts = %d\n", 
1960 //                      (int)pts, (int)ddvd_spu_backnr, (int) spu_backpts[0]);
1961                 struct video_event event;
1962                 if (!ioctl(ddvd_fdvideo, VIDEO_GET_EVENT, &event))
1963                 {
1964                         switch(event.type)
1965                         {
1966                         case VIDEO_EVENT_SIZE_CHANGED:
1967                         {
1968                                 struct ddvd_size_evt evt;
1969                                 int msg = DDVD_SIZE_CHANGED;
1970                                 evt.width = event.u.size.w;
1971                                 evt.height = event.u.size.h;
1972                                 evt.aspect = event.u.size.aspect_ratio;
1973                                 safe_write(message_pipe, &msg, sizeof(int));
1974                                 safe_write(message_pipe, &evt, sizeof(evt));
1975                                 break;
1976                         }
1977                         case VIDEO_EVENT_FRAME_RATE_CHANGED:
1978                         {
1979                                 struct ddvd_framerate_evt evt;
1980                                 int msg = DDVD_FRAMERATE_CHANGED;
1981                                 evt.framerate = event.u.frame_rate;
1982                                 safe_write(message_pipe, &msg, sizeof(int));
1983                                 safe_write(message_pipe, &evt, sizeof(evt));
1984                                 break;
1985                         }
1986                         case 16: // VIDEO_EVENT_PROGRESSIVE_CHANEGD
1987                         {
1988                                 struct ddvd_progressive_evt evt;
1989                                 int msg = DDVD_PROGRESSIVE_CHANGED;
1990                                 evt.progressive = event.u.frame_rate;
1991                                 safe_write(message_pipe, &msg, sizeof(int));
1992                                 safe_write(message_pipe, &evt, sizeof(evt));
1993                                 break;
1994                         }
1995                         }
1996                 }
1997                 if (ddvd_spu_backnr > 0 && pts >= spu_backpts[0])
1998 #endif
1999                 {
2000                         int tmplen = (spu_backbuffer[0] << 8 | spu_backbuffer[1]);
2001                         
2002                         // we dont support overlapping spu timers yet, so we have to clear the screen if there is such a case
2003                         int whole_screen = 0;
2004                         if (ddvd_spu_timer_active || last_spu_return.display_time < 0)
2005                                 memset(p_lfb, 0, ddvd_screeninfo_stride * ddvd_screeninfo_yres);        //clear screen ..
2006                                         /* the last subtitle's bbox is still in last_spu_return, so this subtitle will enlarge this bbox. */
2007                         
2008                         memset(ddvd_lbb, 0, 720 * 576); //clear backbuffer .. 
2009 //                      printf("[SPU] previous bbox: %d %d %d %d\n",
2010 //                              last_spu_return.x_start, last_spu_return.x_end, 
2011 //                              last_spu_return.y_start, last_spu_return.y_end);
2012                         last_spu_return = merge(last_spu_return, ddvd_spu_decode_data(spu_backbuffer, tmplen)); // decode
2013 //                      printf("[SPU] merged   bbox: %d %d %d %d\n",
2014 //                              last_spu_return.x_start, last_spu_return.x_end, 
2015 //                              last_spu_return.y_start, last_spu_return.y_end);
2016                         ddvd_display_time = last_spu_return.display_time;
2017                         ddvd_lbb_changed = 1;
2018                         
2019                         struct ddvd_color colneu;
2020                         int ctmp;
2021                         msg = DDVD_COLORTABLE_UPDATE;
2022                         if (ddvd_screeninfo_bypp == 1)
2023                                 safe_write(message_pipe, &msg, sizeof(int));
2024                         for (ctmp = 0; ctmp < 4; ctmp++) {
2025                                 colneu.blue = ddvd_bl[ctmp + 252];
2026                                 colneu.green = ddvd_gn[ctmp + 252];
2027                                 colneu.red = ddvd_rd[ctmp + 252];
2028                                 colneu.trans = ddvd_tr[ctmp + 252];
2029                                 if (ddvd_screeninfo_bypp == 1)
2030                                         safe_write(message_pipe, &colneu, sizeof(struct ddvd_color));
2031                         }
2032                         msg = DDVD_NULL;
2033
2034                         memcpy(spu_backbuffer, spu_backbuffer + tmplen, ddvd_spu_backptr - tmplen);     // delete SPU packet
2035                         int i;
2036                         for (i = 0; i < NUM_SPU_BACKBUFFER - 1; ++i)
2037                                 spu_backpts[i] = spu_backpts[i + 1];
2038                                 
2039                         ddvd_spu_backnr--;
2040                         ddvd_spu_backptr -= tmplen;
2041                         
2042 //                      printf("[SPU] backnr = %d, backptr = %d\n", ddvd_spu_backnr, ddvd_spu_backptr);
2043
2044                         // set timer
2045                         if (ddvd_display_time > 0) {
2046                                 ddvd_spu_timer_active = 1;
2047                                 ddvd_spu_timer_end = ddvd_get_time() + (ddvd_display_time * 10);        //ms
2048                         } else
2049                                 ddvd_spu_timer_active = 0;
2050
2051                         // dont display SPU if spu sets the HIDE command or the actual SPU track is marked as hide (bit 7) and the packet had no FORCE command
2052                         if (last_spu_return.force_hide == SPU_HIDE || ((dvdnav_get_active_spu_stream(dvdnav) & 0x80) && last_spu_return.force_hide != SPU_FORCE && !spu_lock)) {
2053                                 ddvd_lbb_changed = 0;
2054                                 ddvd_spu_timer_active = 0;
2055                         }
2056
2057                         pci = dvdnav_get_current_nav_pci(dvdnav);       //update highlight buttons
2058                         dsi = dvdnav_get_current_nav_dsi(dvdnav);
2059                         if (pci->hli.hl_gi.btn_ns > 0) {
2060                                 dvdnav_get_current_highlight(dvdnav, &buttonN);
2061                                 if (buttonN == 0)
2062                                         buttonN = 1; 
2063                                 if (buttonN > pci->hli.hl_gi.btn_ns)
2064                                         buttonN = pci->hli.hl_gi.btn_ns; 
2065                                 dvdnav_button_select(dvdnav, pci, buttonN);
2066                                 ddvd_lbb_changed = 0;
2067                                 in_menu = 1;
2068                         }
2069                 }
2070
2071                 if (!in_menu) {
2072                         if (!pci)
2073                                 pci = dvdnav_get_current_nav_pci(dvdnav);
2074
2075                         in_menu = pci && pci->hli.hl_gi.btn_ns > 0;
2076                 }
2077
2078                 if ((dvdnav_is_domain_vmgm(dvdnav) || dvdnav_is_domain_vtsm(dvdnav) || in_menu) && !playerconfig->in_menu) {
2079                         int bla = DDVD_MENU_OPENED;
2080                         safe_write(message_pipe, &bla, sizeof(int));
2081                         playerconfig->in_menu = 1;
2082                 } else if (!(dvdnav_is_domain_vmgm(dvdnav) || dvdnav_is_domain_vtsm(dvdnav) || in_menu) && playerconfig->in_menu) {
2083                         int bla = DDVD_MENU_CLOSED;
2084                         safe_write(message_pipe, &bla, sizeof(int));
2085                         playerconfig->in_menu = 0;
2086                 }
2087
2088                 if (ddvd_wait_for_user) {
2089                         struct pollfd pfd[1];   // make new pollfd array
2090                         pfd[0].fd = key_pipe;
2091                         pfd[0].events = POLLIN | POLLPRI | POLLERR;
2092                         poll(pfd, 1, -1);
2093                 }
2094                 //Userinput
2095                 if (ddvd_readpipe(key_pipe, &rccode, sizeof(int), 0) == sizeof(int)) {
2096                         int keydone = 1;
2097
2098                         if (!dsi)
2099                                 dsi = dvdnav_get_current_nav_dsi(dvdnav);
2100
2101                         if (buttonN == -1)
2102                                 dvdnav_get_current_highlight(dvdnav, &buttonN);
2103
2104                         switch (rccode) // actions inside and outside of menu
2105                         {
2106                                 case DDVD_SET_MUTE:
2107                                         ismute = 1;
2108                                         break;
2109                                 case DDVD_UNSET_MUTE:
2110                                         ismute = 0;
2111                                         break;
2112                                 default:
2113                                         keydone = 0;
2114                                         break;
2115                         }
2116
2117                         if (!keydone && in_menu) {
2118                                 switch (rccode) //Actions inside a Menu
2119                                 {
2120                                 case DDVD_KEY_UP:       //Up
2121                                         dvdnav_upper_button_select(dvdnav, pci);
2122                                         break;
2123                                 case DDVD_KEY_DOWN:     //Down
2124                                         dvdnav_lower_button_select(dvdnav, pci);
2125                                         break;
2126                                 case DDVD_KEY_LEFT:     //left
2127                                         dvdnav_left_button_select(dvdnav, pci);
2128                                         break;
2129                                 case DDVD_KEY_RIGHT:    //right
2130                                         dvdnav_right_button_select(dvdnav, pci);
2131                                         break;
2132                                 case DDVD_KEY_OK:       //OK
2133                                         ddvd_wait_for_user = 0;
2134                                         memset(p_lfb, 0, ddvd_screeninfo_stride * ddvd_screeninfo_yres);        //clear screen ..
2135                                         memset(ddvd_lbb, 0, 720 * 576); //clear backbuffer
2136                                         memset(ddvd_lbb2, 0, 720 * 576 * ddvd_screeninfo_bypp); //clear 2nd backbuffer
2137                                         blit_area.x_start = blit_area.y_start = 0;
2138                                         blit_area.x_end = ddvd_screeninfo_xres - 1;
2139                                         blit_area.y_end = ddvd_screeninfo_yres - 1;
2140                                         blit_area.x_offset = 0;
2141                                         blit_area.y_offset = 0;
2142                                         blit_area.width = ddvd_screeninfo_xres;
2143                                         blit_area.height = ddvd_screeninfo_yres;
2144                                         msg = DDVD_SCREEN_UPDATE;
2145                                         safe_write(message_pipe, &msg, sizeof(int));
2146                                         safe_write(message_pipe, &blit_area, sizeof(struct ddvd_resize_return));
2147                                         
2148                                         ddvd_clear_buttons = 1;
2149                                         dvdnav_button_activate(dvdnav, pci);
2150                                         ddvd_play_empty(TRUE);
2151                                         if (ddvd_wait_timer_active)
2152                                                 ddvd_wait_timer_active = 0;
2153                                         break;
2154                                 case DDVD_KEY_MENU:     //Dream
2155                                         if (dvdnav_menu_call(dvdnav, DVD_MENU_Root) == DVDNAV_STATUS_OK)
2156                                                 ddvd_play_empty(TRUE);
2157                                         break;
2158                                 case DDVD_KEY_AUDIOMENU:        //Audio
2159                                         if (dvdnav_menu_call(dvdnav, DVD_MENU_Audio) == DVDNAV_STATUS_OK)
2160                                                 ddvd_play_empty(TRUE);
2161                                         break;
2162                                 case DDVD_KEY_EXIT:     //Exit
2163                                         {
2164                                                 printf("DDVD_KEY_EXIT (menu)\n");
2165                                                 playerconfig->resume_title = 0;
2166                                                 playerconfig->resume_chapter = 0;
2167                                                 playerconfig->resume_block = 0;
2168                                                 playerconfig->resume_audio_id = 0;
2169                                                 playerconfig->resume_audio_lock = 0;
2170                                                 playerconfig->resume_spu_id = 0;
2171                                                 playerconfig->resume_spu_lock = 0;
2172                                                 finished = 1;
2173                                         }
2174                                         break;                                          
2175                                 case DDVD_SKIP_FWD:
2176                                 case DDVD_SKIP_BWD:
2177                                 case DDVD_SET_TITLE:
2178                                 case DDVD_SET_CHAPTER:
2179                                         // we must empty the pipe here...
2180                                         ddvd_readpipe(key_pipe, &keydone, sizeof(int), 1);
2181                                 default:
2182                                         break;
2183                                 }
2184                         } else if (!keydone)    //Actions inside a Movie
2185                         {
2186                                 switch (rccode) //Main Actions
2187                                 {
2188                                 case DDVD_KEY_PREV_CHAPTER:     //left
2189                                         {
2190                                                 int titleNo, chapterNumber, chapterNo;
2191                                                 dvdnav_current_title_info(dvdnav, &titleNo, &chapterNo);
2192                                                 dvdnav_get_number_of_parts(dvdnav, titleNo, &chapterNumber);
2193                                                 chapterNo--;
2194                                                 if (chapterNo > chapterNumber)
2195                                                         chapterNo = 1;
2196                                                 if (chapterNo <= 0)
2197                                                         chapterNo = chapterNumber;
2198                                                 dvdnav_part_play(dvdnav, titleNo, chapterNo);
2199                                                 ddvd_play_empty(TRUE);
2200                                                 msg = DDVD_SHOWOSD_TIME;
2201                                                 break;
2202                                         }
2203                                 case DDVD_KEY_NEXT_CHAPTER:     //right
2204                                         {
2205                                                 int titleNo, chapterNumber, chapterNo;
2206                                                 dvdnav_current_title_info(dvdnav, &titleNo, &chapterNo);
2207                                                 dvdnav_get_number_of_parts(dvdnav, titleNo, &chapterNumber);
2208                                                 chapterNo++;
2209                                                 if (chapterNo > chapterNumber)
2210                                                         chapterNo = 1;
2211                                                 if (chapterNo <= 0)
2212                                                         chapterNo = chapterNumber;
2213                                                 dvdnav_part_play(dvdnav, titleNo, chapterNo);
2214                                                 ddvd_play_empty(TRUE);
2215                                                 msg = DDVD_SHOWOSD_TIME;
2216                                                 break;
2217                                         }
2218                                 case DDVD_KEY_PREV_TITLE:
2219                                         {
2220                                                 int titleNo, titleNumber, chapterNo;
2221                                                 dvdnav_current_title_info(dvdnav, &titleNo, &chapterNo);
2222                                                 dvdnav_get_number_of_titles(dvdnav, &titleNumber);
2223                                                 titleNo--;
2224                                                 if (titleNo > titleNumber)
2225                                                         titleNo = 1;
2226                                                 if (titleNo <= 0)
2227                                                         titleNo = titleNumber;
2228                                                 dvdnav_part_play(dvdnav, titleNo, 1);
2229                                                 ddvd_play_empty(TRUE);
2230                                                 msg = DDVD_SHOWOSD_TIME;
2231                                                 break;
2232                                         }
2233                                 case DDVD_KEY_NEXT_TITLE:
2234                                         {
2235                                                 int titleNo, titleNumber, chapterNo;
2236                                                 dvdnav_current_title_info(dvdnav, &titleNo, &chapterNo);
2237                                                 dvdnav_get_number_of_titles(dvdnav, &titleNumber);
2238                                                 titleNo++;
2239                                                 if (titleNo > titleNumber)
2240                                                         titleNo = 1;
2241                                                 if (titleNo <= 0)
2242                                                         titleNo = titleNumber;
2243                                                 dvdnav_part_play(dvdnav, titleNo, 1);
2244                                                 ddvd_play_empty(TRUE);
2245                                                 msg = DDVD_SHOWOSD_TIME;
2246                                                 break;
2247                                         }
2248                                 case DDVD_KEY_PAUSE:    // Pause
2249                                         {
2250                                                 if (ddvd_playmode == PLAY) {
2251                                                         ddvd_playmode = PAUSE;
2252                                                         if (ioctl(ddvd_fdaudio, AUDIO_PAUSE) < 0)
2253                                                                 perror("AUDIO_PAUSE");
2254                                                         if (ioctl(ddvd_fdvideo, VIDEO_FREEZE) < 0)
2255                                                                 perror("VIDEO_FREEZE");
2256                                                         msg = DDVD_SHOWOSD_STATE_PAUSE;
2257                                                         safe_write(message_pipe, &msg, sizeof(int));
2258                                                         break;
2259                                                 } else if (ddvd_playmode != PAUSE)
2260                                                         break;
2261                                                 // fall through to PLAY
2262                                         }
2263                                 case DDVD_KEY_PLAY:     // Play
2264                                         {
2265                                                 if (ddvd_playmode == PAUSE || ddvd_trickmode) {
2266                                                         ddvd_playmode = PLAY;
2267 key_play:
2268 #if CONFIG_API_VERSION == 1
2269                                                         ddvd_device_clear();
2270 #endif
2271                                                         if (ddvd_trickmode && !ismute)
2272                                                                 if (ioctl(ddvd_fdaudio, AUDIO_SET_MUTE, 0) < 0)
2273                                                                         perror("AUDIO_SET_MUTE");
2274                                                         ddvd_trickmode = TOFF;
2275                                                         if (ddvd_playmode == PLAY) {
2276                                                                 if (ioctl(ddvd_fdaudio, AUDIO_CONTINUE) < 0)
2277                                                                         perror("AUDIO_CONTINUE");
2278                                                                 if (ioctl(ddvd_fdvideo, VIDEO_CONTINUE) < 0)
2279                                                                         perror("VIDEO_CONTINUE");
2280                                                                 msg = DDVD_SHOWOSD_STATE_PLAY;
2281                                                                 safe_write(message_pipe, &msg, sizeof(int));
2282                                                         }
2283                                                         msg = DDVD_SHOWOSD_TIME;
2284                                                 }
2285                                                 break;
2286                                         }
2287                                 case DDVD_KEY_MENU:     //Dream
2288                                         if (dvdnav_menu_call(dvdnav, DVD_MENU_Root) == DVDNAV_STATUS_OK)
2289                                                 ddvd_play_empty(TRUE);
2290                                         break;
2291                                 case DDVD_KEY_AUDIOMENU:        //Audio
2292                                         if (dvdnav_menu_call(dvdnav, DVD_MENU_Audio) == DVDNAV_STATUS_OK)
2293                                                 ddvd_play_empty(TRUE);
2294                                         break;
2295                                 case DDVD_KEY_EXIT:     //Exit
2296                                         {
2297                                                 printf("DDVD_KEY_EXIT (menu)\n");
2298                                                 int resume_title, resume_chapter; //safe resume info
2299                                                 uint32_t resume_block, total_block;
2300                                                 if (dvdnav_current_title_info(dvdnav, &resume_title, &resume_chapter) && (0 != resume_title)) {
2301                                                         if(dvdnav_get_position (dvdnav, &resume_block, &total_block) == DVDNAV_STATUS_OK) {
2302                                                                 playerconfig->resume_title = resume_title;
2303                                                                 playerconfig->resume_chapter = resume_chapter;
2304                                                                 playerconfig->resume_block = resume_block;
2305                                                                 playerconfig->resume_audio_id = audio_id;
2306                                                                 playerconfig->resume_audio_lock = audio_lock;
2307                                                                 playerconfig->resume_spu_id = spu_active_id;
2308                                                                 playerconfig->resume_spu_lock = spu_lock;
2309                                                         } else perror("error getting resume position");
2310                                                 } perror("error getting resume position");                                      
2311                                                 finished = 1;
2312                                         }
2313                                         break;                                          
2314                                 case DDVD_KEY_FFWD:     //FastForward
2315                                 case DDVD_KEY_FBWD:     //FastBackward
2316                                         {
2317                                                 if (ddvd_trickmode == TOFF) {
2318                                                         if (ioctl(ddvd_fdaudio, AUDIO_SET_MUTE, 1) < 0)
2319                                                                 perror("AUDIO_SET_MUTE");
2320                                                         ddvd_trickspeed = 2;
2321                                                         ddvd_trickmode = (rccode == DDVD_KEY_FBWD ? FASTBW : FASTFW);
2322                                                 } else if (ddvd_trickmode == (rccode == DDVD_KEY_FBWD ? FASTFW : FASTBW)) {
2323                                                         ddvd_trickspeed /= 2;
2324                                                         if (ddvd_trickspeed == 1) {
2325                                                                 ddvd_trickspeed = 0;
2326                                                                 goto key_play;
2327                                                         }
2328                                                 } else if (ddvd_trickspeed < 64)
2329                                                         ddvd_trickspeed *= 2;
2330                                                 break;
2331                                         }
2332                                 case DDVD_KEY_AUDIO:    //jump to next audio track
2333                                         {
2334                                                 int count = 0;
2335                                                 audio_id = (audio_id == MAX_AUDIO-1 ? 0 : audio_id+1);
2336                                                 while (playerconfig->audio_format[audio_id] == -1 && count++ < MAX_AUDIO-1)
2337                                                 {
2338                                                         audio_id = (audio_id == 7 ? 0 : audio_id+1);
2339                                                 }
2340                                                 report_audio_info = 1;
2341                                                 ddvd_play_empty(TRUE);
2342                                                 audio_lock = 1;
2343                                                 ddvd_lpcm_count = 0;
2344                                                 break;
2345                                         }
2346                                 case DDVD_SET_AUDIO:    //change to given audio track
2347                                         {
2348                                                 int set_audio_id;
2349                                                 ddvd_readpipe(key_pipe, &set_audio_id, sizeof(int), 1);
2350                                                 printf("DDVD_SET_AUDIO %i (prev %i)\n", set_audio_id, audio_id);
2351                                                 if (set_audio_id < MAX_AUDIO && playerconfig->audio_format[audio_id] != -1)
2352                                                         audio_id = set_audio_id;
2353                                                 report_audio_info = 1;
2354                                                 ddvd_play_empty(TRUE);
2355                                                 audio_lock = 1;
2356                                                 ddvd_lpcm_count = 0;
2357                                                 break;
2358                                         }
2359                                 case DDVD_KEY_SUBTITLE: //jump to next spu track
2360                                 case DDVD_SET_SUBTITLE: //change to given spu track
2361                                         {
2362                                                 uint16_t spu_lang = 0xFFFF;
2363                                                 int spu_id_logical;
2364                                                 if (rccode == DDVD_KEY_SUBTITLE)
2365                                                 {
2366                                                         int count_tmp;
2367                                                         spu_id_logical = -1;
2368                                                         count_tmp = spu_active_id;
2369                                                         while (count_tmp >= 0)
2370                                                         {
2371                                                                 spu_id_logical = playerconfig->spu_map[count_tmp];
2372                                                                 if (spu_id_logical >= 0)
2373                                                                         count_tmp = 0;
2374                                                                 count_tmp--;
2375                                                         }
2376                                                         spu_id_logical++;
2377                                                         spu_active_id = dvdnav_get_spu_logical_stream(dvdnav, spu_id_logical);
2378                                                 }
2379                                                 else if (rccode == DDVD_SET_SUBTITLE)
2380                                                 {
2381                                                         ddvd_readpipe(key_pipe, &spu_id_logical, sizeof(int), 1);
2382                                                         printf("DDVD_SET_SUBTITLE %i (prev %i)\n", spu_id_logical, spu_active_id);
2383                                                         if (spu_id_logical < MAX_SPU && playerconfig->spu_map[spu_id_logical] > -1)
2384                                                                 spu_active_id = dvdnav_get_spu_logical_stream(dvdnav, spu_id_logical);
2385                                                 }
2386                                                 spu_lang = dvdnav_spu_stream_to_lang(dvdnav, (spu_id_logical >= 0 ? spu_id_logical : spu_active_id) & 0x1F);
2387                                                 if (spu_lang == 0xFFFF) {
2388                                                         spu_lang = 0x2D2D;      // SPU "off" 
2389                                                         spu_active_id = -1;
2390                                                         spu_id_logical = -1;
2391                                                 }
2392                                                 spu_lock = 1;
2393                                                 msg = DDVD_SHOWOSD_SUBTITLE;
2394                                                 int report_spu = spu_id_logical > 31 ? -1 : spu_id_logical;
2395                                                 safe_write(message_pipe, &msg, sizeof(int));
2396                                                 safe_write(message_pipe, &report_spu, sizeof(int));
2397                                                 safe_write(message_pipe, &spu_lang, sizeof(uint16_t));
2398                                                 break;
2399                                         }
2400                                 case DDVD_KEY_ANGLE: //change angle
2401                                         {
2402                                                 int num = 0, current = 0;
2403                                                 dvdnav_get_angle_info(dvdnav, &current, &num);
2404                                                 if(num != 0) {
2405                                                         current++;
2406                                                 if(current > num)
2407                                                         current = 1;
2408                                                 }
2409                                                 dvdnav_angle_change(dvdnav, current);
2410                                                 msg = DDVD_SHOWOSD_ANGLE;
2411                                                 safe_write(message_pipe, &msg, sizeof(int));
2412                                                 safe_write(message_pipe, &current, sizeof(int));
2413                                                 safe_write(message_pipe, &num, sizeof(int));
2414                                                 break;
2415                                         }
2416                                 case DDVD_GET_ANGLE: //frontend wants angle info
2417                                         {
2418                                                 int num = 0, current = 0;
2419                                                 dvdnav_get_angle_info(dvdnav, &current, &num);
2420                                                 msg = DDVD_SHOWOSD_ANGLE;
2421                                                 safe_write(message_pipe, &msg, sizeof(int));
2422                                                 safe_write(message_pipe, &current, sizeof(int));
2423                                                 safe_write(message_pipe, &num, sizeof(int));
2424                                                 break;
2425                                         }
2426                                 case DDVD_GET_TIME:     // frontend wants actual time
2427                                         msg = DDVD_SHOWOSD_TIME;
2428                                         break;
2429                                 case DDVD_SKIP_FWD:
2430                                 case DDVD_SKIP_BWD:
2431                                         {
2432                                                 int skip;
2433                                                 ddvd_readpipe(key_pipe, &skip, sizeof(int), 1);
2434                                                 if (ddvd_trickmode == TOFF) {
2435                                                         uint32_t pos, len;
2436                                                         dvdnav_get_position(dvdnav, &pos, &len);
2437                                                         printf("DDVD_SKIP pos=%u len=%u \n", pos, len);
2438                                                         //90000 = 1 Sek.
2439                                                         if (!len)
2440                                                                 len = 1;
2441                                                         long long int posneu = ((pos * ddvd_lastCellEventInfo.pgc_length) / len) + (90000 * skip);
2442                                                         printf("DDVD_SKIP posneu1=%lld\n", posneu);
2443                                                         long long int posneu2 = posneu <= 0 ? 0 : (posneu * len) / ddvd_lastCellEventInfo.pgc_length;
2444                                                         printf("DDVD_SKIP posneu2=%lld\n", posneu2);
2445                                                         if (len && posneu2 && posneu2 >= len)   // reached end of movie
2446                                                         {
2447                                                                 posneu2 = len - 250;
2448                                                                 reached_eof = 1;
2449                                                         }
2450                                                         dvdnav_sector_search(dvdnav, posneu2, SEEK_SET);
2451                                                         ddvd_lpcm_count = 0;
2452                                                         msg = DDVD_SHOWOSD_TIME;
2453                                                 }
2454                                                 break;
2455                                         }
2456                                 case DDVD_SET_TITLE:
2457                                         {
2458                                                 int title, totalTitles;
2459                                                 ddvd_readpipe(key_pipe, &title, sizeof(int), 1);
2460                                                 dvdnav_get_number_of_titles(dvdnav, &totalTitles);
2461                                                 printf("DDVD_SET_TITLE %d/%d\n", title, totalTitles);
2462                                                 if (title <= totalTitles) {
2463                                                         dvdnav_part_play(dvdnav, title, 0);
2464                                                         ddvd_play_empty(TRUE);
2465                                                         msg = DDVD_SHOWOSD_TIME;
2466                                                 }
2467                                                 break;
2468                                         }
2469                                 case DDVD_SET_CHAPTER:
2470                                         {
2471                                                 int chapter, totalChapters, chapterNo, titleNo;
2472                                                 ddvd_readpipe(key_pipe, &chapter, sizeof(int), 1);
2473                                                 dvdnav_current_title_info(dvdnav, &titleNo, &chapterNo);
2474                                                 dvdnav_get_number_of_parts(dvdnav, titleNo, &totalChapters);
2475                                                 printf("DDVD_SET_CHAPTER %d/%d in title %d\n", chapter, totalChapters, titleNo);
2476                                                 if (chapter <= totalChapters) {
2477                                                         dvdnav_part_play(dvdnav, titleNo, chapter);
2478                                                         ddvd_play_empty(TRUE);
2479                                                         msg = DDVD_SHOWOSD_TIME;
2480                                                 }
2481                                                 break;
2482                                         }
2483                                 default:
2484                                         break;
2485                                 }
2486                         }
2487                 }
2488                 // spu handling
2489                 if (ddvd_lbb_changed == 1) {
2490                         
2491                         if (ddvd_screeninfo_bypp == 1)
2492                                 memcpy(ddvd_lbb2, ddvd_lbb, 720 * 576);
2493                         else {
2494                                 int i = 0;
2495                                 for (i = last_spu_return.y_start; i < last_spu_return.y_end; ++i)
2496                                         ddvd_blit_to_argb(ddvd_lbb2 + (i * 720 + last_spu_return.x_start) * ddvd_screeninfo_bypp, ddvd_lbb + i * 720 + last_spu_return.x_start, last_spu_return.x_end - last_spu_return.x_start);
2497                         }
2498                         //struct ddvd_resize_return blit_area;
2499                         blit_area.x_start = last_spu_return.x_start;
2500                         blit_area.x_end = last_spu_return.x_end;
2501                         blit_area.y_start = last_spu_return.y_start;
2502                         blit_area.y_end = last_spu_return.y_end;
2503                         if (!ddvd_spu_timer_active)
2504                         {
2505                                         /* in case this is the last action for this subtitle's bbox (i.e. no timer has been set), then we will clear the bbox.
2506                                            otherwise, we will leave it there, so it will be contained in the next update as well. */
2507                                 last_spu_return.x_start = last_spu_return.x_end = 0;
2508                                 last_spu_return.y_start = last_spu_return.y_end = 0;
2509                         }
2510
2511                         int y_source = ddvd_have_ntsc ? 480 : 576; // correct ntsc overlay
2512                         int x_offset = calc_x_scale_offset(dvd_aspect, tv_mode, tv_mode2, tv_aspect);
2513                         int y_offset = calc_y_scale_offset(dvd_aspect, tv_mode, tv_mode2, tv_aspect);
2514
2515                         uint64_t start=ddvd_get_time();