示例#1
0
文件: vlm.c 项目: Geal/vlc
static int libvlc_vlm_init( libvlc_instance_t *p_instance )
{
    if( !p_instance->libvlc_vlm.p_event_manager )
    {
        p_instance->libvlc_vlm.p_event_manager =
            libvlc_event_manager_new( p_instance->libvlc_vlm.p_vlm );
        if( unlikely(p_instance->libvlc_vlm.p_event_manager == NULL) )
            return VLC_ENOMEM;
    }

    if( !p_instance->libvlc_vlm.p_vlm )
    {
        p_instance->libvlc_vlm.p_vlm = vlm_New( p_instance->p_libvlc_int );
        if( !p_instance->libvlc_vlm.p_vlm )
        {
            libvlc_printerr( "VLM not supported or out of memory" );
            return VLC_EGENERIC;
        }
        var_AddCallback( (vlc_object_t *)p_instance->libvlc_vlm.p_vlm,
                         "intf-event", VlmEvent,
                         p_instance->libvlc_vlm.p_event_manager );
        p_instance->libvlc_vlm.pf_release = libvlc_vlm_release_internal;
        libvlc_retain( p_instance );
    }

    return VLC_SUCCESS;
}
示例#2
0
文件: vlm.c 项目: IAPark/vlc
static int libvlc_vlm_init( libvlc_instance_t *p_instance )
{
    if( !p_instance->vlm )
    {
        p_instance->vlm = malloc( sizeof(*p_instance->vlm) );
        if( p_instance->vlm == NULL )
            return VLC_ENOMEM;
        p_instance->vlm->p_vlm = NULL;
        libvlc_event_manager_init( &p_instance->vlm->event_manager,
                                   p_instance->vlm );
    }

    if( !p_instance->vlm->p_vlm )
    {
        p_instance->vlm->p_vlm = vlm_New( p_instance->p_libvlc_int );
        if( !p_instance->vlm->p_vlm )
        {
            libvlc_printerr( "VLM not supported or out of memory" );
            return VLC_EGENERIC;
        }
        var_AddCallback( (vlc_object_t *)p_instance->vlm->p_vlm,
                         "intf-event", VlmEvent,
                         &p_instance->vlm->event_manager );
        libvlc_retain( p_instance );
    }

    return VLC_SUCCESS;
}
示例#3
0
/**************************************************************************
 *         new (Public)
 **************************************************************************/
libvlc_media_list_player_t *
libvlc_media_list_player_new(libvlc_instance_t * p_instance)
{
    libvlc_media_list_player_t * p_mlp;
    p_mlp = calloc( 1, sizeof(libvlc_media_list_player_t) );
    if (unlikely(p_mlp == NULL))
    {
        libvlc_printerr("Not enough memory");
        return NULL;
    }

    p_mlp->p_event_manager = libvlc_event_manager_new(p_mlp, p_instance);
    if (unlikely(p_mlp->p_event_manager == NULL))
    {
        free (p_mlp);
        return NULL;
    }

    libvlc_retain(p_instance);
    p_mlp->p_libvlc_instance = p_instance;
    p_mlp->i_refcount = 1;
    vlc_mutex_init(&p_mlp->object_lock);
    vlc_mutex_init(&p_mlp->mp_callback_lock);
    libvlc_event_manager_register_event_type(p_mlp->p_event_manager, libvlc_MediaListPlayerNextItemSet);
    p_mlp->e_playback_mode = libvlc_playback_mode_default;

    return p_mlp;
}
示例#4
0
/**************************************************************************
 *       new (Public)
 **************************************************************************/
libvlc_media_discoverer_t *
libvlc_media_discoverer_new( libvlc_instance_t * p_inst, const char * psz_name )
{
    /* podcast SD is a hack and only works with custom playlist callbacks. */
    if( !strncasecmp( psz_name, "podcast", 7 ) )
        return NULL;

    libvlc_media_discoverer_t *p_mdis;

    p_mdis = malloc(sizeof(*p_mdis) + strlen(psz_name) + 1);
    if( unlikely(p_mdis == NULL) )
    {
        libvlc_printerr( "Not enough memory" );
        return NULL;
    }

    p_mdis->p_libvlc_instance = p_inst;
    p_mdis->p_mlist = libvlc_media_list_new( p_inst );
    p_mdis->p_mlist->b_read_only = true;
    p_mdis->p_sd = NULL;

    vlc_dictionary_init( &p_mdis->catname_to_submedialist, 0 );
    libvlc_event_manager_init( &p_mdis->event_manager, p_mdis );

    libvlc_retain( p_inst );
    strcpy( p_mdis->name, psz_name );
    return p_mdis;
}
示例#5
0
/**************************************************************************
 *       new (Public)
 **************************************************************************/
libvlc_media_library_t *
libvlc_media_library_new( libvlc_instance_t * p_inst )
{
    libvlc_media_library_t * p_mlib;

    p_mlib = malloc(sizeof(libvlc_media_library_t));

    if( !p_mlib )
    {
        libvlc_printerr( "Not enough memory" );
        return NULL;
    }

    p_mlib->p_libvlc_instance = p_inst;
    p_mlib->i_refcount = 1;
    p_mlib->p_mlist = NULL;

    p_mlib->p_event_manager = libvlc_event_manager_new( p_mlib );
    if( unlikely(p_mlib->p_event_manager == NULL) )
    {
        free(p_mlib);
        return NULL;
    }

    libvlc_retain( p_inst );
    return p_mlib;
}
示例#6
0
文件: media_list.c 项目: Geal/vlc
/**************************************************************************
 *       libvlc_media_list_new (Public)
 *
 * Init an object.
 **************************************************************************/
libvlc_media_list_t *
libvlc_media_list_new( libvlc_instance_t * p_inst )
{
    libvlc_media_list_t * p_mlist;

    p_mlist = malloc(sizeof(libvlc_media_list_t));
    if( unlikely(p_mlist == NULL) )
    {
        libvlc_printerr( "Not enough memory" );
        return NULL;
    }

    p_mlist->p_libvlc_instance = p_inst;
    p_mlist->p_event_manager = libvlc_event_manager_new( p_mlist );
    if( unlikely(p_mlist->p_event_manager == NULL) )
    {
        free(p_mlist);
        return NULL;
    }

    p_mlist->b_read_only = false;

    vlc_mutex_init( &p_mlist->object_lock );
    vlc_mutex_init( &p_mlist->refcount_lock ); // FIXME: spinlock?

    vlc_array_init( &p_mlist->items );
    assert( p_mlist->items.i_count == 0 );
    p_mlist->i_refcount = 1;
    p_mlist->p_md = NULL;
    p_mlist->p_internal_md = NULL;

    libvlc_retain( p_inst );
    return p_mlist;
}
示例#7
0
libvlc_log_t *libvlc_log_open( libvlc_instance_t *p_instance )
{
    struct libvlc_log_t *p_log = malloc(sizeof(*p_log));
    if (unlikely(p_log == NULL))
    {
        libvlc_printerr ("Not enough memory");
        return NULL;
    }

    p_log->p_instance = p_instance;
    vlc_spin_init( &p_log->data.lock );
    p_log->data.count = 0;
    p_log->data.verbosity = p_instance->verbosity;
    p_log->p_messages = msg_Subscribe(p_instance->p_libvlc_int, handler, &p_log->data);

    if( !p_log->p_messages )
    {
        free( p_log );
        libvlc_printerr ("Not enough memory");
        return NULL;
    }

    libvlc_retain( p_instance );
    return p_log;
}
vlcjni_object *
VLCJniObject_newFromLibVlc(JNIEnv *env, jobject thiz,
                           libvlc_instance_t *p_libvlc,
                           const char **pp_error)
{
    vlcjni_object *p_obj;
    libvlc_event_manager_t *ev;

    p_obj = VLCJniObject_getInstance(env, thiz);
    if (p_obj)
    {
        *pp_error = "VLCObject.mInstanceID already exists";
        return NULL;
    }

    p_obj = calloc(1, sizeof(vlcjni_object));
    if (!p_obj)
    {
        *pp_error = "vlcjni_object calloc failed";
        goto error;
    }

    p_obj->p_owner = calloc(1, sizeof(vlcjni_object_owner));
    if (!p_obj->p_owner)
    {
        *pp_error = "vlcjni_object_owner calloc failed";
        goto error;
    }

    p_obj->p_libvlc = p_libvlc;
    libvlc_retain(p_libvlc);

    if (fields.VLCObject.getWeakReferenceID)
    {
        jobject weakCompat = (*env)->CallObjectMethod(env, thiz,
                                           fields.VLCObject.getWeakReferenceID);
        if (weakCompat)
        {
            p_obj->p_owner->weakCompat = (*env)->NewGlobalRef(env, weakCompat);
            (*env)->DeleteLocalRef(env, weakCompat);
        }
    } else
        p_obj->p_owner->weak = (*env)->NewWeakGlobalRef(env, thiz);
    if (!p_obj->p_owner->weak && !p_obj->p_owner->weakCompat)
    {
        *pp_error = "No VLCObject weak reference";
        goto error;
    }

    VLCJniObject_setInstance(env, thiz, p_obj);

    *pp_error = NULL;
    return p_obj;

error:
    VLCJniObject_release(env, thiz, p_obj);
    return NULL;
}
示例#9
0
文件: core.c 项目: paa/vlc
static void test_core (const char ** argv, int argc)
{
    libvlc_instance_t *vlc;

    log ("Testing core\n");

    vlc = libvlc_new (argc, argv);
    assert (vlc != NULL);

    libvlc_retain (vlc);
    libvlc_release (vlc);
    libvlc_release (vlc);
}
示例#10
0
/**************************************************************************
 * Create a new media descriptor object from an input_item
 * (libvlc internal)
 * That's the generic constructor
 **************************************************************************/
libvlc_media_t * libvlc_media_new_from_input_item(
                                   libvlc_instance_t *p_instance,
                                   input_item_t *p_input_item )
{
    libvlc_media_t * p_md;

    if (!p_input_item)
    {
        libvlc_printerr( "No input item given" );
        return NULL;
    }

    p_md = calloc( 1, sizeof(libvlc_media_t) );
    if( !p_md )
    {
        libvlc_printerr( "Not enough memory" );
        return NULL;
    }

    p_md->p_libvlc_instance = p_instance;
    p_md->p_input_item      = p_input_item;
    p_md->i_refcount        = 1;

    vlc_cond_init(&p_md->parsed_cond);
    vlc_mutex_init(&p_md->parsed_lock);
    vlc_mutex_init(&p_md->subitems_lock);

    p_md->state = libvlc_NothingSpecial;

    /* A media descriptor can be a playlist. When you open a playlist
     * It can give a bunch of item to read. */
    p_md->p_subitems        = NULL;

    p_md->p_event_manager = libvlc_event_manager_new( p_md );
    if( unlikely(p_md->p_event_manager == NULL) )
    {
        free(p_md);
        return NULL;
    }

    vlc_gc_incref( p_md->p_input_item );

    install_input_item_observer( p_md );

    libvlc_retain( p_instance );
    return p_md;
}
示例#11
0
文件: log.c 项目: mahaserver/MHSVLC
libvlc_log_t *libvlc_log_open( libvlc_instance_t *p_instance, libvlc_exception_t *p_e )
{
    struct libvlc_log_t *p_log =
        (struct libvlc_log_t *)malloc(sizeof(struct libvlc_log_t));

    if( !p_log ) RAISENULL( "Out of memory" );

    p_log->p_instance = p_instance;
    p_log->p_messages = msg_Subscribe(p_instance->p_libvlc_int);

    if( !p_log->p_messages )
    {
        free( p_log );
        RAISENULL( "Out of memory" );
    }

    libvlc_retain( p_instance );
    return p_log;
}
示例#12
0
/**************************************************************************
 *         new (Public)
 **************************************************************************/
libvlc_media_list_player_t *
libvlc_media_list_player_new(libvlc_instance_t * p_instance, libvlc_exception_t * p_e)
{
    (void)p_e;
    libvlc_media_list_player_t * p_mlp;
    p_mlp = calloc( 1, sizeof(libvlc_media_list_player_t) );
    if (!p_mlp)
        return NULL;

    libvlc_retain(p_instance);
    p_mlp->p_libvlc_instance = p_instance;
    p_mlp->i_refcount = 1;
    vlc_mutex_init(&p_mlp->object_lock);
    vlc_mutex_init(&p_mlp->mp_callback_lock);
    p_mlp->p_event_manager = libvlc_event_manager_new(p_mlp, p_instance, p_e);
    libvlc_event_manager_register_event_type(p_mlp->p_event_manager, libvlc_MediaListPlayerNextItemSet, p_e);
    p_mlp->e_playback_mode = libvlc_playback_mode_default;

    return p_mlp;
}
示例#13
0
文件: log.c 项目: Kafay/vlc
libvlc_log_t *libvlc_log_open( libvlc_instance_t *p_instance, libvlc_exception_t *p_e )
{
    struct libvlc_log_t *p_log =
        (struct libvlc_log_t *)malloc(sizeof(struct libvlc_log_t));

    if( !p_log ) RAISENULL( "Out of memory" );

    p_log->p_instance = p_instance;
    vlc_spin_init( &p_log->data.lock );
    p_log->data.count = 0;
    p_log->data.verbosity = p_instance->verbosity;
    p_log->p_messages = msg_Subscribe(p_instance->p_libvlc_int, handler, &p_log->data);

    if( !p_log->p_messages )
    {
        free( p_log );
        RAISENULL( "Out of memory" );
    }

    libvlc_retain( p_instance );
    return p_log;
}
示例#14
0
文件: event.c 项目: AsamQi/vlc
/**************************************************************************
 *       libvlc_event_manager_new (internal) :
 *
 * Init an object's event manager.
 **************************************************************************/
libvlc_event_manager_t *
libvlc_event_manager_new( void * p_obj, libvlc_instance_t * p_libvlc_inst )
{
    libvlc_event_manager_t * p_em;

    p_em = malloc(sizeof( libvlc_event_manager_t ));
    if( !p_em )
    {
        libvlc_printerr( "Not enough memory" );
        return NULL;
    }

    p_em->p_obj = p_obj;
    p_em->p_obj = p_obj;
    p_em->async_event_queue = NULL;
    p_em->p_libvlc_instance = p_libvlc_inst;

    libvlc_retain( p_libvlc_inst );
    vlc_array_init( &p_em->listeners_groups );
    vlc_mutex_init( &p_em->object_lock );
    vlc_mutex_init_recursive( &p_em->event_sending_lock );
    return p_em;
}
示例#15
0
/**************************************************************************
 * Create a Media Instance object.
 *
 * Refcount strategy:
 * - All items created by _new start with a refcount set to 1.
 * - Accessor _release decrease the refcount by 1, if after that
 *   operation the refcount is 0, the object is destroyed.
 * - Accessor _retain increase the refcount by 1 (XXX: to implement)
 *
 * Object locking strategy:
 * - No lock held while in constructor.
 * - When accessing any member variable this lock is held. (XXX who locks?)
 * - When attempting to destroy the object the lock is also held.
 **************************************************************************/
libvlc_media_player_t *
libvlc_media_player_new( libvlc_instance_t *instance )
{
    libvlc_media_player_t * mp;

    assert(instance);

    mp = vlc_object_create (instance->p_libvlc_int, sizeof(*mp));
    if (unlikely(mp == NULL))
    {
        libvlc_printerr("Not enough memory");
        return NULL;
    }

    /* Input */
    var_Create (mp, "rate", VLC_VAR_FLOAT|VLC_VAR_DOINHERIT);

    /* Video */
    var_Create (mp, "vout", VLC_VAR_STRING|VLC_VAR_DOINHERIT);
    var_Create (mp, "window", VLC_VAR_STRING);
    var_Create (mp, "vmem-lock", VLC_VAR_ADDRESS);
    var_Create (mp, "vmem-unlock", VLC_VAR_ADDRESS);
    var_Create (mp, "vmem-display", VLC_VAR_ADDRESS);
    var_Create (mp, "vmem-data", VLC_VAR_ADDRESS);
    var_Create (mp, "vmem-setup", VLC_VAR_ADDRESS);
    var_Create (mp, "vmem-cleanup", VLC_VAR_ADDRESS);
    var_Create (mp, "vmem-chroma", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
    var_Create (mp, "vmem-width", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "vmem-height", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "vmem-pitch", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "avcodec-hw", VLC_VAR_STRING);
    var_Create (mp, "drawable-xid", VLC_VAR_INTEGER);
#if defined (_WIN32) || defined (__OS2__)
    var_Create (mp, "drawable-hwnd", VLC_VAR_INTEGER);
#endif
#ifdef __APPLE__
    var_Create (mp, "drawable-agl", VLC_VAR_INTEGER);
    var_Create (mp, "drawable-nsobject", VLC_VAR_ADDRESS);
#endif

    var_Create (mp, "keyboard-events", VLC_VAR_BOOL);
    var_SetBool (mp, "keyboard-events", true);
    var_Create (mp, "mouse-events", VLC_VAR_BOOL);
    var_SetBool (mp, "mouse-events", true);

    var_Create (mp, "fullscreen", VLC_VAR_BOOL);
    var_Create (mp, "autoscale", VLC_VAR_BOOL);
    var_SetBool (mp, "autoscale", true);
    var_Create (mp, "scale", VLC_VAR_FLOAT);
    var_SetFloat (mp, "scale", 1.);
    var_Create (mp, "aspect-ratio", VLC_VAR_STRING);
    var_Create (mp, "crop", VLC_VAR_STRING);
    var_Create (mp, "deinterlace", VLC_VAR_INTEGER);
    var_Create (mp, "deinterlace-mode", VLC_VAR_STRING);

    var_Create (mp, "vbi-page", VLC_VAR_INTEGER);

    var_Create (mp, "marq-marquee", VLC_VAR_STRING);
    var_Create (mp, "marq-color", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "marq-opacity", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "marq-position", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "marq-refresh", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "marq-size", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "marq-timeout", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "marq-x", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "marq-y", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);

    var_Create (mp, "logo-file", VLC_VAR_STRING);
    var_Create (mp, "logo-x", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "logo-y", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "logo-delay", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "logo-repeat", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "logo-opacity", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "logo-position", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);

    var_Create (mp, "contrast", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
    var_Create (mp, "brightness", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
    var_Create (mp, "hue", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "saturation", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
    var_Create (mp, "gamma", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);

     /* Audio */
    var_Create (mp, "aout", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
    var_Create (mp, "mute", VLC_VAR_BOOL);
    var_Create (mp, "volume", VLC_VAR_FLOAT);
    var_Create (mp, "corks", VLC_VAR_INTEGER);
    var_Create (mp, "audio-filter", VLC_VAR_STRING);
    var_Create (mp, "amem-data", VLC_VAR_ADDRESS);
    var_Create (mp, "amem-setup", VLC_VAR_ADDRESS);
    var_Create (mp, "amem-cleanup", VLC_VAR_ADDRESS);
    var_Create (mp, "amem-play", VLC_VAR_ADDRESS);
    var_Create (mp, "amem-pause", VLC_VAR_ADDRESS);
    var_Create (mp, "amem-resume", VLC_VAR_ADDRESS);
    var_Create (mp, "amem-flush", VLC_VAR_ADDRESS);
    var_Create (mp, "amem-drain", VLC_VAR_ADDRESS);
    var_Create (mp, "amem-set-volume", VLC_VAR_ADDRESS);
    var_Create (mp, "amem-format", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
    var_Create (mp, "amem-rate", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
    var_Create (mp, "amem-channels", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);

    /* Video Title */
    var_Create (mp, "video-title-show", VLC_VAR_BOOL);
    var_Create (mp, "video-title-position", VLC_VAR_INTEGER);
    var_Create (mp, "video-title-timeout", VLC_VAR_INTEGER);

    /* Equalizer */
    var_Create (mp, "equalizer-preamp", VLC_VAR_FLOAT);
    var_Create (mp, "equalizer-vlcfreqs", VLC_VAR_BOOL);
    var_Create (mp, "equalizer-bands", VLC_VAR_STRING);

    mp->p_md = NULL;
    mp->state = libvlc_NothingSpecial;
    mp->p_libvlc_instance = instance;
    mp->input.p_thread = NULL;
    mp->input.p_resource = input_resource_New(VLC_OBJECT(mp));
    if (unlikely(mp->input.p_resource == NULL))
    {
        vlc_object_release(mp);
        return NULL;
    }
    audio_output_t *aout = input_resource_GetAout(mp->input.p_resource);
    if( aout != NULL )
        input_resource_PutAout(mp->input.p_resource, aout);

    vlc_mutex_init (&mp->input.lock);
    mp->i_refcount = 1;
    mp->p_event_manager = libvlc_event_manager_new(mp, instance);
    if (unlikely(mp->p_event_manager == NULL))
    {
        input_resource_Release(mp->input.p_resource);
        vlc_object_release(mp);
        return NULL;
    }
    vlc_mutex_init(&mp->object_lock);

    register_event(mp, NothingSpecial);
    register_event(mp, Opening);
    register_event(mp, Buffering);
    register_event(mp, Playing);
    register_event(mp, Paused);
    register_event(mp, Stopped);
    register_event(mp, Forward);
    register_event(mp, Backward);
    register_event(mp, EndReached);
    register_event(mp, EncounteredError);
    register_event(mp, SeekableChanged);

    register_event(mp, PositionChanged);
    register_event(mp, TimeChanged);
    register_event(mp, LengthChanged);
    register_event(mp, TitleChanged);
    register_event(mp, PausableChanged);

    register_event(mp, Vout);
    register_event(mp, ScrambledChanged);

    /* Snapshot initialization */
    register_event(mp, SnapshotTaken);

    register_event(mp, MediaChanged);

    /* Attach a var callback to the global object to provide the glue between
     * vout_thread that generates the event and media_player that re-emits it
     * with its own event manager
     *
     * FIXME: It's unclear why we want to put this in public API, and why we
     * want to expose it in such a limiting and ugly way.
     */
    var_AddCallback(mp->p_libvlc, "snapshot-file", snapshot_was_taken, mp);

    libvlc_retain(instance);
    return mp;
}
示例#16
0
/**************************************************************************
 *       new (Public)
 **************************************************************************/
libvlc_media_discoverer_t *
libvlc_media_discoverer_new( libvlc_instance_t * p_inst, const char * psz_name )
{
    /* podcast SD is a hack and only works with custom playlist callbacks. */
    if( !strncasecmp( psz_name, "podcast", 7 ) )
        return NULL;

    libvlc_media_discoverer_t *p_mdis = malloc(sizeof(*p_mdis));
    if( unlikely(!p_mdis) )
    {
        libvlc_printerr( "Not enough memory" );
        return NULL;
    }

    p_mdis->p_libvlc_instance = p_inst;
    p_mdis->p_mlist = libvlc_media_list_new( p_inst );
    p_mdis->p_mlist->b_read_only = true;
    p_mdis->running = false;

    vlc_dictionary_init( &p_mdis->catname_to_submedialist, 0 );

    p_mdis->p_event_manager = libvlc_event_manager_new( p_mdis );
    if( unlikely(p_mdis->p_event_manager == NULL) )
    {
        free( p_mdis );
        return NULL;
    }

    p_mdis->p_sd = vlc_sd_Create( (vlc_object_t*)p_inst->p_libvlc_int,
                                  psz_name );
    if( unlikely(p_mdis->p_sd == NULL) )
    {
        libvlc_printerr( "%s: no such discovery module found", psz_name );
        libvlc_media_list_release( p_mdis->p_mlist );
        libvlc_event_manager_release( p_mdis->p_event_manager );
        free( p_mdis );
        return NULL;
    }

    vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ),
                      vlc_ServicesDiscoveryItemAdded,
                      services_discovery_item_added,
                      p_mdis );
    vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ),
                      vlc_ServicesDiscoveryItemRemoved,
                      services_discovery_item_removed,
                      p_mdis );
    vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ),
                      vlc_ServicesDiscoveryStarted,
                      services_discovery_started,
                      p_mdis );
    vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ),
                      vlc_ServicesDiscoveryEnded,
                      services_discovery_ended,
                      p_mdis );
    vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ),
                      vlc_ServicesDiscoveryItemRemoveAll,
                      services_discovery_removeall,
                      p_mdis );

    libvlc_retain( p_inst );
    return p_mdis;
}