Exemplo n.º 1
0
OMX_ERRORTYPE WaitForOmxEvent(OmxEventQueue *queue, OMX_EVENTTYPE *event,
    OMX_U32 *data_1, OMX_U32 *data_2, OMX_PTR *event_data)
{
    OmxEvent *p_event;

    vlc_mutex_lock(&queue->mutex);

    if(!queue->p_events)
        vlc_cond_timedwait(&queue->cond, &queue->mutex, mdate()+CLOCK_FREQ);

    p_event = queue->p_events;
    if(p_event)
    {
        queue->p_events = p_event->next;
        if(!queue->p_events) queue->pp_last_event = &queue->p_events;
    }

    vlc_mutex_unlock(&queue->mutex);

    if(p_event)
    {
        if(event) *event = p_event->event;
        if(data_1) *data_1 = p_event->data_1;
        if(data_2) *data_2 = p_event->data_2;
        if(event_data) *event_data = p_event->event_data;
        free(p_event);
        return OMX_ErrorNone;
    }

    return OMX_ErrorTimeout;
}
Exemplo n.º 2
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);
}
Exemplo n.º 3
0
/**
 * @brief Directory Monitoring thread loop
 */
void *RunMonitoringThread( void *p_this )
{
    monitoring_thread_t *p_mon = (monitoring_thread_t*) p_this;
    vlc_cond_init( &p_mon->wait );
    vlc_mutex_init( &p_mon->lock );

    var_Create( p_mon, "ml-recursive-scan", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );

    while( vlc_object_alive( p_mon ) )
    {
        vlc_mutex_lock( &p_mon->lock );

        /* Update */
        UpdateLibrary( p_mon );

        /* We wait MONITORING_DELAY seconds or wait that the media library
           signals us to do something */
        vlc_cond_timedwait( &p_mon->wait, &p_mon->lock,
                            mdate() + 1000000*MONITORING_DELAY );

        vlc_mutex_unlock( &p_mon->lock );
    }
    vlc_cond_destroy( &p_mon->wait );
    vlc_mutex_destroy( &p_mon->lock );
    return NULL;
}
Exemplo n.º 4
0
Arquivo: utils.c Projeto: Mettbrot/vlc
OMX_ERRORTYPE WaitForOmxEvent(decoder_t *p_dec, OMX_EVENTTYPE *event,
    OMX_U32 *data_1, OMX_U32 *data_2, OMX_PTR *event_data)
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    OmxEvent *p_event;

    vlc_mutex_lock(&p_sys->mutex);

    if(!p_sys->p_events)
        vlc_cond_timedwait(&p_sys->cond, &p_sys->mutex, mdate()+CLOCK_FREQ);

    p_event = p_sys->p_events;
    if(p_event)
    {
        p_sys->p_events = p_event->next;
        if(!p_sys->p_events) p_sys->pp_last_event = &p_sys->p_events;
    }

    vlc_mutex_unlock(&p_sys->mutex);

    if(p_event)
    {
        if(event) *event = p_event->event;
        if(data_1) *data_1 = p_event->data_1;
        if(data_2) *data_2 = p_event->data_2;
        if(event_data) *event_data = p_event->event_data;
        free(p_event);
        return OMX_ErrorNone;
    }

    return OMX_ErrorTimeout;
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
static void test_cancel_thumbnail( libvlc_instance_t* p_vlc )
{
    vlc_thumbnailer_t* p_thumbnailer = vlc_thumbnailer_Create(
                VLC_OBJECT( p_vlc->p_libvlc_int ) );
    assert( p_thumbnailer != NULL );

    struct test_ctx ctx;
    vlc_cond_init( &ctx.cond );
    vlc_mutex_init( &ctx.lock );

    const char* psz_mrl = "mock://video_track_count=1;audio_track_count=1";
    input_item_t* p_item = input_item_New( psz_mrl, "mock item" );
    assert( p_item != NULL );

    vlc_mutex_lock( &ctx.lock );
    int res = 0;
    vlc_thumbnailer_request_t* p_req = vlc_thumbnailer_RequestByTime( p_thumbnailer,
        VLC_TICK_FROM_SEC( 1 ), VLC_THUMBNAILER_SEEK_PRECISE, p_item,
        VLC_TICK_INVALID, thumbnailer_callback_cancel, &ctx );
    vlc_thumbnailer_Cancel( p_thumbnailer, p_req );
    while ( ctx.b_done == false )
    {
        vlc_tick_t timeout = vlc_tick_now() + VLC_TICK_FROM_SEC( 1 );
        res = vlc_cond_timedwait( &ctx.cond, &ctx.lock, timeout );
        assert( res != ETIMEDOUT );
    }
    vlc_mutex_unlock( &ctx.lock );

    input_item_Release( p_item );

    vlc_thumbnailer_Release( p_thumbnailer );
}
Exemplo n.º 7
0
static void test_thumbnails( libvlc_instance_t* p_vlc )
{
    vlc_thumbnailer_t* p_thumbnailer = vlc_thumbnailer_Create(
                VLC_OBJECT( p_vlc->p_libvlc_int ) );
    assert( p_thumbnailer != NULL );

    struct test_ctx ctx;
    vlc_cond_init( &ctx.cond );
    vlc_mutex_init( &ctx.lock );

    for ( size_t i = 0; i < sizeof(test_params) / sizeof(test_params[0]); ++i)
    {
        char* psz_mrl;

        ctx.test_idx = i;
        ctx.b_done = false;

        if ( asprintf( &psz_mrl, "mock://video_track_count=%u;audio_track_count=%u"
                       ";length=%" PRId64 ";video_chroma=ARGB;add_video_track_at=%" PRId64,
                       test_params[i].i_nb_video_tracks,
                       test_params[i].i_nb_audio_tracks, MOCK_DURATION,
                       test_params[i].i_add_video_track_at ) < 0 )
            assert( !"Failed to allocate mock mrl" );
        input_item_t* p_item = input_item_New( psz_mrl, "mock item" );
        assert( p_item != NULL );

        vlc_mutex_lock( &ctx.lock );
        int res = 0;

        if ( test_params[i].b_use_pos )
        {
            vlc_thumbnailer_RequestByPos( p_thumbnailer, test_params[i].f_pos,
                test_params[i].b_fast_seek ?
                    VLC_THUMBNAILER_SEEK_FAST : VLC_THUMBNAILER_SEEK_PRECISE,
                p_item, test_params[i].i_timeout, thumbnailer_callback, &ctx );
        }
        else
        {
            vlc_thumbnailer_RequestByTime( p_thumbnailer, test_params[i].i_time,
                test_params[i].b_fast_seek ?
                    VLC_THUMBNAILER_SEEK_FAST : VLC_THUMBNAILER_SEEK_PRECISE,
                p_item, test_params[i].i_timeout, thumbnailer_callback, &ctx );
        }

        while ( ctx.b_done == false )
        {
            vlc_tick_t timeout = vlc_tick_now() + VLC_TICK_FROM_SEC( 1 );
            res = vlc_cond_timedwait( &ctx.cond, &ctx.lock, timeout );
            assert( res != ETIMEDOUT );
        }
        vlc_mutex_unlock( &ctx.lock );

        input_item_Release( p_item );
        free( psz_mrl );
    }
    vlc_thumbnailer_Release( p_thumbnailer );
}
Exemplo n.º 8
0
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
    }
}
Exemplo n.º 9
0
int vout_GetSnapshot( vout_thread_t *p_vout,
                      block_t **pp_image, picture_t **pp_picture,
                      video_format_t *p_fmt,
                      const char *psz_format, mtime_t i_timeout )
{
    vout_thread_sys_t *p_sys = p_vout->p;

    vlc_mutex_lock( &p_sys->snapshot.lock );
    p_sys->snapshot.i_request++;

    const mtime_t i_deadline = mdate() + i_timeout;
    while( p_sys->snapshot.b_available && !p_sys->snapshot.p_picture )
    {
        if( vlc_cond_timedwait( &p_sys->snapshot.wait, &p_sys->snapshot.lock,
                                i_deadline ) )
            break;
    }

    picture_t *p_picture = p_sys->snapshot.p_picture;
    if( p_picture )
        p_sys->snapshot.p_picture = p_picture->p_next;
    else if( p_sys->snapshot.i_request > 0 )
        p_sys->snapshot.i_request--;
    vlc_mutex_unlock( &p_sys->snapshot.lock );

    if( !p_picture )
    {
        msg_Err( p_vout, "Failed to grab a snapshot" );
        return VLC_EGENERIC;
    }

    if( pp_image )
    {
        vlc_fourcc_t i_format = VLC_CODEC_PNG;
        if( psz_format && image_Type2Fourcc( psz_format ) )
            i_format = image_Type2Fourcc( psz_format );

        const int i_override_width  = var_GetInteger( p_vout, "snapshot-width" );
        const int i_override_height = var_GetInteger( p_vout, "snapshot-height" );

        if( picture_Export( VLC_OBJECT(p_vout), pp_image, p_fmt,
                            p_picture, i_format, i_override_width, i_override_height ) )
        {
            msg_Err( p_vout, "Failed to convert image for snapshot" );
            picture_Release( p_picture );
            return VLC_EGENERIC;
        }
    }
    if( pp_picture )
        *pp_picture = p_picture;
    else
        picture_Release( p_picture );
    return VLC_SUCCESS;
}
Exemplo n.º 10
0
Arquivo: timer.c Projeto: 0xheart0/vlc
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 ();
}
Exemplo n.º 11
0
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);
}
Exemplo n.º 12
0
/*
   does a sleep if the sleep was interrupted through
   the thread kill event return false...
*/
ATMO_BOOL CThread::ThreadSleep(DWORD millisekunden)
{
#if defined(_ATMO_VLC_PLUGIN_)
     ATMO_BOOL temp;
     vlc_mutex_lock( &m_TerminateLock );
     vlc_cond_timedwait(&m_TerminateCond,
                        &m_TerminateLock,
                        mdate() + (mtime_t)(millisekunden * 1000));
     temp = m_bTerminated;
     vlc_mutex_unlock( &m_TerminateLock );
     return !temp;

#else
     DWORD res = WaitForSingleObject(m_hTerminateEvent,millisekunden);
	 return (res == WAIT_TIMEOUT);
#endif
}
Exemplo n.º 13
0
static chunk_t *get_chunk( stream_t *s, const bool wait )
{
    stream_sys_t *p_sys = s->p_sys;
    unsigned count;
    chunk_t *chunk = NULL;

    vlc_mutex_lock( &p_sys->download.lock_wait );
    count = vlc_array_count( p_sys->download.chunks );
    while( p_sys->playback.index >= count || p_sys->b_tseek )
    {
        /* Yes I know, checking for p_sys->b_die is not reliable,
         * that's why vlc_object_alive() has been deprecated. But if I
         * understood well, there is no good solution with a stream_filter
         * module anyaway. */
        if( !wait || p_sys->b_error )
        {
            vlc_mutex_unlock( &p_sys->download.lock_wait );
            msg_Warn( s, "get_chunk failed! (playback index %u)",
                    p_sys->playback.index );
            return NULL;
        }
        if( NO_MORE_CHUNKS )
        {
            vlc_mutex_unlock( &p_sys->download.lock_wait );
            msg_Info( s, "No more chunks, end of the VOD" );
            return NULL;
        }

        msg_Dbg( s, "get_chunk is waiting !!!" );
        vlc_cond_timedwait( &p_sys->download.wait,
                &p_sys->download.lock_wait, mdate() + 500000 );
        count = vlc_array_count( p_sys->download.chunks );
        msg_Dbg( s, "count is %u, and index is %u", count, p_sys->playback.index );
    }
    chunk = vlc_array_item_at_index( p_sys->download.chunks, p_sys->playback.index );

    vlc_mutex_unlock( &p_sys->download.lock_wait );

    return chunk;
}
Exemplo n.º 14
0
picture_t *vout_snapshot_Get(vout_snapshot_t *snap, mtime_t timeout)
{
    vlc_mutex_lock(&snap->lock);

    /* */
    snap->request_count++;

    /* */
    const mtime_t deadline = mdate() + timeout;
    while (snap->is_available && !snap->picture && mdate() < deadline)
        vlc_cond_timedwait(&snap->wait, &snap->lock, deadline);

    /* */
    picture_t *picture = snap->picture;
    if (picture)
        snap->picture = picture->p_next;
    else if (snap->request_count > 0)
        snap->request_count--;

    vlc_mutex_unlock(&snap->lock);

    return picture;
}
Exemplo n.º 15
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;
}
Exemplo n.º 16
0
static chunk_t *get_chunk( stream_t *s, const bool wait, bool *pb_isinit )
{
    stream_sys_t *p_sys = s->p_sys;

    bool b_foo;
    if ( !pb_isinit )
        pb_isinit = &b_foo;

    *pb_isinit = false;

    vlc_mutex_lock( &p_sys->lock );

    assert(p_sys->p_current_stream);
    chunk_t *p_chunk = p_sys->p_current_stream->p_playback;

    /* init chunk handling, overrides the current one */
    vlc_mutex_lock( &p_sys->playback.lock );
    if ( p_sys->playback.init.p_datachunk )
    {
        if ( p_sys->playback.init.p_startchunk == NULL ||
             p_sys->playback.init.p_startchunk == p_chunk )
        {
            /* Override current chunk and pass init chunk instead */
            p_chunk = p_sys->playback.init.p_datachunk;
            *pb_isinit = true;
            setChunkOffset( p_sys, p_chunk );
#ifndef NDEBUG
            if ( !p_chunk->read_pos )
                msg_Dbg( s, "Sending init chunk from offset %"PRId64, p_chunk->offset );
#endif
            vlc_mutex_unlock( &p_sys->playback.lock );
            vlc_mutex_unlock( &p_sys->lock );
            return p_chunk;
        }
    }
    vlc_mutex_unlock( &p_sys->playback.lock );
    /* !init chunk handling */

    vlc_mutex_lock( &p_sys->p_current_stream->chunks_lock );
    vlc_mutex_unlock( &p_sys->lock );

    while( p_chunk && !p_chunk->data )
    {
        /* Yes I know, checking for p_sys->b_die is not reliable,
         * that's why vlc_object_alive() has been deprecated. But if I
         * understood well, there is no good solution with a stream_filter
         * module anyaway. */
        if( !wait )
        {
            msg_Warn( s, "get_chunk failed! (starttime %"PRId64")", p_chunk->start_time );
            vlc_mutex_unlock( &p_sys->p_current_stream->chunks_lock );
            return NULL;
        }

        if( no_more_chunks( p_sys ) )
        {
            msg_Info( s, "No more chunks, end of the VOD" );
            vlc_mutex_unlock( &p_sys->p_current_stream->chunks_lock );
            return NULL;
        }

        msg_Dbg( s, "get_chunk is waiting for chunk %"PRId64"!!!", p_chunk->start_time );
        vlc_cond_timedwait( &p_sys->playback.wait,
                &p_sys->p_current_stream->chunks_lock, mdate() + CLOCK_FREQ/2 );
    }

    if ( p_chunk )
    {
        setChunkOffset( p_sys, p_chunk );
#ifndef NDEBUG
        if ( !p_chunk->read_pos )
            msg_Dbg( s, "Sending chunk %"PRId64" from offset %"PRId64, p_chunk->start_time, p_chunk->offset );
#endif
    }
    vlc_mutex_unlock( &p_sys->p_current_stream->chunks_lock );

    return p_chunk;
}
Exemplo n.º 17
0
/*****************************************************************************
 * 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 );
}
Exemplo n.º 18
0
Arquivo: cast.cpp Projeto: Adatan/vlc
/*****************************************************************************
 * Open: connect to the Chromecast and initialize the sout
 *****************************************************************************/
static int Open(vlc_object_t *p_this)
{
    sout_stream_t *p_stream = (sout_stream_t*)p_this;
    sout_stream_sys_t *p_sys;
    p_sys = new(std::nothrow) sout_stream_sys_t;
    if (p_sys == NULL)
        return VLC_ENOMEM;
    p_stream->p_sys = p_sys;

    config_ChainParse(p_stream, SOUT_CFG_PREFIX, ppsz_sout_options, p_stream->p_cfg);

    char *psz_ipChromecast = var_GetNonEmptyString(p_stream, SOUT_CFG_PREFIX "ip");
    if (psz_ipChromecast == NULL)
    {
        msg_Err(p_stream, "No Chromecast receiver IP provided");
        Clean(p_stream);
        return VLC_EGENERIC;
    }

    p_sys->i_sock_fd = connectChromecast(p_stream, psz_ipChromecast);
    free(psz_ipChromecast);
    if (p_sys->i_sock_fd < 0)
    {
        msg_Err(p_stream, "Could not connect the Chromecast");
        Clean(p_stream);
        return VLC_EGENERIC;
    }
    p_sys->i_status = CHROMECAST_TLS_CONNECTED;

    char psz_localIP[NI_MAXNUMERICHOST];
    if (net_GetSockAddress(p_sys->i_sock_fd, psz_localIP, NULL))
    {
        msg_Err(p_this, "Cannot get local IP address");
        Clean(p_stream);
        return VLC_EGENERIC;
    }
    p_sys->serverIP = psz_localIP;

    char *psz_mux = var_GetNonEmptyString(p_stream, SOUT_CFG_PREFIX "mux");
    if (psz_mux == NULL)
    {
        Clean(p_stream);
        return VLC_EGENERIC;
    }
    char *psz_chain = NULL;
    int i_bytes = asprintf(&psz_chain, "http{dst=:%u/stream,mux=%s}",
                           (unsigned)var_InheritInteger(p_stream, SOUT_CFG_PREFIX"http-port"),
                           psz_mux);
    free(psz_mux);
    if (i_bytes < 0)
    {
        Clean(p_stream);
        return VLC_EGENERIC;
    }

    p_sys->p_out = sout_StreamChainNew(p_stream->p_sout, psz_chain, NULL, NULL);
    free(psz_chain);
    if (p_sys->p_out == NULL)
    {
        Clean(p_stream);
        return VLC_EGENERIC;
    }

    vlc_mutex_init(&p_sys->lock);
    vlc_cond_init(&p_sys->loadCommandCond);

    // Start the Chromecast event thread.
    if (vlc_clone(&p_sys->chromecastThread, chromecastThread, p_stream,
                  VLC_THREAD_PRIORITY_LOW))
    {
        msg_Err(p_stream, "Could not start the Chromecast talking thread");
        Clean(p_stream);
        return VLC_EGENERIC;
    }

    /* Ugly part:
     * We want to be sure that the Chromecast receives the first data packet sent by
     * the HTTP server. */

    // Lock the sout thread until we have sent the media loading command to the Chromecast.
    int i_ret = 0;
    const mtime_t deadline = mdate() + 6 * CLOCK_FREQ;
    vlc_mutex_lock(&p_sys->lock);
    while (p_sys->i_status != CHROMECAST_MEDIA_LOAD_SENT)
    {
        i_ret = vlc_cond_timedwait(&p_sys->loadCommandCond, &p_sys->lock, deadline);
        if (i_ret == ETIMEDOUT)
        {
            msg_Err(p_stream, "Timeout reached before sending the media loading command");
            vlc_mutex_unlock(&p_sys->lock);
            vlc_cancel(p_sys->chromecastThread);
            Clean(p_stream);
            return VLC_EGENERIC;
        }
    }
    vlc_mutex_unlock(&p_sys->lock);

    /* Even uglier: sleep more to let to the Chromecast initiate the connection
     * to the http server. */
    msleep(2 * CLOCK_FREQ);

    // Set the sout callbacks.
    p_stream->pf_add    = Add;
    p_stream->pf_del    = Del;
    p_stream->pf_send   = Send;

    return VLC_SUCCESS;
}