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