Commit c77512ce authored by Hugo Beauzée-Luyssen's avatar Hugo Beauzée-Luyssen

VLCMediaPlayer: Add an helper to wait for an event.

parent 911f4db7
......@@ -92,10 +92,39 @@ MediaPlayer::registerEvents()
/**
* Event dispatcher.
*/
void
MediaPlayer::checkForWaitedEvents(const libvlc_event_t *event)
{
QMutexLocker lock( &m_mutex );
// Use the user provided callback to check if this event suits him.
// This is intented to filter out some events, such as multiple length changed
// with a value of 0
if ( m_eventsCallback != NULL && m_eventsCallback( this, event ) == false )
return ;
if ( m_eventsExpected.contains( event->type ) == true )
{
m_eventReceived = event->type;
m_waitCond.wakeAll();
}
else if ( m_eventsCancel.contains( event->type ) == true )
{
m_eventReceived = event->type;
m_waitCond.wakeAll();
}
//Otherwise this is an event we don't care about.
}
void
MediaPlayer::callbacks( const libvlc_event_t* event, void* ptr )
{
Q_ASSERT_X( event->type >= libvlc_MediaPlayerMediaChanged &&
event->type < libvlc_MediaListItemAdded, "event callback", "Only libvlc_MediaPlayer* events are supported" );
MediaPlayer* self = reinterpret_cast<MediaPlayer*>( ptr );
self->checkForWaitedEvents( event );
switch ( event->type )
{
case libvlc_MediaPlayerPlaying:
......@@ -312,3 +341,35 @@ void MediaPlayer::setAudioOutput(const char *module)
{
libvlc_audio_output_set( m_internalPtr, module );
}
void
MediaPlayer::configureWaitForEvent( const QList<int> &toWait, const QList<int> &cancel,
CheckEventCallback callback )
{
//This mutex will only be unlocked when entering the wait condition, and upon
//wait completion.
m_mutex.lock();
Q_ASSERT_X( m_eventsExpected.size() == 0 && m_eventsCancel.size() == 0,
"waitForEvent", "waitForEvent is not supposed to be used simultaneously" );
m_eventsExpected.append( toWait );
m_eventsCancel.append( cancel );
m_eventReceived = 0;
m_eventsCallback = callback;
}
MediaPlayer::EventWaitResult
MediaPlayer::waitForEvent( unsigned long timeoutDuration )
{
bool timeout = !m_waitCond.wait( &m_mutex, timeoutDuration );
//m_mutex is now locked.
bool found = ( timeout == false && m_eventsExpected.contains( m_eventReceived ) == true );
m_eventsCancel.clear();
m_eventsExpected.clear();
m_eventsCallback = NULL;
m_eventReceived = 0;
m_mutex.unlock();
//And give feedback:
if ( timeout == true )
return Timeout;
return ( found ? Success : Canceled );
}
......@@ -23,8 +23,11 @@
#ifndef VLCMEDIAPLAYER_H
#define VLCMEDIAPLAYER_H
#include <QList>
#include <QMutex>
#include <QObject>
#include <QWaitCondition>
#include "VLCpp.hpp"
struct libvlc_media_player_t;
......@@ -38,6 +41,14 @@ namespace LibVLCpp
{
Q_OBJECT
public:
enum EventWaitResult
{
Success, ///The event has been emited.
Canceled,///A cancelation event has been emited first.
Timeout ///Timeout has been reached.
};
typedef bool (*CheckEventCallback)(const MediaPlayer*, const libvlc_event_t*);
MediaPlayer();
MediaPlayer( Media* media );
~MediaPlayer();
......@@ -70,13 +81,70 @@ namespace LibVLCpp
void setKeyInput( bool enabled );
void setAudioOutput(const char* module);
/**
* @brief configure the usage of waitForEvent.
*
* This method MUST be called before play(). It will lock a mutex
* that only will be unlocked in the waitForEvent() method. This mutex prevent
* any event processing.
* Using this method in any other scheme than:
* \li mediaPlayer->configureWaitForEvent(...);
* \li mediaPlayer->play();
* \li mediaPlayer->waitForEvents(...);
*
* is likely to result in a deadlock.
*
* @param toWait The list of events to wait for.
* @param cancel A list of events that would cancel the waiting process.
* @param callback A callback that will be called to check if this event is
* ok (for instance, accoding to the value of a changed variable)
* Callback will be called from an external thread.
*/
void configureWaitForEvent(const QList<int> &toWait,
const QList<int> &cancel,
CheckEventCallback callback = NULL );
/**
* @brief This method will wait for one of the events specified by the
* list given to configureWaitForEvent().
*
* In case the waiting process should be canceled by
* some specific events, they shall be passed in the cancel vector.
* A timeout parameter can be passed. Default is to wait forever.
*
* This method MUST be called IMMEDIATLY AFTER play(), as a mutex is held,
* and would block any event processing until the actual waiting started.
*
* This method is concieved to wait on one unique given set of events.
* You can't wait for another set of events from another thread at the same time.
*
* Events (regardless of their presence in the wait or cancel list) will
* still be propagated to every potential receiver.
*
* @param timeout The maximum amount of time (in ms) to wait for events.
*
* @warning This method WILL BLOCK and therefore should NEVER been called
* from either a VLC thread, or Qt's main thread.
*
* @returns A value as defined in the EventWaitResult enum.
*/
MediaPlayer::EventWaitResult waitForEvent( unsigned long timeout = ULONG_MAX );
private:
static void callbacks( const libvlc_event_t* event, void* self );
void registerEvents();
void checkForWaitedEvents( const libvlc_event_t* event );
private:
libvlc_event_manager_t* p_em;
Media* m_media;
QWaitCondition m_waitCond;
QMutex m_mutex;
int m_eventReceived;
CheckEventCallback m_eventsCallback;
QList<int> m_eventsExpected;
QList<int> m_eventsCancel;
signals:
void snapshotTaken( const char* );
void timeChanged( qint64 );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment