static void Run( fingerprinter_thread_t *p_fingerprinter ) { fingerprinter_sys_t *p_sys = p_fingerprinter->p_sys; /* main loop */ for (;;) { vlc_mutex_lock( &p_sys->processing.lock ); mutex_cleanup_push( &p_sys->processing.lock ); vlc_cond_timedwait( &p_sys->incoming_queue_filled, &p_sys->processing.lock, mdate() + 1000000 ); vlc_cleanup_run(); QueueIncomingRequests( p_sys ); vlc_mutex_lock( &p_sys->processing.lock ); // L0 mutex_cleanup_push( &p_sys->processing.lock ); vlc_cleanup_push( cancelRun, p_sys ); // C1 //** for ( p_sys->i = 0 ; p_sys->i < vlc_array_count( p_sys->processing.queue ); p_sys->i++ ) { fingerprint_request_t *p_data = vlc_array_item_at_index( p_sys->processing.queue, p_sys->i ); acoustid_fingerprint_t acoustid_print; memset( &acoustid_print , 0, sizeof(acoustid_fingerprint_t) ); vlc_cleanup_push( clearPrint, &acoustid_print ); // C2 p_sys->psz_uri = input_item_GetURI( p_data->p_item ); if ( p_sys->psz_uri ) { /* overwrite with hint, as in this case, fingerprint's session will be truncated */ if ( p_data->i_duration ) acoustid_print.i_duration = p_data->i_duration; DoFingerprint( VLC_OBJECT(p_fingerprinter), p_sys, &acoustid_print ); DoAcoustIdWebRequest( VLC_OBJECT(p_fingerprinter), &acoustid_print ); fill_metas_with_results( p_data, &acoustid_print ); FREENULL( p_sys->psz_uri ); } vlc_cleanup_run( ); // C2 /* copy results */ vlc_mutex_lock( &p_sys->results.lock ); vlc_array_append( p_sys->results.queue, p_data ); vlc_mutex_unlock( &p_sys->results.lock ); vlc_testcancel(); } if ( vlc_array_count( p_sys->processing.queue ) ) { var_TriggerCallback( p_fingerprinter, "results-available" ); vlc_array_clear( p_sys->processing.queue ); } vlc_cleanup_pop( ); // C1 //** vlc_cleanup_run(); // L0 } }
static void *msg_thread (void *data) { msg_subscription_t *sub = data; msg_bank_t *bank = libvlc_bank (sub->instance); vlc_mutex_lock (&bank->lock); for (;;) { /* Wait for messages */ assert (sub->begin < VLC_MSG_QSIZE); assert (sub->end < VLC_MSG_QSIZE); while (sub->begin != sub->end) { msg_item_t *msg = sub->items[sub->begin]; unsigned overruns = sub->overruns; if (++sub->begin == VLC_MSG_QSIZE) sub->begin = 0; sub->overruns = 0; vlc_mutex_unlock (&bank->lock); sub->func (sub->opaque, msg, overruns); msg_Release (msg); vlc_mutex_lock (&bank->lock); } mutex_cleanup_push (&bank->lock); vlc_cond_wait (&bank->wait, &bank->lock); vlc_cleanup_pop (); } assert (0); }
/** * main SAP handler thread * \param p_this the SAP Handler object * \return nothing */ static void *RunThread (void *self) { sap_address_t *addr = self; vlc_mutex_lock (&addr->lock); mutex_cleanup_push (&addr->lock); for (;;) { sap_session_t *p_session; mtime_t deadline; while (addr->first == NULL) vlc_cond_wait (&addr->wait, &addr->lock); assert (addr->session_count > 0); deadline = mdate (); for (p_session = addr->first; p_session; p_session = p_session->next) { send (addr->fd, p_session->data, p_session->length, 0); deadline += addr->interval * CLOCK_FREQ / addr->session_count; if (vlc_cond_timedwait (&addr->wait, &addr->lock, deadline) == 0) break; /* list may have changed! */ } } vlc_cleanup_pop (); assert (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; }
/** * 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(); }
/***************************************************************************** * Run: Thread entry-point ****************************************************************************/ static void* Run( void *data ) { services_discovery_t *p_sd = ( services_discovery_t * )data; services_discovery_sys_t *p_sys = p_sd->p_sys; lua_State *L = p_sys->L; int cancel = vlc_savecancel(); lua_getglobal( L, "main" ); if( !lua_isfunction( L, lua_gettop( L ) ) || lua_pcall( L, 0, 1, 0 ) ) { msg_Err( p_sd, "Error while running script %s, " "function main(): %s", p_sys->psz_filename, lua_tostring( L, lua_gettop( L ) ) ); lua_pop( L, 1 ); vlc_restorecancel( cancel ); return NULL; } msg_Dbg( p_sd, "LuaSD script loaded: %s", p_sys->psz_filename ); /* Force garbage collection, because the core will keep the SD * open, but lua will never gc until lua_close(). */ lua_gc( L, LUA_GCCOLLECT, 0 ); vlc_restorecancel( cancel ); /* Main loop to handle search requests */ vlc_mutex_lock( &p_sys->lock ); mutex_cleanup_push( &p_sys->lock ); while( !p_sys->b_exiting ) { /* Wait for a request */ while( !p_sys->i_query ) vlc_cond_wait( &p_sys->cond, &p_sys->lock ); /* Execute every query each one protected against cancelation */ cancel = vlc_savecancel(); while( !p_sys->b_exiting && p_sys->i_query ) { char *psz_query = p_sys->ppsz_query[p_sys->i_query - 1]; REMOVE_ELEM( (char **), p_sys->ppsz_query, p_sys->i_query, p_sys->i_query - 1 ); // sunqueen modify vlc_mutex_unlock( &p_sys->lock ); DoSearch( p_sd, psz_query ); free( psz_query ); vlc_mutex_lock( &p_sys->lock ); } /* Force garbage collection, because the core will keep the SD * open, but lua will never gc until lua_close(). */ lua_gc( L, LUA_GCCOLLECT, 0 ); vlc_restorecancel( cancel ); } vlc_cleanup_run(); return NULL; }
/** * Receives stream data. * * Dequeues pending incoming data for an HTTP/2 stream. If there is currently * no data block, wait for one. * * \return a VLC data block, or NULL on stream error or end of stream */ static block_t *vlc_h2_stream_read(struct vlc_http_stream *stream) { struct vlc_h2_stream *s = (struct vlc_h2_stream *)stream; struct vlc_h2_conn *conn = s->conn; struct vlc_h2_frame *f; vlc_h2_stream_lock(s); while ((f = s->recv_head) == NULL && !s->recv_end && !s->interrupted) { mutex_cleanup_push(&conn->lock); vlc_cond_wait(&s->recv_wait, &conn->lock); vlc_cleanup_pop(); } if (f == NULL) { vlc_h2_stream_unlock(s); return NULL; } s->recv_head = f->next; if (f->next == NULL) { assert(s->recv_tailp == &f->next); s->recv_tailp = &s->recv_head; } /* Credit the receive window if missing credit exceeds 50%. */ uint_fast32_t credit = VLC_H2_INIT_WINDOW - s->recv_cwnd; if (credit >= (VLC_H2_INIT_WINDOW / 2) && !vlc_h2_output_send(conn->out, vlc_h2_frame_window_update(s->id, credit))) s->recv_cwnd += credit; vlc_h2_stream_unlock(s); /* This, err, unconventional code to avoid copying data. */ block_t *block = block_heap_Alloc(f, sizeof (*f) + vlc_h2_frame_size(f)); if (unlikely(block == NULL)) { free(f); vlc_h2_stream_error(conn, s->id, VLC_H2_INTERNAL_ERROR); return NULL; } size_t len; uint8_t *buf = vlc_h2_frame_data_get(f, &len); assert(block->i_buffer >= len); assert(block->p_buffer <= buf); assert(block->p_buffer + block->i_buffer >= buf + len); block->p_buffer = buf; block->i_buffer = len; return block; }
/***************************************************************************** * Run: main thread *****************************************************************************/ static void *Run( void *data ) { services_discovery_t *p_sd = data; services_discovery_sys_t *p_sys = p_sd->p_sys; vlc_mutex_lock( &p_sys->lock ); mutex_cleanup_push( &p_sys->lock ); for( ;; ) { while( !p_sys->b_update ) vlc_cond_wait( &p_sys->wait, &p_sys->lock ); int canc = vlc_savecancel (); msg_Dbg( p_sd, "Update required" ); if( p_sys->update_type == UPDATE_URLS ) { char* psz_urls = var_GetNonEmptyString( p_sd, "podcast-urls" ); ParseUrls( p_sd, psz_urls ); free( psz_urls ); } else if( p_sys->update_type == UPDATE_REQUEST ) { ParseRequest( p_sd ); } p_sys->b_update = false; for( int i = 0; i < p_sd->p_sys->i_input; i++ ) { input_thread_t *p_input = p_sd->p_sys->pp_input[i]; if( p_input->b_eof || p_input->b_error ) { input_Stop( p_input, false ); vlc_thread_join( p_input ); vlc_object_release( p_input ); p_sd->p_sys->pp_input[i] = NULL; REMOVE_ELEM( p_sys->pp_input, p_sys->i_input, i ); i--; } } vlc_restorecancel (canc); } vlc_cleanup_pop(); assert(0); /* dead code */ }
VLC_NORETURN static void *vlc_timer_thread (void *data) { struct vlc_timer *timer = data; vlc_mutex_lock (&timer->lock); mutex_cleanup_push (&timer->lock); for (;;) { while (timer->value == 0) vlc_cond_wait (&timer->reschedule, &timer->lock); if (vlc_cond_timedwait (&timer->reschedule, &timer->lock, timer->value) == 0) continue; if (timer->interval == 0) timer->value = 0; /* disarm */ vlc_mutex_unlock (&timer->lock); int canc = vlc_savecancel (); timer->func (timer->data); vlc_restorecancel (canc); mtime_t now = mdate (); unsigned misses; vlc_mutex_lock (&timer->lock); if (timer->interval == 0) continue; misses = (now - timer->value) / timer->interval; timer->value += timer->interval; /* Try to compensate for one miss (mwait() will return immediately) * but no more. Otherwise, we might busy loop, after extended periods * without scheduling (suspend, SIGSTOP, RT preemption, ...). */ if (misses > 1) { misses--; timer->value += misses * timer->interval; atomic_fetch_add_explicit (&timer->overruns, misses, memory_order_relaxed); } } vlc_cleanup_pop (); vlc_assert_unreachable (); }
/***************************************************************************** * Run: main thread *****************************************************************************/ VLC_NORETURN static void *Run( void *data ) { services_discovery_t *p_sd = data; services_discovery_sys_t *p_sys = p_sd->p_sys; vlc_mutex_lock( &p_sys->lock ); mutex_cleanup_push( &p_sys->lock ); for( ;; ) { while( !p_sys->b_update ) vlc_cond_wait( &p_sys->wait, &p_sys->lock ); int canc = vlc_savecancel (); msg_Dbg( p_sd, "Update required" ); if( p_sys->update_type == UPDATE_URLS ) { char *psz_urls = var_GetNonEmptyString( p_sd->p_parent, "podcast-urls" ); ParseUrls( p_sd, psz_urls ); free( psz_urls ); } else if( p_sys->update_type == UPDATE_REQUEST ) ParseRequest( p_sd ); p_sys->b_update = false; for( int i = 0; i < p_sd->p_sys->i_input; i++ ) { input_thread_t *p_input = p_sd->p_sys->pp_input[i]; int state = var_GetInteger( p_input, "state" ); if( state == END_S || state == ERROR_S ) { input_Stop( p_input ); input_Close( p_input ); p_sd->p_sys->pp_input[i] = NULL; REMOVE_ELEM( p_sys->pp_input, p_sys->i_input, i ); i--; } } vlc_restorecancel (canc); } vlc_cleanup_pop(); vlc_assert_unreachable(); /* dead code */ }
void mwait (mtime_t deadline) { vlc_mutex_t lock; vlc_cond_t wait; vlc_mutex_init (&lock); vlc_cond_init (&wait); vlc_mutex_lock (&lock); mutex_cleanup_push (&lock); while (!vlc_cond_timedwait (&wait, &lock, deadline)); vlc_cleanup_run (); vlc_cond_destroy (&wait); vlc_mutex_destroy (&lock); }
/** * @brief Thread writing frames to the subprocess */ static void* inputThread(void* userData) { filter_t* intf = (filter_t*)userData; filter_sys_t* sys = intf->p_sys; msg_Info(intf, "inputThread: enter"); while (true) { picture_t* pic; // acquire a frame pushed from y4m_filter() vlc_mutex_lock(&sys->inputMutex); mutex_cleanup_push(&sys->inputMutex); while (NULL == (pic = picture_fifo_Pop(sys->inputFifo))) { //msg_Info(intf, "inputThread: wait picture"); vlc_cond_wait(&sys->inputCond, &sys->inputMutex); } sys->bufferedIn--; vlc_mutex_unlock(&sys->inputMutex); vlc_cleanup_pop(); //msg_Info(intf, "inputThread: write picture"); if (1 != writeY4mFrame(intf, pic, sys->stdin)) { msg_Err(intf, "inputThread: Failed to write y4m frame"); break; } picture_Release(pic); } msg_Info(intf, "inputThread: exit"); sys->threadExit = true; return userData; }
static struct vlc_http_msg *vlc_h2_stream_wait(struct vlc_http_stream *stream) { struct vlc_h2_stream *s = (struct vlc_h2_stream *)stream; struct vlc_h2_conn *conn = s->conn; struct vlc_http_msg *m; vlc_h2_stream_lock(s); while ((m = s->recv_hdr) == NULL && !s->recv_end && !s->interrupted) { mutex_cleanup_push(&conn->lock); vlc_cond_wait(&s->recv_wait, &conn->lock); vlc_cleanup_pop(); } s->recv_hdr = NULL; vlc_h2_stream_unlock(s); /* TODO? distinguish failed/unknown/ignored */ if (m != NULL) vlc_http_msg_attach(m, stream); return m; }
static void *playlist_thread(void *data) { libvlc_media_list_player_t *mlp = data; vlc_mutex_lock(&mlp->mp_callback_lock); mutex_cleanup_push(&mlp->mp_callback_lock); for (;;) { int canc; while (mlp->seek_offset == 0) vlc_cond_wait(&mlp->seek_pending, &mlp->mp_callback_lock); canc = vlc_savecancel(); set_relative_playlist_position_and_play(mlp, mlp->seek_offset); mlp->seek_offset = 0; vlc_restorecancel(canc); } vlc_cleanup_pop(); vlc_assert_unreachable(); }
/***************************************************************************** * Run : call Handshake() then submit songs *****************************************************************************/ static void *Run(void *data) { intf_thread_t *p_intf = data; uint8_t p_buffer[1024]; int canc = vlc_savecancel(); bool b_handshaked = false; bool b_nowp_submission_ongoing = false; /* data about audioscrobbler session */ vlc_tick_t next_exchange = VLC_TICK_INVALID; /**< when can we send data */ unsigned int i_interval = 0; /**< waiting interval (secs)*/ intf_sys_t *p_sys = p_intf->p_sys; /* main loop */ for (;;) { vlc_restorecancel(canc); if (next_exchange != VLC_TICK_INVALID) vlc_tick_wait(next_exchange); vlc_mutex_lock(&p_sys->lock); mutex_cleanup_push(&p_sys->lock); while (p_sys->i_songs == 0 && p_sys->b_submit_nowp == false) vlc_cond_wait(&p_sys->wait, &p_sys->lock); vlc_cleanup_pop(); vlc_mutex_unlock(&p_sys->lock); canc = vlc_savecancel(); /* handshake if needed */ if (!b_handshaked) { msg_Dbg(p_intf, "Handshaking with last.fm ..."); switch(Handshake(p_intf)) { case VLC_ENOMEM: goto out; case VLC_ENOVAR: /* username not set */ vlc_dialog_display_error(p_intf, _("Last.fm username not set"), "%s", _("Please set a username or disable the " "audioscrobbler plugin, and restart VLC.\n" "Visit http://www.last.fm/join/ to get an account.")); goto out; case VLC_SUCCESS: msg_Dbg(p_intf, "Handshake successful :)"); b_handshaked = true; i_interval = 0; next_exchange = VLC_TICK_INVALID; break; case VLC_AUDIOSCROBBLER_EFATAL: msg_Warn(p_intf, "Exiting..."); goto out; case VLC_EGENERIC: default: /* protocol error : we'll try later */ HandleInterval(&next_exchange, &i_interval); break; } /* if handshake failed let's restart the loop */ if (!b_handshaked) continue; } msg_Dbg(p_intf, "Going to submit some data..."); vlc_url_t *url; struct vlc_memstream req, payload; vlc_memstream_open(&payload); vlc_memstream_printf(&payload, "s=%s", p_sys->psz_auth_token); /* forge the HTTP POST request */ vlc_mutex_lock(&p_sys->lock); if (p_sys->b_submit_nowp) { audioscrobbler_song_t *p_song = &p_sys->p_current_song; b_nowp_submission_ongoing = true; url = &p_sys->p_nowp_url; vlc_memstream_printf(&payload, "&a=%s", p_song->psz_a); vlc_memstream_printf(&payload, "&t=%s", p_song->psz_t); vlc_memstream_puts(&payload, "&b="); if (p_song->psz_b != NULL) vlc_memstream_puts(&payload, p_song->psz_b); vlc_memstream_printf(&payload, "&l=%d", p_song->i_l); vlc_memstream_puts(&payload, "&n="); if (p_song->psz_n != NULL) vlc_memstream_puts(&payload, p_song->psz_n); vlc_memstream_puts(&payload, "&m="); if (p_song->psz_m != NULL) vlc_memstream_puts(&payload, p_song->psz_m); } else { url = &p_sys->p_submit_url; for (int i_song = 0 ; i_song < p_sys->i_songs ; i_song++) { audioscrobbler_song_t *p_song = &p_sys->p_queue[i_song]; vlc_memstream_printf(&payload, "&a%%5B%d%%5D=%s", i_song, p_song->psz_a); vlc_memstream_printf(&payload, "&t%%5B%d%%5D=%s", i_song, p_song->psz_t); vlc_memstream_printf(&payload, "&i%%5B%d%%5D=%"PRIu64, i_song, (uint64_t)p_song->date); vlc_memstream_printf(&payload, "&o%%5B%d%%5D=P", i_song); vlc_memstream_printf(&payload, "&r%%5B%d%%5D=", i_song); vlc_memstream_printf(&payload, "&l%%5B%d%%5D=%d", i_song, p_song->i_l); vlc_memstream_printf(&payload, "&b=%%5B%d%%5D=", i_song); if (p_song->psz_b != NULL) vlc_memstream_puts(&payload, p_song->psz_b); vlc_memstream_printf(&payload, "&n=%%5B%d%%5D=", i_song); if (p_song->psz_n != NULL) vlc_memstream_puts(&payload, p_song->psz_n); vlc_memstream_printf(&payload, "&m=%%5B%d%%5D=", i_song); if (p_song->psz_m != NULL) vlc_memstream_puts(&payload, p_song->psz_m); } } vlc_mutex_unlock(&p_sys->lock); if (vlc_memstream_close(&payload)) goto out; vlc_memstream_open(&req); vlc_memstream_printf(&req, "POST %s HTTP/1.1\r\n", url->psz_path); vlc_memstream_printf(&req, "Host: %s\r\n", url->psz_host); vlc_memstream_puts(&req, "User-Agent:" " "PACKAGE_NAME"/"PACKAGE_VERSION"\r\n"); vlc_memstream_puts(&req, "Connection: close\r\n"); vlc_memstream_puts(&req, "Accept-Encoding: identity\r\n"); vlc_memstream_puts(&req, "Content-Type:" " application/x-www-form-urlencoded\r\n"); vlc_memstream_printf(&req, "Content-Length: %zu\r\n", payload.length); vlc_memstream_puts(&req, "\r\n"); /* Could avoid copying payload with iovec... but efforts */ vlc_memstream_write(&req, payload.ptr, payload.length); vlc_memstream_puts(&req, "\r\n\r\n"); free(payload.ptr); if (vlc_memstream_close(&req)) /* Out of memory */ goto out; vlc_tls_t *sock = vlc_tls_SocketOpenTCP(VLC_OBJECT(p_intf), url->psz_host, url->i_port); if (sock == NULL) { /* If connection fails, we assume we must handshake again */ HandleInterval(&next_exchange, &i_interval); b_handshaked = false; free(req.ptr); continue; } /* we transmit the data */ int i_net_ret = vlc_tls_Write(sock, req.ptr, req.length); free(req.ptr); if (i_net_ret == -1) { /* If connection fails, we assume we must handshake again */ HandleInterval(&next_exchange, &i_interval); b_handshaked = false; vlc_tls_Close(sock); continue; } /* FIXME: this might wait forever */ /* FIXME: With TCP, you should never assume that a single read will * return the entire response... */ i_net_ret = vlc_tls_Read(sock, p_buffer, sizeof(p_buffer) - 1, false); vlc_tls_Close(sock); if (i_net_ret <= 0) { /* if we get no answer, something went wrong : try again */ continue; } p_buffer[i_net_ret] = '\0'; char *failed = strstr((char *) p_buffer, "FAILED"); if (failed) { msg_Warn(p_intf, "%s", failed); HandleInterval(&next_exchange, &i_interval); continue; } if (strstr((char *) p_buffer, "BADSESSION")) { msg_Err(p_intf, "Authentication failed (BADSESSION), are you connected to last.fm with another program ?"); b_handshaked = false; HandleInterval(&next_exchange, &i_interval); continue; } if (strstr((char *) p_buffer, "OK")) { if (b_nowp_submission_ongoing) { b_nowp_submission_ongoing = false; p_sys->b_submit_nowp = false; } else { for (int i = 0; i < p_sys->i_songs; i++) DeleteSong(&p_sys->p_queue[i]); p_sys->i_songs = 0; } i_interval = 0; next_exchange = VLC_TICK_INVALID; msg_Dbg(p_intf, "Submission successful!"); } else { msg_Err(p_intf, "Authentication failed, handshaking again (%s)", p_buffer); b_handshaked = false; HandleInterval(&next_exchange, &i_interval); } } out: vlc_restorecancel(canc); return NULL; }
/***************************************************************************** * Run : *****************************************************************************/ static void *Run( void *opaque ) { fingerprinter_thread_t *p_fingerprinter = opaque; fingerprinter_sys_t *p_sys = p_fingerprinter->p_sys; vlc_mutex_lock( &p_sys->processing.lock ); mutex_cleanup_push( &p_sys->processing.lock ); /* main loop */ for (;;) { msleep( CLOCK_FREQ ); QueueIncomingRequests( p_sys ); vlc_testcancel(); for ( size_t i = 0 ; i < vlc_array_count( &p_sys->processing.queue ); i++ ) { int canc = vlc_savecancel(); fingerprint_request_t *p_data = vlc_array_item_at_index( &p_sys->processing.queue, i ); char *psz_uri = input_item_GetURI( p_data->p_item ); if ( psz_uri != NULL ) { acoustid_fingerprint_t acoustid_print; memset( &acoustid_print , 0, sizeof (acoustid_print) ); /* overwrite with hint, as in this case, fingerprint's session will be truncated */ if ( p_data->i_duration ) acoustid_print.i_duration = p_data->i_duration; DoFingerprint( p_fingerprinter, &acoustid_print, psz_uri ); free( psz_uri ); DoAcoustIdWebRequest( VLC_OBJECT(p_fingerprinter), &acoustid_print ); fill_metas_with_results( p_data, &acoustid_print ); for( unsigned j = 0; j < acoustid_print.results.count; j++ ) free_acoustid_result_t( &acoustid_print.results.p_results[j] ); if( acoustid_print.results.count ) free( acoustid_print.results.p_results ); free( acoustid_print.psz_fingerprint ); } vlc_restorecancel(canc); /* copy results */ vlc_mutex_lock( &p_sys->results.lock ); vlc_array_append( &p_sys->results.queue, p_data ); vlc_mutex_unlock( &p_sys->results.lock ); vlc_testcancel(); } if ( vlc_array_count( &p_sys->processing.queue ) ) { var_TriggerCallback( p_fingerprinter, "results-available" ); vlc_array_clear( &p_sys->processing.queue ); } } vlc_cleanup_pop(); vlc_assert_unreachable(); }
/***************************************************************************** * Run : call Handshake() then submit songs *****************************************************************************/ static void *Run(void *data) { intf_thread_t *p_intf = data; uint8_t p_buffer[1024]; int canc = vlc_savecancel(); bool b_handshaked = false; /* data about audioscrobbler session */ mtime_t next_exchange = -1; /**< when can we send data */ unsigned int i_interval = 0; /**< waiting interval (secs)*/ intf_sys_t *p_sys = p_intf->p_sys; /* main loop */ for (;;) { vlc_restorecancel(canc); vlc_mutex_lock(&p_sys->lock); mutex_cleanup_push(&p_sys->lock); do vlc_cond_wait(&p_sys->wait, &p_sys->lock); while (mdate() < next_exchange); vlc_cleanup_run(); canc = vlc_savecancel(); /* handshake if needed */ if (!b_handshaked) { msg_Dbg(p_intf, "Handshaking with last.fm ..."); switch(Handshake(p_intf)) { case VLC_ENOMEM: goto out; case VLC_ENOVAR: /* username not set */ dialog_Fatal(p_intf, _("Last.fm username not set"), "%s", _("Please set a username or disable the " "audioscrobbler plugin, and restart VLC.\n" "Visit http://www.last.fm/join/ to get an account.")); goto out; case VLC_SUCCESS: msg_Dbg(p_intf, "Handshake successful :)"); b_handshaked = true; i_interval = 0; next_exchange = mdate(); break; case VLC_AUDIOSCROBBLER_EFATAL: msg_Warn(p_intf, "Exiting..."); goto out; case VLC_EGENERIC: default: /* protocol error : we'll try later */ HandleInterval(&next_exchange, &i_interval); break; } /* if handshake failed let's restart the loop */ if (!b_handshaked) continue; } msg_Dbg(p_intf, "Going to submit some data..."); char *psz_submit; if (asprintf(&psz_submit, "s=%s", p_sys->psz_auth_token) == -1) break; /* forge the HTTP POST request */ vlc_mutex_lock(&p_sys->lock); audioscrobbler_song_t *p_song; for (int i_song = 0 ; i_song < p_sys->i_songs ; i_song++) { char *psz_submit_song, *psz_submit_tmp; p_song = &p_sys->p_queue[i_song]; if (asprintf(&psz_submit_song, "&a%%5B%d%%5D=%s" "&t%%5B%d%%5D=%s" "&i%%5B%d%%5D=%u" "&o%%5B%d%%5D=P" "&r%%5B%d%%5D=" "&l%%5B%d%%5D=%d" "&b%%5B%d%%5D=%s" "&n%%5B%d%%5D=%s" "&m%%5B%d%%5D=%s", i_song, p_song->psz_a, i_song, p_song->psz_t, i_song, (unsigned)p_song->date, /* HACK: %ju (uintmax_t) unsupported on Windows */ i_song, i_song, i_song, p_song->i_l, i_song, p_song->psz_b, i_song, p_song->psz_n, i_song, p_song->psz_m ) == -1) { /* Out of memory */ vlc_mutex_unlock(&p_sys->lock); goto out; } psz_submit_tmp = psz_submit; if (asprintf(&psz_submit, "%s%s", psz_submit_tmp, psz_submit_song) == -1) { /* Out of memory */ free(psz_submit_tmp); free(psz_submit_song); vlc_mutex_unlock(&p_sys->lock); goto out; } free(psz_submit_song); free(psz_submit_tmp); } vlc_mutex_unlock(&p_sys->lock); int i_post_socket = net_ConnectTCP(p_intf, p_sys->p_submit_url.psz_host, p_sys->p_submit_url.i_port); if (i_post_socket == -1) { /* If connection fails, we assume we must handshake again */ HandleInterval(&next_exchange, &i_interval); b_handshaked = false; free(psz_submit); continue; } /* we transmit the data */ int i_net_ret = net_Printf(p_intf, i_post_socket, NULL, "POST %s HTTP/1.1\n" "Accept-Encoding: identity\n" "Content-length: %zu\n" "Connection: close\n" "Content-type: application/x-www-form-urlencoded\n" "Host: %s\n" "User-agent: VLC media player/"VERSION"\r\n" "\r\n" "%s\r\n" "\r\n", p_sys->p_submit_url.psz_path, strlen(psz_submit), p_sys->p_submit_url.psz_host, psz_submit ); free(psz_submit); if (i_net_ret == -1) { /* If connection fails, we assume we must handshake again */ HandleInterval(&next_exchange, &i_interval); b_handshaked = false; continue; } i_net_ret = net_Read(p_intf, i_post_socket, NULL, p_buffer, sizeof(p_buffer) - 1, false); if (i_net_ret <= 0) { /* if we get no answer, something went wrong : try again */ continue; } net_Close(i_post_socket); p_buffer[i_net_ret] = '\0'; char *failed = strstr((char *) p_buffer, "FAILED"); if (failed) { msg_Warn(p_intf, "%s", failed); HandleInterval(&next_exchange, &i_interval); continue; } if (strstr((char *) p_buffer, "BADSESSION")) { msg_Err(p_intf, "Authentication failed (BADSESSION), are you connected to last.fm with another program ?"); b_handshaked = false; HandleInterval(&next_exchange, &i_interval); continue; } if (strstr((char *) p_buffer, "OK")) { for (int i = 0; i < p_sys->i_songs; i++) DeleteSong(&p_sys->p_queue[i]); p_sys->i_songs = 0; i_interval = 0; next_exchange = mdate(); msg_Dbg(p_intf, "Submission successful!"); } else { msg_Err(p_intf, "Authentication failed, handshaking again (%s)", p_buffer); b_handshaked = false; HandleInterval(&next_exchange, &i_interval); } } out: vlc_restorecancel(canc); return NULL; }
/***************************************************************************** * Run : call Handshake() then submit songs *****************************************************************************/ static void *Run(void *data) { intf_thread_t *p_intf = data; uint8_t p_buffer[1024]; int canc = vlc_savecancel(); bool b_handshaked = false; bool b_nowp_submission_ongoing = false; /* data about audioscrobbler session */ mtime_t next_exchange = 0; /**< when can we send data */ unsigned int i_interval = 0; /**< waiting interval (secs)*/ intf_sys_t *p_sys = p_intf->p_sys; /* main loop */ for (;;) { vlc_restorecancel(canc); mwait(next_exchange); vlc_mutex_lock(&p_sys->lock); mutex_cleanup_push(&p_sys->lock); while (p_sys->i_songs == 0 && p_sys->b_submit_nowp == false) vlc_cond_wait(&p_sys->wait, &p_sys->lock); vlc_cleanup_pop(); vlc_mutex_unlock(&p_sys->lock); canc = vlc_savecancel(); /* handshake if needed */ if (!b_handshaked) { msg_Dbg(p_intf, "Handshaking with last.fm ..."); switch(Handshake(p_intf)) { case VLC_ENOMEM: goto out; case VLC_ENOVAR: /* username not set */ vlc_dialog_display_error(p_intf, _("Last.fm username not set"), "%s", _("Please set a username or disable the " "audioscrobbler plugin, and restart VLC.\n" "Visit http://www.last.fm/join/ to get an account.")); goto out; case VLC_SUCCESS: msg_Dbg(p_intf, "Handshake successful :)"); b_handshaked = true; i_interval = 0; next_exchange = 0; break; case VLC_AUDIOSCROBBLER_EFATAL: msg_Warn(p_intf, "Exiting..."); goto out; case VLC_EGENERIC: default: /* protocol error : we'll try later */ HandleInterval(&next_exchange, &i_interval); break; } /* if handshake failed let's restart the loop */ if (!b_handshaked) continue; } msg_Dbg(p_intf, "Going to submit some data..."); char *psz_submit; vlc_url_t *url; char *psz_submit_song, *psz_submit_tmp; if (asprintf(&psz_submit, "s=%s", p_sys->psz_auth_token) == -1) break; /* forge the HTTP POST request */ vlc_mutex_lock(&p_sys->lock); if (p_sys->b_submit_nowp) { b_nowp_submission_ongoing = true; url = &p_sys->p_nowp_url; if (asprintf(&psz_submit_song, "&a=%s" "&t=%s" "&b=%s" "&l=%d" "&n=%s" "&m=%s", p_sys->p_current_song.psz_a, p_sys->p_current_song.psz_t, p_sys->p_current_song.psz_b ? p_sys->p_current_song.psz_b : "", p_sys->p_current_song.i_l, p_sys->p_current_song.psz_n ? p_sys->p_current_song.psz_n : "", p_sys->p_current_song.psz_m ? p_sys->p_current_song.psz_m : "" ) == -1) { /* Out of memory */ vlc_mutex_unlock(&p_sys->lock); goto out; } } else { url = &p_sys->p_submit_url; audioscrobbler_song_t *p_song; for (int i_song = 0 ; i_song < p_sys->i_songs ; i_song++) { p_song = &p_sys->p_queue[i_song]; if (asprintf(&psz_submit_song, "&a%%5B%d%%5D=%s" "&t%%5B%d%%5D=%s" "&i%%5B%d%%5D=%u" "&o%%5B%d%%5D=P" "&r%%5B%d%%5D=" "&l%%5B%d%%5D=%d" "&b%%5B%d%%5D=%s" "&n%%5B%d%%5D=%s" "&m%%5B%d%%5D=%s", i_song, p_song->psz_a, i_song, p_song->psz_t, i_song, (unsigned)p_song->date, /* HACK: %ju (uintmax_t) unsupported on Windows */ i_song, i_song, i_song, p_song->i_l, i_song, p_song->psz_b ? p_song->psz_b : "", i_song, p_song->psz_n ? p_song->psz_n : "", i_song, p_song->psz_m ? p_song->psz_m : "" ) == -1) { /* Out of memory */ vlc_mutex_unlock(&p_sys->lock); goto out; } } } psz_submit_tmp = psz_submit; int print_ret = asprintf(&psz_submit, "%s%s", psz_submit_tmp, psz_submit_song); free(psz_submit_tmp); free(psz_submit_song); vlc_mutex_unlock(&p_sys->lock); if (print_ret == -1) { /* Out of memory */ goto out; } int i_post_socket = net_ConnectTCP(p_intf, url->psz_host, url->i_port); if (i_post_socket == -1) { /* If connection fails, we assume we must handshake again */ HandleInterval(&next_exchange, &i_interval); b_handshaked = false; free(psz_submit); continue; } /* we transmit the data */ int i_net_ret = net_Printf(p_intf, i_post_socket, "POST %s HTTP/1.1\r\n" "Host: %s\r\n" "User-Agent: "PACKAGE_NAME"/"PACKAGE_VERSION"\r\n" "Connection: close\r\n" "Accept-Encoding: identity\r\n" "Content-Type: application/x-www-form-urlencoded\r\n" "Content-Length: %zu\r\n" "\r\n" "%s\r\n" "\r\n", url->psz_path, url->psz_host, strlen(psz_submit), psz_submit); free(psz_submit); if (i_net_ret == -1) { /* If connection fails, we assume we must handshake again */ HandleInterval(&next_exchange, &i_interval); b_handshaked = false; net_Close(i_post_socket); continue; } /* FIXME: this might wait forever */ struct pollfd ufd = { .fd = i_post_socket, .events = POLLIN }; while( poll( &ufd, 1, -1 ) == -1 ); /* FIXME: With TCP, you should never assume that a single read will * return the entire response... */ i_net_ret = recv(i_post_socket, p_buffer, sizeof(p_buffer) - 1, 0); if (i_net_ret <= 0) { /* if we get no answer, something went wrong : try again */ net_Close(i_post_socket); continue; } net_Close(i_post_socket); p_buffer[i_net_ret] = '\0'; char *failed = strstr((char *) p_buffer, "FAILED"); if (failed) { msg_Warn(p_intf, "%s", failed); HandleInterval(&next_exchange, &i_interval); continue; } if (strstr((char *) p_buffer, "BADSESSION")) { msg_Err(p_intf, "Authentication failed (BADSESSION), are you connected to last.fm with another program ?"); b_handshaked = false; HandleInterval(&next_exchange, &i_interval); continue; } if (strstr((char *) p_buffer, "OK")) { if (b_nowp_submission_ongoing) { b_nowp_submission_ongoing = false; p_sys->b_submit_nowp = false; } else { for (int i = 0; i < p_sys->i_songs; i++) DeleteSong(&p_sys->p_queue[i]); p_sys->i_songs = 0; } i_interval = 0; next_exchange = 0; msg_Dbg(p_intf, "Submission successful!"); } else { msg_Err(p_intf, "Authentication failed, handshaking again (%s)", p_buffer); b_handshaked = false; HandleInterval(&next_exchange, &i_interval); } } out: vlc_restorecancel(canc); return NULL; }
/***************************************************************************** * Run : call Handshake() then submit songs *****************************************************************************/ static void Run( intf_thread_t *p_intf ) { char *psz_submit, *psz_submit_song, *psz_submit_tmp; int i_net_ret; int i_song; uint8_t p_buffer[1024]; char *p_buffer_pos; int i_post_socket; int canc = vlc_savecancel(); intf_sys_t *p_sys = p_intf->p_sys; /* main loop */ for( ;; ) { bool b_wait = false; vlc_restorecancel( canc ); vlc_mutex_lock( &p_sys->lock ); mutex_cleanup_push( &p_sys->lock ); if( mdate() < p_sys->next_exchange ) /* wait until we can resubmit, i.e. */ b_wait = vlc_cond_timedwait( &p_sys->wait, &p_sys->lock, p_sys->next_exchange ) == 0; else /* wait for data to submit */ /* we are signaled each time there is a song to submit */ vlc_cond_wait( &p_sys->wait, &p_sys->lock ); vlc_cleanup_run(); canc = vlc_savecancel(); if( b_wait ) continue; /* holding on until next_exchange */ /* handshake if needed */ if( !p_sys->b_handshaked ) { msg_Dbg( p_intf, "Handshaking with last.fm ..." ); switch( Handshake( p_intf ) ) { case VLC_ENOMEM: return; case VLC_ENOVAR: /* username not set */ dialog_Fatal( p_intf, _("Last.fm username not set"), "%s", _("Please set a username or disable the " "audioscrobbler plugin, and restart VLC.\n" "Visit http://www.last.fm/join/ to get an account.") ); return; case VLC_SUCCESS: msg_Dbg( p_intf, "Handshake successfull :)" ); p_sys->b_handshaked = true; p_sys->i_interval = 0; p_sys->next_exchange = mdate(); break; case VLC_AUDIOSCROBBLER_EFATAL: msg_Warn( p_intf, "Exiting..." ); return; case VLC_EGENERIC: default: /* protocol error : we'll try later */ HandleInterval( &p_sys->next_exchange, &p_sys->i_interval ); break; } /* if handshake failed let's restart the loop */ if( !p_sys->b_handshaked ) continue; } msg_Dbg( p_intf, "Going to submit some data..." ); /* The session may be invalid if there is a trailing \n */ char *psz_ln = strrchr( p_sys->psz_auth_token, '\n' ); if( psz_ln ) *psz_ln = '\0'; if( !asprintf( &psz_submit, "s=%s", p_sys->psz_auth_token ) ) { /* Out of memory */ return; } /* forge the HTTP POST request */ vlc_mutex_lock( &p_sys->lock ); audioscrobbler_song_t *p_song; for( i_song = 0 ; i_song < p_sys->i_songs ; i_song++ ) { p_song = &p_sys->p_queue[i_song]; if( !asprintf( &psz_submit_song, "&a%%5B%d%%5D=%s" "&t%%5B%d%%5D=%s" "&i%%5B%d%%5D=%u" "&o%%5B%d%%5D=P" "&r%%5B%d%%5D=" "&l%%5B%d%%5D=%d" "&b%%5B%d%%5D=%s" "&n%%5B%d%%5D=%s" "&m%%5B%d%%5D=%s", i_song, p_song->psz_a, i_song, p_song->psz_t, i_song, (unsigned)p_song->date, /* HACK: %ju (uintmax_t) unsupported on Windows */ i_song, i_song, i_song, p_song->i_l, i_song, p_song->psz_b, i_song, p_song->psz_n, i_song, p_song->psz_m ) ) { /* Out of memory */ vlc_mutex_unlock( &p_sys->lock ); return; } psz_submit_tmp = psz_submit; if( !asprintf( &psz_submit, "%s%s", psz_submit_tmp, psz_submit_song ) ) { /* Out of memory */ free( psz_submit_tmp ); free( psz_submit_song ); vlc_mutex_unlock( &p_sys->lock ); return; } free( psz_submit_song ); free( psz_submit_tmp ); } vlc_mutex_unlock( &p_sys->lock ); i_post_socket = net_ConnectTCP( p_intf, p_sys->psz_submit_host, p_sys->i_submit_port ); if ( i_post_socket == -1 ) { /* If connection fails, we assume we must handshake again */ HandleInterval( &p_sys->next_exchange, &p_sys->i_interval ); p_sys->b_handshaked = false; free( psz_submit ); continue; } /* we transmit the data */ i_net_ret = net_Printf( p_intf, i_post_socket, NULL, POST_REQUEST, p_sys->psz_submit_file, (unsigned)strlen( psz_submit ), p_sys->psz_submit_host, VERSION, psz_submit ); free( psz_submit ); if ( i_net_ret == -1 ) { /* If connection fails, we assume we must handshake again */ HandleInterval( &p_sys->next_exchange, &p_sys->i_interval ); p_sys->b_handshaked = false; continue; } i_net_ret = net_Read( p_intf, i_post_socket, NULL, p_buffer, 1023, false ); if ( i_net_ret <= 0 ) { /* if we get no answer, something went wrong : try again */ continue; } net_Close( i_post_socket ); p_buffer[i_net_ret] = '\0'; p_buffer_pos = strstr( ( char * ) p_buffer, "FAILED" ); if ( p_buffer_pos ) { msg_Warn( p_intf, "%s", p_buffer_pos ); HandleInterval( &p_sys->next_exchange, &p_sys->i_interval ); continue; } p_buffer_pos = strstr( ( char * ) p_buffer, "BADSESSION" ); if ( p_buffer_pos ) { msg_Err( p_intf, "Authentication failed (BADSESSION), are you connected to last.fm with another program ?" ); p_sys->b_handshaked = false; HandleInterval( &p_sys->next_exchange, &p_sys->i_interval ); continue; } p_buffer_pos = strstr( ( char * ) p_buffer, "OK" ); if ( p_buffer_pos ) { int i; for( i = 0; i < p_sys->i_songs; i++ ) DeleteSong( &p_sys->p_queue[i] ); p_sys->i_songs = 0; p_sys->i_interval = 0; p_sys->next_exchange = mdate(); msg_Dbg( p_intf, "Submission successful!" ); } else { msg_Err( p_intf, "Authentication failed, handshaking again (%s)", p_buffer ); p_sys->b_handshaked = false; HandleInterval( &p_sys->next_exchange, &p_sys->i_interval ); continue; } } vlc_restorecancel( canc ); }
/***************************************************************************** * Run : call Handshake() then submit items *****************************************************************************/ static void Run(intf_thread_t *p_intf) { msg_Dbg(p_intf, "Entering Run()"); uint8_t p_buffer[1024]; int parse_url_ret; int canc = vlc_savecancel(); char *psz_scrobbler_url; mtime_t next_exchange; /**< when can we send data */ unsigned int i_interval; /**< waiting interval (secs)*/ intf_sys_t *p_sys = p_intf->p_sys; psz_scrobbler_url = var_InheritString(p_intf, "mediascrobbler-url"); if(!psz_scrobbler_url) return; msg_Dbg(p_intf, "Scrobbler URL: %s", psz_scrobbler_url); /* main loop */ for (;;) { vlc_restorecancel(canc); vlc_mutex_lock(&p_sys->lock); mutex_cleanup_push(&p_sys->lock); msg_Dbg(p_intf, "Next exchange %lld (current: %lld)", next_exchange, mdate()); do { vlc_cond_wait(&p_sys->wait, &p_sys->lock); } while (mdate() < next_exchange); vlc_cleanup_run(); canc = vlc_savecancel(); msg_Dbg(p_intf, "Going to submit some data..."); char *psz_submit; if (asprintf(&psz_submit, "s=%s", psz_scrobbler_url) == -1) return; msg_Dbg(p_intf, "Going to parse URL (%s)", psz_scrobbler_url); parse_url_ret = ParseURL(psz_scrobbler_url, &p_sys->psz_submit_host, &p_sys->psz_submit_file, &p_sys->i_submit_port); if(parse_url_ret != VLC_SUCCESS) { msg_Err(p_intf, "Couldn't process URL, can't continue"); return; } msg_Dbg(p_intf, "Submit Host: %s", p_sys->psz_submit_host); msg_Dbg(p_intf, "Preparing to submit %d items", p_sys->i_items); /* forge the HTTP POST request */ vlc_mutex_lock(&p_sys->lock); mediascrobbler_item_t *p_item; for (int i_item = 0 ; i_item < p_sys->i_items ; i_item++) { char *psz_submit_item, *psz_submit_tmp; p_item = &p_sys->p_queue[i_item]; if (asprintf(&psz_submit_item, "&n%%5B%d%%5D=%s" "&u%%5B%d%%5D=%s" "&d%%5B%d%%5D=%ju" "&l%%5B%d%%5D=%d", i_item, p_item->psz_n, i_item, p_item->psz_u, i_item, p_item->date, i_item, p_item->i_l ) == -1) { /* Out of memory */ vlc_mutex_unlock(&p_sys->lock); return; } psz_submit_tmp = psz_submit; if (asprintf(&psz_submit, "%s%s", psz_submit_tmp, psz_submit_item) == -1) { /* Out of memory */ free(psz_submit_tmp); free(psz_submit_item); vlc_mutex_unlock(&p_sys->lock); return; } free(psz_submit_item); free(psz_submit_tmp); } vlc_mutex_unlock(&p_sys->lock); int i_post_socket = net_ConnectTCP(p_intf, p_sys->psz_submit_host, p_sys->i_submit_port); if (i_post_socket == -1) { msg_Warn(p_intf, "Couldn't talk to the API, waiting to try again. (%d)", i_interval); HandleInterval(&next_exchange, &i_interval); free(psz_submit); continue; } /* we transmit the data */ int i_net_ret = net_Printf(p_intf, i_post_socket, NULL, "POST %s HTTP/1.1\r\n" "Accept-Encoding: identity\r\n" "Content-length: %zu\r\n" "Connection: close\r\n" "Content-type: application/x-www-form-urlencoded\r\n" "Host: %s\r\n" "User-agent: VLC media player/"VERSION"\r\n" "\r\n" "%s\r\n" "\r\n", p_sys->psz_submit_file, strlen(psz_submit), p_sys->psz_submit_host, psz_submit ); free(psz_submit); if (i_net_ret == -1) { /* If connection fails, back off the timer, and try again */ HandleInterval(&next_exchange, &i_interval); continue; } i_net_ret = net_Read(p_intf, i_post_socket, NULL, p_buffer, sizeof(p_buffer) - 1, false); if (i_net_ret <= 0) { /* if we get no answer, something went wrong : try again */ continue; } net_Close(i_post_socket); p_buffer[i_net_ret] = '\0'; char *failed = strstr((char *) p_buffer, "FAILED"); if (failed) { msg_Warn(p_intf, "%s", failed); HandleInterval(&next_exchange, &i_interval); continue; } if (strstr((char *) p_buffer, "BADAPIKEY")) { msg_Err(p_intf, "Authentication failed (BADAPIKEY), are you sure your API key is valid?"); HandleInterval(&next_exchange, &i_interval); continue; } if (strstr((char *) p_buffer, "OK")) { for (int i = 0; i < p_sys->i_items; i++) DeleteItem(&p_sys->p_queue[i]); p_sys->i_items = 0; i_interval = 0; next_exchange = mdate(); msg_Dbg(p_intf, "Submission successful!"); } else { msg_Err(p_intf, "Authentication failed, trying again (%s)", p_buffer); HandleInterval(&next_exchange, &i_interval); } } vlc_restorecancel(canc); }
/***************************************************************************** * Run: xosd thread ***************************************************************************** * This part of the interface runs in a separate thread *****************************************************************************/ static void Run( intf_thread_t *p_intf ) { playlist_t *p_playlist; playlist_item_t *p_item = NULL; char *psz_display = NULL; int cancel = vlc_savecancel(); while( true ) { // Wait for a signal vlc_restorecancel( cancel ); vlc_mutex_lock( &p_intf->p_sys->lock ); mutex_cleanup_push( &p_intf->p_sys->lock ); while( !p_intf->p_sys->b_need_update ) vlc_cond_wait( &p_intf->p_sys->cond, &p_intf->p_sys->lock ); p_intf->p_sys->b_need_update = false; vlc_cleanup_run(); // Compute the signal cancel = vlc_savecancel(); p_playlist = pl_Hold( p_intf ); PL_LOCK; // If the playlist is empty don't do anything if( playlist_IsEmpty( p_playlist ) ) { PL_UNLOCK; pl_Release( p_intf ); continue; } free( psz_display ); int i_status = playlist_Status( p_playlist ); if( i_status == PLAYLIST_STOPPED ) { psz_display = strdup(_("Stop")); } else if( i_status == PLAYLIST_PAUSED ) { psz_display = strdup(_("Pause")); } else { p_item = playlist_CurrentPlayingItem( p_playlist ); if( !p_item ) { psz_display = NULL; PL_UNLOCK; pl_Release( p_intf ); continue; } input_item_t *p_input = p_item->p_input; mtime_t i_duration = input_item_GetDuration( p_input ); if( i_duration != -1 ) { char psz_durationstr[MSTRTIME_MAX_SIZE]; secstotimestr( psz_durationstr, i_duration / 1000000 ); if( asprintf( &psz_display, "%s (%s)", p_input->psz_name, psz_durationstr ) == -1 ) psz_display = NULL; } else psz_display = strdup( p_input->psz_name ); } PL_UNLOCK; pl_Release( p_intf ); /* Display */ xosd_display( p_intf->p_sys->p_osd, 0, /* first line */ XOSD_string, psz_display ); } }
static void DoFingerprint( vlc_object_t *p_this, fingerprinter_sys_t *p_sys, acoustid_fingerprint_t *fp ) { p_sys->p_input = NULL; p_sys->p_item = NULL; p_sys->chroma_fingerprint.psz_fingerprint = NULL; vlc_cleanup_push( cancelDoFingerprint, p_sys ); p_sys->p_item = input_item_New( NULL, NULL ); if ( ! p_sys->p_item ) goto end; char *psz_sout_option; /* Note: need at -max- 2 channels, but we can't guess it before playing */ /* the stereo upmix could make the mono tracks fingerprint to differ :/ */ if ( asprintf( &psz_sout_option, "sout=#transcode{acodec=%s,channels=2}:chromaprint", ( VLC_CODEC_S16L == VLC_CODEC_S16N ) ? "s16l" : "s16b" ) == -1 ) goto end; input_item_AddOption( p_sys->p_item, psz_sout_option, VLC_INPUT_OPTION_TRUSTED ); free( psz_sout_option ); input_item_AddOption( p_sys->p_item, "vout=dummy", VLC_INPUT_OPTION_TRUSTED ); input_item_AddOption( p_sys->p_item, "aout=dummy", VLC_INPUT_OPTION_TRUSTED ); if ( fp->i_duration ) { if ( asprintf( &psz_sout_option, "stop-time=%u", fp->i_duration ) == -1 ) goto end; input_item_AddOption( p_sys->p_item, psz_sout_option, VLC_INPUT_OPTION_TRUSTED ); free( psz_sout_option ); } input_item_SetURI( p_sys->p_item, p_sys->psz_uri ) ; p_sys->p_input = input_Create( p_this, p_sys->p_item, "fingerprinter", NULL ); if ( p_sys->p_input ) { p_sys->chroma_fingerprint.i_duration = fp->i_duration; var_Create( p_sys->p_input, "fingerprint-data", VLC_VAR_ADDRESS ); var_SetAddress( p_sys->p_input, "fingerprint-data", & p_sys->chroma_fingerprint ); input_Start( p_sys->p_input ); /* Wait for input to start && end */ p_sys->condwait.i_input_state = var_GetInteger( p_sys->p_input, "state" ); if ( likely( var_AddCallback( p_sys->p_input, "intf-event", inputStateCallback, p_sys ) == VLC_SUCCESS ) ) { while( p_sys->condwait.i_input_state <= PAUSE_S ) { vlc_mutex_lock( &p_sys->condwait.lock ); mutex_cleanup_push( &p_sys->condwait.lock ); vlc_cond_wait( &p_sys->condwait.wait, &p_sys->condwait.lock ); vlc_cleanup_run(); } var_DelCallback( p_sys->p_input, "intf-event", inputStateCallback, p_sys ); } input_Stop( p_sys->p_input, true ); input_Close( p_sys->p_input ); p_sys->p_input = NULL; if ( p_sys->chroma_fingerprint.psz_fingerprint ) { fp->psz_fingerprint = strdup( p_sys->chroma_fingerprint.psz_fingerprint ); if ( ! fp->i_duration ) /* had not given hint */ fp->i_duration = p_sys->chroma_fingerprint.i_duration; } } end: vlc_cleanup_run( ); }