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