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