Beispiel #1
0
void var_DestroyAll( vlc_object_t *obj )
{
    vlc_object_internals_t *priv = vlc_internals( obj );

    tdestroy( priv->var_root, CleanupVar );
    priv->var_root = NULL;
}
Beispiel #2
0
int var_GetChecked( vlc_object_t *p_this, const char *psz_name,
                    int expected_type, vlc_value_t *p_val )
{
    assert( p_this );

    vlc_object_internals_t *p_priv = vlc_internals( p_this );
    variable_t *p_var;
    int err = VLC_SUCCESS;

    vlc_mutex_lock( &p_priv->var_lock );

    p_var = Lookup( p_this, psz_name );
    if( p_var != NULL )
    {
        assert( expected_type == 0 ||
                (p_var->i_type & VLC_VAR_CLASS) == expected_type );
        assert ((p_var->i_type & VLC_VAR_CLASS) != VLC_VAR_VOID);

        /* Really get the variable */
        *p_val = p_var->val;

        /* Duplicate value if needed */
        p_var->ops->pf_dup( p_val );
    }
    else
        err = VLC_ENOVAR;

    vlc_mutex_unlock( &p_priv->var_lock );
    return err;
}
Beispiel #3
0
/**
 * Register a callback in a variable
 *
 * We store a function pointer that will be called upon variable
 * modification.
 *
 * \param p_this The object that holds the variable
 * \param psz_name The name of the variable
 * \param pf_callback The function pointer
 * \param p_data A generic pointer that will be passed as the last
 *               argument to the callback function.
 *
 * \warning The callback function is run in the thread that calls var_Set on
 *          the variable. Use proper locking. This thread may not have much
 *          time to spare, so keep callback functions short.
 */
int var_AddCallback( vlc_object_t *p_this, const char *psz_name,
                     vlc_callback_t pf_callback, void *p_data )
{
    variable_t *p_var;
    callback_entry_t entry;

    assert( p_this );

    vlc_object_internals_t *p_priv = vlc_internals( p_this );

    entry.pf_callback = pf_callback;
    entry.p_data = p_data;

    vlc_mutex_lock( &p_priv->var_lock );

    p_var = Lookup( p_this, psz_name );
    if( p_var == NULL )
    {
        vlc_mutex_unlock( &p_priv->var_lock );
        msg_Err( p_this, "cannot add callback %p to nonexistent "
                 "variable '%s'", pf_callback, psz_name );
        return VLC_ENOVAR;
    }

    WaitUnused( p_this, p_var );
    INSERT_ELEM( p_var->p_entries,
                 p_var->i_entries,
                 p_var->i_entries,
                 entry );

    vlc_mutex_unlock( &p_priv->var_lock );

    return VLC_SUCCESS;
}
Beispiel #4
0
static void AddCallback( vlc_object_t *p_this, const char *psz_name,
                        callback_entry_t entry, vlc_callback_type_t i_type )
{
    variable_t *p_var;

    assert( p_this );

    vlc_object_internals_t *p_priv = vlc_internals( p_this );

    p_var = Lookup( p_this, psz_name );
    if( p_var == NULL )
    {
        vlc_mutex_unlock( &p_priv->var_lock );
        msg_Err( p_this, "cannot add callback %p to nonexistent variable '%s'",
                 entry.p_callback, psz_name );
        return;
    }

    WaitUnused( p_this, p_var );

    callback_table_t *p_table;
    if (i_type == vlc_value_callback)
        p_table = &p_var->value_callbacks;
    else
        p_table = &p_var->list_callbacks;
    TAB_APPEND(p_table->i_entries, p_table->p_entries, entry);

    vlc_mutex_unlock( &p_priv->var_lock );
}
Beispiel #5
0
/**
 * Perform a Get and Set on a variable
 *
 * \param p_this: The object that hold the variable
 * \param psz_name: the name of the variable
 * \param i_action: the action to perform
 * \param p_val: The action parameter
 * \return vlc error codes
 */
int var_GetAndSet( vlc_object_t *p_this, const char *psz_name, int i_action,
                   vlc_value_t *p_val )
{
    variable_t *p_var;
    vlc_value_t oldval;

    assert( p_this );
    assert( p_val );

    vlc_object_internals_t *p_priv = vlc_internals( p_this );

    p_var = Lookup( p_this, psz_name );
    if( p_var == NULL )
    {
        vlc_mutex_unlock( &p_priv->var_lock );
        return VLC_ENOVAR;
    }

    WaitUnused( p_this, p_var );

    /* Duplicated data if needed */
    //p_var->ops->pf_dup( &val );

    /* Backup needed stuff */
    oldval = p_var->val;

    /* depending of the action requiered */
    switch( i_action )
    {
    case VLC_VAR_BOOL_TOGGLE:
        assert( ( p_var->i_type & VLC_VAR_BOOL ) == VLC_VAR_BOOL );
        p_var->val.b_bool = !p_var->val.b_bool;
        break;
    case VLC_VAR_INTEGER_ADD:
        assert( ( p_var->i_type & VLC_VAR_INTEGER ) == VLC_VAR_INTEGER );
        p_var->val.i_int += p_val->i_int;
        break;
    case VLC_VAR_INTEGER_OR:
        assert( ( p_var->i_type & VLC_VAR_INTEGER ) == VLC_VAR_INTEGER );
        p_var->val.i_int |= p_val->i_int;
        break;
    case VLC_VAR_INTEGER_NAND:
        assert( ( p_var->i_type & VLC_VAR_INTEGER ) == VLC_VAR_INTEGER );
        p_var->val.i_int &= ~p_val->i_int;
        break;
    default:
        vlc_mutex_unlock( &p_priv->var_lock );
        return VLC_EGENERIC;
    }

    /*  Check boundaries */
    CheckValue( p_var, &p_var->val );
    *p_val = p_var->val;

    /* Deal with callbacks.*/
    TriggerCallback( p_this, p_var, psz_name, oldval );

    vlc_mutex_unlock( &p_priv->var_lock );
    return VLC_SUCCESS;
}
Beispiel #6
0
/**
 * Destroy a vlc variable
 *
 * Look for the variable and destroy it if it is found. As in var_Create we
 * do a call to memmove() but we have performance counterparts elsewhere.
 *
 * \param p_this The object that holds the variable
 * \param psz_name The name of the variable
 */
void (var_Destroy)(vlc_object_t *p_this, const char *psz_name)
{
    variable_t *p_var;

    assert( p_this );

    vlc_object_internals_t *p_priv = vlc_internals( p_this );

    p_var = Lookup( p_this, psz_name );
    if( p_var == NULL )
        msg_Dbg( p_this, "attempt to destroy nonexistent variable \"%s\"",
                 psz_name );
    else if( --p_var->i_usage == 0 )
    {
        assert(!p_var->b_incallback);
        tdelete( p_var, &p_priv->var_root, varcmp );
    }
    else
    {
        assert(p_var->i_usage != -1u);
        p_var = NULL;
    }
    vlc_mutex_unlock( &p_priv->var_lock );

    if( p_var != NULL )
        Destroy( p_var );
}
Beispiel #7
0
int var_GetChecked( vlc_object_t *p_this, const char *psz_name,
                    int expected_type, vlc_value_t *p_val )
{
    assert( p_this );

    vlc_object_internals_t *p_priv = vlc_internals( p_this );
    variable_t *p_var;
    int err = VLC_SUCCESS;

    vlc_mutex_lock( &p_priv->var_lock );

    p_var = Lookup( p_this, psz_name );
    if( p_var != NULL )
    {
        assert( expected_type == 0 ||
                (p_var->i_type & VLC_VAR_CLASS) == expected_type );

        /* Really get the variable */
        *p_val = p_var->val;

#ifndef NDEBUG
        /* Alert if the type is VLC_VAR_VOID */
        if( ( p_var->i_type & VLC_VAR_TYPE ) == VLC_VAR_VOID )
            msg_Warn( p_this, "Calling var_Get on the void variable '%s' (0x%04x)", psz_name, p_var->i_type );
#endif

        /* Duplicate value if needed */
        p_var->ops->pf_dup( p_val );
    }
    else
        err = VLC_ENOVAR;

    vlc_mutex_unlock( &p_priv->var_lock );
    return err;
}
Beispiel #8
0
/**
 * Trigger callback on a variable
 *
 * \param p_this The object that hold the variable
 * \param psz_name The name of the variable
 */
int var_TriggerCallback( vlc_object_t *p_this, const char *psz_name )
{
    int i_ret;
    variable_t *p_var;

    assert( p_this );

    vlc_object_internals_t *p_priv = vlc_internals( p_this );

    vlc_mutex_lock( &p_priv->var_lock );

    p_var = Lookup( p_this, psz_name );
    if( p_var == NULL )
    {
        vlc_mutex_unlock( &p_priv->var_lock );
        return VLC_ENOVAR;
    }

    WaitUnused( p_this, p_var );

    /* Deal with callbacks. Tell we're in a callback, release the lock,
     * call stored functions, retake the lock. */
    i_ret = TriggerCallback( p_this, p_var, psz_name, p_var->val );

    vlc_mutex_unlock( &p_priv->var_lock );
    return i_ret;
}
Beispiel #9
0
Datei: threads.c Projekt: paa/vlc
void vlc_thread_cancel (vlc_object_t *obj)
{
    vlc_object_internals_t *priv = vlc_internals (obj);

    if (priv->b_thread)
        vlc_cancel (priv->thread_id);
}
Beispiel #10
0
/**
 * Destroy a vlc variable
 *
 * Look for the variable and destroy it if it is found. As in var_Create we
 * do a call to memmove() but we have performance counterparts elsewhere.
 *
 * \param p_this The object that holds the variable
 * \param psz_name The name of the variable
 */
int var_Destroy( vlc_object_t *p_this, const char *psz_name )
{
    variable_t *p_var;

    assert( p_this );

    vlc_object_internals_t *p_priv = vlc_internals( p_this );

    vlc_mutex_lock( &p_priv->var_lock );

    p_var = Lookup( p_this, psz_name );
    if( p_var == NULL )
    {
        vlc_mutex_unlock( &p_priv->var_lock );
        return VLC_ENOVAR;
    }

    WaitUnused( p_this, p_var );

    if( --p_var->i_usage == 0 )
        tdelete( p_var, &p_priv->var_root, varcmp );
    else
        p_var = NULL;
    vlc_mutex_unlock( &p_priv->var_lock );

    if( p_var != NULL )
        Destroy( p_var );
    return VLC_SUCCESS;
}
Beispiel #11
0
Datei: threads.c Projekt: paa/vlc
/*****************************************************************************
 * vlc_thread_create: create a thread
 *****************************************************************************
 * Note that i_priority is only taken into account on platforms supporting
 * userland real-time priority threads.
 *****************************************************************************/
int vlc_thread_create( vlc_object_t *p_this, const char * psz_file, int i_line,
                       const char *psz_name, void *(*func) ( vlc_object_t * ),
                       int i_priority )
{
    int i_ret;
    vlc_object_internals_t *p_priv = vlc_internals( p_this );

    struct vlc_thread_boot *boot = malloc (sizeof (*boot));
    if (boot == NULL)
        return errno;
    boot->entry = func;
    boot->object = p_this;

    /* Make sure we don't re-create a thread if the object has already one */
    assert( !p_priv->b_thread );

    p_priv->b_thread = true;
    i_ret = vlc_clone( &p_priv->thread_id, thread_entry, boot, i_priority );
    if( i_ret == 0 )
        msg_Dbg( p_this, "thread (%s) created at priority %d (%s:%d)",
                 psz_name, i_priority, psz_file, i_line );
    else
    {
        p_priv->b_thread = false;
        errno = i_ret;
        msg_Err( p_this, "%s thread could not be created at %s:%d (%m)",
                         psz_name, psz_file, i_line );
    }

    return i_ret;
}
Beispiel #12
0
/**********************************************************************
 * Trigger the callbacks.
 * Tell we're in a callback, release the lock, call stored functions,
 * retake the lock.
 **********************************************************************/
static int TriggerCallback( vlc_object_t *p_this, variable_t *p_var,
                            const char *psz_name, vlc_value_t oldval )
{
    assert( p_this );

    int i_entries = p_var->i_entries;
    if( i_entries == 0 )
        return VLC_SUCCESS;

    callback_entry_t *p_entries = p_var->p_entries;
    vlc_object_internals_t *p_priv = vlc_internals( p_this );

    assert( !p_var->b_incallback );
    p_var->b_incallback = true;
    vlc_mutex_unlock( &p_priv->var_lock );

    /* The real calls */
    for( ; i_entries-- ; )
    {
        p_entries[i_entries].pf_callback( p_this, psz_name, oldval, p_var->val,
                                          p_entries[i_entries].p_data );
    }

    vlc_mutex_lock( &p_priv->var_lock );
    p_var->b_incallback = false;
    vlc_cond_broadcast( &p_priv->var_wait );

    return VLC_SUCCESS;
}
Beispiel #13
0
/*****************************************************************************
 * vlc_thread_set_priority: set the priority of the current thread when we
 * couldn't set it in vlc_thread_create (for instance for the main thread)
 *****************************************************************************/
int vlc_thread_set_priority( vlc_object_t *p_this, const char * psz_file,
                             int i_line, int i_priority )
{
    vlc_object_internals_t *p_priv = vlc_internals( p_this );

    if( !p_priv->b_thread )
    {
        msg_Err( p_this, "couldn't set priority of non-existent thread" );
        return ESRCH;
    }

#if defined( LIBVLC_USE_PTHREAD )
# ifndef __APPLE__
    if( var_InheritBool( p_this, "rt-priority" ) )
# endif
    {
        int i_error, i_policy;
        struct sched_param param;

        memset( &param, 0, sizeof(struct sched_param) );
        if( config_GetType( p_this, "rt-offset" ) )
            i_priority += var_InheritInteger( p_this, "rt-offset" );
        if( i_priority <= 0 )
        {
            param.sched_priority = (-1) * i_priority;
            i_policy = SCHED_OTHER;
        }
        else
        {
            param.sched_priority = i_priority;
            i_policy = SCHED_RR;
        }
        if( (i_error = pthread_setschedparam( p_priv->thread_id,
                                              i_policy, &param )) )
        {
            errno = i_error;
            msg_Warn( p_this, "couldn't set thread priority (%s:%d): %m",
                      psz_file, i_line );
            i_priority = 0;
        }
    }

#elif defined( WIN32 ) || defined( UNDER_CE )
    VLC_UNUSED( psz_file); VLC_UNUSED( i_line );

#ifndef UNDER_CE
    if( !SetThreadPriority(p_priv->thread_id, i_priority) )
#else
    if( !SetThreadPriority(p_priv->thread_id->handle, i_priority) )
#endif
    {
        msg_Warn( p_this, "couldn't set a faster priority" );
        return 1;
    }

#endif

    return 0;
}
Beispiel #14
0
static void DelCallback( vlc_object_t *p_this, const char *psz_name,
                         callback_entry_t entry, vlc_callback_type_t i_type )
{
    int i_entry;
    variable_t *p_var;
#ifndef NDEBUG
    bool b_found_similar = false;
#endif

    assert( p_this );

    vlc_object_internals_t *p_priv = vlc_internals( p_this );

    p_var = Lookup( p_this, psz_name );
    if( p_var == NULL )
    {
        vlc_mutex_unlock( &p_priv->var_lock );
        msg_Err( p_this, "cannot delete callback %p from nonexistent "
                 "variable '%s'", entry.p_callback, psz_name );
        return;
    }

    WaitUnused( p_this, p_var );

    callback_table_t *p_table;
    if (i_type == vlc_value_callback)
        p_table = &p_var->value_callbacks;
    else
        p_table = &p_var->list_callbacks;

    for( i_entry = p_table->i_entries ; i_entry-- ; )
    {
        if( p_table->p_entries[i_entry].p_callback == entry.p_callback
            && p_table->p_entries[i_entry].p_data == entry.p_data )
        {
            break;
        }
#ifndef NDEBUG
        else if( p_table->p_entries[i_entry].p_callback == entry.p_callback )
            b_found_similar = true;
#endif
    }

    if( i_entry < 0 )
    {
#ifndef NDEBUG
        if( b_found_similar )
            fprintf( stderr, "Calling var_DelCallback for '%s' with the same "
                             "function but not the same data.", psz_name );
        vlc_assert_unreachable();
#endif
        vlc_mutex_unlock( &p_priv->var_lock );
        return;
    }

    TAB_ERASE(p_table->i_entries, p_table->p_entries, i_entry);

    vlc_mutex_unlock( &p_priv->var_lock );
}
Beispiel #15
0
static vlc_object_t *ObjectExists (vlc_object_t *root, void *obj)
{
    if (root == obj)
        return vlc_object_hold (root);

    vlc_object_internals_t *priv = vlc_internals(root);
    vlc_object_t *ret = NULL;

    /* NOTE: nested locking here (due to recursive call) */
    vlc_mutex_lock (&vlc_internals(root)->tree_lock);

    for (priv = priv->first; priv != NULL && ret == NULL; priv = priv->next)
        ret = ObjectExists (vlc_externals (priv), obj);

    vlc_mutex_unlock (&vlc_internals(root)->tree_lock);
    return ret;
}
Beispiel #16
0
/**
 * Destroy everything.
 * This function requests the running threads to finish, waits for their
 * termination, and destroys their structure.
 * It stops the thread systems: no instance can run after this has run
 * \param p_libvlc the instance to destroy
 */
void libvlc_InternalDestroy( libvlc_int_t *p_libvlc )
{
    libvlc_priv_t *priv = libvlc_priv( p_libvlc );

    /* Destroy mutexes */
    vlc_ExitDestroy( &priv->exit );
    vlc_mutex_destroy( &priv->ml_lock );

#ifndef NDEBUG /* Hack to dump leaked objects tree */
    if( vlc_internals( p_libvlc )->i_refcount > 1 )
        while( vlc_internals( p_libvlc )->i_refcount > 0 )
            vlc_object_release( p_libvlc );
#endif

    assert( vlc_internals( p_libvlc )->i_refcount == 1 );
    vlc_object_release( p_libvlc );
}
Beispiel #17
0
Datei: objects.c Projekt: paa/vlc
/*****************************************************************************
 * find a typed object and increment its refcount
 *****************************************************************************
 * This function recursively looks for a given object type. i_mode can be one
 * of FIND_PARENT, FIND_CHILD or FIND_ANYWHERE.
 *****************************************************************************/
void * vlc_object_find( vlc_object_t *p_this, int i_type, int i_mode )
{
    vlc_object_t *p_found;

    /* If we are of the requested type ourselves, don't look further */
    if( vlc_internals (p_this)->i_object_type == i_type )
    {
        vlc_object_hold( p_this );
        return p_this;
    }

    /* Otherwise, recursively look for the object */
    if (i_mode == FIND_ANYWHERE)
        return vlc_object_find (VLC_OBJECT(p_this->p_libvlc), i_type, FIND_CHILD);

    switch (i_type)
    {
        case VLC_OBJECT_VOUT:
        case VLC_OBJECT_AOUT:
            break;
        case VLC_OBJECT_INPUT:
            /* input can only be accessed like this from children,
             * otherwise we could not promise that it is initialized */
            if (i_mode != FIND_PARENT)
                return NULL;
            break;
        default:
            return NULL;
    }

    libvlc_lock (p_this->p_libvlc);
    switch (i_mode)
    {
        case FIND_PARENT:
            p_found = FindParent (p_this, i_type);
            break;
        case FIND_CHILD:
            p_found = FindChild (vlc_internals (p_this), i_type);
            break;
        default:
            assert (0);
    }
    libvlc_unlock (p_this->p_libvlc);
    return p_found;
}
Beispiel #18
0
Datei: objects.c Projekt: paa/vlc
/**
 ****************************************************************************
 * Set the destructor of a vlc object
 *
 * This function sets the destructor of the vlc object. It will be called
 * when the object is destroyed when the its refcount reaches 0.
 * (It is called by the internal function vlc_object_destroy())
 *****************************************************************************/
void vlc_object_set_destructor( vlc_object_t *p_this,
                                vlc_destructor_t pf_destructor )
{
    vlc_object_internals_t *p_priv = vlc_internals(p_this );

    vlc_spin_lock( &p_priv->ref_spin );
    p_priv->pf_destructor = pf_destructor;
    vlc_spin_unlock( &p_priv->ref_spin );
}
Beispiel #19
0
/**
 * Destroy everything.
 * This function requests the running threads to finish, waits for their
 * termination, and destroys their structure.
 * It stops the thread systems: no instance can run after this has run
 * \param p_libvlc the instance to destroy
 */
void libvlc_InternalDestroy( libvlc_int_t *p_libvlc )
{
    libvlc_priv_t *priv = libvlc_priv( p_libvlc );

    vlc_ExitDestroy( &priv->exit );

    assert( atomic_load(&(vlc_internals(p_libvlc)->refs)) == 1 );
    vlc_object_release( p_libvlc );
}
Beispiel #20
0
static variable_t *Lookup( vlc_object_t *obj, const char *psz_name )
{
    vlc_object_internals_t *priv = vlc_internals( obj );
    variable_t **pp_var;

    vlc_mutex_lock(&priv->var_lock);
    pp_var = tfind( &psz_name, &priv->var_root, varcmp );
    return (pp_var != NULL) ? *pp_var : NULL;
}
Beispiel #21
0
/**
 * Waits until the variable is inactive (i.e. not executing a callback)
 */
static void WaitUnused(vlc_object_t *obj, variable_t *var)
{
    vlc_object_internals_t *priv = vlc_internals(obj);

    mutex_cleanup_push(&priv->var_lock);
    while (var->b_incallback)
        vlc_cond_wait(&priv->var_wait, &priv->var_lock);
    vlc_cleanup_pop();
}
Beispiel #22
0
/*****************************************************************************
 * vlc_thread_join: wait until a thread exits, inner version
 *****************************************************************************/
void vlc_thread_join( vlc_object_t *p_this )
{
    vlc_object_internals_t *p_priv = vlc_internals( p_this );

#if defined( WIN32 ) && !defined( UNDER_CE )
    HANDLE hThread;
    FILETIME create_ft, exit_ft, kernel_ft, user_ft;
    int64_t real_time, kernel_time, user_time;

    if( ! DuplicateHandle(GetCurrentProcess(),
            p_priv->thread_id,
            GetCurrentProcess(),
            &hThread,
            0,
            FALSE,
            DUPLICATE_SAME_ACCESS) )
    {
        p_priv->b_thread = false;
        return; /* We have a problem! */
    }
#endif

    vlc_join( p_priv->thread_id, NULL );

#if defined( WIN32 ) && !defined( UNDER_CE )
    /* FIXME: this could work on WinCE too... except that it seems always to
     * return 0 for exit_ft and kernel_ft */
    if( GetThreadTimes( hThread, &create_ft, &exit_ft, &kernel_ft, &user_ft ) )
    {
        real_time =
          ((((int64_t)exit_ft.dwHighDateTime)<<32)| exit_ft.dwLowDateTime) -
          ((((int64_t)create_ft.dwHighDateTime)<<32)| create_ft.dwLowDateTime);
        real_time /= 10;

        kernel_time =
          ((((int64_t)kernel_ft.dwHighDateTime)<<32)|
           kernel_ft.dwLowDateTime) / 10;

        user_time =
          ((((int64_t)user_ft.dwHighDateTime)<<32)|
           user_ft.dwLowDateTime) / 10;

        msg_Dbg( p_this, "thread times: "
                 "real %"PRId64"m%fs, kernel %"PRId64"m%fs, user %"PRId64"m%fs",
                 real_time/60/1000000,
                 (double)((real_time%(60*1000000))/1000000.0),
                 kernel_time/60/1000000,
                 (double)((kernel_time%(60*1000000))/1000000.0),
                 user_time/60/1000000,
                 (double)((user_time%(60*1000000))/1000000.0) );
    }
    CloseHandle( hThread );
#endif

    p_priv->b_thread = false;
}
Beispiel #23
0
static void PrintObject (vlc_object_t *obj, const char *prefix)
{
    vlc_object_internals_t *priv = vlc_internals(obj);

    int canc = vlc_savecancel ();
    printf (" %so %p %s, %u refs, parent %p\n", prefix, (void *)obj,
            obj->obj.object_type, atomic_load(&priv->refs),
            (void *)obj->obj.parent);
    vlc_restorecancel (canc);
}
Beispiel #24
0
Datei: objects.c Projekt: paa/vlc
/**
 ****************************************************************************
 * attach object to a parent object
 *****************************************************************************
 * This function sets p_this as a child of p_parent, and p_parent as a parent
 * of p_this. This link can be undone using vlc_object_detach.
 *****************************************************************************/
void vlc_object_attach( vlc_object_t *p_this, vlc_object_t *p_parent )
{
    if( !p_this ) return;

    vlc_object_internals_t *pap = vlc_internals (p_parent);
    vlc_object_internals_t *priv = vlc_internals (p_this);
    vlc_object_t *p_old_parent;

    priv->prev = NULL;
    vlc_object_hold (p_parent);
    libvlc_lock (p_this->p_libvlc);
#ifndef NDEBUG
    /* Reparenting an object carries a risk of invalid access to the parent,
     * from another thread. This can happen when inheriting a variable, or
     * through any direct access to vlc_object_t.p_parent. Also, reparenting
     * brings a functional bug, whereby the reparented object uses incorrect
     * old values for inherited variables (as the new parent may have different
     * variable values, especially if it is an input).
     * Note that the old parent may be already destroyed.
     * So its pointer must not be dereferenced.
     */
    if (priv->old_parent)
        msg_Info (p_this, "Reparenting an object is dangerous (%p -> %p)!",
                  priv->old_parent, p_parent);
#endif

    p_old_parent = p_this->p_parent;
    if (p_old_parent)
        vlc_object_detach_unlocked (p_this);

    /* Attach the parent to its child */
    p_this->p_parent = p_parent;

    /* Attach the child to its parent */
    priv->next = pap->first;
    if (priv->next != NULL)
        priv->next->prev = priv;
    pap->first = priv;
    libvlc_unlock (p_this->p_libvlc);

    if (p_old_parent)
        vlc_object_release (p_old_parent);
}
Beispiel #25
0
/**
 * 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_entry;
    variable_t *p_var;
#ifndef NDEBUG
    bool b_found_similar = false;
#endif

    assert( p_this );

    vlc_object_internals_t *p_priv = vlc_internals( p_this );

    vlc_mutex_lock( &p_priv->var_lock );

    p_var = Lookup( p_this, psz_name );
    if( p_var == NULL )
    {
        vlc_mutex_unlock( &p_priv->var_lock );
        return VLC_ENOVAR;
    }

    WaitUnused( p_this, p_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;
        }
#ifndef NDEBUG
        else if( p_var->p_entries[i_entry].pf_callback == pf_callback )
            b_found_similar = true;
#endif
    }

    if( i_entry < 0 )
    {
#ifndef NDEBUG
        if( b_found_similar )
            fprintf( stderr, "Calling var_DelCallback for '%s' with the same "
                             "function but not the same data.", psz_name );
        assert( 0 );
#endif
        vlc_mutex_unlock( &p_priv->var_lock );
        return VLC_EGENERIC;
    }

    REMOVE_ELEM( p_var->p_entries, p_var->i_entries, i_entry );

    vlc_mutex_unlock( &p_priv->var_lock );

    return VLC_SUCCESS;
}
Beispiel #26
0
Datei: objects.c Projekt: paa/vlc
static vlc_object_t *FindParent (vlc_object_t *p_this, int i_type)
{
    for (vlc_object_t *parent = p_this->p_parent;
         parent != NULL;
         parent = parent->p_parent)
    {
        if (vlc_internals (parent)->i_object_type == i_type)
            return vlc_object_hold (parent);
    }
    return NULL;
}
Beispiel #27
0
Datei: objects.c Projekt: paa/vlc
/**
 * Gets the list of children of an objects, and increment their reference
 * count.
 * @return a list (possibly empty) or NULL in case of error.
 */
vlc_list_t *vlc_list_children( vlc_object_t *obj )
{
    vlc_list_t *l;
    vlc_object_internals_t *priv;
    unsigned count = 0;

    libvlc_lock (obj->p_libvlc);
    for (priv = vlc_internals (obj)->first; priv; priv = priv->next)
         count++;
    l = NewList (count);
    if (likely(l != NULL))
    {
        unsigned i = 0;

        for (priv = vlc_internals (obj)->first; priv; priv = priv->next)
            l->p_values[i++].p_object = vlc_object_hold (vlc_externals (priv));
    }
    libvlc_unlock (obj->p_libvlc);
    return l;
}
Beispiel #28
0
Datei: objects.c Projekt: paa/vlc
char *vlc_object_get_name(const vlc_object_t *obj)
{
    vlc_object_internals_t *priv = vlc_internals(obj);
    char *name;

    vlc_mutex_lock (&name_lock);
    name = priv->psz_name ? strdup (priv->psz_name) : NULL;
    vlc_mutex_unlock (&name_lock);

    return name;
}
Beispiel #29
0
Datei: objects.c Projekt: paa/vlc
static vlc_object_t *FindParentName (vlc_object_t *p_this, const char *name)
{
    for (vlc_object_t *parent = p_this->p_parent;
         parent != NULL;
         parent = parent->p_parent)
    {
        const char *objname = vlc_internals (parent)->psz_name;
        if (objname && !strcmp (objname, name))
            return vlc_object_hold (parent);
    }
    return NULL;
}
Beispiel #30
0
Datei: objects.c Projekt: paa/vlc
static void vlc_object_detach_unlocked (vlc_object_t *p_this)
{
    assert (p_this->p_parent != NULL);

    vlc_object_internals_t *pap = vlc_internals (p_this->p_parent);
    vlc_object_internals_t *priv = vlc_internals (p_this);

    /* Unlink */
    if (priv->prev != NULL)
        priv->prev->next = priv->next;
    else
        pap->first = priv->next;
    if (priv->next != NULL)
        priv->next->prev = priv->prev;

    /* Remove p_this's parent */
#ifndef NDEBUG
    priv->old_parent = p_this->p_parent;
#endif
    p_this->p_parent = NULL;
}