vlc/src/video_output/vout_intf.c

699 lines
25 KiB
C

/*****************************************************************************
* vout_intf.c : video output interface
*****************************************************************************
* Copyright (C) 2000-2007 VLC authors and VideoLAN
*
* Authors: Gildas Bazin <gbazin@videolan.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser 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.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <stdio.h>
#include <stdlib.h> /* free() */
#include <assert.h>
#include <vlc_block.h>
#include <vlc_modules.h>
#include <vlc_vout.h>
#include <vlc_vout_osd.h>
#include <vlc_strings.h>
#include <vlc_charset.h>
#include <vlc_spu.h>
#include <vlc_subpicture.h>
#include "vout_internal.h"
#include "snapshot.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
/* Object variables callbacks */
static int CropCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int CropBorderCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int AspectCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int AutoScaleCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int ZoomCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int AboveCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int WallPaperCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int FullscreenCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int SnapshotCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int VideoFilterCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int SubSourceCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int SubFilterCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int SubMarginCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int SecondarySubMarginCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int ViewpointCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
/*****************************************************************************
* vout_IntfInit: called during the vout creation to initialise misc things.
*****************************************************************************/
static const struct
{
double f_value;
char psz_label[13];
} p_zoom_values[] = {
{ 0.25, N_("1:4 Quarter") },
{ 0.5, N_("1:2 Half") },
{ 1, N_("1:1 Original") },
{ 2, N_("2:1 Double") },
};
static const struct
{
char psz_value[8];
char psz_label[8];
} p_crop_values[] = {
{ "", N_("Default") },
{ "16:10", "16:10" },
{ "16:9", "16:9" },
{ "4:3", "4:3" },
{ "185:100", "1.85:1" },
{ "221:100", "2.21:1" },
{ "235:100", "2.35:1" },
{ "239:100", "2.39:1" },
{ "5:3", "5:3" },
{ "5:4", "5:4" },
{ "1:1", "1:1" },
};
static const struct
{
char psz_value[8];
char psz_label[8];
} p_aspect_ratio_values[] = {
{ "", N_("Default") },
{ "16:9", "16:9" },
{ "4:3", "4:3" },
{ "1:1", "1:1" },
{ "16:10", "16:10" },
{ "221:100", "2.21:1" },
{ "235:100", "2.35:1" },
{ "239:100", "2.39:1" },
{ "5:4", "5:4" },
};
static void AddCustomRatios( vout_thread_t *p_vout, const char *psz_var,
char *psz_list )
{
assert( psz_list );
char *psz_cur = psz_list;
char *psz_next;
while( psz_cur && *psz_cur )
{
vlc_value_t val;
psz_next = strchr( psz_cur, ',' );
if( psz_next )
{
*psz_next = '\0';
psz_next++;
}
val.psz_string = psz_cur;
var_Change( p_vout, psz_var, VLC_VAR_ADDCHOICE, val,
(const char *)psz_cur );
psz_cur = psz_next;
}
}
enum vlc_video_fitting var_InheritFit(vlc_object_t *obj)
{
int64_t v = var_InheritInteger(obj, "fit");
/* Safe variable => paranoid checks */
switch (v) {
case VLC_VIDEO_FIT_SMALLER:
case VLC_VIDEO_FIT_LARGER:
case VLC_VIDEO_FIT_WIDTH:
case VLC_VIDEO_FIT_HEIGHT:
return v;
default:
return VLC_VIDEO_FIT_SMALLER;
}
}
void vout_CreateVars( vout_thread_t *p_vout )
{
vlc_value_t val;
char *psz_buf;
/* Create a few object variables we'll need later on */
var_Create( p_vout, "snapshot-num", VLC_VAR_INTEGER );
var_SetInteger( p_vout, "snapshot-num", 1 );
var_Create( p_vout, "width", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
var_Create( p_vout, "height", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
var_Create( p_vout, "align", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
var_Create( p_vout, "mouse-hide-timeout",
VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
/* Add variables to manage scaling video */
var_Create( p_vout, "autoscale", VLC_VAR_BOOL | VLC_VAR_DOINHERIT
| VLC_VAR_ISCOMMAND );
var_Create( p_vout, "zoom", VLC_VAR_FLOAT | VLC_VAR_ISCOMMAND |
VLC_VAR_DOINHERIT );
var_Change( p_vout, "zoom", VLC_VAR_SETTEXT, _("Zoom") );
for( size_t i = 0; i < ARRAY_SIZE(p_zoom_values); i++ )
{
val.f_float = p_zoom_values[i].f_value;
var_Change( p_vout, "zoom", VLC_VAR_ADDCHOICE, val,
vlc_gettext( p_zoom_values[i].psz_label ) );
}
/* Crop offset vars */
var_Create( p_vout, "crop-left", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
var_Create( p_vout, "crop-top", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
var_Create( p_vout, "crop-right", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
var_Create( p_vout, "crop-bottom", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
/* Crop object var */
var_Create( p_vout, "crop", VLC_VAR_STRING | VLC_VAR_ISCOMMAND |
VLC_VAR_DOINHERIT );
var_Change( p_vout, "crop", VLC_VAR_SETTEXT, _("Crop") );
for( size_t i = 0; i < ARRAY_SIZE(p_crop_values); i++ )
{
val.psz_string = (char*)p_crop_values[i].psz_value;
var_Change( p_vout, "crop", VLC_VAR_ADDCHOICE, val,
p_crop_values[i].psz_label );
}
/* Add custom crop ratios */
psz_buf = var_CreateGetNonEmptyString( p_vout, "custom-crop-ratios" );
if( psz_buf )
{
AddCustomRatios( p_vout, "crop", psz_buf );
free( psz_buf );
}
/* Monitor pixel aspect-ratio */
var_Create( p_vout, "monitor-par", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
/* Aspect-ratio object var */
var_Create( p_vout, "aspect-ratio", VLC_VAR_STRING | VLC_VAR_ISCOMMAND |
VLC_VAR_DOINHERIT );
var_Change( p_vout, "aspect-ratio", VLC_VAR_SETTEXT, _("Aspect ratio") );
for( size_t i = 0; i < ARRAY_SIZE(p_aspect_ratio_values); i++ )
{
val.psz_string = (char*)p_aspect_ratio_values[i].psz_value;
var_Change( p_vout, "aspect-ratio", VLC_VAR_ADDCHOICE, val,
vlc_gettext(p_aspect_ratio_values[i].psz_label) );
}
/* Add custom aspect ratios */
psz_buf = var_CreateGetNonEmptyString( p_vout, "custom-aspect-ratios" );
if( psz_buf )
{
AddCustomRatios( p_vout, "aspect-ratio", psz_buf );
free( psz_buf );
}
/* Add a variable to indicate if the window should be on top of others */
var_Create( p_vout, "video-on-top", VLC_VAR_BOOL | VLC_VAR_DOINHERIT
| VLC_VAR_ISCOMMAND );
var_Change( p_vout, "video-on-top", VLC_VAR_SETTEXT,
_("Always on top") );
/* Add a variable to indicate if the window should be below all others */
var_Create( p_vout, "video-wallpaper", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
/* Add a variable to indicate whether we want window decoration or not */
var_Create( p_vout, "video-deco", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
/* Add a fullscreen variable */
var_Create( p_vout, "fullscreen",
VLC_VAR_BOOL | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
var_Change( p_vout, "fullscreen", VLC_VAR_SETTEXT, _("Fullscreen") );
/* Add a snapshot variable */
var_Create( p_vout, "video-snapshot", VLC_VAR_VOID | VLC_VAR_ISCOMMAND );
var_Change( p_vout, "video-snapshot", VLC_VAR_SETTEXT, _("Snapshot") );
/* Add a video-filter variable */
var_Create( p_vout, "video-filter",
VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
/* Add a sub-source variable */
var_Create( p_vout, "sub-source",
VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
/* Add a sub-filter variable */
var_Create( p_vout, "sub-filter",
VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
/* Add sub-margin variable */
var_Create( p_vout, "sub-margin",
VLC_VAR_INTEGER | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
/* Add secondary-sub-margin variable (dual subtitles) */
var_Create( p_vout, "secondary-sub-margin",
VLC_VAR_INTEGER | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
var_AddCallback( p_vout, "secondary-sub-margin", SecondarySubMarginCallback, NULL );
/* Mouse coordinates */
var_Create( p_vout, "mouse-button-down", VLC_VAR_INTEGER );
var_Create( p_vout, "mouse-moved", VLC_VAR_COORDS );
/* Device orientation */
var_Create( p_vout, "viewpoint-moved", VLC_VAR_ADDRESS );
/* Viewpoint */
var_Create( p_vout, "viewpoint", VLC_VAR_ADDRESS );
var_Create( p_vout, "viewpoint-changeable", VLC_VAR_BOOL );
/* SPU in full window */
var_Create( p_vout, "spu-fill", VLC_VAR_BOOL | VLC_VAR_DOINHERIT
| VLC_VAR_ISCOMMAND );
}
void vout_IntfInit( vout_thread_t *p_vout )
{
var_AddCallback( p_vout, "autoscale", AutoScaleCallback, NULL );
var_AddCallback( p_vout, "zoom", ZoomCallback, NULL );
var_AddCallback( p_vout, "crop-left", CropBorderCallback, NULL );
var_AddCallback( p_vout, "crop-top", CropBorderCallback, NULL );
var_AddCallback( p_vout, "crop-right", CropBorderCallback, NULL );
var_AddCallback( p_vout, "crop-bottom", CropBorderCallback, NULL );
var_AddCallback( p_vout, "crop", CropCallback, NULL );
var_AddCallback( p_vout, "aspect-ratio", AspectCallback, NULL );
var_AddCallback( p_vout, "video-on-top", AboveCallback, NULL );
var_AddCallback( p_vout, "video-wallpaper", WallPaperCallback, NULL );
var_AddCallback( p_vout, "fullscreen", FullscreenCallback, NULL );
var_AddCallback( p_vout, "video-snapshot", SnapshotCallback, NULL );
var_AddCallback( p_vout, "video-filter", VideoFilterCallback, NULL );
var_AddCallback( p_vout, "sub-source", SubSourceCallback, NULL );
var_AddCallback( p_vout, "sub-filter", SubFilterCallback, NULL );
var_AddCallback( p_vout, "sub-margin", SubMarginCallback, NULL );
var_AddCallback( p_vout, "viewpoint", ViewpointCallback, NULL );
}
void vout_IntfReinit( vout_thread_t *p_vout )
{
var_TriggerCallback( p_vout, "video-on-top" );
var_TriggerCallback( p_vout, "video-wallpaper" );
var_TriggerCallback( p_vout, "video-filter" );
var_TriggerCallback( p_vout, "sub-source" );
var_TriggerCallback( p_vout, "sub-filter" );
/* !Warn those will trigger also vlc_player_vout_OSDCallback and
cause unwanted OSD on vout start. Filter out it there. */
var_TriggerCallback( p_vout, "sub-margin" );
var_TriggerCallback( p_vout, "secondary-sub-margin" );
}
void vout_IntfDeinit(vlc_object_t *obj)
{
var_DelCallback(obj, "viewpoint", ViewpointCallback, NULL);
var_DelCallback(obj, "sub-margin", SubMarginCallback, NULL);
var_DelCallback(obj, "secondary-sub-margin", SecondarySubMarginCallback, NULL);
var_DelCallback(obj, "sub-filter", SubFilterCallback, NULL);
var_DelCallback(obj, "sub-source", SubSourceCallback, NULL);
var_DelCallback(obj, "video-filter", VideoFilterCallback, NULL);
var_DelCallback(obj, "video-snapshot", SnapshotCallback, NULL);
var_DelCallback(obj, "fullscreen", FullscreenCallback, NULL);
var_DelCallback(obj, "video-wallpaper", WallPaperCallback, NULL);
var_DelCallback(obj, "video-on-top", AboveCallback, NULL);
var_DelCallback(obj, "aspect-ratio", AspectCallback, NULL);
var_DelCallback(obj, "crop", CropCallback, NULL);
var_DelCallback(obj, "crop-bottom", CropBorderCallback, NULL);
var_DelCallback(obj, "crop-right", CropBorderCallback, NULL);
var_DelCallback(obj, "crop-top", CropBorderCallback, NULL);
var_DelCallback(obj, "crop-left", CropBorderCallback, NULL);
var_DelCallback(obj, "zoom", ZoomCallback, NULL);
var_DelCallback(obj, "autoscale", AutoScaleCallback, NULL);
}
/*****************************************************************************
* vout_Snapshot: generates a snapshot.
*****************************************************************************/
/**
* This function will inject a subpicture into the vout with the provided
* picture
*/
static int VoutSnapshotPip( vout_thread_t *p_vout, picture_t *p_pic )
{
subpicture_t *p_subpic = subpicture_NewFromPicture( VLC_OBJECT(p_vout),
p_pic, VLC_CODEC_YUVA );
if( !p_subpic )
return VLC_EGENERIC;
/* FIXME SPU_DEFAULT_CHANNEL is not good (used by the text) but
* hardcoded 0 doesn't seem right */
p_subpic->i_channel = 0;
p_subpic->i_start = vlc_tick_now();
p_subpic->i_stop = p_subpic->i_start + VLC_TICK_FROM_SEC(4);
p_subpic->b_ephemer = true;
p_subpic->b_fade = true;
/* Reduce the picture to 1/4^2 of the screen */
p_subpic->i_original_picture_width *= 4;
p_subpic->i_original_picture_height *= 4;
vout_PutSubpicture( p_vout, p_subpic );
return VLC_SUCCESS;
}
/**
* This function will display the name and a PIP of the provided snapshot
*/
static void VoutOsdSnapshot( vout_thread_t *p_vout, picture_t *p_pic, const char *psz_filename )
{
msg_Dbg( p_vout, "snapshot taken (%s)", psz_filename );
vout_OSDMessage( p_vout, VOUT_SPU_CHANNEL_OSD, "%s", psz_filename );
if( var_InheritBool( p_vout, "snapshot-preview" ) )
{
if( VoutSnapshotPip( p_vout, p_pic ) )
msg_Warn( p_vout, "Failed to display snapshot" );
}
}
/**
* This function will handle a snapshot request
*/
static void VoutSaveSnapshot( vout_thread_t *p_vout )
{
char *psz_path = var_InheritString( p_vout, "snapshot-path" );
char *psz_format = var_InheritString( p_vout, "snapshot-format" );
char *psz_prefix = var_InheritString( p_vout, "snapshot-prefix" );
/* */
picture_t *p_picture;
block_t *p_image;
/* 500ms timeout
* XXX it will cause trouble with low fps video (< 2fps) */
if( vout_GetSnapshot( p_vout, &p_image, &p_picture, NULL, psz_format, VLC_TICK_FROM_MS(500) ) )
{
p_picture = NULL;
p_image = NULL;
goto exit;
}
if( !psz_path )
{
psz_path = vout_snapshot_GetDirectory();
if( !psz_path )
{
msg_Err( p_vout, "no path specified for snapshots" );
goto exit;
}
}
vout_snapshot_save_cfg_t cfg;
memset( &cfg, 0, sizeof(cfg) );
cfg.is_sequential = var_InheritBool( p_vout, "snapshot-sequential" );
cfg.sequence = var_GetInteger( p_vout, "snapshot-num" );
cfg.path = psz_path;
cfg.format = psz_format;
cfg.prefix_fmt = psz_prefix;
char *psz_filename;
int i_sequence;
if (vout_snapshot_SaveImage( &psz_filename, &i_sequence,
p_image, p_vout, &cfg ) )
goto exit;
if( cfg.is_sequential )
var_SetInteger( p_vout, "snapshot-num", i_sequence + 1 );
VoutOsdSnapshot( p_vout, p_picture, psz_filename );
/* signal creation of a new snapshot file */
var_SetString( vlc_object_instance(p_vout), "snapshot-file", psz_filename );
free( psz_filename );
exit:
if( p_image )
block_Release( p_image );
if( p_picture )
picture_Release( p_picture );
free( psz_prefix );
free( psz_format );
free( psz_path );
}
bool vout_ParseCrop(struct vout_crop *restrict cfg, const char *crop_str)
{
float fnum, fden;
if (sscanf(crop_str, "%u:%u", &cfg->ratio.num, &cfg->ratio.den) == 2) {
if (cfg->ratio.num != 0 && cfg->ratio.den != 0)
cfg->mode = VOUT_CROP_RATIO;
else
cfg->mode = VOUT_CROP_NONE;
} else if (sscanf(crop_str, "%ux%u+%u+%u",
&cfg->window.width, &cfg->window.height,
&cfg->window.x, &cfg->window.y) == 4) {
cfg->mode = VOUT_CROP_WINDOW;
} else if (sscanf(crop_str, "%u+%u+%u+%u",
&cfg->border.left, &cfg->border.top,
&cfg->border.right, &cfg->border.bottom) == 4) {
cfg->mode = VOUT_CROP_BORDER;
} else if (vlc_sscanf_c(crop_str, "%f:%f", &fnum, &fden) == 2) {
long num = lroundf(ldexp(fnum, 24/*-bit mantissa */));
long den = lroundf(ldexp(fden, 24));
long gcd = GCD(num, den);
cfg->mode = VOUT_CROP_RATIO;
cfg->ratio.num = num / gcd;
cfg->ratio.den = den / gcd;
} else if (*crop_str == '\0') {
cfg->mode = VOUT_CROP_NONE;
} else {
return false;
}
return true;
}
/*****************************************************************************
* Object variables callbacks
*****************************************************************************/
static int CropCallback( vlc_object_t *object, char const *cmd,
vlc_value_t oldval, vlc_value_t newval, void *data )
{
vout_thread_t *vout = (vout_thread_t *)object;
VLC_UNUSED(cmd); VLC_UNUSED(oldval); VLC_UNUSED(data);
struct vout_crop crop;
if (vout_ParseCrop(&crop, newval.psz_string))
vout_ChangeCrop(vout, &crop);
else
msg_Err(object, "Unknown crop format (%s)", newval.psz_string);
return VLC_SUCCESS;
}
static int CropBorderCallback(vlc_object_t *object, char const *cmd,
vlc_value_t oldval, vlc_value_t newval, void *data)
{
char buf[4 * 21];
snprintf(buf, sizeof (buf), "%"PRIu64"+%"PRIu64"+%"PRIu64"+%"PRIu64,
var_GetInteger(object, "crop-left"),
var_GetInteger(object, "crop-top"),
var_GetInteger(object, "crop-right"),
var_GetInteger(object, "crop-bottom"));
var_SetString(object, "crop", buf);
VLC_UNUSED(cmd); VLC_UNUSED(oldval); VLC_UNUSED(data); VLC_UNUSED(newval);
return VLC_SUCCESS;
}
bool GetAspectRatio(const char *ar_str, unsigned *num, unsigned *den)
{
if (sscanf(ar_str, "%u:%u", num, den) == 2 &&
(num != 0) == (den != 0))
return true;
else if (*ar_str == '\0') {
*num = *den = 0;
return true;
}
return false;
}
static int AspectCallback( vlc_object_t *object, char const *cmd,
vlc_value_t oldval, vlc_value_t newval, void *data )
{
vout_thread_t *vout = (vout_thread_t *)object;
VLC_UNUSED(cmd); VLC_UNUSED(oldval); VLC_UNUSED(data);
unsigned num, den;
if (GetAspectRatio(newval.psz_string, &num, &den))
vout_ChangeDisplayAspectRatio(vout, num, den);
return VLC_SUCCESS;
}
static int AutoScaleCallback( vlc_object_t *obj, char const *name,
vlc_value_t prev, vlc_value_t cur, void *data )
{
vout_thread_t *p_vout = (vout_thread_t *)obj;
enum vlc_video_fitting fit = cur.b_bool ? var_InheritFit(obj)
: VLC_VIDEO_FIT_NONE;
(void) name; (void) prev; (void) data;
vout_ChangeDisplayFitting(p_vout, fit);
return VLC_SUCCESS;
}
static int ZoomCallback( vlc_object_t *obj, char const *name,
vlc_value_t prev, vlc_value_t cur, void *data )
{
vout_thread_t *p_vout = (vout_thread_t *)obj;
(void) name; (void) prev; (void) data;
vout_ChangeZoom(p_vout, 1000 * cur.f_float, 1000);
return VLC_SUCCESS;
}
static int AboveCallback( vlc_object_t *obj, char const *name,
vlc_value_t prev, vlc_value_t cur, void *data )
{
vout_ChangeWindowState((vout_thread_t *)obj,
cur.b_bool ? VLC_WINDOW_STATE_ABOVE : VLC_WINDOW_STATE_NORMAL);
(void) name; (void) prev; (void) data;
return VLC_SUCCESS;
}
static int WallPaperCallback( vlc_object_t *obj, char const *name,
vlc_value_t prev, vlc_value_t cur, void *data )
{
vout_thread_t *vout = (vout_thread_t *)obj;
if( cur.b_bool )
{
vout_ChangeWindowState(vout, VLC_WINDOW_STATE_BELOW);
vout_ChangeFullscreen(vout, NULL);
}
else
{
var_TriggerCallback( obj, "fullscreen" );
var_TriggerCallback( obj, "video-on-top" );
}
(void) name; (void) prev; (void) data;
return VLC_SUCCESS;
}
static int FullscreenCallback( vlc_object_t *p_this, char const *psz_cmd,
vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
vout_thread_t *p_vout = (vout_thread_t *)p_this;
(void)psz_cmd; (void) oldval; (void)p_data;
if( newval.b_bool )
vout_ChangeFullscreen(p_vout, NULL);
else
vout_ChangeWindowed(p_vout);
return VLC_SUCCESS;
}
static int SnapshotCallback( vlc_object_t *p_this, char const *psz_cmd,
vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
vout_thread_t *p_vout = (vout_thread_t *)p_this;
VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval);
VLC_UNUSED(newval); VLC_UNUSED(p_data);
VoutSaveSnapshot( p_vout );
return VLC_SUCCESS;
}
static int VideoFilterCallback( vlc_object_t *p_this, char const *psz_cmd,
vlc_value_t oldval, vlc_value_t newval, void *p_data)
{
vout_thread_t *p_vout = (vout_thread_t *)p_this;
VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
vout_ControlChangeFilters( p_vout, newval.psz_string );
return VLC_SUCCESS;
}
static int SubSourceCallback( vlc_object_t *p_this, char const *psz_cmd,
vlc_value_t oldval, vlc_value_t newval, void *p_data)
{
vout_thread_t *p_vout = (vout_thread_t *)p_this;
VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
vout_ControlChangeSubSources( p_vout, newval.psz_string );
return VLC_SUCCESS;
}
static int SubFilterCallback( vlc_object_t *p_this, char const *psz_cmd,
vlc_value_t oldval, vlc_value_t newval, void *p_data)
{
vout_thread_t *p_vout = (vout_thread_t *)p_this;
VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
vout_ControlChangeSubFilters( p_vout, newval.psz_string );
return VLC_SUCCESS;
}
static int SubMarginCallback( vlc_object_t *p_this, char const *psz_cmd,
vlc_value_t oldval, vlc_value_t newval, void *p_data)
{
vout_thread_t *p_vout = (vout_thread_t *)p_this;
VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
vout_ChangeSpuChannelMargin(p_vout, VLC_VOUT_ORDER_PRIMARY, newval.i_int);
return VLC_SUCCESS;
}
static int SecondarySubMarginCallback( vlc_object_t *p_this, char const *psz_cmd,
vlc_value_t oldval, vlc_value_t newval, void *p_data)
{
vout_thread_t *p_vout = (vout_thread_t *)p_this;
VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
vout_ChangeSpuChannelMargin(p_vout, VLC_VOUT_ORDER_SECONDARY, newval.i_int);
return VLC_SUCCESS;
}
static int ViewpointCallback( vlc_object_t *p_this, char const *psz_cmd,
vlc_value_t oldval, vlc_value_t newval, void *p_data)
{
vout_thread_t *p_vout = (vout_thread_t *)p_this;
VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
if( newval.p_address != NULL )
vout_ChangeViewpoint(p_vout, newval.p_address);
return VLC_SUCCESS;
}