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