static void
MediaPlayer_newCommon(JNIEnv *env, jobject thiz, vlcjni_object *p_obj,
                      jobject jwindow)
{
    p_obj->p_sys = calloc(1, sizeof(vlcjni_object_sys));

    if (!p_obj->u.p_mp || !p_obj->p_sys)
    {
        VLCJniObject_release(env, thiz, p_obj);
        throw_IllegalStateException(env, "can't create MediaPlayer instance");
        return;
    }
    p_obj->p_sys->jwindow = (*env)->NewGlobalRef(env, jwindow);
    if (!p_obj->p_sys->jwindow)
    {
        VLCJniObject_release(env, thiz, p_obj);
        throw_IllegalStateException(env, "can't create MediaPlayer instance");
        return;
    }
    libvlc_media_player_set_android_context(p_obj->u.p_mp, libvlc_get_jvm(),
                                            p_obj->p_sys->jwindow);

    VLCJniObject_attachEvents(p_obj, MediaPlayer_event_cb,
                              libvlc_media_player_event_manager(p_obj->u.p_mp),
                              mp_events);
}
void
Java_org_videolan_libvlc_MediaDiscoverer_nativeNew(JNIEnv *env,
                                                   jobject thiz, jobject libVlc,
                                                   jstring jname)
{
    vlcjni_object *p_obj;
    const char* p_name;

    if (!jname || !(p_name = (*env)->GetStringUTFChars(env, jname, 0)))
    {
        throw_Exception(env, VLCJNI_EX_ILLEGAL_STATE, "jname invalid");
        return;
    }

    p_obj = VLCJniObject_newFromJavaLibVlc(env, thiz, libVlc);
    if (!p_obj)
    {
        (*env)->ReleaseStringUTFChars(env, jname, p_name);
        return;
    }

    p_obj->u.p_md = libvlc_media_discoverer_new(p_obj->p_libvlc, p_name);

    (*env)->ReleaseStringUTFChars(env, jname, p_name);

    if (!p_obj->u.p_md)
    {
        VLCJniObject_release(env, thiz, p_obj);
        throw_Exception(env, VLCJNI_EX_ILLEGAL_STATE,
                        "can't create MediaDiscoverer instance");
        return;
    }
}
void
Java_org_videolan_libvlc_MediaPlayer_nativeRelease(JNIEnv *env, jobject thiz)
{
    vlcjni_object *p_obj = VLCJniObject_getInstance(env, thiz);

    if (!p_obj)
        return;

    /* TODO: REMOVE */
    libvlc_event_manager_t *ev = libvlc_media_player_event_manager(p_obj->u.p_mp);
    static const libvlc_event_type_t mp_events[] = {
        libvlc_MediaPlayerPlaying,
        libvlc_MediaPlayerPaused,
        libvlc_MediaPlayerEndReached,
        libvlc_MediaPlayerStopped,
        libvlc_MediaPlayerVout,
        libvlc_MediaPlayerPositionChanged,
        libvlc_MediaPlayerTimeChanged,
        libvlc_MediaPlayerEncounteredError,
        libvlc_MediaPlayerESAdded,
        libvlc_MediaPlayerESDeleted,
    };

    for(int i = 0; i < (sizeof(mp_events) / sizeof(*mp_events)); i++)
        libvlc_event_detach(ev, mp_events[i], vlc_event_callback, NULL);
    libvlc_media_player_release(p_obj->u.p_mp);

    VLCJniObject_release(env, thiz, p_obj);
}
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;
}
void
Java_org_videolan_libvlc_MediaDiscoverer_nativeRelease(JNIEnv *env,
                                                       jobject thiz)
{
    vlcjni_object *p_obj = VLCJniObject_getInstance(env, thiz);

    if (!p_obj)
        return;

    libvlc_media_discoverer_release(p_obj->u.p_md);

    VLCJniObject_release(env, thiz, p_obj);
}
void
Java_org_videolan_libvlc_MediaPlayer_nativeRelease(JNIEnv *env, jobject thiz)
{
    vlcjni_object *p_obj = VLCJniObject_getInstance(env, thiz);

    if (!p_obj)
        return;

    libvlc_media_player_release(p_obj->u.p_mp);

    if (p_obj->p_sys && p_obj->p_sys->jwindow)
        (*env)->DeleteGlobalRef(env, p_obj->p_sys->jwindow);

    free(p_obj->p_sys);

    VLCJniObject_release(env, thiz, p_obj);
}
void
Java_org_videolan_libvlc_MediaPlayer_nativeNewFromLibVlc(JNIEnv *env,
                                                         jobject thiz,
                                                         jobject libvlc)
{
    vlcjni_object *p_obj = VLCJniObject_newFromJavaLibVlc(env, thiz, libvlc);
    if (!p_obj)
        return;

    /* Create a media player playing environment */
    p_obj->u.p_mp = libvlc_media_player_new(p_obj->p_libvlc);
    if (!p_obj->u.p_mp)
    {
        VLCJniObject_release(env, thiz, p_obj);
        throw_IllegalStateException(env, "can't create MediaPlayer instance");
        return;
    }
    libvlc_media_player_set_video_title_display(p_obj->u.p_mp,
                                                libvlc_position_disable, 0);

    /* TODO NOT HERE */
    /* Connect the event manager */
    libvlc_event_manager_t *ev = libvlc_media_player_event_manager(p_obj->u.p_mp);
    static const libvlc_event_type_t mp_events[] = {
        libvlc_MediaPlayerPlaying,
        libvlc_MediaPlayerPaused,
        libvlc_MediaPlayerEndReached,
        libvlc_MediaPlayerStopped,
        libvlc_MediaPlayerVout,
        libvlc_MediaPlayerPositionChanged,
        libvlc_MediaPlayerTimeChanged,
        libvlc_MediaPlayerEncounteredError,
        libvlc_MediaPlayerESAdded,
        libvlc_MediaPlayerESDeleted,
    };
    for(int i = 0; i < (sizeof(mp_events) / sizeof(*mp_events)); i++)
        libvlc_event_attach(ev, mp_events[i], vlc_event_callback, NULL);
}