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