Permalink
Browse files

Add playback registration handling

It is an unfortunate fact that you can only do one playback at a time within a frontend; usually because you can only open one audio session at a time.
This commit provides a mechanism for playback objects (such as TV, AirPlay, RAOP, MythMusic) to register themselves as a player and request playback; in which case all other registered player will be asked to close.
  • Loading branch information...
1 parent ea944e6 commit ae61cb983197112c51730063a4e57653f64dd78a @jyavenard jyavenard committed Jul 15, 2012
Showing with 75 additions and 0 deletions.
  1. +70 −0 mythtv/libs/libmythbase/mythcorecontext.cpp
  2. +5 −0 mythtv/libs/libmythbase/mythcorecontext.h
@@ -87,6 +87,9 @@ class MythCoreContextPrivate : public QObject
MythScheduler *m_scheduler;
bool m_blockingClient;
+
+ QMap<QObject *, QByteArray> m_playbackClients;
+ QMutex m_playbackLock;
};
MythCoreContextPrivate::MythCoreContextPrivate(MythCoreContext *lparent,
@@ -1364,4 +1367,71 @@ void MythCoreContext::WaitUntilSignals(const char *signal1, ...)
eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
}
+/**
+ * \fn void MythCoreContext::RegisterForPlayback(QObject *sender, const char *method)
+ * Register sender for TVPlaybackAboutToStart signal. Method will be called upon
+ * the signal being emitted.
+ * sender must call MythCoreContext::UnregisterForPlayback upon deletion
+ */
+void MythCoreContext::RegisterForPlayback(QObject *sender, const char *method)
+{
+ QMutexLocker lock(&d->m_playbackLock);
+
+ if (!d->m_playbackClients.contains(sender))
+ {
+ d->m_playbackClients.insert(sender, QByteArray(method));
+ connect(this, SIGNAL(TVPlaybackAboutToStart()),
+ sender, method,
+ Qt::BlockingQueuedConnection);
+ }
+}
+
+/**
+ * \fn void MythCoreContext::UnregisterForPlayback(QObject *sender)
+ * Unregister sender from being called when TVPlaybackAboutToStart signal
+ * is emitted
+ */
+void MythCoreContext::UnregisterForPlayback(QObject *sender)
+{
+ QMutexLocker lock(&d->m_playbackLock);
+
+ if (d->m_playbackClients.contains(sender))
+ {
+ QByteArray ba = d->m_playbackClients.value(sender);
+ const char *method = ba.constData();
+ disconnect(this, SIGNAL(TVPlaybackAboutToStart()),
+ sender, method);
+ d->m_playbackClients.remove(sender);
+ }
+}
+
+/**
+ * \fn void MythCoreContext::WantingPlayback(QObject *sender)
+ * All the objects that have registered using MythCoreContext::RegisterForPlayback
+ * but sender will be called. The objet's registered method will be called
+ * in a blocking fashion, each of them being called one after the other
+ */
+void MythCoreContext::WantingPlayback(QObject *sender)
+{
+ QMutexLocker lock(&d->m_playbackLock);
+ bool found = false;
+ QByteArray ba;
+ const char *method;
+
+ if (d->m_playbackClients.contains(sender))
+ {
+ found = true;
+ ba = d->m_playbackClients.value(sender);
+ method = ba.constData();
+ disconnect(this, SIGNAL(TVPlaybackAboutToStart()), sender, method);
+ }
+ emit TVPlaybackAboutToStart();
+ if (found)
+ {
+ connect(this, SIGNAL(TVPlaybackAboutToStart()),
+ sender, method,
+ Qt::BlockingQueuedConnection);
+ }
+}
+
/* vim: set expandtab tabstop=4 shiftwidth=4: */
@@ -169,6 +169,10 @@ class MBASE_PUBLIC MythCoreContext : public QObject, public MythObservable, publ
QString GetLanguageAndVariant(void);
void ResetLanguage(void);
+ void RegisterForPlayback(QObject *sender, const char *method);
+ void UnregisterForPlayback(QObject *sender);
+ void WantingPlayback(QObject *sender);
+
// signal related methods
void WaitUntilSignals(const char *signal1, ...);
void emitTVPlaybackStarted(void) { emit TVPlaybackStarted(); }
@@ -185,6 +189,7 @@ class MBASE_PUBLIC MythCoreContext : public QObject, public MythObservable, publ
void TVPlaybackPaused(void);
void TVPlaybackUnpaused(void);
void TVPlaybackAborted(void);
+ void TVPlaybackAboutToStart(void);
private:
MythCoreContextPrivate *d;

0 comments on commit ae61cb9

Please sign in to comment.