[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