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* update_request_thread( void *obj ) { filter_t* p_filter = (filter_t*)obj; filter_sys_t *p_sys = p_filter->p_sys; msg_Dbg( p_filter, "VNC update request thread started" ); rfbFramebufferUpdateRequestMsg udr; udr.type = rfbFramebufferUpdateRequest; udr.incremental = 0; udr.x = 0; udr.y = 0; udr.w = htons(p_sys->i_vnc_width); udr.h = htons(p_sys->i_vnc_height); int w; vlc_cleanup_push( update_request_thread_cleanup, p_filter ); w = write_exact(p_filter, p_sys->i_socket, (char*)&udr, sz_rfbFramebufferUpdateRequestMsg); vlc_cleanup_pop(); if( !w ) { msg_Err( p_filter, "Could not write rfbFramebufferUpdateRequestMsg." ); update_request_thread_cleanup( p_filter ); return NULL; } udr.incremental = 1; mtime_t i_poll_interval_microsec = p_sys->i_vnc_poll_interval * 1000; if( p_sys->b_vnc_poll) { vlc_cleanup_push( update_request_thread_cleanup, p_filter ); for( ;; ) { msleep( i_poll_interval_microsec ); if( !write_exact(p_filter, p_sys->i_socket, (char*)&udr, sz_rfbFramebufferUpdateRequestMsg)) { msg_Err( p_filter, "Could not write rfbFramebufferUpdateRequestMsg." ); break; } } vlc_cleanup_run(); } else { msg_Dbg( p_filter, "VNC polling disabled." ); } msg_Dbg( p_filter, "VNC update request thread ended" ); return NULL; }
static void* Raw1394EventThread( void *obj ) { event_thread_t *p_ev = (event_thread_t *)obj; access_t *p_access = (access_t *) p_ev->p_access; access_sys_t *p_sys = (access_sys_t *) p_access->p_sys; int result = 0; int canc = vlc_savecancel(); AVCPlay( p_access, p_sys->i_node ); vlc_cleanup_push( Raw1394EventThreadCleanup, p_ev ); vlc_restorecancel( canc ); for( ;; ) { while( ( result = poll( &p_sys->raw1394_poll, 1, -1 ) ) < 0 ) { if( errno != EINTR ) msg_Err( p_access, "poll error: %s", vlc_strerror_c(errno) ); } if( result > 0 && ( ( p_sys->raw1394_poll.revents & POLLIN ) || ( p_sys->raw1394_poll.revents & POLLPRI ) ) ) { canc = vlc_savecancel(); result = raw1394_loop_iterate( p_sys->p_raw1394 ); vlc_restorecancel( canc ); } } vlc_cleanup_pop(); vlc_assert_unreachable(); }
/** Background thread for Wayland shell events handling */ static void *Thread(void *data) { vout_window_t *wnd = data; struct wl_display *display = wnd->display.wl; struct pollfd ufd[1]; int canc = vlc_savecancel(); vlc_cleanup_push(cleanup_wl_display_read, display); ufd[0].fd = wl_display_get_fd(display); ufd[0].events = POLLIN; for (;;) { while (wl_display_prepare_read(display) != 0) wl_display_dispatch_pending(display); wl_display_flush(display); vlc_restorecancel(canc); while (poll(ufd, 1, -1) < 0); canc = vlc_savecancel(); wl_display_read_events(display); wl_display_dispatch_pending(display); } vlc_assert_unreachable(); vlc_cleanup_pop(); //vlc_restorecancel(canc); //return NULL; }
int vlc_mwait_i11e(mtime_t deadline) { vlc_interrupt_t *ctx = vlc_threadvar_get(vlc_interrupt_var); if (ctx == NULL) return mwait(deadline), 0; vlc_cond_t wait; vlc_cond_init(&wait); int ret = vlc_interrupt_prepare(ctx, vlc_mwait_i11e_wake, &wait); if (ret) { vlc_cond_destroy(&wait); vlc_testcancel(); return ret; } vlc_mutex_lock(&ctx->lock); vlc_cleanup_push(vlc_mwait_i11e_cleanup, ctx); while (!ctx->interrupted && vlc_cond_timedwait(&wait, &ctx->lock, deadline) == 0); vlc_cleanup_pop(); vlc_mutex_unlock(&ctx->lock); ret = vlc_interrupt_finish(ctx); vlc_cond_destroy(&wait); return ret; }
static void *Thread (void *data) { stream_t *stream = data; stream_sys_t *p_sys = stream->p_sys; #ifdef HAVE_VMSPLICE ssize_t page_mask = sysconf (_SC_PAGE_SIZE) - 1; #endif int fd = p_sys->write_fd; bool error = false; do { ssize_t len; int canc = vlc_savecancel (); #ifdef HAVE_VMSPLICE unsigned char *buf = mmap (NULL, bufsize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); vlc_cleanup_push (cleanup_mmap, buf); #else unsigned char buf[bufsize]; #endif len = stream_Read (stream->p_source, buf, bufsize); vlc_restorecancel (canc); error = len <= 0; for (ssize_t i = 0, j; i < len; i += j) { #ifdef HAVE_VMSPLICE if ((len - i) <= page_mask) /* incomplete last page */ j = write (fd, buf + i, len - i); else { struct iovec iov = { buf + i, (len - i) & ~page_mask, }; j = vmsplice (fd, &iov, 1, SPLICE_F_GIFT); } if (j == -1 && errno == ENOSYS) /* vmsplice() not supported */ #endif j = write (fd, buf + i, len - i); if (j <= 0) { if (j == 0) errno = EPIPE; msg_Err (stream, "cannot write data (%m)"); error = true; break; } } #ifdef HAVE_VMSPLICE vlc_cleanup_run (); /* munmap (buf, bufsize) */ #endif } while (!error); msg_Dbg (stream, "compressed stream at EOF"); return NULL; }
/** * Sends one HTTP/2 frame through TLS. * * This function sends a whole HTTP/2 frame through a TLS session, then * releases the memory used by the frame. * * The caller must "own" the write side of the TLS session. * * @note This is a blocking function and may be a thread cancellation point. * * @return 0 on success, -1 if the connection failed */ static int vlc_h2_frame_send(struct vlc_tls *tls, struct vlc_h2_frame *f) { size_t len = vlc_h2_frame_size(f); ssize_t val; vlc_cleanup_push(free, f); val = vlc_https_send(tls, f->data, len); vlc_cleanup_pop(); free(f); return ((size_t)val == len) ? 0 : -1; }
vlc_tls_t *vlc_tls_ClientSessionCreate (vlc_tls_creds_t *crd, int fd, const char *host, const char *service, const char *const *alpn, char **alp) { vlc_tls_t *session; int canc, val; canc = vlc_savecancel(); session = vlc_tls_SessionCreate (crd, fd, host, alpn); if (session == NULL) { vlc_restorecancel(canc); return NULL; } mtime_t deadline = mdate (); deadline += var_InheritInteger (crd, "ipv4-timeout") * 1000; struct pollfd ufd[1]; ufd[0].fd = fd; vlc_cleanup_push (cleanup_tls, session); while ((val = crd->handshake(crd, session, host, service, alp)) != 0) { if (val < 0) { msg_Err(crd, "TLS session handshake error"); error: vlc_tls_SessionDelete (session); session = NULL; break; } mtime_t now = mdate (); if (now > deadline) now = deadline; assert (val <= 2); ufd[0] .events = (val == 1) ? POLLIN : POLLOUT; vlc_restorecancel(canc); val = poll (ufd, 1, (deadline - now) / 1000); canc = vlc_savecancel(); if (val == 0) { msg_Err(crd, "TLS session handshake timeout"); goto error; } } vlc_cleanup_pop(); vlc_restorecancel(canc); return session; }
static void *joinable_thread(void *data) { vlc_thread_t th = data; void *ret; vlc_cleanup_push(finish_joinable_thread, th); thread = th; ret = th->entry(th->data); vlc_cleanup_run(); return ret; }
static void *detached_thread(void *data) { vlc_thread_t th = data; thread = th; vlc_cleanup_push(clean_detached_thread, th); th->entry(th->data); vlc_cleanup_pop(); clean_detached_thread(th); return NULL; }
int vlc_sem_wait_i11e(vlc_sem_t *sem) { vlc_interrupt_t *ctx = vlc_interrupt_get(); if (ctx == NULL) return vlc_sem_wait(sem), 0; vlc_interrupt_prepare(ctx, vlc_interrupt_sem, sem); vlc_cleanup_push(vlc_interrupt_cleanup, ctx); vlc_sem_wait(sem); vlc_cleanup_pop(); return vlc_interrupt_finish(ctx); }
/***************************************************************************** * ALSAThread: asynchronous thread used to DMA the data to the device *****************************************************************************/ static void* ALSAThread( void *data ) { aout_instance_t * p_aout = data; struct aout_sys_t * p_sys = p_aout->output.p_sys; /* Wait for the exact time to start playing (avoids resampling) */ vlc_sem_wait( &p_sys->wait ); mwait( p_sys->start_date - AOUT_PTS_TOLERANCE / 4 ); vlc_cleanup_push( pcm_drop, p_sys->p_snd_pcm ); for(;;) ALSAFill( p_aout ); assert(0); vlc_cleanup_pop(); }
int vlc_sem_wait_i11e(vlc_sem_t *sem) { vlc_interrupt_t *ctx = vlc_threadvar_get(vlc_interrupt_var); if (ctx == NULL) return vlc_sem_wait(sem), 0; int ret = vlc_interrupt_prepare(ctx, vlc_interrupt_sem, sem); if (ret) { vlc_testcancel(); return ret; } vlc_cleanup_push(vlc_interrupt_cleanup, ctx); vlc_sem_wait(sem); vlc_cleanup_pop(); return vlc_interrupt_finish(ctx); }
static void *Thread(void *data) { demux_t *demux = data; demux_sys_t *sys = demux->p_sys; struct wl_display *display = sys->display; struct pollfd ufd[1]; unsigned interval = lroundf(CLOCK_FREQ / (sys->rate * 1000.f)); int canc = vlc_savecancel(); vlc_cleanup_push(cleanup_wl_display_read, display); ufd[0].fd = wl_display_get_fd(display); ufd[0].events = POLLIN; for (;;) { if (DisplayError(demux, display)) break; if (sys->es != NULL) { block_t *block = Shoot(demux); block->i_pts = block->i_dts = vlc_tick_now(); es_out_SetPCR(demux->out, block->i_pts); es_out_Send(demux->out, sys->es, block); } while (wl_display_prepare_read(display) != 0) wl_display_dispatch_pending(display); wl_display_flush(display); vlc_restorecancel(canc); while (poll(ufd, 1, interval) < 0); canc = vlc_savecancel(); wl_display_read_events(display); wl_display_dispatch_pending(display); } vlc_cleanup_pop(); vlc_restorecancel(canc); return NULL; }
void *rtp_thread (void *data) { demux_t *demux = data; demux_sys_t *p_sys = demux->p_sys; bool autodetect = true; if (vlc_timer_create (&p_sys->timer, rtp_process, data)) return NULL; vlc_cleanup_push (timer_cleanup, (void *)p_sys->timer); for (;;) { block_t *block = rtp_recv (demux); if (block == NULL) break; if (autodetect) { /* Autodetect payload type, _before_ rtp_queue() */ /* No need for lock - the queue is empty. */ if (rtp_autodetect (demux, p_sys->session, block)) { block_Release (block); continue; } autodetect = false; } int canc = vlc_savecancel (); vlc_mutex_lock (&p_sys->lock); rtp_queue (demux, p_sys->session, block); vlc_mutex_unlock (&p_sys->lock); vlc_restorecancel (canc); rtp_process (demux); } vlc_cleanup_run (); return NULL; }
/***************************************************************************** * OSSThread: asynchronous thread used to DMA the data to the device *****************************************************************************/ static void* OSSThread( void *obj ) { audio_output_t * p_aout = (audio_output_t*)obj; struct aout_sys_t * p_sys = p_aout->sys; mtime_t next_date = 0; for( ;; ) { aout_buffer_t * p_buffer = NULL; int canc = vlc_savecancel (); if ( p_aout->format.i_format != VLC_CODEC_SPDIFL ) { mtime_t buffered = BufferDuration( p_aout ); /* Next buffer will be played at mdate() + buffered */ p_buffer = aout_PacketNext( p_aout, mdate() + buffered ); if( p_buffer == NULL && buffered > ( p_aout->sys->max_buffer_duration / p_aout->sys->i_fragstotal ) ) { vlc_restorecancel (canc); /* If we have at least a fragment full, then we can wait a * little and retry to get a new audio buffer instead of * playing a blank sample */ msleep( ( p_aout->sys->max_buffer_duration / p_aout->sys->i_fragstotal / 2 ) ); continue; } } else { vlc_restorecancel (canc); /* emu10k1 driver does not report Buffer Duration correctly in * passthrough mode so we have to cheat */ if( !next_date ) { next_date = mdate(); } else { mtime_t delay = next_date - mdate(); if( delay > AOUT_MAX_PTS_ADVANCE ) { msleep( delay / 2 ); } } for( ;; ) { canc = vlc_savecancel (); p_buffer = aout_PacketNext( p_aout, next_date ); if ( p_buffer ) break; vlc_restorecancel (canc); msleep( VLC_HARD_MIN_SLEEP ); next_date = mdate(); } } uint8_t * p_bytes; int i_size; if ( p_buffer != NULL ) { p_bytes = p_buffer->p_buffer; i_size = p_buffer->i_buffer; /* This is theoretical ... we'll see next iteration whether * we're drifting */ next_date += p_buffer->i_length; } else { i_size = FRAME_SIZE / p_aout->format.i_frame_length * p_aout->format.i_bytes_per_frame; p_bytes = malloc( i_size ); memset( p_bytes, 0, i_size ); next_date = 0; } oss_thread_ctx_t ctx = { .p_buffer = p_buffer, .p_bytes = p_bytes, }; vlc_cleanup_push( OSSThreadCleanup, &ctx ); vlc_restorecancel( canc ); int i_tmp = write( p_sys->i_fd, p_bytes, i_size ); if( i_tmp < 0 ) { msg_Err( p_aout, "write failed (%m)" ); } vlc_cleanup_run(); } return NULL; }
static void* vnc_worker_thread( void *obj ) { filter_t* p_filter = (filter_t*)obj; filter_sys_t *p_sys = p_filter->p_sys; vlc_thread_t update_thread; int canc = vlc_savecancel (); msg_Dbg( p_filter, "VNC worker thread started" ); int fd = vnc_connect( p_filter ); if( fd == -1 ) { msg_Err( p_filter, "Error occurred while handshaking VNC host" ); return NULL; } /* Create an empty picture for VNC the data */ picture_t *pic = picture_New( VLC_CODEC_YUVA, p_sys->i_vnc_width, p_sys->i_vnc_height, 1, 1 ); if( likely(pic != NULL) ) { vlc_mutex_lock( &p_sys->lock ); p_sys->i_socket = fd; p_sys->p_pic = pic; vlc_mutex_unlock( &p_sys->lock ); } else { net_Close( fd ); return NULL; } write_update_request( p_filter, false ); /* create the update request thread */ bool polling = var_InheritBool( p_filter, RMTOSD_CFG "vnc-polling" ); if( polling && vlc_clone( &update_thread, update_request_thread, p_filter, VLC_THREAD_PRIORITY_LOW ) ) { msg_Err( p_filter, "cannot spawn VNC update request thread" ); polling = false; } vlc_cleanup_push( polling ? update_thread_cleanup : dummy_cleanup, &update_thread ); /* connection is initialized, now read and handle server messages */ for( ;; ) { rfbServerToClientMsg msg; int i_msgSize; memset( &msg, 0, sizeof(msg) ); vlc_restorecancel (canc); if( !read_exact(p_filter, fd, &msg, 1 ) ) { msg_Err( p_filter, "Error while waiting for next server message"); break; } switch (msg.type) { case rfbFramebufferUpdate: i_msgSize = sz_rfbFramebufferUpdateMsg; break; case rfbSetColourMapEntries: i_msgSize = sz_rfbSetColourMapEntriesMsg; break; case rfbBell: i_msgSize = sz_rfbBellMsg; break; case rfbServerCutText: i_msgSize = sz_rfbServerCutTextMsg; break; case rfbReSizeFrameBuffer: i_msgSize = sz_rfbReSizeFrameBufferMsg; break; default: i_msgSize = 0; msg_Err( p_filter, "Invalid message %u received", msg.type ); break; } if( i_msgSize <= 0 ) break; if( --i_msgSize > 0 ) { if ( !read_exact( p_filter, fd, ((char *)&msg) + 1, i_msgSize ) ) { msg_Err( p_filter, "Error while reading message of type %u", msg.type ); break; } } canc = vlc_savecancel (); process_server_message( p_filter, &msg); } vlc_cleanup_pop(); if( polling ) update_thread_cleanup( &update_thread ); msg_Dbg( p_filter, "VNC message reader thread ended" ); vlc_restorecancel (canc); return NULL; }
static void *Thread (void *data) { stream_t *stream = data; stream_sys_t *p_sys = stream->p_sys; #ifdef HAVE_VMSPLICE const ssize_t page_mask = sysconf (_SC_PAGE_SIZE) - 1; #endif int fd = p_sys->write_fd; bool error = false; do { ssize_t len; int canc = vlc_savecancel (); #ifdef HAVE_VMSPLICE unsigned char *buf = mmap (NULL, bufsize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if (unlikely(buf == MAP_FAILED)) break; vlc_cleanup_push (cleanup_mmap, buf); #else unsigned char *buf = malloc (bufsize); if (unlikely(buf == NULL)) break; vlc_cleanup_push (free, buf); #endif vlc_mutex_lock (&p_sys->lock); while (p_sys->paused) /* practically always false, but... */ vlc_cond_wait (&p_sys->wait, &p_sys->lock); len = stream_Read (stream->p_source, buf, bufsize); vlc_mutex_unlock (&p_sys->lock); vlc_restorecancel (canc); error = len <= 0; for (ssize_t i = 0, j; i < len; i += j) { #ifdef HAVE_VMSPLICE if ((len - i) <= page_mask) /* incomplete last page */ j = write (fd, buf + i, len - i); else { struct iovec iov = { buf + i, (len - i) & ~page_mask, }; j = vmsplice (fd, &iov, 1, SPLICE_F_GIFT); } if (j == -1 && errno == ENOSYS) /* vmsplice() not supported */ #endif j = write (fd, buf + i, len - i); if (j <= 0) { if (j == 0) errno = EPIPE; msg_Err (stream, "cannot write data: %s", vlc_strerror_c(errno)); error = true; break; } } vlc_cleanup_run (); /* free (buf) */ } while (!error); msg_Dbg (stream, "compressed stream at EOF"); /* Let child process know about EOF */ p_sys->write_fd = -1; close (fd); return NULL; }
int DoAcoustIdWebRequest( vlc_object_t *p_obj, acoustid_fingerprint_t *p_data ) { int i_ret; int i_status; struct webrequest_t request = { NULL, NULL, NULL }; if ( !p_data->psz_fingerprint ) return VLC_SUCCESS; i_ret = asprintf( & request.psz_url, "http://fingerprint.videolan.org/acoustid.php?meta=recordings+tracks+usermeta+releases&duration=%d&fingerprint=%s", p_data->i_duration, p_data->psz_fingerprint ); if ( i_ret < 1 ) return VLC_EGENERIC; vlc_cleanup_push( cancelDoAcoustIdWebRequest, &request ); msg_Dbg( p_obj, "Querying AcoustID from %s", request.psz_url ); request.p_stream = stream_UrlNew( p_obj, request.psz_url ); if ( !request.p_stream ) { i_status = VLC_EGENERIC; goto cleanup; } /* read answer */ i_ret = 0; for( ;; ) { int i_read = 65536; if( i_ret >= INT_MAX - i_read ) break; request.p_buffer = realloc_or_free( request.p_buffer, 1 + i_ret + i_read ); if( !request.p_buffer ) { i_status = VLC_ENOMEM; goto cleanup; } i_read = stream_Read( request.p_stream, &request.p_buffer[i_ret], i_read ); if( i_read <= 0 ) break; i_ret += i_read; } stream_Delete( request.p_stream ); request.p_stream = NULL; request.p_buffer[ i_ret ] = 0; int i_canc = vlc_savecancel(); if ( ParseJson( p_obj, request.p_buffer, & p_data->results ) ) { msg_Dbg( p_obj, "results count == %d", p_data->results.count ); } else { msg_Dbg( p_obj, "No results" ); } vlc_restorecancel( i_canc ); i_status = VLC_SUCCESS; cleanup: vlc_cleanup_run( ); return i_status; }
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( ); }