Skip to content

Commit

Permalink
Add playback registration handling
Browse files Browse the repository at this point in the history
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
jyavenard committed Jul 15, 2012
1 parent ea944e6 commit ae61cb9
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 0 deletions.
70 changes: 70 additions & 0 deletions mythtv/libs/libmythbase/mythcorecontext.cpp
Expand Up @@ -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,
Expand Down Expand Up @@ -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: */
5 changes: 5 additions & 0 deletions mythtv/libs/libmythbase/mythcorecontext.h
Expand Up @@ -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(); }
Expand All @@ -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;
Expand Down

0 comments on commit ae61cb9

Please sign in to comment.