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