input/subtitles.c \
input/var.c \
video_output/chrono.h \
+ video_output/control.c \
+ video_output/control.h \
video_output/display.c \
video_output/display.h \
video_output/event.h \
--- /dev/null
+/*****************************************************************************
+ * control.c : vout internal control
+ *****************************************************************************
+ * Copyright (C) 2009 Laurent Aimar
+ * $Id$
+ *
+ * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include "control.h"
+
+/* */
+void vout_control_cmd_Init(vout_control_cmd_t *cmd, int type)
+{
+ memset(cmd, 0, sizeof(*cmd));
+ cmd->type = type;
+}
+
+void vout_control_cmd_Clean(vout_control_cmd_t *cmd)
+{
+ switch (cmd->type) {
+ //case VOUT_CONTROL_OSD_MESSAGE:
+ case VOUT_CONTROL_OSD_TITLE:
+ free(cmd->u.message.string);
+ break;
+#if 0
+ case VOUT_CONTROL_OSD_TEXT:
+ free(cmd->text.string);
+ if (cmd->text.style)
+ text_style_Delete(cmd->text.style);
+ break;
+ case VOUT_CONTROL_OSD_SUBPICTURE:
+ if (cmd->subpicture)
+ subpicture_Delete(cmd->subpicture);
+ break;
+#endif
+ default:
+ break;
+ }
+}
+
+/* */
+void vout_control_Init(vout_control_t *ctrl)
+{
+ vlc_mutex_init(&ctrl->lock);
+ vlc_cond_init(&ctrl->wait_request);
+ vlc_cond_init(&ctrl->wait_acknowledge);
+
+ ctrl->is_dead = false;
+ ctrl->is_sleeping = false;
+ ctrl->can_sleep = true;
+ ctrl->is_processing = false;
+ ARRAY_INIT(ctrl->cmd);
+}
+
+void vout_control_Clean(vout_control_t *ctrl)
+{
+ /* */
+ for (int i = 0; i < ctrl->cmd.i_size; i++) {
+ vout_control_cmd_t cmd = ARRAY_VAL(ctrl->cmd, i);
+ vout_control_cmd_Clean(&cmd);
+ }
+ ARRAY_RESET(ctrl->cmd);
+
+ vlc_mutex_destroy(&ctrl->lock);
+ vlc_cond_destroy(&ctrl->wait_request);
+ vlc_cond_destroy(&ctrl->wait_acknowledge);
+}
+
+void vout_control_Dead(vout_control_t *ctrl)
+{
+ vlc_mutex_lock(&ctrl->lock);
+ ctrl->is_dead = true;
+ vlc_cond_broadcast(&ctrl->wait_acknowledge);
+ vlc_mutex_unlock(&ctrl->lock);
+
+}
+
+void vout_control_WaitEmpty(vout_control_t *ctrl)
+{
+ vlc_mutex_lock(&ctrl->lock);
+ while ((ctrl->cmd.i_size > 0 || ctrl->is_processing) && !ctrl->is_dead)
+ vlc_cond_wait(&ctrl->wait_acknowledge, &ctrl->lock);
+ vlc_mutex_unlock(&ctrl->lock);
+}
+
+void vout_control_Push(vout_control_t *ctrl, vout_control_cmd_t *cmd)
+{
+ vlc_mutex_lock(&ctrl->lock);
+ if (!ctrl->is_dead) {
+ ARRAY_APPEND(ctrl->cmd, *cmd);
+ vlc_cond_signal(&ctrl->wait_request);
+ } else {
+ vout_control_cmd_Clean(cmd);
+ }
+ vlc_mutex_unlock(&ctrl->lock);
+}
+
+void vout_control_Wake(vout_control_t *ctrl)
+{
+ vlc_mutex_lock(&ctrl->lock);
+ ctrl->can_sleep = false;
+ if (ctrl->is_sleeping)
+ vlc_cond_signal(&ctrl->wait_request);
+ vlc_mutex_unlock(&ctrl->lock);
+}
+
+void vout_control_PushVoid(vout_control_t *ctrl, int type)
+{
+ vout_control_cmd_t cmd;
+
+ vout_control_cmd_Init(&cmd, type);
+ vout_control_Push(ctrl, &cmd);
+}
+void vout_control_PushBool(vout_control_t *ctrl, int type, bool boolean)
+{
+ vout_control_cmd_t cmd;
+
+ vout_control_cmd_Init(&cmd, type);
+ cmd.u.boolean = boolean;
+ vout_control_Push(ctrl, &cmd);
+}
+void vout_control_PushTime(vout_control_t *ctrl, int type, mtime_t time)
+{
+ vout_control_cmd_t cmd;
+
+ vout_control_cmd_Init(&cmd, type);
+ cmd.u.time = time;
+ vout_control_Push(ctrl, &cmd);
+}
+void vout_control_PushMessage(vout_control_t *ctrl, int type, int channel, const char *string)
+{
+ vout_control_cmd_t cmd;
+
+ vout_control_cmd_Init(&cmd, type);
+ cmd.u.message.channel = channel;
+ cmd.u.message.string = strdup(string);
+ vout_control_Push(ctrl, &cmd);
+}
+void vout_control_PushPair(vout_control_t *ctrl, int type, int a, int b)
+{
+ vout_control_cmd_t cmd;
+
+ vout_control_cmd_Init(&cmd, type);
+ cmd.u.pair.a = a;
+ cmd.u.pair.b = b;
+ vout_control_Push(ctrl, &cmd);
+}
+
+int vout_control_Pop(vout_control_t *ctrl, vout_control_cmd_t *cmd,
+ mtime_t deadline, mtime_t timeout)
+{
+ vlc_mutex_lock(&ctrl->lock);
+ if (ctrl->cmd.i_size <= 0) {
+ ctrl->is_processing = false;
+ vlc_cond_broadcast(&ctrl->wait_acknowledge);
+
+ const mtime_t max_deadline = mdate() + timeout;
+
+ /* Supurious wake up are perfectly fine */
+ if (deadline <= VLC_TS_INVALID) {
+ ctrl->is_sleeping = true;
+ if (ctrl->can_sleep)
+ vlc_cond_timedwait(&ctrl->wait_request, &ctrl->lock, max_deadline);
+ ctrl->is_sleeping = false;
+ } else {
+ vlc_cond_timedwait(&ctrl->wait_request, &ctrl->lock, __MIN(deadline, max_deadline));
+ }
+ }
+
+ bool has_cmd;
+ if (ctrl->cmd.i_size > 0) {
+ has_cmd = true;
+ *cmd = ARRAY_VAL(ctrl->cmd, 0);
+ ARRAY_REMOVE(ctrl->cmd, 0);
+
+ ctrl->is_processing = true;
+ } else {
+ has_cmd = false;
+ ctrl->can_sleep = true;
+ }
+ vlc_mutex_unlock(&ctrl->lock);
+
+ return has_cmd ? VLC_SUCCESS : VLC_EGENERIC;
+}
+
--- /dev/null
+/*****************************************************************************
+ * control.h : vout internal control
+ *****************************************************************************
+ * Copyright (C) 2009-2010 Laurent Aimar
+ * $Id$
+ *
+ * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#if defined(__PLUGIN__) || defined(__BUILTIN__) || !defined(__LIBVLC__)
+# error This header file can only be included from LibVLC.
+#endif
+
+#ifndef _VOUT_INTERNAL_CONTROL_H
+#define _VOUT_INTERNAL_CONTROL_H
+
+/* */
+enum {
+#if 0
+ VOUT_CONTROL_INIT,
+ VOUT_CONTROL_EXIT,
+
+ /* */
+ VOUT_CONTROL_START,
+ VOUT_CONTROL_STOP,
+
+ /* */
+ VOUT_CONTROL_RESET,
+ VOUT_CONTROL_FLUSH,
+ VOUT_CONTROL_PAUSE,
+ VOUT_CONTROL_STEP,
+
+ /* Controls */
+ VOUT_CONTROL_FULLSCREEN,
+ VOUT_CONTROL_DISPLAY_FILLED,
+ VOUT_CONTROL_ZOOM,
+ VOUT_CONTROL_ON_TOP,
+
+ VOUT_CONTROL_SOURCE_ASPECT,
+ VOUT_CONTROL_SOURCE_CROP_BORDER,
+ VOUT_CONTROL_SOURCE_CROP_RATIO,
+ VOUT_CONTROL_SOURCE_CROP_WINDOW,
+
+ /* OSD */
+ VOUT_CONTROL_OSD_MESSAGE,
+ VOUT_CONTROL_OSD_TEXT,
+ VOUT_CONTROL_OSD_SLIDER,
+ VOUT_CONTROL_OSD_ICON,
+ VOUT_CONTROL_OSD_SUBPICTURE,
+#endif
+ VOUT_CONTROL_OSD_TITLE,
+};
+
+typedef struct {
+ int type;
+
+ union {
+ bool boolean;
+ mtime_t time;
+ struct {
+ int a;
+ int b;
+ } pair;
+ struct {
+ bool is_on;
+ mtime_t date;
+ } pause;
+ struct {
+ int channel;
+ char *string;
+ } message;
+#if 0
+ struct {
+ int channel;
+ char *string;
+ text_style_t *style;
+ int flags;
+ int hmargin;
+ int vmargin;
+ mtime_t start;
+ mtime_t stop;
+ } text;
+ struct {
+ unsigned left;
+ unsigned top;
+ unsigned right;
+ unsigned bottom;
+ } border;
+ struct {
+ unsigned x;
+ unsigned y;
+ unsigned width;
+ unsigned height;
+ } window;
+ struct {
+ int channel;
+ int type;
+ float position;
+ } slider;
+ struct {
+ int channel;
+ int icon;
+ } icon;
+ subpicture_t *subpicture;
+#endif
+ } u;
+} vout_control_cmd_t;
+
+void vout_control_cmd_Init(vout_control_cmd_t *, int type);
+void vout_control_cmd_Clean(vout_control_cmd_t *);
+
+typedef struct {
+ vlc_mutex_t lock;
+ vlc_cond_t wait_request;
+ vlc_cond_t wait_acknowledge;
+
+ /* */
+ bool is_dead;
+ bool is_sleeping;
+ bool can_sleep;
+ bool is_processing;
+ DECL_ARRAY(vout_control_cmd_t) cmd;
+} vout_control_t;
+
+/* */
+void vout_control_Init(vout_control_t *);
+void vout_control_Clean(vout_control_t *);
+
+/* controls outside of the vout thread */
+void vout_control_WaitEmpty(vout_control_t *);
+
+void vout_control_Push(vout_control_t *, vout_control_cmd_t *);
+void vout_control_PushVoid(vout_control_t *, int type);
+void vout_control_PushBool(vout_control_t *, int type, bool boolean);
+void vout_control_PushTime(vout_control_t *, int type, mtime_t time);
+void vout_control_PushMessage(vout_control_t *, int type, int channel, const char *string);
+void vout_control_PushPair(vout_control_t *, int type, int a, int b);
+void vout_control_Wake(vout_control_t *);
+
+/* control inside of the vout thread */
+int vout_control_Pop(vout_control_t *, vout_control_cmd_t *, mtime_t deadline, mtime_t timeout);
+void vout_control_Dead(vout_control_t *);
+
+#endif
+
video_format_FixRgb( &p_vout->fmt_in );
/* Initialize misc stuff */
+ vout_control_Init( &p_vout->p->control );
p_vout->p->i_changes = 0;
p_vout->p->b_fullscreen = 0;
vout_chrono_Init( &p_vout->p->render, 5, 10000 ); /* Arbitrary initial time */
vlc_mutex_destroy( &p_vout->p->picture_lock );
vlc_mutex_destroy( &p_vout->p->change_lock );
vlc_mutex_destroy( &p_vout->p->vfilter_lock );
+ vout_control_Clean( &p_vout->p->control );
/* */
vout_statistic_Clean( &p_vout->p->statistic );
if (p_vout->p->displayed.decoded)
p_vout->p->displayed.decoded->date += i_duration;
- vlc_cond_signal( &p_vout->p->picture_wait );
vlc_mutex_unlock( &p_vout->p->picture_lock );
+ vout_control_Wake( &p_vout->p->control );
+
spu_OffsetSubtitleDate( p_vout->p->p_spu, i_duration );
}
else
Flush(vout, date, false, false);
- vlc_cond_signal(&vout->p->picture_wait);
vlc_mutex_unlock(&vout->p->picture_lock);
+ vout_control_Wake(&vout->p->control);
}
void vout_Reset(vout_thread_t *vout)
vout->p->pause.is_on = false;
vout->p->pause.date = mdate();
- vlc_cond_signal( &vout->p->picture_wait );
vlc_mutex_unlock(&vout->p->picture_lock);
+ vout_control_Wake(&vout->p->control);
}
void vout_FixLeaks( vout_thread_t *vout )
/* */
picture_pool_NonEmpty(vout->p->decoder_pool, false);
- vlc_cond_signal(&vout->p->picture_wait);
vlc_mutex_unlock(&vout->p->picture_lock);
+ vout_control_Wake(&vout->p->control);
}
void vout_NextPicture(vout_thread_t *vout, mtime_t *duration)
{
vout->p->b_picture_empty = false;
vout->p->step.is_requested = true;
- /* FIXME I highly doubt that it can works with only one cond_t FIXME */
- vlc_cond_signal(&vout->p->picture_wait);
+ vlc_mutex_unlock(&vout->p->picture_lock);
+
+ vout_control_Wake(&vout->p->control);
+ vlc_mutex_lock(&vout->p->picture_lock);
while (vout->p->step.is_requested && !vout->p->b_picture_empty)
vlc_cond_wait(&vout->p->picture_wait, &vout->p->picture_lock);
* Main loop - it is not executed if an error occurred during
* initialization
*/
+ mtime_t deadline = VLC_TS_INVALID;
while (!vout->p->b_done && !vout->p->b_error) {
+ vout_control_cmd_t cmd;
+
+ vlc_mutex_unlock(&vout->p->change_lock);
+ /* FIXME remove thoses ugly timeouts
+ */
+ while (!vout_control_Pop(&vout->p->control, &cmd, deadline, 100000)) {
+ switch(cmd.type) {
+ default:
+ break;
+ }
+ vout_control_cmd_Clean(&cmd);
+ }
+ vlc_mutex_lock(&vout->p->change_lock);
+
/* */
- mtime_t deadline;
if (ThreadManage(vout, &deadline,
&interlacing, &postprocessing)) {
vout->p->b_error = true;
ThreadDisplayOsdTitle(vout);
ThreadChangeFilter(vout);
-
- vlc_mutex_unlock(&vout->p->change_lock);
-
- if (deadline > VLC_TS_INVALID) {
- vlc_mutex_lock(&vout->p->picture_lock);
- vlc_cond_timedwait(&vout->p->picture_wait, &vout->p->picture_lock, deadline);
- vlc_mutex_unlock(&vout->p->picture_lock);
- }
-
- vlc_mutex_lock(&vout->p->change_lock);
}
/*
if (has_wrapper)
vout_CloseWrapper(vout);
+ vout_control_Dead(&vout->p->control);
return NULL;
}
#include <vlc_picture_pool.h>
#include <vlc_vout_display.h>
#include "vout_control.h"
+#include "control.h"
#include "snapshot.h"
#include "statistic.h"
#include "chrono.h"
bool b_ready;
bool b_done;
bool b_error;
+ vout_control_t control;
/* */
struct {
p_pic->p_next = NULL;
picture_fifo_Push(p_vout->p->decoder_fifo, p_pic);
- vlc_cond_signal( &p_vout->p->picture_wait );
vlc_mutex_unlock( &p_vout->p->picture_lock );
+
+ vout_control_Wake( &p_vout->p->control);
}
/**
picture_Release( p_pic );
- vlc_cond_signal( &p_vout->p->picture_wait );
vlc_mutex_unlock( &p_vout->p->picture_lock );
+
+ vout_control_Wake( &p_vout->p->control);
}
/**