Пример #1
0
/**************************************************************************
 *       event_async_loop (private) :
 *
 * Send queued events.
 **************************************************************************/
static void * event_async_loop(void * arg)
{
    libvlc_event_manager_t * p_em = arg;
    libvlc_event_listener_t listener;
    libvlc_event_t event;

    vlc_threadvar_set(queue(p_em)->is_asynch_dispatch_thread_var, p_em);

    queue_lock(p_em);
    while (true) {
        int has_listener = pop(p_em, &listener, &event);

        if (has_listener)
        {
            queue_unlock(p_em);
            listener.pf_callback(&event, listener.p_user_data); // This might edit the queue
            queue_lock(p_em);
        }
        else
        {
            queue(p_em)->is_idle = true;

            mutex_cleanup_push(&queue(p_em)->lock);
            vlc_cond_broadcast(&queue(p_em)->signal_idle); // We'll be idle
            vlc_cond_wait(&queue(p_em)->signal, &queue(p_em)->lock);
            vlc_cleanup_pop();

            queue(p_em)->is_idle = false;
        }
    }
    queue_unlock(p_em);
    return NULL;
}
Пример #2
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;
}
Пример #3
0
void vlc_cond_signal (vlc_cond_t *p_condvar)
{
    if (!p_condvar->clock)
        return;

    /* This is suboptimal but works. */
    vlc_cond_broadcast (p_condvar);
}
Пример #4
0
/** Reports received end of stream */
static void vlc_h2_stream_end(void *ctx)
{
    struct vlc_h2_stream *s = ctx;

    msg_Dbg(SO(s), "stream %"PRIu32" closed by peer", s->id);

    s->recv_end = true;
    vlc_cond_broadcast(&s->recv_wait);
}
Пример #5
0
void vout_snapshot_End(vout_snapshot_t *snap)
{
    vlc_mutex_lock(&snap->lock);

    snap->is_available = false;

    vlc_cond_broadcast(&snap->wait);
    vlc_mutex_unlock(&snap->lock);
}
Пример #6
0
void picture_pool_Cancel(picture_pool_t *pool, bool canceled)
{
    vlc_mutex_lock(&pool->lock);
    assert(pool->refs > 0);

    pool->canceled = canceled;
    if (canceled)
        vlc_cond_broadcast(&pool->wait);
    vlc_mutex_unlock(&pool->lock);
}
Пример #7
0
/** Reports remote stream error */
static int vlc_h2_stream_reset(void *ctx, uint_fast32_t code)
{
    struct vlc_h2_stream *s = ctx;

    msg_Err(SO(s), "peer stream %"PRIu32" error: %s (0x%"PRIXFAST32")",
            s->id, vlc_h2_strerror(code), code);

    s->recv_end = true;
    vlc_cond_broadcast(&s->recv_wait);
    return 0;
}
Пример #8
0
static void vlc_rwlock_wrunlock (vlc_rwlock_t *lock)
{
    vlc_mutex_lock (&lock->mutex);
    assert (lock->writer == GetCurrentThreadId ());
    assert (lock->readers == 0);
    lock->writer = 0; /* Write unlock */

    /* Let reader and writer compete. Scheduler decides who wins. */
    vlc_cond_broadcast (&lock->wait);
    vlc_mutex_unlock (&lock->mutex);
}
Пример #9
0
JNIEXPORT void JNICALL NAME(nativeRelease)(JNIEnv *env, jobject thiz)
{
    vlc_mutex_t *parse_lock = (vlc_mutex_t *) getIntValue(env, thiz, "mNativeMediaParseLock");
    vlc_cond_t *parse_cond = (vlc_cond_t *) getIntValue(env, thiz, "mNativeMediaParseCond");
    /* wake up threads that waiting on prepare */
    vlc_mutex_lock(parse_lock);
    setIntValue(env, thiz, "mNativeMediaParsed", 4);
    vlc_cond_broadcast(parse_cond);
    vlc_mutex_unlock(parse_lock);
    jint mLibVlcMediaPlayer = getIntValue(env, thiz, "mLibVlcMediaPlayer");
    if (mLibVlcMediaPlayer != 0)
    {
        libvlc_event_manager_t *em;
        libvlc_media_player_t *mp = (libvlc_media_player_t*) mLibVlcMediaPlayer;
        libvlc_media_t *md = libvlc_media_player_get_media(mp);
        if (md) {
            em = libvlc_media_event_manager(md);
            for (int i = 0; i < sizeof(md_listening) / sizeof(*md_listening); i++)
            {
                libvlc_event_detach(em, md_listening[i], vlc_event_callback, thiz);
            }
        }
        em = libvlc_media_player_event_manager(mp);
        for (int i = 0; i < sizeof(mp_listening) / sizeof(*mp_listening); i++)
        {
            libvlc_event_detach(em, mp_listening[i], vlc_event_callback, thiz);
        }
        libvlc_media_player_stop(mp);
        libvlc_media_player_release(mp);
        setIntValue(env, thiz, "mLibVlcMediaPlayer", 0);
    }
    jint mLibVlcInstance = getIntValue(env, thiz, "mLibVlcInstance");
    if (mLibVlcInstance != 0)
    {
        libvlc_instance_t *instance = (libvlc_instance_t*) mLibVlcInstance;
        libvlc_release(instance);
        setIntValue(env, thiz, "mLibVlcInstance", 0);
    }
    setIntValue(env, thiz, "mNativeMediaBufferingCount", 0);
    vlc_mutex_destroy(parse_lock);
    free(parse_lock);
    setIntValue(env, thiz, "mNativeMediaParseLock", 0);
    vlc_cond_destroy(parse_cond);
    free(parse_cond);
    setIntValue(env, thiz, "mNativeMediaParseCond", 0);
    freeClasses(env, thiz);
}
Пример #10
0
Файл: thread.c Проект: Tilka/vlc
void vlc_mutex_unlock (vlc_mutex_t *p_mutex)
{
    if (!p_mutex->dynamic)
    {   /* static mutexes */
        assert (p_mutex != &super_mutex); /* this one cannot be static */

        vlc_mutex_lock (&super_mutex);
        assert (p_mutex->locked);
        p_mutex->locked = false;
        if (p_mutex->contention)
            vlc_cond_broadcast (&super_variable);
        vlc_mutex_unlock (&super_mutex);
        return;
    }

    DosReleaseMutexSem( p_mutex->hmtx );
}
Пример #11
0
void vlc_mutex_unlock (vlc_mutex_t *p_mutex)
{
    if (!p_mutex->dynamic)
    {   /* static mutexes */
        assert (p_mutex != &super_mutex); /* this one cannot be static */

        vlc_mutex_lock (&super_mutex);
        assert (p_mutex->locked);
        p_mutex->locked = false;
        if (p_mutex->contention)
            vlc_cond_broadcast (&super_variable);
        vlc_mutex_unlock (&super_mutex);
        return;
    }

    LeaveCriticalSection (&p_mutex->mutex);
}
Пример #12
0
static void send_parsed_changed( libvlc_media_t *p_md,
                                 libvlc_media_parsed_status_t new_status )
{
    libvlc_event_t event;

    vlc_mutex_lock( &p_md->parsed_lock );
    if( p_md->parsed_status == new_status )
    {
        vlc_mutex_unlock( &p_md->parsed_lock );
        return;
    }

    /* Legacy: notify libvlc_media_parse */
    if( !p_md->is_parsed )
    {
        p_md->is_parsed = true;
        vlc_cond_broadcast( &p_md->parsed_cond );
    }

    p_md->parsed_status = new_status;
    if( p_md->parsed_status == libvlc_media_parsed_status_skipped )
        p_md->has_asked_preparse = false;

    vlc_mutex_unlock( &p_md->parsed_lock );

    if( new_status == libvlc_media_parsed_status_done )
    {
        libvlc_media_list_t *p_subitems = media_get_subitems( p_md, false );
        if( p_subitems != NULL )
        {
            /* notify the media list */
            libvlc_media_list_lock( p_subitems );
            libvlc_media_list_internal_end_reached( p_subitems );
            libvlc_media_list_unlock( p_subitems );
        }
    }

    /* Construct the event */
    event.type = libvlc_MediaParsedChanged;
    event.u.media_parsed_changed.new_status = new_status;

    /* Send the event */
    libvlc_event_send( p_md->p_event_manager, &event );
}
Пример #13
0
/**************************************************************************
 * input_item_preparsed_changed (Private) (vlc event Callback)
 **************************************************************************/
static void input_item_preparsed_changed(const vlc_event_t *p_event,
                                         void * user_data)
{
    libvlc_media_t *media = user_data;
    libvlc_event_t event;

    /* Eventually notify libvlc_media_parse() */
    vlc_mutex_lock(&media->parsed_lock);
    media->is_parsed = true;
    vlc_cond_broadcast(&media->parsed_cond);
    vlc_mutex_unlock(&media->parsed_lock);


    /* Construct the event */
    event.type = libvlc_MediaParsedChanged;
    event.u.media_parsed_changed.new_status =
        p_event->u.input_item_preparsed_changed.new_status;

    /* Send the event */
    libvlc_event_send(media->p_event_manager, &event);
}
Пример #14
0
void vout_snapshot_Set(vout_snapshot_t *snap,
                       const video_format_t *fmt,
                       const picture_t *picture)
{
    if (!fmt)
        fmt = &picture->format;

    vlc_mutex_lock(&snap->lock);
    while (snap->request_count > 0) {
        picture_t *dup = picture_NewFromFormat(fmt);
        if (!dup)
            break;

        picture_Copy(dup, picture);

        dup->p_next = snap->picture;
        snap->picture = dup;
        snap->request_count--;
    }
    vlc_cond_broadcast(&snap->wait);
    vlc_mutex_unlock(&snap->lock);
}
Пример #15
0
static void send_preparsed_event(libvlc_media_t *media)
{
    libvlc_event_t event;

    /* Eventually notify libvlc_media_parse() */
    vlc_mutex_lock(&media->parsed_lock);
    if (media->is_parsed == true)
    {
        vlc_mutex_unlock(&media->parsed_lock);
        return;
    }
    media->is_parsed = true;
    vlc_cond_broadcast(&media->parsed_cond);
    vlc_mutex_unlock(&media->parsed_lock);


    /* Construct the event */
    event.type = libvlc_MediaParsedChanged;
    event.u.media_parsed_changed.new_status = true;

    /* Send the event */
    libvlc_event_send(media->p_event_manager, &event);
}
Пример #16
0
static void TriggerListCallback(vlc_object_t *obj, variable_t *var,
                                const char *name, int action, vlc_value_t *val)
{
    assert(obj != NULL);

    size_t count = var->list_callbacks.i_entries;
    if (count == 0)
        return;

    callback_entry_t *entries = var->list_callbacks.p_entries;
    vlc_object_internals_t *priv = vlc_internals(obj);

    assert(!var->b_incallback);
    var->b_incallback = true;
    vlc_mutex_unlock(&priv->var_lock);

    for (size_t i = 0; i < count; i++)
        entries[i].pf_list_callback(obj, name, action, val,
                                      entries[i].p_data);

    vlc_mutex_lock(&priv->var_lock);
    var->b_incallback = false;
    vlc_cond_broadcast(&priv->var_wait);
}
Пример #17
0
/**
 * Add a message to a queue
 *
 * This function provides basic functionnalities to other msg_* functions.
 * It adds a message to a queue (after having printed all stored messages if it
 * is full). If the message can't be converted to string in memory, it issues
 * a warning.
 */
static void QueueMsg( vlc_object_t *p_this, int i_type, const char *psz_module,
                      const char *psz_format, va_list _args )
{
    assert (p_this);
    libvlc_priv_t *priv = libvlc_priv (p_this->p_libvlc);
    int         i_header_size;             /* Size of the additionnal header */
    vlc_object_t *p_obj;
    char *       psz_str = NULL;                 /* formatted message string */
    char *       psz_header = NULL;
    va_list      args;

    if( p_this->i_flags & OBJECT_FLAGS_QUIET ||
        (p_this->i_flags & OBJECT_FLAGS_NODBG && i_type == VLC_MSG_DBG) )
        return;

#ifndef __GLIBC__
    /* Expand %m to strerror(errno) - only once */
    char buf[strlen( psz_format ) + 2001], *ptr;
    strcpy( buf, psz_format );
    ptr = (char*)buf;
    psz_format = (const char*) buf;

    for( ;; )
    {
        ptr = strchr( ptr, '%' );
        if( ptr == NULL )
            break;

        if( ptr[1] == 'm' )
        {
            char errbuf[2001];
            size_t errlen;

#ifndef WIN32
            strerror_r( errno, errbuf, 1001 );
#else
            int sockerr = WSAGetLastError( );
            if( sockerr )
            {
                strncpy( errbuf, net_strerror( sockerr ), 1001 );
                WSASetLastError( sockerr );
            }
            if ((sockerr == 0)
             || (strcmp ("Unknown network stack error", errbuf) == 0))
                strncpy( errbuf, strerror( errno ), 1001 );
#endif
            errbuf[1000] = 0;

            /* Escape '%' from the error string */
            for( char *percent = strchr( errbuf, '%' );
                 percent != NULL;
                 percent = strchr( percent + 2, '%' ) )
            {
                memmove( percent + 1, percent, strlen( percent ) + 1 );
            }

            errlen = strlen( errbuf );
            memmove( ptr + errlen, ptr + 2, strlen( ptr + 2 ) + 1 );
            memcpy( ptr, errbuf, errlen );
            break; /* Only once, so we don't overflow */
        }

        /* Looks for conversion specifier... */
        do
            ptr++;
        while( *ptr && ( strchr( "diouxXeEfFgGaAcspn%", *ptr ) == NULL ) );
        if( *ptr )
            ptr++; /* ...and skip it */
    }
#endif

    /* Convert message to string  */
    vlc_va_copy( args, _args );
    if( vasprintf( &psz_str, psz_format, args ) == -1 )
        psz_str = NULL;
    va_end( args );

    if( psz_str == NULL )
    {
        int canc = vlc_savecancel (); /* Do not print half of a message... */
#ifdef __GLIBC__
        fprintf( stderr, "main warning: can't store message (%m): " );
#else
        char psz_err[1001];
#ifndef WIN32
        /* we're not using GLIBC, so we are sure that the error description
         * will be stored in the buffer we provide to strerror_r() */
        strerror_r( errno, psz_err, 1001 );
#else
        strncpy( psz_err, strerror( errno ), 1001 );
#endif
        psz_err[1000] = '\0';
        fprintf( stderr, "main warning: can't store message (%s): ", psz_err );
#endif
        vlc_va_copy( args, _args );
        /* We should use utf8_vfprintf - but it calls malloc()... */
        vfprintf( stderr, psz_format, args );
        va_end( args );
        fputs( "\n", stderr );
        vlc_restorecancel (canc);
        return;
    }

    msg_item_t * p_item = malloc (sizeof (*p_item));

    if (p_item == NULL)
        return; /* Uho! */

    vlc_gc_init (p_item, msg_Free);
    p_item->psz_module = p_item->psz_msg = p_item->psz_header = NULL;



    i_header_size = 0;
    p_obj = p_this;
    while( p_obj != NULL )
    {
        char *psz_old = NULL;
        if( p_obj->psz_header )
        {
            i_header_size += strlen( p_obj->psz_header ) + 4;
            if( psz_header )
            {
                psz_old = strdup( psz_header );
                psz_header = (char*)realloc( psz_header, i_header_size );
                snprintf( psz_header, i_header_size , "[%s] %s",
                          p_obj->psz_header, psz_old );
            }
            else
            {
                psz_header = (char *)malloc( i_header_size );
                snprintf( psz_header, i_header_size, "[%s]",
                          p_obj->psz_header );
            }
        }
        free( psz_old );
        p_obj = p_obj->p_parent;
    }

    /* Fill message information fields */
    p_item->i_type =        i_type;
    p_item->i_object_id =   (uintptr_t)p_this;
    p_item->psz_object_type = p_this->psz_object_type;
    p_item->psz_module =    strdup( psz_module );
    p_item->psz_msg =       psz_str;
    p_item->psz_header =    psz_header;

    PrintMsg( p_this, p_item );

    msg_bank_t *p_queue = &QUEUE;
    vlc_mutex_lock( &p_queue->lock );
#define bank p_queue
    for (int i = 0; i < bank->i_sub; i++)
    {
        msg_subscription_t *sub = bank->pp_sub[i];
        if ((sub->end + 1 - sub->begin) % VLC_MSG_QSIZE)
        {
            sub->items[sub->end++] = msg_Hold (p_item);
            if (sub->end == VLC_MSG_QSIZE)
                sub->end = 0;
        }
        else
            sub->overruns++;
    }
    vlc_cond_broadcast (&bank->wait);
    vlc_mutex_unlock (&bank->lock);
    msg_Release (p_item);
}
Пример #18
0
static void* Thread( void* data )
{
    struct background_worker* worker = data;

    for( ;; )
    {
        struct bg_queued_item* item = NULL;
        void* handle;

        vlc_mutex_lock( &worker->lock );
        for( ;; )
        {
            if( vlc_array_count( &worker->tail.data ) )
            {
                item = vlc_array_item_at_index( &worker->tail.data, 0 );
                handle = NULL;

                vlc_array_remove( &worker->tail.data, 0 );
            }

            if( worker->head.deadline == VLC_TS_0 && item == NULL )
                worker->head.active = false;
            worker->head.id = item ? item->id : NULL;
            vlc_cond_broadcast( &worker->head.wait );

            if( item )
            {
                if( item->timeout > 0 )
                    worker->head.deadline = mdate() + item->timeout * 1000;
                else
                    worker->head.deadline = INT64_MAX;
            }
            else if( worker->head.deadline != VLC_TS_0 )
            {
                /* Wait 1 seconds for new inputs before terminating */
                mtime_t deadline = mdate() + INT64_C(1000000);
                int ret = vlc_cond_timedwait( &worker->tail.wait,
                                              &worker->lock, deadline );
                if( ret != 0 )
                {
                    /* Timeout: if there is still no items, the thread will be
                     * terminated at next loop iteration (active = false). */
                    worker->head.deadline = VLC_TS_0;
                }
                continue;
            }
            break;
        }

        if( !worker->head.active )
        {
            vlc_mutex_unlock( &worker->lock );
            break;
        }
        vlc_mutex_unlock( &worker->lock );

        assert( item != NULL );

        if( worker->conf.pf_start( worker->owner, item->entity, &handle ) )
        {
            worker->conf.pf_release( item->entity );
            free( item );
            continue;
        }

        for( ;; )
        {
            vlc_mutex_lock( &worker->lock );

            bool const b_timeout = worker->head.deadline <= mdate();
            worker->head.probe_request = false;

            vlc_mutex_unlock( &worker->lock );

            if( b_timeout ||
                worker->conf.pf_probe( worker->owner, handle ) )
            {
                worker->conf.pf_stop( worker->owner, handle );
                worker->conf.pf_release( item->entity );
                free( item );
                break;
            }

            vlc_mutex_lock( &worker->lock );
            if( worker->head.probe_request == false &&
                worker->head.deadline > mdate() )
            {
                vlc_cond_timedwait( &worker->head.worker_wait, &worker->lock,
                                     worker->head.deadline );
            }
            vlc_mutex_unlock( &worker->lock );
        }
    }

    return NULL;
}
Пример #19
0
void vlc_cond_signal (vlc_cond_t *p_condvar)
{
    /* This is suboptimal but works. */
    vlc_cond_broadcast (p_condvar);
}
Пример #20
0
static void vlc_event_callback(const libvlc_event_t *ev, void *data)
{
    JNIEnv *env;
    jobject obj_VlcMediaPlayer = g_obj_VlcMediaPlayer;
    jobject obj_VlcEvent;
    int trigger = 1;

    if ((*gJVM)->AttachCurrentThread(gJVM, &env, 0) < 0)
        return;
    obj_VlcEvent = (*env)->AllocObject(env, clz_VlcEvent);
    if (!obj_VlcEvent)
        return;
    libvlc_media_t *media = (libvlc_media_t *) getIntValue(env, obj_VlcMediaPlayer, "mLibVlcMedia");
    char *mrl = libvlc_media_get_mrl(media);
    libvlc_media_player_t *mp = (libvlc_media_player_t *) getIntValue(env, obj_VlcMediaPlayer, "mLibVlcMediaPlayer");
    vlc_mutex_t *parse_lock = (vlc_mutex_t *) getIntValue(env, obj_VlcMediaPlayer, "mNativeMediaParseLock");
    vlc_cond_t *parse_cond = (vlc_cond_t *) getIntValue(env, obj_VlcMediaPlayer, "mNativeMediaParseCond");
    (*env)->SetIntField(env, obj_VlcEvent, f_VlcEvent_eventType, ev->type);
    switch (ev->type) {
    case libvlc_MediaDurationChanged: {
        int64_t duration = ev->u.media_duration_changed.new_duration;
        (*env)->SetLongField(env, obj_VlcEvent, f_VlcEvent_longValue, (jlong) duration);
        break;
    }
    case libvlc_MediaStateChanged: {
        int state = ev->u.media_state_changed.new_state;
        (*env)->SetIntField(env, obj_VlcEvent, f_VlcEvent_intValue, state);
        /* wake up if there is an error */
        if (state == libvlc_MediaPlayerEncounteredError) {
            vlc_mutex_lock(parse_lock);
            setIntValue(env, obj_VlcMediaPlayer, "mNativeMediaParsed", 2);
            vlc_cond_broadcast(parse_cond);
            vlc_mutex_unlock(parse_lock);
        }
        break;
    }
    case libvlc_MediaParsedChanged: {
        libvlc_media_player_play(mp);
        trigger = 0;
        break;
    }
    case libvlc_MediaPlayerBuffering: {
        float cache = ev->u.media_player_buffering.new_cache;
        (*env)->SetFloatField(env, obj_VlcEvent, f_VlcEvent_floatValue, cache);
        int count = getIntValue(env, obj_VlcMediaPlayer, "mNativeMediaBufferingCount");
        if ((int) cache == 100) {
            setIntValue(env, obj_VlcMediaPlayer, "mNativeMediaBufferingCount", count + 1);
            /* if it's the first time */
            if (count == 0) {
                /* send buffering update event now */
                (*env)->CallVoidMethod(env, obj_VlcMediaPlayer, m_VlcMediaPlayer_onVlcEvent, obj_VlcEvent);
                libvlc_media_player_set_pause(mp, 1);
                /* asynchonous preparing is done */
                vlc_mutex_lock(parse_lock);
                setIntValue(env, obj_VlcMediaPlayer, "mNativeMediaParsed", 1);
                vlc_cond_broadcast(parse_cond);
                vlc_mutex_unlock(parse_lock);
                /* simulate a media prepared event */
                (*env)->SetIntField(env, obj_VlcEvent, f_VlcEvent_eventType, libvlc_MediaParsedChanged);
                (*env)->SetBooleanField(env, obj_VlcEvent, f_VlcEvent_booleanValue, 1);
            }
        }
        break;
    }
    case libvlc_MediaPlayerTimeChanged: {
        int64_t time = ev->u.media_player_time_changed.new_time;
        (*env)->SetLongField(env, obj_VlcEvent, f_VlcEvent_longValue, (jlong) time);
        break;
    }
    case libvlc_MediaPlayerPositionChanged: {
        float position = ev->u.media_player_position_changed.new_position;
        (*env)->SetFloatField(env, obj_VlcEvent, f_VlcEvent_floatValue, position);
        break;
    }
    case libvlc_MediaPlayerSeekableChanged: {
        int seekable = ev->u.media_player_seekable_changed.new_seekable;
        (*env)->SetBooleanField(env, obj_VlcEvent, f_VlcEvent_booleanValue, seekable > 0);
        break;
    }
    case libvlc_MediaPlayerPausableChanged: {
        int pausable = ev->u.media_player_pausable_changed.new_pausable;
        (*env)->SetBooleanField(env, obj_VlcEvent, f_VlcEvent_booleanValue, pausable > 0);
        break;
    }
    case libvlc_MediaPlayerTitleChanged: {
        int title = ev->u.media_player_title_changed.new_title;
        (*env)->SetIntField(env, obj_VlcEvent, f_VlcEvent_intValue, title);
        break;
    }
    case libvlc_MediaPlayerSnapshotTaken: {
        char *p = ev->u.media_player_snapshot_taken.psz_filename;
        jstring path = (*env)->NewStringUTF(env, p);
        (*env)->SetObjectField(env, obj_VlcEvent, f_VlcEvent_stringValue, path);
        break;
    }
    case libvlc_MediaPlayerLengthChanged: {
        int64_t length = ev->u.media_player_length_changed.new_length;
        (*env)->SetLongField(env, obj_VlcEvent, f_VlcEvent_longValue, (jlong) length);
        break;
    }
    default:
        break;
    }
    if (trigger)
        (*env)->CallVoidMethod(env, obj_VlcMediaPlayer, m_VlcMediaPlayer_onVlcEvent, obj_VlcEvent);
    (*env)->DeleteLocalRef(env, obj_VlcEvent);
    free(mrl);
    /* EXPLAIN: this is called in pthread wrapper routines */
    // (*gJVM)->DetachCurrentThread(gJVM);
}