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