Commit 7ee2435d authored by Sam Hocevar's avatar Sam Hocevar

* ./include/variables.h, ./src/misc/variables.c: implemented variable

    callbacks.
parent ec8c6318
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* variables.h: variables handling * variables.h: variables handling
***************************************************************************** *****************************************************************************
* Copyright (C) 2002 VideoLAN * Copyright (C) 2002 VideoLAN
* $Id: variables.h,v 1.3 2002/10/14 19:04:51 sam Exp $ * $Id: variables.h,v 1.4 2002/10/16 19:39:42 sam Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* *
...@@ -21,17 +21,7 @@ ...@@ -21,17 +21,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/ *****************************************************************************/
/* Variable types - probably very incomplete */ typedef struct callback_entry_t callback_entry_t;
#define VLC_VAR_BOOL 0x0100
#define VLC_VAR_INTEGER 0x0200
#define VLC_VAR_STRING 0x0300
#define VLC_VAR_MODULE 0x0301
#define VLC_VAR_FILE 0x0302
#define VLC_VAR_FLOAT 0x0400
#define VLC_VAR_TIME 0x0500
#define VLC_VAR_ADDRESS 0x0600
#define VLC_VAR_COMMAND 0x0700
#define VLC_VAR_MUTEX 0x0800
/***************************************************************************** /*****************************************************************************
* vlc_value_t is the common union for variable values; variable_t is the * vlc_value_t is the common union for variable values; variable_t is the
...@@ -39,18 +29,35 @@ ...@@ -39,18 +29,35 @@
*****************************************************************************/ *****************************************************************************/
struct variable_t struct variable_t
{ {
u32 i_hash; /* The variable's exported value */
char * psz_name; vlc_value_t val;
/* The variable unique name, (almost) unique hashed value, and type */
char * psz_name;
u32 i_hash;
int i_type; int i_type;
vlc_value_t val;
/* Lots of other things that can be added */ /* Lots of other things that can be added */
int i_usage; int i_usage;
vlc_bool_t b_set;
vlc_bool_t b_active; int i_entries;
callback_entry_t * p_entries;
}; };
/*****************************************************************************
* Variable types - probably very incomplete
*****************************************************************************/
#define VLC_VAR_BOOL 0x0100
#define VLC_VAR_INTEGER 0x0200
#define VLC_VAR_STRING 0x0300
#define VLC_VAR_MODULE 0x0301
#define VLC_VAR_FILE 0x0302
#define VLC_VAR_FLOAT 0x0400
#define VLC_VAR_TIME 0x0500
#define VLC_VAR_ADDRESS 0x0600
#define VLC_VAR_COMMAND 0x0700
#define VLC_VAR_MUTEX 0x0800
/***************************************************************************** /*****************************************************************************
* Prototypes * Prototypes
*****************************************************************************/ *****************************************************************************/
...@@ -61,18 +68,25 @@ VLC_EXPORT( int, __var_Type, ( vlc_object_t *, const char * ) ); ...@@ -61,18 +68,25 @@ VLC_EXPORT( int, __var_Type, ( vlc_object_t *, const char * ) );
VLC_EXPORT( int, __var_Set, ( vlc_object_t *, const char *, vlc_value_t ) ); VLC_EXPORT( int, __var_Set, ( vlc_object_t *, const char *, vlc_value_t ) );
VLC_EXPORT( int, __var_Get, ( vlc_object_t *, const char *, vlc_value_t * ) ); VLC_EXPORT( int, __var_Get, ( vlc_object_t *, const char *, vlc_value_t * ) );
#define var_Create(a,b,c) \ #define var_Create(a,b,c) __var_Create( VLC_OBJECT(a), b, c )
__var_Create( VLC_OBJECT(a), b, c ) #define var_Destroy(a,b) __var_Destroy( VLC_OBJECT(a), b )
#define var_Destroy(a,b) \ #define var_Type(a,b) __var_Type( VLC_OBJECT(a), b )
__var_Destroy( VLC_OBJECT(a), b ) #define var_Set(a,b,c) __var_Set( VLC_OBJECT(a), b, c )
#define var_Get(a,b,c) __var_Get( VLC_OBJECT(a), b, c )
#define var_Type(a,b) \ /*****************************************************************************
__var_Type( VLC_OBJECT(a), b ) * Variable callbacks
*****************************************************************************
#define var_Set(a,b,c) \ * int MyCallback( vlc_object_t *p_this,
__var_Set( VLC_OBJECT(a), b, c ) * char const *psz_variable,
* vlc_value_t oldvalue,
* vlc_value_t newvalue,
* void *p_data);
*****************************************************************************/
VLC_EXPORT( int, __var_AddCallback, ( vlc_object_t *, const char *, vlc_callback_t, void * ) );
VLC_EXPORT( int, __var_DelCallback, ( vlc_object_t *, const char *, vlc_callback_t, void * ) );
#define var_Get(a,b,c) \ #define var_AddCallback(a,b,c,d) __var_AddCallback( VLC_OBJECT(a), b, c, d )
__var_Get( VLC_OBJECT(a), b, c ) #define var_DelCallback(a,b,c,d) __var_DelCallback( VLC_OBJECT(a), b, c, d )
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* Collection of useful common types and macros definitions * Collection of useful common types and macros definitions
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN * Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: vlc_common.h,v 1.30 2002/10/16 15:10:39 sam Exp $ * $Id: vlc_common.h,v 1.31 2002/10/16 19:39:42 sam Exp $
* *
* Authors: Samuel Hocevar <sam@via.ecp.fr> * Authors: Samuel Hocevar <sam@via.ecp.fr>
* Vincent Seguin <seguin@via.ecp.fr> * Vincent Seguin <seguin@via.ecp.fr>
...@@ -236,6 +236,15 @@ typedef struct bit_stream_t bit_stream_t; ...@@ -236,6 +236,15 @@ typedef struct bit_stream_t bit_stream_t;
typedef struct network_socket_t network_socket_t; typedef struct network_socket_t network_socket_t;
typedef struct iso639_lang_t iso639_lang_t; typedef struct iso639_lang_t iso639_lang_t;
/*****************************************************************************
* Variable callbacks
*****************************************************************************/
typedef int ( * vlc_callback_t ) ( vlc_object_t *, /* variable's object */
char const *, /* variable name */
vlc_value_t, /* old value */
vlc_value_t, /* new value */
void * ); /* callback data */
/***************************************************************************** /*****************************************************************************
* Plug-in stuff * Plug-in stuff
*****************************************************************************/ *****************************************************************************/
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* variables.c: routines for object variables handling * variables.c: routines for object variables handling
***************************************************************************** *****************************************************************************
* Copyright (C) 2002 VideoLAN * Copyright (C) 2002 VideoLAN
* $Id: variables.c,v 1.6 2002/10/16 10:31:58 sam Exp $ * $Id: variables.c,v 1.7 2002/10/16 19:39:42 sam Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* *
...@@ -30,6 +30,15 @@ ...@@ -30,6 +30,15 @@
# include <stdlib.h> /* realloc() */ # include <stdlib.h> /* realloc() */
#endif #endif
/*****************************************************************************
* Private types
*****************************************************************************/
struct callback_entry_t
{
vlc_callback_t pf_callback;
void * p_data;
};
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
*****************************************************************************/ *****************************************************************************/
...@@ -96,15 +105,37 @@ int __var_Create( vlc_object_t *p_this, const char *psz_name, int i_type ) ...@@ -96,15 +105,37 @@ int __var_Create( vlc_object_t *p_this, const char *psz_name, int i_type )
memset( &p_var->val, 0, sizeof(vlc_value_t) ); memset( &p_var->val, 0, sizeof(vlc_value_t) );
p_var->i_usage = 1; p_var->i_usage = 1;
p_var->b_set = VLC_FALSE;
p_var->b_active = VLC_TRUE;
p_var->i_entries = 0;
p_var->p_entries = NULL;
/* Always initialize the variable */
switch( i_type ) switch( i_type )
{ {
case VLC_VAR_BOOL:
p_var->val.b_bool = VLC_FALSE;
break;
case VLC_VAR_INTEGER:
p_var->val.i_int = 0;
break;
case VLC_VAR_STRING:
case VLC_VAR_MODULE:
case VLC_VAR_FILE:
p_var->val.psz_string = strdup( "" );
break;
case VLC_VAR_FLOAT:
p_var->val.f_float = 0.0;
break;
case VLC_VAR_TIME:
/* TODO */
break;
case VLC_VAR_ADDRESS:
case VLC_VAR_COMMAND:
p_var->val.p_address = NULL;
break;
case VLC_VAR_MUTEX: case VLC_VAR_MUTEX:
p_var->val.p_address = malloc( sizeof(vlc_mutex_t) ); p_var->val.p_address = malloc( sizeof(vlc_mutex_t) );
vlc_mutex_init( p_this, (vlc_mutex_t*)p_var->val.p_address ); vlc_mutex_init( p_this, (vlc_mutex_t*)p_var->val.p_address );
p_var->b_set = VLC_TRUE;
break; break;
} }
...@@ -149,10 +180,7 @@ int __var_Destroy( vlc_object_t *p_this, const char *psz_name ) ...@@ -149,10 +180,7 @@ int __var_Destroy( vlc_object_t *p_this, const char *psz_name )
case VLC_VAR_STRING: case VLC_VAR_STRING:
case VLC_VAR_MODULE: case VLC_VAR_MODULE:
case VLC_VAR_FILE: case VLC_VAR_FILE:
if( p_var->b_set && p_var->val.psz_string )
{
free( p_var->val.psz_string ); free( p_var->val.psz_string );
}
break; break;
case VLC_VAR_MUTEX: case VLC_VAR_MUTEX:
...@@ -161,6 +189,12 @@ int __var_Destroy( vlc_object_t *p_this, const char *psz_name ) ...@@ -161,6 +189,12 @@ int __var_Destroy( vlc_object_t *p_this, const char *psz_name )
break; break;
} }
/* Free callbacks if needed */
if( p_var->p_entries )
{
free( p_var->p_entries );
}
free( p_var->psz_name ); free( p_var->psz_name );
memmove( p_this->p_vars + i_del, memmove( p_this->p_vars + i_del,
...@@ -214,6 +248,8 @@ int __var_Type( vlc_object_t *p_this, const char *psz_name ) ...@@ -214,6 +248,8 @@ int __var_Type( vlc_object_t *p_this, const char *psz_name )
int __var_Set( vlc_object_t *p_this, const char *psz_name, vlc_value_t val ) int __var_Set( vlc_object_t *p_this, const char *psz_name, vlc_value_t val )
{ {
int i_var; int i_var;
variable_t *p_var;
vlc_value_t oldval;
vlc_mutex_lock( &p_this->var_lock ); vlc_mutex_lock( &p_this->var_lock );
...@@ -225,28 +261,47 @@ int __var_Set( vlc_object_t *p_this, const char *psz_name, vlc_value_t val ) ...@@ -225,28 +261,47 @@ int __var_Set( vlc_object_t *p_this, const char *psz_name, vlc_value_t val )
return VLC_ENOVAR; return VLC_ENOVAR;
} }
/* Duplicate value if needed */ p_var = &p_this->p_vars[i_var];
switch( p_this->p_vars[i_var].i_type )
/* Duplicate data if needed */
switch( p_var->i_type )
{ {
case VLC_VAR_STRING: case VLC_VAR_STRING:
case VLC_VAR_MODULE: case VLC_VAR_MODULE:
case VLC_VAR_FILE: case VLC_VAR_FILE:
if( p_this->p_vars[i_var].b_set
&& p_this->p_vars[i_var].val.psz_string )
{
free( p_this->p_vars[i_var].val.psz_string );
}
if( val.psz_string )
{
val.psz_string = strdup( val.psz_string ); val.psz_string = strdup( val.psz_string );
}
break; break;
} }
p_this->p_vars[i_var].val = val; /* Backup needed stuff */
p_this->p_vars[i_var].b_set = VLC_TRUE; oldval = p_var->val;
/* Set the variable */
p_var->val = val;
/* XXX: callback stuff will go here */ /* Deal with callbacks */
if( p_var->i_entries )
{
int i;
for( i = p_var->i_entries ; i-- ; )
{
/* FIXME: oooh, see the deadlocks! see the race conditions! */
p_var->p_entries[i].pf_callback( p_this, p_var->psz_name,
oldval, val,
p_var->p_entries[i].p_data );
}
}
/* Free data if needed */
switch( p_var->i_type )
{
case VLC_VAR_STRING:
case VLC_VAR_MODULE:
case VLC_VAR_FILE:
free( oldval.psz_string );
break;
}
vlc_mutex_unlock( &p_this->var_lock ); vlc_mutex_unlock( &p_this->var_lock );
...@@ -261,6 +316,7 @@ int __var_Set( vlc_object_t *p_this, const char *psz_name, vlc_value_t val ) ...@@ -261,6 +316,7 @@ int __var_Set( vlc_object_t *p_this, const char *psz_name, vlc_value_t val )
int __var_Get( vlc_object_t *p_this, const char *psz_name, vlc_value_t *p_val ) int __var_Get( vlc_object_t *p_this, const char *psz_name, vlc_value_t *p_val )
{ {
int i_var; int i_var;
variable_t *p_var;
vlc_mutex_lock( &p_this->var_lock ); vlc_mutex_lock( &p_this->var_lock );
...@@ -272,26 +328,23 @@ int __var_Get( vlc_object_t *p_this, const char *psz_name, vlc_value_t *p_val ) ...@@ -272,26 +328,23 @@ int __var_Get( vlc_object_t *p_this, const char *psz_name, vlc_value_t *p_val )
return VLC_ENOVAR; return VLC_ENOVAR;
} }
if( !p_this->p_vars[i_var].b_set ) p_var = &p_this->p_vars[i_var];
{
vlc_mutex_unlock( &p_this->var_lock );
return VLC_EBADVAR;
}
/* Some variables trigger special behaviour. */ /* Some variables trigger special behaviour. */
switch( p_this->p_vars[i_var].i_type ) switch( p_var->i_type )
{ {
case VLC_VAR_COMMAND: case VLC_VAR_COMMAND:
if( p_this->p_vars[i_var].b_set ) if( p_var->val.p_address )
{ {
/* We need this to avoid deadlocks */ /* We need to save data before releasing the lock */
int i_ret; int i_ret;
int (*pf_command) (vlc_object_t *, char *, char *) = int (*pf_command) (vlc_object_t *, char *, char *) =
p_this->p_vars[i_var].val.p_address; p_var->val.p_address;
char *psz_cmd = strdup( p_this->p_vars[i_var].psz_name ); char *psz_cmd = strdup( p_var->psz_name );
char *psz_arg = strdup( p_val->psz_string ); char *psz_arg = strdup( p_val->psz_string );
vlc_mutex_unlock( &p_this->var_lock ); vlc_mutex_unlock( &p_this->var_lock );
i_ret = pf_command( p_this, psz_cmd, psz_arg ); i_ret = pf_command( p_this, psz_cmd, psz_arg );
free( psz_cmd ); free( psz_cmd );
free( psz_arg ); free( psz_arg );
...@@ -302,10 +355,10 @@ int __var_Get( vlc_object_t *p_this, const char *psz_name, vlc_value_t *p_val ) ...@@ -302,10 +355,10 @@ int __var_Get( vlc_object_t *p_this, const char *psz_name, vlc_value_t *p_val )
} }
/* Really set the variable */ /* Really set the variable */
*p_val = p_this->p_vars[i_var].val; *p_val = p_var->val;
/* Duplicate value if needed */ /* Duplicate value if needed */
switch( p_this->p_vars[i_var].i_type ) switch( p_var->i_type )
{ {
case VLC_VAR_STRING: case VLC_VAR_STRING:
case VLC_VAR_MODULE: case VLC_VAR_MODULE:
...@@ -322,6 +375,110 @@ int __var_Get( vlc_object_t *p_this, const char *psz_name, vlc_value_t *p_val ) ...@@ -322,6 +375,110 @@ int __var_Get( vlc_object_t *p_this, const char *psz_name, vlc_value_t *p_val )
return VLC_SUCCESS; return VLC_SUCCESS;
} }
/*****************************************************************************
* var_AddCallback: register a callback in a variable
*****************************************************************************
* We store a function pointer pf_callback that will be called upon variable
* modification. p_data is a generic pointer that will be passed as additional
* argument to the callback function.
*****************************************************************************/
int __var_AddCallback( vlc_object_t *p_this, const char *psz_name,
vlc_callback_t pf_callback, void *p_data )
{
int i_var, i_entry;
variable_t *p_var;
vlc_mutex_lock( &p_this->var_lock );
i_var = Lookup( p_this->p_vars, p_this->i_vars, psz_name );
if( i_var < 0 )
{
vlc_mutex_unlock( &p_this->var_lock );
return VLC_ENOVAR;
}
p_var = &p_this->p_vars[i_var];
i_entry = p_var->i_entries++;
if( i_entry )
{
p_var->p_entries = realloc( p_var->p_entries,
sizeof( callback_entry_t ) * p_var->i_entries );
}
else
{
p_var->p_entries = malloc( sizeof( callback_entry_t ) );
}
p_var->p_entries[ i_entry ].pf_callback = pf_callback;
p_var->p_entries[ i_entry ].p_data = p_data;
vlc_mutex_unlock( &p_this->var_lock );
return VLC_SUCCESS;
}
/*****************************************************************************
* var_DelCallback: remove a callback from a variable
*****************************************************************************
* pf_callback and p_data have to be given again, because different objects
* might have registered the same callback function.
*****************************************************************************/
int __var_DelCallback( vlc_object_t *p_this, const char *psz_name,
vlc_callback_t pf_callback, void *p_data )
{
int i_var, i_entry;
variable_t *p_var;
vlc_mutex_lock( &p_this->var_lock );
i_var = Lookup( p_this->p_vars, p_this->i_vars, psz_name );
if( i_var < 0 )
{
vlc_mutex_unlock( &p_this->var_lock );
return VLC_ENOVAR;
}
p_var = &p_this->p_vars[i_var];
for( i_entry = p_var->i_entries ; i_entry-- ; )
{
if( p_var->p_entries[i_entry].pf_callback == pf_callback
|| p_var->p_entries[i_entry].p_data == p_data )
{
break;
}
}
if( i_entry < 0 )
{
vlc_mutex_unlock( &p_this->var_lock );
return VLC_EGENERIC;
}
p_var->i_entries--;
memmove( p_var->p_entries + i_entry,
p_var->p_entries + i_entry + 1,
sizeof( callback_entry_t ) * ( p_var->i_entries - i_entry ) );
if( p_var->i_entries )
{
p_var->p_entries = realloc( p_var->p_entries,
sizeof( callback_entry_t ) * ( p_var->i_entries ) );
}
else
{
free( p_var->p_entries );
p_var->p_entries = NULL;
}
vlc_mutex_unlock( &p_this->var_lock );
return VLC_SUCCESS;
}
/* Following functions are local */ /* Following functions are local */
/***************************************************************************** /*****************************************************************************
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment