www.pudn.com > kceasy-0.19-rc1-src.rar > svlc_interface.c


/***************************************************************************** 
 * svlc_interface.c: a simple shared library wrapper around libvlc 
 ***************************************************************************** 
 * Copyright (C) 2004 Markus Kern  
 * 
 * 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., 59 Temple Place - Suite 330, Boston, MA  02111, USA. 
 *****************************************************************************/ 
 
/***************************************************************************** 
 * Preamble 
 *****************************************************************************/ 
#include "config.h" 
 
#include  
 
#define __BUILTIN__ 
#define __VLC__ 
 
#include  
#include  
#include  
#include  
#include  
#include  
 
#include "svlc_interface.h" 
#include "svlc_event.h" 
 
 
#define VOUT_PLUGINS "directx,dummy" 
#define AOUT_PLUGINS "directx,waveout,dummy" 
#define VLC_PLUGIN_DIR "vlcplugins" 
#define VLC_CONFIG_FILE "vlc.conf" 
 
 
/****************************************************************************** 
 * Some internal helper functions 
 *****************************************************************************/ 
 
/** 
 * This resides in libvcl.c but is not in the headers. 
 */ 
vlc_t * vlc_current_object (int i_object); 
 
 
static vlc_t * aquire_vlc (HSVLC svlc) 
{ 
    vlc_t *vlc; 
 
	if (!svlc) 
		return NULL; 
 
    if (!(vlc = vlc_current_object (svlc->vlc))) 
        return NULL; 
 
	return vlc; 
} 
 
static void release_vlc (vlc_t *vlc) 
{ 
    vlc_object_release (vlc); 
} 
 
/***************************************************************************** 
 * Instance management 
 *****************************************************************************/ 
 
/** 
 * Create simplevlc instance. 
 * 
 * @param verbosity  >= 0 Logging verbosity. 
 *                     -1 Quiet, don't log anything. 
 * 
 * @return  Handle  to instance on success. 
 *          NULL on error. 
 */ 
static HSVLC SVLC_CC if_create (int verbosity) 
{ 
	SVlcInstance *svlc; 
    vlc_t *vlc; 
	int ret; 
	vlc_value_t val; 
 
#ifdef DEBUG 
	char *ppsz_argv[] = { "vlc", 
	                      "--config=" VLC_CONFIG_FILE, 
	                      "--plugin-path=" VLC_PLUGIN_DIR, 
	                      "--vout=" VOUT_PLUGINS, 
	                      "--aout=" AOUT_PLUGINS, 
						  "--no-plugins-cache", 
	                      "--intf=none", 
	                      "--fast-mutex", 
	                      "--win9x-cv-method=1" };  
#else 
	char *ppsz_argv[] = { "vlc", 
	                      "--config=" VLC_CONFIG_FILE, 
	                      "--plugin-path=" VLC_PLUGIN_DIR, 
	                      "--vout=" VOUT_PLUGINS, 
	                      "--aout=" AOUT_PLUGINS, 
						  "--no-plugins-cache", 
	                      "--intf=none" }; 
#endif 
 
	if ((svlc = malloc (sizeof (SVlcInstance))) == NULL) 
		return NULL; 
 
	svlc->callback = NULL; 
	svlc->cb_events = 0; 
	svlc->udata = NULL; 
	svlc->playback_state = SVLC_PLAYBACK_CLOSED; 
	svlc->saved_volume = -1; 
 
    if((svlc->vlc = VLC_Create()) < 0) 
	{ 
		free (svlc); 
		return NULL; 
	} 
 
    if((ret = VLC_Init(svlc->vlc, sizeof(ppsz_argv)/sizeof(char*), ppsz_argv)) != VLC_SUCCESS) 
	{ 
        VLC_Destroy (svlc->vlc); 
		free (svlc); 
		return NULL; 
	} 
 
	/* set verbosity */ 
	val.i_int = verbosity; 
	VLC_VariableSet (svlc->vlc, "verbose", val); 
 
	/* add logger interface if verbosity not set to quiet */ 
	if (verbosity >= 0) 
	{ 
		VLC_AddIntf (svlc->vlc, "logger,none", VLC_FALSE, VLC_FALSE); 
	} 
 
    if (!(vlc = aquire_vlc (svlc))) 
	{ 
        VLC_Destroy (svlc->vlc); 
		free (svlc); 
		return NULL; 
	} 
 
	/* create some vars so we start in a consistent state */ 
    var_Create (vlc, "scale", VLC_VAR_BOOL); 
	val.b_bool = VLC_TRUE; 
	var_Set (vlc, "scale", val); 
 
    var_Create (vlc, "fullscreen", VLC_VAR_BOOL); 
	val.b_bool = VLC_FALSE; 
	var_Set (vlc, "fullscreen", val); 
 
    var_Create (vlc, "zoom", VLC_VAR_FLOAT); 
	val.f_float = 1.0; 
	var_Set (vlc, "zoom", val); 
 
    release_vlc (vlc); 
 
	return svlc; 
} 
 
/** 
 * Destroy simplevlc instance. 
 */ 
static void SVLC_CC if_destroy (HSVLC svlc) 
{ 
	if (!svlc) 
		return; 
 
	/* Don't ask me why there are three functions */ 
	VLC_Die (svlc->vlc); 
	VLC_CleanUp (svlc->vlc); 
	VLC_Destroy (svlc->vlc); 
 
	free (svlc); 
} 
 
/** 
 * Set callback function. 
 * 
 * @param callback  The function that should be called. 
 * @param events    The events you want to be notified about. 
 * 
 * @return  0 Success. 
 *         -1 Error. 
 */ 
static int SVLC_CC if_set_callback (HSVLC svlc, SVlcCallbackFunc callback, unsigned int events) 
{ 
    vlc_t *vlc; 
 
    if (!(vlc = aquire_vlc (svlc))) 
        return -1; 
 
	/* remove any previously registered vlc callbacks */ 
	if (!svlc_event_unregister_callbacks (svlc, vlc)) 
	{ 
	    release_vlc (vlc); 
		return -1; 
	} 
 
	svlc->callback = NULL; 
	svlc->cb_events = 0; 
 
	if (callback != NULL) 
	{ 
		/* set new func and events */ 
		svlc->callback = callback; 
		svlc->cb_events = events; 
 
		/* register vlc callbacks */ 
		if (!svlc_event_register_callbacks (svlc, vlc)) 
		{ 
			release_vlc (vlc); 
			return -1; 
		} 
	} 
 
    release_vlc (vlc); 
     
	return 0; 
} 
 
/** 
 * Return static VLC version string. 
 */ 
static char const * SVLC_CC if_get_vlc_version (void) 
{ 
	return VERSION_MESSAGE; 
} 
 
/** 
 * Retrieve user data. 
 */ 
static void * SVLC_CC if_get_udata (HSVLC svlc) 
{ 
	if (!svlc) 
		return NULL; 
 
	return svlc->udata; 
} 
 
/** 
 * Attach user data. 
 */ 
static void SVLC_CC if_set_udata (HSVLC svlc, void *udata) 
{ 
	if (!svlc) 
		return; 
 
	svlc->udata = udata; 
} 
 
 
/***************************************************************************** 
 * Video output 
 *****************************************************************************/ 
 
/** 
 * Set video output window. 
 * 
 * @param window  Window for video output (HWND on windows). 
 * 
 * @return  0 Success. 
 *         -1 Error. 
 */ 
static int SVLC_CC if_set_window (HSVLC svlc, unsigned int window) 
{ 
    vlc_t *vlc; 
	vlc_value_t value; 
 
    if (!(vlc = aquire_vlc (svlc))) 
        return -1; 
 
    value.i_int = (int) (ptrdiff_t) (void *) window; 
	var_Set (vlc, "drawable", value); 
 
    release_vlc (vlc); 
     
	return 0; 
} 
 
/** 
 * Set visualization plugin used for audio playback. 
 * 
 * @param name  Name of the visualization plugin, e.g. "goom". NULL removes 
 *              anything previously set. 
 * 
 * @return  0 Success. 
 *         -1 Error. 
 */ 
static int SVLC_CC if_set_visualization (HSVLC svlc, const char *name) 
{ 
    vlc_t *vlc; 
	vlc_value_t value; 
    aout_instance_t *aout; 
 
    if (!(vlc = aquire_vlc (svlc))) 
        return -1; 
 
    if ((aout = vlc_object_find (vlc, VLC_OBJECT_AOUT, FIND_CHILD)) && 
		var_Type (aout, "visual") != 0) 
    { 
		msg_Dbg (vlc, "Setting visualization '%s' directly with aout", name); 
 
		value.psz_string = (name != NULL) ? (char *)name : ""; 
		var_Set (aout, "visual", value); 
 
		vlc_object_release (aout); 
    } 
	else 
	{ 
		/* HACKHACK: Set filter directly in vlc object which is inherited by 
		 * future aouts. 
		 * 
		 * FIXME: Does this really work? 
		 */ 
		char *p; 
 
		/* Can happen because of the above ANDed if clause. */ 
		if (aout) 
			vlc_object_release (aout); 
 
		if (var_Type (vlc, "audio-filter") == 0) 
			var_Create (vlc, "audio-filter", VLC_VAR_STRING); 
 
		var_Get (vlc, "audio-filter", &value); 
		 
		if (!value.psz_string) 
			value.psz_string = strdup(""); 
 
		if ((p = strstr (value.psz_string, name))) 
		{ 
			/* remove if requested */ 
			if (name == NULL) 
			{ 
				char *rest = p + strlen(name) + ((p[strlen(name)] == ',') ? 1 : 0); 
				memmove (p, rest, strlen(rest) + 1); 
				var_Set (vlc, "audio-filter", value); 
			} 
		} 
		else 
		{ 
			/* add if requested */ 
			if (name != NULL) 
			{ 
				char *tmp = value.psz_string; 
		 
				asprintf (&value.psz_string, 
				          (value.psz_string[0] != '\0') ? "%s,%s" : "%s%s", 
		                  value.psz_string, name); 
				free (tmp); 
				var_Set (vlc, "audio-filter", value); 
			} 
		} 
 
        free (value.psz_string); 
	} 
 
    release_vlc (vlc); 
     
	return 0; 
} 
 
/** 
 * Get fullscreen mode. 
 * 
 * @return  1 Fullscreen on. 
 *          0 Fullscreen off. 
 *         -1 Error. 
 */ 
static int SVLC_CC if_get_fullscreen (HSVLC svlc) 
{ 
    vlc_t *vlc; 
    vout_thread_t *vout; 
    playlist_t *playlist; 
	vlc_value_t val; 
	int ret = VLC_ENOVAR; 
 
    if (!(vlc = aquire_vlc (svlc))) 
        return -1; 
 
    if ((vout = vlc_object_find (vlc, VLC_OBJECT_VOUT, FIND_CHILD))) 
    { 
		ret = var_Get (vout, "fullscreen", &val); 
        vlc_object_release (vout); 
    } 
    else if ((playlist = vlc_object_find (vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD))) 
    { 
		ret = var_Get (playlist, "fullscreen", &val); 
        vlc_object_release (playlist); 
    } 
 
	if (ret != VLC_SUCCESS) 
		ret = var_Get (vlc, "fullscreen", &val); 
  
    release_vlc (vlc); 
     
	return (ret == VLC_SUCCESS) ? val.b_bool : -1; 
} 
 
/** 
 * Set fullscreen mode. This merely maximizes the output window on windows 
 * (probably other platforms too) so you need to set fitwindow to true and 
 * the window set with set_window must have no (non-maximized) parents. 
 * 
 * @param fullscreen  1 Switch fullscreen on 
 *                    0 Switch fullscreen off 
 *                   -1 Toggle fullscreen 
 * 
 * @return  0 Success. 
 *         -1 Error. 
 */ 
static int SVLC_CC if_set_fullscreen (HSVLC svlc, int fullscreen) 
{ 
    vlc_t *vlc; 
    vout_thread_t *vout; 
    playlist_t *playlist; 
	vlc_value_t val; 
	int current; 
 
	if((current = if_get_fullscreen (svlc)) < 0) 
		return -1; 
 
	if (fullscreen == -1) 
		val.b_bool = (current == 0); 
	else if (current != fullscreen) 
		val.b_bool = (fullscreen != 0); 
	else 
		return 0; /* the specified state is already set */ 
 
    if (!(vlc = aquire_vlc (svlc))) 
        return -1; 
 
    if ((vout = vlc_object_find (vlc, VLC_OBJECT_VOUT, FIND_CHILD))) 
    { 
		/* setting this negates the actual fullscreen while ignoring val */ 
		var_Set (vout, "fullscreen", val); 
	    vlc_object_release (vout); 
    } 
 
    if ((playlist = vlc_object_find (vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD))) 
    { 
		var_Set (playlist, "fullscreen", val); 
        vlc_object_release (playlist); 
    } 
 
	var_Set (vlc, "fullscreen", val); 
 
    release_vlc (vlc); 
     
	return 0; 
} 
 
/** 
 * Get fit to window mode. 
 * 
 * @return  1 Fitting on. 
 *          0 Fitting off. 
 *         -1 Error. 
 */ 
static int SVLC_CC if_get_fitwindow (HSVLC svlc) 
{ 
    vlc_t *vlc; 
    vout_thread_t *vout; 
    playlist_t *playlist; 
	vlc_value_t val; 
	int ret = VLC_ENOVAR; 
 
    if (!(vlc = aquire_vlc (svlc))) 
        return -1; 
 
    if ((vout = vlc_object_find (vlc, VLC_OBJECT_VOUT, FIND_CHILD))) 
    { 
		ret = var_Get (vout, "scale", &val); 
        vlc_object_release (vout); 
    } 
    else if ((playlist = vlc_object_find (vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD))) 
    { 
		ret = var_Get (playlist, "scale", &val); 
        vlc_object_release (playlist); 
    } 
 
	if (ret != VLC_SUCCESS) 
		ret = var_Get (vlc, "scale", &val); 
 
    release_vlc (vlc); 
     
	return (ret == VLC_SUCCESS) ? val.b_bool : -1; 
} 
 
/** 
 * Scale video output to match window size. 
 * 
 * @param fullscreen  1 Fit to window. 
 *                    0 Don't fit to window. 
 *                   -1 Toggle fit. 
 * 
 * @return  0 Success. 
 *         -1 Error. 
 */ 
static int SVLC_CC if_set_fitwindow (HSVLC svlc, int fit) 
{ 
    vlc_t *vlc; 
    vout_thread_t *vout; 
    playlist_t *playlist; 
	vlc_value_t val; 
	int current; 
 
	if((current = if_get_fitwindow (svlc)) < 0) 
		return -1; 
 
	if (fit == -1) 
		val.b_bool = (current == 0); 
	else if (current != fit) 
		val.b_bool = (fit != 0); 
	else 
		return 0; /* the specified state is already set */ 
 
    if (!(vlc = aquire_vlc (svlc))) 
        return -1; 
 
    if ((vout = vlc_object_find (vlc, VLC_OBJECT_VOUT, FIND_CHILD))) 
    { 
		var_Set (vout, "scale", val); 
	    vlc_object_release (vout); 
    } 
 
    if ((playlist = vlc_object_find (vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD))) 
    { 
		var_Set (playlist, "scale", val); 
        vlc_object_release (playlist); 
    } 
 
	var_Set (vlc, "scale", val); 
 
    release_vlc (vlc); 
     
	return 0; 
} 
 
/** 
 * Get current zoom factor. 
 * 
 * @return >= 0 Current zoom factor. 
 *           -1 Error. 
 */ 
static float SVLC_CC if_get_zoom (HSVLC svlc) 
{ 
    vlc_t *vlc; 
    vout_thread_t *vout; 
    playlist_t *playlist; 
	vlc_value_t val; 
	int ret = VLC_SUCCESS; 
 
    if (!(vlc = aquire_vlc (svlc))) 
        return -1; 
 
    if ((vout = vlc_object_find (vlc, VLC_OBJECT_VOUT, FIND_CHILD))) 
    { 
	    ret = var_Get (vout, "zoom", &val); 
	    vlc_object_release (vout); 
    } 
    else if ((playlist = vlc_object_find (vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD))) 
    { 
		ret = var_Get (playlist, "zoom", &val); 
        vlc_object_release (playlist); 
    } 
 
	if (ret != VLC_SUCCESS) 
		ret = var_Get (vlc, "zoom", &val); 
 
    release_vlc (vlc); 
     
	return (ret == VLC_SUCCESS) ? val.f_float : -1; 
} 
 
/** 
 * Zoom video. This only has an effect if fitwindow is false. 
 * 
 * @param zoom  Zoom factor (e.g. 0.5, 1.0, 1.5, 2.0). 
 * 
 * @return  0 Success. 
 *         -1 Error. 
 */ 
static int SVLC_CC if_set_zoom (HSVLC svlc, float zoom) 
{ 
    vlc_t *vlc; 
    vout_thread_t *vout; 
    playlist_t *playlist; 
	vlc_value_t val; 
     
	if (zoom <= 0) 
		return -1; 
 
    if (!(vlc = aquire_vlc (svlc))) 
        return -1; 
 
	val.f_float = zoom; 
 
    if ((vout = vlc_object_find (vlc, VLC_OBJECT_VOUT, FIND_CHILD))) 
    { 
		var_Set (vout, "zoom", val); 
 
		/* FIXME: This will recreate the picture buffers and everything. I 
		 * believe that's a Bad Thing. 
		 */ 
	    vout->i_changes |= VOUT_SIZE_CHANGE; 
	    vlc_object_release (vout); 
    } 
 
    if ((playlist = vlc_object_find (vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD))) 
    { 
		var_Set (playlist, "zoom", val); 
        vlc_object_release (playlist); 
    } 
 
	var_Set (vlc, "zoom", val); 
 
    release_vlc (vlc); 
     
	return 0; 
} 
 
 
/***************************************************************************** 
 * Audio output 
 *****************************************************************************/ 
 
/** 
 * Get audio volume. 
 * 
 * @return >= 0 Current volume in [0,1]. 
 *           -1 Error. 
 */ 
static float SVLC_CC if_get_volume (HSVLC svlc) 
{ 
    vlc_t *vlc; 
    audio_volume_t volume; 
 
    if (!(vlc = aquire_vlc (svlc))) 
        return -1; 
 
	if (svlc->saved_volume >= 0) 
		volume = svlc->saved_volume; 
	else 
		aout_VolumeGet (vlc, &volume); 
	 
    release_vlc (vlc); 
     
	return ((float)volume) / AOUT_VOLUME_DEFAULT; 
} 
 
/** 
 * Set audio volume. 
 * 
 * @param volume  Volume in [0,1]. 
 * 
 * @return  0 Success. 
 *         -1 Error. 
 */ 
static int SVLC_CC if_set_volume (HSVLC svlc, float volume) 
{ 
    vlc_t *vlc; 
 
	if (volume < 0) volume = 0; 
	if (volume > 1) volume = 1; 
 
    if (!(vlc = aquire_vlc (svlc))) 
        return -1; 
 
	/* Note: We use AOUT_VOLUME_DEFAULT instead of AOUT_VOLUME_MAX because the 
	 * current software scaling used by vlc uses AOUT_VOLUME_DEFAULT as 100% 
	 * of original volume. This prevents sound distortion when going above it. 
	 */ 
	volume *= AOUT_VOLUME_DEFAULT; 
 
	if (svlc->saved_volume >= 0) 
		svlc->saved_volume = volume; 
	else 
	    aout_VolumeSet (vlc, (audio_volume_t)volume); 
 
    release_vlc (vlc); 
     
	return 0; 
} 
 
/** 
 * Get audio mute. 
 * 
 * @return  1 Muted. 
 *          0 Not muted. 
 *         -1 Error. 
 */ 
static int SVLC_CC if_get_mute (HSVLC svlc) 
{ 
	return (svlc->saved_volume < 0) ? 0 : 1; 
} 
 
/** 
 * Set audio mute. 
 * 
 * @param mute  1 Mute audio 
 *              0 Unmute audio 
 *             -1 Toggle mute 
 * 
 * @return  0 Success. 
 *         -1 Error. 
 */ 
static int SVLC_CC if_set_mute (HSVLC svlc, int mute) 
{ 
    vlc_t *vlc; 
    audio_volume_t volume; 
	int res = 0; 
 
    if (!(vlc = aquire_vlc (svlc))) 
        return -1; 
 
	/* if svlc->saved_volume is negative we are not muted */ 
     
	if (svlc->saved_volume < 0 && (mute == 1 || mute == -1)) 
	{ 
		/* Mute */ 
		aout_VolumeGet (vlc, &volume); 
	    svlc->saved_volume = (int)volume; 
        res = aout_VolumeSet (vlc, AOUT_VOLUME_MIN); 
	} 
	else if (svlc->saved_volume >= 0 && (mute == 0 || mute == -1)) 
	{ 
		/* Un-Mute */ 
        res = aout_VolumeSet (vlc, (audio_volume_t)svlc->saved_volume); 
		svlc->saved_volume = -1; 
	} 
 
	release_vlc (vlc); 
 
	return res; 
} 
 
 
/***************************************************************************** 
 * Playback 
 *****************************************************************************/ 
 
/** 
 * Play target. 
 * 
 * @param target  Target to play, e.g. filename. 
 * 
 * @return  0 Success. 
 *         -1 Error. 
 */ 
static int SVLC_CC if_play (HSVLC svlc, const char *target) 
{ 
    vlc_t *vlc; 
    playlist_t *playlist; 
 
    if (!(vlc = aquire_vlc (svlc))) 
        return -1; 
 
	/* get playlist or create one if necessary */ 
    if (!(playlist = vlc_object_find (vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD))) 
    { 
        msg_Dbg (vlc, "no playlist present, creating one" ); 
 
        if (!(playlist = playlist_Create (vlc))) 
        { 
			release_vlc (vlc); 
            return -1; 
        } 
 
        vlc_object_yield (playlist); 
 
		/* reregister playlist hooks */ 
		svlc_event_register_callbacks (svlc, vlc); 
    } 
 
	/* set loading state */ 
	svlc_event_set_playback_state (svlc, SVLC_PLAYBACK_LOADING); 
 
	/* empty playlist */ 
	playlist_Clear (playlist); 
 
	/* add target to playlist and start playback */ 
    playlist_Add (playlist, target, target, PLAYLIST_INSERT | PLAYLIST_GO, 0); 
 
    vlc_object_release (playlist); 
	release_vlc (vlc); 
 
	return 0; 
} 
 
/** 
 * Stop playback and remove any targets. 
 * 
 * @return  0 Success. 
 *         -1 Error. 
 */ 
static int SVLC_CC if_stop (HSVLC svlc) 
{ 
    vlc_t *vlc; 
    playlist_t *playlist; 
 
    if (!(vlc = aquire_vlc (svlc))) 
        return -1; 
 
    if (!(playlist = vlc_object_find (vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD))) 
    { 
        msg_Dbg (vlc, "no playlist to stop" ); 
		release_vlc (vlc); 
        return -1; 
    } 
 
	/* stop playlist */ 
    playlist_Stop (playlist); 
 
#if 0 /* race condition with input */ 
	/* empty playlist */ 
	playlist_Clear (playlist); 
#endif 
 
    vlc_object_release (playlist); 
	release_vlc (vlc); 
 
	return 0; 
} 
 
/** 
 * Set pause. 
 * 
 * @param pause  1 Pause playback 
 *               0 Resume playback 
 *              -1 Toggle pause 
 * 
 * @return  0 Success. 
 *         -1 Error. 
 */ 
static int SVLC_CC if_pause (HSVLC svlc, int pause) 
{ 
    vlc_t *vlc; 
    input_thread_t *input; 
    vlc_value_t status; 
 
    if (!(vlc = aquire_vlc (svlc))) 
        return -1; 
 
    if (!(input = vlc_object_find (vlc, VLC_OBJECT_INPUT, FIND_CHILD))) 
    { 
	    release_vlc (vlc); 
        return -1; 
    } 
 
	var_Get (input, "state", &status); 
	 
	if (status.i_int == PAUSE_S) 
	{ 
		if (pause == -1 || pause == 0) 
		{ 
			status.i_int = PLAYING_S; 
			/* calling var_Set twice with PAUSE_S resumes playback */ 
			var_Set (input, "state", status); 
		} 
	} 
	else 
	{ 
		if (pause == -1 || pause == 1) 
		{ 
			status.i_int = PAUSE_S; 
			var_Set (input, "state", status); 
		} 
	} 
 
    vlc_object_release (input); 
	release_vlc (vlc); 
 
	return 0; 
} 
 
/** 
 * Retrieve playback state. 
 * 
 * @return  See declaration of SVlcPlaybackState 
 */ 
static SVlcPlaybackState SVLC_CC if_get_playback_state (HSVLC svlc) 
{ 
#if 0 
    vlc_t *vlc; 
    input_thread_t *input; 
    vlc_value_t status; 
 
    if (!(vlc = aquire_vlc (svlc))) 
        return SVLC_PLAYBACK_STOPPED; 
 
    if (!(input = vlc_object_find (vlc, VLC_OBJECT_INPUT, FIND_CHILD))) 
    { 
	    release_vlc (vlc); 
        return SVLC_PLAYBACK_CLOSED; 
    } 
 
	var_Get (input, "state", &status); 
 
    vlc_object_release (input); 
	release_vlc (vlc); 
 
	switch (status.i_int) 
	{ 
	case INIT_S:		return SVLC_PLAYBACK_LOADING; 
	case PLAYING_S:		return SVLC_PLAYBACK_PLAYING; 
	case PAUSE_S:		return SVLC_PLAYBACK_PAUSED; 
	case END_S:         return SVLC_PLAYBACK_STOPPED; 
	} 
 
	return SVLC_PLAYBACK_CLOSED; 
#else 
	return svlc->playback_state; 
#endif 
} 
 
/** 
 * Get current stream position. 
 * 
 * @return >= 0 Current postition in [0,1]. 
 *           -1 Error. 
 */ 
static float SVLC_CC if_get_position (HSVLC svlc) 
{ 
    vlc_t *vlc; 
    input_thread_t *input; 
    vlc_value_t position; 
 
    if (!(vlc = aquire_vlc (svlc))) 
        return -1; 
 
    if (!(input = vlc_object_find (vlc, VLC_OBJECT_INPUT, FIND_CHILD))) 
    { 
	    release_vlc (vlc); 
        return -1; 
    } 
 
    vlc_mutex_lock (&input->object_lock); 
	var_Get (input, "position", &position); 
    vlc_mutex_unlock (&input->object_lock); 
 
    vlc_object_release (input); 
	release_vlc (vlc); 
 
	return position.f_float; 
} 
 
/** 
 * Seek to new stream position (if seekable). 
 * 
 * @param position  Position in [0,1] to seek to. 
 * 
 * @return  0 Success. 
 *         -1 Error. 
 */ 
static int SVLC_CC if_set_position (HSVLC svlc, float position) 
{ 
    vlc_t *vlc; 
    input_thread_t *input; 
    vlc_value_t val; 
 
	if (position < 0) position = 0; 
	if (position > 1) position = 1; 
 
    if (!(vlc = aquire_vlc (svlc))) 
        return -1; 
 
    if (!(input = vlc_object_find (vlc, VLC_OBJECT_INPUT, FIND_CHILD))) 
    { 
	    release_vlc (vlc); 
        return -1; 
    } 
 
	var_Get (input, "seekable", &val); 
 
	if (!val.b_bool) 
	{ 
	    vlc_object_release (input); 
		release_vlc (vlc); 
		return -1; 
	} 
 
	val.f_float = position; 
	var_Set (input, "position", val); 
 
    vlc_object_release (input); 
	release_vlc (vlc); 
 
	return 0; 
} 
 
/** 
 * Get seekability of current stream. 
 * 
 * @return  1 Current stream is seekable 
 *          0 Current stream is not seekable 
 *         -1 Error. 
 */ 
static int SVLC_CC if_is_seekable (HSVLC svlc) 
{ 
    vlc_t *vlc; 
    input_thread_t *input; 
    vlc_value_t val; 
 
    if (!(vlc = aquire_vlc (svlc))) 
        return -1; 
 
    if (!(input = vlc_object_find (vlc, VLC_OBJECT_INPUT, FIND_CHILD))) 
    { 
	    release_vlc (vlc); 
        return -1; 
    } 
 
	var_Get (input, "seekable", &val); 
 
    vlc_object_release (input); 
	release_vlc (vlc); 
 
	return val.b_bool; 
} 
 
/** 
 * Get play length of current stream. 
 * 
 * @return > 0 Stream duration in milliseconds. 
 *           0 No time data available for this stream. 
 *          -1 Error. 
 */ 
static int SVLC_CC if_get_duration (HSVLC svlc) 
{ 
    vlc_t *vlc; 
    input_thread_t *input; 
    vlc_value_t length; 
 
    if (!(vlc = aquire_vlc (svlc))) 
        return -1; 
 
    if (!(input = vlc_object_find (vlc, VLC_OBJECT_INPUT, FIND_CHILD))) 
    { 
	    release_vlc (vlc); 
        return -1; 
    } 
 
    var_Get (input, "length", &length); 
 
    vlc_object_release (input); 
	release_vlc (vlc); 
 
	return (length.i_time / 1000); 
} 
 
/** 
 * Get information about an the currently opened stream. 
 * 
 * @param info  Pointer to SVlcStreamInfo which is filled with the data. 
 * 
 * @return  0 Success. 
 *         -1 Error. 
 */ 
int SVLC_CC if_get_stream_info (HSVLC svlc, SVlcStreamInfo *info) 
{ 
    vlc_t *vlc; 
    input_thread_t *input; 
	vlc_value_t val; 
 
	if (!info) 
		return -1; 
 
	if (svlc->playback_state != SVLC_PLAYBACK_OPEN && 
	    svlc->playback_state != SVLC_PLAYBACK_PLAYING && 
	    svlc->playback_state != SVLC_PLAYBACK_PAUSED && 
	    svlc->playback_state != SVLC_PLAYBACK_STOPPED) 
	{ 
		return -1; 
	} 
 
    if (!(vlc = aquire_vlc (svlc))) 
        return -1; 
 
    if (!(input = vlc_object_find (vlc, VLC_OBJECT_INPUT, FIND_CHILD))) 
    { 
	    release_vlc (vlc); 
        return -1; 
    } 
 
	/* audio */ 
    var_Change (input, "audio-es", VLC_VAR_CHOICESCOUNT, &val, NULL); 
	/* - 1 for "Disabled" choice */ 
	info->audio_streams = val.i_int > 0 ? val.i_int - 1 : 0; 
 
	/* video */ 
    var_Change (input, "video-es", VLC_VAR_CHOICESCOUNT, &val, NULL); 
	/* - 1 for "Disabled" choice */ 
	info->video_streams = val.i_int > 0 ? val.i_int - 1 : 0; 
 
#ifdef DEBUG 
	msg_Dbg (input, "audio streams: %d, video_streams: %d", 
	         info->audio_streams, info->video_streams); 
#endif 
 
    vlc_object_release (input); 
	release_vlc (vlc); 
 
	/* demuxer doesn't yet know how much streams there are */ 
	if (info->audio_streams == 0 && info->video_streams == 0) 
		return -1; 
 
	return 0; 
} 
 
/***************************************************************************** 
 * Interface initialization 
 *****************************************************************************/ 
 
int svlc_init_interface (SVlcInterface *intf) 
{ 
	if (intf == NULL) 
		return -1; 
 
	/* instance management */ 
	intf->create				= if_create; 
	intf->destroy				= if_destroy; 
	intf->set_callback			= if_set_callback; 
	intf->get_vlc_version		= if_get_vlc_version; 
	intf->set_udata				= if_set_udata; 
	intf->get_udata				= if_get_udata; 
 
	/* video out */ 
	intf->set_window			= if_set_window; 
	intf->set_visualization     = if_set_visualization; 
	intf->set_fullscreen		= if_set_fullscreen; 
	intf->get_fullscreen		= if_get_fullscreen; 
	intf->set_fitwindow			= if_set_fitwindow; 
	intf->get_fitwindow			= if_get_fitwindow; 
	intf->set_zoom				= if_set_zoom; 
	intf->get_zoom				= if_get_zoom; 
 
	/* audio out */ 
	intf->set_volume			= if_set_volume; 
	intf->get_volume			= if_get_volume; 
	intf->set_mute				= if_set_mute; 
	intf->get_mute				= if_get_mute; 
 
	/* playback */ 
	intf->play					= if_play; 
	intf->stop					= if_stop; 
	intf->pause					= if_pause; 
	intf->get_playback_state	= if_get_playback_state; 
	intf->set_position			= if_set_position; 
	intf->get_position			= if_get_position; 
	intf->is_seekable			= if_is_seekable; 
	intf->get_duration			= if_get_duration; 
	intf->get_stream_info		= if_get_stream_info; 
 
	return 0; 
}