updated on Thu Jan 26 16:09:46 UTC 2012
[aur-mirror.git] / xine-lib-vdr / xine-lib.patch
blob45c9123d712e123f06519d737f2de41bd12f101f
1 diff --git a/configure.ac b/configure.ac
2 --- a/configure.ac
3 +++ b/configure.ac
4 @@ -2768,6 +2768,7 @@ src/video_out/vidix/drivers/Makefile
5 src/video_out/vidix/drivers/Makefile
6 src/xine-utils/Makefile
7 src/xine-engine/Makefile
8 +src/vdr/Makefile
9 win32/Makefile
10 win32/include/Makefile])
11 AC_CONFIG_COMMANDS([default],[[chmod +x ./misc/SlackBuild ./misc/build_rpms.sh ./misc/relchk.sh]],[[]])
12 @@ -2810,7 +2811,7 @@ echo " - stdin_fifo - rtp"
13 echo " - stdin_fifo - rtp"
14 echo " - http - mms"
15 echo " - pnm - rtsp"
16 -echo " - dvb"
17 +echo " - dvb - vdr"
18 if test "x$external_dvdnav" = "xyes"; then
19 echo " - dvd (external libs)"
20 else
21 @@ -3015,6 +3016,7 @@ echo " - eq - eq2"
22 echo " - eq - eq2"
23 echo " - boxblur - denoise3d"
24 echo " - unsharp - tvtime"
25 +echo " - vdr"
26 echo " * SFX:"
27 echo " - goom - oscope"
28 echo " - fftscope - mosaico"
29 diff --git a/src/Makefile.am b/src/Makefile.am
30 --- a/src/Makefile.am
31 +++ b/src/Makefile.am
32 @@ -26,4 +26,5 @@ SUBDIRS = \
33 libfaad \
34 libmusepack \
35 post \
36 - combined
37 + combined \
38 + vdr
39 diff --git a/src/vdr/Makefile.am b/src/vdr/Makefile.am
40 new file mode 100644
41 --- /dev/null
42 +++ b/src/vdr/Makefile.am
43 @@ -0,0 +1,13 @@
44 +include $(top_srcdir)/misc/Makefile.common
46 +AM_CFLAGS = -D_LARGEFILE64_SOURCE
48 +xineplug_LTLIBRARIES = \
49 + xineplug_vdr.la
51 +xineplug_vdr_la_SOURCES = combined_vdr.c input_vdr.c post_vdr_video.c post_vdr_audio.c
52 +xineplug_vdr_la_LIBADD = $(XINE_LIB)
53 +xineplug_vdr_la_LDFLAGS = -avoid-version -module @IMPURE_TEXT_LDFLAGS@
55 +xineinclude_HEADERS = vdr.h
56 +noinst_HEADERS = combined_vdr.h
57 diff --git a/src/vdr/combined_vdr.c b/src/vdr/combined_vdr.c
58 new file mode 100644
59 --- /dev/null
60 +++ b/src/vdr/combined_vdr.c
61 @@ -0,0 +1,44 @@
62 +/*
63 + * Copyright (C) 2000-2004 the xine project
64 + *
65 + * This file is part of xine, a free video player.
66 + *
67 + * xine is free software; you can redistribute it and/or modify
68 + * it under the terms of the GNU General Public License as published by
69 + * the Free Software Foundation; either version 2 of the License, or
70 + * (at your option) any later version.
71 + *
72 + * xine is distributed in the hope that it will be useful,
73 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
74 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
75 + * GNU General Public License for more details.
76 + *
77 + * You should have received a copy of the GNU General Public License
78 + * along with this program; if not, write to the Free Software
79 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
80 + */
82 +/*
83 + * plugins for VDR
84 + */
86 +#include "xine_internal.h"
87 +#include "post.h"
88 +#include "combined_vdr.h"
92 +static const post_info_t vdr_video_special_info = { XINE_POST_TYPE_VIDEO_FILTER };
93 +static const post_info_t vdr_audio_special_info = { XINE_POST_TYPE_AUDIO_FILTER };
95 +/* exported plugin catalog entry */
96 +const plugin_info_t xine_plugin_info[] EXPORTED =
98 + /* type , API, "name" , version , special_info , init_function */
99 + { PLUGIN_INPUT, 17, "VDR" , XINE_VERSION_CODE, NULL , &vdr_input_init_plugin },
100 + { PLUGIN_POST , 9, "vdr" , XINE_VERSION_CODE, &vdr_video_special_info, &vdr_video_init_plugin },
101 + { PLUGIN_POST , 9, "vdr_video", XINE_VERSION_CODE, &vdr_video_special_info, &vdr_video_init_plugin },
102 + { PLUGIN_POST , 9, "vdr_audio", XINE_VERSION_CODE, &vdr_audio_special_info, &vdr_audio_init_plugin },
103 + { PLUGIN_NONE , 0, "" , 0 , NULL , NULL }
106 diff --git a/src/vdr/combined_vdr.h b/src/vdr/combined_vdr.h
107 new file mode 100644
108 --- /dev/null
109 +++ b/src/vdr/combined_vdr.h
110 @@ -0,0 +1,92 @@
112 + * Copyright (C) 2000-2004 the xine project
114 + * This file is part of xine, a free video player.
116 + * xine is free software; you can redistribute it and/or modify
117 + * it under the terms of the GNU General Public License as published by
118 + * the Free Software Foundation; either version 2 of the License, or
119 + * (at your option) any later version.
121 + * xine is distributed in the hope that it will be useful,
122 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
123 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
124 + * GNU General Public License for more details.
126 + * You should have received a copy of the GNU General Public License
127 + * along with this program; if not, write to the Free Software
128 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
129 + */
131 +#ifndef __COMBINED_VDR_H
132 +#define __COMBINED_VDR_H
136 +typedef struct vdr_set_video_window_data_s {
137 + int32_t x;
138 + int32_t y;
139 + int32_t w;
140 + int32_t h;
141 + int32_t w_ref;
142 + int32_t h_ref;
144 +} vdr_set_video_window_data_t;
148 +typedef struct vdr_frame_size_changed_data_s {
149 + int32_t x;
150 + int32_t y;
151 + int32_t w;
152 + int32_t h;
153 + double r;
155 +} vdr_frame_size_changed_data_t;
159 +typedef struct vdr_select_audio_data_s {
160 + uint8_t channels;
162 +} vdr_select_audio_data_t;
166 +inline static int vdr_is_vdr_stream(xine_stream_t *stream)
168 + if (!stream
169 + || !stream->input_plugin
170 + || !stream->input_plugin->input_class)
172 + return 0;
176 + input_class_t *input_class = stream->input_plugin->input_class;
178 + if (input_class->get_identifier)
180 + const char *identifier = input_class->get_identifier(input_class);
181 + if (identifier
182 + && 0 == strcmp(identifier, "VDR"))
184 + return 1;
189 + return 0;
194 +/* plugin class initialization function */
195 +void *vdr_input_init_plugin(xine_t *xine, void *data);
196 +void *vdr_video_init_plugin(xine_t *xine, void *data);
197 +void *vdr_audio_init_plugin(xine_t *xine, void *data);
201 +#endif /* __COMBINED_VDR_H */
203 diff --git a/src/vdr/input_vdr.c b/src/vdr/input_vdr.c
204 new file mode 100644
205 --- /dev/null
206 +++ b/src/vdr/input_vdr.c
207 @@ -0,0 +1,2363 @@
209 + * Copyright (C) 2003-2004 the xine project
211 + * This file is part of xine, a free video player.
212 + *
213 + * xine is free software; you can redistribute it and/or modify
214 + * it under the terms of the GNU General Public License as published by
215 + * the Free Software Foundation; either version 2 of the License, or
216 + * (at your option) any later version.
217 + *
218 + * xine is distributed in the hope that it will be useful,
219 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
220 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
221 + * GNU General Public License for more details.
222 + *
223 + * You should have received a copy of the GNU General Public License
224 + * along with this program; if not, write to the Free Software
225 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
226 + */
228 +#ifdef HAVE_CONFIG_H
229 +#include "config.h"
230 +#endif
232 +#include <stdio.h>
233 +#include <stdlib.h>
234 +#include <string.h>
235 +#include <fcntl.h>
236 +#include <unistd.h>
237 +#include <sys/stat.h>
238 +#include <sys/poll.h>
239 +#include <errno.h>
240 +#include <pthread.h>
242 +#include <sys/socket.h>
243 +#include <resolv.h>
244 +#include <netdb.h>
246 +#define LOG_MODULE "input_vdr"
247 +#define LOG_VERBOSE
249 +#define LOG
251 +#include "xine_internal.h"
252 +#include "xineutils.h"
253 +#include "input_plugin.h"
255 +#include "vdr.h"
256 +#include "combined_vdr.h"
260 +#define VDR_MAX_NUM_WINDOWS 16
261 +#define VDR_ABS_FIFO_DIR "/tmp/vdr-xine"
263 +#define BUF_SIZE 1024
265 +#define LOG_OSD(x)
267 +#define LOG_OSD(x) x
271 +typedef struct vdr_input_plugin_s vdr_input_plugin_t;
273 +typedef struct
275 + metronom_t metronom;
276 + metronom_t *stream_metronom;
277 + vdr_input_plugin_t *input;
279 +vdr_metronom_t;
282 +typedef struct vdr_osd_s
284 + xine_osd_t *window;
285 + uint8_t *argb_buffer;
286 + int width;
287 + int height;
289 +vdr_osd_t;
292 +struct vdr_input_plugin_s
294 + input_plugin_t input_plugin;
296 + xine_stream_t *stream;
297 + xine_stream_t *stream_external;
299 + int fh;
300 + int fh_control;
301 + int fh_result;
302 + int fh_event;
304 + char *mrl;
306 + off_t curpos;
307 + char seek_buf[ BUF_SIZE ];
309 + char *preview;
310 + off_t preview_size;
312 + enum funcs cur_func;
313 + off_t cur_size;
314 + off_t cur_done;
316 + vdr_osd_t osd[ VDR_MAX_NUM_WINDOWS ];
317 + uint8_t *osd_buffer;
318 + uint32_t osd_buffer_size;
319 + uint8_t osd_unscaled_blending;
320 + uint8_t osd_supports_custom_extent;
321 + uint8_t osd_supports_argb_layer;
323 + uint8_t audio_channels;
324 + uint8_t trick_speed_mode;
325 + uint8_t mute_mode;
326 + uint8_t volume_mode;
327 + int last_volume;
328 + vdr_frame_size_changed_data_t frame_size;
330 + pthread_t rpc_thread;
331 + int rpc_thread_shutdown;
332 + pthread_mutex_t rpc_thread_shutdown_lock;
333 + pthread_cond_t rpc_thread_shutdown_cond;
334 + int startup_phase;
336 + xine_event_queue_t *event_queue;
337 + xine_event_queue_t *event_queue_external;
339 + pthread_mutex_t adjust_zoom_lock;
340 + uint16_t image4_3_zoom_x;
341 + uint16_t image4_3_zoom_y;
342 + uint16_t image16_9_zoom_x;
343 + uint16_t image16_9_zoom_y;
345 + uint8_t find_sync_point;
346 + pthread_mutex_t find_sync_point_lock;
348 + vdr_metronom_t metronom;
349 + int last_disc_type;
353 +typedef struct
355 + input_class_t input_class;
356 + xine_t *xine;
357 + const char *mrls[ 2 ];
359 +vdr_input_class_t;
363 +static int vdr_write(int f, void *b, int n)
365 + int t = 0, r;
367 + while (t < n)
369 + /*
370 + * System calls are not a thread cancellation point in Linux
371 + * pthreads. However, the RT signal sent to cancel the thread
372 + * will cause recv() to return with EINTR, and we can manually
373 + * check cancellation.
374 + */
375 + pthread_testcancel();
376 + r = write(f, ((char *)b) + t, n - t);
377 + pthread_testcancel();
379 + if (r < 0
380 + && (errno == EINTR
381 + || errno == EAGAIN))
383 + continue;
386 + if (r < 0)
387 + return r;
389 + t += r;
392 + return t;
397 +static int internal_write_event_play_external(vdr_input_plugin_t *this, uint32_t key);
399 +static void event_handler_external(void *user_data, const xine_event_t *event)
401 + vdr_input_plugin_t *this = (vdr_input_plugin_t *)user_data;
402 + uint32_t key = key_none;
403 +/*
404 + printf("event_handler_external(): event->type: %d\n", event->type);
406 + switch (event->type)
408 + case XINE_EVENT_UI_PLAYBACK_FINISHED:
409 + break;
411 + default:
412 + return;
413 + }
415 + if (0 != internal_write_event_play_external(this, key))
416 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
417 + _("%s: input event write: %s.\n"), LOG_MODULE, strerror(errno));
420 +static void external_stream_stop(vdr_input_plugin_t *this)
422 + if (this->stream_external)
423 + {
424 + xine_stop(this->stream_external);
425 + xine_close(this->stream_external);
427 + if (this->event_queue_external)
429 + xine_event_dispose_queue(this->event_queue_external);
430 + this->event_queue_external = 0;
433 + _x_demux_flush_engine(this->stream_external);
435 + xine_dispose(this->stream_external);
436 + this->stream_external = 0;
440 +static void external_stream_play(vdr_input_plugin_t *this, char *file_name)
442 + external_stream_stop(this);
444 + this->stream_external = xine_stream_new(this->stream->xine, this->stream->audio_out, this->stream->video_out);
446 + this->event_queue_external = xine_event_new_queue(this->stream_external);
448 + xine_event_create_listener_thread(this->event_queue_external, event_handler_external, this);
450 + if (!xine_open(this->stream_external, file_name)
451 + || !xine_play(this->stream_external, 0, 0))
453 + uint32_t key = key_none;
455 + if ( 0 != internal_write_event_play_external(this, key))
456 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
457 + _("%s: input event write: %s.\n"), LOG_MODULE, strerror(errno));
461 +static off_t vdr_read_abort(xine_stream_t *stream, int fd, char *buf, off_t todo)
463 + off_t ret;
465 + while (1)
467 + /*
468 + * System calls are not a thread cancellation point in Linux
469 + * pthreads. However, the RT signal sent to cancel the thread
470 + * will cause recv() to return with EINTR, and we can manually
471 + * check cancellation.
472 + */
473 + pthread_testcancel();
474 + ret = _x_read_abort(stream, fd, buf, todo);
475 + pthread_testcancel();
477 + if (ret < 0
478 + && (errno == EINTR
479 + || errno == EAGAIN))
481 + continue;
484 + break;
487 + return ret;
490 +#define READ_DATA_OR_FAIL(kind, log) \
491 + data_##kind##_t *data = &data_union.kind; \
492 + { \
493 + log; \
494 + n = vdr_read_abort(this->stream, this->fh_control, (char *)data + sizeof (data->header), sizeof (*data) - sizeof (data->header)); \
495 + if (n != sizeof (*data) - sizeof (data->header)) \
496 + return -1; \
498 + this->cur_size -= n; \
499 + }
501 +static double _now()
503 + struct timeval tv;
505 + gettimeofday(&tv, 0);
507 + return (tv.tv_sec * 1000000.0 + tv.tv_usec) / 1000.0;
510 +static void adjust_zoom(vdr_input_plugin_t *this)
512 + pthread_mutex_lock(&this->adjust_zoom_lock);
514 + if (this->image4_3_zoom_x && this->image4_3_zoom_y
515 + && this->image16_9_zoom_x && this->image16_9_zoom_y)
517 + int ratio = (int)(10000 * this->frame_size.r + 0.5);
518 +fprintf(stderr, "ratio: %d\n", ratio);
519 + if (13332 <= ratio && ratio <= 13334)
521 + xine_set_param(this->stream, XINE_PARAM_VO_ZOOM_X, this->image4_3_zoom_x);
522 + xine_set_param(this->stream, XINE_PARAM_VO_ZOOM_Y, this->image4_3_zoom_y);
524 + else /* if (17777 <= ratio && ratio <= 17779) */
526 + xine_set_param(this->stream, XINE_PARAM_VO_ZOOM_X, this->image16_9_zoom_x);
527 + xine_set_param(this->stream, XINE_PARAM_VO_ZOOM_Y, this->image16_9_zoom_y);
531 + pthread_mutex_unlock(&this->adjust_zoom_lock);
534 +static off_t vdr_execute_rpc_command(vdr_input_plugin_t *this)
536 + data_union_t data_union;
537 + off_t n;
539 + n = vdr_read_abort(this->stream, this->fh_control, (char *)&data_union, sizeof (data_union.header));
540 + if (n != sizeof (data_union.header))
541 + return -1;
543 + this->cur_func = data_union.header.func;
544 + this->cur_size = data_union.header.len - sizeof (data_union.header);
545 + this->cur_done = 0;
547 + switch (this->cur_func)
549 + case func_nop:
551 + READ_DATA_OR_FAIL(nop, lprintf("got NOP\n"));
553 + break;
555 + case func_osd_new:
557 + READ_DATA_OR_FAIL(osd_new, LOG_OSD(lprintf("got OSDNEW\n")));
559 + LOG_OSD(lprintf("... (%d,%d)-(%d,%d)@(%d,%d)\n", data->x, data->y, data->width, data->height, data->w_ref, data->h_ref));
561 + fprintf(stderr, "vdr: osdnew %d\n", data->window);
562 +*/
563 + if (data->window >= VDR_MAX_NUM_WINDOWS)
564 + return -1;
566 + if (0 != this->osd[ data->window ].window)
567 + return -1;
569 + this->osd[ data->window ].window = xine_osd_new(this->stream
570 + , data->x
571 + , data->y
572 + , data->width
573 + , data->height);
575 + this->osd[ data->window ].width = data->width;
576 + this->osd[ data->window ].height = data->height;
578 + if (0 == this->osd[ data->window ].window)
579 + return -1;
581 +#ifdef XINE_OSD_CAP_CUSTOM_EXTENT
582 + if (this->osd_supports_custom_extent && data->w_ref > 0 && data->h_ref > 0)
583 + xine_osd_set_extent(this->osd[ data->window ].window, data->w_ref, data->h_ref);
584 +#endif
586 + break;
588 + case func_osd_free:
590 + READ_DATA_OR_FAIL(osd_free, LOG_OSD(lprintf("got OSDFREE\n")));
591 +/*
592 + fprintf(stderr, "vdr: osdfree %d\n", data->window);
593 +*/
594 + if (data->window >= VDR_MAX_NUM_WINDOWS)
595 + return -1;
597 + if (0 != this->osd[ data->window ].window)
598 + xine_osd_free(this->osd[ data->window ].window);
600 + this->osd[ data->window ].window = 0;
602 + free(this->osd[ data->window ].argb_buffer);
603 + this->osd[ data->window ].argb_buffer = 0;
605 + break;
607 + case func_osd_show:
609 + READ_DATA_OR_FAIL(osd_show, LOG_OSD(lprintf("got OSDSHOW\n")));
610 +/*
611 + fprintf(stderr, "vdr: osdshow %d\n", data->window);
612 +*/
613 + if (data->window >= VDR_MAX_NUM_WINDOWS)
614 + return -1;
616 + if (0 != this->osd[ data->window ].window)
618 + if (this->osd_unscaled_blending)
619 + xine_osd_show_unscaled(this->osd[ data->window ].window, 0);
620 + else
621 + xine_osd_show(this->osd[ data->window ].window, 0);
624 + break;
626 + case func_osd_hide:
628 + READ_DATA_OR_FAIL(osd_hide, LOG_OSD(lprintf("got OSDHIDE\n")));
629 +/*
630 + fprintf(stderr, "vdr: osdhide %d\n", data->window);
631 +*/
632 + if (data->window >= VDR_MAX_NUM_WINDOWS)
633 + return -1;
635 + if (0 != this->osd[ data->window ].window)
637 + if (this->osd_unscaled_blending)
638 + xine_osd_show_unscaled(this->osd[ data->window ].window, 0);
639 + else
640 + xine_osd_show(this->osd[ data->window ].window, 0);
643 + break;
645 + case func_osd_flush:
647 + double _t1, _t2;
648 + int _n = 0;
649 + int _to = 0;
650 + int r = 0;
652 + READ_DATA_OR_FAIL(osd_flush, LOG_OSD(lprintf("got OSDFLUSH\n")));
653 +/*
654 + fprintf(stderr, "vdr: osdflush +\n");
656 + _t1 = _now();
658 + while ((r = _x_query_unprocessed_osd_events(this->stream)))
660 + if ((_now() - _t1) > 200)
662 + _to = 1;
663 + break;
665 +/*
666 + fprintf(stderr, "redraw_needed: 1\n");
667 +*/
668 +/* sched_yield(); */
669 + xine_usec_sleep(5000);
670 + _n++;
673 + _t2 = _now();
674 + fprintf(stderr, "vdr: osdflush: n: %d, %.1lf, timeout: %d, result: %d\n", _n, _t2 - _t1, _to, r);
675 +/*
676 + fprintf(stderr, "redraw_needed: 0\n");
678 + fprintf(stderr, "vdr: osdflush -\n");
681 + break;
683 + case func_osd_set_position:
685 + READ_DATA_OR_FAIL(osd_set_position, LOG_OSD(lprintf("got OSDSETPOSITION\n")));
687 + fprintf(stderr, "vdr: osdsetposition %d\n", data->window);
688 +*/
689 + if (data->window >= VDR_MAX_NUM_WINDOWS)
690 + return -1;
692 + if (0 != this->osd[ data->window ].window)
693 + xine_osd_set_position(this->osd[ data->window ].window, data->x, data->y);
695 + break;
697 + case func_osd_draw_bitmap:
699 + READ_DATA_OR_FAIL(osd_draw_bitmap, LOG_OSD(lprintf("got OSDDRAWBITMAP\n")));
701 + fprintf(stderr, "vdr: osddrawbitmap %d\n", data->window);
702 +*/
703 + if (this->osd_buffer_size < this->cur_size)
705 + if (this->osd_buffer)
706 + free(this->osd_buffer);
708 + this->osd_buffer_size = 0;
710 + this->osd_buffer = xine_xmalloc(this->cur_size);
711 + if (!this->osd_buffer)
712 + return -1;
714 + this->osd_buffer_size = this->cur_size;
717 + n = vdr_read_abort (this->stream, this->fh_control, (char *)this->osd_buffer, this->cur_size);
718 + if (n != this->cur_size)
719 + return -1;
721 + this->cur_size -= n;
723 + if (data->window >= VDR_MAX_NUM_WINDOWS)
724 + return -1;
726 + if (0 != this->osd[ data->window ].window)
728 + vdr_osd_t *osd = &this->osd[ data->window ];
730 + if (data->argb)
732 + if (!osd->argb_buffer)
733 + osd->argb_buffer = calloc(4 * osd->width, osd->height);
736 + int src_stride = 4 * data->width;
737 + int dst_stride = 4 * osd->width;
739 + uint8_t *src = this->osd_buffer;
740 + uint8_t *dst = osd->argb_buffer + data->y * dst_stride + data->x * 4;
741 + int y;
743 + if (src_stride == dst_stride)
744 + xine_fast_memcpy(dst, src, src_stride * data->height);
745 + else
747 + for (y = 0; y < data->height; y++)
749 + xine_fast_memcpy(dst, src, src_stride);
750 + dst += dst_stride;
751 + src += src_stride;
756 +#ifdef XINE_OSD_CAP_ARGB_LAYER
757 + xine_osd_set_argb_buffer(osd->window, (uint32_t *)osd->argb_buffer, data->x, data->y, data->width, data->height);
758 +#endif
760 + else
761 + xine_osd_draw_bitmap(osd->window, this->osd_buffer, data->x, data->y, data->width, data->height, 0);
764 + break;
766 + case func_set_color:
768 + uint32_t vdr_color[ 256 ];
770 + READ_DATA_OR_FAIL(set_color, lprintf("got SETCOLOR\n"));
772 + if (((data->num + 1) * sizeof (uint32_t)) != this->cur_size)
773 + return -1;
775 + n = vdr_read_abort (this->stream, this->fh_control, (char *)&vdr_color[ data->index ], this->cur_size);
776 + if (n != this->cur_size)
777 + return -1;
779 + this->cur_size -= n;
781 + if (data->window >= VDR_MAX_NUM_WINDOWS)
782 + return -1;
784 + if (0 != this->osd[ data->window ].window)
786 + uint32_t color[ 256 ];
787 + uint8_t trans[ 256 ];
789 + xine_osd_get_palette(this->osd[ data->window ].window, color, trans);
792 + int i;
794 + for (i = data->index; i <= (data->index + data->num); i++)
796 + int a = (vdr_color[ i ] & 0xff000000) >> 0x18;
797 + int r = (vdr_color[ i ] & 0x00ff0000) >> 0x10;
798 + int g = (vdr_color[ i ] & 0x0000ff00) >> 0x08;
799 + int b = (vdr_color[ i ] & 0x000000ff) >> 0x00;
801 + int y = (( 66 * r + 129 * g + 25 * b + 128) >> 8) + 16;
802 + int cr = ((112 * r - 94 * g - 18 * b + 128) >> 8) + 128;
803 + int cb = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128;
805 + uint8_t *dst = (uint8_t *)&color[ i ];
806 + *dst++ = cb;
807 + *dst++ = cr;
808 + *dst++ = y;
809 + *dst++ = 0;
811 + trans[ i ] = a >> 4;
815 + xine_osd_set_palette(this->osd[ data->window ].window, color, trans);
818 + break;
820 + case func_play_external:
822 + char file_name[ 1024 ];
823 + int file_name_len = 0;
825 + READ_DATA_OR_FAIL(play_external, lprintf("got PLAYEXTERNAL\n"));
827 + file_name_len = this->cur_size;
829 + if (0 != file_name_len)
831 + if (file_name_len <= 1
832 + || file_name_len > sizeof (file_name))
834 + return -1;
837 + n = vdr_read_abort (this->stream, this->fh_control, file_name, file_name_len);
838 + if (n != file_name_len)
839 + return -1;
841 + if (file_name[ file_name_len - 1 ] != '\0')
842 + return -1;
844 + this->cur_size -= n;
847 + lprintf((file_name_len > 0) ? "----------- play external: %s\n" : "---------- stop external\n", file_name);
849 + if (file_name_len > 0)
850 + external_stream_play(this, file_name);
851 + else
852 + external_stream_stop(this);
854 + break;
856 + case func_clear:
858 + READ_DATA_OR_FAIL(clear, lprintf("got CLEAR\n"));
861 + int orig_speed = xine_get_param(this->stream, XINE_PARAM_FINE_SPEED);
862 + if (orig_speed <= 0)
863 + xine_set_param(this->stream, XINE_PARAM_FINE_SPEED, XINE_FINE_SPEED_NORMAL);
864 +fprintf(stderr, "+++ CLEAR(%d%c): sync point: %02x\n", data->n, data->s ? 'b' : 'a', data->i);
865 + if (!data->s)
867 + pthread_mutex_lock(&this->find_sync_point_lock);
868 + this->find_sync_point = data->i;
869 + pthread_mutex_unlock(&this->find_sync_point_lock);
871 +/*
872 + if (!this->dont_change_xine_volume)
873 + xine_set_param(this->stream, XINE_PARAM_AUDIO_VOLUME, 0);
874 +*/
875 + _x_demux_flush_engine(this->stream);
876 +fprintf(stderr, "=== CLEAR(%d.1)\n", data->n);
877 + _x_demux_control_start(this->stream);
878 +fprintf(stderr, "=== CLEAR(%d.2)\n", data->n);
879 + _x_demux_seek(this->stream, 0, 0, 0);
880 +fprintf(stderr, "=== CLEAR(%d.3)\n", data->n);
882 + _x_stream_info_reset(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE);
883 +fprintf(stderr, "=== CLEAR(%d.4)\n", data->n);
884 + _x_meta_info_reset(this->stream, XINE_META_INFO_AUDIOCODEC);
885 +fprintf(stderr, "=== CLEAR(%d.5)\n", data->n);
887 + _x_trigger_relaxed_frame_drop_mode(this->stream);
888 +/* _x_reset_relaxed_frame_drop_mode(this->stream); */
889 +/*
890 + if (!this->dont_change_xine_volume)
891 + xine_set_param(this->stream, XINE_PARAM_AUDIO_VOLUME, this->last_volume);
893 +fprintf(stderr, "--- CLEAR(%d%c)\n", data->n, data->s ? 'b' : 'a');
894 + if (orig_speed <= 0)
895 + xine_set_param(this->stream, XINE_PARAM_FINE_SPEED, orig_speed);
898 + break;
900 + case func_first_frame:
902 + READ_DATA_OR_FAIL(first_frame, lprintf("got FIRST FRAME\n"));
904 + _x_trigger_relaxed_frame_drop_mode(this->stream);
905 +/* _x_reset_relaxed_frame_drop_mode(this->stream); */
907 + break;
909 + case func_still_frame:
911 + READ_DATA_OR_FAIL(still_frame, lprintf("got STILL FRAME\n"));
913 + _x_reset_relaxed_frame_drop_mode(this->stream);
915 + break;
917 + case func_set_video_window:
919 + READ_DATA_OR_FAIL(set_video_window, lprintf("got SET VIDEO WINDOW\n"));
921 + fprintf(stderr, "svw: (%d, %d)x(%d, %d), (%d, %d)\n", data->x, data->y, data->w, data->h, data->wRef, data->hRef);
922 +*/
924 + xine_event_t event;
925 + vdr_set_video_window_data_t event_data;
927 + event_data.x = data->x;
928 + event_data.y = data->y;
929 + event_data.w = data->w;
930 + event_data.h = data->h;
931 + event_data.w_ref = data->w_ref;
932 + event_data.h_ref = data->h_ref;
934 + event.type = XINE_EVENT_VDR_SETVIDEOWINDOW;
935 + event.data = &event_data;
936 + event.data_length = sizeof (event_data);
938 + xine_event_send(this->stream, &event);
941 + break;
943 + case func_select_audio:
945 + READ_DATA_OR_FAIL(select_audio, lprintf("got SELECT AUDIO\n"));
947 + this->audio_channels = data->channels;
950 + xine_event_t event;
951 + vdr_select_audio_data_t event_data;
953 + event_data.channels = this->audio_channels;
955 + event.type = XINE_EVENT_VDR_SELECTAUDIO;
956 + event.data = &event_data;
957 + event.data_length = sizeof (event_data);
959 + xine_event_send(this->stream, &event);
962 + break;
964 + case func_trick_speed_mode:
966 + READ_DATA_OR_FAIL(trick_speed_mode, lprintf("got TRICK SPEED MODE\n"));
968 + if (this->trick_speed_mode != data->on)
970 + this->trick_speed_mode = data->on;
972 + _x_demux_seek(this->stream, 0, 0, 0);
975 + xine_event_t event;
977 + event.type = XINE_EVENT_VDR_TRICKSPEEDMODE;
978 + event.data = 0;
979 + event.data_length = this->trick_speed_mode;
980 +/* fprintf(stderr, "************************: %p, %d\n", event.data, event.data_length); */
981 + xine_event_send(this->stream, &event);
985 + break;
987 + case func_flush:
989 + READ_DATA_OR_FAIL(flush, lprintf("got FLUSH\n"));
991 + if (!data->just_wait)
993 + if (this->stream->video_fifo)
995 + buf_element_t *buf = this->stream->video_fifo->buffer_pool_alloc(this->stream->video_fifo);
996 + if (!buf)
998 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("%s: buffer_pool_alloc() failed!\n"), LOG_MODULE);
999 + return -1;
1002 + buf->type = BUF_CONTROL_FLUSH_DECODER;
1004 + this->stream->video_fifo->put(this->stream->video_fifo, buf);
1009 + double _t1, _t2;
1010 + int _n = 0;
1012 + int vb = -1, ab = -1, vf = -1, af = -1;
1014 + uint8_t timed_out = 0;
1016 + struct timeval now, then;
1018 + if (data->ms_timeout >= 0)
1020 + gettimeofday(&now, 0);
1022 + then = now;
1023 + then.tv_usec += (data->ms_timeout % 1000) * 1000;
1024 + then.tv_sec += (data->ms_timeout / 1000);
1026 + if (then.tv_usec >= 1000000)
1028 + then.tv_usec -= 1000000;
1029 + then.tv_sec += 1;
1032 + else
1034 + then.tv_usec = 0;
1035 + then.tv_sec = 0;
1038 + _t1 = _now();
1040 + while (1)
1042 + _x_query_buffer_usage(this->stream, &vb, &ab, &vf, &af);
1044 + if (vb <= 0 && ab <= 0 && vf <= 0 && af <= 0)
1045 + break;
1047 + if (data->ms_timeout >= 0
1048 + && timercmp(&now, &then, >=))
1050 + timed_out++;
1051 + break;
1054 +/* sched_yield(); */
1055 + xine_usec_sleep(5000);
1056 + _n++;
1058 + if (data->ms_timeout >= 0)
1059 + gettimeofday(&now, 0);
1062 + _t2 = _now();
1063 + fprintf(stderr, "vdr: flush: n: %d, %.1lf\n", _n, _t2 - _t1);
1065 + xprintf(this->stream->xine
1066 + , XINE_VERBOSITY_LOG
1067 + , _("%s: flush buffers (vb: %d, ab: %d, vf: %d, af: %d) %s.\n")
1068 + , LOG_MODULE, vb, ab, vf, af
1069 + , (timed_out ? "timed out" : "done"));
1072 + result_flush_t result_flush;
1073 + result_flush.header.func = data->header.func;
1074 + result_flush.header.len = sizeof (result_flush);
1076 + result_flush.timed_out = timed_out;
1078 + if (sizeof (result_flush) != vdr_write(this->fh_result, &result_flush, sizeof (result_flush)))
1079 + return -1;
1083 + break;
1085 + case func_mute:
1087 + READ_DATA_OR_FAIL(mute, lprintf("got MUTE\n"));
1089 + {
1090 + int param_mute = (this->volume_mode == XINE_VDR_VOLUME_CHANGE_SW) ? XINE_PARAM_AUDIO_AMP_MUTE : XINE_PARAM_AUDIO_MUTE;
1091 + xine_set_param(this->stream, param_mute, data->mute);
1094 + break;
1096 + case func_set_volume:
1098 + READ_DATA_OR_FAIL(set_volume, lprintf("got SETVOLUME\n"));
1101 + int change_volume = (this->volume_mode != XINE_VDR_VOLUME_IGNORE);
1102 + int do_mute = (this->last_volume != 0 && 0 == data->volume);
1103 + int do_unmute = (this->last_volume <= 0 && 0 != data->volume);
1104 + int report_change = 0;
1106 + int param_mute = (this->volume_mode == XINE_VDR_VOLUME_CHANGE_SW) ? XINE_PARAM_AUDIO_AMP_MUTE : XINE_PARAM_AUDIO_MUTE;
1107 + int param_volume = (this->volume_mode == XINE_VDR_VOLUME_CHANGE_SW) ? XINE_PARAM_AUDIO_AMP_LEVEL : XINE_PARAM_AUDIO_VOLUME;
1109 + this->last_volume = data->volume;
1111 + if (do_mute || do_unmute)
1113 + switch (this->mute_mode)
1115 + case XINE_VDR_MUTE_EXECUTE:
1116 + report_change = 1;
1117 + xine_set_param(this->stream, param_mute, do_mute);
1119 + case XINE_VDR_MUTE_IGNORE:
1120 + if (do_mute)
1121 + change_volume = 0;
1122 + break;
1124 + case XINE_VDR_MUTE_SIMULATE:
1125 + change_volume = 1;
1126 + break;
1128 + default:
1129 + return -1;
1130 + };
1133 + if (change_volume)
1135 + report_change = 1;
1136 + xine_set_param(this->stream, param_volume, this->last_volume);
1139 + if (report_change && this->volume_mode != XINE_VDR_VOLUME_CHANGE_SW)
1141 + xine_event_t event;
1142 + xine_audio_level_data_t data;
1144 + data.left
1145 + = data.right
1146 + = xine_get_param(this->stream, param_volume);
1147 + data.mute
1148 + = xine_get_param(this->stream, param_mute);
1150 + event.type = XINE_EVENT_AUDIO_LEVEL;
1151 + event.data = &data;
1152 + event.data_length = sizeof (data);
1154 + xine_event_send(this->stream, &event);
1158 + break;
1160 + case func_set_speed:
1162 + READ_DATA_OR_FAIL(set_speed, lprintf("got SETSPEED\n"));
1164 + lprintf("... got SETSPEED %d\n", data->speed);
1166 + if (data->speed != xine_get_param(this->stream, XINE_PARAM_FINE_SPEED))
1167 + xine_set_param(this->stream, XINE_PARAM_FINE_SPEED, data->speed);
1169 + break;
1171 + case func_set_prebuffer:
1173 + READ_DATA_OR_FAIL(set_prebuffer, lprintf("got SETPREBUFFER\n"));
1175 + xine_set_param(this->stream, XINE_PARAM_METRONOM_PREBUFFER, data->prebuffer);
1177 + break;
1179 + case func_metronom:
1181 + READ_DATA_OR_FAIL(metronom, lprintf("got METRONOM\n"));
1183 + _x_demux_control_newpts(this->stream, data->pts, data->flags);
1185 + break;
1187 + case func_start:
1189 + READ_DATA_OR_FAIL(start, lprintf("got START\n"));
1191 + _x_demux_control_start(this->stream);
1192 + _x_demux_seek(this->stream, 0, 0, 0);
1194 + break;
1196 + case func_wait:
1198 + READ_DATA_OR_FAIL(wait, lprintf("got WAIT\n"));
1201 + result_wait_t result_wait;
1202 + result_wait.header.func = data->header.func;
1203 + result_wait.header.len = sizeof (result_wait);
1205 + if (sizeof (result_wait) != vdr_write(this->fh_result, &result_wait, sizeof (result_wait)))
1206 + return -1;
1208 + if (data->id == 1)
1209 + this->startup_phase = 0;
1212 + break;
1214 + case func_setup:
1216 + READ_DATA_OR_FAIL(setup, lprintf("got SETUP\n"));
1218 + this->osd_unscaled_blending = data->osd_unscaled_blending;
1219 + this->volume_mode = data->volume_mode;
1220 + this->mute_mode = data->mute_mode;
1221 + this->image4_3_zoom_x = data->image4_3_zoom_x;
1222 + this->image4_3_zoom_y = data->image4_3_zoom_y;
1223 + this->image16_9_zoom_x = data->image16_9_zoom_x;
1224 + this->image16_9_zoom_y = data->image16_9_zoom_y;
1226 + adjust_zoom(this);
1228 + break;
1230 + case func_grab_image:
1232 + READ_DATA_OR_FAIL(grab_image, lprintf("got GRABIMAGE\n"));
1235 + off_t ret_val = -1;
1237 + xine_current_frame_data_t frame_data;
1238 + memset(&frame_data, 0, sizeof (frame_data));
1240 + if (xine_get_current_frame_data(this->stream, &frame_data, XINE_FRAME_DATA_ALLOCATE_IMG))
1242 + if (frame_data.ratio_code == XINE_VO_ASPECT_SQUARE)
1243 + frame_data.ratio_code = 10000;
1244 + else if (frame_data.ratio_code == XINE_VO_ASPECT_4_3)
1245 + frame_data.ratio_code = 13333;
1246 + else if (frame_data.ratio_code == XINE_VO_ASPECT_ANAMORPHIC)
1247 + frame_data.ratio_code = 17778;
1248 + else if (frame_data.ratio_code == XINE_VO_ASPECT_DVB)
1249 + frame_data.ratio_code = 21100;
1252 + if (!frame_data.img)
1253 + memset(&frame_data, 0, sizeof (frame_data));
1256 + result_grab_image_t result_grab_image;
1257 + result_grab_image.header.func = data->header.func;
1258 + result_grab_image.header.len = sizeof (result_grab_image) + frame_data.img_size;
1260 + result_grab_image.width = frame_data.width;
1261 + result_grab_image.height = frame_data.height;
1262 + result_grab_image.ratio = frame_data.ratio_code;
1263 + result_grab_image.format = frame_data.format;
1264 + result_grab_image.interlaced = frame_data.interlaced;
1265 + result_grab_image.crop_left = frame_data.crop_left;
1266 + result_grab_image.crop_right = frame_data.crop_right;
1267 + result_grab_image.crop_top = frame_data.crop_top;
1268 + result_grab_image.crop_bottom = frame_data.crop_bottom;
1270 + if (sizeof (result_grab_image) == vdr_write(this->fh_result, &result_grab_image, sizeof (result_grab_image)))
1272 + if (!frame_data.img_size || (frame_data.img_size == vdr_write(this->fh_result, frame_data.img, frame_data.img_size)))
1273 + ret_val = 0;
1277 + free(frame_data.img);
1279 + if (ret_val != 0)
1280 + return ret_val;
1283 + break;
1285 + case func_get_pts:
1287 + READ_DATA_OR_FAIL(get_pts, lprintf("got GETPTS\n"));
1290 + result_get_pts_t result_get_pts;
1291 + result_get_pts.header.func = data->header.func;
1292 + result_get_pts.header.len = sizeof (result_get_pts);
1294 + result_get_pts.pts = (this->last_disc_type == DISC_STREAMSTART) ? -2 : (xine_get_current_vpts(this->stream) - this->stream->metronom->get_option(this->stream->metronom, METRONOM_VPTS_OFFSET));
1295 + if (sizeof (result_get_pts) != vdr_write(this->fh_result, &result_get_pts, sizeof (result_get_pts)))
1296 + return -1;
1299 + break;
1301 + case func_get_version:
1303 + READ_DATA_OR_FAIL(get_version, lprintf("got GETVERSION\n"));
1306 + result_get_version_t result_get_version;
1307 + result_get_version.header.func = data->header.func;
1308 + result_get_version.header.len = sizeof (result_get_version);
1310 + result_get_version.version = XINE_VDR_VERSION;
1312 + if (sizeof (result_get_version) != vdr_write(this->fh_result, &result_get_version, sizeof (result_get_version)))
1313 + return -1;
1316 + break;
1318 + case func_video_size:
1320 + READ_DATA_OR_FAIL(video_size, lprintf("got VIDEO SIZE\n"));
1323 + int format;
1325 + result_video_size_t result_video_size;
1326 + result_video_size.header.func = data->header.func;
1327 + result_video_size.header.len = sizeof (result_video_size);
1329 + result_video_size.top = -1;
1330 + result_video_size.left = -1;
1331 + result_video_size.width = -1;
1332 + result_video_size.height = -1;
1333 + result_video_size.ratio = 0;
1335 + xine_get_current_frame(this->stream, &result_video_size.width, &result_video_size.height, &result_video_size.ratio, &format, 0);
1337 + if (result_video_size.ratio == XINE_VO_ASPECT_SQUARE)
1338 + result_video_size.ratio = 10000;
1339 + else if (result_video_size.ratio == XINE_VO_ASPECT_4_3)
1340 + result_video_size.ratio = 13333;
1341 + else if (result_video_size.ratio == XINE_VO_ASPECT_ANAMORPHIC)
1342 + result_video_size.ratio = 17778;
1343 + else if (result_video_size.ratio == XINE_VO_ASPECT_DVB)
1344 + result_video_size.ratio = 21100;
1346 + if (0 != this->frame_size.x
1347 + || 0 != this->frame_size.y
1348 + || 0 != this->frame_size.w
1349 + || 0 != this->frame_size.h)
1351 + result_video_size.left = this->frame_size.x;
1352 + result_video_size.top = this->frame_size.y;
1353 + result_video_size.width = this->frame_size.w;
1354 + result_video_size.height = this->frame_size.h;
1356 +//fprintf(stderr, "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n");
1357 + result_video_size.zoom_x = xine_get_param(this->stream, XINE_PARAM_VO_ZOOM_X);
1358 + result_video_size.zoom_y = xine_get_param(this->stream, XINE_PARAM_VO_ZOOM_Y);
1359 +//fprintf(stderr, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n");
1360 + if (sizeof (result_video_size) != vdr_write(this->fh_result, &result_video_size, sizeof (result_video_size)))
1361 + return -1;
1362 +//fprintf(stderr, "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\n");
1365 + break;
1367 + case func_reset_audio:
1369 + double _t1, _t2;
1370 + int _n = 0;
1372 + READ_DATA_OR_FAIL(reset_audio, lprintf("got RESET AUDIO\n"));
1374 + if (this->stream->audio_fifo)
1376 + xine_set_param(this->stream, XINE_PARAM_IGNORE_AUDIO, 1);
1377 + xine_set_param(this->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, -2);
1379 + _t1 = _now();
1381 + while (1)
1383 + int n = xine_get_stream_info(this->stream, XINE_STREAM_INFO_MAX_AUDIO_CHANNEL);
1384 + if (n <= 0)
1385 + break;
1387 + /* keep the decoder running */
1388 + if (this->stream->audio_fifo)
1390 + buf_element_t *buf = this->stream->audio_fifo->buffer_pool_alloc(this->stream->audio_fifo);
1391 + if (!buf)
1393 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("%s: buffer_pool_alloc() failed!\n"), LOG_MODULE);
1394 + return -1;
1397 + buf->type = BUF_CONTROL_RESET_TRACK_MAP;
1399 + this->stream->audio_fifo->put(this->stream->audio_fifo, buf);
1402 +/* sched_yield(); */
1403 + xine_usec_sleep(5000);
1404 + _n++;
1407 + _t2 = _now();
1408 + fprintf(stderr, "vdr: reset_audio: n: %d, %.1lf\n", _n, _t2 - _t1);
1410 + xine_set_param(this->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, -1);
1412 + _x_stream_info_reset(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE);
1413 + _x_meta_info_reset(this->stream, XINE_META_INFO_AUDIOCODEC);
1415 + xine_set_param(this->stream, XINE_PARAM_IGNORE_AUDIO, 0);
1418 + break;
1420 + case func_query_capabilities:
1422 + READ_DATA_OR_FAIL(query_capabilities, lprintf("got QUERYCAPABILITIES\n"));
1425 + result_query_capabilities_t result_query_capabilities;
1426 + result_query_capabilities.header.func = data->header.func;
1427 + result_query_capabilities.header.len = sizeof (result_query_capabilities);
1429 + result_query_capabilities.osd_max_num_windows = MAX_SHOWING;
1430 + result_query_capabilities.osd_palette_max_depth = 8;
1431 + result_query_capabilities.osd_palette_is_shared = 0;
1432 + result_query_capabilities.osd_supports_argb_layer = this->osd_supports_argb_layer;
1433 + result_query_capabilities.osd_supports_custom_extent = this->osd_supports_custom_extent;
1435 + if (sizeof (result_query_capabilities) != vdr_write(this->fh_result, &result_query_capabilities, sizeof (result_query_capabilities)))
1436 + return -1;
1439 + break;
1441 + default:
1442 + lprintf("unknown function: %d\n", this->cur_func);
1445 + if (this->cur_size != this->cur_done)
1447 + off_t skip = this->cur_size - this->cur_done;
1449 + lprintf("func: %d, skipping: %lld\n", this->cur_func, skip);
1451 + while (skip > BUF_SIZE)
1453 + n = vdr_read_abort(this->stream, this->fh_control, this->seek_buf, BUF_SIZE);
1454 + if (n != BUF_SIZE)
1455 + return -1;
1457 + skip -= BUF_SIZE;
1460 + n = vdr_read_abort(this->stream, this->fh_control, this->seek_buf, skip);
1461 + if (n != skip)
1462 + return -1;
1464 + this->cur_done = this->cur_size;
1466 + return -1;
1469 + return 0;
1472 +static void *vdr_rpc_thread_loop(void *arg)
1474 + vdr_input_plugin_t *this = (vdr_input_plugin_t *)arg;
1475 + int frontend_lock_failures = 0;
1476 + int failed = 0;
1477 + int was_startup_phase = this->startup_phase;
1479 + while (!failed
1480 + && !this->rpc_thread_shutdown
1481 + && was_startup_phase == this->startup_phase)
1483 + struct timeval timeout;
1484 + fd_set rset;
1486 + FD_ZERO(&rset);
1487 + FD_SET(this->fh_control, &rset);
1489 + timeout.tv_sec = 0;
1490 + timeout.tv_usec = 50000;
1492 + if (select(this->fh_control + 1, &rset, NULL, NULL, &timeout) > 0)
1494 + if (!_x_lock_frontend(this->stream, 100))
1496 + if (++frontend_lock_failures > 50)
1498 + failed = 1;
1499 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
1500 + LOG_MODULE ": locking frontend for rpc command execution failed, exiting ...\n");
1503 + else
1505 + frontend_lock_failures = 0;
1507 + if (_x_lock_port_rewiring(this->stream->xine, 100))
1509 + if (vdr_execute_rpc_command(this) < 0)
1511 + failed = 1;
1512 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
1513 + LOG_MODULE ": execution of rpc command %d (%s) failed, exiting ...\n", this->cur_func, "");
1516 + _x_unlock_port_rewiring(this->stream->xine);
1519 + _x_unlock_frontend(this->stream);
1524 + if (!failed && was_startup_phase)
1525 + return (void *)1;
1527 + /* close control and result channel here to have vdr-xine initiate a disconnect for the above error case ... */
1528 + close(this->fh_control);
1529 + this->fh_control = -1;
1531 + close(this->fh_result);
1532 + this->fh_result = -1;
1534 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
1535 + LOG_MODULE ": rpc thread done.\n");
1537 + pthread_mutex_lock(&this->rpc_thread_shutdown_lock);
1538 + this->rpc_thread_shutdown = -1;
1539 + pthread_cond_broadcast(&this->rpc_thread_shutdown_cond);
1540 + pthread_mutex_unlock(&this->rpc_thread_shutdown_lock);
1542 + return 0;
1545 +static int internal_write_event_key(vdr_input_plugin_t *this, uint32_t key)
1547 + event_key_t event;
1548 + event.header.func = func_key;
1549 + event.header.len = sizeof (event);
1551 + event.key = key;
1553 + if (sizeof (event) != vdr_write(this->fh_event, &event, sizeof (event)))
1554 + return -1;
1556 + return 0;
1559 +static int internal_write_event_frame_size(vdr_input_plugin_t *this)
1561 + event_frame_size_t event;
1562 + event.header.func = func_frame_size;
1563 + event.header.len = sizeof (event);
1565 + event.left = this->frame_size.x;
1566 + event.top = this->frame_size.y;
1567 + event.width = this->frame_size.w,
1568 + event.height = this->frame_size.h;
1569 + event.zoom_x = xine_get_param(this->stream, XINE_PARAM_VO_ZOOM_X);
1570 + event.zoom_y = xine_get_param(this->stream, XINE_PARAM_VO_ZOOM_Y);
1572 + if (sizeof (event) != vdr_write(this->fh_event, &event, sizeof (event)))
1573 + return -1;
1575 + return 0;
1578 +static int internal_write_event_play_external(vdr_input_plugin_t *this, uint32_t key)
1580 + event_play_external_t event;
1581 + event.header.func = func_play_external;
1582 + event.header.len = sizeof (event);
1584 + event.key = key;
1586 + if (sizeof (event) != vdr_write(this->fh_event, &event, sizeof (event)))
1587 + return -1;
1589 + return 0;
1592 +static int internal_write_event_discontinuity(vdr_input_plugin_t *this, int32_t type)
1594 + event_discontinuity_t event;
1595 + event.header.func = func_discontinuity;
1596 + event.header.len = sizeof (event);
1598 + event.type = type;
1600 + if (sizeof (event) != vdr_write(this->fh_event, &event, sizeof (event)))
1601 + return -1;
1603 + return 0;
1606 +static off_t vdr_plugin_read(input_plugin_t *this_gen,
1607 + char *buf_gen, off_t len)
1609 + vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_gen;
1610 + uint8_t *buf = (uint8_t *)buf_gen;
1611 + off_t n, total;
1612 +#ifdef LOG_READ
1613 + lprintf ("reading %lld bytes...\n", len);
1614 +#endif
1615 + total=0;
1616 + if (this->curpos < this->preview_size)
1618 + n = this->preview_size - this->curpos;
1619 + if (n > (len - total))
1620 + n = len - total;
1621 +#ifdef LOG_READ
1622 + lprintf ("%lld bytes from preview (which has %lld bytes)\n",
1623 + n, this->preview_size);
1624 +#endif
1625 + memcpy (&buf[total], &this->preview[this->curpos], n);
1626 + this->curpos += n;
1627 + total += n;
1630 + if( (len-total) > 0 )
1632 + int retries = 0;
1633 + do
1635 + n = vdr_read_abort (this->stream, this->fh, (char *)&buf[total], len-total);
1636 + if (0 == n)
1637 + lprintf("read 0, retries: %d\n", retries);
1639 + while (0 == n
1640 + && !this->stream_external
1641 + && _x_continue_stream_processing(this->stream)
1642 + && 200 > retries++); /* 200 * 50ms */
1643 +#ifdef LOG_READ
1644 + lprintf ("got %lld bytes (%lld/%lld bytes read)\n",
1645 + n,total,len);
1646 +#endif
1647 + if (n < 0)
1649 + _x_message(this->stream, XINE_MSG_READ_ERROR, NULL);
1650 + return 0;
1653 + this->curpos += n;
1654 + total += n;
1657 + if (this->find_sync_point
1658 + && total == 6)
1660 + pthread_mutex_lock(&this->find_sync_point_lock);
1662 + while (this->find_sync_point
1663 + && total == 6
1664 + && buf[0] == 0x00
1665 + && buf[1] == 0x00
1666 + && buf[2] == 0x01)
1668 + int l, sp;
1670 + if (buf[3] == 0xbe
1671 + && buf[4] == 0xff)
1673 +//fprintf(stderr, "------- seen sync point: %02x, waiting for: %02x\n", buf[5], this->find_sync_point);
1674 + if (buf[5] == this->find_sync_point)
1676 + this->find_sync_point = 0;
1677 + break;
1681 + if ((buf[3] & 0xf0) != 0xe0
1682 + && (buf[3] & 0xe0) != 0xc0
1683 + && buf[3] != 0xbd
1684 + && buf[3] != 0xbe)
1686 + break;
1689 + l = buf[4] * 256 + buf[5];
1690 + if (l <= 0)
1691 + break;
1693 + sp = this->find_sync_point;
1694 + this->find_sync_point = 0;
1695 + this_gen->seek(this_gen, l, SEEK_CUR);
1696 + total = this_gen->read(this_gen, buf, 6);
1697 + this->find_sync_point = sp;
1700 + pthread_mutex_unlock(&this->find_sync_point_lock);
1703 + return total;
1706 +static buf_element_t *vdr_plugin_read_block(input_plugin_t *this_gen, fifo_buffer_t *fifo,
1707 + off_t todo)
1709 + off_t total_bytes;
1710 + buf_element_t *buf = fifo->buffer_pool_alloc(fifo);
1712 + buf->content = buf->mem;
1713 + buf->type = BUF_DEMUX_BLOCK;
1715 + total_bytes = vdr_plugin_read(this_gen, (char *)buf->content, todo);
1717 + if (total_bytes != todo)
1719 + buf->free_buffer(buf);
1720 + return NULL;
1723 + buf->size = total_bytes;
1725 + return buf;
1728 +/* forward reference */
1729 +static off_t vdr_plugin_get_current_pos(input_plugin_t *this_gen);
1731 +static off_t vdr_plugin_seek(input_plugin_t *this_gen, off_t offset, int origin)
1733 + vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen;
1735 + lprintf("seek %lld offset, %d origin...\n",
1736 + offset, origin);
1738 + if ((origin == SEEK_CUR) && (offset >= 0))
1740 + for ( ; ((int)offset) - BUF_SIZE > 0; offset -= BUF_SIZE)
1742 + if (!this_gen->read(this_gen, this->seek_buf, BUF_SIZE))
1743 + return this->curpos;
1746 + this_gen->read (this_gen, this->seek_buf, offset);
1749 + if (origin == SEEK_SET)
1751 + if (offset < this->curpos)
1753 + if (this->curpos <= this->preview_size)
1754 + this->curpos = offset;
1755 + else
1756 + lprintf("cannot seek back! (%lld > %lld)\n", this->curpos, offset);
1758 + else
1760 + offset -= this->curpos;
1762 + for ( ; ((int)offset) - BUF_SIZE > 0; offset -= BUF_SIZE)
1764 + if (!this_gen->read(this_gen, this->seek_buf, BUF_SIZE))
1765 + return this->curpos;
1768 + this_gen->read(this_gen, this->seek_buf, offset);
1772 + return this->curpos;
1775 +static off_t vdr_plugin_get_length(input_plugin_t *this_gen)
1777 + return 0;
1780 +static uint32_t vdr_plugin_get_capabilities(input_plugin_t *this_gen)
1782 + return INPUT_CAP_PREVIEW;
1785 +static uint32_t vdr_plugin_get_blocksize(input_plugin_t *this_gen)
1787 + return 0;
1790 +static off_t vdr_plugin_get_current_pos(input_plugin_t *this_gen)
1792 + vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen;
1794 + return this->curpos;
1797 +static const char *vdr_plugin_get_mrl(input_plugin_t *this_gen)
1799 + vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen;
1801 + return this->mrl;
1804 +static void vdr_plugin_dispose(input_plugin_t *this_gen)
1806 + vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen;
1807 + int i;
1809 + external_stream_stop(this);
1811 + if (this->event_queue)
1812 + xine_event_dispose_queue(this->event_queue);
1814 + if (this->rpc_thread)
1816 + struct timespec abstime;
1817 + int ms_to_time_out = 10000;
1819 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("%s: shutting down rpc thread (timeout: %d ms) ...\n"), LOG_MODULE, ms_to_time_out);
1821 + pthread_mutex_lock(&this->rpc_thread_shutdown_lock);
1823 + if (this->rpc_thread_shutdown > -1)
1825 + this->rpc_thread_shutdown = 1;
1828 + struct timeval now;
1829 + gettimeofday(&now, 0);
1831 + abstime.tv_sec = now.tv_sec + ms_to_time_out / 1000;
1832 + abstime.tv_nsec = now.tv_usec * 1000 + (ms_to_time_out % 1000) * 1e6;
1834 + if (abstime.tv_nsec > 1e9)
1836 + abstime.tv_nsec -= 1e9;
1837 + abstime.tv_sec++;
1841 + if (0 != pthread_cond_timedwait(&this->rpc_thread_shutdown_cond, &this->rpc_thread_shutdown_lock, &abstime))
1843 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("%s: cancelling rpc thread in function %d...\n"), LOG_MODULE, this->cur_func);
1844 + pthread_cancel(this->rpc_thread);
1848 + pthread_mutex_unlock(&this->rpc_thread_shutdown_lock);
1850 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("%s: joining rpc thread ...\n"), LOG_MODULE);
1851 + pthread_join(this->rpc_thread, 0);
1852 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("%s: rpc thread joined.\n"), LOG_MODULE);
1855 + pthread_cond_destroy(&this->rpc_thread_shutdown_cond);
1856 + pthread_mutex_destroy(&this->rpc_thread_shutdown_lock);
1858 + pthread_mutex_destroy(&this->find_sync_point_lock);
1859 + pthread_mutex_destroy(&this->adjust_zoom_lock);
1861 + if (this->fh_result != -1)
1862 + close(this->fh_result);
1864 + if (this->fh_control != -1)
1865 + close(this->fh_control);
1867 + if (this->fh_event != -1)
1868 + close(this->fh_event);
1870 + for (i = 0; i < VDR_MAX_NUM_WINDOWS; i++)
1872 + if (0 == this->osd[ i ].window)
1873 + continue;
1875 + xine_osd_hide(this->osd[ i ].window, 0);
1876 + xine_osd_free(this->osd[ i ].window);
1878 + free(this->osd[ i ].argb_buffer);
1881 + if (this->osd_buffer)
1882 + free(this->osd_buffer);
1884 + if ((this->fh != STDIN_FILENO) && (this->fh != -1))
1885 + close(this->fh);
1887 + free(this->mrl);
1889 + this->stream->metronom = this->metronom.stream_metronom;
1890 + this->metronom.stream_metronom = 0;
1892 + free(this);
1895 +static int vdr_plugin_get_optional_data(input_plugin_t *this_gen,
1896 + void *data, int data_type)
1898 + vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen;
1899 + (void)this;
1900 + switch (data_type)
1902 + case INPUT_OPTIONAL_DATA_PREVIEW:
1903 + /* just fake what mpeg_pes demuxer expects */
1904 + memcpy (data, "\x00\x00\x01\xe0\x00\x03\x80\x00\x00", 9);
1905 + return 9;
1907 + return INPUT_OPTIONAL_UNSUPPORTED;
1910 +static inline const char *mrl_to_fifo (const char *mrl)
1912 + /* vdr://foo -> /foo */
1913 + return mrl + 3 + strspn (mrl + 4, "/");
1916 +static inline const char *mrl_to_host (const char *mrl)
1918 + /* netvdr://host:port -> host:port */
1919 + return strrchr (mrl, '/') + 1;
1922 +static int vdr_plugin_open_fifo_mrl(input_plugin_t *this_gen)
1924 + vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen;
1925 + char *filename = (char *)mrl_to_fifo (this->mrl);
1927 + if(!strcmp(filename, "/")) {
1928 + filename = (char *)VDR_ABS_FIFO_DIR "/stream";
1931 + filename = strdup(filename);
1933 + _x_mrl_unescape (filename);
1934 + this->fh = open(filename, O_RDONLY | O_NONBLOCK);
1936 + lprintf("filename '%s'\n", filename);
1938 + if (this->fh == -1)
1940 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
1941 + _("%s: failed to open '%s' (%s)\n"), LOG_MODULE,
1942 + filename,
1943 + strerror(errno));
1944 + free (filename);
1945 + return 0;
1949 + struct pollfd poll_fh = { this->fh, POLLIN, 0 };
1951 + int r = poll(&poll_fh, 1, 300);
1952 + if (1 != r)
1954 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
1955 + _("%s: failed to open '%s' (%s)\n"), LOG_MODULE,
1956 + filename,
1957 + _("timeout expired during setup phase"));
1958 + free (filename);
1959 + return 0;
1963 + fcntl(this->fh, F_SETFL, ~O_NONBLOCK & fcntl(this->fh, F_GETFL, 0));
1965 + /* eat initial handshake byte */
1967 + char b;
1968 + read(this->fh, &b, 1);
1972 + char *filename_control = 0;
1973 + asprintf(&filename_control, "%s.control", filename);
1975 + this->fh_control = open(filename_control, O_RDONLY);
1977 + if (this->fh_control == -1) {
1978 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
1979 + _("%s: failed to open '%s' (%s)\n"), LOG_MODULE,
1980 + filename_control,
1981 + strerror(errno));
1983 + free(filename_control);
1984 + free (filename);
1985 + return 0;
1988 + free(filename_control);
1992 + char *filename_result = 0;
1993 + asprintf(&filename_result, "%s.result", filename);
1995 + this->fh_result = open(filename_result, O_WRONLY);
1997 + if (this->fh_result == -1) {
1998 + perror("failed");
2000 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
2001 + _("%s: failed to open '%s' (%s)\n"), LOG_MODULE,
2002 + filename_result,
2003 + strerror(errno));
2005 + free(filename_result);
2006 + free (filename);
2007 + return 0;
2010 + free(filename_result);
2014 + char *filename_event = 0;
2015 + asprintf(&filename_event, "%s.event", filename);
2017 + this->fh_event = open(filename_event, O_WRONLY);
2019 + if (this->fh_event == -1) {
2020 + perror("failed");
2022 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
2023 + _("%s: failed to open '%s' (%s)\n"), LOG_MODULE,
2024 + filename_event,
2025 + strerror(errno));
2027 + free(filename_event);
2028 + free (filename);
2029 + return 0;
2032 + free(filename_event);
2035 + free (filename);
2036 + return 1;
2039 +static int vdr_plugin_open_socket(vdr_input_plugin_t *this, struct hostent *host, unsigned short port)
2041 + int fd;
2042 + struct sockaddr_in sain;
2043 + struct in_addr iaddr;
2045 + if ((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
2047 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
2048 + _("%s: failed to create socket for port %d (%s)\n"), LOG_MODULE,
2049 + port, strerror(errno));
2050 + return -1;
2053 + iaddr.s_addr = *((unsigned int *)host->h_addr_list[0]);
2055 + sain.sin_port = htons(port);
2056 + sain.sin_family = AF_INET;
2057 + sain.sin_addr = iaddr;
2059 + if (connect(fd, (struct sockaddr *)&sain, sizeof (sain)) < 0)
2061 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
2062 + _("%s: failed to connect to port %d (%s)\n"), LOG_MODULE, port,
2063 + strerror(errno));
2065 + return -1;
2068 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
2069 + _("%s: socket opening (port %d) successful, fd = %d\n"), LOG_MODULE, port, fd);
2071 + return fd;
2074 +static int vdr_plugin_open_sockets(vdr_input_plugin_t *this)
2076 + struct hostent *host;
2077 + char *mrl_host = strdup (mrl_to_host (this->mrl));
2078 + char *mrl_port;
2079 + int port = 18701;
2081 + mrl_port = strchr(mrl_host, '#');
2082 + if (mrl_port)
2083 + *mrl_port = 0; /* strip off things like '#demux:mpeg_pes' */
2085 + _x_mrl_unescape (mrl_host);
2087 + mrl_port = strchr(mrl_host, ':');
2088 + if (mrl_port)
2090 + port = atoi(mrl_port + 1);
2091 + *mrl_port = 0;
2094 + host = gethostbyname(mrl_host);
2096 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
2097 + _("%s: connecting to vdr.\n"), LOG_MODULE);
2099 + if (!host)
2101 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
2102 + _("%s: failed to resolve hostname '%s' (%s)\n"), LOG_MODULE,
2103 + mrl_host,
2104 + strerror(errno));
2105 + free (mrl_host);
2106 + return 0;
2108 + free (mrl_host);
2110 + if ((this->fh = vdr_plugin_open_socket(this, host, port + 0)) == -1)
2111 + return 0;
2113 + fcntl(this->fh, F_SETFL, ~O_NONBLOCK & fcntl(this->fh, F_GETFL, 0));
2115 + if ((this->fh_control = vdr_plugin_open_socket(this, host, port + 1)) == -1)
2116 + return 0;
2118 + if ((this->fh_result = vdr_plugin_open_socket(this, host, port + 2)) == -1)
2119 + return 0;
2121 + if ((this->fh_event = vdr_plugin_open_socket(this, host, port + 3)) == -1)
2122 + return 0;
2124 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
2125 + _("%s: connecting to all sockets (port %d .. %d) was successful.\n"), LOG_MODULE, port, port + 3);
2127 + return 1;
2130 +static int vdr_plugin_open_socket_mrl(input_plugin_t *this_gen)
2132 + vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen;
2134 + lprintf("input_vdr: connecting to vdr-xine-server...\n");
2136 + if (!vdr_plugin_open_sockets(this))
2137 + return 0;
2139 + return 1;
2142 +static int vdr_plugin_open(input_plugin_t *this_gen)
2144 + vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen;
2146 + lprintf("trying to open '%s'...\n", this->mrl);
2148 + if (this->fh == -1)
2150 + int err = 0;
2152 + if (!strncasecmp(&this->mrl[0], "vdr:/", 5))
2154 + if (!vdr_plugin_open_fifo_mrl(this_gen))
2155 + return 0;
2157 + else if (!strncasecmp(&this->mrl[0], "netvdr:/", 8))
2159 + if (!vdr_plugin_open_socket_mrl(this_gen))
2160 + return 0;
2162 + else
2164 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
2165 + _("%s: MRL (%s) invalid! MRL should start with vdr://path/to/fifo/stream or netvdr://host:port where ':port' is optional.\n"), LOG_MODULE,
2166 + strerror(err));
2167 + return 0;
2170 + this->rpc_thread_shutdown = 0;
2172 + /* let this thread handle rpc commands in startup phase */
2173 + this->startup_phase = 1;
2174 + if (0 == vdr_rpc_thread_loop(this))
2175 + return 0;
2177 + if ((err = pthread_create(&this->rpc_thread, NULL,
2178 + vdr_rpc_thread_loop, (void *)this)) != 0)
2180 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
2181 + _("%s: can't create new thread (%s)\n"), LOG_MODULE,
2182 + strerror(err));
2184 + return 0;
2188 + /*
2189 + * mrl accepted and opened successfully at this point
2191 + * => create plugin instance
2192 + */
2194 + this->preview = NULL;
2195 + this->preview_size = 0;
2196 + this->curpos = 0;
2198 + return 1;
2201 +static void event_handler(void *user_data, const xine_event_t *event)
2203 + vdr_input_plugin_t *this = (vdr_input_plugin_t *)user_data;
2204 + uint32_t key = key_none;
2206 + lprintf("eventHandler(): event->type: %d\n", event->type);
2208 + if (XINE_EVENT_VDR_FRAMESIZECHANGED == event->type)
2210 + memcpy(&this->frame_size, event->data, event->data_length);
2212 + if (0 != internal_write_event_frame_size(this))
2213 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
2214 + _("%s: input event write: %s.\n"), LOG_MODULE, strerror(errno));
2216 + adjust_zoom(this);
2217 + return;
2220 + if (XINE_EVENT_VDR_DISCONTINUITY == event->type)
2222 + if (0 != internal_write_event_discontinuity(this, event->data_length))
2223 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
2224 + _("%s: input event write: %s.\n"), LOG_MODULE, strerror(errno));
2226 + return;
2229 + if (XINE_EVENT_VDR_PLUGINSTARTED == event->type)
2231 + if (0 == event->data_length) /* vdr_video */
2233 + xine_event_t event;
2235 + event.type = XINE_EVENT_VDR_TRICKSPEEDMODE;
2236 + event.data = 0;
2237 + event.data_length = this->trick_speed_mode;
2239 + xine_event_send(this->stream, &event);
2241 + else if (1 == event->data_length) /* vdr_audio */
2243 + xine_event_t event;
2244 + vdr_select_audio_data_t event_data;
2246 + event_data.channels = this->audio_channels;
2248 + event.type = XINE_EVENT_VDR_SELECTAUDIO;
2249 + event.data = &event_data;
2250 + event.data_length = sizeof (event_data);
2252 + xine_event_send(this->stream, &event);
2254 + else
2256 + fprintf(stderr, "input_vdr: illegal XINE_EVENT_VDR_PLUGINSTARTED: %d\n", event->data_length);
2259 + return;
2262 + switch (event->type)
2264 + case XINE_EVENT_INPUT_UP: key = key_up; break;
2265 + case XINE_EVENT_INPUT_DOWN: key = key_down; break;
2266 + case XINE_EVENT_INPUT_LEFT: key = key_left; break;
2267 + case XINE_EVENT_INPUT_RIGHT: key = key_right; break;
2268 + case XINE_EVENT_INPUT_SELECT: key = key_ok; break;
2269 + case XINE_EVENT_VDR_BACK: key = key_back; break;
2270 + case XINE_EVENT_VDR_CHANNELPLUS: key = key_channel_plus; break;
2271 + case XINE_EVENT_VDR_CHANNELMINUS: key = key_channel_minus; break;
2272 + case XINE_EVENT_VDR_RED: key = key_red; break;
2273 + case XINE_EVENT_VDR_GREEN: key = key_green; break;
2274 + case XINE_EVENT_VDR_YELLOW: key = key_yellow; break;
2275 + case XINE_EVENT_VDR_BLUE: key = key_blue; break;
2276 + case XINE_EVENT_VDR_PLAY: key = key_play; break;
2277 + case XINE_EVENT_VDR_PAUSE: key = key_pause; break;
2278 + case XINE_EVENT_VDR_STOP: key = key_stop; break;
2279 + case XINE_EVENT_VDR_RECORD: key = key_record; break;
2280 + case XINE_EVENT_VDR_FASTFWD: key = key_fast_fwd; break;
2281 + case XINE_EVENT_VDR_FASTREW: key = key_fast_rew; break;
2282 + case XINE_EVENT_VDR_POWER: key = key_power; break;
2283 + case XINE_EVENT_VDR_SCHEDULE: key = key_schedule; break;
2284 + case XINE_EVENT_VDR_CHANNELS: key = key_channels; break;
2285 + case XINE_EVENT_VDR_TIMERS: key = key_timers; break;
2286 + case XINE_EVENT_VDR_RECORDINGS: key = key_recordings; break;
2287 + case XINE_EVENT_INPUT_MENU1: key = key_menu; break;
2288 + case XINE_EVENT_VDR_SETUP: key = key_setup; break;
2289 + case XINE_EVENT_VDR_COMMANDS: key = key_commands; break;
2290 + case XINE_EVENT_INPUT_NUMBER_0: key = key_0; break;
2291 + case XINE_EVENT_INPUT_NUMBER_1: key = key_1; break;
2292 + case XINE_EVENT_INPUT_NUMBER_2: key = key_2; break;
2293 + case XINE_EVENT_INPUT_NUMBER_3: key = key_3; break;
2294 + case XINE_EVENT_INPUT_NUMBER_4: key = key_4; break;
2295 + case XINE_EVENT_INPUT_NUMBER_5: key = key_5; break;
2296 + case XINE_EVENT_INPUT_NUMBER_6: key = key_6; break;
2297 + case XINE_EVENT_INPUT_NUMBER_7: key = key_7; break;
2298 + case XINE_EVENT_INPUT_NUMBER_8: key = key_8; break;
2299 + case XINE_EVENT_INPUT_NUMBER_9: key = key_9; break;
2300 + case XINE_EVENT_VDR_USER1: key = key_user1; break;
2301 + case XINE_EVENT_VDR_USER2: key = key_user2; break;
2302 + case XINE_EVENT_VDR_USER3: key = key_user3; break;
2303 + case XINE_EVENT_VDR_USER4: key = key_user4; break;
2304 + case XINE_EVENT_VDR_USER5: key = key_user5; break;
2305 + case XINE_EVENT_VDR_USER6: key = key_user6; break;
2306 + case XINE_EVENT_VDR_USER7: key = key_user7; break;
2307 + case XINE_EVENT_VDR_USER8: key = key_user8; break;
2308 + case XINE_EVENT_VDR_USER9: key = key_user9; break;
2309 + case XINE_EVENT_VDR_VOLPLUS: key = key_volume_plus; break;
2310 + case XINE_EVENT_VDR_VOLMINUS: key = key_volume_minus; break;
2311 + case XINE_EVENT_VDR_MUTE: key = key_mute; break;
2312 + case XINE_EVENT_VDR_AUDIO: key = key_audio; break;
2313 + case XINE_EVENT_VDR_INFO: key = key_info; break;
2314 + case XINE_EVENT_VDR_CHANNELPREVIOUS: key = key_channel_previous; break;
2315 + case XINE_EVENT_INPUT_NEXT: key = key_next; break;
2316 + case XINE_EVENT_INPUT_PREVIOUS: key = key_previous; break;
2317 + case XINE_EVENT_VDR_SUBTITLES: key = key_subtitles; break;
2318 + default:
2319 + return;
2322 + if (0 != internal_write_event_key(this, key))
2323 + xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
2324 + _("%s: input event write: %s.\n"), LOG_MODULE, strerror(errno));
2328 +static void vdr_metronom_set_audio_rate(metronom_t *self, int64_t pts_per_smpls)
2330 + vdr_metronom_t *this = (vdr_metronom_t *)self;
2331 + this->stream_metronom->set_audio_rate(this->stream_metronom, pts_per_smpls);
2334 +static void vdr_metronom_got_video_frame(metronom_t *self, vo_frame_t *frame)
2336 + vdr_metronom_t *this = (vdr_metronom_t *)self;
2337 + this->stream_metronom->got_video_frame(this->stream_metronom, frame);
2340 +static int64_t vdr_metronom_got_audio_samples(metronom_t *self, int64_t pts, int nsamples)
2342 + vdr_metronom_t *this = (vdr_metronom_t *)self;
2343 + return this->stream_metronom->got_audio_samples(this->stream_metronom, pts, nsamples);
2346 +static int64_t vdr_metronom_got_spu_packet(metronom_t *self, int64_t pts)
2348 + vdr_metronom_t *this = (vdr_metronom_t *)self;
2349 + return this->stream_metronom->got_spu_packet(this->stream_metronom, pts);
2352 +static void vdr_handle_discontinuity(vdr_input_plugin_t *this, int type)
2354 + this->last_disc_type = type;
2357 + xine_event_t event;
2359 + event.type = XINE_EVENT_VDR_DISCONTINUITY;
2360 + event.data = 0;
2361 + event.data_length = type;
2363 + xine_event_send(this->stream, &event);
2367 +static void vdr_metronom_handle_audio_discontinuity(metronom_t *self, int type, int64_t disc_off)
2369 + vdr_metronom_t *this = (vdr_metronom_t *)self;
2370 + this->stream_metronom->handle_audio_discontinuity(this->stream_metronom, type, disc_off);
2371 + vdr_handle_discontinuity(this->input, type);
2374 +static void vdr_metronom_handle_video_discontinuity(metronom_t *self, int type, int64_t disc_off)
2376 + vdr_metronom_t *this = (vdr_metronom_t *)self;
2377 + this->stream_metronom->handle_video_discontinuity(this->stream_metronom, type, disc_off);
2378 + vdr_handle_discontinuity(this->input, type);
2381 +static void vdr_metronom_set_option(metronom_t *self, int option, int64_t value)
2383 + vdr_metronom_t *this = (vdr_metronom_t *)self;
2384 + this->stream_metronom->set_option(this->stream_metronom, option, value);
2387 +static int64_t vdr_metronom_get_option(metronom_t *self, int option)
2389 + vdr_metronom_t *this = (vdr_metronom_t *)self;
2390 + return this->stream_metronom->get_option(this->stream_metronom, option);
2393 +static void vdr_metronom_set_master(metronom_t *self, metronom_t *master)
2395 + vdr_metronom_t *this = (vdr_metronom_t *)self;
2396 + this->stream_metronom->set_master(this->stream_metronom, master);
2399 +static void vdr_metronom_exit(metronom_t *self)
2401 + _x_abort();
2405 +static input_plugin_t *vdr_class_get_instance(input_class_t *cls_gen, xine_stream_t *stream,
2406 + const char *data)
2408 + vdr_input_plugin_t *this;
2409 + char *mrl = strdup(data);
2411 + if (!strncasecmp(mrl, "vdr:/", 5))
2412 + lprintf("filename '%s'\n", mrl_to_path (mrl));
2413 + else if (!strncasecmp(mrl, "netvdr:/", 5))
2414 + lprintf("host '%s'\n", mrl_to_socket (mrl));
2415 + else
2417 + free(mrl);
2418 + return NULL;
2421 + /*
2422 + * mrl accepted and opened successfully at this point
2424 + * => create plugin instance
2425 + */
2427 + this = (vdr_input_plugin_t *)xine_xmalloc(sizeof (vdr_input_plugin_t));
2429 + this->stream = stream;
2430 + this->curpos = 0;
2431 + this->mrl = mrl;
2432 + this->fh = -1;
2433 + this->fh_control = -1;
2434 + this->fh_result = -1;
2435 + this->fh_event = -1;
2437 + this->input_plugin.open = vdr_plugin_open;
2438 + this->input_plugin.get_capabilities = vdr_plugin_get_capabilities;
2439 + this->input_plugin.read = vdr_plugin_read;
2440 + this->input_plugin.read_block = vdr_plugin_read_block;
2441 + this->input_plugin.seek = vdr_plugin_seek;
2442 + this->input_plugin.get_current_pos = vdr_plugin_get_current_pos;
2443 + this->input_plugin.get_length = vdr_plugin_get_length;
2444 + this->input_plugin.get_blocksize = vdr_plugin_get_blocksize;
2445 + this->input_plugin.get_mrl = vdr_plugin_get_mrl;
2446 + this->input_plugin.dispose = vdr_plugin_dispose;
2447 + this->input_plugin.get_optional_data = vdr_plugin_get_optional_data;
2448 + this->input_plugin.input_class = cls_gen;
2450 + this->cur_func = func_unknown;
2451 + this->cur_size = 0;
2452 + this->cur_done = 0;
2454 + memset(this->osd, 0, sizeof (this->osd));
2457 + xine_osd_t *osd = xine_osd_new(this->stream, 0, 0, 16, 16);
2458 + uint32_t caps = xine_osd_get_capabilities(osd);
2459 + xine_osd_free(osd);
2461 +#ifdef XINE_OSD_CAP_ARGB_LAYER
2462 + this->osd_supports_argb_layer = !!(caps & XINE_OSD_CAP_ARGB_LAYER);
2463 +#endif
2464 +#ifdef XINE_OSD_CAP_CUSTOM_EXTENT
2465 + this->osd_supports_custom_extent = !!(caps & XINE_OSD_CAP_CUSTOM_EXTENT);
2466 +#endif
2469 + this->osd_buffer = 0;
2470 + this->osd_buffer_size = 0;
2471 + this->osd_unscaled_blending = 0;
2472 + this->trick_speed_mode = 0;
2473 + this->audio_channels = 0;
2474 + this->mute_mode = XINE_VDR_MUTE_SIMULATE;
2475 + this->volume_mode = XINE_VDR_VOLUME_CHANGE_HW;
2476 + this->last_volume = -1;
2477 + this->frame_size.x = 0;
2478 + this->frame_size.y = 0;
2479 + this->frame_size.w = 0;
2480 + this->frame_size.h = 0;
2481 + this->frame_size.r = 0;
2483 + this->stream_external = 0;
2484 + this->event_queue_external = 0;
2486 + pthread_mutex_init(&this->rpc_thread_shutdown_lock, 0);
2487 + pthread_cond_init(&this->rpc_thread_shutdown_cond, 0);
2489 + pthread_mutex_init(&this->find_sync_point_lock, 0);
2490 + pthread_mutex_init(&this->adjust_zoom_lock, 0);
2491 + this->image4_3_zoom_x = 0;
2492 + this->image4_3_zoom_y = 0;
2493 + this->image16_9_zoom_x = 0;
2494 + this->image16_9_zoom_y = 0;
2496 + this->event_queue = xine_event_new_queue(this->stream);
2497 + if (this->event_queue)
2498 + xine_event_create_listener_thread(this->event_queue, event_handler, this);
2500 + this->metronom.input = this;
2501 + this->metronom.metronom.set_audio_rate = vdr_metronom_set_audio_rate;
2502 + this->metronom.metronom.got_video_frame = vdr_metronom_got_video_frame;
2503 + this->metronom.metronom.got_audio_samples = vdr_metronom_got_audio_samples;
2504 + this->metronom.metronom.got_spu_packet = vdr_metronom_got_spu_packet;
2505 + this->metronom.metronom.handle_audio_discontinuity = vdr_metronom_handle_audio_discontinuity;
2506 + this->metronom.metronom.handle_video_discontinuity = vdr_metronom_handle_video_discontinuity;
2507 + this->metronom.metronom.set_option = vdr_metronom_set_option;
2508 + this->metronom.metronom.get_option = vdr_metronom_get_option;
2509 + this->metronom.metronom.set_master = vdr_metronom_set_master;
2510 + this->metronom.metronom.exit = vdr_metronom_exit;
2512 + this->metronom.stream_metronom = stream->metronom;
2513 + stream->metronom = &this->metronom.metronom;
2515 + return &this->input_plugin;
2519 + * vdr input plugin class stuff
2520 + */
2522 +static const char *vdr_class_get_description(input_class_t *this_gen)
2524 + return _("VDR display device plugin");
2527 +static const char *vdr_class_get_identifier (input_class_t *this_gen)
2529 + return "VDR";
2532 +static void vdr_class_dispose (input_class_t *this_gen)
2534 + vdr_input_class_t *this = (vdr_input_class_t *)this_gen;
2536 + free(this);
2539 +static char **vdr_class_get_autoplay_list(input_class_t *this_gen,
2540 + int *num_files)
2542 + vdr_input_class_t *class = (vdr_input_class_t *)this_gen;
2544 + *num_files = 1;
2545 + return (char **)class->mrls;
2548 +void *vdr_input_init_plugin(xine_t *xine, void *data)
2550 + vdr_input_class_t *this;
2552 + lprintf("init_class\n");
2554 + this = (vdr_input_class_t *)xine_xmalloc(sizeof (vdr_input_class_t));
2556 + this->xine = xine;
2558 + this->mrls[ 0 ] = "vdr:/" VDR_ABS_FIFO_DIR "/stream#demux:mpeg_pes";
2559 + this->mrls[ 1 ] = 0;
2561 + this->input_class.get_instance = vdr_class_get_instance;
2562 + this->input_class.get_identifier = vdr_class_get_identifier;
2563 + this->input_class.get_description = vdr_class_get_description;
2564 + this->input_class.get_dir = NULL;
2565 + this->input_class.get_autoplay_list = vdr_class_get_autoplay_list;
2566 + this->input_class.dispose = vdr_class_dispose;
2567 + this->input_class.eject_media = NULL;
2569 + return this;
2571 diff --git a/src/vdr/post_vdr_audio.c b/src/vdr/post_vdr_audio.c
2572 new file mode 100644
2573 --- /dev/null
2574 +++ b/src/vdr/post_vdr_audio.c
2575 @@ -0,0 +1,285 @@
2577 + * Copyright (C) 2000-2004 the xine project
2578 + *
2579 + * This file is part of xine, a free video player.
2580 + *
2581 + * xine is free software; you can redistribute it and/or modify
2582 + * it under the terms of the GNU General Public License as published by
2583 + * the Free Software Foundation; either version 2 of the License, or
2584 + * (at your option) any later version.
2585 + *
2586 + * xine is distributed in the hope that it will be useful,
2587 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2588 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2589 + * GNU General Public License for more details.
2590 + *
2591 + * You should have received a copy of the GNU General Public License
2592 + * along with this program; if not, write to the Free Software
2593 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
2594 + */
2597 + * select audio channel plugin for VDR
2598 + */
2600 +#define LOG_MODULE "vdr_audio"
2601 +#define LOG_VERBOSE
2603 +#define LOG
2606 +#include "xine_internal.h"
2607 +#include "post.h"
2608 +#include "combined_vdr.h"
2612 +typedef struct vdr_audio_post_plugin_s
2614 + post_plugin_t post_plugin;
2616 + xine_event_queue_t *event_queue;
2617 + xine_stream_t *vdr_stream;
2619 + uint8_t audio_channels;
2620 + int num_channels;
2623 +vdr_audio_post_plugin_t;
2626 +static void vdr_audio_select_audio(vdr_audio_post_plugin_t *this, uint8_t channels)
2628 + this->audio_channels = channels;
2632 +/* plugin class functions */
2633 +static post_plugin_t *vdr_audio_open_plugin(post_class_t *class_gen, int inputs,
2634 + xine_audio_port_t **audio_target,
2635 + xine_video_port_t **video_target);
2636 +static char *vdr_audio_get_identifier(post_class_t *class_gen);
2637 +static char *vdr_audio_get_description(post_class_t *class_gen);
2638 +static void vdr_audio_class_dispose(post_class_t *class_gen);
2640 +/* plugin instance functions */
2641 +static void vdr_audio_dispose(post_plugin_t *this_gen);
2643 +/* replaced ao_port functions */
2644 +static int vdr_audio_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream,
2645 + uint32_t bits, uint32_t rate, int mode);
2646 +static void vdr_audio_port_put_buffer(xine_audio_port_t *port_gen, audio_buffer_t *buf, xine_stream_t *stream);
2650 +void *vdr_audio_init_plugin(xine_t *xine, void *data)
2652 + post_class_t *class = (post_class_t *)xine_xmalloc(sizeof (post_class_t));
2654 + if (!class)
2655 + return NULL;
2657 + class->open_plugin = vdr_audio_open_plugin;
2658 + class->get_identifier = vdr_audio_get_identifier;
2659 + class->get_description = vdr_audio_get_description;
2660 + class->dispose = vdr_audio_class_dispose;
2662 + return class;
2665 +static post_plugin_t *vdr_audio_open_plugin(post_class_t *class_gen, int inputs,
2666 + xine_audio_port_t **audio_target,
2667 + xine_video_port_t **video_target)
2669 + vdr_audio_post_plugin_t *this = (vdr_audio_post_plugin_t *)xine_xmalloc(sizeof (vdr_audio_post_plugin_t));
2670 + post_in_t *input;
2671 + post_out_t *output;
2672 + post_audio_port_t *port;
2673 +/*
2674 +fprintf(stderr, "~~~~~~~~~~ vdr open plugin\n");
2676 + if (!this || !audio_target || !audio_target[ 0 ])
2678 + free(this);
2679 + return NULL;
2682 + _x_post_init(&this->post_plugin, 1, 0);
2683 + this->post_plugin.dispose = vdr_audio_dispose;
2685 + port = _x_post_intercept_audio_port(&this->post_plugin, audio_target[ 0 ], &input, &output);
2686 + port->new_port.open = vdr_audio_port_open;
2687 + port->new_port.put_buffer = vdr_audio_port_put_buffer;
2689 + this->post_plugin.xine_post.audio_input[ 0 ] = &port->new_port;
2693 + this->audio_channels = 0;
2695 + return &this->post_plugin;
2698 +static char *vdr_audio_get_identifier(post_class_t *class_gen)
2700 + return "vdr_audio";
2703 +static char *vdr_audio_get_description(post_class_t *class_gen)
2705 + return "modifies every audio frame as requested by VDR";
2708 +static void vdr_audio_class_dispose(post_class_t *class_gen)
2710 + free(class_gen);
2714 +static void vdr_audio_dispose(post_plugin_t *this_gen)
2717 +fprintf(stderr, "~~~~~~~~~~ vdr dispose\n");
2719 + if (_x_post_dispose(this_gen))
2721 + vdr_audio_post_plugin_t *this = (vdr_audio_post_plugin_t *)this_gen;
2723 + if (this->vdr_stream)
2724 + xine_event_dispose_queue(this->event_queue);
2726 + free(this_gen);
2730 +static int vdr_audio_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream,
2731 + uint32_t bits, uint32_t rate, int mode) {
2733 + post_audio_port_t *port = (post_audio_port_t *)port_gen;
2734 + vdr_audio_post_plugin_t *this = (vdr_audio_post_plugin_t *)port->post;
2736 + _x_post_rewire(&this->post_plugin);
2737 + _x_post_inc_usage(port);
2739 +fprintf(stderr, "~~~~~~~~~~ vdr port open\n");
2741 + port->stream = stream;
2742 + port->bits = bits;
2743 + port->rate = rate;
2744 + port->mode = mode;
2746 + this->num_channels = _x_ao_mode2channels(mode);
2748 + return (port->original_port->open) (port->original_port, stream, bits, rate, mode );
2752 +static void vdr_audio_port_put_buffer(xine_audio_port_t *port_gen, audio_buffer_t *buf, xine_stream_t *stream)
2754 + post_audio_port_t *port = (post_audio_port_t *)port_gen;
2755 + vdr_audio_post_plugin_t *this = (vdr_audio_post_plugin_t *)port->post;
2756 + xine_event_t *event;
2758 +fprintf(stderr, "~~~~~~ vdr_audio\n");
2760 + if (this->vdr_stream
2761 + && !_x_continue_stream_processing(this->vdr_stream))
2763 + this->vdr_stream = 0;
2765 + xine_event_dispose_queue(this->event_queue);
2766 + this->event_queue = 0;
2768 + this->audio_channels = 0;
2771 + if (!this->vdr_stream
2772 + && vdr_is_vdr_stream(stream))
2774 + this->event_queue = xine_event_new_queue(stream);
2775 + if (this->event_queue)
2777 + this->vdr_stream = stream;
2780 + xine_event_t event;
2782 + event.type = XINE_EVENT_VDR_PLUGINSTARTED;
2783 + event.data = 0;
2784 + event.data_length = 1; /* vdr_audio */
2786 + xine_event_send(this->vdr_stream, &event);
2791 + if (this->event_queue)
2793 + while ((event = xine_event_get(this->event_queue)))
2795 + if (event->type == XINE_EVENT_VDR_SELECTAUDIO)
2797 + vdr_select_audio_data_t *data = (vdr_select_audio_data_t *)event->data;
2799 + vdr_audio_select_audio(this, data->channels);
2802 + xine_event_free(event);
2806 + if (this->num_channels == 2
2807 + && this->audio_channels != 0
2808 + && this->audio_channels != 3)
2810 + audio_buffer_t *vdr_buf = port->original_port->get_buffer(port->original_port);
2811 + vdr_buf->num_frames = buf->num_frames;
2812 + vdr_buf->vpts = buf->vpts;
2813 + vdr_buf->frame_header_count = buf->frame_header_count;
2814 + vdr_buf->first_access_unit = buf->first_access_unit;
2815 + /* FIXME: The audio buffer should contain this info.
2816 + * We should not have to get it from the open call.
2817 + */
2818 + vdr_buf->format.bits = buf->format.bits;
2819 + vdr_buf->format.rate = buf->format.rate;
2820 + vdr_buf->format.mode = buf->format.mode;
2821 + _x_extra_info_merge(vdr_buf->extra_info, buf->extra_info);
2824 + int step = buf->format.bits / 8;
2825 + uint8_t *src = (uint8_t *)buf->mem;
2826 + uint8_t *dst = (uint8_t *)vdr_buf->mem;
2828 + if (this->audio_channels == 2)
2829 + src += step;
2830 +/*
2831 + fprintf(stderr, "~~~~~~~~~~ vdr port put buffer: channels: %d, %d\n"
2832 + , this->audio_channels
2833 + , buf->format.bits);
2834 +*/
2835 + int i, k;
2836 + for (i = 0; i < buf->num_frames; i++)
2838 + for (k = 0; k < step; k++)
2839 + *dst++ = *src++;
2841 + src -= step;
2843 + for (k = 0; k < step; k++)
2844 + *dst++ = *src++;
2846 + src += step;
2850 + /* pass data to original port */
2851 + port->original_port->put_buffer(port->original_port, vdr_buf, stream);
2853 + /* free data from origial buffer */
2854 + buf->num_frames = 0; /* UNDOCUMENTED, but hey, it works! Force old audio_out buffer free. */
2857 + port->original_port->put_buffer(port->original_port, buf, stream);
2859 + return;
2861 diff --git a/src/vdr/post_vdr_video.c b/src/vdr/post_vdr_video.c
2862 new file mode 100644
2863 --- /dev/null
2864 +++ b/src/vdr/post_vdr_video.c
2865 @@ -0,0 +1,502 @@
2867 + * Copyright (C) 2000-2004 the xine project
2868 + *
2869 + * This file is part of xine, a free video player.
2870 + *
2871 + * xine is free software; you can redistribute it and/or modify
2872 + * it under the terms of the GNU General Public License as published by
2873 + * the Free Software Foundation; either version 2 of the License, or
2874 + * (at your option) any later version.
2875 + *
2876 + * xine is distributed in the hope that it will be useful,
2877 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2878 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2879 + * GNU General Public License for more details.
2880 + *
2881 + * You should have received a copy of the GNU General Public License
2882 + * along with this program; if not, write to the Free Software
2883 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
2884 + */
2887 + * frame scaler plugin for VDR
2888 + */
2890 +#define LOG_MODULE "vdr_video"
2892 +#define LOG
2893 +#define LOG_VERBOSE
2896 +#include "xine_internal.h"
2897 +#include "post.h"
2898 +#include "combined_vdr.h"
2902 +typedef struct vdr_video_post_plugin_s
2904 + post_plugin_t post_plugin;
2906 + xine_event_queue_t *event_queue;
2907 + xine_stream_t *vdr_stream;
2909 + int8_t trick_speed_mode;
2910 + int8_t enabled;
2912 + int32_t x;
2913 + int32_t y;
2914 + int32_t w;
2915 + int32_t h;
2916 + int32_t w_ref;
2917 + int32_t h_ref;
2919 + int32_t old_frame_left;
2920 + int32_t old_frame_top;
2921 + int32_t old_frame_width;
2922 + int32_t old_frame_height;
2923 + double old_frame_ratio;
2926 +vdr_video_post_plugin_t;
2929 +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)
2931 + this->enabled = 0;
2933 + this->x = x;
2934 + this->y = y;
2935 + this->w = w;
2936 + this->h = h;
2937 + this->w_ref = w_ref;
2938 + this->h_ref = h_ref;
2940 + if (w != w_ref || h != h_ref)
2941 + this->enabled = 1;
2945 +/* plugin class functions */
2946 +static post_plugin_t *vdr_video_open_plugin(post_class_t *class_gen, int inputs,
2947 + xine_audio_port_t **audio_target,
2948 + xine_video_port_t **video_target);
2949 +static char *vdr_video_get_identifier(post_class_t *class_gen);
2950 +static char *vdr_video_get_description(post_class_t *class_gen);
2951 +static void vdr_video_class_dispose(post_class_t *class_gen);
2953 +/* plugin instance functions */
2954 +static void vdr_video_dispose(post_plugin_t *this_gen);
2956 +/* route preprocessing functions check */
2957 +static int vdr_video_route_preprocessing_procs(post_video_port_t *port, vo_frame_t *frame);
2959 +/* replaced vo_frame functions */
2960 +static int vdr_video_draw(vo_frame_t *frame, xine_stream_t *stream);
2963 +void *vdr_video_init_plugin(xine_t *xine, void *data)
2965 + post_class_t *class = (post_class_t *)xine_xmalloc(sizeof (post_class_t));
2967 + if (!class)
2968 + return NULL;
2970 + class->open_plugin = vdr_video_open_plugin;
2971 + class->get_identifier = vdr_video_get_identifier;
2972 + class->get_description = vdr_video_get_description;
2973 + class->dispose = vdr_video_class_dispose;
2975 + return class;
2978 +static post_plugin_t *vdr_video_open_plugin(post_class_t *class_gen, int inputs,
2979 + xine_audio_port_t **audio_target,
2980 + xine_video_port_t **video_target)
2982 + vdr_video_post_plugin_t *this = (vdr_video_post_plugin_t *)xine_xmalloc(sizeof (vdr_video_post_plugin_t));
2983 + post_in_t *input;
2984 + post_out_t *output;
2985 + post_video_port_t *port;
2987 + if (!this || !video_target || !video_target[ 0 ])
2989 + free(this);
2990 + return NULL;
2993 + _x_post_init(&this->post_plugin, 0, 1);
2994 + this->post_plugin.dispose = vdr_video_dispose;
2996 + port = _x_post_intercept_video_port(&this->post_plugin, video_target[ 0 ], &input, &output);
2997 + port->route_preprocessing_procs = vdr_video_route_preprocessing_procs;
2998 + port->new_frame->draw = vdr_video_draw;
2999 + this->post_plugin.xine_post.video_input[ 0 ] = &port->new_port;
3001 + this->enabled = 0;
3002 + this->vdr_stream = 0;
3003 + this->event_queue = 0;
3004 + this->old_frame_left = 0;
3005 + this->old_frame_top = 0;
3006 + this->old_frame_width = 0;
3007 + this->old_frame_height = 0;
3008 + this->old_frame_ratio = 0;
3009 + this->trick_speed_mode = 0;
3011 + return &this->post_plugin;
3014 +static char *vdr_video_get_identifier(post_class_t *class_gen)
3016 + return "vdr";
3019 +static char *vdr_video_get_description(post_class_t *class_gen)
3021 + return "modifies every video frame as requested by VDR";
3024 +static void vdr_video_class_dispose(post_class_t *class_gen)
3026 + free(class_gen);
3030 +static void vdr_video_dispose(post_plugin_t *this_gen)
3032 + if (_x_post_dispose(this_gen))
3034 + vdr_video_post_plugin_t *this = (vdr_video_post_plugin_t *)this_gen;
3036 + if (this->vdr_stream)
3038 + xine_event_t event;
3039 + vdr_frame_size_changed_data_t event_data;
3041 + event_data.x = 0;
3042 + event_data.y = 0;
3043 + event_data.w = 0;
3044 + event_data.h = 0;
3046 + event.type = XINE_EVENT_VDR_FRAMESIZECHANGED;
3047 + event.data = &event_data;
3048 + event.data_length = sizeof (event_data);
3050 + xine_event_send(this->vdr_stream, &event);
3052 + xine_event_dispose_queue(this->event_queue);
3055 + free(this_gen);
3059 +static int vdr_video_route_preprocessing_procs(post_video_port_t *port, vo_frame_t *frame)
3061 + vdr_video_post_plugin_t *this = (vdr_video_post_plugin_t *)port->post;
3062 + return !this->enabled
3063 + || (frame->format != XINE_IMGFMT_YUY2
3064 + && frame->format != XINE_IMGFMT_YV12);
3068 +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)
3070 + int x0 = x * w_dst / w_ref;
3071 + int y0 = y * h_dst / h_ref;
3073 + int x1 = ((x + w) * w_dst - 1 + w_ref) / w_ref;
3074 + int y1 = ((y + h) * h_dst - 1 + h_ref) / h_ref;
3076 + int dx = x1 - x0;
3077 + int dy = y1 - y0;
3079 + int yy, xx;
3081 + int dy2 = dy + dy;
3082 + int h_dst2 = h_dst + h_dst;
3083 + int y_eps = h_dst - dy2;
3085 + int dx2 = dx + dx;
3086 + int w_dst2 = w_dst + w_dst;
3087 + int x_eps0 = w_dst - dx2;
3089 + for (yy = 0; yy < y0; yy++)
3091 + uint8_t *dst0 = dst;
3093 + for (xx = 0; xx < w_dst; xx++)
3095 + *dst0 = init;
3096 + dst0 += x_inc;
3099 + dst += y_inc;
3102 + for (yy = y0; yy < y1; yy++)
3104 + uint8_t *dst0 = dst;
3105 + uint8_t *src0 = src;
3107 + int x_eps = x_eps0;
3109 + for (xx = 0; xx < x0; xx++)
3111 + *dst0 = init;
3112 + dst0 += x_inc;
3115 + for (xx = x0; xx < x1; xx++)
3117 + *dst0 = *src0;
3118 + dst0 += x_inc;
3120 + x_eps += w_dst2;
3121 + while (x_eps >= 0)
3123 + src0 += x_inc;
3124 + x_eps -= dx2;
3128 + for (xx = x1; xx < w_dst; xx++)
3130 + *dst0 = init;
3131 + dst0 += x_inc;
3134 + dst += y_inc;
3136 + y_eps += h_dst2;
3137 + while (y_eps >= 0)
3139 + src += y_inc;
3140 + y_eps -= dy2;
3144 + for (yy = y1; yy < h_dst; yy++)
3146 + uint8_t *dst0 = dst;
3148 + for (xx = 0; xx < w_dst; xx++)
3150 + *dst0 = init;
3151 + dst0 += x_inc;
3154 + dst += y_inc;
3155 + }
3158 +static void vdr_video_scale_YUY2(vdr_video_post_plugin_t *this, vo_frame_t *src, vo_frame_t *dst)
3160 + int w = dst->width - dst->crop_left - dst->crop_right;
3161 + int h = dst->height - dst->crop_top - dst->crop_bottom;
3162 + int offset;
3164 + if (w < 0)
3165 + w = 0;
3167 + if (h < 0)
3168 + h = 0;
3170 + offset = dst->pitches[ 0 ] * dst->crop_top + 2 * dst->crop_left;
3171 + 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);
3172 + offset = dst->pitches[ 0 ] * dst->crop_top + 4 * ((dst->crop_left + 1) / 2);
3173 + 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);
3174 + offset = dst->pitches[ 0 ] * dst->crop_top + 4 * ((dst->crop_left + 1) / 2);
3175 + 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);
3178 +static void vdr_video_scale_YV12(vdr_video_post_plugin_t *this, vo_frame_t *src, vo_frame_t *dst)
3180 + int w = dst->width - dst->crop_left - dst->crop_right;
3181 + int h = dst->height - dst->crop_top - dst->crop_bottom;
3182 + int offset;
3184 + if (w < 0)
3185 + w = 0;
3187 + if (h < 0)
3188 + h = 0;
3190 + offset = dst->pitches[ 0 ] * dst->crop_top + 1 * dst->crop_left;
3191 + 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);
3192 + offset = dst->pitches[ 1 ] * ((dst->crop_top + 1) / 2) + 1 * ((dst->crop_left + 1) / 2);
3193 + 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);
3194 + offset = dst->pitches[ 2 ] * ((dst->crop_top + 1) / 2) + 1 * ((dst->crop_left + 1) / 2);
3195 + 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);
3199 +static int vdr_video_draw(vo_frame_t *frame, xine_stream_t *stream)
3201 + post_video_port_t *port = (post_video_port_t *)frame->port;
3202 + vdr_video_post_plugin_t *this = (vdr_video_post_plugin_t *)port->post;
3203 + vo_frame_t *vdr_frame;
3204 + xine_event_t *event;
3205 + int skip;
3207 + if (this->vdr_stream
3208 + && !_x_continue_stream_processing(this->vdr_stream))
3210 + this->vdr_stream = 0;
3212 + xine_event_dispose_queue(this->event_queue);
3213 + this->event_queue = 0;
3215 + this->old_frame_left = 0;
3216 + this->old_frame_top = 0;
3217 + this->old_frame_width = 0;
3218 + this->old_frame_height = 0;
3219 + this->old_frame_ratio = 0;
3222 + if (!this->vdr_stream
3223 + && vdr_is_vdr_stream(stream))
3225 + this->event_queue = xine_event_new_queue(stream);
3226 + if (this->event_queue)
3228 + this->vdr_stream = stream;
3231 + xine_event_t event;
3233 + event.type = XINE_EVENT_VDR_PLUGINSTARTED;
3234 + event.data = 0;
3235 + event.data_length = 0; /* vdr_video */
3237 + xine_event_send(this->vdr_stream, &event);
3242 + if (this->event_queue)
3244 + while ((event = xine_event_get(this->event_queue)))
3246 + if (event->type == XINE_EVENT_VDR_SETVIDEOWINDOW)
3248 + vdr_set_video_window_data_t *data = (vdr_set_video_window_data_t *)event->data;
3250 + vdr_video_set_video_window(this, data->x, data->y, data->w, data->h, data->w_ref, data->h_ref);
3252 + else if (event->type == XINE_EVENT_VDR_TRICKSPEEDMODE)
3255 + fprintf(stderr, "###############################: %p, %d\n", event->data, event->data_length);
3256 + this->trick_speed_mode = (0 != event->data_length);
3260 + xine_event_free(event);
3265 + int32_t frame_left = frame->crop_left;
3266 + int32_t frame_width = frame->width - frame->crop_left - frame->crop_right;
3267 + int32_t frame_top = frame->crop_top;
3268 + int32_t frame_height = frame->height - frame->crop_top - frame->crop_bottom;
3269 + double frame_ratio = frame->ratio;
3271 + if (frame_left < 0)
3272 + frame_left = 0;
3273 + if (frame_width > frame->width)
3274 + frame_width = frame->width;
3275 + if (frame_top < 0)
3276 + frame_top = 0;
3277 + if (frame_height > frame->height)
3278 + frame_height = frame->height;
3280 + if (this->vdr_stream
3281 + && frame_width != 0
3282 + && frame_height != 0
3283 + && (this->old_frame_left != frame_left
3284 + || this->old_frame_top != frame_top
3285 + || this->old_frame_width != frame_width
3286 + || this->old_frame_height != frame_height
3287 + || this->old_frame_ratio != frame_ratio))
3289 + xine_event_t event;
3290 + vdr_frame_size_changed_data_t event_data;
3292 + event_data.x = frame_left;
3293 + event_data.y = frame_top;
3294 + event_data.w = frame_width;
3295 + event_data.h = frame_height;
3296 + event_data.r = frame_ratio;
3298 + xprintf(this->vdr_stream->xine, XINE_VERBOSITY_LOG,
3299 + _(LOG_MODULE ": osd: (%d, %d)-(%d, %d)@%lg\n"), frame_left, frame_top, frame_width, frame_height, frame_ratio);
3301 + event.type = XINE_EVENT_VDR_FRAMESIZECHANGED;
3302 + event.data = &event_data;
3303 + event.data_length = sizeof (event_data);
3305 + xine_event_send(this->vdr_stream, &event);
3307 + this->old_frame_left = frame_left;
3308 + this->old_frame_top = frame_top;
3309 + this->old_frame_width = frame_width;
3310 + this->old_frame_height = frame_height;
3311 + this->old_frame_ratio = frame_ratio;
3315 + fprintf(stderr, "~~~~~~~~~~~~ trickspeedmode: %d\n", this->trick_speed_mode);
3317 + if (this->vdr_stream
3318 + && this->trick_speed_mode)
3320 + frame->pts = 0;
3321 + frame->next->pts = 0;
3323 +*/
3324 +#if defined(LOG) && defined(LOG_VERBOSE)
3326 + int a = 0, b = 0, c = 0, d = 0;
3327 + if (stream)
3328 + _x_query_buffer_usage(stream, &a, &b, &c, &d);
3329 + lprintf("buffer usage: %3d, %2d, %2d, %2d, %p\n", a, b, c, d, stream);
3331 +#endif
3333 + if (!this->enabled
3334 + || frame->bad_frame
3335 + || (frame->format != XINE_IMGFMT_YUY2
3336 + && frame->format != XINE_IMGFMT_YV12)
3337 + || frame->proc_frame
3338 + || frame->proc_slice)
3340 + _x_post_frame_copy_down(frame, frame->next);
3341 + skip = frame->next->draw(frame->next, stream);
3342 + _x_post_frame_copy_up(frame, frame->next);
3343 + return skip;
3346 + vdr_frame = port->original_port->get_frame(port->original_port,
3347 + frame->width, frame->height, frame->ratio, frame->format, frame->flags | VO_BOTH_FIELDS);
3349 + _x_post_frame_copy_down(frame, vdr_frame);
3351 + switch (vdr_frame->format)
3353 + case XINE_IMGFMT_YUY2:
3354 + vdr_video_scale_YUY2(this, frame, vdr_frame);
3355 + break;
3357 + case XINE_IMGFMT_YV12:
3358 + vdr_video_scale_YV12(this, frame, vdr_frame);
3359 + break;
3362 + skip = vdr_frame->draw(vdr_frame, stream);
3363 + _x_post_frame_copy_up(frame, vdr_frame);
3364 + vdr_frame->free(vdr_frame);
3366 + return skip;
3368 diff --git a/src/vdr/vdr.h b/src/vdr/vdr.h
3369 new file mode 100644
3370 --- /dev/null
3371 +++ b/src/vdr/vdr.h
3372 @@ -0,0 +1,663 @@
3374 + * Copyright (C) 2000-2004 the xine project
3376 + * This file is part of xine, a free video player.
3378 + * xine is free software; you can redistribute it and/or modify
3379 + * it under the terms of the GNU General Public License as published by
3380 + * the Free Software Foundation; either version 2 of the License, or
3381 + * (at your option) any later version.
3383 + * xine is distributed in the hope that it will be useful,
3384 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3385 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3386 + * GNU General Public License for more details.
3388 + * You should have received a copy of the GNU General Public License
3389 + * along with this program; if not, write to the Free Software
3390 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
3391 + */
3393 +#ifndef __VDR_H
3394 +#define __VDR_H
3397 +#define XINE_VDR_VERSION 900
3400 +enum funcs
3402 + func_unknown = -1
3403 + , func_nop
3404 + , func_osd_new
3405 + , func_osd_free
3406 + , func_osd_show
3407 + , func_osd_hide
3408 + , func_osd_set_position
3409 + , func_osd_draw_bitmap
3410 + , func_set_color
3411 + , func_clear
3412 + , func_mute
3413 + , func_set_volume
3414 + , func_set_speed
3415 + , func_set_prebuffer
3416 + , func_metronom
3417 + , func_start
3418 + , func_wait
3419 + , func_setup
3420 + , func_grab_image
3421 + , func_get_pts
3422 + , func_flush
3423 + , func_first_frame
3424 + , func_still_frame
3425 + , func_video_size
3426 + , func_set_video_window
3427 + , func_osd_flush
3428 + , func_play_external
3429 + , func_key
3430 + , func_frame_size
3431 + , func_reset_audio
3432 + , func_select_audio
3433 + , func_trick_speed_mode
3434 + , func_get_version
3435 + , func_discontinuity
3436 + , func_query_capabilities
3439 +enum keys
3441 + key_none,
3442 + key_up,
3443 + key_down,
3444 + key_menu,
3445 + key_ok,
3446 + key_back,
3447 + key_left,
3448 + key_right,
3449 + key_red,
3450 + key_green,
3451 + key_yellow,
3452 + key_blue,
3453 + key_0,
3454 + key_1,
3455 + key_2,
3456 + key_3,
3457 + key_4,
3458 + key_5,
3459 + key_6,
3460 + key_7,
3461 + key_8,
3462 + key_9,
3463 + key_play,
3464 + key_pause,
3465 + key_stop,
3466 + key_record,
3467 + key_fast_fwd,
3468 + key_fast_rew,
3469 + key_power,
3470 + key_channel_plus,
3471 + key_channel_minus,
3472 + key_volume_plus,
3473 + key_volume_minus,
3474 + key_mute,
3475 + key_schedule,
3476 + key_channels,
3477 + key_timers,
3478 + key_recordings,
3479 + key_setup,
3480 + key_commands,
3481 + key_user1,
3482 + key_user2,
3483 + key_user3,
3484 + key_user4,
3485 + key_user5,
3486 + key_user6,
3487 + key_user7,
3488 + key_user8,
3489 + key_user9,
3490 + key_audio,
3491 + key_info,
3492 + key_channel_previous,
3493 + key_next,
3494 + key_previous,
3495 + key_subtitles,
3500 +typedef struct __attribute__((packed)) data_header_s
3502 + uint32_t func:8;
3503 + uint32_t len:24;
3505 +data_header_t;
3509 +typedef data_header_t result_header_t;
3510 +typedef data_header_t event_header_t;
3514 +typedef struct __attribute__((packed)) data_nop_s
3516 + data_header_t header;
3518 +data_nop_t;
3522 +typedef struct __attribute__((packed)) data_osd_new_s
3524 + data_header_t header;
3526 + uint8_t window;
3527 + int16_t x;
3528 + int16_t y;
3529 + uint16_t width;
3530 + uint16_t height;
3531 + uint16_t w_ref;
3532 + uint16_t h_ref;
3534 +data_osd_new_t;
3538 +typedef struct __attribute__((packed)) data_osd_free_s
3540 + data_header_t header;
3542 + uint8_t window;
3544 +data_osd_free_t;
3548 +typedef struct __attribute__((packed)) data_osd_show_s
3550 + data_header_t header;
3552 + uint8_t window;
3554 +data_osd_show_t;
3558 +typedef struct __attribute__((packed)) data_osd_hide_s
3560 + data_header_t header;
3562 + uint8_t window;
3564 +data_osd_hide_t;
3568 +typedef struct __attribute__((packed)) data_osd_flush_s
3570 + data_header_t header;
3572 +data_osd_flush_t;
3576 +typedef struct __attribute__((packed)) data_play_external_s
3578 + data_header_t header;
3580 +data_play_external_t;
3584 +typedef struct __attribute__((packed)) data_osd_set_position_s
3586 + data_header_t header;
3588 + uint8_t window;
3589 + int16_t x;
3590 + int16_t y;
3592 +data_osd_set_position_t;
3596 +typedef struct __attribute__((packed)) data_osd_draw_bitmap_s
3598 + data_header_t header;
3600 + uint8_t window;
3601 + int16_t x;
3602 + int16_t y;
3603 + uint16_t width;
3604 + uint16_t height;
3605 + uint8_t argb;
3607 +data_osd_draw_bitmap_t;
3611 +typedef struct __attribute__((packed)) data_set_color_s
3613 + data_header_t header;
3615 + uint8_t window;
3616 + uint8_t index;
3617 + uint8_t num;
3619 +data_set_color_t;
3623 +typedef struct __attribute__((packed)) data_flush_s
3625 + data_header_t header;
3627 + int32_t ms_timeout;
3628 + uint8_t just_wait;
3630 +data_flush_t;
3634 +typedef struct __attribute__((packed)) result_flush_s
3636 + result_header_t header;
3638 + uint8_t timed_out;
3640 +result_flush_t;
3644 +typedef struct __attribute__((packed)) data_clear_s
3646 + data_header_t header;
3648 + int32_t n;
3649 + int8_t s;
3650 + uint8_t i;
3652 +data_clear_t;
3656 +typedef struct __attribute__((packed)) data_mute_s
3658 + data_header_t header;
3660 + uint8_t mute;
3662 +data_mute_t;
3666 +typedef struct __attribute__((packed)) data_set_volume_s
3668 + data_header_t header;
3670 + uint8_t volume;
3672 +data_set_volume_t;
3676 +typedef struct __attribute__((packed)) data_set_speed_s
3678 + data_header_t header;
3680 + int32_t speed;
3682 +data_set_speed_t;
3686 +typedef struct __attribute__((packed)) data_set_prebuffer_s
3688 + data_header_t header;
3690 + uint32_t prebuffer;
3692 +data_set_prebuffer_t;
3696 +typedef struct __attribute__((packed)) data_metronom_s
3698 + data_header_t header;
3700 + int64_t pts;
3701 + uint32_t flags;
3703 +data_metronom_t;
3707 +typedef struct __attribute__((packed)) data_start_s
3709 + data_header_t header;
3711 +data_start_t;
3715 +typedef struct __attribute__((packed)) data_wait_s
3717 + data_header_t header;
3718 + uint8_t id;
3720 +data_wait_t;
3724 +typedef struct __attribute__((packed)) result_wait_s
3726 + result_header_t header;
3728 +result_wait_t;
3732 +#define XINE_VDR_VOLUME_IGNORE 0
3733 +#define XINE_VDR_VOLUME_CHANGE_HW 1
3734 +#define XINE_VDR_VOLUME_CHANGE_SW 2
3736 +#define XINE_VDR_MUTE_IGNORE 0
3737 +#define XINE_VDR_MUTE_EXECUTE 1
3738 +#define XINE_VDR_MUTE_SIMULATE 2
3740 +typedef struct __attribute__((packed)) data_setup_s
3742 + data_header_t header;
3744 + uint8_t osd_unscaled_blending;
3745 + uint8_t volume_mode;
3746 + uint8_t mute_mode;
3747 + uint16_t image4_3_zoom_x;
3748 + uint16_t image4_3_zoom_y;
3749 + uint16_t image16_9_zoom_x;
3750 + uint16_t image16_9_zoom_y;
3752 +data_setup_t;
3756 +typedef struct __attribute__((packed)) data_first_frame_s
3758 + data_header_t header;
3760 +data_first_frame_t;
3764 +typedef struct __attribute__((packed)) data_still_frame_s
3766 + data_header_t header;
3768 +data_still_frame_t;
3772 +typedef struct __attribute__((packed)) data_set_video_window_s
3774 + data_header_t header;
3776 + uint32_t x;
3777 + uint32_t y;
3778 + uint32_t w;
3779 + uint32_t h;
3780 + uint32_t w_ref;
3781 + uint32_t h_ref;
3783 +data_set_video_window_t;
3787 +typedef struct __attribute__((packed)) data_grab_image_s
3789 + data_header_t header;
3791 +data_grab_image_t;
3795 +typedef struct __attribute__((packed)) result_grab_image_s
3797 + result_header_t header;
3799 + int32_t width;
3800 + int32_t height;
3801 + int32_t ratio;
3802 + int32_t format;
3803 + int32_t interlaced;
3804 + int32_t crop_left;
3805 + int32_t crop_right;
3806 + int32_t crop_top;
3807 + int32_t crop_bottom;
3809 +result_grab_image_t;
3813 +typedef struct __attribute__((packed)) data_get_pts_s
3815 + data_header_t header;
3817 +data_get_pts_t;
3821 +typedef struct __attribute__((packed)) result_get_pts_s
3823 + result_header_t header;
3825 + int64_t pts;
3827 +result_get_pts_t;
3831 +typedef struct __attribute__((packed)) data_get_version_s
3833 + data_header_t header;
3835 +data_get_version_t;
3839 +typedef struct __attribute__((packed)) result_get_version_s
3841 + result_header_t header;
3843 + int32_t version;
3845 +result_get_version_t;
3849 +typedef struct __attribute__((packed)) data_video_size_s
3851 + data_header_t header;
3853 +data_video_size_t;
3857 +typedef struct __attribute__((packed)) result_video_size_s
3859 + result_header_t header;
3861 + int32_t left;
3862 + int32_t top;
3863 + int32_t width;
3864 + int32_t height;
3865 + int32_t ratio;
3866 + int32_t zoom_x;
3867 + int32_t zoom_y;
3869 +result_video_size_t;
3873 +typedef struct __attribute__((packed)) data_reset_audio_s
3875 + data_header_t header;
3877 +data_reset_audio_t;
3881 +typedef struct __attribute__((packed)) event_key_s
3883 + event_header_t header;
3885 + uint32_t key;
3887 +event_key_t;
3891 +typedef struct __attribute__((packed)) event_frame_size_s
3893 + event_header_t header;
3895 + int32_t left;
3896 + int32_t top;
3897 + int32_t width;
3898 + int32_t height;
3899 + int32_t zoom_x;
3900 + int32_t zoom_y;
3902 +event_frame_size_t;
3906 +typedef struct __attribute__((packed)) event_play_external_s
3908 + event_header_t header;
3910 + uint32_t key;
3912 +event_play_external_t;
3916 +typedef struct __attribute__((packed)) data_select_audio_s
3918 + data_header_t header;
3920 + uint8_t channels;
3922 +data_select_audio_t;
3926 +typedef struct __attribute__((packed)) data_trick_speed_mode_s
3928 + data_header_t header;
3930 + uint8_t on;
3932 +data_trick_speed_mode_t;
3936 +typedef struct __attribute__((packed)) event_discontinuity_s
3938 + event_header_t header;
3940 + int32_t type;
3942 +event_discontinuity_t;
3946 +typedef struct __attribute__((packed)) data_query_capabilities_s
3948 + data_header_t header;
3950 +data_query_capabilities_t;
3954 +typedef struct __attribute__((packed)) result_query_capabilities_s
3956 + result_header_t header;
3958 + uint8_t osd_max_num_windows;
3959 + uint8_t osd_palette_max_depth;
3960 + uint8_t osd_palette_is_shared;
3961 + uint8_t osd_supports_argb_layer;
3962 + uint8_t osd_supports_custom_extent;
3964 +result_query_capabilities_t;
3968 +typedef union __attribute__((packed)) data_union_u
3970 + data_header_t header;
3971 + data_nop_t nop;
3972 + data_osd_new_t osd_new;
3973 + data_osd_free_t osd_free;
3974 + data_osd_show_t osd_show;
3975 + data_osd_hide_t osd_hide;
3976 + data_osd_set_position_t osd_set_position;
3977 + data_osd_draw_bitmap_t osd_draw_bitmap;
3978 + data_set_color_t set_color;
3979 + data_flush_t flush;
3980 + data_clear_t clear;
3981 + data_mute_t mute;
3982 + data_set_volume_t set_volume;
3983 + data_set_speed_t set_speed;
3984 + data_set_prebuffer_t set_prebuffer;
3985 + data_metronom_t metronom;
3986 + data_start_t start;
3987 + data_wait_t wait;
3988 + data_setup_t setup;
3989 + data_grab_image_t grab_image;
3990 + data_get_pts_t get_pts;
3991 + data_first_frame_t first_frame;
3992 + data_still_frame_t still_frame;
3993 + data_video_size_t video_size;
3994 + data_set_video_window_t set_video_window;
3995 + data_osd_flush_t osd_flush;
3996 + data_play_external_t play_external;
3997 + data_reset_audio_t reset_audio;
3998 + data_select_audio_t select_audio;
3999 + data_trick_speed_mode_t trick_speed_mode;
4000 + data_get_version_t get_version;
4001 + data_query_capabilities_t query_capabilities;
4003 +data_union_t;
4007 +typedef union __attribute__((packed)) result_union_u
4009 + result_header_t header;
4010 + result_grab_image_t grab_image;
4011 + result_get_pts_t get_pts;
4012 + result_flush_t flush;
4013 + result_video_size_t video_size;
4014 + result_get_version_t get_version;
4015 + result_wait_t wait;
4016 + result_query_capabilities_t query_capabilities;
4018 +result_union_t;
4022 +typedef union __attribute__((packed)) event_union_u
4024 + event_header_t header;
4025 + event_key_t key;
4026 + event_frame_size_t frame_size;
4027 + event_play_external_t play_external;
4028 + event_discontinuity_t discontinuity;
4030 +event_union_t;
4034 +#endif /* __VDR_H */
4036 diff --git a/src/video_out/video_out_xvmc.c b/src/video_out/video_out_xvmc.c
4037 --- a/src/video_out/video_out_xvmc.c
4038 +++ b/src/video_out/video_out_xvmc.c
4039 @@ -486,9 +486,9 @@ static void xvmc_render_macro_blocks(vo_
4040 int second_field,
4041 xvmc_macroblocks_t *macroblocks) {
4042 xvmc_driver_t *this = (xvmc_driver_t *) current_image->driver;
4043 - xvmc_frame_t *current_frame = (xvmc_frame_t *) current_image;
4044 - xvmc_frame_t *forward_frame = (xvmc_frame_t *) forward_ref_image;
4045 - xvmc_frame_t *backward_frame = (xvmc_frame_t *) backward_ref_image;
4046 + xvmc_frame_t *current_frame = XVMC_FRAME(current_image);
4047 + xvmc_frame_t *forward_frame = XVMC_FRAME(forward_ref_image);
4048 + xvmc_frame_t *backward_frame = XVMC_FRAME(backward_ref_image);
4049 int flags;
4051 lprintf ("xvmc_render_macro_blocks\n");
4052 @@ -561,6 +561,7 @@ static vo_frame_t *xvmc_alloc_frame (vo_
4053 return NULL;
4055 frame->vo_frame.accel_data = &frame->xvmc_data;
4056 + frame->xvmc_data.vo_frame = &frame->vo_frame;
4058 /* keep track of frames and how many frames alocated. */
4059 this->frames[this->num_frame_buffers++] = frame;
4060 diff --git a/src/video_out/video_out_xxmc.c b/src/video_out/video_out_xxmc.c
4061 --- a/src/video_out/video_out_xxmc.c
4062 +++ b/src/video_out/video_out_xxmc.c
4063 @@ -365,15 +365,15 @@ static int xxmc_lock_and_validate_surfac
4065 switch(pc_type) {
4066 case XINE_PICT_B_TYPE:
4067 - frame = (xxmc_frame_t *) bw_frame;
4068 + frame = XXMC_FRAME(bw_frame);
4069 if (!xxmc_xvmc_surface_valid( driver, frame->xvmc_surf)) break;
4070 /* fall through */
4071 case XINE_PICT_P_TYPE:
4072 - frame = (xxmc_frame_t *) fw_frame;
4073 + frame = XXMC_FRAME(fw_frame);
4074 if (!xxmc_xvmc_surface_valid( driver, frame->xvmc_surf)) break;
4075 /* fall through */
4076 default:
4077 - frame = (xxmc_frame_t *) cur_frame;
4078 + frame = XXMC_FRAME(cur_frame);
4079 if (!xxmc_xvmc_surface_valid( driver, frame->xvmc_surf)) break;
4080 return 0;
4082 @@ -404,7 +404,7 @@ static void xvmc_flush(vo_frame_t *this_
4085 xxmc_frame_t
4086 - *frame = (xxmc_frame_t *) this_gen;
4087 + *frame = XXMC_FRAME(this_gen);
4088 xxmc_driver_t
4089 *driver = (xxmc_driver_t *) this_gen->driver;
4091 @@ -452,6 +452,7 @@ static void xxmc_duplicate_frame_data(vo
4092 return;
4094 this->xxmc_data = *xxmc;
4095 + this->xxmc_data.xvmc.vo_frame = &this->vo_frame;
4096 this->width = original->width;
4097 this->height = original->height;
4098 this->format = original->format;
4099 @@ -566,6 +567,7 @@ static vo_frame_t *xxmc_alloc_frame (vo_
4100 frame->vo_frame.driver = this_gen;
4101 frame->last_sw_format = 0;
4102 frame->vo_frame.accel_data = &frame->xxmc_data;
4103 + frame->xxmc_data.xvmc.vo_frame = &frame->vo_frame;
4104 frame->image = NULL;
4106 xprintf (this->xine, XINE_VERBOSITY_DEBUG, "Allocating frame\n");
4107 @@ -1213,10 +1215,17 @@ static void xxmc_do_update_frame(vo_driv
4108 double ratio, int format, int flags) {
4110 xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
4111 - xxmc_frame_t *frame = (xxmc_frame_t *) frame_gen;
4112 + xxmc_frame_t *frame = XXMC_FRAME(frame_gen);
4114 if ( XINE_IMGFMT_XXMC == format ) {
4115 xine_xxmc_t *xxmc = &frame->xxmc_data;
4116 + vo_frame_t orig_frame_content;
4118 + if (frame_gen != &frame->vo_frame) {
4119 + /* this is an intercepted frame, so we need to detect and propagate any
4120 + * changes on the original vo_frame to all the intercepted frames */
4121 + xine_fast_memcpy(&orig_frame_content, &frame->vo_frame, sizeof (vo_frame_t));
4124 xvmc_context_writer_lock( &this->xvmc_lock);
4125 if (xxmc_accel_update(this, this->last_accel_request, xxmc->acceleration) ||
4126 @@ -1232,7 +1241,7 @@ static void xxmc_do_update_frame(vo_driv
4127 if (this->contextActive)
4128 xxmc_frame_updates(this, frame, 1);
4130 - xxmc_do_update_frame_xv(this_gen, frame_gen, width, height, ratio,
4131 + xxmc_do_update_frame_xv(this_gen, &frame->vo_frame, width, height, ratio,
4132 xxmc->fallback_format, flags);
4134 if (!this->contextActive) {
4135 @@ -1246,6 +1255,33 @@ static void xxmc_do_update_frame(vo_driv
4137 xvmc_context_writer_unlock( &this->xvmc_lock);
4139 + if (frame_gen != &frame->vo_frame) {
4140 + /* this is an intercepted frame, so we need to detect and propagate any
4141 + * changes on the original vo_frame to all the intercepted frames */
4142 + unsigned char *p0 = (unsigned char *)&orig_frame_content;
4143 + unsigned char *p1 = (unsigned char *)&frame->vo_frame;
4144 + int i;
4145 + for (i = 0; i < sizeof (vo_frame_t); i++) {
4146 + if (*p0 != *p1) {
4147 + /* propagate the change */
4148 + vo_frame_t *f = frame_gen;
4149 + while (f->next) {
4150 + /* serveral restrictions apply when intercepting XXMC frames. So let's check
4151 + * the intercepted frames before modifing them and fail otherwise. */
4152 + unsigned char *p = (unsigned char *)f + i;
4153 + if (*p != *p0) {
4154 + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "xxmc_do_update_frame: a post plugin violates the restrictions on intercepting XXMC frames\n");
4155 + _x_abort();
4158 + *p = *p1;
4159 + f = f->next;
4162 + p0++;
4163 + p1++;
4166 } else {
4167 /* switch back to an unaccelerated context */
4168 if (this->last_accel_request != 0xFFFFFFFF) {
4169 @@ -1253,7 +1289,7 @@ static void xxmc_do_update_frame(vo_driv
4170 xxmc_xvmc_update_context(this, frame, width, height, 0);
4172 frame->vo_frame.proc_duplicate_frame_data = NULL;
4173 - xxmc_do_update_frame_xv(this_gen, frame_gen, width, height, ratio,
4174 + xxmc_do_update_frame_xv(this_gen, &frame->vo_frame, width, height, ratio,
4175 format, flags);
4178 diff --git a/src/video_out/xvmc_mocomp.c b/src/video_out/xvmc_mocomp.c
4179 --- a/src/video_out/xvmc_mocomp.c
4180 +++ b/src/video_out/xvmc_mocomp.c
4181 @@ -70,9 +70,9 @@ static void xvmc_render_macro_blocks(vo_
4182 int second_field,
4183 xvmc_macroblocks_t *macroblocks) {
4184 xxmc_driver_t *this = (xxmc_driver_t *) current_image->driver;
4185 - xxmc_frame_t *current_frame = (xxmc_frame_t *) current_image;
4186 - xxmc_frame_t *forward_frame = (xxmc_frame_t *) forward_ref_image;
4187 - xxmc_frame_t *backward_frame = (xxmc_frame_t *) backward_ref_image;
4188 + xxmc_frame_t *current_frame = XXMC_FRAME(current_image);
4189 + xxmc_frame_t *forward_frame = XXMC_FRAME(forward_ref_image);
4190 + xxmc_frame_t *backward_frame = XXMC_FRAME(backward_ref_image);
4191 int flags;
4193 lprintf ("xvmc_render_macro_blocks\n");
4194 diff --git a/src/video_out/xvmc_vld.c b/src/video_out/xvmc_vld.c
4195 --- a/src/video_out/xvmc_vld.c
4196 +++ b/src/video_out/xvmc_vld.c
4197 @@ -32,12 +32,12 @@ void xvmc_vld_frame(struct vo_frame_s *t
4199 vo_frame_t *this = (vo_frame_t *) this_gen;
4200 xxmc_frame_t
4201 - *cf = (xxmc_frame_t *) this;
4202 + *cf = XXMC_FRAME(this);
4203 xine_vld_frame_t
4204 *vft = &(cf->xxmc_data.vld_frame);
4205 xxmc_frame_t
4206 - *ff = (xxmc_frame_t *) vft->forward_reference_frame,
4207 - *bf = (xxmc_frame_t *) vft->backward_reference_frame;
4208 + *ff = XXMC_FRAME(vft->forward_reference_frame),
4209 + *bf = XXMC_FRAME(vft->backward_reference_frame);
4210 XvMCMpegControl ctl;
4211 xxmc_driver_t
4212 *driver = (xxmc_driver_t *) cf->vo_frame.driver;
4213 @@ -104,7 +104,7 @@ void xvmc_vld_slice(vo_frame_t *this_gen
4214 void xvmc_vld_slice(vo_frame_t *this_gen)
4216 xxmc_frame_t
4217 - *cf = (xxmc_frame_t *) this_gen;
4218 + *cf = XXMC_FRAME(this_gen);
4219 xxmc_driver_t
4220 *driver = (xxmc_driver_t *) cf->vo_frame.driver;
4222 diff --git a/src/xine-engine/accel_xvmc.h b/src/xine-engine/accel_xvmc.h
4223 --- a/src/xine-engine/accel_xvmc.h
4224 +++ b/src/xine-engine/accel_xvmc.h
4225 @@ -65,6 +65,7 @@ typedef struct xine_vld_frame_s {
4228 typedef struct xine_xvmc_s {
4229 + vo_frame_t *vo_frame;
4230 xine_macroblocks_t *macroblocks;
4231 void (*proc_macro_block)(int x,int y,int mb_type,
4232 int motion_type,int (*mv_field_sel)[2],
4233 @@ -73,6 +74,9 @@ typedef struct xine_xvmc_s {
4234 vo_frame_t *backward_ref_frame,int picture_structure,
4235 int second_field,int (*f_mot_pmv)[2],int (*b_mot_pmv)[2]);
4236 } xine_xvmc_t ;
4238 +#define XVMC_DATA(frame_gen) ((frame_gen) ? (xine_xvmc_t *)(frame_gen)->accel_data : (xine_xvmc_t *)0)
4239 +#define XVMC_FRAME(frame_gen) ((frame_gen) ? (xvmc_frame_t *)XVMC_DATA(frame_gen)->vo_frame : (xvmc_frame_t *)0)
4241 typedef struct xine_xxmc_s {
4243 @@ -108,6 +112,9 @@ typedef struct xine_xxmc_s {
4244 void (*proc_xxmc_unlock) (vo_driver_t *this_gen);
4245 } xine_xxmc_t;
4247 +#define XXMC_DATA(frame_gen) ((frame_gen) ? (xine_xxmc_t *)(frame_gen)->accel_data : (xine_xxmc_t *)0)
4248 +#define XXMC_FRAME(frame_gen) ((frame_gen) ? (xxmc_frame_t *)XXMC_DATA(frame_gen)->xvmc.vo_frame : (xxmc_frame_t *)0)
4251 * Register XvMC stream types here.
4253 diff --git a/src/xine-engine/post.c b/src/xine-engine/post.c
4254 --- a/src/xine-engine/post.c
4255 +++ b/src/xine-engine/post.c
4256 @@ -144,6 +144,14 @@ static void post_video_flush(xine_video_
4257 if (port->port_lock) pthread_mutex_unlock(port->port_lock);
4260 +static void post_video_trigger_drawing(xine_video_port_t *port_gen) {
4261 + post_video_port_t *port = (post_video_port_t *)port_gen;
4263 + if (port->port_lock) pthread_mutex_lock(port->port_lock);
4264 + port->original_port->trigger_drawing(port->original_port);
4265 + if (port->port_lock) pthread_mutex_unlock(port->port_lock);
4268 static int post_video_status(xine_video_port_t *port_gen, xine_stream_t *stream,
4269 int *width, int *height, int64_t *img_duration) {
4270 post_video_port_t *port = (post_video_port_t *)port_gen;
4271 @@ -187,6 +195,7 @@ static int post_video_rewire(xine_post_o
4272 if (!new_port)
4273 return 0;
4275 + this->running_ticket->lock_port_rewiring(this->running_ticket, -1);
4276 this->running_ticket->revoke(this->running_ticket, 1);
4278 if (input_port->original_port->status(input_port->original_port, input_port->stream,
4279 @@ -197,6 +206,7 @@ static int post_video_rewire(xine_post_o
4280 input_port->original_port = new_port;
4282 this->running_ticket->issue(this->running_ticket, 1);
4283 + this->running_ticket->unlock_port_rewiring(this->running_ticket);
4285 return 1;
4287 @@ -218,6 +228,7 @@ post_video_port_t *_x_post_intercept_vid
4288 port->new_port.exit = post_video_exit;
4289 port->new_port.get_overlay_manager = post_video_get_overlay_manager;
4290 port->new_port.flush = post_video_flush;
4291 + port->new_port.trigger_drawing = post_video_trigger_drawing;
4292 port->new_port.status = post_video_status;
4293 port->new_port.get_property = post_video_get_property;
4294 port->new_port.set_property = post_video_set_property;
4295 @@ -377,10 +388,11 @@ vo_frame_t *_x_post_intercept_video_fram
4296 port->new_frame->free ? port->new_frame->free : post_frame_free;
4297 new_frame->dispose =
4298 port->new_frame->dispose ? port->new_frame->dispose : post_frame_dispose;
4300 - if (!port->new_frame->draw) {
4302 + if (!port->new_frame->draw || (port->route_preprocessing_procs && port->route_preprocessing_procs(port, frame))) {
4303 /* draw will most likely modify the frame, so the decoder
4304 - * should only request preprocessing when there is no new draw */
4305 + * should only request preprocessing when there is no new draw
4306 + * but route_preprocessing_procs() can override this decision */
4307 if (frame->proc_frame && !new_frame->proc_frame)
4308 new_frame->proc_frame = post_frame_proc_frame;
4309 if (frame->proc_slice && !new_frame->proc_slice)
4310 @@ -697,6 +709,7 @@ static int post_audio_rewire(xine_post_o
4311 if (!new_port)
4312 return 0;
4314 + this->running_ticket->lock_port_rewiring(this->running_ticket, -1);
4315 this->running_ticket->revoke(this->running_ticket, 1);
4317 if (input_port->original_port->status(input_port->original_port, input_port->stream,
4318 @@ -707,6 +720,7 @@ static int post_audio_rewire(xine_post_o
4319 input_port->original_port = new_port;
4321 this->running_ticket->issue(this->running_ticket, 1);
4322 + this->running_ticket->unlock_port_rewiring(this->running_ticket);
4324 return 1;
4326 diff --git a/src/xine-engine/post.h b/src/xine-engine/post.h
4327 --- a/src/xine-engine/post.h
4328 +++ b/src/xine-engine/post.h
4329 @@ -177,6 +177,13 @@ struct post_video_port_s {
4330 /* the new frame function pointers */
4331 vo_frame_t *new_frame;
4333 + /* if you want to decide yourself, whether the preprocessing functions
4334 + * should still be routed when draw is intercepted, fill in this
4335 + * function; _x_post_intercept_video_frame() acts as a template method
4336 + * and asks your function; return a boolean; the default is _not_ to
4337 + * route preprocessing functions when draw is intercepted */
4338 + int (*route_preprocessing_procs)(post_video_port_t *self, vo_frame_t *frame);
4340 /* if you want to decide yourself, whether the overlay manager should
4341 * be intercepted, fill in this function; get_overlay_manager() acts as
4342 * a template method and asks your function; return a boolean;
4343 diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c
4344 --- a/src/xine-engine/video_out.c
4345 +++ b/src/xine-engine/video_out.c
4346 @@ -132,6 +132,9 @@ typedef struct {
4347 int frame_drop_cpt;
4348 int frame_drop_suggested;
4349 int crop_left, crop_right, crop_top, crop_bottom;
4350 + pthread_mutex_t trigger_drawing_mutex;
4351 + pthread_cond_t trigger_drawing_cond;
4352 + int trigger_drawing;
4353 } vos_t;
4356 @@ -1068,6 +1071,32 @@ static void check_redraw_needed (vos_t *
4357 this->redraw_needed = 1;
4360 +static int interruptable_sleep(vos_t *this, int usec_to_sleep)
4362 + int timedout = 0;
4364 + struct timeval now;
4365 + gettimeofday(&now, 0);
4367 + pthread_mutex_lock (&this->trigger_drawing_mutex);
4368 + if (!this->trigger_drawing) {
4369 + struct timespec abstime;
4370 + abstime.tv_sec = now.tv_sec + usec_to_sleep / 1000000;
4371 + abstime.tv_nsec = now.tv_usec * 1000 + (usec_to_sleep % 1000000) * 1000;
4373 + if (abstime.tv_nsec > 1000000000) {
4374 + abstime.tv_nsec -= 1000000000;
4375 + abstime.tv_sec++;
4378 + timedout = pthread_cond_timedwait(&this->trigger_drawing_cond, &this->trigger_drawing_mutex, &abstime);
4380 + this->trigger_drawing = 0;
4381 + pthread_mutex_unlock (&this->trigger_drawing_mutex);
4383 + return timedout;
4386 /* special loop for paused mode
4387 * needed to update screen due overlay changes, resize, window
4388 * movement, brightness adjusting etc.
4389 @@ -1113,7 +1142,7 @@ static void paused_loop( vos_t *this, in
4392 pthread_mutex_unlock( &this->free_img_buf_queue->mutex );
4393 - xine_usec_sleep (20000);
4394 + interruptable_sleep(this, 20000);
4395 pthread_mutex_lock( &this->free_img_buf_queue->mutex );
4398 @@ -1243,7 +1272,10 @@ static void *video_out_loop (void *this_
4399 "video_out: vpts/clock error, next_vpts=%" PRId64 " cur_vpts=%" PRId64 "\n", next_frame_vpts,vpts);
4401 if (usec_to_sleep > 0)
4402 - xine_usec_sleep (usec_to_sleep);
4404 + if (0 == interruptable_sleep(this, usec_to_sleep))
4405 + break;
4408 if (this->discard_frames)
4409 break;
4410 @@ -1626,6 +1658,9 @@ static void vo_exit (xine_video_port_t *
4411 free (this->free_img_buf_queue);
4412 free (this->display_img_buf_queue);
4414 + pthread_cond_destroy(&this->trigger_drawing_cond);
4415 + pthread_mutex_destroy(&this->trigger_drawing_mutex);
4417 free (this);
4420 @@ -1693,6 +1728,15 @@ static void vo_flush (xine_video_port_t
4421 this->discard_frames--;
4422 pthread_mutex_unlock(&this->display_img_buf_queue->mutex);
4426 +static void vo_trigger_drawing (xine_video_port_t *this_gen) {
4427 + vos_t *this = (vos_t *) this_gen;
4429 + pthread_mutex_lock (&this->trigger_drawing_mutex);
4430 + this->trigger_drawing = 1;
4431 + pthread_cond_signal (&this->trigger_drawing_cond);
4432 + pthread_mutex_unlock (&this->trigger_drawing_mutex);
4435 /* crop_frame() will allocate a new frame to copy in the given image
4436 @@ -1790,6 +1834,7 @@ xine_video_port_t *_x_vo_new_port (xine_
4437 this->vo.enable_ovl = vo_enable_overlay;
4438 this->vo.get_overlay_manager = vo_get_overlay_manager;
4439 this->vo.flush = vo_flush;
4440 + this->vo.trigger_drawing = vo_trigger_drawing;
4441 this->vo.get_property = vo_get_property;
4442 this->vo.set_property = vo_set_property;
4443 this->vo.status = vo_status;
4444 @@ -1883,6 +1928,9 @@ xine_video_port_t *_x_vo_new_port (xine_
4445 "were not scheduled for display in time, xine sends a notification."),
4446 20, NULL, NULL);
4448 + pthread_mutex_init(&this->trigger_drawing_mutex, NULL);
4449 + pthread_cond_init(&this->trigger_drawing_cond, NULL);
4450 + this->trigger_drawing = 0;
4452 if (grabonly) {
4454 diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h
4455 --- a/src/xine-engine/video_out.h
4456 +++ b/src/xine-engine/video_out.h
4457 @@ -202,6 +202,9 @@ struct xine_video_port_s {
4458 /* flush video_out fifo */
4459 void (*flush) (xine_video_port_t *self);
4461 + /* trigger immediate drawing */
4462 + void (*trigger_drawing) (xine_video_port_t *self);
4464 /* Get/Set video property
4466 * See VO_PROP_* bellow
4467 diff --git a/src/xine-engine/video_overlay.h b/src/xine-engine/video_overlay.h
4468 --- a/src/xine-engine/video_overlay.h
4469 +++ b/src/xine-engine/video_overlay.h
4470 @@ -35,7 +35,7 @@
4472 #define MAX_OBJECTS 50
4473 #define MAX_EVENTS 50
4474 -#define MAX_SHOWING 16
4475 +#define MAX_SHOWING (5 + 16)
4477 #define OVERLAY_EVENT_NULL 0
4478 #define OVERLAY_EVENT_SHOW 1
4479 diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
4480 --- a/src/xine-engine/xine.c
4481 +++ b/src/xine-engine/xine.c
4482 @@ -294,8 +294,37 @@ static void ticket_revoke(xine_ticket_t
4483 pthread_mutex_unlock(&this->revoke_lock);
4486 +static int ticket_lock_port_rewiring(xine_ticket_t *this, int ms_timeout) {
4488 + if (ms_timeout >= 0) {
4489 + struct timespec abstime;
4491 + struct timeval now;
4492 + gettimeofday(&now, 0);
4494 + abstime.tv_sec = now.tv_sec + ms_timeout / 1000;
4495 + abstime.tv_nsec = now.tv_usec * 1000 + (ms_timeout % 1000) * 1e6;
4497 + if (abstime.tv_nsec > 1e9) {
4498 + abstime.tv_nsec -= 1e9;
4499 + abstime.tv_sec++;
4502 + return (0 == pthread_mutex_timedlock(&this->port_rewiring_lock, &abstime));
4505 + pthread_mutex_lock(&this->port_rewiring_lock);
4506 + return 1;
4509 +static void ticket_unlock_port_rewiring(xine_ticket_t *this) {
4511 + pthread_mutex_unlock(&this->port_rewiring_lock);
4514 static void ticket_dispose(xine_ticket_t *this) {
4516 + pthread_mutex_destroy(&this->port_rewiring_lock);
4517 pthread_mutex_destroy(&this->lock);
4518 pthread_mutex_destroy(&this->revoke_lock);
4519 pthread_cond_destroy(&this->issued);
4520 @@ -316,12 +345,15 @@ static xine_ticket_t *XINE_MALLOC ticket
4521 port_ticket->renew = ticket_renew;
4522 port_ticket->issue = ticket_issue;
4523 port_ticket->revoke = ticket_revoke;
4524 + port_ticket->lock_port_rewiring = ticket_lock_port_rewiring;
4525 + port_ticket->unlock_port_rewiring = ticket_unlock_port_rewiring;
4526 port_ticket->dispose = ticket_dispose;
4527 port_ticket->holder_thread_count = XINE_MAX_TICKET_HOLDER_THREADS;
4528 port_ticket->holder_threads = calloc(XINE_MAX_TICKET_HOLDER_THREADS,sizeof(*port_ticket->holder_threads));
4530 pthread_mutex_init(&port_ticket->lock, NULL);
4531 pthread_mutex_init(&port_ticket->revoke_lock, NULL);
4532 + pthread_mutex_init(&port_ticket->port_rewiring_lock, NULL);
4533 pthread_cond_init(&port_ticket->issued, NULL);
4534 pthread_cond_init(&port_ticket->revoked, NULL);
4536 @@ -515,6 +547,7 @@ static int stream_rewire_audio(xine_post
4537 if (!data)
4538 return 0;
4540 + stream->xine->port_ticket->lock_port_rewiring(stream->xine->port_ticket, -1);
4541 stream->xine->port_ticket->revoke(stream->xine->port_ticket, 1);
4543 if (stream->audio_out->status(stream->audio_out, stream, &bits, &rate, &mode)) {
4544 @@ -525,6 +558,7 @@ static int stream_rewire_audio(xine_post
4545 stream->audio_out = new_port;
4547 stream->xine->port_ticket->issue(stream->xine->port_ticket, 1);
4548 + stream->xine->port_ticket->unlock_port_rewiring(stream->xine->port_ticket);
4550 return 1;
4552 @@ -539,6 +573,7 @@ static int stream_rewire_video(xine_post
4553 if (!data)
4554 return 0;
4556 + stream->xine->port_ticket->lock_port_rewiring(stream->xine->port_ticket, -1);
4557 stream->xine->port_ticket->revoke(stream->xine->port_ticket, 1);
4559 if (stream->video_out->status(stream->video_out, stream, &width, &height, &img_duration)) {
4560 @@ -549,6 +584,7 @@ static int stream_rewire_video(xine_post
4561 stream->video_out = new_port;
4563 stream->xine->port_ticket->issue(stream->xine->port_ticket, 1);
4564 + stream->xine->port_ticket->unlock_port_rewiring(stream->xine->port_ticket);
4566 return 1;
4568 @@ -2330,3 +2366,83 @@ int _x_query_buffer_usage(xine_stream_t
4570 return ticket_acquired != 0;
4573 +int _x_lock_port_rewiring(xine_t *xine, int ms_timeout)
4575 + return xine->port_ticket->lock_port_rewiring(xine->port_ticket, ms_timeout);
4578 +void _x_unlock_port_rewiring(xine_t *xine)
4580 + xine->port_ticket->unlock_port_rewiring(xine->port_ticket);
4583 +int _x_lock_frontend(xine_stream_t *stream, int ms_to_time_out)
4585 + if (ms_to_time_out >= 0) {
4586 + struct timespec abstime;
4588 + struct timeval now;
4589 + gettimeofday(&now, 0);
4591 + abstime.tv_sec = now.tv_sec + ms_to_time_out / 1000;
4592 + abstime.tv_nsec = now.tv_usec * 1000 + (ms_to_time_out % 1000) * 1e6;
4594 + if (abstime.tv_nsec > 1e9) {
4595 + abstime.tv_nsec -= 1e9;
4596 + abstime.tv_sec++;
4599 + return (0 == pthread_mutex_timedlock(&stream->frontend_lock, &abstime));
4602 + pthread_mutex_lock(&stream->frontend_lock);
4603 + return 1;
4606 +void _x_unlock_frontend(xine_stream_t *stream)
4608 + pthread_mutex_unlock(&stream->frontend_lock);
4611 +int _x_query_unprocessed_osd_events(xine_stream_t *stream)
4613 + video_overlay_manager_t *ovl;
4614 + int redraw_needed;
4616 + if (!stream->xine->port_ticket->acquire_nonblocking(stream->xine->port_ticket, 1))
4617 + return -1;
4619 + ovl = stream->video_out->get_overlay_manager(stream->video_out);
4620 + redraw_needed = ovl->redraw_needed(ovl, 0);
4622 + if (redraw_needed)
4623 + stream->video_out->trigger_drawing(stream->video_out);
4625 + stream->xine->port_ticket->release_nonblocking(stream->xine->port_ticket, 1);
4627 + return redraw_needed;
4630 +int _x_demux_seek(xine_stream_t *stream, off_t start_pos, int start_time, int playing)
4632 + if (!stream->demux_plugin)
4633 + return -1;
4634 + return stream->demux_plugin->seek(stream->demux_plugin, start_pos, start_time, playing);
4637 +int _x_continue_stream_processing(xine_stream_t *stream)
4639 + return stream->status != XINE_STATUS_STOP
4640 + && stream->status != XINE_STATUS_QUIT;
4643 +void _x_trigger_relaxed_frame_drop_mode(xine_stream_t *stream)
4645 + stream->first_frame_flag = 2;
4648 +void _x_reset_relaxed_frame_drop_mode(xine_stream_t *stream)
4650 + stream->first_frame_flag = 1;
4652 diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h
4653 --- a/src/xine-engine/xine_internal.h
4654 +++ b/src/xine-engine/xine_internal.h
4655 @@ -169,6 +169,9 @@ struct xine_ticket_s {
4656 * be used in combination with acquire_nonblocking() */
4657 void (*release_nonblocking)(xine_ticket_t *self, int irrevocable);
4659 + int (*lock_port_rewiring)(xine_ticket_t *self, int ms_timeout);
4660 + void (*unlock_port_rewiring)(xine_ticket_t *self);
4662 void (*dispose)(xine_ticket_t *self);
4664 pthread_mutex_t lock;
4665 @@ -185,6 +188,7 @@ struct xine_ticket_s {
4666 pthread_t holder;
4667 } *holder_threads;
4668 unsigned holder_thread_count;
4669 + pthread_mutex_t port_rewiring_lock;
4670 #endif
4673 @@ -374,6 +378,15 @@ struct xine_stream_s {
4676 int _x_query_buffer_usage(xine_stream_t *stream, int *num_video_buffers, int *num_audio_buffers, int *num_video_frames, int *num_audio_frames) XINE_PROTECTED;
4677 +int _x_lock_port_rewiring(xine_t *xine, int ms_to_time_out) XINE_PROTECTED;
4678 +void _x_unlock_port_rewiring(xine_t *xine) XINE_PROTECTED;
4679 +int _x_lock_frontend(xine_stream_t *stream, int ms_to_time_out) XINE_PROTECTED;
4680 +void _x_unlock_frontend(xine_stream_t *stream) XINE_PROTECTED;
4681 +int _x_query_unprocessed_osd_events(xine_stream_t *stream) XINE_PROTECTED;
4682 +int _x_demux_seek(xine_stream_t *stream, off_t start_pos, int start_time, int playing) XINE_PROTECTED;
4683 +int _x_continue_stream_processing(xine_stream_t *stream) XINE_PROTECTED;
4684 +void _x_trigger_relaxed_frame_drop_mode(xine_stream_t *stream) XINE_PROTECTED;
4685 +void _x_reset_relaxed_frame_drop_mode(xine_stream_t *stream) XINE_PROTECTED;
4687 void _x_handle_stream_end (xine_stream_t *stream, int non_user) XINE_PROTECTED;