[telepathy-qt4/master] StreamedMediaChannel: Added Hold interface support.

Andre Moreira Magalhaes (andrunko) andre.magalhaes at collabora.co.uk
Wed Aug 12 07:29:37 PDT 2009


---
 TelepathyQt4/streamed-media-channel.cpp |  147 ++++++++++++++++++++++++++++++-
 TelepathyQt4/streamed-media-channel.h   |   11 +++
 2 files changed, 157 insertions(+), 1 deletions(-)

diff --git a/TelepathyQt4/streamed-media-channel.cpp b/TelepathyQt4/streamed-media-channel.cpp
index 8856353..bf3c073 100644
--- a/TelepathyQt4/streamed-media-channel.cpp
+++ b/TelepathyQt4/streamed-media-channel.cpp
@@ -436,6 +436,7 @@ struct StreamedMediaChannel::Private
     ~Private();
 
     static void introspectStreams(Private *self);
+    static void introspectHoldState(Private *self);
 
     // Public object
     StreamedMediaChannel *parent;
@@ -446,11 +447,16 @@ struct StreamedMediaChannel::Private
 
     QHash<uint, MediaStreamPtr> incompleteStreams;
     QHash<uint, MediaStreamPtr> streams;
+
+    LocalHoldState holdState;
+    LocalHoldStateReason holdStateReason;
 };
 
 StreamedMediaChannel::Private::Private(StreamedMediaChannel *parent)
     : parent(parent),
-      readinessHelper(parent->readinessHelper())
+      readinessHelper(parent->readinessHelper()),
+      holdState(LocalHoldStateUnheld),
+      holdStateReason(LocalHoldStateReasonNone)
 {
     ReadinessHelper::Introspectables introspectables;
 
@@ -462,6 +468,14 @@ StreamedMediaChannel::Private::Private(StreamedMediaChannel *parent)
         this);
     introspectables[FeatureStreams] = introspectableStreams;
 
+    ReadinessHelper::Introspectable introspectableHoldState(
+        QSet<uint>() << 0,                                                      // makesSenseForStatuses
+        Features() << Channel::FeatureCore,                                     // dependsOnFeatures (core)
+        QStringList(TELEPATHY_INTERFACE_CHANNEL_INTERFACE_HOLD),                // dependsOnInterfaces
+        (ReadinessHelper::IntrospectFunc) &Private::introspectHoldState,
+        this);
+    introspectables[FeatureHoldState] = introspectableHoldState;
+
     readinessHelper->addIntrospectables(introspectables);
 }
 
@@ -498,6 +512,24 @@ void StreamedMediaChannel::Private::introspectStreams(StreamedMediaChannel::Priv
             SLOT(gotStreams(QDBusPendingCallWatcher *)));
 }
 
+void StreamedMediaChannel::Private::introspectHoldState(StreamedMediaChannel::Private *self)
+{
+    StreamedMediaChannel *parent = self->parent;
+    Client::ChannelInterfaceHoldInterface *holdInterface =
+        parent->holdInterface();
+
+    parent->connect(holdInterface,
+            SIGNAL(HoldStateChanged(uint, uint)),
+            SLOT(onHoldStateChanged(uint, uint)));
+
+    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(
+            holdInterface->GetHoldState(), parent);
+    parent->connect(watcher,
+            SIGNAL(finished(QDBusPendingCallWatcher *)),
+            SLOT(gotHoldState(QDBusPendingCallWatcher *)));
+}
+
+
 /**
  * \class StreamedMediaChannel
  * \ingroup clientchannel
@@ -508,6 +540,7 @@ void StreamedMediaChannel::Private::introspectStreams(StreamedMediaChannel::Priv
  */
 
 const Feature StreamedMediaChannel::FeatureStreams = Feature(StreamedMediaChannel::staticMetaObject.className(), 0);
+const Feature StreamedMediaChannel::FeatureHoldState = Feature(StreamedMediaChannel::staticMetaObject.className(), 1);
 
 StreamedMediaChannelPtr StreamedMediaChannel::create(const ConnectionPtr &connection,
         const QString &objectPath, const QVariantMap &immutableProperties)
@@ -666,6 +699,87 @@ bool StreamedMediaChannel::handlerStreamingRequired() const
             TELEPATHY_INTERFACE_CHANNEL_INTERFACE_MEDIA_SIGNALLING);
 }
 
+/**
+ * Return the channel hold state.
+ *
+ * This method requires StreamedMediaChannel::FeatureHoldState to be enabled.
+ *
+ * \return The channel hold state.
+ * \sa requestHold()
+ */
+LocalHoldState StreamedMediaChannel::holdState() const
+{
+    if (!isReady(FeatureHoldState)) {
+        warning() << "StreamedMediaChannel::holdState() used with FeatureHoldState not ready";
+    } else if (!interfaces().contains(TELEPATHY_INTERFACE_CHANNEL_INTERFACE_HOLD)) {
+        warning() << "StreamedMediaChannel::holdStateReason() used with no hold interface";
+    }
+
+    return mPriv->holdState;
+}
+
+/**
+ * Return the channel hold state reason.
+ *
+ * This method requires StreamedMediaChannel::FeatureHoldState to be enabled.
+ *
+ * \return The channel hold state reason.
+ * \sa requestHold()
+ */
+LocalHoldStateReason StreamedMediaChannel::holdStateReason() const
+{
+    if (!isReady(FeatureHoldState)) {
+        warning() << "StreamedMediaChannel::holdStateReason() used with FeatureHoldState not ready";
+    } else if (!interfaces().contains(TELEPATHY_INTERFACE_CHANNEL_INTERFACE_HOLD)) {
+        warning() << "StreamedMediaChannel::holdStateReason() used with no hold interface";
+    }
+
+    return mPriv->holdStateReason;
+}
+
+/**
+ * Request that the channel be put on hold (be instructed not to send any media
+ * streams to you) or be taken off hold.
+ *
+ * If the connection manager can immediately tell that the requested state
+ * change could not possibly succeed, the resulting PendingOperation SHOULD fail
+ * with error code %TELEPATHY_ERROR_NOT_AVAILABLE.
+ * If the requested state is the same as the current state, the resulting
+ * PendingOperation SHOULD finish successfully.
+ *
+ * Otherwise, this method SHOULD immediately set the hold state to
+ * Tp::LocalHoldStatePendingHold or Tp::LocalHoldStatePendingUnhold (as
+ * appropriate), emitting holdStateChanged() if this is a change, and the
+ * resulting PendingOperation should finish successfully.
+ *
+ * The eventual success or failure of the request is indicated by a subsequent
+ * holdStateChanged() signal, changing the hold state to Tp::LocalHoldStateHeld
+ * or Tp::LocalHoldStateUnheld.
+ *
+ * If the channel has multiple streams, and the connection manager succeeds in
+ * changing the hold state of one stream but fails to change the hold state of
+ * another, it SHOULD attempt to revert all streams to their previous hold
+ * states.
+ *
+ * If the channel does not support the %TELEPATHY_INTERFACE_CHANNEL_INTERFACE_HOLD
+ * interface, the resulting PendingOperation will fail with error code
+ * %TELEPATHY_ERROR_NOT_IMPLEMENTED.
+ *
+ * \param hold A boolean indicating whether or not the channel should be on hold 
+ * \return A %PendingOperation, which will emit PendingOperation::finished
+ *         when the request finishes.
+ * \sa holdState(), holdStateReason()
+ */
+PendingOperation *StreamedMediaChannel::requestHold(bool hold)
+{
+    if (!interfaces().contains(TELEPATHY_INTERFACE_CHANNEL_INTERFACE_HOLD)) {
+        warning() << "StreamedMediaChannel::requestHold() used with no hold interface";
+        return new PendingFailure(this, TELEPATHY_ERROR_NOT_IMPLEMENTED,
+                "StreamedMediaChannel does not support hold interface");
+    }
+    return new PendingVoidMethodCall(this, holdInterface()->RequestHold(hold));
+}
+
 void StreamedMediaChannel::gotStreams(QDBusPendingCallWatcher *watcher)
 {
     QDBusPendingReply<MediaStreamInfoList> reply = *watcher;
@@ -858,6 +972,37 @@ void StreamedMediaChannel::onStreamError(uint streamId,
     }
 }
 
+void StreamedMediaChannel::gotHoldState(QDBusPendingCallWatcher *watcher)
+{
+    QDBusPendingReply<uint, uint> reply = *watcher;
+    if (reply.isError()) {
+        warning().nospace() << "StreamedMedia::Hold::GetHoldState()"
+            " failed with " << reply.error().name() << ": " <<
+            reply.error().message();
+
+        // should we fail here or just ignore?
+        mPriv->readinessHelper->setIntrospectCompleted(FeatureHoldState,
+                false, reply.error());
+        return;
+    }
+
+    debug() << "Got reply to StreamedMedia::Hold::GetHoldState()";
+    onHoldStateChanged(reply.argumentAt<0>(), reply.argumentAt<1>());
+    watcher->deleteLater();
+}
+
+void StreamedMediaChannel::onHoldStateChanged(uint holdState, uint holdStateReason)
+{
+    mPriv->holdState = static_cast<LocalHoldState>(holdState);
+    mPriv->holdStateReason = static_cast<LocalHoldStateReason>(holdStateReason);
+
+    if (!isReady(FeatureHoldState)) {
+        mPriv->readinessHelper->setIntrospectCompleted(FeatureHoldState, true);
+    } else {
+        emit holdStateChanged(mPriv->holdState, mPriv->holdStateReason);
+    }
+}
+
 void StreamedMediaChannel::addStream(const MediaStreamPtr &stream)
 {
     mPriv->incompleteStreams.insert(stream->id(), stream);
diff --git a/TelepathyQt4/streamed-media-channel.h b/TelepathyQt4/streamed-media-channel.h
index 7b369c7..3530dee 100644
--- a/TelepathyQt4/streamed-media-channel.h
+++ b/TelepathyQt4/streamed-media-channel.h
@@ -126,6 +126,7 @@ class StreamedMediaChannel : public Channel
 
 public:
     static const Feature FeatureStreams;
+    static const Feature FeatureHoldState;
 
     static StreamedMediaChannelPtr create(const ConnectionPtr &connection,
             const QString &objectPath, const QVariantMap &immutableProperties);
@@ -152,6 +153,10 @@ public:
 
     bool handlerStreamingRequired() const;
 
+    LocalHoldState holdState() const;
+    LocalHoldStateReason holdStateReason() const;
+    PendingOperation *requestHold(bool hold);
+
 Q_SIGNALS:
     void streamAdded(const Tp::MediaStreamPtr &stream);
     void streamRemoved(const Tp::MediaStreamPtr &stream);
@@ -164,6 +169,9 @@ Q_SIGNALS:
             Tp::MediaStreamError errorCode,
             const QString &errorMessage);
 
+    void holdStateChanged(Tp::LocalHoldState state,
+            Tp::LocalHoldStateReason reason);
+
 protected:
     StreamedMediaChannel(const ConnectionPtr &connection,
             const QString &objectPath, const QVariantMap &immutableProperties);
@@ -177,6 +185,9 @@ private Q_SLOTS:
     void onStreamStateChanged(uint, uint);
     void onStreamError(uint, uint, const QString &);
 
+    void gotHoldState(QDBusPendingCallWatcher *);
+    void onHoldStateChanged(uint, uint);
+
 private:
     friend class PendingMediaStreams;
 
-- 
1.5.6.5




More information about the telepathy-commits mailing list