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