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