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