[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    playground/network/kcall
From:       George Kiagiadakis <gkiagiad () csd ! uoc ! gr>
Date:       2009-07-09 19:05:09
Message-ID: 1247166309.293842.6373.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 993939 by gkiagia:

Cleanup the MediaHandler api and implementation.
- Allocate resources on request and not at construction time.
- Use signals to inform the GUI about changes.
- Remove the useless AbstractMediaHandler::State.

 M  +1 -14     kcall_handler/abstractmediahandler.cpp  
 M  +5 -31     kcall_handler/abstractmediahandler.h  
 M  +32 -7     kcall_handler/callwindow.cpp  
 M  +5 -0      kcall_handler/callwindow.h  
 M  +82 -104   kcall_handler/farsight/mediahandler.cpp  
 M  +3 -4      kcall_handler/farsight/mediahandler.h  
 M  +2 -0      libkgstdevices/devicefactory.cpp  


--- trunk/playground/network/kcall/kcall_handler/abstractmediahandler.cpp #993938:993939
@@ -18,7 +18,7 @@
 #include "farsight/mediahandler.h"
 
 AbstractMediaHandler::AbstractMediaHandler(QObject *parent)
-    : QObject(parent), m_status(Disconnected)
+    : QObject(parent)
 {
 }
 
@@ -29,17 +29,4 @@
     return new Farsight::MediaHandler(channel, parent);
 }
 
-AbstractMediaHandler::Status AbstractMediaHandler::status() const
-{
-    return m_status;
-}
-
-void AbstractMediaHandler::setStatus(AbstractMediaHandler::Status s)
-{
-    if ( s != m_status ) {
-        m_status = s;
-        emit statusChanged(s);
-    }
-}
-
 #include "abstractmediahandler.moc"
--- trunk/playground/network/kcall/kcall_handler/abstractmediahandler.h #993938:993939
@@ -24,45 +24,19 @@
 class AbstractMediaHandler : public QObject
 {
     Q_OBJECT
-    Q_ENUMS(Capability)
-    Q_FLAGS(Capabilities)
 public:
-    enum Capability {
-        None = 0x0,
-        SendAudio = 0x1,
-        ReceiveAudio = 0x2,
-        SendVideo = 0x4,
-        ReceiveVideo = 0x8
-    };
-    Q_DECLARE_FLAGS(Capabilities, Capability);
-
-    enum Status {
-        Disconnected,
-        Connecting,
-        Connected
-    };
-
     static AbstractMediaHandler *create(const Tp::StreamedMediaChannelPtr & channel,
                                         QObject *parent = 0);
 
-    Status status() const;
-    virtual Capabilities capabilities() const = 0;
-    virtual VolumeControlInterface *inputVolumeControl() const = 0;
-    virtual VolumeControlInterface *outputVolumeControl() const = 0;
-
 Q_SIGNALS:
-    void statusChanged(AbstractMediaHandler::Status newStatus);
+    void audioInputDeviceCreated(VolumeControlInterface *inputVolumeControl);
+    void audioInputDeviceDestroyed();
 
+    void audioOutputDeviceCreated(VolumeControlInterface *outputVolumeControl);
+    void audioOutputDeviceDestroyed();
+
 protected:
     AbstractMediaHandler(QObject *parent = 0);
-
-protected Q_SLOTS:
-    void setStatus(AbstractMediaHandler::Status s);
-
-private:
-    Status m_status;
 };
 
-Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMediaHandler::Capabilities)
-
 #endif
--- trunk/playground/network/kcall/kcall_handler/callwindow.cpp #993938:993939
@@ -108,8 +108,9 @@
 {
     d->hangupAction->setEnabled(false);
     d->ui.participantsDock->setEnabled(false);
-    d->ui.tabWidget->setTabEnabled(VolumeTabIndex, false);
-    d->ui.volumeTab->setEnabled(false);
+    //d->ui.tabWidget->setTabEnabled(VolumeTabIndex, false);
+    d->ui.microphoneGroupBox->setEnabled(false);
+    d->ui.speakersGroupBox->setEnabled(false);
     d->ui.tabWidget->setTabEnabled(VideoControlsTabIndex, false);
     d->ui.videoControlsTab->setEnabled(false);
     d->ui.tabWidget->setTabEnabled(DialpadTabIndex, false);
@@ -162,13 +163,37 @@
 
 void CallWindow::onMediaHandlerCreated(AbstractMediaHandler *handler)
 {
-    //FIXME this signal doesn't imply that we have an audio stream
-    d->ui.tabWidget->setTabEnabled(VolumeTabIndex, true);
-    d->ui.volumeTab->setEnabled(true);
-    d->ui.inputVolumeWidget->setVolumeControl(handler->inputVolumeControl());
-    d->ui.outputVolumeWidget->setVolumeControl(handler->outputVolumeControl());
+    connect(handler, SIGNAL(audioInputDeviceCreated(VolumeControlInterface*)),
+            SLOT(onAudioInputDeviceCreated(VolumeControlInterface*)));
+    connect(handler, SIGNAL(audioInputDeviceDestroyed()), SLOT(onAudioInputDeviceDestroyed()));
+
+    connect(handler, SIGNAL(audioOutputDeviceCreated(VolumeControlInterface*)),
+            SLOT(onAudioOutputDeviceCreated(VolumeControlInterface*)));
+    connect(handler, SIGNAL(audioOutputDeviceDestroyed()), SLOT(onAudioOutputDeviceDestroyed()));
 }
 
+void CallWindow::onAudioInputDeviceCreated(VolumeControlInterface *control)
+{
+    d->ui.microphoneGroupBox->setEnabled(true);
+    d->ui.inputVolumeWidget->setVolumeControl(control);
+}
+
+void CallWindow::onAudioInputDeviceDestroyed()
+{
+    d->ui.microphoneGroupBox->setEnabled(false);
+}
+
+void CallWindow::onAudioOutputDeviceCreated(VolumeControlInterface *control)
+{
+    d->ui.speakersGroupBox->setEnabled(true);
+    d->ui.outputVolumeWidget->setVolumeControl(control);
+}
+
+void CallWindow::onAudioOutputDeviceDestroyed()
+{
+    d->ui.speakersGroupBox->setEnabled(false);
+}
+
 void CallWindow::onGroupMembersModelCreated(GroupMembersModel *model)
 {
     d->ui.participantsDock->setEnabled(true);
--- trunk/playground/network/kcall/kcall_handler/callwindow.h #993938:993939
@@ -19,6 +19,7 @@
 
 #include "channelhandler.h"
 #include <KXmlGuiWindow>
+class VolumeControlInterface;
 
 class CallWindow : public KXmlGuiWindow
 {
@@ -36,6 +37,10 @@
     void setState(ChannelHandler::State state);
     void setStatus(const QString & msg);
     void onMediaHandlerCreated(AbstractMediaHandler *handler);
+    void onAudioInputDeviceCreated(VolumeControlInterface *control);
+    void onAudioInputDeviceDestroyed();
+    void onAudioOutputDeviceCreated(VolumeControlInterface *control);
+    void onAudioOutputDeviceDestroyed();
     void onGroupMembersModelCreated(GroupMembersModel *model);
     void onDtmfHandlerCreated(DtmfHandler *handler);
     void onCallDurationTimerTimeout();
--- trunk/playground/network/kcall/kcall_handler/farsight/mediahandler.cpp #993938:993939
@@ -40,9 +40,8 @@
     static void onSrcPadAdded(TfStream *stream, GstPad *src, FsCodec *codec, MediaHandler *self);
     static gboolean onRequestResource(TfStream *stream, guint direction, MediaHandler *self);
 
-    GstPad *audioSinkPad();
+    GstPad *newAudioSinkPad();
 
-    AbstractMediaHandler::Capabilities caps;
     Tp::StreamedMediaChannelPtr channel;
     TfChannel *tfChannel;
     GstElement *pipeline;
@@ -52,31 +51,9 @@
     guint busWatchSrc;
 };
 
-GstPad *MediaHandler::Private::audioSinkPad()
-{
-    if ( !liveadder ) {
-        if ( !(liveadder = gst_element_factory_make("liveadder", NULL)) ) {
-            kDebug() << "liveadder not available. Attempting to use plain adder";
-            if ( !(liveadder = gst_element_factory_make("adder", NULL)) ) {
-                kFatal() << "Failed to create an adder gstreamer element. Please install "
-                            "either the \"adder\" or the \"liveadder\" gstreamer plugin.";
-            }
-        }
-
-        gst_bin_add(GST_BIN(pipeline), liveadder);
-        gst_bin_add(GST_BIN(pipeline), deviceFactory->audioOutputDevice()->bin());
-        gst_element_link(liveadder, deviceFactory->audioOutputDevice()->bin());
-
-        gst_element_set_state(liveadder, GST_STATE_PLAYING);
-        gst_element_set_state(deviceFactory->audioOutputDevice()->bin(), GST_STATE_PLAYING);
-    }
-    return gst_element_get_request_pad(liveadder, "sink%d");
-}
-
 MediaHandler::MediaHandler(const Tp::StreamedMediaChannelPtr & channel, QObject *parent)
     : AbstractMediaHandler(parent), d(new Private)
 {
-    d->caps = None;
     d->channel = channel;
     d->tfChannel = NULL;
     d->pipeline = NULL;
@@ -85,6 +62,7 @@
     d->bus = NULL;
     d->busWatchSrc = 0;
 
+    qRegisterMetaType<VolumeControlInterface*>("VolumeControlInterface*");
     initialize();
 }
 
@@ -113,21 +91,6 @@
     delete d;
 }
 
-AbstractMediaHandler::Capabilities MediaHandler::capabilities() const
-{
-    return d->caps;
-}
-
-VolumeControlInterface *MediaHandler::inputVolumeControl() const
-{
-    return d->deviceFactory->audioInputDevice();
-}
-
-VolumeControlInterface *MediaHandler::outputVolumeControl() const
-{
-    return d->deviceFactory->audioOutputDevice();
-}
-
 void MediaHandler::initialize()
 {
     static bool gInitDone = false;
@@ -161,49 +124,61 @@
 
     const KConfigGroup deviceSettings = KGlobal::config()->group("Gstreamer Devices");
     d->deviceFactory = new KGstDevices::DeviceFactory(deviceSettings);
-
-    if ( d->deviceFactory->createAudioInputDevice() ) {
-        d->caps |= SendAudio;
-    }
-
-    if ( d->deviceFactory->createAudioOutputDevice() ) {
-        gst_element_link(d->liveadder, d->deviceFactory->audioOutputDevice()->bin());
-        d->caps |= ReceiveAudio;
-    }
-
-    setStatus(Connecting);
 }
 
 void MediaHandler::stop()
 {
-    if (status() == Disconnected) {
-        return;
-    }
-
     if (d->bus) {
         if (d->busWatchSrc != 0) {
             g_source_remove(d->busWatchSrc);
         }
     }
 
-    if ( d->liveadder ) {
-        gst_element_set_state(d->liveadder, GST_STATE_NULL);
+    if (d->pipeline) {
+        gst_element_set_state(d->pipeline, GST_STATE_NULL);
     }
 
-    if ( d->deviceFactory->audioInputDevice() ) {
-        gst_element_set_state(d->deviceFactory->audioInputDevice()->bin(), GST_STATE_NULL);
-    }
+    QMetaObject::invokeMethod(this, "audioInputDeviceDestroyed", Qt::QueuedConnection);
+    QMetaObject::invokeMethod(this, "audioOutputDeviceDestroyed", Qt::QueuedConnection);
+}
 
-    if ( d->deviceFactory->audioOutputDevice() ) {
-        gst_element_set_state(d->deviceFactory->audioOutputDevice()->bin(), GST_STATE_NULL);
+void MediaHandler::onAudioSrcPadAdded(GstPad *srcPad)
+{
+    if ( !d->deviceFactory->audioOutputDevice() ) {
+        if ( !d->deviceFactory->createAudioOutputDevice() ) {
+            kError() << "Could not create audio output device"; //TODO use error log
+            return;
+        }
+        gst_bin_add(GST_BIN(d->pipeline), d->deviceFactory->audioOutputDevice()->bin());
+        gst_element_set_state(d->deviceFactory->audioOutputDevice()->bin(), GST_STATE_PLAYING);
     }
 
-    if (d->pipeline) {
-        gst_element_set_state(d->pipeline, GST_STATE_NULL);
+    GstPad *sinkPad = d->newAudioSinkPad();
+    Q_ASSERT(sinkPad);
+    gst_pad_link(srcPad, sinkPad);
+
+    QMetaObject::invokeMethod(this, "audioOutputDeviceCreated", Qt::QueuedConnection,
+                              Q_ARG(VolumeControlInterface*, d->deviceFactory->audioOutputDevice()));
+}
+
+void MediaHandler::onAudioSinkPadAdded(GstPad *sinkPad)
+{
+    if ( !d->deviceFactory->audioInputDevice() ) {
+        if ( !d->deviceFactory->createAudioInputDevice() ) {
+            kError() << "Could not create audio input device"; //TODO use error log
+            return;
+        }
+        gst_bin_add(GST_BIN(d->pipeline), d->deviceFactory->audioInputDevice()->bin());
+        gst_element_set_state(d->deviceFactory->audioInputDevice()->bin(), GST_STATE_PLAYING);
     }
 
-    d->caps = None;
-    setStatus(Disconnected);
+    GstPad *srcPad = gst_element_get_static_pad(d->deviceFactory->audioInputDevice()->bin(), "src");
+    Q_ASSERT(srcPad);
+    gst_pad_link(srcPad, sinkPad);
+    gst_object_unref(srcPad);
+
+    QMetaObject::invokeMethod(this, "audioInputDeviceCreated", Qt::QueuedConnection,
+                              Q_ARG(VolumeControlInterface*, d->deviceFactory->audioInputDevice()));
 }
 
 gboolean MediaHandler::Private::busWatch(GstBus *bus, GstMessage *message, MediaHandler *self)
@@ -236,34 +211,10 @@
                                             MediaHandler *self)
 {
     Q_UNUSED(tfChannel);
-    guint media_type;
-    GstPad *sink;
-    GstElement *element = NULL;
-
-    g_object_get(stream, "media-type", &media_type, "sink-pad", &sink, NULL);
-
-    switch (media_type) {
-    case Tp::MediaStreamTypeAudio:
-        element = self->d->deviceFactory->audioInputDevice()->bin();
-        break;
-    case Tp::MediaStreamTypeVideo:
-        kWarning() << "Handling video is not supported yet.";
-        return;
-    default:
-        Q_ASSERT(false);
-    }
-
     g_signal_connect(stream, "src-pad-added",
                      G_CALLBACK(&MediaHandler::Private::onSrcPadAdded), self);
     g_signal_connect(stream, "request-resource",
                      G_CALLBACK(&MediaHandler::Private::onRequestResource), self);
-
-    GstPad *pad = gst_element_get_static_pad(element, "src");
-    gst_bin_add(GST_BIN(self->d->pipeline), element);
-    gst_pad_link(pad, sink);
-    gst_object_unref(sink);
-    gst_object_unref(pad);
-    gst_element_set_state(element, GST_STATE_PLAYING);
 }
 
 void MediaHandler::Private::onSrcPadAdded(TfStream *stream, GstPad *src,
@@ -271,14 +222,11 @@
 {
     Q_UNUSED(codec);
     guint media_type;
-    GstPad *pad = NULL;
-
     g_object_get(stream, "media-type", &media_type, NULL);
 
     switch (media_type) {
     case Tp::MediaStreamTypeAudio:
-        pad = self->d->audioSinkPad();
-        Q_ASSERT(pad);
+        self->onAudioSrcPadAdded(src);
         break;
     case Tp::MediaStreamTypeVideo:
         kWarning() << "Handling video is not supported yet.";
@@ -286,9 +234,6 @@
     default:
         Q_ASSERT(false);
     }
-
-    gst_pad_link(src, pad);
-    self->setStatus(Connected);
 }
 
 gboolean MediaHandler::Private::onRequestResource(TfStream *stream, guint direction,
@@ -299,23 +244,56 @@
 
     switch (media_type) {
     case Tp::MediaStreamTypeAudio:
-        if ( (direction & Tp::MediaStreamDirectionSend)
-              && !(self->d->caps & SendAudio) ) {
-            return FALSE;
+
+        switch(direction) {
+        case Tp::MediaStreamDirectionSend:
+            GstPad *sink;
+            g_object_get(stream, "sink-pad", &sink, NULL);
+            self->onAudioSinkPadAdded(sink);
+            gst_object_unref(sink);
+            return (self->d->deviceFactory->audioInputDevice() != NULL);
+
+        case Tp::MediaStreamDirectionReceive:
+            /* The tp-farsight api is broken, so this signal will come after
+               the src-pad-added signal, which will allocate the resource instead.
+               Here we just return whether src-pad-added could allocate the device or not. */
+            return (self->d->deviceFactory->audioOutputDevice() != NULL);
+
+        default:
+            Q_ASSERT(false);
         }
-        if ( (direction & Tp::MediaStreamDirectionReceive)
-              && !(self->d->caps & ReceiveAudio) ) {
-            return FALSE;
-        }
-        return TRUE;
+        break;
+
     case Tp::MediaStreamTypeVideo:
         return FALSE;
+
     default:
         Q_ASSERT(false);
     }
     return FALSE; //warnings--
 }
 
+GstPad *MediaHandler::Private::newAudioSinkPad()
+{
+    if ( !liveadder ) {
+        if ( !(liveadder = gst_element_factory_make("liveadder", NULL)) ) {
+            kDebug() << "liveadder not available. Attempting to use plain adder";
+            if ( !(liveadder = gst_element_factory_make("adder", NULL)) ) {
+                kFatal() << "Failed to create an adder gstreamer element. Please install "
+                            "either the \"adder\" or the \"liveadder\" gstreamer plugin.";
+            }
+        }
+
+        gst_bin_add(GST_BIN(pipeline), liveadder);
+        gst_bin_add(GST_BIN(pipeline), deviceFactory->audioOutputDevice()->bin());
+        gst_element_link(liveadder, deviceFactory->audioOutputDevice()->bin());
+
+        gst_element_set_state(liveadder, GST_STATE_PLAYING);
+        gst_element_set_state(deviceFactory->audioOutputDevice()->bin(), GST_STATE_PLAYING);
+    }
+    return gst_element_get_request_pad(liveadder, "sink%d");
+}
+
 } //namespace Farsight
 
 #include "mediahandler.moc"
--- trunk/playground/network/kcall/kcall_handler/farsight/mediahandler.h #993938:993939
@@ -18,6 +18,7 @@
 #define _FARSIGHT_MEDIAHANDLER_H
 
 #include "../abstractmediahandler.h"
+typedef struct _GstPad GstPad;
 
 namespace Farsight {
 
@@ -28,13 +29,11 @@
     explicit MediaHandler(const Tp::StreamedMediaChannelPtr & channel, QObject *parent = 0);
     virtual ~MediaHandler();
 
-    virtual Capabilities capabilities() const;
-    virtual VolumeControlInterface *inputVolumeControl() const;
-    virtual VolumeControlInterface *outputVolumeControl() const;
-
 private:
     void initialize();
     void stop();
+    void onAudioSrcPadAdded(GstPad *srcPad);
+    void onAudioSinkPadAdded(GstPad *sinkPad);
 
     struct Private;
     friend class Private;
--- trunk/playground/network/kcall/libkgstdevices/devicefactory.cpp #993938:993939
@@ -39,6 +39,8 @@
     : d(new Private)
 {
     d->config = group;
+    d->audioInputDevice = NULL;
+    d->audioOutputDevice = NULL;
 }
 
 DeviceFactory::~DeviceFactory()
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic