forgot to remove some debug code
[libdreamdvd.git] / main.c
1 /*
2  * DreamDVD V0.9 - DVD-Player for Dreambox
3  * Copyright (C) 2007 by Seddi
4  *
5  * This DVD Player is based upon the great work from the libdvdnav project,
6  * a52dec library, ffmpeg and the knowledge from all the people who made
7  * watching DVD within linux possible.
8  *
9  * DreamDVD is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * DreamDVD is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
22  *
23  * part of libdreamdvd
24  */
25
26 #include "main.h"
27 #include "mpegaudioenc.h"
28 #include "a52dec.h"
29
30 /*
31  * local helper functions
32  */
33 static ssize_t safe_write(int fd, const void *buf, size_t count)
34 {
35         const uint8_t *ptr = buf;
36         size_t written = 0;
37         ssize_t n;
38
39         while (written < count) {
40                 n = write(fd, &ptr[written], count - written);
41                 if (n < 0) {
42                         if (errno != EINTR) {
43                                 perror("write");
44                                 return written ? written : -1;
45                         }
46                 } else {
47                         written += n;
48                 }
49         }
50
51         return written;
52 }
53
54 static void write_string(const char *filename, const char *string)
55 {
56         FILE *f;
57
58         f = fopen(filename, "w");
59         if (f == NULL) {
60                 perror(filename);
61                 return;
62         }
63
64         fputs(string, f);
65         fclose(f);
66 }
67
68 static int open_pipe(int fd[2])
69 {
70         int flags;
71
72         fd[0] = fd[1] = -1;
73
74         if (pipe(fd) < 0) {
75                 perror("pipe");
76                 goto err;
77         }
78
79         flags = fcntl(fd[0], F_GETFL);
80         if (flags < 0) {
81                 perror("F_GETFL");
82                 goto err;
83         }
84         if (fcntl(fd[0], F_SETFL, flags | O_NONBLOCK) < 0) {
85                 perror("F_SETFL");
86                 goto err;
87         }
88
89         return 0;
90
91 err:
92         if (fd[0] != -1) {
93                 close(fd[0]);
94                 fd[0] = -1;
95         }
96         if (fd[1] != -1) {
97                 close(fd[1]);
98                 fd[1] = -1;
99         }
100
101         return -1;
102 }
103
104 /*
105  * external functions
106  */
107
108 // create ddvd handle and set defaults
109 struct ddvd *ddvd_create(void)
110 {
111         struct ddvd *pconfig;
112
113         pconfig = malloc(sizeof(struct ddvd));
114         if (pconfig == NULL) {
115                 perror("malloc");
116                 return NULL;
117         }
118
119         memset(pconfig, 0, sizeof(struct ddvd));
120
121         // defaults
122         ddvd_set_ac3thru(pconfig, 0);
123         ddvd_set_language(pconfig, "en");
124         ddvd_set_dvd_path(pconfig, "/dev/cdroms/cdrom0");
125         ddvd_set_video(pconfig, DDVD_4_3, DDVD_LETTERBOX, DDVD_PAL);
126         ddvd_set_lfb(pconfig, NULL, 720, 576, 1, 720);
127         struct ddvd_resume resume_info;
128         resume_info.title=resume_info.chapter=resume_info.block=resume_info.audio_id=resume_info.audio_lock=resume_info.spu_id=resume_info.spu_lock=0;
129         ddvd_set_resume_pos(pconfig, resume_info);
130         pconfig->should_resume = 0;
131         pconfig->next_time_update = 0;
132         strcpy(pconfig->title_string, "");
133
134         // open pipes
135         if (open_pipe(pconfig->key_pipe) < 0) {
136                 ddvd_close(pconfig);
137                 return NULL;
138         }
139         if (open_pipe(pconfig->message_pipe) < 0) {
140                 ddvd_close(pconfig);
141                 return NULL;
142         }
143
144         return pconfig;
145 }
146
147 // destroy ddvd handle
148 void ddvd_close(struct ddvd *pconfig)
149 {
150         if (pconfig->message_pipe[0] != -1)
151                 close(pconfig->message_pipe[0]);
152         if (pconfig->message_pipe[1] != -1)
153                 close(pconfig->message_pipe[1]);
154         if (pconfig->key_pipe[0] != -1)
155                 close(pconfig->key_pipe[0]);
156         if (pconfig->key_pipe[1] != -1)
157                 close(pconfig->key_pipe[1]);
158         if (pconfig->dvd_path != NULL)
159                 free(pconfig->dvd_path);
160
161         free(pconfig);
162 }
163
164 // get message_pipe fd for polling functions in the host app
165 int ddvd_get_messagepipe_fd(struct ddvd *pconfig)
166 {
167         return pconfig->message_pipe[0];
168 }
169
170 // set resume postion
171 void ddvd_set_resume_pos(struct ddvd *pconfig, struct ddvd_resume resume_info)
172 {
173         pconfig->resume_title = resume_info.title;
174         pconfig->resume_chapter = resume_info.chapter;
175         pconfig->resume_block = resume_info.block;
176         pconfig->should_resume = 1;
177         pconfig->resume_audio_id = resume_info.audio_id;
178         pconfig->resume_audio_lock = resume_info.audio_lock;
179         pconfig->resume_spu_id = resume_info.spu_id;
180         pconfig->resume_spu_lock = resume_info.spu_lock;
181 }
182
183 // set framebuffer options
184 void ddvd_set_lfb(struct ddvd *pconfig, unsigned char *lfb, int xres, int yres, int bypp, int stride)
185 {
186         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         safe_write(ddvd_output_fd, ddvd_startup_logo, sizeof(ddvd_startup_logo));
548 #endif
549 #endif
550
551         int audio_type = DDVD_AC3;
552
553 #if CONFIG_API_VERSION == 3
554         ddvd_set_pcr_offset();
555 #endif
556
557         uint8_t mem[DVD_VIDEO_LB_LEN];
558         uint8_t *buf = mem;
559         int result, event, len;
560
561         unsigned char lpcm_data[2048 * 6 * 6 /*4608 */ ];
562         int mpa_header_length;
563         int mpa_count, mpa_count2;
564         uint8_t mpa_data[2048 * 4];
565         int ac3_len;
566         int16_t ac3_tmp[2048 * 6 * 6];
567
568         ddvd_mpa_init(48000, 192000);   //init MPA Encoder with 48kHz and 192k Bitrate
569
570         int ac3thru = 1;
571         if (have_liba52) {
572                 state = a52_init(0);    //init AC3 Decoder 
573                 ac3thru = playerconfig->ac3thru;
574         }
575
576         char osdtext[512];
577         strcpy(osdtext, "");
578
579         int tv_aspect = playerconfig->aspect;   //0-> 4:3 lb 1-> 4:3 ps 2-> 16:9 3-> always 16:9
580         int tv_mode = playerconfig->tv_mode;
581         int dvd_aspect = 0;     //0-> 4:3 2-> 16:9
582         int dvd_scale_perm = 0;
583         int tv_scale = 0;       //0-> off 1-> letterbox 2-> panscan
584         int spu_active_id = -1;
585         int finished = 0;
586         int audio_id;
587         int report_audio_info = 0;
588         struct ddvd_spu_return last_spu_return;
589         struct ddvd_resize_return last_blit_area;
590         memcpy(&last_blit_area,&blit_area,sizeof(struct ddvd_resize_return));
591         last_spu_return.x_start = last_spu_return.y_start = 0;
592         last_spu_return.x_end = last_spu_return.y_end = 0;
593         
594         ddvd_trickmode = TOFF;
595         ddvd_trickspeed = 0;
596
597         int rccode;
598         int ismute = 0;
599
600         if (ac3thru) {
601                 if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)
602                         perror("AUDIO_SET_AV_SYNC");
603 #ifdef CONVERT_TO_DVB_COMPLIANT_AC3
604                 if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 0) < 0)  // AC3 (dvb compliant)
605 #else
606                 if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 3) < 0)  // AC3 VOB
607 #endif
608                         perror("AUDIO_SET_BYPASS_MODE");
609         } else {
610                 if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)
611                         perror("AUDIO_SET_AV_SYNC");
612                 if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 1) < 0)
613                         perror("AUDIO_SET_BYPASS_MODE");
614         }
615
616 #if CONFIG_API_VERSION == 1     
617         // set video system
618         int pal_ntsc = playerconfig->tv_system;
619         int saa;
620         if (pal_ntsc == 1)
621                 saa = SAA_NTSC;
622         else
623                 saa = SAA_PAL;
624         int saafd = open("/dev/dbox/saa0", O_RDWR);
625         if (saafd >= 0) {
626                 if (ioctl(saafd, SAAIOSENC, &saa) < 0)
627                         perror("SAAIOSENC");
628                 close(saafd);
629         }
630 #endif
631         
632         /* open dvdnav handle */
633         printf("Opening DVD...%s\n", playerconfig->dvd_path);
634         if (dvdnav_open(&dvdnav, playerconfig->dvd_path) != DVDNAV_STATUS_OK) {
635                 printf("Error on dvdnav_open\n");
636                 sprintf(osdtext, "Error: Cant open DVD Source: %s", playerconfig->dvd_path);
637                 msg = DDVD_SHOWOSD_STRING;
638                 safe_write(message_pipe, &msg, sizeof(int));
639                 safe_write(message_pipe, &osdtext, sizeof(osdtext));
640                 res = DDVD_FAIL_OPEN;
641                 goto err_dvdnav_open;
642         }
643
644         /* set read ahead cache usage to no */
645         if (dvdnav_set_readahead_flag(dvdnav, 0) != DVDNAV_STATUS_OK) {
646                 printf("Error on dvdnav_set_readahead_flag: %s\n", dvdnav_err_to_string(dvdnav));
647                 res = DDVD_FAIL_PREFS;
648                 goto err_dvdnav;
649         }
650
651         /* set the language */
652         if (dvdnav_menu_language_select(dvdnav, playerconfig->language) != DVDNAV_STATUS_OK ||
653             dvdnav_audio_language_select(dvdnav, playerconfig->language) != DVDNAV_STATUS_OK ||
654             dvdnav_spu_language_select(dvdnav, playerconfig->language) != DVDNAV_STATUS_OK) {
655                 printf("Error on setting languages: %s\n", dvdnav_err_to_string(dvdnav));
656                 res = DDVD_FAIL_PREFS;
657                 goto err_dvdnav;
658         }
659
660         /* set the PGC positioning flag to have position information relatively to the
661          * whole feature instead of just relatively to the current chapter */
662         if (dvdnav_set_PGC_positioning_flag(dvdnav, 1) != DVDNAV_STATUS_OK) {
663                 printf("Error on dvdnav_set_PGC_positioning_flag: %s\n", dvdnav_err_to_string(dvdnav));
664                 res = DDVD_FAIL_PREFS;
665                 goto err_dvdnav;
666         }
667
668         int audio_lock = 0;
669         int spu_lock = 0;
670         int audio_format[8] = { -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                                 // collect audio data
857                                 if (((buf[14 + 3]) & 0xF0) == 0xC0)
858                                         audio_format[(buf[14 + 3]) - 0xC0] = DDVD_MPEG;
859                                 if ((buf[14 + 3]) == 0xBD && ((buf[14 + buf[14 + 8] + 9]) & 0xF8) == 0x80)
860                                         audio_format[(buf[14 + buf[14 + 8] + 9]) - 0x80] = DDVD_AC3;
861                                 if ((buf[14 + 3]) == 0xBD && ((buf[14 + buf[14 + 8] + 9]) & 0xF8) == 0x88)
862                                         audio_format[(buf[14 + buf[14 + 8] + 9]) - 0x88] = DDVD_DTS;
863                                 if ((buf[14 + 3]) == 0xBD && ((buf[14 + buf[14 + 8] + 9]) & 0xF8) == 0xA0)
864                                         audio_format[(buf[14 + buf[14 + 8] + 9]) - 0xA0] = DDVD_LPCM;
865
866                                 if ((buf[14 + 3] & 0xF0) == 0xE0) {     // video
867                                         if (buf[14 + 7] & 128) {
868                                                 /* damn gcc bug */
869                                                 vpts = ((unsigned long long)(((buf[14 + 9] >> 1) & 7))) << 30;
870                                                 vpts |= buf[14 + 10] << 22;
871                                                 vpts |= (buf[14 + 11] >> 1) << 15;
872                                                 vpts |= buf[14 + 12] << 7;
873                                                 vpts |= (buf[14 + 14] >> 1);
874                                                 //printf("VPTS? %X\n",(int)vpts);
875                                         }
876 #if CONFIG_API_VERSION == 1
877                                         // Eliminate 00 00 01 B4 sequence error packet because it breaks the pallas mpeg decoder
878                                         // This is very strange because the 00 00 01 B4 is partly inside the header extension ...
879                                         if (buf[21] == 0x00 && buf[22] == 0x00 && buf[23] == 0x01 && buf[24] == 0xB4) {
880                                                 buf[21] = 0x01;
881                                         }
882                                         if (buf[22] == 0x00 && buf[23] == 0x00 && buf[24] == 0x01 && buf[25] == 0xB4) {
883                                                 buf[22] = 0x01;
884                                         }
885 #endif
886                                         // if we have 16:9 Zoom Mode on the DVD and we use a "always 16:9" mode on tv we have
887                                         // to patch the mpeg header and the Sequence Display Extension inside the Stream in some cases
888                                         if (dvd_aspect == 3 && (tv_aspect == DDVD_16_9 || tv_aspect == DDVD_16_9) && (tv_mode == DDVD_PAN_SCAN || tv_mode == DDVD_LETTERBOX)) {
889                                                 int z=0;
890                                                 for (z=0; z<2040; z++)
891                                                 {
892                                                         if (buf[z] == 0x0 && buf[z+1] == 0x0 && buf[z+2] ==0x01 && buf[z+3] == 0xB5 && (buf[z+4] == 0x22 || buf[z+4] == 0x23))
893                                                         {
894                                                                 buf[z+5]=0x22;
895                                                                 buf[z+5]=0x0B;
896                                                                 buf[z+6]=0x42;
897                                                                 buf[z+7]=0x12;
898                                                                 buf[z+8]=0x00;
899                                                         }
900                                                 }
901                                                 if (buf[33] == 0 && buf[33 + 1] == 0 && buf[33 + 2] == 1 && buf[33 + 3] == 0xB3) {
902                                                         buf[33 + 7] = (buf[33 + 7] & 0xF) + 0x30;
903                                                 }
904                                                 if (buf[36] == 0 && buf[36 + 1] == 0 && buf[36 + 2] == 1 && buf[36 + 3] == 0xB3) {
905                                                         buf[36 + 7] = (buf[36 + 7] & 0xF) + 0x30;
906                                                 }
907                                         }
908                         
909                                         // check yres for detecting ntsc/pal
910                                         if (ddvd_have_ntsc == -1) {
911                                                 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) 
912                                                         || (buf[36] == 0 && buf[36 + 1] == 0 && buf[36 + 2] == 1 && buf[36 + 3] == 0xB3 && ((buf[36+5] & 0xF) << 8) + buf[36+6] == 0x1E0))
913                                                         ddvd_have_ntsc = 1;
914                                                 else
915                                                         ddvd_have_ntsc = 0;
916                                         }
917
918                                         safe_write(ddvd_output_fd, buf + 14, 2048 - 14);
919
920                                         // 14+8 header_length
921                                         // 14+(header_length)+3  -> start mpeg header
922                                         // buf[14+buf[14+8]+3] start mpeg header
923
924                                         int datalen = (buf[19] + (buf[18] << 8) + 6) - buf[14 + 8];     // length mpeg packet
925                                         int data = buf[14 + buf[14 + 8] + 3];   // start mpeg packet(header)
926
927                                         int do_copy = (ddvd_iframerun == 0x01) && !(buf[data] == 0 && buf[data + 1] == 0 && buf[data + 2] == 1) ? 1 : 0;
928                                         int have_pictureheader = 0;
929                                         int haveslice = 0;
930                                         int setrun = 0;
931
932                                         while (datalen > 6) {
933                                                 if (buf[data] == 0 && buf[data + 1] == 0 && buf[data + 2] == 1) {
934                                                         if (buf[data + 3] == 0x00)      //picture
935                                                         {
936                                                                 if (!setrun) {
937                                                                         ddvd_iframerun = ((buf[data + 5] >> 3) & 0x07);
938                                                                         setrun = 1;
939                                                                 }
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                                                         {
952                                                                 ddvd_last_iframe_len = 0;       // clear iframe buffer
953                                                                 data += 7;
954                                                                 datalen -= 7;
955                                                         } else if (buf[data + 3] == 0xBE)       //padding stream
956                                                         {
957                                                                 break;
958                                                         } else if (0x01 <= buf[data + 3] && buf[data + 3] <= 0xaf)      //slice ?
959                                                         {
960                                                                 if (!have_pictureheader && ddvd_last_iframe_len == 0)
961                                                                         haveslice = 1;
962                                                         }
963                                                 }
964                                                 data++;
965                                                 datalen--;
966                                         }
967                                         if ((ddvd_iframerun <= 0x01 || do_copy) && ddvd_still_frame) {
968                                                 if (haveslice)
969                                                         ddvd_iframerun = 0xFF;
970                                                 else if (ddvd_last_iframe_len < (320 * 1024) - (buf[19] + (buf[18] << 8) + 6)) {
971                                                         memcpy(last_iframe + ddvd_last_iframe_len, buf + 14, buf[19] + (buf[18] << 8) + 6);
972                                                         ddvd_last_iframe_len += buf[19] + (buf[18] << 8) + 6;
973                                                 }
974                                         }
975                                 } else if ((buf[14 + 3]) == 0xC0 + audio_id)    // mpeg audio
976                                 {
977                                         if (audio_type != DDVD_MPEG) {
978                                                 //printf("Switch to MPEG Audio\n");
979                                                 if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)
980                                                         perror("AUDIO_SET_AV_SYNC");
981                                                 if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 1) < 0)
982                                                         perror("AUDIO_SET_BYPASS_MODE");
983                                                 audio_type = DDVD_MPEG;
984                                         }
985
986                                         if (buf[14 + 7] & 128) {
987                                                 /* damn gcc bug */
988                                                 apts = ((unsigned long long)(((buf[14 + 9] >> 1) & 7))) << 30;
989                                                 apts |= buf[14 + 10] << 22;
990                                                 apts |= (buf[14 + 11] >> 1) << 15;
991                                                 apts |= buf[14 + 12] << 7;
992                                                 apts |= (buf[14 + 14] >> 1);
993                                                 //printf("APTS? %X\n",(int)apts);
994                                         }
995
996                                         safe_write(ddvd_ac3_fd, buf + 14, buf[19] + (buf[18] << 8) + 6);
997                                 } else if ((buf[14 + 3]) == 0xBD && (buf[14 + buf[14 + 8] + 9]) == 0xA0 + audio_id)     // lpcm audio
998                                 {
999                                         if (audio_type != DDVD_LPCM) {
1000                                                 //printf("Switch to LPCM Audio\n");
1001                                                 if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)
1002                                                         perror("AUDIO_SET_AV_SYNC");
1003                                                 if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 1) < 0)
1004                                                         perror("AUDIO_SET_BYPASS_MODE");
1005                                                 audio_type = DDVD_LPCM;
1006                                                 ddvd_lpcm_count = 0;
1007                                         }
1008                                         if (buf[14 + 7] & 128) {
1009                                                 /* damn gcc bug */
1010                                                 apts = ((unsigned long long)(((buf[14 + 9] >> 1) & 7))) << 30;
1011                                                 apts |= buf[14 + 10] << 22;
1012                                                 apts |= (buf[14 + 11] >> 1) << 15;
1013                                                 apts |= buf[14 + 12] << 7;
1014                                                 apts |= (buf[14 + 14] >> 1);
1015                                                 //printf("APTS? %X\n",(int)apts);
1016                                         }
1017                                         int i = 0;
1018                                         char abuf[(((buf[18] << 8) | buf[19]) - buf[22] - 14)];
1019 #if BYTE_ORDER == BIG_ENDIAN
1020                                         // just copy, byte order is correct on ppc machines
1021                                         memcpy(abuf, buf + 14 + buf[14 + 8] + 9 + 7, (((buf[18] << 8) | buf[19]) - buf[22] - 14));
1022                                         i = (((buf[18] << 8) | buf[19]) - buf[22] - 14);
1023 #else
1024                                         // byte swapping .. we become the wrong byteorder on lpcm on the 7025
1025                                         while (i < (((buf[18] << 8) | buf[19]) - buf[22] - 14)) {
1026                                                 abuf[i + 0] = (buf[14 + buf[14 + 8] + 9 + 7 + i + 1]);
1027                                                 abuf[i + 1] = (buf[14 + buf[14 + 8] + 9 + 7 + i + 0]);
1028                                                 i += 2;
1029                                         }
1030 #endif
1031                                         // we will encode the raw lpcm data to mpeg audio and send them with pts
1032                                         // information to the decoder to get a sync. playing the pcm data via
1033                                         // oss will break the pic/sound sync. So believe it or not, this is the 
1034                                         // smartest way to get a synced lpcm track ;-)
1035                                         if (ddvd_lpcm_count == 0) {     // save mpeg header with pts
1036                                                 memcpy(mpa_data, buf + 14, buf[14 + 8] + 9);
1037                                                 mpa_header_length = buf[14 + 8] + 9;
1038                                         }
1039                                         if (ddvd_lpcm_count + i >= 4608) {      //we have to send 4608 bytes to the encoder
1040                                                 memcpy(lpcm_data + ddvd_lpcm_count, abuf, 4608 - ddvd_lpcm_count);
1041                                                 //encode
1042                                                 mpa_count = ddvd_mpa_encode_frame(mpa_data + mpa_header_length, 4608, lpcm_data);
1043                                                 //patch pes__packet_length
1044                                                 mpa_count = mpa_count + mpa_header_length - 6;
1045                                                 mpa_data[4] = mpa_count >> 8;
1046                                                 mpa_data[5] = mpa_count & 0xFF;
1047                                                 //patch header type to mpeg
1048                                                 mpa_data[3] = 0xC0;
1049                                                 //write
1050                                                 safe_write(ddvd_ac3_fd, mpa_data, mpa_count + mpa_header_length);
1051                                                 memcpy(lpcm_data, abuf + (4608 - ddvd_lpcm_count), i - (4608 - ddvd_lpcm_count));
1052                                                 ddvd_lpcm_count = i - (4608 - ddvd_lpcm_count);
1053                                                 memcpy(mpa_data, buf + 14, buf[14 + 8] + 9);
1054                                                 mpa_header_length = buf[14 + 8] + 9;
1055                                         } else {
1056                                                 memcpy(lpcm_data + ddvd_lpcm_count, abuf, i);
1057                                                 ddvd_lpcm_count += i;
1058                                         }
1059
1060                                         //safe_write(ddvd_ac3_fd, buf+14 , buf[19]+(buf[18]<<8)+6);
1061                                 } else if ((buf[14 + 3]) == 0xBD && (buf[14 + buf[14 + 8] + 9]) == 0x88 + audio_id) {   // dts audio
1062                                         if (audio_type != DDVD_DTS) {
1063                                                 //printf("Switch to DTS Audio (thru)\n");
1064                                                 if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)
1065                                                         perror("AUDIO_SET_AV_SYNC");
1066                                                 if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 5) < 0)
1067                                                         perror("AUDIO_SET_BYPASS_MODE");
1068                                                 audio_type = DDVD_DTS;
1069                                         }
1070
1071                                         if (buf[14 + 7] & 128) {
1072                                                 /* damn gcc bug */
1073                                                 apts = ((unsigned long long)(((buf[14 + 9] >> 1) & 7))) << 30;
1074                                                 apts |= buf[14 + 10] << 22;
1075                                                 apts |= (buf[14 + 11] >> 1) << 15;
1076                                                 apts |= buf[14 + 12] << 7;
1077                                                 apts |= (buf[14 + 14] >> 1);
1078                                                 //printf("APTS? %X\n",(int)apts);
1079                                         }
1080
1081                                         safe_write(ddvd_ac3_fd, buf + 14, buf[19] + (buf[18] << 8) + 6);        // not working yet ....
1082                                 } else if ((buf[14 + 3]) == 0xBD && (buf[14 + buf[14 + 8] + 9]) == 0x80 + audio_id) {   // ac3 audio
1083                                         if (audio_type != DDVD_AC3) {
1084                                                 //printf("Switch to AC3 Audio\n");
1085                                                 if (ac3thru || !have_liba52) {  // !have_liba52 and !ac3thru should never happen, but who knows ;)
1086                                                         if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)
1087                                                                 perror("AUDIO_SET_AV_SYNC");
1088 #ifdef CONVERT_TO_DVB_COMPLIANT_AC3
1089                                                         if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 0) < 0)  // AC3 (dvb compliant)
1090 #else
1091                                                         if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 3) < 0)  // AC3 VOB
1092 #endif
1093                                                                 perror("AUDIO_SET_BYPASS_MODE");
1094                                                 } else {
1095                                                         if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)
1096                                                                 perror("AUDIO_SET_AV_SYNC");
1097                                                         if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 1) < 0)
1098                                                                 perror("AUDIO_SET_BYPASS_MODE");
1099                                                 }
1100                                                 audio_type = DDVD_AC3;
1101                                         }
1102
1103                                         if (buf[14 + 7] & 128) {
1104                                                 /* damn gcc bug */
1105                                                 apts = ((unsigned long long)(((buf[14 + 9] >> 1) & 7))) << 30;
1106                                                 apts |= buf[14 + 10] << 22;
1107                                                 apts |= (buf[14 + 11] >> 1) << 15;
1108                                                 apts |= buf[14 + 12] << 7;
1109                                                 apts |= (buf[14 + 14] >> 1);
1110                                                 //printf("APTS? %X\n",(int)apts);
1111                                         }
1112
1113                                         if (ac3thru || !have_liba52) {  // !have_liba52 and !ac3thru should never happen, but who knows ;)
1114 #ifdef CONVERT_TO_DVB_COMPLIANT_AC3
1115                                                 unsigned short pes_len = (buf[14 + 4] << 8 | buf[14 + 5]);
1116                                                 pes_len -= 4;   // strip first 4 bytes of pes payload
1117                                                 buf[14 + 4] = pes_len >> 8;     // patch pes len
1118                                                 buf[15 + 4] = pes_len & 0xFF;
1119
1120                                                 safe_write(ddvd_ac3_fd, buf + 14, 9 + buf[14 + 8]);     // write pes_header
1121                                                 safe_write(ddvd_ac3_fd, buf + 14 + 9 + buf[14 + 8] + 4, pes_len - (3 + buf[14 + 8]));   // write pes_payload
1122 #else
1123                                                 safe_write(ddvd_ac3_fd, buf + 14, buf[19] + (buf[18] << 8) + 6);
1124 #endif
1125                                                 //fwrite(buf+buf[22]+27, 1, ((buf[18]<<8)|buf[19])-buf[22]-7, fac3); //debugwrite
1126                                         } else {
1127                                                 // a bit more funny than lpcm sound, because we do a complete recoding here
1128                                                 // we will decode the ac3 data to plain lpcm and will then encode to mpeg
1129                                                 // audio and send them with pts information to the decoder to get a sync.
1130
1131                                                 // decode and convert ac3 to raw lpcm
1132                                                 ac3_len = ddvd_ac3_decode(buf + buf[22] + 27, ((buf[18] << 8) | buf[19]) - buf[22] - 7, ac3_tmp);
1133
1134                                                 // save the pes header incl. PTS
1135                                                 memcpy(mpa_data, buf + 14, buf[14 + 8] + 9);
1136                                                 mpa_header_length = buf[14 + 8] + 9;
1137
1138                                                 //apts-=(((unsigned long long)(ddvd_lpcm_count)*90)/192);
1139
1140                                                 //mpa_data[14]=(int)((apts<<1)&0xFF);
1141                                                 //mpa_data[12]=(int)((apts>>7)&0xFF);
1142                                                 //mpa_data[11]=(int)(((apts<<1)>>15)&0xFF);
1143                                                 //mpa_data[10]=(int)((apts>>22)&0xFF);
1144
1145                                                 // copy lpcm data into buffer for encoding
1146                                                 memcpy(lpcm_data + ddvd_lpcm_count, ac3_tmp, ac3_len);
1147                                                 ddvd_lpcm_count += ac3_len;
1148
1149                                                 // encode the whole packet to mpa
1150                                                 mpa_count2 = mpa_count = 0;
1151                                                 while (ddvd_lpcm_count >= 4608) {
1152                                                         mpa_count = ddvd_mpa_encode_frame(mpa_data + mpa_header_length + mpa_count2, 4608, lpcm_data);
1153                                                         mpa_count2 += mpa_count;
1154                                                         ddvd_lpcm_count -= 4608;
1155                                                         memcpy(lpcm_data, lpcm_data + 4608, ddvd_lpcm_count);
1156                                                 }
1157
1158                                                 // patch pes__packet_length
1159                                                 mpa_count = mpa_count2 + mpa_header_length - 6;
1160                                                 mpa_data[4] = mpa_count >> 8;
1161                                                 mpa_data[5] = mpa_count & 0xFF;
1162
1163                                                 // patch header type to mpeg
1164                                                 mpa_data[3] = 0xC0;
1165
1166                                                 // write to decoder
1167                                                 safe_write(ddvd_ac3_fd, mpa_data, mpa_count2 + mpa_header_length);
1168
1169                                         }
1170                                 } 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
1171                                         memcpy(spu_buffer + ddvd_spu_ptr, buf + buf[22] + 14 + 10, 2048 - (buf[22] + 14 + 10));
1172                                         ddvd_spu_ptr += 2048 - (buf[22] + 14 + 10);
1173
1174                                         if (buf[14 + 7] & 128) {
1175                                                 /* damn gcc bug */
1176 #if CONFIG_API_VERSION == 3
1177                                                 spts = ((unsigned long long)(((buf[14 + 9] >> 1) & 7))) << 30;
1178                                                 spts |= buf[14 + 10] << 22;
1179                                                 spts |= (buf[14 + 11] >> 1) << 15;
1180                                                 spts |= buf[14 + 12] << 7;
1181                                                 spts |= (buf[14 + 14] >> 1);
1182 #else
1183                                                 spts = (buf[14 + 9] >> 1) << 29;        // need a corrected "spts" because vulcan/pallas will give us a 32bit pts instead of 33bit
1184                                                 spts |= buf[14 + 10] << 21;
1185                                                 spts |= (buf[14 + 11] >> 1) << 14;
1186                                                 spts |= buf[14 + 12] << 6;
1187                                                 spts |= buf[14 + 12] >> 2;
1188 #endif
1189                                                 //printf("SPTS? %X\n",(int)spts);
1190                                         }
1191
1192                                         if (ddvd_spu_ptr >= (spu_buffer[0] << 8 | spu_buffer[1]))       // SPU packet complete ?
1193                                         {
1194                                                 if (ddvd_spu_backnr == 3)       // backbuffer already full ?
1195                                                 {
1196                                                         int tmplen = (spu_backbuffer[0] << 8 | spu_backbuffer[1]);
1197                                                         memcpy(spu_backbuffer, spu_backbuffer + tmplen, ddvd_spu_backptr - tmplen);     // delete oldest SPU packet
1198                                                         spu_backpts[0] = spu_backpts[1];
1199                                                         spu_backpts[1] = spu_backpts[2];
1200                                                         ddvd_spu_backnr = 2;
1201                                                         ddvd_spu_backptr -= tmplen;
1202                                                 }
1203
1204                                                 memcpy(spu_backbuffer + ddvd_spu_backptr, spu_buffer, (spu_buffer[0] << 8 | spu_buffer[1]));    // copy into backbuffer
1205                                                 spu_backpts[ddvd_spu_backnr++] = spts;  // store pts
1206                                                 ddvd_spu_backptr += (spu_buffer[0] << 8 | spu_buffer[1]);       // increase ptr
1207
1208                                                 ddvd_spu_ptr = 0;
1209                                         }
1210                                 }
1211                                 break;
1212
1213                         case DVDNAV_NOP:
1214                                 /* Nothing to do here. */
1215                                 break;
1216
1217                         case DVDNAV_STILL_FRAME:
1218                                 /* We have reached a still frame. So we start a timer to wait
1219                                  * the amount of time specified by the still's length while still handling
1220                                  * user input to make menus and other interactive stills work.
1221                                  * A length of 0xff means an indefinite still which has to be skipped
1222                                  * indirectly by some user interaction. */
1223                                 {
1224                                         if (ddvd_iframesend == 0 && ddvd_last_iframe_len)
1225                                                 ddvd_iframesend = 1;
1226
1227                                         dvdnav_still_event_t *still_event = (dvdnav_still_event_t *) buf;
1228                                         if (still_event->length < 0xff) {
1229                                                 if (!ddvd_wait_timer_active) {
1230                                                         ddvd_wait_timer_active = 1;
1231                                                         ddvd_wait_timer_end = ddvd_get_time() + (still_event->length * 1000);   //ms
1232                                                 }
1233                                         } else
1234                                                 ddvd_wait_for_user = 1;
1235                                 }
1236                                 break;
1237
1238                         case DVDNAV_WAIT:
1239                                 /* We have reached a point in DVD playback, where timing is critical.
1240                                  * We dont use readahead, so we can simply skip the wait state. */
1241                                 dvdnav_wait_skip(dvdnav);
1242                                 break;
1243
1244                         case DVDNAV_SPU_CLUT_CHANGE:
1245                                 /* We received a new color lookup table so we read and store
1246                                  * it */
1247                                 {
1248                                         int i = 0, i2 = 0;
1249                                         uint8_t pal[16 * 4];
1250 #if BYTE_ORDER == BIG_ENDIAN
1251                                         memcpy(pal, buf, 16 * sizeof(uint32_t));
1252 #else
1253                                         for (; i < 16; ++i)
1254                                                 *(int *)(pal + i * 4) = htonl(*(int *)(buf + i * 4));
1255                                         i = 0;
1256 #endif
1257                                         while (i < 16 * 4) {
1258                                                 int y = buf[i + 1];
1259                                                 signed char cr = buf[i + 2];    //v
1260                                                 signed char cb = buf[i + 3];    //u
1261                                                 //printf("%d %d %d ->", y, cr, cb);
1262                                                 y = pal[i + 1];
1263                                                 cr = pal[i + 2];        //v
1264                                                 cb = pal[i + 3];        //u
1265                                                 //printf(" %d %d %d\n", y, cr, cb);
1266                                                 i += 4;
1267                                         }
1268                                         i = 0;
1269
1270                                         while (i < 16 * 4) {
1271                                                 int y = pal[i + 1];
1272                                                 signed char cr = pal[i + 2];    //v
1273                                                 signed char cb = pal[i + 3];    //u
1274
1275                                                 y = 76310 * (y - 16);   //yuv2rgb
1276                                                 cr -= 128;
1277                                                 cb -= 128;
1278                                                 int r = CLAMP((y + 104635 * cr) >> 16);
1279                                                 int g = CLAMP((y - 53294 * cr - 25690 * cb) >> 16);
1280                                                 int b = CLAMP((y + 132278 * cb) >> 16);
1281
1282                                                 ddvd_bl[i2] = b << 8;
1283                                                 ddvd_gn[i2] = g << 8;
1284                                                 ddvd_rd[i2] = r << 8;
1285                                                 i += 4;
1286                                                 i2++;
1287                                         }
1288                                         //CHANGE COLORMAP
1289                                 }
1290                                 break;
1291
1292                         case DVDNAV_SPU_STREAM_CHANGE:
1293                                 /* We received a new SPU stream ID */
1294                                 if (spu_lock)
1295                                         break;
1296
1297                                 dvdnav_spu_stream_change_event_t *ev = (dvdnav_spu_stream_change_event_t *) buf;
1298                                 switch (tv_scale) {
1299                                 case 0: //off
1300                                         spu_active_id = ev->physical_wide;
1301                                         break;
1302                                 case 1: //letterbox
1303                                         spu_active_id = ev->physical_letterbox;
1304                                         break;
1305                                 case 2: //panscan
1306                                         spu_active_id = ev->physical_pan_scan;
1307                                         break;
1308                                 default:        // should not happen
1309                                         spu_active_id = ev->physical_wide;
1310                                         break;
1311                                 }       
1312                                 spu_active_id&=0x1F;
1313                                 uint16_t spu_lang = 0xFFFF;
1314                                 int spu_id_logical;
1315                                 spu_id_logical = dvdnav_get_spu_logical_stream(dvdnav, spu_active_id);
1316                                 spu_lang = dvdnav_spu_stream_to_lang(dvdnav, (spu_id_logical >= 0 ? spu_id_logical : spu_active_id) & 0x1F);
1317                                 if (spu_lang == 0xFFFF) {
1318                                         spu_lang = 0x2D2D;      // SPU "off, unknown or maybe menuoverlays" 
1319                                 }                                                       
1320                                 msg = DDVD_SHOWOSD_SUBTITLE;
1321                                 safe_write(message_pipe, &msg, sizeof(int));
1322                                 safe_write(message_pipe, &spu_active_id, sizeof(int));
1323                                 safe_write(message_pipe, &spu_lang, sizeof(uint16_t));
1324                                 //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);
1325                                 break;
1326
1327                         case DVDNAV_AUDIO_STREAM_CHANGE:
1328                                 /* We received a new Audio stream ID  */
1329                                 if (!audio_lock)
1330                                 {
1331                                         audio_id = dvdnav_get_active_audio_stream(dvdnav);
1332                                         report_audio_info = 1;
1333                                 }
1334                                 break;
1335
1336                         case DVDNAV_HIGHLIGHT:
1337                                 /* Lets display some Buttons */
1338                                 if (ddvd_clear_buttons == 0) {
1339                                         dvdnav_highlight_event_t *highlight_event = (dvdnav_highlight_event_t *) buf;
1340
1341                                         pci = dvdnav_get_current_nav_pci(dvdnav);
1342                                         dsi = dvdnav_get_current_nav_dsi(dvdnav);
1343                                         dvdnav_highlight_area_t hl;
1344                                         
1345                                         memcpy(&blit_area,&last_blit_area,sizeof(struct ddvd_resize_return));
1346                                         memset(p_lfb, 0, ddvd_screeninfo_stride * ddvd_screeninfo_yres);        //clear backbuffer .. 
1347                                         msg = DDVD_SCREEN_UPDATE;       // wipe old highlight
1348                                         safe_write(message_pipe, &msg, sizeof(int));
1349                                         safe_write(message_pipe, &blit_area, sizeof(struct ddvd_resize_return));
1350                                         //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);
1351                                         
1352                                         //struct ddvd_resize_return blit_area;
1353                                         blit_area.x_start = blit_area.x_end = blit_area.y_start = blit_area.y_end = 0;
1354                                                 
1355                                         int libdvdnav_workaround = 0;
1356
1357                                         if (pci->hli.hl_gi.btngr_ns) {
1358                                                 int btns_per_group = 36 / pci->hli.hl_gi.btngr_ns;
1359                                                 btni_t *btni = NULL;
1360                                                 int modeMask = 1 << tv_scale;
1361
1362                                                 if (!btni && pci->hli.hl_gi.btngr_ns >= 1 && (pci->hli.hl_gi.btngr1_dsp_ty & modeMask)) {
1363                                                         btni = &pci->hli.btnit[0 * btns_per_group + highlight_event->buttonN - 1];
1364                                                 }
1365                                                 if (!btni && pci->hli.hl_gi.btngr_ns >= 2 && (pci->hli.hl_gi.btngr2_dsp_ty & modeMask)) {
1366                                                         btni = &pci->hli.btnit[1 * btns_per_group + highlight_event->buttonN - 1];
1367                                                 }
1368                                                 if (!btni && pci->hli.hl_gi.btngr_ns >= 3 && (pci->hli.hl_gi.btngr3_dsp_ty & modeMask)) {
1369                                                         btni = &pci->hli.btnit[2 * btns_per_group + highlight_event->buttonN - 1];
1370                                                 }
1371
1372                                                 if (btni && btni->btn_coln != 0) {
1373                                                         // get and set clut for actual button
1374                                                         unsigned char tmp, tmp2;
1375                                                         struct ddvd_color colneu;
1376                                                         int i;
1377                                                         msg = DDVD_COLORTABLE_UPDATE;
1378                                                         if (ddvd_screeninfo_bypp == 1)
1379                                                                 safe_write(message_pipe, &msg, sizeof(int));
1380                                                         for (i = 0; i < 4; i++) {
1381                                                                 tmp = ((pci->hli.btn_colit.btn_coli[btni->btn_coln - 1][0]) >> (16 + 4 * i)) & 0xf;
1382                                                                 tmp2 = ((pci->hli.btn_colit.btn_coli[btni->btn_coln - 1][0]) >> (4 * i)) & 0xf;
1383                                                                 colneu.blue = ddvd_bl[i + 252] = ddvd_bl[tmp];
1384                                                                 colneu.green = ddvd_gn[i + 252] = ddvd_gn[tmp];
1385                                                                 colneu.red = ddvd_rd[i + 252] = ddvd_rd[tmp];
1386                                                                 colneu.trans = ddvd_tr[i + 252] = (0xF - tmp2) * 0x1111;
1387                                                                 if (ddvd_screeninfo_bypp == 1)
1388                                                                         safe_write(message_pipe, &colneu, sizeof(struct ddvd_color));
1389                                                         }
1390                                                         msg = DDVD_NULL;
1391                                                         //CHANGE COLORMAP
1392
1393                                                         memset(ddvd_lbb2, 0, ddvd_screeninfo_stride * ddvd_screeninfo_yres);    //clear backbuffer ..
1394                                                         //copy button into screen
1395                                                         for (i = btni->y_start; i < btni->y_end; i++) {
1396                                                                 if (ddvd_screeninfo_bypp == 1)
1397                                                                         memcpy(ddvd_lbb2 + btni->x_start + 720 * (i),
1398                                                                                ddvd_lbb + btni->x_start + 720 * (i),
1399                                                                                btni->x_end - btni->x_start);
1400                                                                 else
1401                                                                         ddvd_blit_to_argb(ddvd_lbb2 + btni->x_start * ddvd_screeninfo_bypp +
1402                                                                                           720 * ddvd_screeninfo_bypp * i,
1403                                                                                           ddvd_lbb + btni->x_start + 720 * (i),
1404                                                                                           btni->x_end - btni->x_start);
1405                                                         }
1406                                                         blit_area.x_start = btni->x_start;
1407                                                         blit_area.x_end = btni->x_end;
1408                                                         blit_area.y_start = btni->y_start;
1409                                                         blit_area.y_end = btni->y_end;
1410                                                         libdvdnav_workaround = 1;
1411                                                 }
1412                                         }
1413                                         if (!libdvdnav_workaround && dvdnav_get_highlight_area(pci, highlight_event->buttonN, 0, &hl) == DVDNAV_STATUS_OK) {
1414                                                 // get and set clut for actual button
1415                                                 unsigned char tmp, tmp2;
1416                                                 struct ddvd_color colneu;
1417                                                 int i;
1418                                                 msg = DDVD_COLORTABLE_UPDATE;
1419                                                 if (ddvd_screeninfo_bypp == 1)
1420                                                         safe_write(message_pipe, &msg, sizeof(int));
1421                                                 for (i = 0; i < 4; i++) {
1422                                                         tmp = ((hl.palette) >> (16 + 4 * i)) & 0xf;
1423                                                         tmp2 = ((hl.palette) >> (4 * i)) & 0xf;
1424                                                         colneu.blue = ddvd_bl[i + 252] = ddvd_bl[tmp];
1425                                                         colneu.green = ddvd_gn[i + 252] = ddvd_gn[tmp];
1426                                                         colneu.red = ddvd_rd[i + 252] = ddvd_rd[tmp];
1427                                                         colneu.trans = ddvd_tr[i + 252] = (0xF - tmp2) * 0x1111;
1428                                                         if (ddvd_screeninfo_bypp == 1)
1429                                                                 safe_write(message_pipe, &colneu, sizeof(struct ddvd_color));
1430                                                 }
1431                                                 msg = DDVD_NULL;
1432                                                 //CHANGE COLORMAP
1433
1434                                                 memset(ddvd_lbb2, 0, ddvd_screeninfo_stride * ddvd_screeninfo_yres);    //clear backbuffer ..
1435                                                 //copy button into screen
1436                                                 for (i = hl.sy; i < hl.ey; i++) {
1437                                                         if (ddvd_screeninfo_bypp == 1)
1438                                                                 memcpy(ddvd_lbb2 + hl.sx + 720 * (i),
1439                                                                        ddvd_lbb + hl.sx + 720 * (i), hl.ex - hl.sx);
1440                                                         else
1441                                                                 ddvd_blit_to_argb(ddvd_lbb2 + hl.sx * ddvd_screeninfo_bypp + 720 * ddvd_screeninfo_bypp * i,
1442                                                                                   ddvd_lbb + hl.sx + 720 * (i), hl.ex - hl.sx);
1443                                                 }
1444                                                 blit_area.x_start = hl.sx;
1445                                                 blit_area.x_end = hl.ex;
1446                                                 blit_area.y_start = hl.sy;
1447                                                 blit_area.y_end = hl.ey;
1448                                                 libdvdnav_workaround = 1;
1449                                         }
1450                                         if (!libdvdnav_workaround)
1451                                                 memset(ddvd_lbb2, 0, ddvd_screeninfo_stride * ddvd_screeninfo_yres);    //clear backbuffer .. 
1452                                         else
1453                                         {
1454                                                 int y_source = ddvd_have_ntsc ? 480 : 576; // correct ntsc overlay
1455                                                 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
1456                                                 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
1457                                                 uint64_t start=ddvd_get_time();
1458                                                 if (x_offset != 0 || y_offset != 0 || y_source != ddvd_screeninfo_yres || ddvd_screeninfo_xres != 720)
1459                                                         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
1460                                                 memcpy(p_lfb, ddvd_lbb2, ddvd_screeninfo_xres * ddvd_screeninfo_yres * ddvd_screeninfo_bypp); //copy backbuffer into screen
1461                                                 //printf("needed time for resizing: %d ms\n",(int)(ddvd_get_time()-start));
1462                                                 //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);
1463                                                 msg = DDVD_SCREEN_UPDATE;
1464                                                 safe_write(message_pipe, &msg, sizeof(int));
1465                                                 safe_write(message_pipe, &blit_area, sizeof(struct ddvd_resize_return));
1466                                                 memcpy(&last_blit_area,&blit_area,sizeof(struct ddvd_resize_return)); // safe blit area for next wipe
1467                                         }
1468                                 } else {
1469                                         ddvd_clear_buttons = 0;
1470                                         //printf("clear buttons\n");
1471                                 }
1472                                 break;
1473
1474                         case DVDNAV_VTS_CHANGE:
1475                                 {
1476                                         /* Some status information like video aspect and video scale permissions do
1477                                          * not change inside a VTS. Therefore we will set it new at this place */
1478                                         ddvd_play_empty(FALSE);
1479                                         audio_lock = 0; // reset audio & spu lock
1480                                         spu_lock = 0;
1481                                         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;
1482
1483                                         dvd_aspect = dvdnav_get_video_aspect(dvdnav);
1484                                         dvd_scale_perm = dvdnav_get_video_scale_permission(dvdnav);
1485                                         tv_scale = ddvd_check_aspect(dvd_aspect, dvd_scale_perm, tv_aspect, tv_mode);
1486                                         //printf("DVD Aspect: %d TV Aspect: %d Scale: %d Allowed: %d\n",dvd_aspect,tv_aspect,tv_scale,dvd_scale_perm);
1487                                         
1488                                         // resuming a dvd ?
1489                                         if (playerconfig->should_resume && first_vts_change) {
1490                                                 first_vts_change = 0;
1491                                                 int title_numbers,part_numbers;
1492                                                 dvdnav_get_number_of_titles(dvdnav, &title_numbers);
1493                                                 dvdnav_get_number_of_parts(dvdnav, playerconfig->resume_title, &part_numbers);
1494                                                 if (playerconfig->resume_title <= title_numbers && playerconfig->resume_title > 0 && playerconfig->resume_chapter <= part_numbers && playerconfig->resume_chapter > 0) {
1495                                                         dvdnav_part_play(dvdnav, playerconfig->resume_title, playerconfig->resume_chapter);
1496                                                         next_cell_change = 1;
1497                                                 } else {
1498                                                         playerconfig->should_resume = 0;
1499                                                         playerconfig->resume_title = 0;
1500                                                         playerconfig->resume_chapter = 0;
1501                                                         playerconfig->resume_block = 0;
1502                                                         playerconfig->resume_audio_id = 0;
1503                                                         playerconfig->resume_audio_lock = 0;
1504                                                         playerconfig->resume_spu_id = 0;
1505                                                         playerconfig->resume_spu_lock = 0;                                                      
1506                                                         perror("DVD resuming failed");
1507                                                 }
1508                                                 
1509                                                 
1510                                         }
1511                                 }
1512                                 break;
1513
1514                         case DVDNAV_CELL_CHANGE:
1515                                 {
1516                                         /* Store new cell information */
1517                                         memcpy(&ddvd_lastCellEventInfo, buf, sizeof(dvdnav_cell_change_event_t));
1518
1519                                         if ((ddvd_still_frame & CELL_STILL) && ddvd_iframesend == 0 && ddvd_last_iframe_len)
1520                                                 ddvd_iframesend = 1;
1521
1522                                         ddvd_still_frame = (dvdnav_get_next_still_flag(dvdnav) != 0) ? CELL_STILL : 0;
1523                                         
1524                                         // resuming a dvd ?
1525                                         if (playerconfig->should_resume && next_cell_change) {
1526                                                 next_cell_change = 0;
1527                                                 playerconfig->should_resume = 0;
1528                                                 if (dvdnav_sector_search(dvdnav, playerconfig->resume_block, SEEK_SET) != DVDNAV_STATUS_OK)
1529                                                 {
1530                                                         perror("DVD resuming failed");
1531                                                 } else {
1532                                                         audio_id = playerconfig->resume_audio_id;
1533                                                         audio_lock = 1;//playerconfig->resume_audio_lock;
1534                                                         spu_active_id = playerconfig->resume_spu_id & 0x1F;
1535                                                         spu_lock = 1;//playerconfig->resume_spu_lock;
1536                                                         report_audio_info = 1;
1537                                                         uint16_t spu_lang = 0xFFFF;
1538                                                         int spu_id_logical;
1539                                                         spu_id_logical = dvdnav_get_spu_logical_stream(dvdnav, spu_active_id);
1540                                                         spu_lang = dvdnav_spu_stream_to_lang(dvdnav, (spu_id_logical >= 0 ? spu_id_logical : spu_active_id) & 0x1F);
1541                                                         if (spu_lang == 0xFFFF) {
1542                                                                 spu_lang = 0x2D2D;      // SPU "off" 
1543                                                                 spu_active_id = -1;
1544                                                         }
1545                                                         msg = DDVD_SHOWOSD_SUBTITLE;
1546                                                         safe_write(message_pipe, &msg, sizeof(int));
1547                                                         safe_write(message_pipe, &spu_active_id, sizeof(int));
1548                                                         safe_write(message_pipe, &spu_lang, sizeof(uint16_t));
1549                                                         msg = DDVD_SHOWOSD_TIME; // send new position to the frontend
1550                                                 }
1551                                                 playerconfig->resume_title = 0;
1552                                                 playerconfig->resume_chapter = 0;
1553                                                 playerconfig->resume_block = 0;
1554                                                 playerconfig->resume_audio_id = 0;
1555                                                 playerconfig->resume_audio_lock = 0;
1556                                                 playerconfig->resume_spu_id = 0;
1557                                                 playerconfig->resume_spu_lock = 0;
1558                                         }
1559                                 }
1560                                 break;
1561
1562                         case DVDNAV_NAV_PACKET:
1563                                 /* A NAV packet provides PTS discontinuity information, angle linking information and
1564                                  * button definitions for DVD menus. We have to handle some stilframes here */
1565                                 pci = dvdnav_get_current_nav_pci(dvdnav);
1566                                 dsi = dvdnav_get_current_nav_dsi(dvdnav);
1567
1568                                 if ((ddvd_still_frame & NAV_STILL) && ddvd_iframesend == 0 && ddvd_last_iframe_len)
1569                                         ddvd_iframesend = 1;
1570
1571                                 if (dsi->vobu_sri.next_video == 0xbfffffff)
1572                                         ddvd_still_frame |= NAV_STILL;  //|= 1;
1573                                 else
1574                                         ddvd_still_frame &= ~NAV_STILL; //&= 1;
1575                                 break;
1576
1577                         case DVDNAV_HOP_CHANNEL:
1578                                 /* This event is issued whenever a non-seamless operation has been executed.
1579                                  * So we drop our buffers */
1580                                 ddvd_play_empty(TRUE);
1581                                 break;
1582
1583                         case DVDNAV_STOP:
1584                                 /* Playback should end here. */
1585                                 printf("DVDNAV_STOP\n");
1586                                 playerconfig->resume_title = 0;
1587                                 playerconfig->resume_chapter = 0;
1588                                 playerconfig->resume_block = 0;
1589                                 playerconfig->resume_audio_id = 0;
1590                                 playerconfig->resume_audio_lock = 0;
1591                                 playerconfig->resume_spu_id = 0;
1592                                 playerconfig->resume_spu_lock = 0;
1593                                 finished = 1;
1594                                 break;
1595
1596                         default:
1597                                 printf("Unknown event (%i)\n", event);
1598                                 finished = 1;
1599                                 break;
1600                         }
1601                 }
1602                 // spu handling
1603 #if CONFIG_API_VERSION == 1
1604                 unsigned int tpts;
1605                 if (ioctl(ddvd_output_fd, VIDEO_GET_PTS, &tpts) < 0)
1606                         perror("VIDEO_GET_PTS");
1607                 pts = (unsigned long long)tpts;
1608                 signed long long diff = spts - pts;
1609                 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
1610                                                                                                         // so on non animated menus the buttons will be displayed to soon, but we we have to accept it
1611 #else
1612                 if (ioctl(ddvd_fdvideo, VIDEO_GET_PTS, &pts) < 0)
1613                         perror("VIDEO_GET_PTS");
1614                 if (ddvd_spu_backnr > 0 && pts >= spu_backpts[0])
1615 #endif
1616                 {
1617                         int tmplen = (spu_backbuffer[0] << 8 | spu_backbuffer[1]);
1618                         
1619                         memset(ddvd_lbb, 0, 720 * 576); //clear backbuffer .. 
1620                         last_spu_return = ddvd_spu_decode_data(spu_backbuffer, tmplen); // decode
1621                         ddvd_display_time = last_spu_return.display_time;
1622                         ddvd_lbb_changed = 1;
1623
1624                         struct ddvd_color colneu;
1625                         int ctmp;
1626                         msg = DDVD_COLORTABLE_UPDATE;
1627                         if (ddvd_screeninfo_bypp == 1)
1628                                 safe_write(message_pipe, &msg, sizeof(int));
1629                         for (ctmp = 0; ctmp < 4; ctmp++) {
1630                                 colneu.blue = ddvd_bl[ctmp + 252];
1631                                 colneu.green = ddvd_gn[ctmp + 252];
1632                                 colneu.red = ddvd_rd[ctmp + 252];
1633                                 colneu.trans = ddvd_tr[ctmp + 252];
1634                                 if (ddvd_screeninfo_bypp == 1)
1635                                         safe_write(message_pipe, &colneu, sizeof(struct ddvd_color));
1636                         }
1637                         msg = DDVD_NULL;
1638
1639                         memcpy(spu_backbuffer, spu_backbuffer + tmplen, ddvd_spu_backptr - tmplen);     // delete SPU packet
1640                         spu_backpts[0] = spu_backpts[1];
1641                         spu_backpts[1] = spu_backpts[2];
1642                         ddvd_spu_backnr--;
1643                         ddvd_spu_backptr -= tmplen;
1644
1645                         // set timer
1646                         if (ddvd_display_time > 0) {
1647                                 ddvd_spu_timer_active = 1;
1648                                 ddvd_spu_timer_end = ddvd_get_time() + (ddvd_display_time * 10);        //ms
1649                         } else
1650                                 ddvd_spu_timer_active = 0;
1651
1652                         pci = dvdnav_get_current_nav_pci(dvdnav);       //update highlight buttons
1653                         dsi = dvdnav_get_current_nav_dsi(dvdnav);
1654                         if (pci->hli.hl_gi.btn_ns > 0) {
1655                                 dvdnav_get_current_highlight(dvdnav, &buttonN);
1656                                 dvdnav_button_select(dvdnav, pci, buttonN);
1657                                 ddvd_lbb_changed = 0;
1658                                 in_menu = 1;
1659                         }
1660                 }
1661
1662                 if (!in_menu) {
1663                         if (!pci)
1664                                 pci = dvdnav_get_current_nav_pci(dvdnav);
1665
1666                         in_menu = pci && pci->hli.hl_gi.btn_ns > 0;
1667                 }
1668
1669                 if (in_menu && !playerconfig->in_menu) {
1670                         int bla = DDVD_MENU_OPENED;
1671                         safe_write(message_pipe, &bla, sizeof(int));
1672                         playerconfig->in_menu = 1;
1673                 } else if (!in_menu && playerconfig->in_menu) {
1674                         int bla = DDVD_MENU_CLOSED;
1675                         safe_write(message_pipe, &bla, sizeof(int));
1676                         playerconfig->in_menu = 0;
1677                 }
1678
1679                 if (ddvd_wait_for_user) {
1680                         struct pollfd pfd[1];   // make new pollfd array
1681                         pfd[0].fd = key_pipe;
1682                         pfd[0].events = POLLIN | POLLPRI | POLLERR;
1683                         poll(pfd, 1, -1);
1684                 }
1685                 //Userinput
1686                 if (ddvd_readpipe(key_pipe, &rccode, sizeof(int), 0) == sizeof(int)) {
1687                         int keydone = 1;
1688
1689                         if (!dsi)
1690                                 dsi = dvdnav_get_current_nav_dsi(dvdnav);
1691
1692                         if (buttonN == -1)
1693                                 dvdnav_get_current_highlight(dvdnav, &buttonN);
1694
1695                         switch (rccode) // actions inside and outside of menu
1696                         {
1697                                 case DDVD_SET_MUTE:
1698                                         ismute = 1;
1699                                         break;
1700                                 case DDVD_UNSET_MUTE:
1701                                         ismute = 0;
1702                                         break;
1703                                 default:
1704                                         keydone = 0;
1705                                         break;
1706                         }
1707
1708                         if (!keydone && in_menu) {
1709                                 switch (rccode) //Actions inside a Menu
1710                                 {
1711                                 case DDVD_KEY_UP:       //Up
1712                                         dvdnav_upper_button_select(dvdnav, pci);
1713                                         break;
1714                                 case DDVD_KEY_DOWN:     //Down
1715                                         dvdnav_lower_button_select(dvdnav, pci);
1716                                         break;
1717                                 case DDVD_KEY_LEFT:     //left
1718                                         dvdnav_left_button_select(dvdnav, pci);
1719                                         break;
1720                                 case DDVD_KEY_RIGHT:    //right
1721                                         dvdnav_right_button_select(dvdnav, pci);
1722                                         break;
1723                                 case DDVD_KEY_OK:       //OK
1724                                         ddvd_wait_for_user = 0;
1725                                         memset(p_lfb, 0, ddvd_screeninfo_stride * ddvd_screeninfo_yres);        //clear screen ..
1726                                         memset(ddvd_lbb, 0, 720 * 576); //clear backbuffer
1727                                         blit_area.x_start = blit_area.y_start = 0;
1728                                         blit_area.x_end = ddvd_screeninfo_xres;
1729                                         blit_area.y_end = ddvd_screeninfo_yres;
1730                                         msg = DDVD_SCREEN_UPDATE;
1731                                         safe_write(message_pipe, &msg, sizeof(int));
1732                                         safe_write(message_pipe, &blit_area, sizeof(struct ddvd_resize_return));
1733                                         
1734                                         ddvd_clear_buttons = 1;
1735                                         dvdnav_button_activate(dvdnav, pci);
1736                                         ddvd_play_empty(TRUE);
1737                                         if (ddvd_wait_timer_active)
1738                                                 ddvd_wait_timer_active = 0;
1739                                         break;
1740                                 case DDVD_KEY_MENU:     //Dream
1741                                         if (dvdnav_menu_call(dvdnav, DVD_MENU_Root) == DVDNAV_STATUS_OK)
1742                                                 ddvd_play_empty(TRUE);
1743                                         break;
1744                                 case DDVD_KEY_AUDIOMENU:        //Audio
1745                                         if (dvdnav_menu_call(dvdnav, DVD_MENU_Audio) == DVDNAV_STATUS_OK)
1746                                                 ddvd_play_empty(TRUE);
1747                                         break;
1748                                 case DDVD_KEY_EXIT:     //Exit
1749                                         {
1750                                                 printf("DDVD_KEY_EXIT (menu)\n");
1751                                                 playerconfig->resume_title = 0;
1752                                                 playerconfig->resume_chapter = 0;
1753                                                 playerconfig->resume_block = 0;
1754                                                 playerconfig->resume_audio_id = 0;
1755                                                 playerconfig->resume_audio_lock = 0;
1756                                                 playerconfig->resume_spu_id = 0;
1757                                                 playerconfig->resume_spu_lock = 0;
1758                                                 finished = 1;
1759                                         }
1760                                         break;                                          
1761                                 case DDVD_SKIP_FWD:
1762                                 case DDVD_SKIP_BWD:
1763                                 case DDVD_SET_TITLE:
1764                                 case DDVD_SET_CHAPTER:
1765                                         // we must empty the pipe here...
1766                                         ddvd_readpipe(key_pipe, &keydone, sizeof(int), 1);
1767                                 default:
1768                                         break;
1769                                 }
1770                         } else if (!keydone)    //Actions inside a Movie
1771                         {
1772                                 switch (rccode) //Main Actions
1773                                 {
1774                                 case DDVD_KEY_PREV_CHAPTER:     //left
1775                                         {
1776                                                 int titleNo, chapterNumber, chapterNo;
1777                                                 dvdnav_current_title_info(dvdnav, &titleNo, &chapterNo);
1778                                                 dvdnav_get_number_of_parts(dvdnav, titleNo, &chapterNumber);
1779                                                 chapterNo--;
1780                                                 if (chapterNo > chapterNumber)
1781                                                         chapterNo = 1;
1782                                                 if (chapterNo <= 0)
1783                                                         chapterNo = chapterNumber;
1784                                                 dvdnav_part_play(dvdnav, titleNo, chapterNo);
1785                                                 ddvd_play_empty(TRUE);
1786                                                 msg = DDVD_SHOWOSD_TIME;
1787                                                 break;
1788                                         }
1789                                 case DDVD_KEY_NEXT_CHAPTER:     //right
1790                                         {
1791                                                 int titleNo, chapterNumber, chapterNo;
1792                                                 dvdnav_current_title_info(dvdnav, &titleNo, &chapterNo);
1793                                                 dvdnav_get_number_of_parts(dvdnav, titleNo, &chapterNumber);
1794                                                 chapterNo++;
1795                                                 if (chapterNo > chapterNumber)
1796                                                         chapterNo = 1;
1797                                                 if (chapterNo <= 0)
1798                                                         chapterNo = chapterNumber;
1799                                                 dvdnav_part_play(dvdnav, titleNo, chapterNo);
1800                                                 ddvd_play_empty(TRUE);
1801                                                 msg = DDVD_SHOWOSD_TIME;
1802                                                 break;
1803                                         }
1804                                 case DDVD_KEY_PREV_TITLE:
1805                                         {
1806                                                 int titleNo, titleNumber, chapterNo;
1807                                                 dvdnav_current_title_info(dvdnav, &titleNo, &chapterNo);
1808                                                 dvdnav_get_number_of_titles(dvdnav, &titleNumber);
1809                                                 titleNo--;
1810                                                 if (titleNo > titleNumber)
1811                                                         titleNo = 1;
1812                                                 if (titleNo <= 0)
1813                                                         titleNo = titleNumber;
1814                                                 dvdnav_part_play(dvdnav, titleNo, 1);
1815                                                 ddvd_play_empty(TRUE);
1816                                                 msg = DDVD_SHOWOSD_TIME;
1817                                                 break;
1818                                         }
1819                                 case DDVD_KEY_NEXT_TITLE:
1820                                         {
1821                                                 int titleNo, titleNumber, chapterNo;
1822                                                 dvdnav_current_title_info(dvdnav, &titleNo, &chapterNo);
1823                                                 dvdnav_get_number_of_titles(dvdnav, &titleNumber);
1824                                                 titleNo++;
1825                                                 if (titleNo > titleNumber)
1826                                                         titleNo = 1;
1827                                                 if (titleNo <= 0)
1828                                                         titleNo = titleNumber;
1829                                                 dvdnav_part_play(dvdnav, titleNo, 1);
1830                                                 ddvd_play_empty(TRUE);
1831                                                 msg = DDVD_SHOWOSD_TIME;
1832                                                 break;
1833                                         }
1834                                 case DDVD_KEY_PAUSE:    // Pause
1835                                         {
1836                                                 if (ddvd_playmode == PLAY) {
1837                                                         ddvd_playmode = PAUSE;
1838                                                         if (ioctl(ddvd_fdaudio, AUDIO_PAUSE) < 0)
1839                                                                 perror("AUDIO_PAUSE");
1840                                                         if (ioctl(ddvd_fdvideo, VIDEO_FREEZE) < 0)
1841                                                                 perror("VIDEO_FREEZE");
1842                                                         msg = DDVD_SHOWOSD_STATE_PAUSE;
1843                                                         safe_write(message_pipe, &msg, sizeof(int));
1844                                                         break;
1845                                                 } else if (ddvd_playmode != PAUSE)
1846                                                         break;
1847                                                 // fall through to PLAY
1848                                         }
1849                                 case DDVD_KEY_PLAY:     // Play
1850                                         {
1851                                                 if (ddvd_playmode == PAUSE || ddvd_trickmode) {
1852                                                         ddvd_playmode = PLAY;
1853 key_play:
1854 #if CONFIG_API_VERSION == 1
1855                                                         ddvd_device_clear();
1856 #endif
1857                                                         if (ddvd_trickmode && !ismute)
1858                                                                 if (ioctl(ddvd_fdaudio, AUDIO_SET_MUTE, 0) < 0)
1859                                                                         perror("AUDIO_SET_MUTE");
1860                                                         ddvd_trickmode = TOFF;
1861                                                         if (ddvd_playmode == PLAY) {
1862                                                                 if (ioctl(ddvd_fdaudio, AUDIO_CONTINUE) < 0)
1863                                                                         perror("AUDIO_CONTINUE");
1864                                                                 if (ioctl(ddvd_fdvideo, VIDEO_CONTINUE) < 0)
1865                                                                         perror("VIDEO_CONTINUE");
1866                                                                 msg = DDVD_SHOWOSD_STATE_PLAY;
1867                                                                 safe_write(message_pipe, &msg, sizeof(int));
1868                                                         }
1869                                                         msg = DDVD_SHOWOSD_TIME;
1870                                                 }
1871                                                 break;
1872                                         }
1873                                 case DDVD_KEY_MENU:     //Dream
1874                                         if (dvdnav_menu_call(dvdnav, DVD_MENU_Root) == DVDNAV_STATUS_OK)
1875                                                 ddvd_play_empty(TRUE);
1876                                         break;
1877                                 case DDVD_KEY_AUDIOMENU:        //Audio
1878                                         if (dvdnav_menu_call(dvdnav, DVD_MENU_Audio) == DVDNAV_STATUS_OK)
1879                                                 ddvd_play_empty(TRUE);
1880                                         break;
1881                                 case DDVD_KEY_EXIT:     //Exit
1882                                         {
1883                                                 printf("DDVD_KEY_EXIT (menu)\n");
1884                                                 int resume_title, resume_chapter; //safe resume info
1885                                                 uint32_t resume_block, total_block;
1886                                                 if (dvdnav_current_title_info(dvdnav, &resume_title, &resume_chapter) && (0 != resume_title)) {
1887                                                         if(dvdnav_get_position (dvdnav, &resume_block, &total_block) == DVDNAV_STATUS_OK) {
1888                                                                 playerconfig->resume_title = resume_title;
1889                                                                 playerconfig->resume_chapter = resume_chapter;
1890                                                                 playerconfig->resume_block = resume_block;
1891                                                                 playerconfig->resume_audio_id = audio_id;
1892                                                                 playerconfig->resume_audio_lock = audio_lock;
1893                                                                 playerconfig->resume_spu_id = spu_active_id;
1894                                                                 playerconfig->resume_spu_lock = spu_lock;
1895                                                         } else perror("error getting resume position");
1896                                                 } perror("error getting resume position");                                      
1897                                                 finished = 1;
1898                                         }
1899                                         break;                                          
1900                                 case DDVD_KEY_FFWD:     //FastForward
1901                                 case DDVD_KEY_FBWD:     //FastBackward
1902                                         {
1903                                                 if (ddvd_trickmode == TOFF) {
1904                                                         if (ioctl(ddvd_fdaudio, AUDIO_SET_MUTE, 1) < 0)
1905                                                                 perror("AUDIO_SET_MUTE");
1906                                                         ddvd_trickspeed = 2;
1907                                                         ddvd_trickmode = (rccode == DDVD_KEY_FBWD ? FASTBW : FASTFW);
1908                                                 } else if (ddvd_trickmode == (rccode == DDVD_KEY_FBWD ? FASTFW : FASTBW)) {
1909                                                         ddvd_trickspeed /= 2;
1910                                                         if (ddvd_trickspeed == 1) {
1911                                                                 ddvd_trickspeed = 0;
1912                                                                 goto key_play;
1913                                                         }
1914                                                 } else if (ddvd_trickspeed < 64)
1915                                                         ddvd_trickspeed *= 2;
1916                                                 break;
1917                                         }
1918                                 case DDVD_KEY_AUDIO:    //change audio track 
1919                                         {
1920                                                 int count = 0;
1921                                                 audio_id = (audio_id == 7 ? 0 : audio_id+1);
1922                                                 while (audio_format[audio_id] == -1 && count++ < 7)
1923                                                 {
1924                                                         audio_id = (audio_id == 7 ? 0 : audio_id+1);
1925                                                 }
1926                                                 report_audio_info = 1;
1927                                                 ddvd_play_empty(TRUE);
1928                                                 audio_lock = 1;
1929                                                 ddvd_lpcm_count = 0;
1930                                                 break;
1931                                         }
1932                                 case DDVD_KEY_SUBTITLE: //change spu track 
1933                                         {
1934                                                 uint16_t spu_lang = 0xFFFF;
1935                                                 int spu_id_logical;
1936                                                 spu_active_id++;
1937                                                 spu_id_logical = dvdnav_get_spu_logical_stream(dvdnav, spu_active_id);
1938                                                 spu_lang = dvdnav_spu_stream_to_lang(dvdnav, (spu_id_logical >= 0 ? spu_id_logical : spu_active_id) & 0x1F);
1939                                                 if (spu_lang == 0xFFFF) {
1940                                                         spu_lang = 0x2D2D;      // SPU "off" 
1941                                                         spu_active_id = -1;
1942                                                 }
1943                                                 spu_lock = 1;
1944                                                 msg = DDVD_SHOWOSD_SUBTITLE;
1945                                                 safe_write(message_pipe, &msg, sizeof(int));
1946                                                 safe_write(message_pipe, &spu_active_id, sizeof(int));
1947                                                 safe_write(message_pipe, &spu_lang, sizeof(uint16_t));
1948                                                 break;
1949                                         }
1950                                 case DDVD_GET_TIME:     // frontend wants actual time
1951                                         msg = DDVD_SHOWOSD_TIME;
1952                                         break;
1953                                 case DDVD_SKIP_FWD:
1954                                 case DDVD_SKIP_BWD:
1955                                         {
1956                                                 int skip;
1957                                                 ddvd_readpipe(key_pipe, &skip, sizeof(int), 1);
1958                                                 if (ddvd_trickmode == TOFF) {
1959                                                         uint32_t pos, len;
1960                                                         dvdnav_get_position(dvdnav, &pos, &len);
1961                                                         printf("DDVD_SKIP pos=%u len=%u \n", pos, len);
1962                                                         //90000 = 1 Sek.
1963                                                         if (!len)
1964                                                                 len = 1;
1965                                                         long long int posneu = ((pos * ddvd_lastCellEventInfo.pgc_length) / len) + (90000 * skip);
1966                                                         printf("DDVD_SKIP posneu1=%lld\n", posneu);
1967                                                         long long int posneu2 = posneu <= 0 ? 0 : (posneu * len) / ddvd_lastCellEventInfo.pgc_length;
1968                                                         printf("DDVD_SKIP posneu2=%lld\n", posneu2);
1969                                                         if (len && posneu2 && posneu2 >= len)   // reached end of movie
1970                                                         {
1971                                                                 posneu2 = len - 250;
1972                                                                 reached_eof = 1;
1973                                                         }
1974                                                         dvdnav_sector_search(dvdnav, posneu2, SEEK_SET);
1975                                                         ddvd_lpcm_count = 0;
1976                                                         msg = DDVD_SHOWOSD_TIME;
1977                                                 }
1978                                                 break;
1979                                         }
1980                                 case DDVD_SET_TITLE:
1981                                         {
1982                                                 int title, totalTitles;
1983                                                 ddvd_readpipe(key_pipe, &title, sizeof(int), 1);
1984                                                 dvdnav_get_number_of_titles(dvdnav, &totalTitles);
1985                                                 printf("DDVD_SET_TITLE %d/%d\n", title, totalTitles);
1986                                                 if (title <= totalTitles) {
1987                                                         dvdnav_part_play(dvdnav, title, 0);
1988                                                         ddvd_play_empty(TRUE);
1989                                                         msg = DDVD_SHOWOSD_TIME;
1990                                                 }
1991                                                 break;
1992                                         }
1993                                 case DDVD_SET_CHAPTER:
1994                                         {
1995                                                 int chapter, totalChapters, chapterNo, titleNo;
1996                                                 ddvd_readpipe(key_pipe, &chapter, sizeof(int), 1);
1997                                                 dvdnav_current_title_info(dvdnav, &titleNo, &chapterNo);
1998                                                 dvdnav_get_number_of_parts(dvdnav, titleNo, &totalChapters);
1999                                                 printf("DDVD_SET_CHAPTER %d/%d in title %d\n", chapter, totalChapters, titleNo);
2000                                                 if (chapter <= totalChapters) {
2001                                                         dvdnav_part_play(dvdnav, titleNo, chapter);
2002                                                         ddvd_play_empty(TRUE);
2003                                                         msg = DDVD_SHOWOSD_TIME;
2004                                                 }
2005                                                 break;
2006                                         }
2007                                 default:
2008                                         break;
2009                                 }
2010                         }
2011                 }
2012                 // spu handling
2013                 if (ddvd_lbb_changed == 1) {
2014                         
2015                         if (ddvd_screeninfo_bypp == 1)
2016                                 memcpy(ddvd_lbb2, ddvd_lbb, 720 * 576);
2017                         else {
2018                                 int i = 0;
2019                                 for (i = last_spu_return.y_start; i < last_spu_return.y_end; ++i)
2020                                         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);
2021                         }
2022                         //struct ddvd_resize_return blit_area;
2023                         blit_area.x_start = last_spu_return.x_start;
2024                         blit_area.x_end = last_spu_return.x_end;
2025                         blit_area.y_start = last_spu_return.y_start;
2026                         blit_area.y_end = last_spu_return.y_end;
2027                         int y_source = ddvd_have_ntsc ? 480 : 576; // correct ntsc overlay
2028                         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
2029                         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
2030                         uint64_t start=ddvd_get_time();
2031                         if (x_offset != 0 || y_offset != 0 || y_source != ddvd_screeninfo_yres || ddvd_screeninfo_xres != 720)
2032                                 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
2033                         memcpy(p_lfb, ddvd_lbb2, ddvd_screeninfo_xres * ddvd_screeninfo_yres * ddvd_screeninfo_bypp); //copy backbuffer into screen
2034                         //printf("needed time for resizing: %d ms\n",(int)(ddvd_get_time()-start));
2035                         //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);
2036                         int msg_old = msg;      // save and restore msg it may not be empty
2037                         msg = DDVD_SCREEN_UPDATE;
2038                         safe_write(message_pipe, &msg, sizeof(int));
2039                         safe_write(message_pipe, &blit_area, sizeof(struct ddvd_resize_return));
2040                         msg = msg_old;
2041                         ddvd_lbb_changed = 0;           
2042                 }
2043                 // report audio info
2044                 if (report_audio_info) { 
2045                         if (audio_format[audio_id] > -1) {
2046                                 uint16_t audio_lang = 0xFFFF;
2047                                 int audio_id_logical;
2048                                 audio_id_logical = dvdnav_get_audio_logical_stream(dvdnav, audio_id);
2049                                 audio_lang = dvdnav_audio_stream_to_lang(dvdnav, audio_id_logical);
2050                                 if (audio_lang == 0xFFFF)
2051                                         audio_lang = 0x2D2D;    
2052                                 int msg_old = msg;      // save and restore msg it may not bee empty
2053                                 msg = DDVD_SHOWOSD_AUDIO;
2054                                 safe_write(message_pipe, &msg, sizeof(int));
2055                                 safe_write(message_pipe, &audio_id, sizeof(int));
2056                                 safe_write(message_pipe, &audio_lang, sizeof(uint16_t));
2057                                 safe_write(message_pipe, &audio_format[audio_id], sizeof(int));
2058                                 msg = msg_old;
2059                                 report_audio_info = 0;
2060                         }
2061                 }
2062
2063         }
2064
2065 err_dvdnav:
2066         /* destroy dvdnav handle */
2067         if (dvdnav_close(dvdnav) != DVDNAV_STATUS_OK)
2068                 printf("Error on dvdnav_close: %s\n", dvdnav_err_to_string(dvdnav));
2069
2070 err_dvdnav_open:
2071         if (ioctl(ddvd_fdvideo, VIDEO_CLEAR_BUFFER) < 0)
2072                 perror("VIDEO_CLEAR_BUFFER");
2073         if (ioctl(ddvd_fdvideo, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX) < 0)
2074                 perror("VIDEO_SELECT_SOURCE");
2075         if (ioctl(ddvd_fdaudio, AUDIO_CLEAR_BUFFER) < 0)
2076                 perror("AUDIO_CLEAR_BUFFER");
2077         if (ioctl(ddvd_fdaudio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX) < 0)
2078                 perror("AUDIO_SELECT_SOURCE");
2079
2080         if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)      // restore AudioDecoder State
2081                 perror("AUDIO_SET_AV_SYNC");
2082         if (ioctl(ddvd_fdaudio, AUDIO_SET_BYPASS_MODE, 1) < 0)
2083                 perror("AUDIO_SET_BYPASS_MODE");
2084
2085         close(ddvd_ac3_fd);
2086 err_open_ac3_fd:
2087         close(ddvd_fdaudio);
2088 err_open_fdaudio:
2089         close(ddvd_fdvideo);
2090 err_open_fdvideo:
2091         close(ddvd_output_fd);
2092 err_open_output_fd:
2093
2094         if (have_liba52) {
2095                 a52_free(state);
2096                 ddvd_close_liba52();
2097         }
2098
2099         //Clear Screen
2100         //struct ddvd_resize_return blit_area;                  
2101         blit_area.x_start = blit_area.y_start = 0;
2102         blit_area.x_end = ddvd_screeninfo_xres;
2103         blit_area.y_end = ddvd_screeninfo_yres;
2104         memset(p_lfb, 0, ddvd_screeninfo_stride * ddvd_screeninfo_yres);
2105         msg = DDVD_SCREEN_UPDATE;
2106         safe_write(message_pipe, &msg, sizeof(int));
2107         safe_write(message_pipe, &blit_area, sizeof(struct ddvd_resize_return));
2108
2109 err_malloc:
2110         // clean up
2111         if (ddvd_lbb != NULL)
2112                 free(ddvd_lbb);
2113         if (ddvd_lbb2 != NULL)
2114                 free(ddvd_lbb2);
2115         if (last_iframe != NULL)
2116                 free(last_iframe);
2117         if (spu_buffer != NULL)
2118                 free(spu_buffer);
2119         if (spu_backbuffer != NULL)
2120                 free(spu_backbuffer);
2121
2122 #if CONFIG_API_VERSION == 3
2123         ddvd_unset_pcr_offset();
2124 #endif
2125         return res;
2126 }
2127
2128 /*
2129  * internal functions
2130  */
2131
2132 // reading from pipe
2133 static int ddvd_readpipe(int pipefd, void *dest, size_t bytes, int blocked_read)
2134 {
2135         size_t bytes_completed = 0;
2136
2137         while (bytes_completed < bytes) {
2138                 ssize_t rd = read(pipefd, dest + bytes_completed, bytes - bytes_completed);
2139                 if (rd < 0) {
2140                         if (errno == EAGAIN) {
2141                                 if (blocked_read || bytes_completed) {
2142                                         usleep(1);
2143                                         continue;
2144                                 }
2145                                 break;  // leave while loop
2146                         }
2147                         /* else if (errno == ????) // hier sollte evtl noch geschaut werden welcher error code kommt wenn die pipe geschlossen wurde... 
2148                            break; */
2149                         printf("unhandled read error %d(%m)\n", errno);
2150                 }
2151
2152                 bytes_completed += rd;
2153                 if (!blocked_read && !bytes_completed)
2154                         break;
2155         }
2156
2157         return bytes_completed;
2158 }
2159
2160 // get actual playing time
2161 static struct ddvd_time ddvd_get_osd_time(struct ddvd *playerconfig)
2162 {
2163         int titleNo;
2164         struct ddvd_time info;
2165         uint32_t pos, len;
2166
2167         info.pos_minutes = info.pos_hours = info.pos_seconds = info.pos_chapter = info.pos_title = 0;
2168         info.end_minutes = info.end_hours = info.end_seconds = info.end_chapter = 0;
2169
2170         dvdnav_get_number_of_titles(dvdnav, &info.end_title);
2171         dvdnav_current_title_info(dvdnav, &titleNo, &info.pos_chapter);
2172
2173         if (titleNo) {
2174                 dvdnav_get_number_of_parts(dvdnav, titleNo, &info.end_chapter);
2175                 dvdnav_get_position_in_title(dvdnav, &pos, &len);
2176
2177                 uint64_t len_s = ddvd_lastCellEventInfo.pgc_length / 90000;
2178                 uint64_t pos_s = ((ddvd_lastCellEventInfo.pgc_length / len) * pos) / 90000;
2179
2180                 info.pos_minutes = pos_s / 60;
2181                 info.pos_hours = info.pos_minutes / 60;
2182                 info.pos_minutes = info.pos_minutes - (info.pos_hours * 60);
2183                 info.pos_seconds = pos_s - ((info.pos_hours * 60) + info.pos_minutes) * 60;
2184                 info.end_minutes = len_s / 60;
2185                 info.end_hours = info.end_minutes / 60;
2186                 info.end_minutes = info.end_minutes - (info.end_hours * 60);
2187                 info.end_seconds = len_s - ((info.end_hours * 60) + info.end_minutes) * 60;
2188
2189                 info.pos_title = titleNo;
2190         }
2191
2192         playerconfig->next_time_update = ddvd_get_time() + 1000;
2193
2194         return info;
2195 }
2196
2197 // video out aspect/scale
2198 static int ddvd_check_aspect(int dvd_aspect, int dvd_scale_perm, int tv_aspect, int tv_mode)
2199 {
2200         int tv_scale = 0; // widescreen spu
2201
2202         if (dvd_aspect == 0) // dvd 4:3
2203         {
2204                 if((tv_aspect == DDVD_16_9 || tv_aspect == DDVD_16_10) && (tv_mode == DDVD_PAN_SCAN || tv_mode == DDVD_LETTERBOX))
2205                         tv_scale = 2; // pan_scan spu
2206                 if (tv_aspect == DDVD_4_3 && tv_mode == DDVD_PAN_SCAN)
2207                         tv_scale = 2; // pan_scan spu
2208                 if (tv_aspect == DDVD_4_3 && tv_mode == DDVD_LETTERBOX)
2209                         tv_scale = 1; // letterbox spu
2210         } 
2211         
2212         return tv_scale;
2213 }
2214
2215 // get timestamp
2216 static uint64_t ddvd_get_time(void)
2217 {
2218         static time_t t0 = 0;
2219         struct timeval t;
2220
2221         if (gettimeofday(&t, NULL) == 0) {
2222                 if (t0 == 0)
2223                         t0 = t.tv_sec;  // this avoids an overflow (we only work with deltas)
2224                 return (uint64_t) (t.tv_sec - t0) * 1000 + (uint64_t) (t.tv_usec / 1000);
2225         }
2226
2227         return 0;
2228 }
2229
2230 // Empty all Buffers
2231 static void ddvd_play_empty(int device_clear)
2232 {
2233         ddvd_wait_for_user = 0;
2234         ddvd_clear_buttons = 0;
2235         ddvd_lpcm_count = 0;
2236         ddvd_iframerun = 0;
2237         ddvd_still_frame = 0;
2238         ddvd_iframesend = 0;
2239         ddvd_last_iframe_len = 0;
2240         ddvd_spu_ptr = 0;
2241         ddvd_spu_backnr = 0;
2242         ddvd_spu_backptr = 0;
2243
2244         ddvd_wait_timer_active = 0;
2245         ddvd_wait_timer_end = 0;
2246
2247         ddvd_spu_timer_active = 0;
2248         ddvd_spu_timer_end = 0;
2249
2250         memset(ddvd_lbb, 0, 720 * 576); //clear backbuffer
2251         ddvd_lbb_changed = 1;
2252         
2253         if (device_clear)
2254                 ddvd_device_clear();
2255 }
2256
2257 // Empty Device Buffers
2258 static void ddvd_device_clear(void)
2259 {
2260         if (ioctl(ddvd_fdaudio, AUDIO_CLEAR_BUFFER) < 0)
2261                 perror("AUDIO_CLEAR_BUFFER");
2262         if (ioctl(ddvd_fdaudio, AUDIO_PLAY) < 0)
2263                 perror("AUDIO_PLAY");
2264
2265         if (ioctl(ddvd_fdvideo, VIDEO_CLEAR_BUFFER) < 0)
2266                 perror("VIDEO_CLEAR_BUFFER");
2267         if (ioctl(ddvd_fdvideo, VIDEO_PLAY) < 0)
2268                 perror("VIDEO_PLAY");
2269
2270         if (ioctl(ddvd_fdaudio, AUDIO_SET_AV_SYNC, 1) < 0)
2271                 perror("AUDIO_SET_AV_SYNC");
2272 }
2273
2274 // SPU Decoder
2275 static struct ddvd_spu_return ddvd_spu_decode_data(const uint8_t * buffer, int len)
2276 {
2277         int x1spu, x2spu, y1spu, y2spu, xspu, yspu;
2278         int offset[2];
2279         int size, datasize, controlsize, aligned, id;
2280         int menubutton = 0;
2281         int display_time = -1;
2282
2283         size = (buffer[0] << 8 | buffer[1]);
2284         datasize = (buffer[2] << 8 | buffer[3]);
2285         controlsize = (buffer[datasize + 2] << 8 | buffer[datasize + 3]);
2286
2287         //printf("SPU_dec: Size: %X Datasize: %X Controlsize: %X\n",size,datasize,controlsize);
2288         // parse header
2289         int i = datasize + 4;
2290
2291         while (i < size && buffer[i] != 0xFF) {
2292                 switch (buffer[i]) {
2293                 case 0x00:      /* menu button special color handling */
2294                         menubutton = 1;
2295                         memset(ddvd_lbb, 0, 720 * 576); //clear backbuffer
2296                         i++;
2297                         break;
2298                 case 0x01:      /* show */
2299                         i++;
2300                         break;
2301                 case 0x02:      /* hide */
2302                         i++;
2303                         break;
2304                 case 0x03:      /* palette */
2305                         {
2306                                 ddvd_spudec_clut_t *clut = (ddvd_spudec_clut_t *) (buffer + i + 1);
2307                                 //printf("update palette %d %d %d %d\n", clut->entry0, clut->entry1, clut->entry2, clut->entry3);
2308
2309                                 ddvd_bl[3 + 252] = ddvd_bl[clut->entry0];
2310                                 ddvd_gn[3 + 252] = ddvd_gn[clut->entry0];
2311                                 ddvd_rd[3 + 252] = ddvd_rd[clut->entry0];
2312
2313                                 ddvd_bl[2 + 252] = ddvd_bl[clut->entry1];
2314                                 ddvd_gn[2 + 252] = ddvd_gn[clut->entry1];
2315                                 ddvd_rd[2 + 252] = ddvd_rd[clut->entry1];
2316
2317                                 ddvd_bl[1 + 252] = ddvd_bl[clut->entry2];
2318                                 ddvd_gn[1 + 252] = ddvd_gn[clut->entry2];
2319                                 ddvd_rd[1 + 252] = ddvd_rd[clut->entry2];
2320
2321                                 ddvd_bl[0 + 252] = ddvd_bl[clut->entry3];
2322                                 ddvd_gn[0 + 252] = ddvd_gn[clut->entry3];
2323                                 ddvd_rd[0 + 252] = ddvd_rd[clut->entry3];
2324
2325                                 //CHANGE COLORMAP
2326                                 i += 3;
2327                         }
2328                         break;
2329                 case 0x04:      /* transparency palette */
2330                         {
2331                                 ddvd_spudec_clut_t *clut = (ddvd_spudec_clut_t *) (buffer + i + 1);
2332                                 //printf("update transp palette %d %d %d %d\n", clut->entry0, clut->entry1, clut->entry2, clut->entry3);
2333
2334                                 ddvd_tr[0 + 252] = (0xF - clut->entry3) * 0x1111;
2335                                 ddvd_tr[1 + 252] = (0xF - clut->entry2) * 0x1111;
2336                                 ddvd_tr[2 + 252] = (0xF - clut->entry1) * 0x1111;
2337                                 ddvd_tr[3 + 252] = (0xF - clut->entry0) * 0x1111;
2338
2339                                 //CHANGE COLORMAP
2340                                 i += 3;
2341                         }
2342                         break;
2343                 case 0x05:      /* image coordinates */
2344                         //printf("image coords\n");
2345                         xspu = x1spu = (((unsigned int)buffer[i + 1]) << 4) + (buffer[i + 2] >> 4);
2346                         yspu = y1spu = (((unsigned int)buffer[i + 4]) << 4) + (buffer[i + 5] >> 4);
2347                         x2spu = (((buffer[i + 2] & 0x0f) << 8) + buffer[i + 3]);
2348                         y2spu = (((buffer[i + 5] & 0x0f) << 8) + buffer[i + 6]);
2349                         //printf("%d %d %d %d\n", xspu, yspu, x2spu, y2spu);
2350                         i += 7;
2351                         break;
2352                 case 0x06:      /* image 1 / image 2 offsets */
2353                         //printf("image offsets\n");
2354                         offset[0] = (((unsigned int)buffer[i + 1]) << 8) + buffer[i + 2];
2355                         offset[1] = (((unsigned int)buffer[i + 3]) << 8) + buffer[i + 4];
2356                         //printf("%d %d\n", offset[0], offset[1]);
2357                         i += 5;
2358                         break;
2359                 default:
2360                         i++;
2361                         break;
2362                 }
2363         }
2364
2365         //get display time
2366         if (i + 6 <= size) {
2367                 if (buffer[i + 5] == 0x02 && buffer[i + 6] == 0xFF) {
2368                         display_time = ((buffer[i + 1] << 8) + buffer[i + 2]);
2369                         //printf("Display Time: %d\n",ddvd_display_time);
2370                 }
2371         }
2372         //printf("SPU_dec: Image coords x1: %d y1: %d x2: %d y2: %d\n",x1spu,y1spu,x2spu,y2spu);
2373         //printf("Offset[0]: %X Offset[1]: %X\n",offset[0],offset[1]);
2374
2375         // parse picture
2376
2377         aligned = 1;
2378         id = 0;
2379
2380         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 ;)
2381         {
2382                 u_int len;
2383                 u_int code;
2384
2385                 code = (aligned ? (buffer[offset[id]++] >> 4) : (buffer[offset[id] - 1] & 0xF));
2386                 aligned = aligned ? 0 : 1;
2387
2388                 if (code < 0x0004) {
2389                         code = (code << 4) | (aligned ? (buffer[offset[id]++] >> 4) : (buffer[offset[id] - 1] & 0xF));
2390                         aligned = aligned ? 0 : 1;
2391                         if (code < 0x0010) {
2392                                 code = (code << 4) | (aligned ? (buffer[offset[id]++] >> 4) : (buffer[offset[id] - 1] & 0xF));
2393                                 aligned = aligned ? 0 : 1;
2394                                 if (code < 0x0040) {
2395                                         code = (code << 4) | (aligned ? (buffer[offset[id]++] >> 4) : (buffer[offset[id] - 1] & 0xF));
2396                                         aligned = aligned ? 0 : 1;
2397                                 }
2398                         }
2399                 }
2400
2401                 len = code >> 2;
2402
2403                 if (len == 0)
2404                         len = (x2spu - xspu) + 1;
2405
2406                 memset(ddvd_lbb + xspu + 720 * (yspu), (code & 3) + 252, len);  //drawpixel into backbuffer
2407                 xspu += len;
2408                 if (xspu > x2spu) {
2409                         if (!aligned) {
2410                                 code = (aligned ? (buffer[offset[id]++] >> 4) : (buffer[offset[id] - 1] & 0xF));
2411                                 aligned = aligned ? 0 : 1;
2412                         }
2413                         xspu = x1spu;   //next line
2414                         yspu++;
2415                         id = id ? 0 : 1;
2416                 }
2417         }
2418         struct ddvd_spu_return return_code;
2419         return_code.display_time = display_time;
2420         return_code.x_start = x1spu;
2421         return_code.x_end = x2spu;
2422         return_code.y_start = y1spu;
2423         return_code.y_end = y2spu;
2424         
2425         return return_code;
2426 }
2427
2428 // blit to argb in 32bit mode
2429 static void ddvd_blit_to_argb(void *_dst, const void *_src, int pix)
2430 {
2431         unsigned long *dst = _dst;
2432         const unsigned char *src = _src;
2433         while (pix--) {
2434                 int p = (*src++);
2435                 int a, r, g, b;
2436                 if (p == 0) {
2437                         r = g = b = a = 0;      //clear screen (transparency)
2438                 } else {
2439                         a = 0xFF - (ddvd_tr[p] >> 8);
2440                         r = ddvd_rd[p] >> 8;
2441                         g = ddvd_gn[p] >> 8;
2442                         b = ddvd_bl[p] >> 8;
2443                 }
2444                 *dst++ = (a << 24) | (r << 16) | (g << 8) | (b << 0);
2445         }
2446 }
2447
2448 #if CONFIG_API_VERSION == 3
2449
2450 // set decoder buffer offsets to a minimum
2451 static void ddvd_set_pcr_offset(void)
2452 {
2453         write_string("/proc/stb/pcr/pcr_stc_offset", "200");
2454         write_string("/proc/stb/vmpeg/0/sync_offset", "200");
2455 }
2456
2457 // reset decoder buffer offsets
2458 static void ddvd_unset_pcr_offset(void)
2459 {
2460         write_string("/proc/stb/pcr/pcr_stc_offset", "2710");
2461         write_string("/proc/stb/vmpeg/0/sync_offset", "2710");
2462 }
2463
2464 #endif
2465
2466
2467 // "nearest neighbor" pixmap resizing
2468 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)
2469 {
2470     int x_ratio = (int)((xsource<<16)/(xdest-2*xoffset)) ;
2471     int y_ratio = (int)(((ysource-2*yoffset)<<16)/ydest) ;
2472         int yoffset2 = (yoffset<<16)/y_ratio;
2473         
2474         unsigned char *pixmap_tmp;
2475         pixmap_tmp = (unsigned char *)malloc(xsource*ysource*colors);
2476         memcpy(pixmap_tmp, pixmap, xsource*ysource*colors);
2477         memset(pixmap, 0, xdest * ydest * colors);      //clear screen ..
2478         struct ddvd_resize_return return_code;
2479         
2480         return_code.x_start=(xstart<<16)/x_ratio; // transform input resize area to destination area
2481         return_code.x_end=(xend<<16)/x_ratio;
2482         return_code.y_start=((ystart<<16)/y_ratio)-yoffset2;
2483         return_code.y_end=((yend<<16)/y_ratio)-yoffset2;
2484         return_code.y_start = return_code.y_start < 0 ? 0 : return_code.y_start;
2485         return_code.y_end = return_code.y_end > ydest ? ydest : return_code.y_end;
2486         
2487         int x2, y2, c, i ,j;
2488     for (i=return_code.y_start;i<return_code.y_end;i++) {
2489         for (j=return_code.x_start;j<return_code.x_end;j++) {
2490             x2 = ((j*x_ratio)>>16) ;
2491             y2 = ((i*y_ratio)>>16)+yoffset ;
2492             for (c=0; c<colors; c++)
2493                                 pixmap[((i*xdest)+j)*colors + c + xoffset*colors] = pixmap_tmp[((y2*xsource)+x2)*colors + c] ;
2494         }                
2495     }   
2496         free(pixmap_tmp);
2497         
2498         return_code.x_start+=xoffset; // correct xoffset
2499         return_code.x_end+=xoffset;
2500         
2501         return return_code;
2502 }
2503
2504 // bicubic picture resize
2505 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)
2506 {
2507         unsigned int xs,ys,xd,yd,dpixel,fx,fy;
2508         unsigned int c,tmp_i;
2509         int x,y,t,t1;
2510
2511         xs=xsource; // x-resolution source
2512         ys=ysource-2*yoffset; // y-resolution source
2513         xd=xdest-2*xoffset; // x-resolution destination
2514         yd=ydest; // y-resolution destination
2515         unsigned char *pixmap_tmp;
2516         pixmap_tmp = (unsigned char *)malloc(xsource*ysource*colors);
2517         memcpy(pixmap_tmp, pixmap, xsource*ysource*colors);
2518         memset(pixmap, 0, xdest * ydest * colors);      //clear screen ..
2519         struct ddvd_resize_return return_code;
2520         
2521         int yoffset2 = (yoffset<<16)/((ys<<16)/yd);
2522         return_code.x_start=(xstart<<16)/((xs<<16)/xd); // transform input resize area to destination area
2523         return_code.x_end=(xend<<16)/((xs<<16)/xd);
2524         return_code.y_start=((ystart<<16)/((ys<<16)/yd))-yoffset2;
2525         return_code.y_end=((yend<<16)/((ys<<16)/yd))-yoffset2;
2526         return_code.y_start = return_code.y_start < 0 ? 0 : return_code.y_start;
2527         return_code.y_end = return_code.y_end > ydest ? ydest : return_code.y_end;
2528         
2529         // get x scale factor, use bitshifting to get rid of floats
2530         fx=((xs-1)<<16)/xd;
2531
2532         // get y scale factor, use bitshifting to get rid of floats
2533         fy=((ys-1)<<16)/yd;
2534
2535         unsigned int sx1[xd],sx2[xd],sy1,sy2;
2536         
2537         // pre calculating sx1/sx2 for faster resizing
2538         for (x=return_code.x_start; x<return_code.x_end; x++) 
2539         {
2540                 // first x source pixel for calculating destination pixel
2541                 sx1[x]=(fx*x)>>16; //floor()
2542
2543                 // last x source pixel for calculating destination pixel
2544                 sx2[x]=sx1[x]+(fx>>16);
2545                 if (fx & 0x7FFF) //ceil()
2546                         sx2[x]++;
2547         }
2548         
2549         // Scale
2550         for (y=return_code.y_start; y<return_code.y_end; y++) 
2551         {
2552
2553                 // first y source pixel for calculating destination pixel
2554                 sy1=(fy*y)>>16; //floor()
2555
2556                 // last y source pixel for calculating destination pixel
2557                 sy2=sy1+(fy>>16);
2558                 if (fy & 0x7FFF) //ceil()
2559                         sy2++;
2560
2561                 for (x=return_code.x_start; x<return_code.x_end; x++) 
2562                 {
2563                         // we do this for every color
2564                         for (c=0; c<colors; c++) 
2565                         {
2566                                 // calculating destination pixel
2567                                 tmp_i=0;
2568                                 dpixel=0;
2569                                 for (t1=sy1; t1<sy2; t1++) 
2570                                 {
2571                                         for (t=sx1[x]; t<=sx2[x]; t++) 
2572                                         {
2573                                                 tmp_i+=(int)pixmap_tmp[(t*colors)+c+((t1+yoffset)*xs*colors)];
2574                                                 dpixel++;               
2575                                         }
2576                                 }
2577                                 // writing calculated pixel into destination pixmap
2578                                 pixmap[((x+xoffset)*colors)+c+(y*(xd+2*xoffset)*colors)]=tmp_i/dpixel;
2579                         }
2580                 }
2581         }
2582         free(pixmap_tmp);
2583         
2584         return_code.x_start+=xoffset; // correct xoffset
2585         return_code.x_end+=xoffset;
2586         
2587         return return_code;
2588 }
2589
2590 // very simple linear resize used for 1bypp mode
2591 struct ddvd_resize_return ddvd_resize_pixmap_1bpp(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) 
2592 {
2593         unsigned char *pixmap_tmp;
2594         pixmap_tmp = (unsigned char *)malloc(xsource * ysource * colors);
2595         memcpy(pixmap_tmp, pixmap, xsource * ysource * colors);
2596         memset(pixmap, 0, xdest * ydest * colors);      //clear screen ..
2597         struct ddvd_resize_return return_code;
2598         
2599         int i, fx, fy, tmp;
2600         
2601         // precalculate scale factor, use factor 10 to get rid of floats
2602         fx=xsource*10/(xdest-2*xoffset);
2603         fy=(ysource-2*yoffset)*10/ydest;
2604         int yoffset2 = (yoffset*10)/fy;
2605         
2606         return_code.x_start=(xstart*10)/fx; // transform input resize area to destination area
2607         return_code.x_end=(xend*10)/fx;
2608         return_code.y_start=(ystart*10)/fy;
2609         return_code.y_end=(yend*10)/fy;
2610         return_code.y_start = return_code.y_start < 0 ? 0 : return_code.y_start;
2611         return_code.y_end = return_code.y_end > ydest ? ydest : return_code.y_end;
2612         
2613         // scale x
2614         for (i = return_code.x_start; i < return_code.x_end; i++)
2615                 pixmap[i+xoffset]=pixmap_tmp[((fx*i)/10)];
2616
2617         // scale y
2618         for (i = return_code.y_start; i < return_code.y_end; i++)
2619         {
2620                 tmp=(fy*i)/10;
2621                 if (tmp != i)
2622                         memcpy(pixmap + (i*xdest), pixmap + (tmp + yoffset) * xdest, xdest);
2623         }       
2624         free(pixmap_tmp);
2625         
2626         return_code.x_start+=xoffset; // correct xoffset
2627         return_code.x_end+=xoffset;
2628         
2629         return return_code;
2630 }
2631