[vlmc-devel] VLCMediaPlayer: Add an helper to wait for an event.
Hugo Beauzée-Luyssen
git at videolan.org
Sun Sep 23 16:31:35 CEST 2012
vlmc | branch: master | Hugo Beauzée-Luyssen <beauze.h at gmail.com> | Sun Sep 23 00:00:29 2012 +0300| [c77512ce63b2c921025e56f82c3fbce9b04e44a1] | committer: Hugo Beauzée-Luyssen
VLCMediaPlayer: Add an helper to wait for an event.
> http://git.videolan.org/gitweb.cgi/vlmc.git/?a=commit;h=c77512ce63b2c921025e56f82c3fbce9b04e44a1
---
src/LibVLCpp/VLCMediaPlayer.cpp | 61 +++++++++++++++++++++++++++++++++++
src/LibVLCpp/VLCMediaPlayer.h | 68 +++++++++++++++++++++++++++++++++++++++
2 files changed, 129 insertions(+)
diff --git a/src/LibVLCpp/VLCMediaPlayer.cpp b/src/LibVLCpp/VLCMediaPlayer.cpp
index 3301044..d471868 100644
--- a/src/LibVLCpp/VLCMediaPlayer.cpp
+++ b/src/LibVLCpp/VLCMediaPlayer.cpp
@@ -93,9 +93,38 @@ 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 );
+}
diff --git a/src/LibVLCpp/VLCMediaPlayer.h b/src/LibVLCpp/VLCMediaPlayer.h
index fa48921..13d111f 100644
--- a/src/LibVLCpp/VLCMediaPlayer.h
+++ b/src/LibVLCpp/VLCMediaPlayer.h
@@ -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 );
More information about the Vlmc-devel
mailing list