]> git.sesse.net Git - vlc/blobdiff - src/misc/variables.c
* ALL: experimental code for stream (dvd) navigation through object variables.
[vlc] / src / misc / variables.c
index e87ba6ed3096f8b91f579c15077244e9d347092d..72a59ca0946e5e3cebff3ab8c9e214986d5acd13 100644 (file)
@@ -2,7 +2,7 @@
  * variables.c: routines for object variables handling
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: variables.c,v 1.11 2002/10/29 13:22:48 sam Exp $
+ * $Id: variables.c,v 1.21 2003/03/11 23:56:54 gbazin Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
@@ -10,7 +10,7 @@
  * 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
@@ -51,23 +51,24 @@ static int CmpAddress( vlc_value_t v, vlc_value_t w ) { return v.p_address == w.
 /*****************************************************************************
  * Local duplication functions, and local deallocation functions
  *****************************************************************************/
-static void DupDummy( vlc_value_t *p_val ) { ; }
+static void DupDummy( vlc_value_t *p_val ) { (void)p_val; /* unused */ }
 static void DupString( vlc_value_t *p_val ) { p_val->psz_string = strdup( p_val->psz_string ); }
 
-static void FreeDummy( vlc_value_t *p_val ) { ; }
+static void FreeDummy( vlc_value_t *p_val ) { (void)p_val; /* unused */ }
 static void FreeString( vlc_value_t *p_val ) { free( p_val->psz_string ); }
+static void FreeMutex( vlc_value_t *p_val ) { vlc_mutex_destroy( (vlc_mutex_t*)p_val->p_address ); free( p_val->p_address ); }
 
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
-static int GetUnused      ( vlc_object_t *, const char * );
-static u32 HashString     ( const char * );
-static int Insert         ( variable_t *, int, const char * );
-static int InsertInner    ( variable_t *, int, u32 );
-static int Lookup         ( variable_t *, int, const char * );
-static int LookupInner    ( variable_t *, int, u32 );
+static int      GetUnused   ( vlc_object_t *, const char * );
+static uint32_t HashString  ( const char * );
+static int      Insert      ( variable_t *, int, const char * );
+static int      InsertInner ( variable_t *, int, uint32_t );
+static int      Lookup      ( variable_t *, int, const char * );
+static int      LookupInner ( variable_t *, int, uint32_t );
 
-static void CheckValue    ( variable_t *, vlc_value_t * );
+static void     CheckValue  ( variable_t *, vlc_value_t * );
 
 /*****************************************************************************
  * var_Create: initialize a vlc variable
@@ -131,8 +132,8 @@ int __var_Create( vlc_object_t *p_this, const char *psz_name, int i_type )
     p_var->i_usage = 1;
 
     p_var->i_default = -1;
-    p_var->i_choices = 0;
-    p_var->pp_choices = NULL;
+    p_var->choices.i_count = 0;
+    p_var->choices.p_values = NULL;
 
     p_var->b_incallback = VLC_FALSE;
     p_var->i_entries = 0;
@@ -154,6 +155,8 @@ int __var_Create( vlc_object_t *p_this, const char *psz_name, int i_type )
         case VLC_VAR_STRING:
         case VLC_VAR_MODULE:
         case VLC_VAR_FILE:
+        case VLC_VAR_DIRECTORY:
+        case VLC_VAR_VARIABLE:
             p_var->pf_cmp = CmpString;
             p_var->pf_dup = DupString;
             p_var->pf_free = FreeString;
@@ -167,12 +170,12 @@ int __var_Create( vlc_object_t *p_this, const char *psz_name, int i_type )
             /* FIXME: TODO */
             break;
         case VLC_VAR_ADDRESS:
-        case VLC_VAR_COMMAND:
             p_var->pf_cmp = CmpAddress;
             p_var->val.p_address = NULL;
             break;
         case VLC_VAR_MUTEX:
             p_var->pf_cmp = CmpAddress;
+            p_var->pf_free = FreeMutex;
             p_var->val.p_address = malloc( sizeof(vlc_mutex_t) );
             vlc_mutex_init( p_this, (vlc_mutex_t*)p_var->val.p_address );
             break;
@@ -218,23 +221,14 @@ int __var_Destroy( vlc_object_t *p_this, const char *psz_name )
     /* Free value if needed */
     p_var->pf_free( &p_var->val );
 
-    switch( p_var->i_type & VLC_VAR_TYPE )
-    {
-        /* XXX: find a way to put this in pf_free */
-        case VLC_VAR_MUTEX:
-            vlc_mutex_destroy( (vlc_mutex_t*)p_var->val.p_address );
-            free( p_var->val.p_address );
-            break;
-    }
-
     /* Free choice list if needed */
-    if( p_var->pp_choices )
+    if( p_var->choices.i_count )
     {
-        for( i = 0 ; i < p_var->i_choices ; i++ )
+        for( i = 0 ; i < p_var->choices.i_count ; i++ )
         {
-            p_var->pf_free( &p_var->pp_choices[i] );
+            p_var->pf_free( &p_var->choices.p_values[i] );
         }
-        free( p_var->pp_choices );
+        free( p_var->choices.p_values );
     }
 
     /* Free callbacks if needed */
@@ -265,13 +259,14 @@ int __var_Destroy( vlc_object_t *p_this, const char *psz_name )
 /*****************************************************************************
  * var_Change: perform an action on a variable
  *****************************************************************************
- * 
+ *
  *****************************************************************************/
 int __var_Change( vlc_object_t *p_this, const char *psz_name,
                   int i_action, vlc_value_t *p_val )
 {
     int i_var, i;
     variable_t *p_var;
+    vlc_value_t oldval;
 
     vlc_mutex_lock( &p_this->var_lock );
 
@@ -317,12 +312,11 @@ int __var_Change( vlc_object_t *p_this, const char *psz_name,
             p_var->pf_dup( &p_var->step );
             CheckValue( p_var, &p_var->val );
             break;
-
         case VLC_VAR_ADDCHOICE:
             /* FIXME: the list is sorted, dude. Use something cleverer. */
-            for( i = p_var->i_choices ; i-- ; )
+            for( i = p_var->choices.i_count ; i-- ; )
             {
-                if( p_var->pf_cmp( p_var->pp_choices[i], *p_val ) < 0 )
+                if( p_var->pf_cmp( p_var->choices.p_values[i], *p_val ) < 0 )
                 {
                     break;
                 }
@@ -336,22 +330,23 @@ int __var_Change( vlc_object_t *p_this, const char *psz_name,
                 p_var->i_default++;
             }
 
-            INSERT_ELEM( p_var->pp_choices, p_var->i_choices, i, *p_val );
-            p_var->pf_dup( &p_var->pp_choices[i] );
+            INSERT_ELEM( p_var->choices.p_values, p_var->choices.i_count,
+                         i, *p_val );
+            p_var->pf_dup( &p_var->choices.p_values[i] );
 
             CheckValue( p_var, &p_var->val );
             break;
         case VLC_VAR_DELCHOICE:
             /* FIXME: the list is sorted, dude. Use something cleverer. */
-            for( i = 0 ; i < p_var->i_choices ; i++ )
+            for( i = 0 ; i < p_var->choices.i_count ; i++ )
             {
-                if( p_var->pf_cmp( p_var->pp_choices[i], *p_val ) == 0 )
+                if( p_var->pf_cmp( p_var->choices.p_values[i], *p_val ) == 0 )
                 {
                     break;
                 }
             }
 
-            if( i == p_var->i_choices )
+            if( i == p_var->choices.i_count )
             {
                 /* Not found */
                 vlc_mutex_unlock( &p_this->var_lock );
@@ -367,22 +362,34 @@ int __var_Change( vlc_object_t *p_this, const char *psz_name,
                 p_var->i_default = -1;
             }
 
-            p_var->pf_free( &p_var->pp_choices[i] );
-            REMOVE_ELEM( p_var->pp_choices, p_var->i_choices, i );
+            p_var->pf_free( &p_var->choices.p_values[i] );
+            REMOVE_ELEM( p_var->choices.p_values, p_var->choices.i_count, i );
 
             CheckValue( p_var, &p_var->val );
             break;
+        case VLC_VAR_CLEARCHOICES:
+            for( i = 0 ; i < p_var->choices.i_count ; i++ )
+            {
+                p_var->pf_free( &p_var->choices.p_values[i] );
+            }
+            if( p_var->choices.i_count )
+                free( p_var->choices.p_values );
+
+            p_var->choices.i_count = 0;
+            p_var->choices.p_values = NULL;
+            p_var->i_default = -1;
+            break;
         case VLC_VAR_SETDEFAULT:
             /* FIXME: the list is sorted, dude. Use something cleverer. */
-            for( i = 0 ; i < p_var->i_choices ; i++ )
+            for( i = 0 ; i < p_var->choices.i_count ; i++ )
             {
-                if( p_var->pf_cmp( p_var->pp_choices[i], *p_val ) == 0 )
+                if( p_var->pf_cmp( p_var->choices.p_values[i], *p_val ) == 0 )
                 {
                     break;
                 }
             }
 
-            if( i == p_var->i_choices )
+            if( i == p_var->choices.i_count )
             {
                 /* Not found */
                 break;
@@ -391,23 +398,38 @@ int __var_Change( vlc_object_t *p_this, const char *psz_name,
             p_var->i_default = i;
             CheckValue( p_var, &p_var->val );
             break;
-
+        case VLC_VAR_SETVALUE:
+            /* Duplicate data if needed */
+            p_var->pf_dup( p_val );
+            /* Backup needed stuff */
+            oldval = p_var->val;
+            /* Check boundaries and list */
+            CheckValue( p_var, p_val );
+            /* Set the variable */
+            p_var->val = *p_val;
+            /* Free data if needed */
+            p_var->pf_free( &oldval );
+            break;
         case VLC_VAR_GETLIST:
-            p_val->p_address = malloc( (1 + p_var->i_choices)
-                                        * sizeof(vlc_value_t) );
-            ((vlc_value_t*)p_val->p_address)[0].i_int = p_var->i_choices;
-            for( i = 0 ; i < p_var->i_choices ; i++ )
+            p_val->p_list = malloc( sizeof(vlc_list_t) );
+            if( p_var->choices.i_count )
+                p_val->p_list->p_values = malloc( p_var->choices.i_count
+                                                  * sizeof(vlc_value_t) );
+            p_val->p_list->i_count = p_var->choices.i_count;
+            for( i = 0 ; i < p_var->choices.i_count ; i++ )
             {
-                ((vlc_value_t*)p_val->p_address)[i+1] = p_var->pp_choices[i];
-                p_var->pf_dup( &((vlc_value_t*)p_val->p_address)[i+1] );
+                p_val->p_list->p_values[i] = p_var->choices.p_values[i];
+                p_var->pf_dup( &p_val->p_list->p_values[i] );
             }
             break;
         case VLC_VAR_FREELIST:
-            for( i = ((vlc_value_t*)p_val->p_address)[0].i_int ; i-- ; )
+            for( i = p_val->p_list->i_count ; i-- ; )
             {
-                p_var->pf_free( &((vlc_value_t*)p_val->p_address)[i+1] );
+                p_var->pf_free( &p_val->p_list->p_values[i] );
             }
-            free( p_val->p_address );
+            if( p_val->p_list->i_count )
+                free( p_val->p_list->p_values );
+            free( p_val->p_list );
             break;
 
         default:
@@ -420,9 +442,10 @@ int __var_Change( vlc_object_t *p_this, const char *psz_name,
 }
 
 /*****************************************************************************
- * var_Type: request a variable's type, 0 if not found
+ * var_Type: request a variable's type
  *****************************************************************************
- * 
+ * This function returns the variable type if it exists, or 0 if the
+ * variable could not be found.
  *****************************************************************************/
 int __var_Type( vlc_object_t *p_this, const char *psz_name )
 {
@@ -476,6 +499,9 @@ int __var_Set( vlc_object_t *p_this, const char *psz_name, vlc_value_t val )
     /* Check boundaries and list */
     CheckValue( p_var, &val );
 
+    /* Set the variable */
+    p_var->val = val;
+
     /* Deal with callbacks. Tell we're in a callback, release the lock,
      * call stored functions, retake the lock. */
     if( p_var->i_entries )
@@ -499,7 +525,7 @@ int __var_Set( vlc_object_t *p_this, const char *psz_name, vlc_value_t val )
         i_var = Lookup( p_this->p_vars, p_this->i_vars, psz_name );
         if( i_var < 0 )
         {
-            msg_Err( p_this, "variable %s has disappeared" );
+            msg_Err( p_this, "variable %s has disappeared", psz_name );
             vlc_mutex_unlock( &p_this->var_lock );
             return VLC_ENOVAR;
         }
@@ -508,9 +534,6 @@ int __var_Set( vlc_object_t *p_this, const char *psz_name, vlc_value_t val )
         p_var->b_incallback = VLC_FALSE;
     }
 
-    /* Set the variable */
-    p_var->val = val;
-
     /* Free data if needed */
     p_var->pf_free( &oldval );
 
@@ -541,30 +564,6 @@ int __var_Get( vlc_object_t *p_this, const char *psz_name, vlc_value_t *p_val )
 
     p_var = &p_this->p_vars[i_var];
 
-    /* Some variables trigger special behaviour. */
-    switch( p_var->i_type & VLC_VAR_TYPE )
-    {
-        case VLC_VAR_COMMAND:
-            if( p_var->val.p_address )
-            {
-                /* We need to save data before releasing the lock */
-                int i_ret;
-                int (*pf_command) (vlc_object_t *, char *, char *) =
-                                          p_var->val.p_address;
-                char *psz_cmd = strdup( p_var->psz_name );
-                char *psz_arg = strdup( p_val->psz_string );
-
-                vlc_mutex_unlock( &p_this->var_lock );
-
-                i_ret = pf_command( p_this, psz_cmd, psz_arg );
-                free( psz_cmd );
-                free( psz_arg );
-
-                return i_ret;
-            }
-            break;
-    }
-
     /* Really get the variable */
     *p_val = p_var->val;
 
@@ -592,7 +591,7 @@ int __var_AddCallback( vlc_object_t *p_this, const char *psz_name,
 
     entry.pf_callback = pf_callback;
     entry.p_data = p_data;
-        
+
     vlc_mutex_lock( &p_this->var_lock );
 
     i_var = GetUnused( p_this, psz_name );
@@ -640,7 +639,7 @@ int __var_DelCallback( vlc_object_t *p_this, const char *psz_name,
     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 )
+            && p_var->p_entries[i_entry].p_data == p_data )
         {
             break;
         }
@@ -703,9 +702,9 @@ static int GetUnused( vlc_object_t *p_this, const char *psz_name )
  * fast and not suck too much. This one is pretty fast and did 0 collisions
  * in wenglish's dictionary.
  *****************************************************************************/
-static u32 HashString( const char *psz_string )
+static uint32_t HashString( const char *psz_string )
 {
-    u32 i_hash = 0;
+    uint32_t i_hash = 0;
 
     while( *psz_string )
     {
@@ -735,7 +734,7 @@ static int Insert( variable_t *p_vars, int i_count, const char *psz_name )
     return InsertInner( p_vars, i_count, HashString( psz_name ) );
 }
 
-static int InsertInner( variable_t *p_vars, int i_count, u32 i_hash )
+static int InsertInner( variable_t *p_vars, int i_count, uint32_t i_hash )
 {
     int i_middle;
 
@@ -777,7 +776,7 @@ static int InsertInner( variable_t *p_vars, int i_count, u32 i_hash )
  *****************************************************************************/
 static int Lookup( variable_t *p_vars, int i_count, const char *psz_name )
 {
-    u32 i_hash;
+    uint32_t i_hash;
     int i, i_pos;
 
     if( i_count == 0 )
@@ -824,7 +823,7 @@ static int Lookup( variable_t *p_vars, int i_count, const char *psz_name )
     return -1;
 }
 
-static int LookupInner( variable_t *p_vars, int i_count, u32 i_hash )
+static int LookupInner( variable_t *p_vars, int i_count, uint32_t i_hash )
 {
     int i_middle;
 
@@ -867,14 +866,14 @@ static int LookupInner( variable_t *p_vars, int i_count, u32 i_hash )
 static void CheckValue ( variable_t *p_var, vlc_value_t *p_val )
 {
     /* Check that our variable is in the list */
-    if( p_var->i_type & VLC_VAR_ISLIST && p_var->i_choices )
+    if( p_var->i_type & VLC_VAR_HASCHOICE && p_var->choices.i_count )
     {
         int i;
 
         /* FIXME: the list is sorted, dude. Use something cleverer. */
-        for( i = p_var->i_choices ; i-- ; )
+        for( i = p_var->choices.i_count ; i-- ; )
         {
-            if( p_var->pf_cmp( *p_val, p_var->pp_choices[i] ) == 0 )
+            if( p_var->pf_cmp( *p_val, p_var->choices.p_values[i] ) == 0 )
             {
                 break;
             }
@@ -885,8 +884,8 @@ static void CheckValue ( variable_t *p_var, vlc_value_t *p_val )
         {
             /* Free the old variable, get the new one, dup it */
             p_var->pf_free( p_val );
-            *p_val = p_var->pp_choices[p_var->i_default >= 0
-                                        ? p_var->i_default : 0 ];
+            *p_val = p_var->choices.p_values[p_var->i_default >= 0
+                                          ? p_var->i_default : 0 ];
             p_var->pf_dup( p_val );
         }
     }
@@ -938,4 +937,3 @@ static void CheckValue ( variable_t *p_var, vlc_value_t *p_val )
             break;
     }
 }
-