/************************************************************************** * 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; }
/********************************************************************** * 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; }
void vlc_cond_signal (vlc_cond_t *p_condvar) { if (!p_condvar->clock) return; /* This is suboptimal but works. */ vlc_cond_broadcast (p_condvar); }
/** 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); }
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); }
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); }
/** 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; }
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); }
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); }
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 ); }
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); }
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 ); }
/************************************************************************** * 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); }
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); }
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); }
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); }
/** * 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); }
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; }
void vlc_cond_signal (vlc_cond_t *p_condvar) { /* This is suboptimal but works. */ vlc_cond_broadcast (p_condvar); }
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); }