It basically works but they are some issues to be fixed.
*/
typedef struct {
vout_display_cfg_t cfg;
-
- bool is_on_top;
+ unsigned wm_state;
struct {
int num;
int den;
if (vout_display_Control(vd, VOUT_DISPLAY_CHANGE_FULLSCREEN, &cfg)) {
msg_Err(vd, "Failed to set fullscreen");
is_fullscreen = osys->cfg.is_fullscreen;
+ } else if (!is_fullscreen) {
+ vout_display_Control(vd, VOUT_DISPLAY_CHANGE_DISPLAY_SIZE, &cfg, true);
}
osys->cfg.is_fullscreen = is_fullscreen;
vout_display_cfg_t *cfg = &osys->cfg;
*cfg = state->cfg;
- osys->wm_state_initial = VOUT_WINDOW_STATE_NORMAL;
+ osys->wm_state_initial = -1;
osys->sar_initial.num = state->sar.num;
osys->sar_initial.den = state->sar.den;
vout_display_GetDefaultDisplaySize(&cfg->display.width, &cfg->display.height,
osys->mouse.double_click_timeout = double_click_timeout;
osys->mouse.hide_timeout = hide_timeout;
osys->is_fullscreen = cfg->is_fullscreen;
- osys->width_saved =
osys->display_width = cfg->display.width;
- osys->height_saved =
osys->display_height = cfg->display.height;
osys->is_display_filled = cfg->is_display_filled;
+ osys->width_saved = cfg->display.width;
+ osys->height_saved = cfg->display.height;
+ if (osys->is_fullscreen) {
+ vout_display_cfg_t cfg_windowed = *cfg;
+ cfg_windowed.is_fullscreen = false;
+ cfg_windowed.display.width = 0;
+ cfg_windowed.display.height = 0;
+ vout_display_GetDefaultDisplaySize(&osys->width_saved,
+ &osys->height_saved,
+ source_org, &cfg_windowed);
+ }
osys->zoom.num = cfg->zoom.num;
osys->zoom.den = cfg->zoom.den;
- osys->wm_state = state->is_on_top ? VOUT_WINDOW_STATE_ABOVE
- : VOUT_WINDOW_STATE_NORMAL;
+ osys->wm_state = state->wm_state;
osys->fit_window = 0;
osys->source = *source_org;
if (state) {
if (!osys->is_wrapper )
state->cfg = osys->cfg;
- state->is_on_top = (osys->wm_state & VOUT_WINDOW_STATE_ABOVE) != 0;
- state->sar.num = osys->sar_initial.num;
- state->sar.den = osys->sar_initial.den;
+ state->wm_state = osys->wm_state;
+ state->sar.num = osys->sar_initial.num;
+ state->sar.den = osys->sar_initial.den;
}
VoutDisplayDestroyRender(vd);
}
}
#endif
-vout_window_t * vout_NewDisplayWindow(vout_thread_t *vout, vout_display_t *vd, const vout_window_cfg_t *cfg)
-{
- VLC_UNUSED(vd);
- vout_window_cfg_t cfg_override = *cfg;
-
- if( !var_InheritBool( vout, "embedded-video" ) )
- cfg_override.is_standalone = true;
-
- return vout_window_New(VLC_OBJECT(vout), NULL, &cfg_override);
-}
-void vout_DeleteDisplayWindow(vout_thread_t *vout, vout_display_t *vd, vout_window_t *window)
-{
- VLC_UNUSED(vout);
- VLC_UNUSED(vd);
- vout_window_Delete(window);
-}
filters);
}
+/* */
+static void VoutGetDisplayCfg(vout_thread_t *vout, vout_display_cfg_t *cfg, const char *title)
+{
+ /* Load configuration */
+ cfg->is_fullscreen = var_CreateGetBool(vout, "fullscreen");
+ cfg->display.title = title;
+ const int display_width = var_CreateGetInteger(vout, "width");
+ const int display_height = var_CreateGetInteger(vout, "height");
+ cfg->display.width = display_width > 0 ? display_width : 0;
+ cfg->display.height = display_height > 0 ? display_height : 0;
+ cfg->is_display_filled = var_CreateGetBool(vout, "autoscale");
+ cfg->display.sar.num = 1; /* TODO monitor AR */
+ cfg->display.sar.den = 1;
+ unsigned zoom_den = 1000;
+ unsigned zoom_num = zoom_den * var_CreateGetFloat(vout, "scale");
+ vlc_ureduce(&zoom_num, &zoom_den, zoom_num, zoom_den, 0);
+ cfg->zoom.num = zoom_num;
+ cfg->zoom.den = zoom_den;
+ cfg->align.vertical = VOUT_DISPLAY_ALIGN_CENTER;
+ cfg->align.horizontal = VOUT_DISPLAY_ALIGN_CENTER;
+ const int align_mask = var_CreateGetInteger(vout, "align");
+ if (align_mask & 0x1)
+ cfg->align.horizontal = VOUT_DISPLAY_ALIGN_LEFT;
+ else if (align_mask & 0x2)
+ cfg->align.horizontal = VOUT_DISPLAY_ALIGN_RIGHT;
+ if (align_mask & 0x4)
+ cfg->align.horizontal = VOUT_DISPLAY_ALIGN_TOP;
+ else if (align_mask & 0x8)
+ cfg->align.horizontal = VOUT_DISPLAY_ALIGN_BOTTOM;
+}
+
+vout_window_t * vout_NewDisplayWindow(vout_thread_t *vout, vout_display_t *vd,
+ const vout_window_cfg_t *cfg)
+{
+ VLC_UNUSED(vd);
+ vout_window_cfg_t cfg_override = *cfg;
+
+ if (!var_InheritBool( vout, "embedded-video"))
+ cfg_override.is_standalone = true;
+
+ if (vout->p->window.is_unused && vout->p->window.object) {
+ assert(!vout->p->splitter_name);
+ if (!cfg_override.is_standalone == !vout->p->window.cfg.is_standalone &&
+ cfg_override.type == vout->p->window.cfg.type) {
+ /* Reuse the stored window */
+ msg_Dbg(vout, "Reusing previous vout window");
+ vout_window_t *window = vout->p->window.object;
+ if (cfg_override.width != vout->p->window.cfg.width ||
+ cfg_override.height != vout->p->window.cfg.height)
+ vout_window_SetSize(window,
+ cfg_override.width, cfg_override.height);
+ vout->p->window.is_unused = false;
+ vout->p->window.cfg = cfg_override;
+ return window;
+ }
+
+ vout_window_Delete(vout->p->window.object);
+ vout->p->window.is_unused = true;
+ vout->p->window.object = NULL;
+ }
+
+ vout_window_t *window = vout_window_New(VLC_OBJECT(vout), NULL,
+ &cfg_override);
+ if (!window)
+ return NULL;
+ if (!vout->p->splitter_name) {
+ vout->p->window.is_unused = false;
+ vout->p->window.cfg = cfg_override;
+ vout->p->window.object = window;
+ }
+ return window;
+}
+
+void vout_DeleteDisplayWindow(vout_thread_t *vout, vout_display_t *vd,
+ vout_window_t *window)
+{
+ VLC_UNUSED(vd);
+ if (!vout->p->window.is_unused && vout->p->window.object == window)
+ vout->p->window.is_unused = true;
+ else
+ vout_window_Delete(window);
+}
+
/* */
static picture_t *VoutVideoFilterNewPicture(filter_t *filter)
{
source->i_visible_height);
}
-static int ThreadStart(vout_thread_t *vout)
+static int ThreadStart(vout_thread_t *vout, const vout_display_state_t *state)
{
vlc_mouse_Init(&vout->p->mouse);
vout->p->decoder_fifo = picture_fifo_New();
filter_chain_New( vout, "video filter2", false,
VoutVideoFilterAllocationSetup, NULL, vout);
- if (vout_OpenWrapper(vout, vout->p->splitter_name))
+ vout_display_state_t state_default;
+ if (!state) {
+ VoutGetDisplayCfg(vout, &state_default.cfg, vout->p->display.title);
+ state_default.wm_state = var_CreateGetBool(vout, "video-on-top") ? VOUT_WINDOW_STATE_ABOVE :
+ VOUT_WINDOW_STATE_NORMAL;
+ state_default.sar.num = 0;
+ state_default.sar.den = 0;
+
+ state = &state_default;
+ }
+
+ if (vout_OpenWrapper(vout, vout->p->splitter_name, state))
return VLC_EGENERIC;
if (vout_InitWrapper(vout))
return VLC_EGENERIC;
return VLC_SUCCESS;
}
-static void ThreadStop(vout_thread_t *vout)
+static void ThreadStop(vout_thread_t *vout, vout_display_state_t *state)
{
/* Destroy the video filters2 */
filter_chain_Delete(vout->p->vfilter_chain);
ThreadFlush(vout, true, INT64_MAX);
vout_EndWrapper(vout);
}
- vout_CloseWrapper(vout);
+ vout_CloseWrapper(vout, state);
}
if (vout->p->decoder_fifo)
static void ThreadInit(vout_thread_t *vout)
{
- vout->p->dead = false;
- vout->p->is_late_dropped = var_InheritBool(vout, "drop-late-frames");
- vout->p->pause.is_on = false;
- vout->p->pause.date = VLC_TS_INVALID;
+ vout->p->window.is_unused = true;
+ vout->p->window.object = NULL;
+ vout->p->dead = false;
+ vout->p->is_late_dropped = var_InheritBool(vout, "drop-late-frames");
+ vout->p->pause.is_on = false;
+ vout->p->pause.date = VLC_TS_INVALID;
vout_chrono_Init(&vout->p->render, 5, 10000); /* Arbitrary initial time */
}
static void ThreadClean(vout_thread_t *vout)
{
+ if (vout->p->window.object) {
+ assert(vout->p->window.is_unused);
+ vout_window_Delete(vout->p->window.object);
+ }
vout_chrono_Clean(&vout->p->render);
vout->p->dead = true;
vout_control_Dead(&vout->p->control);
{
video_format_t original;
if (VoutValidateFormat(&original, fmt)) {
- ThreadStop(vout);
+ ThreadStop(vout, NULL);
ThreadClean(vout);
return VLC_EGENERIC;
}
if (video_format_IsSimilar(&original, &vout->p->original))
return VLC_SUCCESS;
- ThreadStop(vout);
+ vout_display_state_t state;
+ memset(&state, 0, sizeof(state));
+
+ ThreadStop(vout, &state);
+
+ if (!state.cfg.is_fullscreen) {
+ state.cfg.display.width = 0;
+ state.cfg.display.height = 0;
+ }
+ state.sar.num = 0;
+ state.sar.den = 0;
+ /* FIXME current vout "variables" are not in sync here anymore
+ * and I am not sure what to do */
vout->p->original = original;
- if (ThreadStart(vout)) {
+ if (ThreadStart(vout, &state)) {
ThreadClean(vout);
return VLC_EGENERIC;
}
switch(cmd.type) {
case VOUT_CONTROL_INIT:
ThreadInit(vout);
- if (ThreadStart(vout)) {
- ThreadStop(vout);
+ if (ThreadStart(vout, NULL)) {
+ ThreadStop(vout, NULL);
ThreadClean(vout);
return NULL;
}
break;
case VOUT_CONTROL_CLEAN:
- ThreadStop(vout);
+ ThreadStop(vout, NULL);
ThreadClean(vout);
return NULL;
case VOUT_CONTROL_REINIT:
#include <vlc_picture_fifo.h>
#include <vlc_picture_pool.h>
#include <vlc_vout_display.h>
+#include <vlc_vout_wrapper.h>
#include "vout_control.h"
#include "control.h"
#include "snapshot.h"
unsigned int i_par_num;
unsigned int i_par_den;
+ /* Video output window */
+ struct {
+ bool is_unused;
+ vout_window_cfg_t cfg;
+ vout_window_t *object;
+ } window;
+
/* Thread & synchronization */
vlc_thread_t thread;
bool dead;
void vout_IntfInit( vout_thread_t * );
/* */
-int vout_OpenWrapper (vout_thread_t *, const char *);
-void vout_CloseWrapper(vout_thread_t *);
+int vout_OpenWrapper (vout_thread_t *, const char *, const vout_display_state_t *);
+void vout_CloseWrapper(vout_thread_t *, vout_display_state_t *);
int vout_InitWrapper(vout_thread_t *);
void vout_EndWrapper(vout_thread_t *);
void vout_ManageWrapper(vout_thread_t *);
/*****************************************************************************
* Local prototypes
*****************************************************************************/
-static void VoutGetDisplayCfg(vout_thread_t *,
- vout_display_cfg_t *, const char *title);
#ifdef WIN32
static int Forward(vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void *);
/*****************************************************************************
*
*****************************************************************************/
-int vout_OpenWrapper(vout_thread_t *vout, const char *name)
+int vout_OpenWrapper(vout_thread_t *vout,
+ const char *name, const vout_display_state_t *state)
{
vout_thread_sys_t *sys = vout->p;
msg_Dbg(vout, "Opening vout display wrapper");
source.i_x_offset = 0;
source.i_y_offset = 0;
- vout_display_state_t state;
- VoutGetDisplayCfg(vout, &state.cfg, sys->display.title);
- state.is_on_top = var_CreateGetBool(vout, "video-on-top");
- state.sar.num = 0;
- state.sar.den = 0;
-
const mtime_t double_click_timeout = 300000;
const mtime_t hide_timeout = var_CreateGetInteger(vout, "mouse-hide-timeout") * 1000;
- sys->display.vd = vout_NewDisplay(vout, &source, &state, name ? name : "$vout",
+ sys->display.vd = vout_NewDisplay(vout, &source, state, name ? name : "$vout",
double_click_timeout, hide_timeout);
/* If we need to video filter and it fails, then try a splitter
* XXX it is a hack for now FIXME */
if (name && !sys->display.vd)
- sys->display.vd = vout_NewSplitter(vout, &source, &state, "$vout", name,
+ sys->display.vd = vout_NewSplitter(vout, &source, state, "$vout", name,
double_click_timeout, hide_timeout);
if (!sys->display.vd) {
free(sys->display.title);
/*****************************************************************************
*
*****************************************************************************/
-void vout_CloseWrapper(vout_thread_t *vout)
+void vout_CloseWrapper(vout_thread_t *vout, vout_display_state_t *state)
{
vout_thread_sys_t *sys = vout->p;
#endif
sys->decoder_pool = NULL; /* FIXME remove */
- vout_DeleteDisplay(sys->display.vd, NULL);
+ vout_DeleteDisplay(sys->display.vd, state);
free(sys->display.title);
}
sys->display.filtered = NULL;
}
-static void VoutGetDisplayCfg(vout_thread_t *vout, vout_display_cfg_t *cfg, const char *title)
-{
- /* Load configuration */
- cfg->is_fullscreen = var_CreateGetBool(vout, "fullscreen");
- cfg->display.title = title;
- const int display_width = var_CreateGetInteger(vout, "width");
- const int display_height = var_CreateGetInteger(vout, "height");
- cfg->display.width = display_width > 0 ? display_width : 0;
- cfg->display.height = display_height > 0 ? display_height : 0;
- cfg->is_display_filled = var_CreateGetBool(vout, "autoscale");
- cfg->display.sar.num = 1; /* TODO monitor AR */
- cfg->display.sar.den = 1;
- unsigned zoom_den = 1000;
- unsigned zoom_num = zoom_den * var_CreateGetFloat(vout, "scale");
- vlc_ureduce(&zoom_num, &zoom_den, zoom_num, zoom_den, 0);
- cfg->zoom.num = zoom_num;
- cfg->zoom.den = zoom_den;
- cfg->align.vertical = VOUT_DISPLAY_ALIGN_CENTER;
- cfg->align.horizontal = VOUT_DISPLAY_ALIGN_CENTER;
- const int align_mask = var_CreateGetInteger(vout, "align");
- if (align_mask & 0x1)
- cfg->align.horizontal = VOUT_DISPLAY_ALIGN_LEFT;
- else if (align_mask & 0x2)
- cfg->align.horizontal = VOUT_DISPLAY_ALIGN_RIGHT;
- if (align_mask & 0x4)
- cfg->align.horizontal = VOUT_DISPLAY_ALIGN_TOP;
- else if (align_mask & 0x8)
- cfg->align.horizontal = VOUT_DISPLAY_ALIGN_BOTTOM;
-}
-
#ifdef WIN32
static int Forward(vlc_object_t *object, char const *var,
vlc_value_t oldval, vlc_value_t newval, void *data)