[vdr] xine plugin

Chad Flynt hoochster at sofnet.com
Thu Jan 26 16:03:38 CET 2006


I tried compiling Xine last night albeit was the CVS from yesterday, so 
maybe I need to grab the one from the 5th, but applied these patches and 
when I compile it and try to do the install I get the following:  This 
is for XINE-LIB

make  install-data-hook
make[4]: Entering directory 
`/usr/local/src/xine.cvs/xine-lib/src/xine-engine'
 chcon system_u:object_r:texrel_shlib_t /usr/lib/libxine.so
chcon: /usr/lib/libxine.so: Operation not supported
make[4]: *** [install-data-hook] Error 1
make[4]: Leaving directory 
`/usr/local/src/xine.cvs/xine-lib/src/xine-engine'
make[3]: *** [install-data-am] Error 2
make[3]: Leaving directory 
`/usr/local/src/xine.cvs/xine-lib/src/xine-engine'
make[2]: *** [install-am] Error 2
make[2]: Leaving directory 
`/usr/local/src/xine.cvs/xine-lib/src/xine-engine'
make[1]: *** [install-recursive] Error 1
make[1]: Leaving directory `/usr/local/src/xine.cvs/xine-lib/src'
make: *** [install-recursive] Error 1

Anyone by chance know what I am missing, maybe in my configure or 
whatnot?  Thanks for any help.

Jaroslaw Swierczynski wrote:

>Here are patches from vdr-xine 0.7.6 that I modified to apply to
>xine-lib and xine-ui snapshots from January 5th. They work fine.
>
>Btw, why the Xine developers haven't applied those patches yet?
>
>--
>Jaroslaw Swierczynski <swiergot at gmail.com>
>www.archlinux.org | www.juvepoland.com
>  
>
>------------------------------------------------------------------------
>
>diff -ruN xine-lib-1.1.1.orig/configure.ac xine-lib-1.1.1/configure.ac
>--- xine-lib-1.1.1.orig/configure.ac	2005-11-14 13:34:45.000000000 +0100
>+++ xine-lib-1.1.1/configure.ac	2006-01-02 19:49:17.000000000 +0100
>@@ -2298,6 +2298,7 @@
> src/video_out/vidix/drivers/Makefile
> src/xine-utils/Makefile
> src/xine-engine/Makefile
>+src/vdr/Makefile
> win32/Makefile
> win32/include/Makefile])
> AC_CONFIG_COMMANDS([default],[[chmod +x ./misc/SlackBuild ./misc/build_rpms.sh ./misc/relchk.sh]],[[]])
>@@ -2353,7 +2354,7 @@
> echo "   - stdin_fifo    - rtp"
> echo "   - http          - mms"
> echo "   - pnm           - rtsp"
>-echo "   - dvb"
>+echo "   - dvb           - vdr"
> if test x"$external_dvdnav" = "xyes"; then
>   echo "   - dvd (external libs)"
> else
>@@ -2533,6 +2534,7 @@
> echo "   - eq              - eq2"
> echo "   - boxblur         - denoise3d"
> echo "   - unsharp         - tvtime"
>+echo "   - vdr"
> echo "  * SFX:"
> echo "   - goom            - oscope"
> echo "   - fftscope        - mosaico"
>diff -ruN xine-lib-1.1.1.orig/include/xine.h.in xine-lib-1.1.1/include/xine.h.in
>--- xine-lib-1.1.1.orig/include/xine.h.in	2005-11-15 12:41:03.000000000 +0100
>+++ xine-lib-1.1.1/include/xine.h.in	2006-01-02 19:49:55.000000000 +0100
>@@ -1528,6 +1528,9 @@
> /* some space for further keys */
> #define XINE_EVENT_VDR_SETVIDEOWINDOW   350
> #define XINE_EVENT_VDR_FRAMESIZECHANGED 351
>+#define XINE_EVENT_VDR_SELECTAUDIO      352
>+#define XINE_EVENT_VDR_TRICKSPEEDMODE   353
>+#define XINE_EVENT_VDR_PLUGINSTARTED    354
> 
> /*
>  * xine event struct
>diff -ruN xine-lib-1.1.1.orig/src/demuxers/demux_mpeg_pes.c xine-lib-1.1.1/src/demuxers/demux_mpeg_pes.c
>--- xine-lib-1.1.1.orig/src/demuxers/demux_mpeg_pes.c	2005-02-06 16:26:17.000000000 +0100
>+++ xine-lib-1.1.1/src/demuxers/demux_mpeg_pes.c	2006-01-02 19:53:31.000000000 +0100
>@@ -51,7 +51,7 @@
> #define NUM_PREVIEW_BUFFERS   250
> #define DISC_TRESHOLD       90000
> 
>-#define WRAP_THRESHOLD     120000 
>+#define WRAP_THRESHOLD     270000
> #define PTS_AUDIO 0
> #define PTS_VIDEO 1
> 
>@@ -157,7 +157,7 @@
>   }
>   
>   if( pts )
>-    this->last_pts[video] = pts;
>+    this->last_pts[video] = this->last_pts[1-video] = pts;
> }
> 
> static void demux_mpeg_pes_parse_pack (demux_mpeg_pes_t *this, int preview_mode) {
>diff -ruN xine-lib-1.1.1.orig/src/libmpeg2/decode.c xine-lib-1.1.1/src/libmpeg2/decode.c
>--- xine-lib-1.1.1.orig/src/libmpeg2/decode.c	2005-06-18 00:33:02.000000000 +0200
>+++ xine-lib-1.1.1/src/libmpeg2/decode.c	2006-01-02 19:59:24.000000000 +0100
>@@ -251,7 +251,7 @@
> }
> 
> static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,
>-			       uint8_t * buffer)
>+			       uint8_t * buffer, int next_code)
> {
>     picture_t * picture;
>     int is_frame_done;
>@@ -408,6 +408,9 @@
> 	    /* abort(); */
> 	    break;
> 	}
>+	
>+	picture->mpeg1 = (next_code != 0xb5);
>+	
> 	if (mpeg2dec->force_aspect) picture->aspect_ratio_information = mpeg2dec->force_aspect;
> 
> 	if (mpeg2dec->is_sequence_needed ) {
>@@ -593,6 +596,12 @@
>     uint8_t * limit;
>     uint8_t byte;
> 
>+    if (mpeg2dec->code == 0xb7) {
>+       mpeg2dec->code = 0xb4;
>+       mpeg2dec->chunk_size = 0;
>+       return current;
>+    }
>+
>     shift = mpeg2dec->shift;
>     chunk_ptr = mpeg2dec->chunk_ptr;
>     limit = current + (mpeg2dec->chunk_buffer + BUFFER_SIZE - chunk_ptr);
>@@ -644,12 +653,12 @@
>     if (pts)
>       mpeg2dec->pts = pts;
> 
>-    while (current != end) {
>+    while (current != end || mpeg2dec->code == 0xb7) {
> 	code = mpeg2dec->code;
> 	current = copy_chunk (mpeg2dec, current, end);
> 	if (current == NULL) 
> 	    break;
>-	ret += parse_chunk (mpeg2dec, code, mpeg2dec->chunk_buffer);
>+	ret += parse_chunk (mpeg2dec, code, mpeg2dec->chunk_buffer, mpeg2dec->code);
>     }
> 
>     libmpeg2_accel_frame_completion(&mpeg2dec->accel, mpeg2dec->frame_format, 
>@@ -816,7 +825,7 @@
> void mpeg2_find_sequence_header (mpeg2dec_t * mpeg2dec,
> 				 uint8_t * current, uint8_t * end){
> 
>-  uint8_t code;
>+  uint8_t code, next_code;
>   picture_t *picture = mpeg2dec->picture;
> 
>   mpeg2dec->seek_mode = 1;
>@@ -826,6 +835,7 @@
>     current = copy_chunk (mpeg2dec, current, end);
>     if (current == NULL)
>       return ;
>+    next_code = mpeg2dec->code;
> 
>     /* printf ("looking for sequence header... %02x\n", code);  */
> 
>@@ -836,6 +846,9 @@
> 	printf ("libmpeg2: bad sequence header\n");
> 	continue;
>       }
>+      
>+      picture->mpeg1 = (next_code != 0xb5);
>+      
>       if (mpeg2dec->force_aspect) picture->aspect_ratio_information = mpeg2dec->force_aspect;
> 	  
>       if (mpeg2dec->is_sequence_needed) {
>diff -ruN xine-lib-1.1.1.orig/src/Makefile.am xine-lib-1.1.1/src/Makefile.am
>--- xine-lib-1.1.1.orig/src/Makefile.am	2005-01-14 16:24:08.000000000 +0100
>+++ xine-lib-1.1.1/src/Makefile.am	2006-01-02 19:50:25.000000000 +0100
>@@ -29,5 +29,6 @@
> 	libreal \
> 	libfaad \
> 	libflac \
>-        libmusepack \
>-	post
>+	libmusepack \
>+	post \
>+	vdr
>diff -ruN xine-lib-1.1.1.orig/src/post/planar/expand.c xine-lib-1.1.1/src/post/planar/expand.c
>--- xine-lib-1.1.1.orig/src/post/planar/expand.c	2005-09-11 15:37:31.000000000 +0200
>+++ xine-lib-1.1.1/src/post/planar/expand.c	2006-01-02 20:06:11.000000000 +0100
>@@ -62,6 +62,7 @@
> typedef struct expand_parameters_s {
>   int enable_automatic_shift;
>   int overlay_y_offset;
>+  int centre_cut_out_mode;
>   double aspect;
> } expand_parameters_t;
> 
>@@ -70,6 +71,8 @@
>   "enable automatic overlay shifting")
> PARAM_ITEM(POST_PARAM_TYPE_INT, overlay_y_offset, NULL, -500, 500, 0,
>   "manually shift the overlay vertically")
>+PARAM_ITEM(POST_PARAM_TYPE_BOOL, centre_cut_out_mode, NULL, 0, 1, 0,
>+  "cut out centered 4:3 image contained in 16:9 frame")
> PARAM_ITEM(POST_PARAM_TYPE_DOUBLE, aspect, NULL, 1.0, 3.5, 0,
>   "target aspect ratio")
> END_PARAM_DESCR(expand_param_descr)
>@@ -83,6 +86,8 @@
>   int                      overlay_y_offset;
>   double                   aspect;
>   int                      top_bar_height;
>+  int                      centre_cut_out_mode;
>+  int                      cropping_active;
> } post_expand_t;
> 
> /* plugin class functions */
>@@ -107,6 +112,8 @@
> 				       uint32_t height, double ratio, 
> 				       int format, int flags);
> 
>+static int            expand_draw(vo_frame_t *frame, xine_stream_t *stream);
>+
> /* overlay manager intercept check */
> static int            expand_intercept_ovl(post_video_port_t *port);
> 
>@@ -151,12 +158,15 @@
>   
>   this->enable_automatic_shift = 0;
>   this->overlay_y_offset       = 0;
>+  this->centre_cut_out_mode    = 0;
>+  this->cropping_active        = 0;
>   this->aspect                 = 4.0 / 3.0;
>   
>   port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output);
>   port->new_port.get_frame     = expand_get_frame;
>   port->intercept_ovl          = expand_intercept_ovl;
>   port->new_manager->add_event = expand_overlay_add_event;
>+  port->new_frame->draw        = expand_draw;
>   
>   input_param       = &this->parameter_input;
>   input_param->name = "parameters";
>@@ -211,6 +221,7 @@
> 
>   this->enable_automatic_shift = param->enable_automatic_shift;
>   this->overlay_y_offset       = param->overlay_y_offset;
>+  this->centre_cut_out_mode    = param->centre_cut_out_mode;
>   this->aspect                 = param->aspect;
>   return 1;
> }
>@@ -222,6 +233,7 @@
>   
>   param->enable_automatic_shift = this->enable_automatic_shift;
>   param->overlay_y_offset       = this->overlay_y_offset;
>+  param->centre_cut_out_mode    = this->centre_cut_out_mode;
>   param->aspect                 = this->aspect;
>   return 1;
> }
>@@ -322,6 +334,10 @@
> 
> static int expand_intercept_ovl(post_video_port_t *port)
> {
>+  post_expand_t         *this = (post_expand_t *)port->post;
>+
>+  if (this->centre_cut_out_mode && this->cropping_active) return 0;
>+
>   /* we always intercept overlay manager */
>   return 1;
> }
>@@ -350,3 +366,78 @@
>   
>   return port->original_manager->add_event(port->original_manager, event_gen);
> }
>+
>+static int is_pixel_black(vo_frame_t *frame, int x, int y)
>+{
>+  int Y = 0x00, Cr = 0x00, Cb = 0x00;
>+
>+  if (x < 0)              x = 0;
>+  if (x >= frame->width)  x = frame->width - 1;
>+  if (y < 0)              y = 0;
>+  if (y >= frame->height) y = frame->height - 1;
>+  
>+  switch (frame->format)
>+  {
>+  case XINE_IMGFMT_YV12:
>+    Y  = *(frame->base[ 0 ] + frame->pitches[ 0 ] * y     + x);
>+    Cr = *(frame->base[ 1 ] + frame->pitches[ 1 ] * y / 2 + x / 2);
>+    Cb = *(frame->base[ 2 ] + frame->pitches[ 2 ] * y / 2 + x / 2);
>+    break;
>+    
>+  case XINE_IMGFMT_YUY2:
>+    Y  = *(frame->base[ 0 ] + frame->pitches[ 0 ] * y + x * 2 + 0);
>+    x &= ~1;
>+    Cr = *(frame->base[ 0 ] + frame->pitches[ 0 ] * y + x * 2 + 1);
>+    Cb = *(frame->base[ 0 ] + frame->pitches[ 0 ] * y + x * 2 + 3);
>+    break;
>+  }
>+
>+  return (Y == 0x10 && Cr == 0x80 && Cb == 0x80);
>+}
>+
>+
>+static int expand_draw(vo_frame_t *frame, xine_stream_t *stream)
>+{
>+  post_video_port_t *port = (post_video_port_t *)frame->port;
>+  post_expand_t     *this = (post_expand_t *)port->post;
>+  int                skip;
>+
>+  if (this->centre_cut_out_mode && !frame->bad_frame)
>+  {
>+    /* expected area of inner 4:3 image */
>+    int centre_width = frame->width * (9 * 4) / (16 * 3);
>+    int centre_left  = (frame->width - centre_width ) / 2;
>+
>+    /* centre point for detecting a black frame */
>+    int centre_x = frame->width  / 2;
>+    int centre_y = frame->height / 2;
>+
>+    /* ignore a black frame as it could lead to wrong results */
>+    if (!is_pixel_black(frame, centre_x, centre_y))
>+    {
>+      /* coordinates for testing black border near the centre area */
>+      int test_left  = centre_left - 16;
>+      int test_right = centre_left + 16 + centre_width;
>+
>+      /* enable cropping when these pixels are black */
>+      this->cropping_active = is_pixel_black(frame, test_left, centre_y)
>+        && is_pixel_black(frame, test_right, centre_y);
>+    }
>+
>+    /* crop frame */
>+    if (this->centre_cut_out_mode && this->cropping_active) {
>+      frame->crop_left  += centre_left;
>+      frame->crop_right += centre_left;
>+
>+      /* get_frame() allocated an extra high frame */
>+      frame->crop_top    += (frame->next->height - frame->height) / 2;
>+      frame->crop_bottom += (frame->next->height - frame->height) / 2;
>+    }
>+  }
>+
>+  _x_post_frame_copy_down(frame, frame->next);
>+  skip = frame->next->draw(frame->next, stream);
>+  _x_post_frame_copy_up(frame, frame->next);
>+
>+  return skip;
>+}
>diff -ruN xine-lib-1.1.1.orig/src/vdr/input_vdr.c xine-lib-1.1.1/src/vdr/input_vdr.c
>--- xine-lib-1.1.1.orig/src/vdr/input_vdr.c	1970-01-01 01:00:00.000000000 +0100
>+++ xine-lib-1.1.1/src/vdr/input_vdr.c	2006-01-02 20:15:09.000000000 +0100
>@@ -0,0 +1,1840 @@
>+/*
>+ * Copyright (C) 2003-2004 the xine project
>+ *
>+ * This file is part of xine, a free video player.
>+ * 
>+ * xine is free software; you can redistribute it and/or modify
>+ * it under the terms of the GNU General Public License as published by
>+ * the Free Software Foundation; either version 2 of the License, or
>+ * (at your option) any later version.
>+ * 
>+ * xine is distributed in the hope that it will be useful,
>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>+ * GNU General Public License for more details.
>+ * 
>+ * You should have received a copy of the GNU General Public License
>+ * along with this program; if not, write to the Free Software
>+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
>+ *
>+ * $Id: input_vdr.c,v 1.51 2003/05/02 15:02:11 miguelfreitas Exp $
>+ */
>+
>+#ifdef HAVE_CONFIG_H
>+#include "config.h"
>+#endif
>+
>+#include <stdio.h>
>+#include <stdlib.h>
>+#include <string.h>
>+#include <fcntl.h>
>+#include <unistd.h>
>+#include <sys/stat.h>
>+#include <sys/poll.h>
>+#include <errno.h>
>+#include <pthread.h>
>+
>+#define LOG_MODULE "input_vdr"
>+#define LOG_VERBOSE
>+/*
>+#define LOG
>+*/
>+#include "xine_internal.h"
>+#include "xineutils.h"
>+#include "input_plugin.h"
>+
>+#include "input_vdr.h"
>+#include "post_vdr.h"
>+
>+
>+
>+#define VDR_MAX_NUM_WINDOWS 16
>+#define VDR_ABS_FIFO_DIR "/tmp/vdr-xine"
>+
>+
>+
>+#define BUF_SIZE 1024
>+
>+#define LOG_OSD(x)
>+/*
>+#define LOG_OSD(x) x
>+*/
>+
>+
>+typedef struct
>+{
>+  input_plugin_t      input_plugin;
>+   
>+  xine_stream_t      *stream;
>+  xine_stream_t      *stream_external;
>+
>+  int                 fh;
>+  int                 fh_control;
>+  int                 fh_result;
>+  int                 fh_event;
>+  
>+  char               *mrl;
>+
>+  off_t               curpos;
>+  char                seek_buf[ BUF_SIZE ];
>+   
>+  char                preview[ MAX_PREVIEW_SIZE ];
>+  off_t               preview_size;
>+   
>+  enum funcs          cur_func;
>+  off_t               cur_size;
>+  off_t               cur_done;
>+
>+  xine_osd_t         *osd_window[ VDR_MAX_NUM_WINDOWS ];
>+  uint8_t            *osd_buffer;
>+  uint32_t            osd_buffer_size;
>+  uint8_t             osd_unscaled_blending;
>+
>+  uint8_t             audio_channels;
>+  uint8_t             trick_speed_mode;
>+  uint8_t             mute_mode;
>+  uint8_t             dont_change_xine_volume;
>+  int                 last_volume;
>+  vdr_frame_size_changed_data_t frame_size;
>+  
>+  pthread_t           rpc_thread;
>+  int                 rpc_thread_shutdown;
>+  pthread_mutex_t     rpc_thread_shutdown_lock;
>+  pthread_cond_t      rpc_thread_shutdown_cond;
>+
>+  xine_event_queue_t *event_queue;
>+  xine_event_queue_t *event_queue_external;
>+
>+}
>+vdr_input_plugin_t;
>+
>+
>+
>+typedef struct
>+{
>+  input_class_t       input_class;
>+  xine_t             *xine;
>+  char               *mrls[ 2 ];
>+}
>+vdr_input_class_t;
>+
>+
>+
>+static int vdr_write(int f, void *b, int n)
>+{
>+  int t = 0, r;
>+  
>+  while (t < n)
>+  {
>+    /*
>+     * System calls are not a thread cancellation point in Linux
>+     * pthreads.  However, the RT signal sent to cancel the thread
>+     * will cause recv() to return with EINTR, and we can manually
>+     * check cancellation.
>+     */
>+    pthread_testcancel();
>+    r = write(f, ((char *)b) + t, n - t);
>+    pthread_testcancel();
>+
>+    if (r < 0
>+        && (errno == EINTR
>+          || errno == EAGAIN))
>+    {
>+      continue;
>+    }
>+    
>+    if (r < 0)
>+      return r;
>+    
>+    t += r;
>+  }
>+  
>+  return t;
>+}
>+
>+
>+
>+static int internal_write_event_play_external(vdr_input_plugin_t *this, uint32_t key);
>+
>+static void event_handler_external(void *user_data, const xine_event_t *event)
>+{
>+  vdr_input_plugin_t *this = (vdr_input_plugin_t *)user_data;
>+  uint32_t key = key_none;
>+/*  
>+  printf("event_handler_external(): event->type: %d\n", event->type);
>+*/
>+  switch (event->type)
>+  {
>+  case XINE_EVENT_UI_PLAYBACK_FINISHED:
>+    break;
>+
>+  default:
>+    return;
>+  }	
>+  
>+  if (0 != internal_write_event_play_external(this, key))
>+    xprintf(this->stream->xine, XINE_VERBOSITY_LOG, 
>+            _(LOG_MODULE ": input event write: %s.\n"), strerror(errno));
>+}
>+
>+static void external_stream_stop(vdr_input_plugin_t *this)
>+{
>+  if (this->stream_external)
>+  {    
>+    xine_stop(this->stream_external);
>+    xine_close(this->stream_external);
>+
>+    if (this->event_queue_external)
>+    {
>+      xine_event_dispose_queue(this->event_queue_external);
>+      this->event_queue_external = 0;
>+    }
>+
>+    _x_demux_flush_engine(this->stream_external);
>+    
>+    xine_dispose(this->stream_external);    
>+    this->stream_external = 0;
>+  }
>+}
>+
>+static void external_stream_play(vdr_input_plugin_t *this, char *file_name)
>+{
>+  external_stream_stop(this);
>+
>+  this->stream_external = xine_stream_new(this->stream->xine, this->stream->audio_out, this->stream->video_out);
>+  
>+  this->event_queue_external = xine_event_new_queue(this->stream_external);
>+
>+  xine_event_create_listener_thread(this->event_queue_external, event_handler_external, this);
>+
>+  if (!xine_open(this->stream_external, file_name)
>+      || !xine_play(this->stream_external, 0, 0))
>+  {
>+    uint32_t key = key_none;
>+    
>+    if ( 0 != internal_write_event_play_external(this, key))
>+      xprintf(this->stream->xine, XINE_VERBOSITY_LOG, 
>+              _(LOG_MODULE ": input event write: %s.\n"), strerror(errno));
>+  }
>+}
>+
>+static off_t vdr_read_abort(xine_stream_t *stream, int fd, char *buf, off_t todo)
>+{  
>+  off_t ret;
>+  
>+  while (1)
>+  {
>+    /*
>+     * System calls are not a thread cancellation point in Linux
>+     * pthreads.  However, the RT signal sent to cancel the thread
>+     * will cause recv() to return with EINTR, and we can manually
>+     * check cancellation.
>+     */
>+    pthread_testcancel();
>+    ret = _x_read_abort(stream, fd, buf, todo);
>+    pthread_testcancel();
>+    
>+    if (ret < 0
>+        && (errno == EINTR
>+          || errno == EAGAIN))
>+    {
>+      continue;
>+    }
>+    
>+    break;
>+  }
>+
>+  return ret;
>+}
>+
>+#define READ_DATA_OR_FAIL(kind, log) \
>+  data_##kind##_t *data = &data_union.kind; \
>+  { \
>+    log; \
>+    n = vdr_read_abort(this->stream, this->fh_control, (char *)data + sizeof (data->header), sizeof (*data) - sizeof (data->header)); \
>+    if (n != sizeof (*data) - sizeof (data->header)) \
>+      return -1; \
>+    \
>+    this->cur_size -= n; \
>+  } 
>+
>+static double _now()
>+{
>+  struct timeval tv;
>+  
>+  gettimeofday(&tv, 0);
>+
>+  return (tv.tv_sec * 1000000.0 + tv.tv_usec) / 1000.0;
>+}
>+
>+static off_t vdr_execute_rpc_command(vdr_input_plugin_t *this)
>+{
>+  data_union_t data_union;
>+  off_t n;
>+   
>+  n = vdr_read_abort(this->stream, this->fh_control, (char *)&data_union, sizeof (data_union.header));
>+  if (n != sizeof (data_union.header))
>+    return -1;
>+  
>+  this->cur_func = data_union.header.func;
>+  this->cur_size = data_union.header.len - sizeof (data_union.header);
>+  this->cur_done = 0;
>+
>+  switch (this->cur_func)
>+  {
>+  case func_nop:
>+    {
>+      READ_DATA_OR_FAIL(nop, lprintf("got NOP\n"));
>+    }
>+    break;
>+
>+  case func_osd_new:
>+    {
>+      READ_DATA_OR_FAIL(osd_new, LOG_OSD(lprintf("got OSDNEW\n")));
>+/*
>+      LOG_OSD(lprintf("... (%d,%d)-(%d,%d)\n", data->x, data->y, data->width, data->height));
>+
>+      fprintf(stderr, "vdr: osdnew %d\n", data->window);
>+*/    
>+      if (data->window >= VDR_MAX_NUM_WINDOWS)
>+        return -1;
>+      
>+      if (0 != this->osd_window[ data->window ])
>+        return -1;
>+      
>+      this->osd_window[ data->window ] = xine_osd_new(this->stream
>+                                                     , data->x
>+                                                     , data->y
>+                                                     , data->width
>+                                                     , data->height);
>+      
>+      if (0 == this->osd_window[ data->window ])
>+        return -1;
>+    }
>+    break;
>+
>+  case func_osd_free:
>+    {
>+      READ_DATA_OR_FAIL(osd_free, LOG_OSD(lprintf("got OSDFREE\n")));
>+/*      
>+      fprintf(stderr, "vdr: osdfree %d\n", data->window);
>+*/      
>+      if (data->window >= VDR_MAX_NUM_WINDOWS)
>+        return -1;
>+      
>+      if (0 != this->osd_window[ data->window ])
>+        xine_osd_free(this->osd_window[ data->window ]);
>+      
>+      this->osd_window[ data->window ] = 0;
>+    }
>+    break;
>+    
>+  case func_osd_show:
>+    {
>+      READ_DATA_OR_FAIL(osd_show, LOG_OSD(lprintf("got OSDSHOW\n")));
>+/*      
>+      fprintf(stderr, "vdr: osdshow %d\n", data->window);
>+*/      
>+      if (data->window >= VDR_MAX_NUM_WINDOWS)
>+        return -1;
>+      
>+      if (0 != this->osd_window[ data->window ])
>+      {
>+        if (this->osd_unscaled_blending)
>+          xine_osd_show_unscaled(this->osd_window[ data->window ], 0);
>+        else
>+          xine_osd_show(this->osd_window[ data->window ], 0);
>+      }
>+    }
>+    break;
>+    
>+  case func_osd_hide:
>+    {
>+      READ_DATA_OR_FAIL(osd_hide, LOG_OSD(lprintf("got OSDHIDE\n")));
>+/*      
>+      fprintf(stderr, "vdr: osdhide %d\n", data->window);
>+*/      
>+      if (data->window >= VDR_MAX_NUM_WINDOWS)
>+        return -1;
>+      
>+      if (0 != this->osd_window[ data->window ])
>+      {
>+        if (this->osd_unscaled_blending)
>+          xine_osd_show_unscaled(this->osd_window[ data->window ], 0);
>+        else
>+          xine_osd_show(this->osd_window[ data->window ], 0);
>+      }
>+    }
>+    break;
>+    
>+  case func_osd_flush:
>+    {
>+      double _t1, _t2;
>+      int _n = 0;
>+      
>+      READ_DATA_OR_FAIL(osd_flush, LOG_OSD(lprintf("got OSDFLUSH\n")));
>+/*      
>+      fprintf(stderr, "vdr: osdflush +\n");
>+*/
>+      _t1 = _now();
>+      
>+      while (_x_query_unprocessed_osd_events(this->stream))
>+      {
>+/*        
>+        fprintf(stderr, "redraw_needed: 1\n");
>+*/        
>+/*        sched_yield(); */
>+        xine_usec_sleep(5000);
>+        _n++;
>+      }
>+
>+      _t2 = _now();
>+      fprintf(stderr, "vdr: osdflush: n: %d, %.1lf\n", _n, _t2 - _t1);
>+/*      
>+      fprintf(stderr, "redraw_needed: 0\n");        
>+      
>+      fprintf(stderr, "vdr: osdflush -\n");
>+*/
>+    }
>+    break;
>+    
>+  case func_osd_set_position:
>+    {
>+      READ_DATA_OR_FAIL(osd_set_position, LOG_OSD(lprintf("got OSDSETPOSITION\n")));
>+/*
>+      fprintf(stderr, "vdr: osdsetposition %d\n", data->window);    
>+*/      
>+      if (data->window >= VDR_MAX_NUM_WINDOWS)
>+        return -1;
>+      
>+      if (0 != this->osd_window[ data->window ])
>+        xine_osd_set_position(this->osd_window[ data->window ], data->x, data->y);
>+    }
>+    break;
>+  
>+  case func_osd_draw_bitmap:
>+    {
>+      READ_DATA_OR_FAIL(osd_draw_bitmap, LOG_OSD(lprintf("got OSDDRAWBITMAP\n")));
>+/*
>+      fprintf(stderr, "vdr: osddrawbitmap %d\n", data->window);    
>+*/      
>+      if (this->osd_buffer_size < this->cur_size)
>+      {
>+        if (this->osd_buffer)
>+          free(this->osd_buffer);
>+        
>+        this->osd_buffer_size = 0;
>+        
>+        this->osd_buffer = xine_xmalloc(this->cur_size);
>+        if (!this->osd_buffer)
>+          return -1;
>+        
>+        this->osd_buffer_size = this->cur_size;
>+      }
>+      
>+      n = vdr_read_abort (this->stream, this->fh_control, (char *)this->osd_buffer, this->cur_size);
>+      if (n != this->cur_size)
>+        return -1;
>+      
>+      this->cur_size -= n;
>+      
>+      if (data->window >= VDR_MAX_NUM_WINDOWS)
>+        return -1;
>+      
>+      if (0 != this->osd_window[ data->window ])
>+        xine_osd_draw_bitmap(this->osd_window[ data->window ], this->osd_buffer, data->x, data->y, data->width, data->height, 0);
>+    }
>+    break;
>+    
>+  case func_set_color:
>+    {
>+      uint32_t vdr_color[ 256 ];
>+      
>+      READ_DATA_OR_FAIL(set_color, lprintf("got SETCOLOR\n"));
>+      
>+      if (((data->num + 1) * sizeof (uint32_t)) != this->cur_size)
>+        return -1;
>+      
>+      n = vdr_read_abort (this->stream, this->fh_control, (char *)&vdr_color[ data->index ], this->cur_size);
>+      if (n != this->cur_size)
>+        return -1;
>+      
>+      this->cur_size -= n;
>+      
>+      if (data->window >= VDR_MAX_NUM_WINDOWS)
>+        return -1;
>+      
>+      if (0 != this->osd_window[ data->window ])
>+      {
>+        uint32_t color[ 256 ];
>+        uint8_t trans[ 256 ];
>+        
>+        xine_osd_get_palette(this->osd_window[ data->window ], color, trans);
>+        
>+        {
>+          int i;
>+          
>+          for (i = data->index; i <= (data->index + data->num); i++)
>+          {
>+            int a = (vdr_color[ i ] & 0xff000000) >> 0x18;
>+            int r = (vdr_color[ i ] & 0x00ff0000) >> 0x10;
>+            int g = (vdr_color[ i ] & 0x0000ff00) >> 0x08;
>+            int b = (vdr_color[ i ] & 0x000000ff) >> 0x00;
>+            
>+            int y  = (( 66 * r + 129 * g +  25 * b + 128) >> 8) +  16;
>+            int cr = ((112 * r -  94 * g -  18 * b + 128) >> 8) + 128;
>+            int cb = ((-38 * r -  74 * g + 112 * b + 128) >> 8) + 128;
>+
>+            uint8_t *dst = (uint8_t *)&color[ i ];
>+            *dst++ = cb;
>+            *dst++ = cr;
>+            *dst++ = y;
>+            *dst++ = 0;
>+
>+            trans[ i ] = a >> 4;
>+          }
>+        }
>+        
>+        xine_osd_set_palette(this->osd_window[ data->window ], color, trans);
>+      }
>+    }
>+    break;
>+
>+  case func_play_external:
>+    {
>+      char file_name[ 1024 ];
>+      int file_name_len = 0;
>+      
>+      READ_DATA_OR_FAIL(play_external, lprintf("got PLAYEXTERNAL\n"));
>+
>+      file_name_len = this->cur_size;
>+
>+      if (0 != file_name_len)
>+      {
>+        if (file_name_len <= 1
>+            || file_name_len > sizeof (file_name))
>+        {
>+          return -1;
>+        }
>+      
>+        n = vdr_read_abort (this->stream, this->fh_control, file_name, file_name_len);
>+        if (n != file_name_len)
>+          return -1;
>+      
>+        if (file_name[ file_name_len - 1 ] != '\0')
>+          return -1;
>+      
>+        this->cur_size -= n;
>+      }
>+
>+      lprintf((file_name_len > 0) ? "----------- play external: %s\n" : "---------- stop external\n", file_name);
>+      
>+      if (file_name_len > 0)
>+        external_stream_play(this, file_name);
>+      else
>+        external_stream_stop(this);
>+    }
>+    break;
>+
>+  case func_clear:
>+    {
>+      READ_DATA_OR_FAIL(clear, lprintf("got CLEAR\n"));
>+
>+      {
>+fprintf(stderr, "+++ CLEAR(%d)\n", data->n);       
>+/*        
>+        if (!this->dont_change_xine_volume)
>+          xine_set_param(this->stream, XINE_PARAM_AUDIO_VOLUME, 0);
>+*/      
>+        _x_demux_flush_engine(this->stream);
>+        _x_demux_seek(this->stream, 0, 0, 0);
>+
>+        _x_stream_info_reset(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE);
>+	_x_meta_info_reset(this->stream, XINE_META_INFO_AUDIOCODEC);
>+
>+        _x_trigger_relaxed_frame_drop_mode(this->stream);
>+/*        _x_reset_relaxed_frame_drop_mode(this->stream); */
>+/*      
>+        if (!this->dont_change_xine_volume)
>+          xine_set_param(this->stream, XINE_PARAM_AUDIO_VOLUME, this->last_volume);
>+*/
>+fprintf(stderr, "--- CLEAR(%d)\n", data->n);       
>+      }
>+    }
>+    break;
>+
>+  case func_first_frame:
>+    {
>+      READ_DATA_OR_FAIL(first_frame, lprintf("got FIRST FRAME\n"));
>+
>+      _x_trigger_relaxed_frame_drop_mode(this->stream);
>+/*      _x_reset_relaxed_frame_drop_mode(this->stream); */
>+    }
>+    break;
>+
>+  case func_still_frame:
>+    {
>+      READ_DATA_OR_FAIL(still_frame, lprintf("got STILL FRAME\n"));
>+
>+      _x_reset_relaxed_frame_drop_mode(this->stream);
>+    }
>+    break;
>+
>+  case func_set_video_window:
>+    {
>+      READ_DATA_OR_FAIL(set_video_window, lprintf("got SET VIDEO WINDOW\n"));
>+/*
>+      fprintf(stderr, "svw: (%d, %d)x(%d, %d), (%d, %d)\n", data->x, data->y, data->w, data->h, data->wRef, data->hRef);
>+*/    
>+      {
>+        xine_event_t event;
>+        vdr_set_video_window_data_t event_data;
>+        
>+        event_data.x = data->x;
>+        event_data.y = data->y;
>+        event_data.w = data->w;
>+        event_data.h = data->h;
>+        event_data.w_ref = data->w_ref;
>+        event_data.h_ref = data->h_ref;
>+        
>+        event.type = XINE_EVENT_VDR_SETVIDEOWINDOW;
>+        event.data = &event_data;
>+        event.data_length = sizeof (event_data);
>+        
>+        xine_event_send(this->stream, &event);
>+      }
>+    }
>+    break;
>+    
>+  case func_select_audio:
>+    {
>+      READ_DATA_OR_FAIL(select_audio, lprintf("got SELECT AUDIO\n"));
>+
>+      this->audio_channels = data->channels;
>+      
>+      {
>+        xine_event_t event;
>+        vdr_select_audio_data_t event_data;
>+        
>+        event_data.channels = this->audio_channels;
>+        
>+        event.type = XINE_EVENT_VDR_SELECTAUDIO;
>+        event.data = &event_data;
>+        event.data_length = sizeof (event_data);
>+        
>+        xine_event_send(this->stream, &event);
>+      }
>+    }
>+    break;
>+    
>+  case func_trick_speed_mode:
>+    {
>+      READ_DATA_OR_FAIL(trick_speed_mode, lprintf("got TRICK SPEED MODE\n"));
>+
>+      this->trick_speed_mode = data->on;
>+      
>+      _x_demux_seek(this->stream, 0, 0, 0);
>+
>+      {
>+        xine_event_t event;
>+        
>+        event.type = XINE_EVENT_VDR_TRICKSPEEDMODE;
>+        event.data = 0;
>+        event.data_length = this->trick_speed_mode;
>+/*        fprintf(stderr, "************************: %p, %d\n", event.data, event.data_length); */
>+        xine_event_send(this->stream, &event);
>+      }
>+    }
>+    break;
>+    
>+  case func_flush:
>+    {
>+      READ_DATA_OR_FAIL(flush, lprintf("got FLUSH\n"));
>+
>+      if (!data->just_wait)
>+      {
>+        if (this->stream->video_fifo)
>+        {
>+          buf_element_t *buf = this->stream->video_fifo->buffer_pool_alloc(this->stream->video_fifo);
>+          if (!buf)
>+          {
>+            xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _(LOG_MODULE ": buffer_pool_alloc() failed!\n"));
>+            return -1;
>+          }
>+          
>+          buf->type = BUF_CONTROL_FLUSH_DECODER;
>+          
>+          this->stream->video_fifo->put(this->stream->video_fifo, buf);
>+        }
>+      }
>+      
>+      {
>+        double _t1, _t2;
>+        int _n = 0;
>+        
>+        int vb = -1, ab = -1, vf = -1, af = -1;
>+        
>+        uint8_t timed_out = 0;
>+        
>+        struct timeval now, then;
>+        
>+        if (data->ms_timeout >= 0)
>+        {
>+          gettimeofday(&now, 0);
>+          
>+          then = now;
>+          then.tv_usec += (data->ms_timeout % 1000) * 1000;
>+          then.tv_sec  += (data->ms_timeout / 1000);
>+          
>+          if (then.tv_usec >= 1000000)
>+          {
>+            then.tv_usec -= 1000000;
>+            then.tv_sec  += 1;
>+          }
>+        }
>+        else
>+        {
>+          then.tv_usec = 0;
>+          then.tv_sec  = 0;
>+        }
>+
>+        _t1 = _now();
>+        
>+        while (1)
>+        {
>+          _x_query_buffer_usage(this->stream, &vb, &ab, &vf, &af);
>+          
>+          if (vb <= 0 && ab <= 0 && vf <= 0 && af <= 0)
>+            break;
>+          
>+          if (data->ms_timeout >= 0
>+              && timercmp(&now, &then, >))
>+          {
>+            timed_out++;
>+            break;
>+          }
>+          
>+/*          sched_yield(); */
>+          xine_usec_sleep(5000);
>+          _n++;
>+          
>+          if (data->ms_timeout >= 0)
>+            gettimeofday(&now, 0);          
>+        }
>+
>+        _t2 = _now();
>+        fprintf(stderr, "vdr: flush: n: %d, %.1lf\n", _n, _t2 - _t1);
>+        
>+        xprintf(this->stream->xine
>+                , XINE_VERBOSITY_LOG
>+                , _(LOG_MODULE ": flush buffers (vb: %d, ab: %d, vf: %d, af: %d) %s.\n")
>+                , vb, ab, vf, af
>+                , (timed_out ? "timed out" : "done"));
>+        
>+        {
>+          result_flush_t result_flush;
>+          result_flush.header.func = data->header.func;
>+          result_flush.header.len = sizeof (result_flush);
>+          
>+          result_flush.timed_out = timed_out;
>+          
>+          if (sizeof (result_flush) != vdr_write(this->fh_result, &result_flush, sizeof (result_flush)))
>+            return -1;
>+        }
>+      }
>+    }
>+    break;
>+
>+  case func_mute:
>+    {
>+      READ_DATA_OR_FAIL(mute, lprintf("got MUTE\n"));
>+      
>+      xine_set_param(this->stream, XINE_PARAM_AUDIO_MUTE, data->mute);
>+    }
>+    break;
>+
>+  case func_set_volume:
>+    {
>+      READ_DATA_OR_FAIL(set_volume, lprintf("got SETVOLUME\n"));
>+
>+      {
>+        int change_volume = !this->dont_change_xine_volume;
>+        int do_mute   = (0 != this->last_volume && 0 == data->volume);
>+        int do_unmute = (0 == this->last_volume && 0 != data->volume);
>+        int report_change = 0;
>+        
>+        this->last_volume = data->volume;
>+
>+        if (do_mute || do_unmute)
>+        {
>+          switch (this->mute_mode)
>+          {
>+          case INPUT_VDR_MUTE_EXECUTE:
>+            report_change = 1;
>+            xine_set_param(this->stream, XINE_PARAM_AUDIO_MUTE, do_mute);
>+            
>+          case INPUT_VDR_MUTE_IGNORE:
>+            if (do_mute)
>+              change_volume = 0;
>+            break;
>+
>+          case INPUT_VDR_MUTE_SIMULATE:
>+            change_volume = 1;
>+            break;
>+
>+          default:
>+            return -1;
>+          };
>+        }
>+        
>+        if (change_volume)
>+        {
>+          report_change = 1;
>+          xine_set_param(this->stream, XINE_PARAM_AUDIO_VOLUME, this->last_volume);
>+        }
>+
>+        if (report_change)
>+        {
>+          xine_event_t            event;
>+          xine_audio_level_data_t data;
>+          
>+          data.left
>+            = data.right
>+            = xine_get_param(this->stream, XINE_PARAM_AUDIO_VOLUME);
>+          data.mute
>+            = xine_get_param(this->stream, XINE_PARAM_AUDIO_MUTE);
>+          
>+          event.type        = XINE_EVENT_AUDIO_LEVEL;
>+          event.data        = &data;
>+          event.data_length = sizeof (data);
>+          
>+          xine_event_send(this->stream, &event);
>+        }
>+      }
>+    }
>+    break;
>+
>+  case func_set_speed:
>+    {
>+      READ_DATA_OR_FAIL(set_speed, lprintf("got SETSPEED\n"));
>+      
>+      lprintf("... got SETSPEED %d\n", data->speed);
>+      
>+      if (data->speed != xine_get_param(this->stream, XINE_PARAM_FINE_SPEED))
>+        xine_set_param(this->stream, XINE_PARAM_FINE_SPEED, data->speed);
>+    }
>+    break;
>+
>+  case func_set_prebuffer:
>+    {
>+      READ_DATA_OR_FAIL(set_prebuffer, lprintf("got SETPREBUFFER\n"));
>+
>+      xine_set_param(this->stream, XINE_PARAM_METRONOM_PREBUFFER, data->prebuffer);
>+    }
>+    break;
>+
>+  case func_metronom:
>+    {
>+      READ_DATA_OR_FAIL(metronom, lprintf("got METRONOM\n"));
>+
>+      _x_demux_control_newpts(this->stream, data->pts, data->flags);
>+    }
>+    break;
>+    
>+  case func_start:
>+    {
>+      READ_DATA_OR_FAIL(start, lprintf("got START\n"));
>+
>+      _x_demux_control_start(this->stream);
>+      _x_demux_seek(this->stream, 0, 0, 0);
>+    }
>+    break;
>+
>+  case func_wait:
>+    {
>+      READ_DATA_OR_FAIL(wait, lprintf("got WAIT\n"));
>+    }
>+    break;
>+
>+  case func_setup:
>+    {
>+      READ_DATA_OR_FAIL(setup, lprintf("got SETUP\n"));
>+
>+      this->osd_unscaled_blending   = data->osd_unscaled_blending;
>+      this->dont_change_xine_volume = data->dont_change_xine_volume;
>+      this->mute_mode               = data->mute_mode;
>+    }
>+    break;
>+
>+  case func_grab_image:
>+    {
>+      READ_DATA_OR_FAIL(grab_image, lprintf("got GRABIMAGE\n"));
>+
>+      {
>+        off_t ret_val = -1;
>+        
>+        uint8_t *img   = 0;
>+        int frame_size = 0;
>+        int width      = 0;
>+        int height     = 0;       
>+        int ratio_code = 0;
>+        int format     = 0;
>+        
>+        int orig_speed = xine_get_param(this->stream, XINE_PARAM_FINE_SPEED);
>+        if (XINE_SPEED_PAUSE != orig_speed)
>+          xine_set_param(this->stream, XINE_PARAM_FINE_SPEED, XINE_SPEED_PAUSE);
>+        
>+        if (xine_get_current_frame(this->stream, &width, &height, &ratio_code, &format, 0))
>+        {
>+          switch (format)
>+          {
>+          case XINE_IMGFMT_YV12:
>+            frame_size = width * height
>+              + ((width + 1) / 2) * ((height + 1) / 2)
>+              + ((width + 1) / 2) * ((height + 1) / 2);
>+            break;
>+            
>+          case XINE_IMGFMT_YUY2:
>+            frame_size = width * height
>+              + ((width + 1) / 2) * height
>+              + ((width + 1) / 2) * height;
>+            break;
>+          }
>+          
>+          img = xine_xmalloc(frame_size);
>+          
>+          if (!xine_get_current_frame(this->stream, &width, &height, &ratio_code, &format, img))
>+            frame_size = 0;
>+          
>+          if (ratio_code == XINE_VO_ASPECT_SQUARE)
>+            ratio_code = 10000;
>+          else if (ratio_code == XINE_VO_ASPECT_4_3)
>+            ratio_code = 13333;
>+          else if (ratio_code == XINE_VO_ASPECT_ANAMORPHIC)
>+            ratio_code = 17778;
>+          else if (ratio_code == XINE_VO_ASPECT_DVB)
>+            ratio_code = 21100;
>+          
>+          if (0 == frame_size)
>+          {
>+            width      = 0;
>+            height     = 0;
>+            ratio_code = 0;
>+          }          
>+        }
>+        
>+        if (XINE_SPEED_PAUSE != orig_speed)
>+          xine_set_param(this->stream, XINE_PARAM_FINE_SPEED, orig_speed);
>+        
>+        {
>+          result_grab_image_t result_grab_image;
>+          result_grab_image.header.func = data->header.func;
>+          result_grab_image.header.len = sizeof (result_grab_image) + frame_size;
>+          
>+          result_grab_image.width  = width;
>+          result_grab_image.height = height;
>+          result_grab_image.ratio  = ratio_code;
>+          result_grab_image.format = format;
>+          
>+          if (sizeof (result_grab_image) == vdr_write(this->fh_result, &result_grab_image, sizeof (result_grab_image)))
>+          {
>+            if (frame_size == vdr_write(this->fh_result, img, frame_size))
>+              ret_val = 0;
>+          }
>+        }
>+        
>+        if (img)
>+          free(img);
>+        
>+        if (ret_val != 0)
>+          return ret_val;
>+      }
>+    }
>+    break;
>+    
>+  case func_get_pts:
>+    {
>+      READ_DATA_OR_FAIL(get_pts, lprintf("got GETPTS\n"));
>+      
>+      {
>+        result_get_pts_t result_get_pts;
>+        result_get_pts.header.func = data->header.func;
>+        result_get_pts.header.len = sizeof (result_get_pts);
>+        
>+        result_get_pts.pts = xine_get_current_vpts(this->stream) - this->stream->metronom->get_option(this->stream->metronom, METRONOM_VPTS_OFFSET);
>+        
>+        if (sizeof (result_get_pts) != vdr_write(this->fh_result, &result_get_pts, sizeof (result_get_pts)))
>+          return -1;
>+      }
>+    }
>+    break;
>+
>+  case func_video_size:
>+    {
>+      READ_DATA_OR_FAIL(video_size, lprintf("got VIDEO SIZE\n"));
>+
>+      {
>+        int format;
>+        
>+        result_video_size_t result_video_size;
>+        result_video_size.header.func = data->header.func;
>+        result_video_size.header.len = sizeof (result_video_size);
>+        
>+        result_video_size.top    = -1;
>+        result_video_size.left   = -1;
>+        result_video_size.width  = -1;
>+        result_video_size.height = -1;
>+        result_video_size.ratio  = 0;
>+        
>+        xine_get_current_frame(this->stream, &result_video_size.width, &result_video_size.height, &result_video_size.ratio, &format, 0);
>+        
>+        if (result_video_size.ratio == XINE_VO_ASPECT_SQUARE)
>+          result_video_size.ratio = 10000;
>+        else if (result_video_size.ratio == XINE_VO_ASPECT_4_3)
>+          result_video_size.ratio = 13333;
>+        else if (result_video_size.ratio == XINE_VO_ASPECT_ANAMORPHIC)
>+          result_video_size.ratio = 17778;
>+        else if (result_video_size.ratio == XINE_VO_ASPECT_DVB)
>+          result_video_size.ratio = 21100;
>+        
>+        if (0 != this->frame_size.x
>+            || 0 != this->frame_size.y
>+            || 0 != this->frame_size.w
>+            || 0 != this->frame_size.h)
>+        {
>+          result_video_size.left   = this->frame_size.x;
>+          result_video_size.top    = this->frame_size.y;
>+          result_video_size.width  = this->frame_size.w;
>+          result_video_size.height = this->frame_size.h;
>+        }
>+        
>+        if (sizeof (result_video_size) != vdr_write(this->fh_result, &result_video_size, sizeof (result_video_size)))
>+          return -1;
>+      }
>+    }
>+    break;
>+
>+  case func_reset_audio:
>+    {
>+      double _t1, _t2;
>+      int _n = 0;
>+      
>+      READ_DATA_OR_FAIL(reset_audio, lprintf("got RESET AUDIO\n"));
>+
>+      if (this->stream->audio_fifo)
>+      {
>+        xine_set_param(this->stream, XINE_PARAM_IGNORE_AUDIO, 1);
>+        xine_set_param(this->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, -2);
>+
>+        _t1 = _now();
>+        
>+        while (1)
>+        {
>+          int n = xine_get_stream_info(this->stream, XINE_STREAM_INFO_MAX_AUDIO_CHANNEL);
>+          if (n <= 0)
>+            break;
>+          
>+          /* keep the decoder running */
>+          if (this->stream->audio_fifo)
>+          {
>+            buf_element_t *buf = this->stream->audio_fifo->buffer_pool_alloc(this->stream->audio_fifo);
>+            if (!buf)
>+            {
>+              xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _(LOG_MODULE ": buffer_pool_alloc() failed!\n"));
>+              return -1;
>+            }
>+            
>+            buf->type = BUF_CONTROL_NOP;
>+            
>+            this->stream->audio_fifo->put(this->stream->audio_fifo, buf);
>+          }
>+          
>+/*          sched_yield(); */
>+          xine_usec_sleep(5000);
>+          _n++;
>+        }
>+
>+        _t2 = _now();
>+        fprintf(stderr, "vdr: reset_audio: n: %d, %.1lf\n", _n, _t2 - _t1);
>+        
>+        xine_set_param(this->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, -1);
>+
>+        _x_stream_info_reset(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE);
>+        _x_meta_info_reset(this->stream, XINE_META_INFO_AUDIOCODEC);
>+
>+        xine_set_param(this->stream, XINE_PARAM_IGNORE_AUDIO, 0);
>+      }
>+    }
>+    break;
>+    
>+  default:
>+    lprintf("unknown function: %d\n", this->cur_func);
>+  }
>+    
>+  if (this->cur_size != this->cur_done)
>+  {
>+    off_t skip = this->cur_size - this->cur_done;
>+
>+    lprintf("func: %d, skipping: %lld\n", this->cur_func, skip);
>+     
>+    while (skip > BUF_SIZE)
>+    {
>+      n = vdr_read_abort(this->stream, this->fh_control, this->seek_buf, BUF_SIZE);
>+      if (n != BUF_SIZE)
>+        return -1;
>+
>+      skip -= BUF_SIZE;
>+    }
>+
>+    n = vdr_read_abort(this->stream, this->fh_control, this->seek_buf, skip);
>+    if (n != skip)
>+      return -1;
>+
>+    this->cur_done = this->cur_size;
>+
>+    return -1;
>+  }
>+
>+  return 0;
>+}
>+
>+static void *vdr_rpc_thread_loop(void *arg)
>+{
>+  vdr_input_plugin_t *this = (vdr_input_plugin_t *)arg;
>+  int frontend_lock_failures = 0;
>+  int failed = 0;
>+  
>+  while (!failed
>+    && !this->rpc_thread_shutdown)
>+  {
>+    struct timeval timeout;
>+    fd_set rset;
>+  
>+    FD_ZERO(&rset);
>+    FD_SET(this->fh_control, &rset);
>+
>+    timeout.tv_sec  = 0;
>+    timeout.tv_usec = 50000;
>+
>+    if (select(this->fh_control + 1, &rset, NULL, NULL, &timeout) > 0)
>+    {
>+      if (!_x_lock_frontend(this->stream, 100))
>+      {
>+        if (++frontend_lock_failures > 50)
>+        {
>+          failed = 1;
>+          xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
>+                  LOG_MODULE ": locking frontend for rpc command execution failed, exiting ...\n");
>+        }
>+      }
>+      else
>+      {
>+        frontend_lock_failures = 0;
>+        
>+        if (vdr_execute_rpc_command(this) < 0)
>+        {
>+          failed = 1;
>+          xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
>+                  LOG_MODULE ": execution of rpc command %d (%s) failed, exiting ...\n", this->cur_func, "");
>+        }
>+
>+        _x_unlock_frontend(this->stream);
>+      }
>+    }
>+  }
>+
>+  /* close control and result channel here to have vdr-xine initiate a disconnect for the above error case ... */
>+  close(this->fh_control);
>+  this->fh_control = -1;
>+  
>+  close(this->fh_result);
>+  this->fh_result = -1;
>+  
>+  xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
>+          LOG_MODULE ": rpc thread done.\n");
>+
>+  pthread_mutex_lock(&this->rpc_thread_shutdown_lock);
>+  this->rpc_thread_shutdown = -1;
>+  pthread_cond_broadcast(&this->rpc_thread_shutdown_cond);
>+  pthread_mutex_unlock(&this->rpc_thread_shutdown_lock);
>+  
>+  return 0;
>+}
>+
>+static int internal_write_event_key(vdr_input_plugin_t *this, uint32_t key)
>+{
>+  event_key_t event;
>+  event.header.func = func_key;
>+  event.header.len = sizeof (event);
>+
>+  event.key = key;
>+
>+  if (sizeof (event) != vdr_write(this->fh_event, &event, sizeof (event)))
>+    return -1;
>+  
>+  return 0;
>+}
>+
>+static int internal_write_event_frame_size(vdr_input_plugin_t *this)
>+{
>+  event_frame_size_t event;
>+  event.header.func = func_frame_size;
>+  event.header.len = sizeof (event);
>+
>+  event.top    = this->frame_size.x;
>+  event.left   = this->frame_size.y;
>+  event.width  = this->frame_size.w,
>+  event.height = this->frame_size.h;
>+
>+  if (sizeof (event) != vdr_write(this->fh_event, &event, sizeof (event)))
>+    return -1;
>+  
>+  return 0;
>+}
>+
>+static int internal_write_event_play_external(vdr_input_plugin_t *this, uint32_t key)
>+{
>+  event_play_external_t event;
>+  event.header.func = func_play_external;
>+  event.header.len = sizeof (event);
>+
>+  event.key = key;
>+
>+  if (sizeof (event) != vdr_write(this->fh_event, &event, sizeof (event)))
>+    return -1;
>+  
>+  return 0;
>+}
>+
>+static off_t vdr_plugin_read(input_plugin_t *this_gen, 
>+                             char *buf, off_t len)
>+{
>+  vdr_input_plugin_t  *this = (vdr_input_plugin_t *) this_gen;
>+  off_t n, total;
>+#ifdef LOG_READ   
>+  lprintf ("reading %lld bytes...\n", len);
>+#endif   
>+  total=0;
>+  if (this->curpos < this->preview_size)
>+  {
>+    n = this->preview_size - this->curpos;
>+    if (n > (len - total))
>+      n = len - total;
>+#ifdef LOG_READ
>+    lprintf ("%lld bytes from preview (which has %lld bytes)\n",
>+            n, this->preview_size);
>+#endif
>+    memcpy (&buf[total], &this->preview[this->curpos], n);
>+    this->curpos += n;
>+    total += n;
>+  }
>+   
>+  if( (len-total) > 0 )
>+  {
>+    int retries = 0;
>+    do
>+    {
>+      n = vdr_read_abort (this->stream, this->fh, &buf[total], len-total);
>+      if (0 == n)
>+        lprintf("read 0, retries: %d\n", retries);
>+    }
>+    while (0 == n
>+           && !this->stream_external
>+           && _x_continue_stream_processing(this->stream)
>+           && 200 > retries++); /* 200 * 50ms */
>+#ifdef LOG_READ      
>+    lprintf ("got %lld bytes (%lld/%lld bytes read)\n",
>+            n,total,len);
>+#endif
>+    if (n < 0)
>+    {
>+      _x_message(this->stream, XINE_MSG_READ_ERROR, NULL);
>+      return 0;
>+    }
>+
>+    this->curpos += n;
>+    total += n;
>+  }
>+  return total;
>+}
>+
>+static buf_element_t *vdr_plugin_read_block(input_plugin_t *this_gen, fifo_buffer_t *fifo, 
>+                                            off_t todo)
>+{
>+  off_t          total_bytes;
>+  buf_element_t *buf = fifo->buffer_pool_alloc(fifo);
>+
>+  buf->content = buf->mem;
>+  buf->type = BUF_DEMUX_BLOCK;
>+
>+  total_bytes = vdr_plugin_read(this_gen, (char *)buf->content, todo);
>+
>+  if (total_bytes != todo)
>+  {
>+    buf->free_buffer(buf);
>+    return NULL;
>+  }
>+
>+  buf->size = total_bytes;
>+
>+  return buf;
>+}
>+
>+/* forward reference */
>+static off_t vdr_plugin_get_current_pos(input_plugin_t *this_gen);
>+
>+static off_t vdr_plugin_seek(input_plugin_t *this_gen, off_t offset, int origin)
>+{
>+  vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen;
>+
>+  lprintf("seek %lld offset, %d origin...\n",
>+          offset, origin);
>+
>+  if ((origin == SEEK_CUR) && (offset >= 0))
>+  {
>+    for ( ; ((int)offset) - BUF_SIZE > 0; offset -= BUF_SIZE)
>+    {
>+      if (!this_gen->read(this_gen, this->seek_buf, BUF_SIZE))
>+        return this->curpos;
>+    }
>+
>+    this_gen->read (this_gen, this->seek_buf, offset);
>+  }
>+
>+  if (origin == SEEK_SET)
>+  {
>+    if (offset < this->curpos)
>+    {
>+      if (this->curpos <= this->preview_size) 
>+        this->curpos = offset;
>+      else
>+        lprintf("cannot seek back! (%lld > %lld)\n", this->curpos, offset);
>+    }
>+    else
>+    {
>+      offset -= this->curpos;
>+
>+      for ( ; ((int)offset) - BUF_SIZE > 0; offset -= BUF_SIZE)
>+      {
>+        if (!this_gen->read(this_gen, this->seek_buf, BUF_SIZE))
>+          return this->curpos;
>+      }
>+
>+      this_gen->read(this_gen, this->seek_buf, offset);
>+    }
>+  }
>+
>+  return this->curpos;
>+}
>+
>+static off_t vdr_plugin_get_length(input_plugin_t *this_gen)
>+{
>+  return 0;
>+}
>+
>+static uint32_t vdr_plugin_get_capabilities(input_plugin_t *this_gen)
>+{
>+  /* return INPUT_CAP_PREVIEW; */
>+  return INPUT_CAP_NOCAP;
>+}
>+
>+static uint32_t vdr_plugin_get_blocksize(input_plugin_t *this_gen)
>+{
>+  return 0;
>+}
>+
>+static off_t vdr_plugin_get_current_pos(input_plugin_t *this_gen)
>+{
>+  vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen;
>+
>+  return this->curpos;
>+}
>+
>+static char* vdr_plugin_get_mrl(input_plugin_t *this_gen)
>+{
>+  vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen;
>+
>+  return this->mrl;
>+}
>+
>+static void vdr_plugin_dispose(input_plugin_t *this_gen)
>+{
>+  vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen;
>+  int i;
>+
>+  external_stream_stop(this);
>+
>+  if (this->event_queue)
>+    xine_event_dispose_queue(this->event_queue);
>+
>+  if (this->rpc_thread)
>+  {
>+    struct timespec abstime;
>+    int ms_to_time_out = 10000;
>+
>+    xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _(LOG_MODULE ": shutting down rpc thread (timeout: %d ms) ...\n"), ms_to_time_out);
>+
>+    pthread_mutex_lock(&this->rpc_thread_shutdown_lock);
>+
>+    if (this->rpc_thread_shutdown > -1)
>+    {
>+      this->rpc_thread_shutdown = 1;
>+      
>+      {
>+        struct timeval now;
>+        gettimeofday(&now, 0);
>+        
>+        abstime.tv_sec = now.tv_sec + ms_to_time_out / 1000;
>+        abstime.tv_nsec = now.tv_usec * 1000 + (ms_to_time_out % 1000) * 1e6;
>+        
>+        if (abstime.tv_nsec > 1e9)
>+        {
>+          abstime.tv_nsec -= 1e9;
>+          abstime.tv_sec++;
>+        }
>+      }
>+      
>+      if (0 != pthread_cond_timedwait(&this->rpc_thread_shutdown_cond, &this->rpc_thread_shutdown_lock, &abstime))
>+      {
>+        xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _(LOG_MODULE ": cancelling rpc thread ...\n"));
>+        pthread_cancel(this->rpc_thread);
>+      }
>+    }
>+    
>+    pthread_mutex_unlock(&this->rpc_thread_shutdown_lock);
>+    
>+    xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _(LOG_MODULE ": joining rpc thread ...\n"));
>+    pthread_join(this->rpc_thread, 0);
>+    xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _(LOG_MODULE ": rpc thread joined.\n"));
>+  }
>+
>+  pthread_cond_destroy(&this->rpc_thread_shutdown_cond);
>+  pthread_mutex_destroy(&this->rpc_thread_shutdown_lock);
>+  
>+  if (this->fh_result != -1)
>+    close(this->fh_result);
>+  
>+  if (this->fh_control != -1)
>+    close(this->fh_control);
>+
>+  if (this->fh_event != -1)
>+    close(this->fh_event);
>+  
>+  for (i = 0; i < VDR_MAX_NUM_WINDOWS; i++)
>+  {
>+    if (0 == this->osd_window[ i ])
>+      continue;
>+
>+    xine_osd_hide(this->osd_window[ i ], 0);
>+    xine_osd_free(this->osd_window[ i ]);
>+  }
>+
>+  if (this->osd_buffer)
>+    free(this->osd_buffer);
>+  
>+  if ((this->fh != STDIN_FILENO) && (this->fh != -1))
>+    close(this->fh);
>+
>+  free(this->mrl);
>+  free(this);
>+}
>+
>+static int vdr_plugin_get_optional_data(input_plugin_t *this_gen, 
>+                                        void *data, int data_type)
>+{
>+/*
>+  vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen;
>+  
>+  switch (data_type)
>+  {
>+  case INPUT_OPTIONAL_DATA_PREVIEW:
>+    memcpy (data, this->preview, this->preview_size);
>+    return this->preview_size;
>+  }
>+*/  
>+  return INPUT_OPTIONAL_UNSUPPORTED;
>+}
>+
>+static int vdr_plugin_open(input_plugin_t *this_gen)
>+{
>+  vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen;
>+
>+  lprintf("trying to open '%s'...\n", this->mrl);
>+
>+  if (this->fh == -1)
>+  {
>+    char *filename;
>+    int err = 0;
>+
>+    filename = (char *)&this->mrl[ 4 ];
>+    this->fh = open(filename, O_RDONLY | O_NONBLOCK);
>+
>+    lprintf("filename '%s'\n", filename);
>+
>+    if (this->fh == -1)
>+    {
>+      xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
>+              _(LOG_MODULE ": failed to open '%s' (%s)\n"),
>+              filename,
>+              strerror(errno));
>+      
>+      return 0;
>+    }
>+
>+    {
>+      struct pollfd poll_fh = { this->fh, POLLIN, 0 };
>+      
>+      int r = poll(&poll_fh, 1, 300);      
>+      if (1 != r)
>+      {
>+        xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
>+                _(LOG_MODULE ": failed to open '%s' (%s)\n"),
>+                filename,
>+                _("timeout expired during setup phase"));
>+        
>+        return 0;
>+      }
>+    }
>+    
>+    fcntl(this->fh, F_SETFL, ~O_NONBLOCK & fcntl(this->fh, F_GETFL, 0));
>+    
>+    {
>+      char *filename_control = 0;
>+      asprintf(&filename_control, "%s.control", filename);
>+
>+      this->fh_control = open(filename_control, O_RDONLY);
>+
>+      if (this->fh_control == -1) {
>+        xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
>+                _(LOG_MODULE ": failed to open '%s' (%s)\n"),
>+                filename_control,
>+                strerror(errno));
>+
>+        free(filename_control);
>+        return 0;
>+      }
>+
>+      free(filename_control);      
>+    }
>+
>+    {
>+      char *filename_result = 0;
>+      asprintf(&filename_result, "%s.result", filename);
>+
>+      this->fh_result = open(filename_result, O_WRONLY);
>+
>+      if (this->fh_result == -1) {
>+        perror("failed");
>+        
>+        xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
>+                _(LOG_MODULE ": failed to open '%s' (%s)\n"),
>+                filename_result,
>+                strerror(errno));
>+        
>+        free(filename_result);
>+        return 0;
>+      }
>+
>+      free(filename_result);
>+    }
>+
>+    {
>+      char *filename_event = 0;
>+      asprintf(&filename_event, "%s.event", filename);
>+
>+      this->fh_event = open(filename_event, O_WRONLY);
>+
>+      if (this->fh_event == -1) {
>+        perror("failed");
>+
>+        xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
>+                _(LOG_MODULE ": failed to open '%s' (%s)\n"),
>+                filename_event,
>+                strerror(errno));
>+        
>+        free(filename_event);
>+        return 0;
>+      }
>+
>+      free(filename_event);
>+    }
>+
>+    this->rpc_thread_shutdown = 0;
>+    if ((err = pthread_create(&this->rpc_thread, NULL,
>+                              vdr_rpc_thread_loop, (void *)this)) != 0)
>+    {
>+      xprintf(this->stream->xine, XINE_VERBOSITY_LOG, 
>+              _(LOG_MODULE ": can't create new thread (%s)\n"),
>+              strerror(err));
>+      
>+      return 0;
>+    }
>+  }
>+
>+
>+  /*
>+   * mrl accepted and opened successfully at this point
>+   *
>+   * => create plugin instance
>+   */
>+
>+  /*
>+   * fill preview buffer
>+   */
>+
>+  this->preview_size = 0; /* vdr_plugin_read (&this->input_plugin, this->preview,
>+                             MAX_PREVIEW_SIZE) */ 
>+  this->curpos       = 0;
>+
>+  return 1;
>+}
>+
>+static void event_handler(void *user_data, const xine_event_t *event)
>+{
>+  vdr_input_plugin_t *this = (vdr_input_plugin_t *)user_data;
>+  uint32_t key = key_none;
>+
>+  lprintf("eventHandler(): event->type: %d\n", event->type);
>+
>+  if (XINE_EVENT_VDR_FRAMESIZECHANGED == event->type)
>+  {
>+    memcpy(&this->frame_size, event->data, event->data_length);
>+
>+    if (0 != internal_write_event_frame_size(this))
>+      xprintf(this->stream->xine, XINE_VERBOSITY_LOG, 
>+              _(LOG_MODULE ": input event write: %s.\n"), strerror(errno));
>+
>+    return;
>+  }
>+  else if (XINE_EVENT_VDR_PLUGINSTARTED == event->type)
>+  {
>+    if (0 == event->data_length) /* vdr_video */
>+    {
>+      xine_event_t event;
>+        
>+      event.type = XINE_EVENT_VDR_TRICKSPEEDMODE;
>+      event.data = 0;
>+      event.data_length = this->trick_speed_mode;
>+
>+      xine_event_send(this->stream, &event);
>+    }
>+    else if (1 == event->data_length) /* vdr_audio */
>+    {
>+      xine_event_t event;
>+      vdr_select_audio_data_t event_data;
>+        
>+      event_data.channels = this->audio_channels;
>+        
>+      event.type = XINE_EVENT_VDR_SELECTAUDIO;
>+      event.data = &event_data;
>+      event.data_length = sizeof (event_data);
>+        
>+      xine_event_send(this->stream, &event);
>+    }
>+    else
>+    {
>+      fprintf(stderr, "input_vdr: illegal XINE_EVENT_VDR_PLUGINSTARTED: %d\n", event->data_length);
>+    }
>+  }
>+
>+  switch (event->type)
>+  {
>+  case XINE_EVENT_INPUT_UP:            key = key_up;               break;
>+  case XINE_EVENT_INPUT_DOWN:          key = key_down;             break;
>+  case XINE_EVENT_INPUT_LEFT:          key = key_left;             break;
>+  case XINE_EVENT_INPUT_RIGHT:         key = key_right;            break;
>+  case XINE_EVENT_INPUT_SELECT:        key = key_ok;               break;
>+  case XINE_EVENT_VDR_BACK:            key = key_back;             break;
>+  case XINE_EVENT_VDR_CHANNELPLUS:     key = key_channel_plus;     break;
>+  case XINE_EVENT_VDR_CHANNELMINUS:    key = key_channel_minus;    break;
>+  case XINE_EVENT_VDR_RED:             key = key_red;              break;
>+  case XINE_EVENT_VDR_GREEN:           key = key_green;            break;
>+  case XINE_EVENT_VDR_YELLOW:          key = key_yellow;           break;
>+  case XINE_EVENT_VDR_BLUE:            key = key_blue;             break;
>+  case XINE_EVENT_VDR_PLAY:            key = key_play;             break;
>+  case XINE_EVENT_VDR_PAUSE:           key = key_pause;            break;
>+  case XINE_EVENT_VDR_STOP:            key = key_stop;             break;
>+  case XINE_EVENT_VDR_RECORD:          key = key_record;           break;
>+  case XINE_EVENT_VDR_FASTFWD:         key = key_fast_fwd;         break;
>+  case XINE_EVENT_VDR_FASTREW:         key = key_fast_rew;         break;
>+  case XINE_EVENT_VDR_POWER:           key = key_power;            break;
>+  case XINE_EVENT_VDR_SCHEDULE:        key = key_schedule;         break;
>+  case XINE_EVENT_VDR_CHANNELS:        key = key_channels;         break;
>+  case XINE_EVENT_VDR_TIMERS:          key = key_timers;           break;
>+  case XINE_EVENT_VDR_RECORDINGS:      key = key_recordings;       break;
>+  case XINE_EVENT_INPUT_MENU1:         key = key_menu;             break;
>+  case XINE_EVENT_VDR_SETUP:           key = key_setup;            break;
>+  case XINE_EVENT_VDR_COMMANDS:        key = key_commands;         break;
>+  case XINE_EVENT_INPUT_NUMBER_0:      key = key_0;                break;
>+  case XINE_EVENT_INPUT_NUMBER_1:      key = key_1;                break;
>+  case XINE_EVENT_INPUT_NUMBER_2:      key = key_2;                break;
>+  case XINE_EVENT_INPUT_NUMBER_3:      key = key_3;                break;
>+  case XINE_EVENT_INPUT_NUMBER_4:      key = key_4;                break;
>+  case XINE_EVENT_INPUT_NUMBER_5:      key = key_5;                break;
>+  case XINE_EVENT_INPUT_NUMBER_6:      key = key_6;                break;
>+  case XINE_EVENT_INPUT_NUMBER_7:      key = key_7;                break;
>+  case XINE_EVENT_INPUT_NUMBER_8:      key = key_8;                break;
>+  case XINE_EVENT_INPUT_NUMBER_9:      key = key_9;                break;
>+  case XINE_EVENT_VDR_USER1:           key = key_user1;            break;
>+  case XINE_EVENT_VDR_USER2:           key = key_user2;            break;
>+  case XINE_EVENT_VDR_USER3:           key = key_user3;            break;
>+  case XINE_EVENT_VDR_USER4:           key = key_user4;            break;
>+  case XINE_EVENT_VDR_USER5:           key = key_user5;            break;
>+  case XINE_EVENT_VDR_USER6:           key = key_user6;            break;
>+  case XINE_EVENT_VDR_USER7:           key = key_user7;            break;
>+  case XINE_EVENT_VDR_USER8:           key = key_user8;            break;
>+  case XINE_EVENT_VDR_USER9:           key = key_user9;            break;
>+  case XINE_EVENT_VDR_VOLPLUS:         key = key_volume_plus;      break;
>+  case XINE_EVENT_VDR_VOLMINUS:        key = key_volume_minus;     break;
>+  case XINE_EVENT_VDR_MUTE:            key = key_mute;             break;
>+  case XINE_EVENT_VDR_AUDIO:           key = key_audio;            break;
>+  default:
>+    return;
>+  }
>+
>+  if (0 != internal_write_event_key(this, key))
>+    xprintf(this->stream->xine, XINE_VERBOSITY_LOG, 
>+            _(LOG_MODULE ": input event write: %s.\n"), strerror(errno));
>+}
>+
>+static input_plugin_t *vdr_class_get_instance(input_class_t *cls_gen, xine_stream_t *stream,
>+                                               const char *data)
>+{
>+  vdr_input_plugin_t *this;
>+  char               *mrl = strdup(data);
>+
>+  if (!strncasecmp(mrl, "vdr:/", 5))
>+  {
>+    lprintf("filename '%s'\n", (char *)&mrl[ 4 ]);
>+  }
>+  else
>+  {
>+    free(mrl);
>+    return NULL;
>+  }
>+
>+  /*
>+   * mrl accepted and opened successfully at this point
>+   *
>+   * => create plugin instance
>+   */
>+
>+  this = (vdr_input_plugin_t *)xine_xmalloc(sizeof (vdr_input_plugin_t));
>+
>+  this->stream     = stream;
>+  this->curpos     = 0;
>+  this->mrl        = mrl;
>+  this->fh         = -1;
>+  this->fh_control = -1;
>+  this->fh_result  = -1;
>+  this->fh_event   = -1;
>+
>+  this->input_plugin.open              = vdr_plugin_open;
>+  this->input_plugin.get_capabilities  = vdr_plugin_get_capabilities;
>+  this->input_plugin.read              = vdr_plugin_read;
>+  this->input_plugin.read_block        = vdr_plugin_read_block;
>+  this->input_plugin.seek              = vdr_plugin_seek;
>+  this->input_plugin.get_current_pos   = vdr_plugin_get_current_pos;
>+  this->input_plugin.get_length        = vdr_plugin_get_length;
>+  this->input_plugin.get_blocksize     = vdr_plugin_get_blocksize;
>+  this->input_plugin.get_mrl           = vdr_plugin_get_mrl;
>+  this->input_plugin.dispose           = vdr_plugin_dispose;
>+  this->input_plugin.get_optional_data = vdr_plugin_get_optional_data;
>+  this->input_plugin.input_class       = cls_gen;
>+
>+  this->cur_func = func_unknown;
>+  this->cur_size = 0;
>+  this->cur_done = 0;
>+
>+  memset(this->osd_window, 0, sizeof (this->osd_window));
>+
>+  this->osd_buffer              = 0;
>+  this->osd_buffer_size         = 0;
>+  this->osd_unscaled_blending   = 0;
>+  this->trick_speed_mode        = 0;
>+  this->audio_channels          = 0;
>+  this->mute_mode               = INPUT_VDR_MUTE_SIMULATE;
>+  this->dont_change_xine_volume = 0;
>+  this->last_volume             = 0;
>+  this->frame_size.x            = 0;
>+  this->frame_size.y            = 0;
>+  this->frame_size.w            = 0;
>+  this->frame_size.h            = 0;
>+  
>+  this->stream_external      = 0;
>+  this->event_queue_external = 0;
>+
>+  pthread_mutex_init(&this->rpc_thread_shutdown_lock, 0);
>+  pthread_cond_init(&this->rpc_thread_shutdown_cond, 0);  
>+  
>+  this->event_queue = xine_event_new_queue(this->stream);
>+  if (this->event_queue)
>+    xine_event_create_listener_thread(this->event_queue, event_handler, this);
>+
>+  return &this->input_plugin;
>+}
>+
>+/*
>+ * vdr input plugin class stuff
>+ */
>+
>+static char *vdr_class_get_description(input_class_t *this_gen)
>+{
>+  return _("VDR display device plugin");
>+}
>+
>+static const char *vdr_class_get_identifier (input_class_t *this_gen)
>+{
>+  return "VDR";
>+}
>+
>+static void vdr_class_dispose (input_class_t *this_gen)
>+{
>+  vdr_input_class_t *this = (vdr_input_class_t *)this_gen;
>+
>+  free(this);
>+}
>+
>+static char **vdr_class_get_autoplay_list(input_class_t *this_gen,
>+                                          int *num_files)
>+{
>+  vdr_input_class_t *class = (vdr_input_class_t *)this_gen;
>+
>+  *num_files = 1;
>+  return class->mrls;
>+}
>+
>+static void *init_class(xine_t *xine, void *data)
>+{
>+  vdr_input_class_t *this;
>+  
>+  lprintf("init_class\n");
>+  
>+  this = (vdr_input_class_t *)xine_xmalloc(sizeof (vdr_input_class_t));
>+  
>+  this->xine = xine;
>+
>+  this->mrls[ 0 ] = "vdr:" VDR_ABS_FIFO_DIR "/stream#demux:mpeg_pes";
>+  this->mrls[ 1 ] = 0;
>+
>+  this->input_class.get_instance      = vdr_class_get_instance;
>+  this->input_class.get_identifier    = vdr_class_get_identifier;
>+  this->input_class.get_description   = vdr_class_get_description;
>+  this->input_class.get_dir           = NULL;
>+  this->input_class.get_autoplay_list = vdr_class_get_autoplay_list;
>+  this->input_class.dispose           = vdr_class_dispose;
>+  this->input_class.eject_media       = NULL;
>+
>+  return this;
>+}
>+
>+/*
>+ * exported plugin catalog entry
>+ */
>+
>+plugin_info_t xine_plugin_info[] =
>+{
>+  /* type, API, "name", version, special_info, init_function */
>+  { PLUGIN_INPUT, 17, "VDR", XINE_VERSION_CODE, NULL, init_class },
>+  { PLUGIN_NONE, 0, "", 0, NULL, NULL }
>+};
>diff -ruN xine-lib-1.1.1.orig/src/vdr/input_vdr.h xine-lib-1.1.1/src/vdr/input_vdr.h
>--- xine-lib-1.1.1.orig/src/vdr/input_vdr.h	1970-01-01 01:00:00.000000000 +0100
>+++ xine-lib-1.1.1/src/vdr/input_vdr.h	2006-01-02 20:15:55.000000000 +0100
>@@ -0,0 +1,548 @@
>+
>+#ifndef __INPUT_VDR_H
>+#define __INPUT_VDR_H
>+
>+
>+
>+enum funcs
>+{
>+  func_unknown = -1
>+  , func_nop
>+  , func_osd_new
>+  , func_osd_free
>+  , func_osd_show
>+  , func_osd_hide
>+  , func_osd_set_position
>+  , func_osd_draw_bitmap
>+  , func_set_color
>+  , func_clear
>+  , func_mute
>+  , func_set_volume
>+  , func_set_speed
>+  , func_set_prebuffer
>+  , func_metronom
>+  , func_start
>+  , func_wait
>+  , func_setup
>+  , func_grab_image
>+  , func_get_pts
>+  , func_flush
>+  , func_first_frame
>+  , func_still_frame
>+  , func_video_size
>+  , func_set_video_window
>+  , func_osd_flush
>+  , func_play_external
>+  , func_key
>+  , func_frame_size
>+  , func_reset_audio
>+  , func_select_audio
>+  , func_trick_speed_mode
>+};
>+
>+enum keys
>+{
>+  key_none,
>+  key_up,
>+  key_down,
>+  key_menu,
>+  key_ok,
>+  key_back,
>+  key_left,
>+  key_right,
>+  key_red,
>+  key_green,
>+  key_yellow,
>+  key_blue,
>+  key_0,
>+  key_1,
>+  key_2,
>+  key_3,
>+  key_4,
>+  key_5,
>+  key_6,
>+  key_7,
>+  key_8,
>+  key_9,
>+  key_play,
>+  key_pause,
>+  key_stop,
>+  key_record,
>+  key_fast_fwd,
>+  key_fast_rew,
>+  key_power,
>+  key_channel_plus,
>+  key_channel_minus,
>+  key_volume_plus,
>+  key_volume_minus,
>+  key_mute,
>+  key_schedule,
>+  key_channels,
>+  key_timers,
>+  key_recordings,
>+  key_setup,
>+  key_commands,
>+  key_user1,
>+  key_user2,
>+  key_user3,
>+  key_user4,
>+  key_user5,
>+  key_user6,
>+  key_user7,
>+  key_user8,
>+  key_user9,
>+  key_audio,
>+};
>+
>+
>+
>+typedef struct __attribute__((packed)) data_header_s
>+{
>+  uint32_t func:8;
>+  uint32_t len:24;
>+} 
>+data_header_t;
>+
>+
>+
>+typedef data_header_t result_header_t;
>+typedef data_header_t event_header_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_nop_s
>+{
>+  data_header_t header;
>+}
>+data_nop_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_osd_new_s
>+{
>+  data_header_t header;
>+  
>+  uint8_t  window;
>+  int16_t  x;
>+  int16_t  y;
>+  uint16_t width;
>+  uint16_t height;
>+}
>+data_osd_new_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_osd_free_s
>+{
>+  data_header_t header;
>+  
>+  uint8_t window;
>+}
>+data_osd_free_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_osd_show_s
>+{
>+  data_header_t header;
>+  
>+  uint8_t window;
>+}
>+data_osd_show_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_osd_hide_s
>+{
>+  data_header_t header;
>+  
>+  uint8_t window;
>+}
>+data_osd_hide_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_osd_flush_s
>+{
>+  data_header_t header;
>+}
>+data_osd_flush_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_play_external_s
>+{
>+  data_header_t header;
>+}
>+data_play_external_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_osd_set_position_s
>+{
>+  data_header_t header;
>+  
>+  uint8_t window;
>+  int16_t x;
>+  int16_t y;
>+}
>+data_osd_set_position_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_osd_draw_bitmap_s
>+{
>+  data_header_t header;
>+  
>+  uint8_t  window;
>+  int16_t  x;
>+  int16_t  y;
>+  uint16_t width;
>+  uint16_t height;
>+}
>+data_osd_draw_bitmap_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_set_color_s
>+{
>+  data_header_t header;
>+  
>+  uint8_t window;
>+  uint8_t index;
>+  uint8_t num;
>+}
>+data_set_color_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_flush_s
>+{
>+  data_header_t header;
>+
>+  int32_t ms_timeout;
>+  uint8_t just_wait;
>+}
>+data_flush_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) result_flush_s
>+{
>+  result_header_t header;
>+  
>+  uint8_t timed_out;
>+}
>+result_flush_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_clear_s
>+{
>+  data_header_t header;
>+
>+  int32_t n;
>+}
>+data_clear_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_mute_s
>+{
>+  data_header_t header;
>+
>+  uint8_t mute;
>+}
>+data_mute_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_set_volume_s
>+{
>+  data_header_t header;
>+
>+  uint8_t volume;
>+}
>+data_set_volume_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_set_speed_s
>+{
>+  data_header_t header;
>+
>+  int32_t speed;
>+}
>+data_set_speed_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_set_prebuffer_s
>+{
>+  data_header_t header;
>+
>+  uint32_t prebuffer;
>+}
>+data_set_prebuffer_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_metronom_s
>+{
>+  data_header_t header;
>+
>+  int64_t  pts;
>+  uint32_t flags;
>+}
>+data_metronom_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_start_s
>+{
>+  data_header_t header;
>+}
>+data_start_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_wait_s
>+{
>+  data_header_t header;
>+
>+  uint8_t data[ 64 * 1024 - sizeof (data_header_t) ];
>+}
>+data_wait_t;
>+
>+
>+
>+#define INPUT_VDR_MUTE_IGNORE   0
>+#define INPUT_VDR_MUTE_EXECUTE  1
>+#define INPUT_VDR_MUTE_SIMULATE 2
>+
>+typedef struct __attribute__((packed)) data_setup_s
>+{
>+  data_header_t header;
>+
>+  uint8_t osd_unscaled_blending;
>+  uint8_t dont_change_xine_volume;
>+  uint8_t mute_mode;
>+}
>+data_setup_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_first_frame_s
>+{
>+  data_header_t header;
>+}
>+data_first_frame_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_still_frame_s
>+{
>+  data_header_t header;
>+}
>+data_still_frame_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_set_video_window_s
>+{
>+  data_header_t header;
>+
>+  uint32_t x;
>+  uint32_t y;
>+  uint32_t w;
>+  uint32_t h;
>+  uint32_t w_ref;
>+  uint32_t h_ref;
>+}
>+data_set_video_window_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_grab_image_s
>+{
>+  data_header_t header;
>+}
>+data_grab_image_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) result_grab_image_s
>+{
>+  result_header_t header;
>+
>+  int32_t width;
>+  int32_t height;
>+  int32_t ratio;
>+  int32_t format;
>+}
>+result_grab_image_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_get_pts_s
>+{
>+  data_header_t header;
>+}
>+data_get_pts_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) result_get_pts_s
>+{
>+  result_header_t header;
>+
>+  int64_t pts;
>+}
>+result_get_pts_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_video_size_s
>+{
>+  data_header_t header;
>+}
>+data_video_size_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) result_video_size_s
>+{
>+  result_header_t header;
>+
>+  int32_t left;
>+  int32_t top;
>+  int32_t width;
>+  int32_t height;
>+  int32_t ratio;
>+}
>+result_video_size_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_reset_audio_s
>+{
>+  data_header_t header;
>+}
>+data_reset_audio_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) event_key_s
>+{
>+  event_header_t header;
>+  
>+  uint32_t key;
>+}
>+event_key_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) event_frame_size_s
>+{
>+  event_header_t header;
>+  
>+  int32_t left;
>+  int32_t top;
>+  int32_t width;
>+  int32_t height;
>+}
>+event_frame_size_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) event_play_external_s
>+{
>+  event_header_t header;
>+  
>+  uint32_t key;
>+}
>+event_play_external_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_select_audio_s
>+{
>+  data_header_t header;
>+  
>+  uint8_t channels;
>+}
>+data_select_audio_t;
>+
>+
>+
>+typedef struct __attribute__((packed)) data_trick_speed_mode_s
>+{
>+  data_header_t header;
>+
>+  uint8_t on;
>+}
>+data_trick_speed_mode_t;
>+
>+
>+
>+typedef union __attribute__((packed)) data_union_u
>+{
>+  data_header_t           header;
>+  data_nop_t              nop;
>+  data_osd_new_t          osd_new;
>+  data_osd_free_t         osd_free;
>+  data_osd_show_t         osd_show;
>+  data_osd_hide_t         osd_hide;
>+  data_osd_set_position_t osd_set_position;
>+  data_osd_draw_bitmap_t  osd_draw_bitmap;
>+  data_set_color_t        set_color;
>+  data_flush_t            flush;
>+  data_clear_t            clear;
>+  data_mute_t             mute;
>+  data_set_volume_t       set_volume;
>+  data_set_speed_t        set_speed;
>+  data_set_prebuffer_t    set_prebuffer;
>+  data_metronom_t         metronom;
>+  data_start_t            start;
>+  data_wait_t             wait;
>+  data_setup_t            setup;
>+  data_grab_image_t       grab_image;
>+  data_get_pts_t          get_pts;
>+  data_first_frame_t      first_frame;
>+  data_still_frame_t      still_frame;
>+  data_video_size_t       video_size;
>+  data_set_video_window_t set_video_window;
>+  data_osd_flush_t        osd_flush;
>+  data_play_external_t    play_external;
>+  data_reset_audio_t      reset_audio;
>+  data_select_audio_t     select_audio;
>+  data_trick_speed_mode_t trick_speed_mode;
>+}
>+data_union_t;
>+
>+
>+
>+typedef union __attribute__((packed)) result_union_u
>+{
>+  result_header_t         header;
>+  result_grab_image_t     grab_image;
>+  result_get_pts_t        get_pts;
>+  result_flush_t          flush;
>+  result_video_size_t     video_size;
>+}
>+result_union_t;
>+
>+
>+
>+typedef union __attribute__((packed)) event_union_u
>+{
>+  event_header_t          header;
>+  event_key_t             key;
>+  event_frame_size_t      frame_size;
>+  event_play_external_t   play_external;
>+}
>+event_union_t;
>+
>+
>+
>+#endif /* __INPUT_VDR_H */
>diff -ruN xine-lib-1.1.1.orig/src/vdr/Makefile.am xine-lib-1.1.1/src/vdr/Makefile.am
>--- xine-lib-1.1.1.orig/src/vdr/Makefile.am	1970-01-01 01:00:00.000000000 +0100
>+++ xine-lib-1.1.1/src/vdr/Makefile.am	2006-01-02 20:11:39.000000000 +0100
>@@ -0,0 +1,29 @@
>+include $(top_srcdir)/misc/Makefile.common
>+
>+
>+
>+libdir = $(XINE_PLUGINDIR)
>+
>+AM_CFLAGS = -D_LARGEFILE64_SOURCE
>+
>+lib_LTLIBRARIES = \
>+	xineplug_inp_vdr.la
>+
>+xineplug_inp_vdr_la_SOURCES = input_vdr.c
>+xineplug_inp_vdr_la_LIBADD = $(XINE_LIB)
>+xineplug_inp_vdr_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@
>+
>+include_HEADERS = input_vdr.h
>+
>+
>+
>+postlibdir = $(XINE_PLUGINDIR)/post
>+
>+postlib_LTLIBRARIES = \
>+	xineplug_post_vdr.la
>+
>+xineplug_post_vdr_la_SOURCES = post_vdr.c post_vdr_video.c post_vdr_audio.c
>+xineplug_post_vdr_la_LIBADD = $(XINE_LIB)
>+xineplug_post_vdr_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@
>+
>+noinst_HEADERS = post_vdr.h
>diff -ruN xine-lib-1.1.1.orig/src/vdr/post_vdr_audio.c xine-lib-1.1.1/src/vdr/post_vdr_audio.c
>--- xine-lib-1.1.1.orig/src/vdr/post_vdr_audio.c	1970-01-01 01:00:00.000000000 +0100
>+++ xine-lib-1.1.1/src/vdr/post_vdr_audio.c	2006-01-02 20:17:42.000000000 +0100
>@@ -0,0 +1,287 @@
>+/*
>+ * Copyright (C) 2000-2004 the xine project
>+ * 
>+ * This file is part of xine, a free video player.
>+ * 
>+ * xine is free software; you can redistribute it and/or modify
>+ * it under the terms of the GNU General Public License as published by
>+ * the Free Software Foundation; either version 2 of the License, or
>+ * (at your option) any later version.
>+ * 
>+ * xine is distributed in the hope that it will be useful,
>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>+ * GNU General Public License for more details.
>+ * 
>+ * You should have received a copy of the GNU General Public License
>+ * along with this program; if not, write to the Free Software
>+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
>+ *
>+ * $Id: vdr.c,v 1.20 2004/04/17 19:54:32 mroi Exp $
>+ */
>+ 
>+/*
>+ * select audio channel plugin for VDR
>+ */
>+
>+#define LOG_MODULE "vdr_audio"
>+#define LOG_VERBOSE
>+/*
>+#define LOG
>+*/
>+
>+#include "xine_internal.h"
>+#include "post.h"
>+#include "post_vdr.h"
>+
>+
>+
>+typedef struct vdr_audio_post_plugin_s
>+{
>+  post_plugin_t post_plugin;
>+
>+  xine_event_queue_t *event_queue;
>+  xine_stream_t      *vdr_stream;
>+  
>+  uint8_t audio_channels;
>+  int num_channels;
>+  
>+}
>+vdr_audio_post_plugin_t;
>+
>+
>+static void vdr_audio_select_audio(vdr_audio_post_plugin_t *this, uint8_t channels)
>+{
>+  this->audio_channels = channels;
>+}
>+
>+ 
>+/* plugin class functions */
>+static post_plugin_t *vdr_audio_open_plugin(post_class_t *class_gen, int inputs,
>+                                            xine_audio_port_t **audio_target,
>+                                            xine_video_port_t **video_target);
>+static char          *vdr_audio_get_identifier(post_class_t *class_gen);
>+static char          *vdr_audio_get_description(post_class_t *class_gen);
>+static void           vdr_audio_class_dispose(post_class_t *class_gen);
>+
>+/* plugin instance functions */
>+static void           vdr_audio_dispose(post_plugin_t *this_gen);
>+
>+/* replaced ao_port functions */
>+static int            vdr_audio_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream,
>+                                          uint32_t bits, uint32_t rate, int mode);
>+static void           vdr_audio_port_put_buffer(xine_audio_port_t *port_gen, audio_buffer_t *buf, xine_stream_t *stream);
>+
>+
>+
>+void *vdr_audio_init_plugin(xine_t *xine, void *data)
>+{
>+  post_class_t *class = (post_class_t *)malloc(sizeof (post_class_t));
>+  
>+  if (!class)
>+    return NULL;
>+  
>+  class->open_plugin     = vdr_audio_open_plugin;
>+  class->get_identifier  = vdr_audio_get_identifier;
>+  class->get_description = vdr_audio_get_description;
>+  class->dispose         = vdr_audio_class_dispose;
>+  
>+  return class;
>+}
>+
>+static post_plugin_t *vdr_audio_open_plugin(post_class_t *class_gen, int inputs,
>+				      xine_audio_port_t **audio_target,
>+				      xine_video_port_t **video_target)
>+{
>+  vdr_audio_post_plugin_t *this = (vdr_audio_post_plugin_t *)xine_xmalloc(sizeof (vdr_audio_post_plugin_t));
>+  post_in_t               *input;
>+  post_out_t              *output;
>+  post_audio_port_t       *port;
>+/*  
>+fprintf(stderr, "~~~~~~~~~~ vdr open plugin\n");
>+*/
>+  if (!this || !audio_target || !audio_target[ 0 ])
>+  {
>+    free(this);
>+    return NULL;
>+  }
>+
>+  _x_post_init(&this->post_plugin, 1, 0);
>+  this->post_plugin.dispose = vdr_audio_dispose;
>+
>+  port = _x_post_intercept_audio_port(&this->post_plugin, audio_target[ 0 ], &input, &output);
>+  port->new_port.open       = vdr_audio_port_open;
>+  port->new_port.put_buffer = vdr_audio_port_put_buffer;
>+
>+  this->post_plugin.xine_post.audio_input[ 0 ] = &port->new_port;
>+
>+  
>+
>+  this->audio_channels = 0;
>+  
>+  return &this->post_plugin;
>+}
>+
>+static char *vdr_audio_get_identifier(post_class_t *class_gen)
>+{
>+  return "vdr_audio";
>+}
>+
>+static char *vdr_audio_get_description(post_class_t *class_gen)
>+{
>+  return "modifies every audio frame as requested by VDR";
>+}
>+
>+static void vdr_audio_class_dispose(post_class_t *class_gen)
>+{
>+  free(class_gen);
>+}
>+
>+
>+static void vdr_audio_dispose(post_plugin_t *this_gen)
>+{
>+/*
>+fprintf(stderr, "~~~~~~~~~~ vdr dispose\n");
>+*/
>+  if (_x_post_dispose(this_gen))
>+  {
>+    vdr_audio_post_plugin_t *this = (vdr_audio_post_plugin_t *)this_gen;
>+    
>+    if (this->vdr_stream)
>+      xine_event_dispose_queue(this->event_queue);
>+    
>+    free(this_gen);
>+  }
>+}
>+
>+static int vdr_audio_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream,
>+                               uint32_t bits, uint32_t rate, int mode) {
>+
>+  post_audio_port_t       *port = (post_audio_port_t *)port_gen;
>+  vdr_audio_post_plugin_t *this = (vdr_audio_post_plugin_t *)port->post;
>+
>+  _x_post_rewire(&this->post_plugin);
>+  _x_post_inc_usage(port);
>+/*
>+fprintf(stderr, "~~~~~~~~~~ vdr port open\n");
>+*/
>+  port->stream = stream;
>+  port->bits = bits;
>+  port->rate = rate;
>+  port->mode = mode;
>+
>+  this->num_channels = _x_ao_mode2channels(mode);
>+
>+  return port->original_port->open(port->original_port, stream, bits, rate, mode );
>+}
>+
>+
>+static void vdr_audio_port_put_buffer(xine_audio_port_t *port_gen, audio_buffer_t *buf, xine_stream_t *stream)
>+{
>+  post_audio_port_t       *port = (post_audio_port_t *)port_gen;
>+  vdr_audio_post_plugin_t *this = (vdr_audio_post_plugin_t *)port->post;
>+  xine_event_t *event;
>+/*
>+fprintf(stderr, "~~~~~~ vdr_audio\n");
>+*/
>+  if (this->vdr_stream
>+      && !_x_continue_stream_processing(this->vdr_stream))
>+  {
>+    this->vdr_stream = 0;
>+    
>+    xine_event_dispose_queue(this->event_queue);
>+    this->event_queue = 0;
>+    
>+    this->audio_channels = 0;
>+  }
>+  
>+  if (!this->vdr_stream
>+      && vdr_is_vdr_stream(stream))
>+  {
>+    this->event_queue = xine_event_new_queue(stream);
>+    if (this->event_queue)
>+    {
>+      this->vdr_stream = stream;
>+      
>+      {
>+        xine_event_t event;
>+        
>+        event.type = XINE_EVENT_VDR_PLUGINSTARTED;
>+        event.data = 0;
>+        event.data_length = 1; /* vdr_audio */
>+        
>+        xine_event_send(this->vdr_stream, &event);
>+      }
>+    }
>+  }
>+  
>+  if (this->event_queue)
>+  {
>+    while ((event = xine_event_get(this->event_queue)))
>+    {
>+      if (event->type == XINE_EVENT_VDR_SELECTAUDIO)
>+      {
>+        vdr_select_audio_data_t *data = (vdr_select_audio_data_t *)event->data;
>+        
>+        vdr_audio_select_audio(this, data->channels);
>+      }
>+
>+      xine_event_free(event);
>+    }
>+  }
>+ 
>+  if (this->num_channels == 2
>+      && this->audio_channels != 0
>+      && this->audio_channels != 3)
>+  {
>+    audio_buffer_t *vdr_buf = port->original_port->get_buffer(port->original_port);
>+    vdr_buf->num_frames = buf->num_frames;
>+    vdr_buf->vpts = buf->vpts;
>+    vdr_buf->frame_header_count = buf->frame_header_count;
>+    vdr_buf->first_access_unit = buf->first_access_unit;
>+    /* FIXME: The audio buffer should contain this info.
>+     *        We should not have to get it from the open call.
>+     */
>+    vdr_buf->format.bits = buf->format.bits;
>+    vdr_buf->format.rate = buf->format.rate;
>+    vdr_buf->format.mode = buf->format.mode;
>+    _x_extra_info_merge(vdr_buf->extra_info, buf->extra_info);
>+
>+    {
>+      int step = buf->format.bits / 8;
>+      uint8_t *src = (uint8_t *)buf->mem;
>+      uint8_t *dst = (uint8_t *)vdr_buf->mem;
>+
>+      if (this->audio_channels == 2)
>+        src += step;
>+/*      
>+      fprintf(stderr, "~~~~~~~~~~ vdr port put buffer: channels: %d, %d\n"
>+              , this->audio_channels
>+              , buf->format.bits);
>+*/      
>+      int i, k;
>+      for (i = 0; i < buf->num_frames; i++)
>+      {
>+        for (k = 0; k < step; k++)
>+          *dst++ = *src++;
>+
>+        src -= step;
>+        
>+        for (k = 0; k < step; k++)
>+          *dst++ = *src++;
>+
>+        src += step;
>+      }
>+    }
>+    
>+    /* pass data to original port */
>+    port->original_port->put_buffer(port->original_port, vdr_buf, stream);
>+
>+    /* free data from origial buffer */
>+    buf->num_frames = 0; /* UNDOCUMENTED, but hey, it works! Force old audio_out buffer free. */
>+  }
>+ 
>+  port->original_port->put_buffer(port->original_port, buf, stream);
>+
>+  return;
>+}
>diff -ruN xine-lib-1.1.1.orig/src/vdr/post_vdr.c xine-lib-1.1.1/src/vdr/post_vdr.c
>--- xine-lib-1.1.1.orig/src/vdr/post_vdr.c	1970-01-01 01:00:00.000000000 +0100
>+++ xine-lib-1.1.1/src/vdr/post_vdr.c	2006-01-02 20:16:44.000000000 +0100
>@@ -0,0 +1,43 @@
>+/*
>+ * Copyright (C) 2000-2004 the xine project
>+ * 
>+ * This file is part of xine, a free video player.
>+ * 
>+ * xine is free software; you can redistribute it and/or modify
>+ * it under the terms of the GNU General Public License as published by
>+ * the Free Software Foundation; either version 2 of the License, or
>+ * (at your option) any later version.
>+ * 
>+ * xine is distributed in the hope that it will be useful,
>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>+ * GNU General Public License for more details.
>+ * 
>+ * You should have received a copy of the GNU General Public License
>+ * along with this program; if not, write to the Free Software
>+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
>+ *
>+ * $Id: vdr.c,v 1.20 2004/04/17 19:54:32 mroi Exp $
>+ */
>+ 
>+/*
>+ * plugins for VDR
>+ */
>+
>+#include "xine_internal.h"
>+#include "post.h"
>+#include "post_vdr.h"
>+
>+
>+
>+static post_info_t vdr_video_special_info = { XINE_POST_TYPE_VIDEO_FILTER };
>+static post_info_t vdr_audio_special_info = { XINE_POST_TYPE_AUDIO_FILTER };
>+
>+plugin_info_t xine_plugin_info[] =
>+{
>+  /* type, API, "name", version, special_info, init_function */  
>+  { PLUGIN_POST, 9, "vdr"      , XINE_VERSION_CODE, &vdr_video_special_info, &vdr_video_init_plugin },
>+  { PLUGIN_POST, 9, "vdr_video", XINE_VERSION_CODE, &vdr_video_special_info, &vdr_video_init_plugin },
>+  { PLUGIN_POST, 9, "vdr_audio", XINE_VERSION_CODE, &vdr_audio_special_info, &vdr_audio_init_plugin },
>+  { PLUGIN_NONE, 0, "", 0, NULL, NULL }
>+};
>diff -ruN xine-lib-1.1.1.orig/src/vdr/post_vdr.h xine-lib-1.1.1/src/vdr/post_vdr.h
>--- xine-lib-1.1.1.orig/src/vdr/post_vdr.h	1970-01-01 01:00:00.000000000 +0100
>+++ xine-lib-1.1.1/src/vdr/post_vdr.h	2006-01-02 20:17:08.000000000 +0100
>@@ -0,0 +1,70 @@
>+
>+#ifndef __POST_VDR_H
>+#define __POST_VDR_H
>+
>+
>+
>+typedef struct vdr_set_video_window_data_s {
>+  int32_t x;
>+  int32_t y;
>+  int32_t w;
>+  int32_t h;
>+  int32_t w_ref;
>+  int32_t h_ref;
>+
>+} vdr_set_video_window_data_t;
>+
>+
>+
>+typedef struct vdr_frame_size_changed_data_s {
>+  int32_t x;
>+  int32_t y;
>+  int32_t w;
>+  int32_t h;
>+
>+} vdr_frame_size_changed_data_t;
>+
>+
>+
>+typedef struct vdr_select_audio_data_s {
>+  uint8_t channels;
>+
>+} vdr_select_audio_data_t;
>+
>+
>+
>+inline static int vdr_is_vdr_stream(xine_stream_t *stream)
>+{
>+  if (!stream
>+      || !stream->input_plugin
>+      || !stream->input_plugin->input_class)
>+  {
>+    return 0;
>+  }
>+
>+  {
>+    input_class_t *input_class = stream->input_plugin->input_class;
>+
>+    if (input_class->get_identifier)
>+    {
>+      const char *identifier = input_class->get_identifier(input_class);
>+      if (identifier
>+          && 0 == strcmp(identifier, "VDR"))
>+      {
>+        return 1;
>+      }
>+    }
>+  }
>+
>+  return 0;
>+}
>+
>+
>+
>+/* plugin class initialization function */
>+void *vdr_video_init_plugin(xine_t *xine, void *);
>+void *vdr_audio_init_plugin(xine_t *xine, void *);
>+
>+
>+
>+#endif /* __POST_VDR_H */
>diff -ruN xine-lib-1.1.1.orig/src/vdr/post_vdr_video.c xine-lib-1.1.1/src/vdr/post_vdr_video.c
>--- xine-lib-1.1.1.orig/src/vdr/post_vdr_video.c	1970-01-01 01:00:00.000000000 +0100
>+++ xine-lib-1.1.1/src/vdr/post_vdr_video.c	2006-01-02 20:18:27.000000000 +0100
>@@ -0,0 +1,485 @@
>+/*
>+ * Copyright (C) 2000-2004 the xine project
>+ * 
>+ * This file is part of xine, a free video player.
>+ * 
>+ * xine is free software; you can redistribute it and/or modify
>+ * it under the terms of the GNU General Public License as published by
>+ * the Free Software Foundation; either version 2 of the License, or
>+ * (at your option) any later version.
>+ * 
>+ * xine is distributed in the hope that it will be useful,
>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>+ * GNU General Public License for more details.
>+ * 
>+ * You should have received a copy of the GNU General Public License
>+ * along with this program; if not, write to the Free Software
>+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
>+ *
>+ * $Id: vdr.c,v 1.20 2004/04/17 19:54:32 mroi Exp $
>+ */
>+ 
>+/*
>+ * frame scaler plugin for VDR
>+ */
>+
>+#define LOG_MODULE "vdr_video"
>+#define LOG_VERBOSE
>+/*
>+#define LOG
>+*/
>+
>+#include "xine_internal.h"
>+#include "post.h"
>+#include "post_vdr.h"
>+
>+
>+
>+typedef struct vdr_video_post_plugin_s
>+{
>+  post_plugin_t post_plugin;
>+
>+  xine_event_queue_t *event_queue;
>+  xine_stream_t      *vdr_stream;
>+  
>+  int8_t trick_speed_mode;
>+  int8_t enabled;
>+  
>+  int32_t x;
>+  int32_t y;
>+  int32_t w;
>+  int32_t h;
>+  int32_t w_ref;
>+  int32_t h_ref;
>+
>+  int32_t old_frame_left;
>+  int32_t old_frame_top;
>+  int32_t old_frame_width;
>+  int32_t old_frame_height;
>+  
>+}
>+vdr_video_post_plugin_t;
>+
>+
>+static void vdr_video_set_video_window(vdr_video_post_plugin_t *this, int32_t x, int32_t y, int32_t w, int32_t h, int32_t w_ref, int32_t h_ref)
>+{
>+  this->enabled = 0;
>+  
>+  this->x     = x;
>+  this->y     = y;
>+  this->w     = w;
>+  this->h     = h;
>+  this->w_ref = w_ref;
>+  this->h_ref = h_ref;
>+
>+  if (w != w_ref || h != h_ref)
>+    this->enabled = 1;
>+}
>+
>+ 
>+/* plugin class functions */
>+static post_plugin_t *vdr_video_open_plugin(post_class_t *class_gen, int inputs,
>+                                            xine_audio_port_t **audio_target,
>+                                            xine_video_port_t **video_target);
>+static char          *vdr_video_get_identifier(post_class_t *class_gen);
>+static char          *vdr_video_get_description(post_class_t *class_gen);
>+static void           vdr_video_class_dispose(post_class_t *class_gen);
>+
>+/* plugin instance functions */
>+static void           vdr_video_dispose(post_plugin_t *this_gen);
>+
>+/* frame intercept check */
>+static int            vdr_video_intercept_frame(post_video_port_t *port, vo_frame_t *frame);
>+
>+/* replaced vo_frame functions */
>+static int            vdr_video_draw(vo_frame_t *frame, xine_stream_t *stream);
>+
>+
>+void *vdr_video_init_plugin(xine_t *xine, void *data)
>+{
>+  post_class_t *class = (post_class_t *)malloc(sizeof (post_class_t));
>+  
>+  if (!class)
>+    return NULL;
>+  
>+  class->open_plugin     = vdr_video_open_plugin;
>+  class->get_identifier  = vdr_video_get_identifier;
>+  class->get_description = vdr_video_get_description;
>+  class->dispose         = vdr_video_class_dispose;
>+  
>+  return class;
>+}
>+
>+static post_plugin_t *vdr_video_open_plugin(post_class_t *class_gen, int inputs,
>+                                            xine_audio_port_t **audio_target,
>+                                            xine_video_port_t **video_target)
>+{
>+  vdr_video_post_plugin_t *this = (vdr_video_post_plugin_t *)xine_xmalloc(sizeof (vdr_video_post_plugin_t));
>+  post_in_t               *input;
>+  post_out_t              *output;
>+  post_video_port_t       *port;
>+  
>+  if (!this || !video_target || !video_target[ 0 ])
>+  {
>+    free(this);
>+    return NULL;
>+  }
>+
>+  _x_post_init(&this->post_plugin, 0, 1);
>+  this->post_plugin.dispose = vdr_video_dispose;
>+
>+  port = _x_post_intercept_video_port(&this->post_plugin, video_target[ 0 ], &input, &output);
>+  port->intercept_frame = vdr_video_intercept_frame;
>+  port->new_frame->draw = vdr_video_draw;
>+  this->post_plugin.xine_post.video_input[ 0 ] = &port->new_port;
>+  
>+  
>+  
>+  this->enabled          = 0;
>+  this->vdr_stream       = 0;
>+  this->event_queue      = 0;
>+  this->old_frame_left   = 0;
>+  this->old_frame_top    = 0;
>+  this->old_frame_width  = 0;
>+  this->old_frame_height = 0;
>+  this->trick_speed_mode = 0;
>+  
>+  return &this->post_plugin;
>+}
>+
>+static char *vdr_video_get_identifier(post_class_t *class_gen)
>+{
>+  return "vdr";
>+}
>+
>+static char *vdr_video_get_description(post_class_t *class_gen)
>+{
>+  return "modifies every video frame as requested by VDR";
>+}
>+
>+static void vdr_video_class_dispose(post_class_t *class_gen)
>+{
>+  free(class_gen);
>+}
>+
>+
>+static void vdr_video_dispose(post_plugin_t *this_gen)
>+{
>+  if (_x_post_dispose(this_gen))
>+  {
>+    vdr_video_post_plugin_t *this = (vdr_video_post_plugin_t *)this_gen;
>+    
>+    if (this->vdr_stream)
>+    {
>+      xine_event_t event;
>+      vdr_frame_size_changed_data_t event_data;
>+
>+      event_data.x = 0;
>+      event_data.y = 0;
>+      event_data.w = 0;
>+      event_data.h = 0;
>+      
>+      event.type        = XINE_EVENT_VDR_FRAMESIZECHANGED;
>+      event.data        = &event_data;
>+      event.data_length = sizeof (event_data);
>+      
>+      xine_event_send(this->vdr_stream, &event);
>+
>+      xine_event_dispose_queue(this->event_queue);
>+    }
>+    
>+    free(this_gen);
>+  }
>+}
>+
>+
>+static int vdr_video_intercept_frame(post_video_port_t *port, vo_frame_t *frame)
>+{
>+  return (frame->format == XINE_IMGFMT_YUY2
>+          || frame->format == XINE_IMGFMT_YV12);
>+}
>+
>+
>+static inline void vdr_video_scale(uint8_t *src, uint8_t *dst, int y_inc, int x_inc, int w_dst, int h_dst, int x, int y, int w, int h, int w_ref, int h_ref, int init)
>+{
>+  int x0 = x * w_dst / w_ref;
>+  int y0 = y * h_dst / h_ref;
>+
>+  int x1 = ((x + w) * w_dst - 1 + w_ref) / w_ref;
>+  int y1 = ((y + h) * h_dst - 1 + h_ref) / h_ref;
>+
>+  int dx = x1 - x0;
>+  int dy = y1 - y0;
>+
>+  int yy, xx;
>+
>+  int dy2    = dy + dy;
>+  int h_dst2 = h_dst + h_dst;
>+  int y_eps  = h_dst - dy2;
>+
>+  int dx2    = dx + dx;
>+  int w_dst2 = w_dst + w_dst;
>+  int x_eps0 = w_dst - dx2;
>+    
>+  for (yy = 0; yy < y0; yy++)
>+  {
>+    uint8_t *dst0 = dst;
>+    
>+    for (xx = 0; xx < w_dst; xx++)
>+    {
>+      *dst0 = init;
>+      dst0 += x_inc;
>+    }
>+
>+    dst += y_inc;
>+  }
>+
>+  for (yy = y0; yy < y1; yy++)
>+  {
>+    uint8_t *dst0 = dst;
>+    uint8_t *src0 = src;
>+
>+    int x_eps = x_eps0;
>+    
>+    for (xx = 0; xx < x0; xx++)
>+    {
>+      *dst0 = init;
>+      dst0 += x_inc;
>+    }
>+    
>+    for (xx = x0; xx < x1; xx++)
>+    {
>+      *dst0 = *src0;
>+      dst0 += x_inc;
>+      
>+      x_eps += w_dst2;
>+      while (x_eps >= 0)
>+      {
>+        src0  += x_inc;
>+        x_eps -= dx2;
>+      }
>+    }
>+    
>+    for (xx = x1; xx < w_dst; xx++)
>+    {
>+      *dst0 = init;
>+      dst0 += x_inc;
>+    }
>+
>+    dst += y_inc;
>+
>+    y_eps += h_dst2;
>+    while (y_eps >= 0)
>+    {
>+      src   += y_inc;
>+      y_eps -= dy2;
>+    }
>+  }
>+  
>+  for (yy = y1; yy < h_dst; yy++)
>+  {
>+    uint8_t *dst0 = dst;
>+    
>+    for (xx = 0; xx < w_dst; xx++)
>+    {
>+      *dst0 = init;
>+      dst0 += x_inc;
>+    }
>+
>+    dst += y_inc;
>+  }  
>+}
>+
>+static void vdr_video_scale_YUY2(vdr_video_post_plugin_t *this, vo_frame_t *src, vo_frame_t *dst)
>+{
>+  int w = dst->width  - dst->crop_left - dst->crop_right;
>+  int h = dst->height - dst->crop_top  - dst->crop_bottom;
>+  int offset;
>+  
>+  if (w < 0)
>+    w = 0;
>+  
>+  if (h < 0)
>+    h = 0;
>+
>+  offset = dst->pitches[ 0 ] * dst->crop_top + 2 *   dst->crop_left;
>+  vdr_video_scale(&src->base[ 0 ][ 0 ] + offset, &dst->base[ 0 ][ 0 ] + offset, dst->pitches[ 0 ], 2,  w         , h, this->x, this->y, this->w, this->h, this->w_ref, this->h_ref, 0x00);
>+  offset = dst->pitches[ 0 ] * dst->crop_top + 4 * ((dst->crop_left + 1) / 2);
>+  vdr_video_scale(&src->base[ 0 ][ 1 ] + offset, &dst->base[ 0 ][ 1 ] + offset, dst->pitches[ 0 ], 4, (w + 1) / 2, h, this->x, this->y, this->w, this->h, this->w_ref, this->h_ref, 0x80);
>+  offset = dst->pitches[ 0 ] * dst->crop_top + 4 * ((dst->crop_left + 1) / 2);
>+  vdr_video_scale(&src->base[ 0 ][ 3 ] + offset, &dst->base[ 0 ][ 3 ] + offset, dst->pitches[ 0 ], 4, (w + 1) / 2, h, this->x, this->y, this->w, this->h, this->w_ref, this->h_ref, 0x80);
>+}
>+
>+static void vdr_video_scale_YV12(vdr_video_post_plugin_t *this, vo_frame_t *src, vo_frame_t *dst)
>+{
>+  int w = dst->width  - dst->crop_left - dst->crop_right;
>+  int h = dst->height - dst->crop_top  - dst->crop_bottom;
>+  int offset;
>+  
>+  if (w < 0)
>+    w = 0;
>+  
>+  if (h < 0)
>+    h = 0;
>+
>+  offset = dst->pitches[ 0 ] *   dst->crop_top           + 1 *   dst->crop_left;
>+  vdr_video_scale(&src->base[ 0 ][ 0 ] + offset, &dst->base[ 0 ][ 0 ] + offset, dst->pitches[ 0 ], 1,  w         ,  h         , this->x, this->y, this->w, this->h, this->w_ref, this->h_ref, 0x00);
>+  offset = dst->pitches[ 1 ] * ((dst->crop_top + 1) / 2) + 1 * ((dst->crop_left + 1) / 2);
>+  vdr_video_scale(&src->base[ 1 ][ 0 ] + offset, &dst->base[ 1 ][ 0 ] + offset, dst->pitches[ 1 ], 1, (w + 1) / 2, (h + 1) / 2, this->x, this->y, this->w, this->h, this->w_ref, this->h_ref, 0x80);
>+  offset = dst->pitches[ 2 ] * ((dst->crop_top + 1) / 2) + 1 * ((dst->crop_left + 1) / 2);
>+  vdr_video_scale(&src->base[ 2 ][ 0 ] + offset, &dst->base[ 2 ][ 0 ] + offset, dst->pitches[ 2 ], 1, (w + 1) / 2, (h + 1) / 2, this->x, this->y, this->w, this->h, this->w_ref, this->h_ref, 0x80);
>+}
>+
>+
>+static int vdr_video_draw(vo_frame_t *frame, xine_stream_t *stream)
>+{
>+  post_video_port_t       *port = (post_video_port_t *)frame->port;
>+  vdr_video_post_plugin_t *this = (vdr_video_post_plugin_t *)port->post;
>+  vo_frame_t *vdr_frame;
>+  xine_event_t *event;
>+  int skip;
>+
>+  if (this->vdr_stream
>+      && !_x_continue_stream_processing(this->vdr_stream))
>+  {
>+    this->vdr_stream = 0;
>+    
>+    xine_event_dispose_queue(this->event_queue);
>+    this->event_queue = 0;
>+    
>+    this->old_frame_left   = 0;
>+    this->old_frame_top    = 0;
>+    this->old_frame_width  = 0;
>+    this->old_frame_height = 0;
>+  }
>+  
>+  if (!this->vdr_stream
>+      && vdr_is_vdr_stream(stream))
>+  {
>+    this->event_queue = xine_event_new_queue(stream);
>+    if (this->event_queue)
>+    {
>+      this->vdr_stream = stream;
>+      
>+      {
>+        xine_event_t event;
>+        
>+        event.type = XINE_EVENT_VDR_PLUGINSTARTED;
>+        event.data = 0;
>+        event.data_length = 0; /* vdr_video */
>+        
>+        xine_event_send(this->vdr_stream, &event);
>+      }
>+    }
>+  }
>+  
>+  if (this->event_queue)
>+  {
>+    while ((event = xine_event_get(this->event_queue)))
>+    {
>+      if (event->type == XINE_EVENT_VDR_SETVIDEOWINDOW)
>+      {
>+        vdr_set_video_window_data_t *data = (vdr_set_video_window_data_t *)event->data;
>+        
>+        vdr_video_set_video_window(this, data->x, data->y, data->w, data->h, data->w_ref, data->h_ref);
>+      }
>+      else if (event->type == XINE_EVENT_VDR_TRICKSPEEDMODE)
>+      {
>+/*
>+        fprintf(stderr, "###############################: %p, %d\n", event->data, event->data_length);
>+        this->trick_speed_mode = (0 != event->data_length);
>+*/
>+      }
>+
>+      xine_event_free(event);
>+    }
>+  }
>+
>+  {
>+    int frame_left   = frame->crop_left;
>+    int frame_width  = frame->width - frame->crop_left - frame->crop_right;
>+    int frame_top    = frame->crop_top;
>+    int frame_height = frame->height - frame->crop_top - frame->crop_bottom;
>+
>+    if (frame_left < 0)
>+      frame_left = 0;
>+    if (frame_width > frame->width)
>+      frame_width = frame->width;
>+    if (frame_top < 0)
>+      frame_top = 0;
>+    if (frame_height > frame->height)
>+      frame_height = frame->height;
>+    
>+    if (this->vdr_stream
>+        && (this->old_frame_left != frame_left
>+          || this->old_frame_top != frame_top
>+          || this->old_frame_width != frame_width
>+          || this->old_frame_height != frame_height))
>+    {
>+      xine_event_t event;
>+      vdr_frame_size_changed_data_t event_data;
>+
>+      event_data.x = frame_left;
>+      event_data.y = frame_top;
>+      event_data.w = frame_width;
>+      event_data.h = frame_height;
>+      
>+      xprintf(this->vdr_stream->xine, XINE_VERBOSITY_LOG,
>+            _(LOG_MODULE ": osd: (%d, %d)-(%d, %d)\n"), frame_left, frame_top, frame_width, frame_height);
>+      
>+      event.type        = XINE_EVENT_VDR_FRAMESIZECHANGED;
>+      event.data        = &event_data;
>+      event.data_length = sizeof (event_data);
>+      
>+      xine_event_send(this->vdr_stream, &event);
>+    
>+      this->old_frame_left   = frame_left;
>+      this->old_frame_top    = frame_top;
>+      this->old_frame_width  = frame_width;
>+      this->old_frame_height = frame_height;
>+    }
>+  }
>+/*
>+  fprintf(stderr, "~~~~~~~~~~~~ trickspeedmode: %d\n", this->trick_speed_mode);  
>+  
>+  if (this->vdr_stream
>+      && this->trick_speed_mode)
>+  {
>+    frame->pts = 0;
>+    frame->next->pts = 0;
>+  }
>+*/  
>+  if (!this->enabled 
>+      || frame->bad_frame
>+      || (frame->format != XINE_IMGFMT_YUY2
>+          && frame->format != XINE_IMGFMT_YV12))
>+  {
>+    _x_post_frame_copy_down(frame, frame->next);
>+    skip = frame->next->draw(frame->next, stream);
>+    _x_post_frame_copy_up(frame, frame->next);
>+    return skip;
>+  }
>+
>+  vdr_frame = port->original_port->get_frame(port->original_port,
>+    frame->width, frame->height, frame->ratio, frame->format, frame->flags | VO_BOTH_FIELDS);
>+
>+  _x_post_frame_copy_down(frame, vdr_frame);
>+    
>+  switch (vdr_frame->format)
>+  {
>+  case XINE_IMGFMT_YUY2:
>+    vdr_video_scale_YUY2(this, frame, vdr_frame);
>+    break;
>+    
>+  case XINE_IMGFMT_YV12:
>+    vdr_video_scale_YV12(this, frame, vdr_frame);    
>+    break;
>+  }
>+  
>+  skip = vdr_frame->draw(vdr_frame, stream);
>+  _x_post_frame_copy_up(frame, vdr_frame);
>+  vdr_frame->free(vdr_frame);
>+  
>+  return skip;
>+}
>diff -ruN xine-lib-1.1.1.orig/src/xine-engine/video_out.c xine-lib-1.1.1/src/xine-engine/video_out.c
>--- xine-lib-1.1.1.orig/src/xine-engine/video_out.c	2005-11-15 00:48:19.000000000 +0100
>+++ xine-lib-1.1.1/src/xine-engine/video_out.c	2006-01-02 20:07:20.000000000 +0100
>@@ -566,6 +566,7 @@
>     vo_append_to_img_buf_queue (this->display_img_buf_queue, img);
>     
>   } else {
>+    fprintf (stderr, "bad_frame\n");
>     lprintf ("bad_frame\n");
> 
>     if (stream) {
>diff -ruN xine-lib-1.1.1.orig/src/xine-engine/video_overlay.h xine-lib-1.1.1/src/xine-engine/video_overlay.h
>--- xine-lib-1.1.1.orig/src/xine-engine/video_overlay.h	2005-09-24 21:08:26.000000000 +0200
>+++ xine-lib-1.1.1/src/xine-engine/video_overlay.h	2006-01-02 20:08:00.000000000 +0100
>@@ -38,7 +38,7 @@
> 
> #define MAX_OBJECTS   50
> #define MAX_EVENTS    50
>-#define MAX_SHOWING   16
>+#define MAX_SHOWING   (5 + 16)
> 
> #define OVERLAY_EVENT_NULL             0
> #define OVERLAY_EVENT_SHOW             1
>diff -ruN xine-lib-1.1.1.orig/src/xine-engine/xine.c xine-lib-1.1.1/src/xine-engine/xine.c
>--- xine-lib-1.1.1.orig/src/xine-engine/xine.c	2005-10-30 03:18:35.000000000 +0100
>+++ xine-lib-1.1.1/src/xine-engine/xine.c	2006-01-02 20:09:45.000000000 +0100
>@@ -1936,3 +1936,86 @@
>   slave->master = master->master;
>   return 1;
> }
>+
>+int _x_continue_stream_processing(xine_stream_t *stream)
>+{
>+  return stream->status != XINE_STATUS_STOP
>+    && stream->status != XINE_STATUS_QUIT;
>+}
>+
>+void _x_trigger_relaxed_frame_drop_mode(xine_stream_t *stream)
>+{
>+  stream->first_frame_flag = 2;
>+}
>+
>+void _x_reset_relaxed_frame_drop_mode(xine_stream_t *stream)
>+{
>+  stream->first_frame_flag = 1;
>+}
>+
>+void _x_query_buffer_usage(xine_stream_t *stream, int *num_video_buffers, int *num_audio_buffers, int *num_video_frames, int *num_audio_frames)
>+{
>+  stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
>+
>+  if (num_video_buffers)
>+    *num_video_buffers = (stream->video_fifo ? stream->video_fifo->size(stream->video_fifo) : 0);
>+    
>+  if (num_audio_buffers)
>+    *num_audio_buffers = (stream->audio_fifo ? stream->audio_fifo->size(stream->audio_fifo) : 0);
>+    
>+  if (num_video_frames)
>+    *num_video_frames = (stream->video_out ? stream->video_out->get_property(stream->video_out, VO_PROP_BUFS_IN_FIFO) : 0);
>+
>+  if (num_audio_frames)
>+    *num_audio_frames = (stream->audio_out ? stream->audio_out->get_property(stream->audio_out, AO_PROP_BUFS_IN_FIFO) : 0);
>+
>+  stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
>+}
>+
>+int _x_query_unprocessed_osd_events(xine_stream_t *stream)
>+{
>+  video_overlay_manager_t *ovl;
>+  int redraw_needed;
>+  
>+  stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
>+
>+  ovl = stream->video_out->get_overlay_manager(stream->video_out);
>+  redraw_needed = ovl->redraw_needed(ovl, 0);
>+  
>+  stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
>+
>+  return redraw_needed;
>+}
>+
>+int _x_demux_seek(xine_stream_t *stream, off_t start_pos, int start_time, int playing)
>+{
>+  return stream->demux_plugin->seek(stream->demux_plugin, start_pos, start_time, playing);
>+}
>+
>+int _x_lock_frontend(xine_stream_t *stream, int ms_to_time_out)
>+{
>+  if (ms_to_time_out >= 0) {
>+    struct timespec abstime;
>+
>+    struct timeval now;
>+    gettimeofday(&now, 0);
>+
>+    abstime.tv_sec = now.tv_sec + ms_to_time_out / 1000;
>+    abstime.tv_nsec = now.tv_usec * 1000 + (ms_to_time_out % 1000) * 1e6;
>+
>+    if (abstime.tv_nsec > 1e9) {
>+      abstime.tv_nsec -= 1e9;
>+      abstime.tv_sec++;
>+    }
>+
>+    return (0 == pthread_mutex_timedlock(&stream->frontend_lock, &abstime));
>+  }
>+
>+  pthread_mutex_lock(&stream->frontend_lock);
>+  return 1;
>+}
>+
>+void _x_unlock_frontend(xine_stream_t *stream)
>+{
>+  pthread_mutex_unlock(&stream->frontend_lock);
>+}
>diff -ruN xine-lib-1.1.1.orig/src/xine-engine/xine_internal.h xine-lib-1.1.1/src/xine-engine/xine_internal.h
>--- xine-lib-1.1.1.orig/src/xine-engine/xine_internal.h	2005-10-30 03:18:35.000000000 +0100
>+++ xine-lib-1.1.1/src/xine-engine/xine_internal.h	2006-01-02 20:10:34.000000000 +0100
>@@ -350,6 +350,15 @@
>  * private function prototypes:
>  */
> 
>+int _x_continue_stream_processing(xine_stream_t *stream);
>+void _x_trigger_relaxed_frame_drop_mode(xine_stream_t *stream);
>+void _x_reset_relaxed_frame_drop_mode(xine_stream_t *stream);
>+void _x_query_buffer_usage(xine_stream_t *stream, int *num_video_buffers, int *num_audio_buffers, int *num_video_frames, int *num_audio_frames);
>+int _x_query_unprocessed_osd_events(xine_stream_t *stream);
>+int _x_demux_seek(xine_stream_t *stream, off_t start_pos, int start_time, int playing);
>+int _x_lock_frontend(xine_stream_t *stream, int ms_to_time_out);
>+void _x_unlock_frontend(xine_stream_t *stream);
>+
> void _x_handle_stream_end      (xine_stream_t *stream, int non_user);
> 
> /* report message to UI. usually these are async errors */
>  
>
>------------------------------------------------------------------------
>
>diff -ruN xine-ui-0.99.4.orig/src/fb/actions.c xine-ui-0.99.4/src/fb/actions.c
>--- xine-ui-0.99.4.orig/src/fb/actions.c	2004-08-11 13:45:37.000000000 +0200
>+++ xine-ui-0.99.4/src/fb/actions.c	2006-01-02 20:32:42.000000000 +0100
>@@ -275,6 +275,8 @@
> 	  "VDRVolumeMinus",         ACTID_EVENT_VDR_VOLMINUS },
> 	{ "VDR Audio Mute",
> 	  "VDRMute",                ACTID_EVENT_VDR_MUTE },
>+	{ "VDR Audio menu",
>+	  "VDRAudio",               ACTID_EVENT_VDR_AUDIO },
> #endif
> 	{ 0,
> 		  0, 0 }
>diff -ruN xine-ui-0.99.4.orig/src/fb/actions.h xine-ui-0.99.4/src/fb/actions.h
>--- xine-ui-0.99.4.orig/src/fb/actions.h	2004-08-11 13:45:38.000000000 +0200
>+++ xine-ui-0.99.4/src/fb/actions.h	2006-01-02 20:33:20.000000000 +0100
>@@ -188,7 +188,8 @@
>   ACTID_EVENT_VDR_USER9         = XINE_EVENT_VDR_USER9            | ACTID_IS_INPUT_EVENT,
>   ACTID_EVENT_VDR_VOLPLUS       = XINE_EVENT_VDR_VOLPLUS          | ACTID_IS_INPUT_EVENT,
>   ACTID_EVENT_VDR_VOLMINUS      = XINE_EVENT_VDR_VOLMINUS         | ACTID_IS_INPUT_EVENT,
>-  ACTID_EVENT_VDR_MUTE          = XINE_EVENT_VDR_MUTE             | ACTID_IS_INPUT_EVENT
>+  ACTID_EVENT_VDR_MUTE          = XINE_EVENT_VDR_MUTE             | ACTID_IS_INPUT_EVENT,
>+  ACTID_EVENT_VDR_AUDIO         = XINE_EVENT_VDR_AUDIO            | ACTID_IS_INPUT_EVENT
> #endif
> 
>   /*
>diff -ruN xine-ui-0.99.4.orig/src/xitk/kbindings.c xine-ui-0.99.4/src/xitk/kbindings.c
>--- xine-ui-0.99.4.orig/src/xitk/kbindings.c	2005-07-16 21:05:31.000000000 +0200
>+++ xine-ui-0.99.4/src/xitk/kbindings.c	2006-01-02 20:34:03.000000000 +0100
>@@ -511,6 +511,8 @@
>     "VDRVolumeMinus",         ACTID_EVENT_VDR_VOLMINUS      , "VOID",     KEYMOD_NOMOD   , 0 , 0},
>   { "VDR Audio Mute",
>     "VDRMute",                ACTID_EVENT_VDR_MUTE          , "VOID",     KEYMOD_NOMOD   , 0 , 0},
>+  { "VDR Audio menu",
>+    "VDRAudio",               ACTID_EVENT_VDR_AUDIO         , "VOID",     KEYMOD_NOMOD   , 0 , 0},
> #endif
>   { 0,
>     0,                        0,                              0,          0              , 0 , 0}
>diff -ruN xine-ui-0.99.4.orig/src/xitk/kbindings.h xine-ui-0.99.4/src/xitk/kbindings.h
>--- xine-ui-0.99.4.orig/src/xitk/kbindings.h	2005-07-16 21:05:31.000000000 +0200
>+++ xine-ui-0.99.4/src/xitk/kbindings.h	2006-01-02 20:34:28.000000000 +0100
>@@ -209,7 +209,8 @@
>   ACTID_EVENT_VDR_USER9         = XINE_EVENT_VDR_USER9            | ACTID_IS_INPUT_EVENT,
>   ACTID_EVENT_VDR_VOLPLUS       = XINE_EVENT_VDR_VOLPLUS          | ACTID_IS_INPUT_EVENT,
>   ACTID_EVENT_VDR_VOLMINUS      = XINE_EVENT_VDR_VOLMINUS         | ACTID_IS_INPUT_EVENT,
>-  ACTID_EVENT_VDR_MUTE          = XINE_EVENT_VDR_MUTE             | ACTID_IS_INPUT_EVENT
>+  ACTID_EVENT_VDR_MUTE          = XINE_EVENT_VDR_MUTE             | ACTID_IS_INPUT_EVENT,
>+  ACTID_EVENT_VDR_AUDIO         = XINE_EVENT_VDR_AUDIO            | ACTID_IS_INPUT_EVENT
> #endif
> 
>   /*
>  
>
>------------------------------------------------------------------------
>
>_______________________________________________
>vdr mailing list
>vdr at linuxtv.org
>http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
>  
>




More information about the vdr mailing list