]> git.sesse.net Git - vlc/blobdiff - src/libvlc.c
Small warning fix.
[vlc] / src / libvlc.c
index fd8f1d6b02e9553100d022e435b1baa3fc222cf3..4fce0d9c358bff3b1c2f48e0b1b468fba435aa54 100644 (file)
 #   include <hal/libhal.h>
 #endif
 
+#if defined(__GNUC__)
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 0)
+#define USE_SYNC
+#endif
+#endif
+
 #include <vlc_playlist.h>
 #include <vlc_interface.h>
 
 #include "audio_output/aout_internal.h"
 
 #include <vlc_vout.h>
-
 #include <vlc_sout.h>
-#include "stream_output/stream_output.h"
-
 #include <vlc_charset.h>
 
 #include "libvlc.h"
 
 #include <vlc_vlm.h>
 
+#ifdef __APPLE__
+# include <libkern/OSAtomic.h>
+#endif
+
 #include <assert.h>
 
 /*****************************************************************************
@@ -107,39 +114,87 @@ static unsigned          i_instances = 0;
 static bool b_daemon = false;
 #endif
 
-/*****************************************************************************
- * vlc_gc_*.
- *****************************************************************************/
-void __vlc_gc_incref( gc_object_t * p_gc )
+#undef vlc_gc_init
+#undef vlc_hold
+#undef vlc_release
+
+/**
+ * Atomically set the reference count to 1.
+ * @param p_gc reference counted object
+ * @param pf_destruct destruction calback
+ * @return p_gc.
+ */
+void *vlc_gc_init (gc_object_t *p_gc, void (*pf_destruct) (gc_object_t *))
 {
-    assert( p_gc->i_gc_refcount > 0 );
+    p_gc->pf_destructor = pf_destruct;
 
-    /* FIXME: atomic version needed! */
-    p_gc->i_gc_refcount ++;
+    p_gc->refs = 1;
+#ifdef USE_SYNC
+    __sync_synchronize ();
+#elif defined(__APPLE__)
+    OSMemoryBarrier ();
+#else
+    /* Nobody else can possibly lock the spin - it's there as a barrier */
+    vlc_spin_init (&p_gc->spin);
+    vlc_spin_lock (&p_gc->spin);
+    vlc_spin_unlock (&p_gc->spin);
+#endif
+    return p_gc;
 }
 
-void __vlc_gc_decref( gc_object_t *p_gc )
+/**
+ * Atomically increment the reference count.
+ * @param p_gc reference counted object
+ * @return p_gc.
+ */
+void *vlc_hold (gc_object_t * p_gc)
 {
+    uintptr_t refs;
     assert( p_gc );
-    assert( p_gc->i_gc_refcount > 0 );
-
-    /* FIXME: atomic version needed! */
-    p_gc->i_gc_refcount -- ;
 
-    if( p_gc->i_gc_refcount == 0 )
-    {
-        p_gc->pf_destructor( p_gc );
-        /* Do not use the p_gc pointer from now on ! */
-    }
+#ifdef USE_SYNC
+    refs = __sync_fetch_and_add (&p_gc->refs, 1);
+#elif defined(__APPLE__)
+    refs = OSAtomicIncrement32Barrier((int*)&p_gc->refs) - 1;
+#else
+    vlc_spin_lock (&p_gc->spin);
+    refs = p_gc->refs++;
+    vlc_spin_unlock (&p_gc->spin);
+#endif
+    assert (refs > 0);
+    return p_gc;
 }
 
-void
-__vlc_gc_init( gc_object_t * p_gc, void (*pf_destructor)( gc_object_t * ),
-               void * arg)
+/**
+ * Atomically decrement the reference count and, if it reaches zero, destroy.
+ * @param p_gc reference counted object.
+ */
+void vlc_release (gc_object_t *p_gc)
 {
-    p_gc->i_gc_refcount = 1;
-    p_gc->pf_destructor = pf_destructor;
-    p_gc->p_destructor_arg = arg;
+    unsigned refs;
+
+    assert( p_gc );
+
+#ifdef USE_SYNC
+    refs = __sync_fetch_and_sub (&p_gc->refs, 1);
+#elif defined(__APPLE__)
+    refs = OSAtomicDecrement32Barrier((int*)&p_gc->refs) + 1;
+#else
+    vlc_spin_lock (&p_gc->spin);
+    refs = p_gc->refs--;
+    vlc_spin_unlock (&p_gc->spin);
+#endif
+
+    assert (refs > 0);
+    if (refs == 1)
+    {
+#ifdef USE_SYNC
+#elif defined(__APPLE__)
+#else
+        vlc_spin_destroy (&p_gc->spin);
+#endif
+        p_gc->pf_destructor (p_gc);
+    }
 }
 
 /*****************************************************************************
@@ -152,7 +207,7 @@ static void SetLanguage   ( char const * );
 static inline int LoadMessages (void);
 static int  GetFilenames  ( libvlc_int_t *, int, const char *[] );
 static void Help          ( libvlc_int_t *, char const *psz_help_name );
-static void Usage         ( libvlc_int_t *, char const *psz_module_name );
+static void Usage         ( libvlc_int_t *, char const *psz_search );
 static void ListModules   ( libvlc_int_t *, bool );
 static void Version       ( void );
 
@@ -269,18 +324,6 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
     /* System specific initialization code */
     system_Init( p_libvlc, &i_argc, ppsz_argv );
 
-    /* Get the executable name (similar to the basename command) */
-    if( i_argc > 0 && ppsz_argv[0][0] )
-    {
-        free( p_libvlc->psz_object_name );
-
-        const char *psz_exe = strrchr( ppsz_argv[0], '/' );
-        if( psz_exe && *(psz_exe + 1) )
-            p_libvlc->psz_object_name = strdup( psz_exe + 1 );
-        else
-            p_libvlc->psz_object_name = strdup( ppsz_argv[0] );
-    }
-
     /*
      * Support for gettext
      */
@@ -546,7 +589,9 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
 #ifdef HAVE_DBUS
     dbus_threads_init_default();
 
-    if( config_GetInt( p_libvlc, "one-instance" ) > 0 )
+    if( config_GetInt( p_libvlc, "one-instance" ) > 0
+        || ( config_GetInt( p_libvlc, "one-instance-when-started-from-file" )
+             && config_GetInt( p_libvlc, "started-from-file" ) ) )
     {
         /* Initialise D-Bus interface, check for other instances */
         DBusConnection  *p_conn = NULL;
@@ -666,6 +711,28 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
     /*
      * Message queue options
      */
+    char * psz_verbose_objects = config_GetPsz( p_libvlc, "verbose-objects" );
+    if( psz_verbose_objects )
+    {
+        char * psz_object, * iter = psz_verbose_objects;
+        while( (psz_object = strsep( &iter, "," )) )
+        {
+            switch( psz_object[0] )
+            {
+                printf("%s\n", psz_object+1);
+                case '+': msg_EnableObjectPrinting(p_libvlc, psz_object+1); break;
+                case '-': msg_DisableObjectPrinting(p_libvlc, psz_object+1); break;
+                default:
+                    msg_Err( p_libvlc, "verbose-objects usage: \n"
+                            "--verbose-objects=+printthatobject,"
+                            "-dontprintthatone\n"
+                            "(keyword 'all' to applies to all objects)\n");
+                    free( psz_verbose_objects );
+                    return VLC_EGENERIC;
+            }
+        }
+        free( psz_verbose_objects );
+    }
 
     var_Create( p_libvlc, "verbose", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
     if( config_GetInt( p_libvlc, "quiet" ) > 0 )
@@ -744,10 +811,6 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
     vlc_mutex_init( &p_libvlc->p_stats->lock );
     priv->p_stats_computer = NULL;
 
-    /* Init the array that holds every input item */
-    ARRAY_INIT( priv->input_items );
-    priv->i_last_input_id = 0;
-
     /*
      * Initialize hotkey handling
      */
@@ -844,7 +907,9 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
 #ifdef HAVE_DBUS
     /* loads dbus control interface if in one-instance mode
      * we do it only when playlist exists, because dbus module needs it */
-    if( config_GetInt( p_libvlc, "one-instance" ) > 0 )
+    if( config_GetInt( p_libvlc, "one-instance" ) > 0
+        || ( config_GetInt( p_libvlc, "one-instance-when-started-from-file" )
+             && config_GetInt( p_libvlc, "started-from-file" ) ) )
         libvlc_InternalAddIntf( p_libvlc, "dbus,none" );
 
     /* Prevents the power management daemon from suspending the system
@@ -948,7 +1013,7 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
     var_Get( p_libvlc, "open", &val );
     if ( val.psz_string != NULL && *val.psz_string )
     {
-        playlist_t *p_playlist = pl_Yield( p_libvlc );
+        playlist_t *p_playlist = pl_Hold( p_libvlc );
         playlist_AddExt( p_playlist, val.psz_string, NULL, PLAYLIST_INSERT, 0,
                          -1, NULL, 0, true, pl_Unlocked );
         pl_Release( p_libvlc );
@@ -991,10 +1056,10 @@ int libvlc_InternalCleanup( libvlc_int_t *p_libvlc )
     playlist_ServicesDiscoveryKillAll( p_playlist );
 
     /* Free playlist */
-    /* Any thread still running must not assume pl_Yield() succeeds. */
+    /* Any thread still running must not assume pl_Hold() succeeds. */
     msg_Dbg( p_libvlc, "removing playlist" );
     priv->p_playlist = NULL;
-    vlc_object_kill( p_playlist ); /* <-- memory barrier for pl_Yield() */
+    vlc_object_kill( p_playlist ); /* <-- memory barrier for pl_Hold() */
     vlc_thread_join( p_playlist );
     vlc_object_release( p_playlist );
 
@@ -1012,29 +1077,6 @@ int libvlc_InternalCleanup( libvlc_int_t *p_libvlc )
     stats_TimersDumpAll( p_libvlc );
     stats_TimersCleanAll( p_libvlc );
 
-#ifdef ENABLE_SOUT
-    announce_handler_t * p_announce;
-
-    /* Free announce handler(s?) */
-    while( (p_announce = vlc_object_find( p_libvlc, VLC_OBJECT_ANNOUNCE,
-                                                 FIND_CHILD ) ) )
-    {
-        msg_Dbg( p_libvlc, "removing announce handler" );
-        vlc_object_detach( p_announce );
-        vlc_object_release( p_announce );
-        announce_HandlerDestroy( p_announce );
-    }
-#endif
-
-    bool b_clean = true;
-    FOREACH_ARRAY( input_item_t *p_del, priv->input_items )
-        msg_Err( p_libvlc, "input item %p has not been deleted properly: refcount %d, name %s",
-            p_del, p_del->i_gc_refcount, p_del->psz_name ? p_del->psz_name : "(null)" );
-        b_clean = false;
-    FOREACH_END();
-    assert( b_clean );
-    ARRAY_RESET( priv->input_items );
-
     msg_Dbg( p_libvlc, "removing stats" );
     vlc_mutex_destroy( &p_libvlc->p_stats->lock );
     FREENULL( p_libvlc->p_stats );
@@ -1267,7 +1309,7 @@ static int GetFilenames( libvlc_int_t *p_vlc, int i_argc, const char *ppsz_argv[
         /* TODO: write an internal function of this one, to avoid
          *       unnecessary lookups. */
 
-        playlist_t *p_playlist = pl_Yield( p_vlc );
+        playlist_t *p_playlist = pl_Hold( p_vlc );
         playlist_AddExt( p_playlist, ppsz_argv[i_opt], NULL, PLAYLIST_INSERT,
                          0, -1, ( i_options ? &ppsz_argv[i_opt + 1] : NULL ),
                          i_options, true, pl_Unlocked );
@@ -1296,20 +1338,20 @@ static void Help( libvlc_int_t *p_this, char const *psz_help_name )
 
     if( psz_help_name && !strcmp( psz_help_name, "help" ) )
     {
-        utf8_fprintf( stdout, vlc_usage, p_this->psz_object_name );
-        Usage( p_this, "help" );
-        Usage( p_this, "main" );
+        utf8_fprintf( stdout, vlc_usage, "vlc" );
+        Usage( p_this, "=help" );
+        Usage( p_this, "=main" );
         print_help_on_full_help();
     }
     else if( psz_help_name && !strcmp( psz_help_name, "longhelp" ) )
     {
-        utf8_fprintf( stdout, vlc_usage, p_this->psz_object_name );
+        utf8_fprintf( stdout, vlc_usage, "vlc" );
         Usage( p_this, NULL );
         print_help_on_full_help();
     }
     else if( psz_help_name && !strcmp( psz_help_name, "full-help" ) )
     {
-        utf8_fprintf( stdout, vlc_usage, p_this->psz_object_name );
+        utf8_fprintf( stdout, vlc_usage, "vlc" );
         Usage( p_this, NULL );
     }
     else if( psz_help_name )
@@ -1355,7 +1397,7 @@ static void print_help_section( module_config_t *p_item, bool b_color, bool b_de
     }
 }
 
-static void Usage( libvlc_int_t *p_this, char const *psz_module_name )
+static void Usage( libvlc_int_t *p_this, char const *psz_search )
 {
 #define FORMAT_STRING "  %s --%s%s%s%s%s%s%s "
     /* short option ------'    | | | | | | |
@@ -1398,6 +1440,8 @@ static void Usage( libvlc_int_t *p_this, char const *psz_module_name )
     bool b_found       = false;
     int  i_only_advanced = 0; /* Number of modules ignored because they
                                * only have advanced options */
+    bool b_strict = psz_search && *psz_search == '=';
+    if( b_strict ) psz_search++;
 
     memset( psz_spaces_text, ' ', PADDING_SPACES+LINE_START );
     psz_spaces_text[PADDING_SPACES+LINE_START] = '\0';
@@ -1424,7 +1468,7 @@ static void Usage( libvlc_int_t *p_this, char const *psz_module_name )
 
     /* Ugly hack to make sure that the help options always come first
      * (part 1) */
-    if( !psz_module_name )
+    if( !psz_search )
         Usage( p_this, "help" );
 
     /* Enumerate the config for each module */
@@ -1436,13 +1480,15 @@ static void Usage( libvlc_int_t *p_this, char const *psz_module_name )
         module_config_t *p_section = NULL;
         module_config_t *p_end = p_parser->p_config + p_parser->confsize;
 
-        if( psz_module_name && strcmp( psz_module_name,
-                                       p_parser->psz_object_name ) )
+        if( psz_search &&
+            ( b_strict ? strcmp( psz_search, p_parser->psz_object_name )
+                       : !strstr( p_parser->psz_object_name, psz_search ) ) )
         {
             char *const *pp_shortcut = p_parser->pp_shortcuts;
             while( *pp_shortcut )
             {
-                if( !strcmp( psz_module_name, *pp_shortcut ) )
+                if( b_strict ? !strcmp( psz_search, *pp_shortcut )
+                             : !!strstr( *pp_shortcut, psz_search ) )
                     break;
                 pp_shortcut ++;
             }
@@ -1459,7 +1505,7 @@ static void Usage( libvlc_int_t *p_this, char const *psz_module_name )
         b_help_module = !strcmp( "help", p_parser->psz_object_name );
         /* Ugly hack to make sure that the help options always come first
          * (part 2) */
-        if( !psz_module_name && b_help_module )
+        if( !psz_search && b_help_module )
             continue;
 
         /* Ignore modules with only advanced config options if requested */
@@ -1470,7 +1516,7 @@ static void Usage( libvlc_int_t *p_this, char const *psz_module_name )
                  p_item++ )
             {
                 if( (p_item->i_type & CONFIG_ITEM) &&
-                    !p_item->b_advanced ) break;
+                    !p_item->b_advanced && !p_item->b_removed ) break;
             }
 
             if( p_item == p_end )