[Telepathy-commits] [telepathy-qt4/master] StreamedMediaChannel: Continue implementation (added FeatureStreams support).

Andre Moreira Magalhaes (andrunko) andre.magalhaes at collabora.co.uk
Tue Mar 10 22:44:26 PDT 2009


---
 TelepathyQt4/Client/streamed-media-channel.cpp |  297 +++++++++++++++++++++++-
 TelepathyQt4/Client/streamed-media-channel.h   |   54 +++--
 2 files changed, 325 insertions(+), 26 deletions(-)

diff --git a/TelepathyQt4/Client/streamed-media-channel.cpp b/TelepathyQt4/Client/streamed-media-channel.cpp
index 263b63c..90108ee 100644
--- a/TelepathyQt4/Client/streamed-media-channel.cpp
+++ b/TelepathyQt4/Client/streamed-media-channel.cpp
@@ -21,27 +21,198 @@
 #include <TelepathyQt4/Client/StreamedMediaChannel>
 
 #include "TelepathyQt4/Client/_gen/streamed-media-channel.moc.hpp"
+
 #include "TelepathyQt4/debug-internal.h"
 
+#include <TelepathyQt4/Client/Connection>
+#include <TelepathyQt4/Client/ContactManager>
+#include <TelepathyQt4/Client/PendingVoidMethodCall>
+
+#include <QHash>
+
 namespace Telepathy
 {
 namespace Client
 {
 
+struct MediaStream::Private
+{
+    Private(StreamedMediaChannel *channel, uint id,
+            uint contactHandle, MediaStreamType type,
+            MediaStreamState state, MediaStreamDirection direction,
+            MediaStreamPendingSend pendingSend)
+        : id(id), contactHandle(contactHandle),
+          type(type), state(state), direction(direction),
+          pendingSend(pendingSend)
+    {
+    }
+
+    StreamedMediaChannel *channel;
+    uint id;
+    uint contactHandle;
+    MediaStreamType type;
+    MediaStreamState state;
+    MediaStreamDirection direction;
+    MediaStreamPendingSend pendingSend;
+};
+
+MediaStream::MediaStream(StreamedMediaChannel *channel, uint id,
+        uint contactHandle, MediaStreamType type,
+        MediaStreamState state, MediaStreamDirection direction,
+        MediaStreamPendingSend pendingSend)
+    : QObject(),
+      mPriv(new Private(channel, id, contactHandle, type,
+                  state, direction, pendingSend))
+{
+}
+
+MediaStream::~MediaStream()
+{
+    delete mPriv;
+}
+
+StreamedMediaChannel *MediaStream::channel() const
+{
+    return mPriv->channel;
+}
+
+uint MediaStream::id() const
+{
+    return mPriv->id;
+}
+
+QSharedPointer<Contact> MediaStream::contact() const
+{
+    ContactManager *contactManager = mPriv->channel->connection()->contactManager();
+    return contactManager->lookupContactByHandle(mPriv->contactHandle);
+}
+
+Telepathy::MediaStreamState MediaStream::state() const
+{
+    return mPriv->state;
+}
+
+Telepathy::MediaStreamType MediaStream::type() const
+{
+    return mPriv->type;
+}
+
+bool MediaStream::sending() const
+{
+    return (mPriv->direction & Telepathy::MediaStreamDirectionSend ||
+            mPriv->direction & Telepathy::MediaStreamDirectionBidirectional);
+}
+
+bool MediaStream::receiving() const
+{
+    return (mPriv->direction & Telepathy::MediaStreamDirectionReceive ||
+            mPriv->direction & Telepathy::MediaStreamDirectionBidirectional);
+}
+
+bool MediaStream::localSendingRequested() const
+{
+    return mPriv->pendingSend & MediaStreamPendingLocalSend;
+}
+
+bool MediaStream::remoteSendingRequested() const
+{
+    return mPriv->pendingSend & MediaStreamPendingRemoteSend;
+}
+
+Telepathy::MediaStreamDirection MediaStream::direction() const
+{
+    return mPriv->direction;
+}
+
+Telepathy::MediaStreamPendingSend MediaStream::pendingSend() const
+{
+    return mPriv->pendingSend;
+}
+
+void MediaStream::setDirection(Telepathy::MediaStreamDirection direction,
+        Telepathy::MediaStreamPendingSend pendingSend)
+{
+    mPriv->direction = direction;
+    mPriv->pendingSend = pendingSend;
+    emit directionChanged(direction, pendingSend);
+}
+
+void MediaStream::setState(Telepathy::MediaStreamState state)
+{
+    mPriv->state = state;
+    emit stateChanged(state);
+}
+
+
 struct StreamedMediaChannel::Private
 {
-    inline Private();
-    inline ~Private();
+    Private(StreamedMediaChannel *parent);
+    ~Private();
+
+    static void introspectStreams(Private *self);
+
+    // Public object
+    StreamedMediaChannel *parent;
+
+    ReadinessHelper *readinessHelper;
+
+    // Introspection
+    bool initialStreamsReceived;
+
+    QHash<uint, QSharedPointer<MediaStream> > streams;
 };
 
-StreamedMediaChannel::Private::Private()
+StreamedMediaChannel::Private::Private(StreamedMediaChannel *parent)
+    : parent(parent),
+      readinessHelper(parent->readinessHelper()),
+      initialStreamsReceived(false)
 {
+    ReadinessHelper::Introspectables introspectables;
+
+    ReadinessHelper::Introspectable introspectableStreams(
+        QSet<uint>() << 0,                                                      // makesSenseForStatuses
+        Features() << Channel::FeatureCore,                                     // dependsOnFeatures (core)
+        QStringList(),                                                          // dependsOnInterfaces
+        (ReadinessHelper::IntrospectFunc) &Private::introspectStreams,
+        this);
+    introspectables[FeatureStreams] = introspectableStreams;
+
+    readinessHelper->addIntrospectables(introspectables);
 }
 
 StreamedMediaChannel::Private::~Private()
 {
 }
 
+void StreamedMediaChannel::Private::introspectStreams(StreamedMediaChannel::Private *self)
+{
+    StreamedMediaChannel *parent = self->parent;
+    ChannelTypeStreamedMediaInterface *streamedMediaInterface =
+        parent->streamedMediaInterface();
+
+    parent->connect(streamedMediaInterface,
+            SIGNAL(StreamAdded(uint, uint, uint)),
+            SLOT(onStreamAdded(uint, uint, uint)));
+    parent->connect(streamedMediaInterface,
+            SIGNAL(StreamRemoved(uint)),
+            SLOT(onStreamRemoved(uint)));
+    parent->connect(streamedMediaInterface,
+            SIGNAL(StreamDirectionChanged(uint, uint, uint)),
+            SLOT(onStreamDirectionChanged(uint, uint, uint)));
+    parent->connect(streamedMediaInterface,
+            SIGNAL(StreamStateChanged(uint, uint)),
+            SLOT(onStreamStateChanged(uint, uint)));
+    parent->connect(streamedMediaInterface,
+            SIGNAL(StreamError(uint, uint, const QString &)),
+            SLOT(onStreamError(uint, uint, const QString &)));
+
+    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(
+            streamedMediaInterface->ListStreams(), parent);
+    parent->connect(watcher,
+            SIGNAL(finished(QDBusPendingCallWatcher *)),
+            SLOT(gotStreams(QDBusPendingCallWatcher *)));
+}
+
 /**
  * \class StreamedMediaChannel
  * \ingroup clientchannel
@@ -54,6 +225,8 @@ StreamedMediaChannel::Private::~Private()
  * StreamedMedia interface. Until then, it's just a Channel.
  */
 
+const Feature StreamedMediaChannel::FeatureStreams = Feature(StreamedMediaChannel::staticMetaObject.className(), 0);
+
 /**
  * Creates a StreamedMediaChannel associated with the given object on the same
  * service as the given connection.
@@ -71,7 +244,7 @@ StreamedMediaChannel::StreamedMediaChannel(Connection *connection,
         const QVariantMap &immutableProperties,
         QObject *parent)
     : Channel(connection, objectPath, immutableProperties, parent),
-      mPriv(new Private())
+      mPriv(new Private(this))
 {
 }
 
@@ -83,6 +256,11 @@ StreamedMediaChannel::~StreamedMediaChannel()
     delete mPriv;
 }
 
+MediaStreams StreamedMediaChannel::streams() const
+{
+    return mPriv->streams.values();
+}
+
 bool StreamedMediaChannel::awaitingLocalAnswer() const
 {
     return groupSelfHandleIsLocalPending();
@@ -98,5 +276,116 @@ PendingOperation *StreamedMediaChannel::acceptCall()
     return groupAddSelfHandle();
 }
 
+void StreamedMediaChannel::gotStreams(QDBusPendingCallWatcher *watcher)
+{
+    QDBusPendingReply<QVariantMap> reply = *watcher;
+    if (reply.isError()) {
+        warning().nospace() << "StreamedMedia::ListStreams()"
+            " failed with " << reply.error().name() << ": " <<
+            reply.error().message();
+
+        mPriv->readinessHelper->setIntrospectCompleted(FeatureStreams,
+                false, reply.error());
+        return;
+    }
+
+    debug() << "Got reply to StreamedMedia::ListStreams()";
+    mPriv->initialStreamsReceived = true;
+
+    MediaStreamInfoList list = qdbus_cast<MediaStreamInfoList>(reply.value());
+    foreach (const MediaStreamInfo &streamInfo, list) {
+        mPriv->streams.insert(streamInfo.identifier,
+                QSharedPointer<MediaStream>(
+                    new MediaStream(this,
+                        streamInfo.identifier,
+                        streamInfo.contact,
+                        (Telepathy::MediaStreamType) streamInfo.type,
+                        (Telepathy::MediaStreamState) streamInfo.state,
+                        (Telepathy::MediaStreamDirection) streamInfo.direction,
+                        (Telepathy::MediaStreamPendingSend) streamInfo.pendingSendFlags)));
+    }
+
+    mPriv->readinessHelper->setIntrospectCompleted(FeatureStreams, true);
+
+    watcher->deleteLater();
+}
+
+void StreamedMediaChannel::onStreamAdded(uint streamId,
+        uint contactHandle, uint streamType)
+{
+    if (mPriv->initialStreamsReceived) {
+        Q_ASSERT(!mPriv->streams.contains(streamId));
+    }
+
+    QSharedPointer<MediaStream> stream = QSharedPointer<MediaStream>(
+            new MediaStream(this, streamId,
+                contactHandle,
+                (Telepathy::MediaStreamType) streamType,
+                // TODO where to get this info from?
+                Telepathy::MediaStreamStateDisconnected,
+                Telepathy::MediaStreamDirectionNone,
+                (Telepathy::MediaStreamPendingSend) 0));
+    mPriv->streams.insert(streamId, stream);
+
+    if (mPriv->initialStreamsReceived) {
+        emit streamAdded(stream);
+    }
+}
+
+void StreamedMediaChannel::onStreamRemoved(uint streamId)
+{
+    if (mPriv->initialStreamsReceived) {
+        Q_ASSERT(mPriv->streams.contains(streamId));
+    }
+
+    if (mPriv->streams.contains(streamId)) {
+        QSharedPointer<MediaStream> stream = mPriv->streams[streamId];
+        emit stream->removed();
+        stream.clear();
+    }
+}
+
+void StreamedMediaChannel::onStreamDirectionChanged(uint streamId,
+        uint streamDirection, uint pendingFlags)
+{
+    if (mPriv->initialStreamsReceived) {
+        Q_ASSERT(mPriv->streams.contains(streamId));
+    }
+
+    if (mPriv->streams.contains(streamId)) {
+        QSharedPointer<MediaStream> stream = mPriv->streams[streamId];
+        stream->setDirection(
+                (Telepathy::MediaStreamDirection) streamDirection,
+                (Telepathy::MediaStreamPendingSend) pendingFlags);
+    }
+}
+
+void StreamedMediaChannel::onStreamStateChanged(uint streamId,
+        uint streamState)
+{
+    if (mPriv->initialStreamsReceived) {
+        Q_ASSERT(mPriv->streams.contains(streamId));
+    }
+
+    if (mPriv->streams.contains(streamId)) {
+        QSharedPointer<MediaStream> stream = mPriv->streams[streamId];
+        stream->setState((Telepathy::MediaStreamState) streamState);
+    }
+}
+
+void StreamedMediaChannel::onStreamError(uint streamId,
+        uint errorCode, const QString &errorMessage)
+{
+    if (mPriv->initialStreamsReceived) {
+        Q_ASSERT(mPriv->streams.contains(streamId));
+    }
+
+    if (mPriv->streams.contains(streamId)) {
+        QSharedPointer<MediaStream> stream = mPriv->streams[streamId];
+        emit stream->error((Telepathy::MediaStreamError) errorCode,
+                errorMessage);
+    }
+}
+
 } // Telepathy::Client
 } // Telepathy
diff --git a/TelepathyQt4/Client/streamed-media-channel.h b/TelepathyQt4/Client/streamed-media-channel.h
index e15fcf9..ce4d19f 100644
--- a/TelepathyQt4/Client/streamed-media-channel.h
+++ b/TelepathyQt4/Client/streamed-media-channel.h
@@ -39,10 +39,11 @@ class MediaStream : public QObject
     Q_OBJECT
     Q_DISABLE_COPY(MediaStream)
 
-#if 0
 public:
+    ~MediaStream();
+
     StreamedMediaChannel *channel() const;
-    uint streamId() const;
+    uint id() const;
 
     QSharedPointer<Contact> contact() const;
     Telepathy::MediaStreamState state() const;
@@ -56,36 +57,38 @@ public:
     Telepathy::MediaStreamDirection direction() const;
     Telepathy::MediaStreamPendingSend pendingSend() const;
 
-public Q_SLOTS:
+#if 0
     PendingOperation *remove();
-    PendingOperation *requestStreamDirection(bool send, bool receive);
     PendingOperation *requestStreamDirection(
             Telepathy::MediaStreamDirection direction);
+#endif
 
 Q_SIGNALS:
-    void directionChanged(Telepathy::Client::MediaStream *stream,
-            bool sending, bool receiving, bool localSendingRequested,
-            bool remoteSendingRequested);
-    void error(Telepathy::Client::MediaStream *stream,
-            Telepathy::MediaStreamError code, const QString &debugMessage);
-    void stateChanged(Telepathy::Client::MediaStream *stream);
-    void removed(Telepathy::Client::MediaStream *stream);
+    void removed();
+    void directionChanged(Telepathy::MediaStreamDirection direction,
+            Telepathy::MediaStreamPendingSend pendingSend);
+    void stateChanged(Telepathy::MediaStreamState);
+    void error(Telepathy::MediaStreamError errorCode,
+            const QString &errorMessage);
 
 private:
     friend class StreamedMediaChannel;
 
-    MediaStream(StreamedMediaChannel *parent, uint streamId, uint
-            contactHandle, MediaStreamType type,
+    MediaStream(StreamedMediaChannel *channel, uint id,
+            uint contactHandle, MediaStreamType type,
             MediaStreamState state, MediaStreamDirection direction,
-            MediaStreamPendingSend pendingSend) const;
+            MediaStreamPendingSend pendingSend);
+
+    void setDirection(Telepathy::MediaStreamDirection direction,
+            Telepathy::MediaStreamPendingSend pendingSend);
+    void setState(Telepathy::MediaStreamState state);
 
     struct Private;
     friend struct Private;
     Private *mPriv;
-#endif
 };
 
-typedef QSet<QSharedPointer<MediaStream> > MediaStreams;
+typedef QList<QSharedPointer<MediaStream> > MediaStreams;
 
 class StreamedMediaChannel : public Channel
 {
@@ -93,24 +96,20 @@ class StreamedMediaChannel : public Channel
     Q_DISABLE_COPY(StreamedMediaChannel)
 
 public:
+    static const Feature FeatureStreams;
+
     StreamedMediaChannel(Connection *connection, const QString &objectPath,
             const QVariantMap &immutableProperties, QObject *parent = 0);
     ~StreamedMediaChannel();
 
-#if 0
-public:
     MediaStreams streams() const;
-#endif
 
-public:
     bool awaitingLocalAnswer() const;
     bool awaitingRemoteAnswer() const;
 
-public Q_SLOTS:
     PendingOperation *acceptCall();
 
 #if 0
-public Q_SLOTS:
     PendingOperation *removeStreams(MediaStreams streams);
     PendingOperation *removeStreams(QSet<uint> streams);
 
@@ -119,6 +118,17 @@ public Q_SLOTS:
             QList<Telepathy::MediaStreamType> types);
 #endif
 
+Q_SIGNALS:
+    void streamAdded(const QSharedPointer<MediaStream> &stream);
+
+private Q_SLOTS:
+    void gotStreams(QDBusPendingCallWatcher *);
+    void onStreamAdded(uint, uint, uint);
+    void onStreamRemoved(uint);
+    void onStreamDirectionChanged(uint, uint, uint);
+    void onStreamStateChanged(uint, uint);
+    void onStreamError(uint, uint, const QString &);
+
 private:
     struct Private;
     friend struct Private;
-- 
1.5.6.5




More information about the telepathy-commits mailing list