I have made the following changes intended for :
  CE:Apps / voicecall

Please review and accept or decline.
BOSS has already run some checks on this request.
See the "Messages from BOSS" section below.

https://build.pub.meego.com//request/show/6524

Thank You,
tswindell

[This message was auto-generated]

---

Request # 6524:

Messages from BOSS:

State: review at 2012-08-31T14:32:58 by bossbot

Reviews:
       accepted by bossbot : Prechecks succeeded.
       new for CE-maintainers : Please replace this text with a review and 
approve/reject the review (not the SR). BOSS will take care of the rest

Changes:
  submit: home:tswindell:CE:Apps / voicecall -> CE:Apps / voicecall
  
changes files:
--------------
--- voicecall.changes
+++ voicecall.changes
@@ -0,0 +1,3 @@
+* Fri Aug 31 2012 Tom Swindell <[email protected]> - 0.2.0
+- Updated sources to latest upstream version.
+

old:
----
  voicecall-0.1.4+git9.4b7b286.tar.gz

new:
----
  voicecall-0.2.0.tar.gz

spec files:
-----------
--- voicecall.spec
+++ voicecall.spec
@@ -1,26 +1,69 @@
 Name:       voicecall
 Summary:    Voice Call Suite
-Version:    0.1.4+git9.4b7b286
+Version:    0.2.0
 Release:    1
 Group:      Communications/Telephony and IM
 License:    Apache License, Version 2.0
 URL:        http://github.com/nemomobile/voicecall
 Source0:    %{name}-%{version}.tar.gz
 Requires:   tone-generator
+Requires:   voicecall-ui == %{version}-%{release}
 BuildRequires:  pkgconfig(QtOpenGL)
 BuildRequires:  pkgconfig(QtDeclarative)
 BuildRequires:  pkgconfig(QtMultimediaKit)
 BuildRequires:  pkgconfig(libresourceqt1)
 BuildRequires:  pkgconfig(libpulse-mainloop-glib)
 BuildRequires:  pkgconfig(ofono-qt)
-BuildRequires:  pkgconfig(TelepathyQt4)
-
-Obsoletes: meego-handset-dialer < 0.2.4
-Provides: meego-handset-dialer >= 0.2.4
+# May work with earlier version, but this is tested against in nemo.
+# Requires header includes to be under TelepathyQt/ rather than TelepathyQt4/
+BuildRequires:  pkgconfig(TelepathyQt4) >= 0.9.3
 
 %description
 Next Generation Dialer Application for Nemo Mobile
 
+%package libs
+Summary: Core voicecall libraries
+Group: Communications/Telephony and IM
+
+%description libs
+Core voicecall libraries
+
+%package devel
+Requires: voicecall-libs == %{version}-%{release}
+Summary: Voicecall development package
+Group: Communications/Telephony and IM
+
+%description devel
+Voicecall development libraries and headers
+
+%package core
+Requires: voicecall-libs == %{version}-%{release}
+Summary: Core voicecall service and libraries
+Group: Communications/Telephony and IM
+
+%description core
+Core voicecall service executable, core plugins and library
+
+%package plugin-ofono
+Requires: voicecall-core == %{version}-%{release}
+Summary: Voicecall ofono plugin provider
+Group: Communications/Telephony and IM
+
+%description plugin-ofono
+Voicecall manager plugin for using ofono to make and receive calls.
+
+%package ui-reference
+Provides: voicecall > 0.1.5
+Obsoletes: voicecall <= 0.1.5
+Provides: meego-handset-dialer >= 0.2.4
+Obsoletes: meego-handset-dialer < 0.2.4
+Requires: voicecall-core == %{version}-%{release}
+Summary: Voicecall reference QML user interface
+Group: Communications/Telephony and IM
+
+%description ui-reference
+Voicecall reference QML phone application user interface
+
 %prep
 %setup -q -n %{name}-%{version}
 
@@ -33,29 +76,40 @@
 rm -rf %{buildroot}
 %qmake_install
 
-%post
+%post libs
 /sbin/ldconfig
 
-%postun
+%postun libs
 /sbin/ldconfig
 
-%files
+%files libs
 %defattr(-,root,root,-)
-%{_bindir}/voicecall-manager
-%{_bindir}/voicecall-ui
-%{_libdir}/libvoicecall.so
 %{_libdir}/libvoicecall.so.1
 %{_libdir}/libvoicecall.so.1.0
 %{_libdir}/libvoicecall.so.1.0.0
-%{_libdir}/voicecall/plugins/libvoicecall-ofono-plugin.so
-%{_libdir}/voicecall/plugins/libvoicecall-pulseaudio-plugin.so
-%{_libdir}/voicecall/plugins/libvoicecall-tonegend-plugin.so
-%{_libdir}/voicecall/plugins/libvoicecall-telepathy-plugin.so
 %{_libdir}/qt4/imports/stage/rubyx/voicecall/libvoicecall.so
 %{_libdir}/qt4/imports/stage/rubyx/voicecall/qmldir
+
+%files core
+%defattr(-,root,root,-)
+%{_bindir}/voicecall-manager
+%{_libdir}/voicecall/plugins/libvoicecall-pulseaudio-plugin.so
+%{_libdir}/voicecall/plugins/libvoicecall-telepathy-plugin.so
+%config %{_sysconfdir}/xdg/autostart/voicecall-manager.desktop
 %config %{_sysconfdir}/voicecall/modes.ini
+
+%files devel
+%defattr(-,root,root,-)
+%{_libdir}/libvoicecall.so
+
+%files plugin-ofono
+%defattr(-,root,root,-)
+%{_libdir}/voicecall/plugins/libvoicecall-ofono-plugin.so
+#TODO: Add voicecall-manager -reconfigure to post/un when implemented in core.
+
+%files ui-reference
+%defattr(-,root,root,-)
+%{_bindir}/voicecall-ui
 %{_datadir}/voicecall-ui/qml
 %{_datadir}/applications/voicecall-ui.desktop
-%config %{_sysconfdir}/xdg/autostart/voicecall-manager.desktop
 %config %{_sysconfdir}/xdg/autostart/voicecall-ui-prestart.desktop
-

other changes:
--------------

++++++ voicecall-0.1.4+git9.4b7b286.tar.gz -> voicecall-0.2.0.tar.gz
--- lib/src/abstractvoicecallprovider.h
+++ lib/src/abstractvoicecallprovider.h
@@ -32,7 +32,7 @@
     Q_PROPERTY(QString providerType READ providerType)
 
     Q_PROPERTY(QList<AbstractVoiceCallHandler*> voiceCalls READ voiceCalls 
NOTIFY voiceCallsChanged)
-    Q_PROPERTY(QString errorString READ errorString)
+    Q_PROPERTY(QString errorString READ errorString NOTIFY error)
 
 public:
     explicit AbstractVoiceCallProvider(QObject *parent = 0) : QObject(parent) 
{/* ... */}
@@ -44,6 +44,8 @@
     virtual QString errorString() const = 0;
 
 Q_SIGNALS:
+    void error(QString);
+
     void voiceCallsChanged();
     void voiceCallAdded(AbstractVoiceCallHandler *handler);
     void voiceCallRemoved(const QString &handlerId);
--- packaging/voicecall.spec.in
+++ packaging/voicecall.spec.in
@@ -7,13 +7,16 @@
 URL:        http://github.com/nemomobile/voicecall
 Source0:    %{name}-%{version}.tar.gz
 Requires:   tone-generator
+Requires:   voicecall-ui == %{version}-%{release}
 BuildRequires:  pkgconfig(QtOpenGL)
 BuildRequires:  pkgconfig(QtDeclarative)
 BuildRequires:  pkgconfig(QtMultimediaKit)
 BuildRequires:  pkgconfig(libresourceqt1)
 BuildRequires:  pkgconfig(libpulse-mainloop-glib)
 BuildRequires:  pkgconfig(ofono-qt)
-BuildRequires:  pkgconfig(TelepathyQt4)
+# May work with earlier version, but this is tested against in nemo.
+# Requires header includes to be under TelepathyQt/ rather than TelepathyQt4/
+BuildRequires:  pkgconfig(TelepathyQt4) >= 0.9.3
 
 Obsoletes: meego-handset-dialer < 0.2.4
 Provides: meego-handset-dialer >= 0.2.4
@@ -21,6 +24,47 @@
 %description
 Next Generation Dialer Application for Nemo Mobile
 
+%package libs
+Summary: Core voicecall libraries
+Group: Communications/Telephony and IM
+
+%description libs
+Core voicecall libraries
+
+%package devel
+Requires: voicecall-libs == %{version}-%{release}
+Summary: Voicecall development package
+Group: Communications/Telephony and IM
+
+%description devel
+Voicecall development libraries and headers
+
+%package core
+Requires: voicecall-libs == %{version}-%{release}
+Summary: Core voicecall service and libraries
+Group: Communications/Telephony and IM
+
+%description core
+Core voicecall service executable, core plugins and library
+
+%package plugin-ofono
+Requires: voicecall-core == %{version}-%{release}
+Summary: Voicecall ofono plugin provider
+Group: Communications/Telephony and IM
+
+%description plugin-ofono
+Voicecall manager plugin for using ofono to make and receive calls.
+
+%package ui-reference
+Provides: voicecall > 0.1.4
+Obsoletes: voicecall <= 0.1.4
+Requires: voicecall-core == %{version}-%{release}
+Summary: Voicecall reference QML user interface
+Group: Communications/Telephony and IM
+
+%description ui-reference
+Voicecall reference QML phone application user interface
+
 %prep
 %setup -q -n %{name}-%{version}
 
@@ -33,29 +77,40 @@
 rm -rf %{buildroot}
 %qmake_install
 
-%post
+%post libs
 /sbin/ldconfig
 
-%postun
+%postun libs
 /sbin/ldconfig
 
-%files
+%files libs
 %defattr(-,root,root,-)
-%{_bindir}/voicecall-manager
-%{_bindir}/voicecall-ui
-%{_libdir}/libvoicecall.so
 %{_libdir}/libvoicecall.so.1
 %{_libdir}/libvoicecall.so.1.0
 %{_libdir}/libvoicecall.so.1.0.0
-%{_libdir}/voicecall/plugins/libvoicecall-ofono-plugin.so
-%{_libdir}/voicecall/plugins/libvoicecall-pulseaudio-plugin.so
-%{_libdir}/voicecall/plugins/libvoicecall-tonegend-plugin.so
-%{_libdir}/voicecall/plugins/libvoicecall-telepathy-plugin.so
 %{_libdir}/qt4/imports/stage/rubyx/voicecall/libvoicecall.so
 %{_libdir}/qt4/imports/stage/rubyx/voicecall/qmldir
+
+%files core
+%defattr(-,root,root,-)
+%{_bindir}/voicecall-manager
+%{_libdir}/voicecall/plugins/libvoicecall-pulseaudio-plugin.so
+%{_libdir}/voicecall/plugins/libvoicecall-telepathy-plugin.so
+%config %{_sysconfdir}/xdg/autostart/voicecall-manager.desktop
 %config %{_sysconfdir}/voicecall/modes.ini
+
+%files devel
+%defattr(-,root,root,-)
+%{_libdir}/libvoicecall.so
+
+%files plugin-ofono
+%defattr(-,root,root,-)
+%{_libdir}/voicecall/plugins/libvoicecall-ofono-plugin.so
+#TODO: Add voicecall-manager -reconfigure to post/un when implemented in core.
+
+%files ui-reference
+%defattr(-,root,root,-)
+%{_bindir}/voicecall-ui
 %{_datadir}/voicecall-ui/qml
 %{_datadir}/applications/voicecall-ui.desktop
-%config %{_sysconfdir}/xdg/autostart/voicecall-manager.desktop
 %config %{_sysconfdir}/xdg/autostart/voicecall-ui-prestart.desktop
-
--- plugins/plugins.pro
+++ plugins/plugins.pro
@@ -1,3 +1,3 @@
 TEMPLATE = subdirs
 CONFIG = ordered
-SUBDIRS = declarative ofono pulseaudio tonegend telepathy
+SUBDIRS = declarative pulseaudio telepathy ofono
--- plugins/telepathy/src/common.h
+++ plugins/telepathy/src/common.h
@@ -0,0 +1,35 @@
+/*
+ * This file is a part of the Voice Call Manager project
+ *
+ * Copyright (C) 2011-2012  Tom Swindell <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#ifndef COMMON_H
+#define COMMON_H
+
+#include <QDebug>
+
+#define DEBUG_T(message) qDebug() << QString("D:VCM: [%1] %2():%3: 
%4").arg(__FILE__).arg(__func__).arg(__LINE__).arg(message);
+#define WARNING_T(message) qWarning() << QString("W:VCM: [%1] %2():%3: 
%4").arg(__FILE__).arg(__func__).arg(__LINE__).arg(message);
+
+#ifndef WANT_TRACE
+#   define TRACE
+#else
+#   define TRACE qDebug() << QString("T:VCM: [%1] %2(): 
%3").arg(__FILE__).arg(__func__).arg(__LINE__);
+#endif
+
+#endif // COMMON_H
--- plugins/telepathy/src/src.pro
+++ plugins/telepathy/src/src.pro
@@ -9,11 +9,18 @@
 
 PKGCONFIG += TelepathyQt4
 
+DEFINES += WANT_TRACE
+
 HEADERS += \
-    telepathyproviderplugin.h
+    common.h \
+    telepathyproviderplugin.h \
+    telepathyprovider.h \
+    telepathyhandler.h
 
 SOURCES += \
-    telepathyproviderplugin.cpp
+    telepathyproviderplugin.cpp \
+    telepathyprovider.cpp \
+    telepathyhandler.cpp
 
 DEFINES += PLUGIN_NAME=\\\"voicecall-telepathy-plugin\\\"
 DEFINES += PLUGIN_VERSION=\\\"0.0.0.1\\\"
--- plugins/telepathy/src/telepathyhandler.cpp
+++ plugins/telepathy/src/telepathyhandler.cpp
@@ -0,0 +1,380 @@
+#include "common.h"
+#include "telepathyhandler.h"
+
+#include "telepathyprovider.h"
+
+#include <TelepathyQt/Channel>
+#include <TelepathyQt/CallChannel>
+#include <TelepathyQt/PendingReady>
+
+#include <TelepathyQt/ChannelInterface>
+
+static const Tp::Features RequiredFeatures = Tp::Features() << 
Tp::StreamedMediaChannel::FeatureCore
+                                                            << 
Tp::StreamedMediaChannel::FeatureLocalHoldState
+                                                            << 
Tp::StreamedMediaChannel::FeatureStreams;
+
+class TelepathyHandlerPrivate
+{
+    Q_DECLARE_PUBLIC(TelepathyHandler)
+
+public:
+    TelepathyHandlerPrivate(TelepathyHandler *q, const QString &id, 
Tp::StreamedMediaChannelPtr c, const QDateTime &s, TelepathyProvider *p)
+        : q_ptr(q), handlerId(id), provider(p), startedAt(s), channel(c),
+          status(AbstractVoiceCallHandler::STATUS_NULL),
+          iCallState(NULL), iDtmf(NULL), iGroup(NULL), iHold(NULL), 
iServicePoint(NULL)
+    { /* ... */ }
+
+    TelepathyHandler  *q_ptr;
+
+    QString            handlerId;
+    TelepathyProvider *provider;
+
+    QDateTime          startedAt;
+
+    AbstractVoiceCallHandler::VoiceCallStatus status;
+
+    // TODO: This should use "CallChannel", and, handle "Farstream" usage.
+    //       Which relies on telepathy-ring implementing these ...
+
+    // Streamed media channel and interfaces.
+    Tp::StreamedMediaChannelPtr channel;
+    Tp::Client::ChannelInterfaceCallStateInterface      *iCallState;
+    Tp::Client::ChannelInterfaceDTMFInterface           *iDtmf;
+    Tp::Client::ChannelInterfaceGroupInterface          *iGroup;
+    Tp::Client::ChannelInterfaceHoldInterface           *iHold;
+    Tp::Client::ChannelInterfaceServicePointInterface   *iServicePoint;
+
+    void updateStatus(AbstractVoiceCallHandler::VoiceCallStatus status)
+    {
+        this->status = status;
+        emit q_ptr->statusChanged();
+    }
+};
+
+TelepathyHandler::TelepathyHandler(const QString &id, 
Tp::StreamedMediaChannelPtr channel, const QDateTime &userActionTime, 
TelepathyProvider *provider)
+    : AbstractVoiceCallHandler(provider), d_ptr(new 
TelepathyHandlerPrivate(this, id, channel, userActionTime, provider))
+{
+    TRACE
+    Q_D(const TelepathyHandler);
+
+    QObject::connect(d->channel->becomeReady(RequiredFeatures),
+                     SIGNAL(finished(Tp::PendingOperation*)),
+                     SLOT(onChannelReady(Tp::PendingOperation*)));
+
+    QObject::connect(d->channel.data(),
+                     SIGNAL(invalidated(Tp::DBusProxy*,QString,QString)),
+                     
SLOT(onChannelInvalidated(Tp::DBusProxy*,QString,QString)));
+}
+
+TelepathyHandler::~TelepathyHandler()
+{
+    TRACE
+    delete this->d_ptr;
+}
+
+AbstractVoiceCallProvider* TelepathyHandler::provider() const
+{
+    TRACE
+    Q_D(const TelepathyHandler);
+    return d->provider;
+}
+
+QString TelepathyHandler::handlerId() const
+{
+    TRACE
+    Q_D(const TelepathyHandler);
+    return d->handlerId;
+}
+
+QString TelepathyHandler::lineId() const
+{
+    TRACE
+    Q_D(const TelepathyHandler);
+    if(!d->channel->isReady()) return QString::null;
+    return d->channel->targetId();
+}
+
+QDateTime TelepathyHandler::startedAt() const
+{
+    TRACE
+    Q_D(const TelepathyHandler);
+    return d->startedAt;
+}
+
+int TelepathyHandler::duration() const
+{
+    TRACE
+    Q_D(const TelepathyHandler);
+    return d->startedAt.secsTo(QDateTime());
+}
+
+bool TelepathyHandler::isMultiparty() const
+{
+    TRACE
+    Q_D(const TelepathyHandler);
+    if(!d->channel->isReady()) return false;
+    return d->channel->isConference();
+}
+
+bool TelepathyHandler::isEmergency() const
+{
+    TRACE
+    Q_D(const TelepathyHandler);
+    if(!d->channel->isReady()) return false;
+    return false;
+}
+
+AbstractVoiceCallHandler::VoiceCallStatus TelepathyHandler::status() const
+{
+    TRACE
+    Q_D(const TelepathyHandler);
+    return d->status;
+}
+
+//TODO: Move to AbstractVoiceCallHandler as this is generic.
+QString TelepathyHandler::statusText() const
+{
+    TRACE
+    Q_D(const TelepathyHandler);
+
+    switch(d->status)
+    {
+    case STATUS_ACTIVE:
+        return "active";
+    case STATUS_HELD:
+        return "held";
+    case STATUS_DIALING:
+        return "dialing";
+    case STATUS_ALERTING:
+        return "alerting";
+    case STATUS_INCOMING:
+        return "incoming";
+    case STATUS_WAITING:
+        return "waiting";
+    case STATUS_DISCONNECTED:
+        return "disconnected";
+
+    default:
+        return "null";
+    }
+}
+
+void TelepathyHandler::answer()
+{
+    TRACE
+    Q_D(TelepathyHandler);
+    QObject::connect(d->channel->acceptCall(),
+                     SIGNAL(finished(Tp::PendingOperation*)),
+                     SLOT(onAcceptCallFinished(Tp::PendingOperation*)));
+}
+
+void TelepathyHandler::hangup()
+{
+    TRACE
+    Q_D(TelepathyHandler);
+    d->channel->hangupCall();
+    QObject::connect(d->channel->hangupCall(),
+                     SIGNAL(finished(Tp::PendingOperation*)),
+                     SLOT(onHangupCallFinished(Tp::PendingOperation*)));
+}
+
+//FIXME: Don't know what telepathy API provides this.
+void TelepathyHandler::deflect(const QString &target)
+{
+    TRACE
+    Q_UNUSED(target)
+    emit this->error("NOT IMPLEMENTED YET!");
+}
+
+void TelepathyHandler::onChannelReady(Tp::PendingOperation *op)
+{
+    TRACE
+    Q_D(TelepathyHandler);
+    if(op->isError())
+    {
+        WARNING_T(QString("Operation failed: ") + op->errorName() + ": " + 
op->errorMessage());
+        emit this->error(QString("Telepathy Operation Failed: %1 - 
%2").arg(op->errorName(), op->errorMessage()));
+        return;
+    }
+
+    DEBUG_T("Channel Ready:");
+    qDebug() << "\tType:" << d->channel->channelType();
+    qDebug() << "\tInterfaces:" << d->channel->interfaces();
+
+    //TODO: Implement handle for Splittable (DRAFT) interface?
+    if(d->channel->hasInterface(TP_QT_IFACE_CHANNEL_INTERFACE_CALL_STATE))
+    {
+        DEBUG_T("Constructing call state interface.");
+        d->iCallState = new 
Tp::Client::ChannelInterfaceCallStateInterface(d->channel.data(), this);
+        QObject::connect(d->iCallState,
+                         SIGNAL(CallStateChanged(uint,uint)),
+                         SLOT(onCallStateChanged(uint,uint)));
+        //TODO: d->iCallState->GetCallStates();
+    }
+    if(d->channel->hasInterface(TP_QT_IFACE_CHANNEL_INTERFACE_DTMF))
+    {
+        DEBUG_T("Constructing dtmf interface.");
+        d->iDtmf = new 
Tp::Client::ChannelInterfaceDTMFInterface(d->channel.data());
+    }
+    if(d->channel->hasInterface(TP_QT_IFACE_CHANNEL_INTERFACE_GROUP))
+    {
+        DEBUG_T("Constructing group interface.");
+        d->iGroup = new 
Tp::Client::ChannelInterfaceGroupInterface(d->channel.data());
+    }
+    if(d->channel->hasInterface(TP_QT_IFACE_CHANNEL_INTERFACE_HOLD))
+    {
+        DEBUG_T("Constructing hold interface.");
+        d->iHold = new 
Tp::Client::ChannelInterfaceHoldInterface(d->channel.data());
+    }
+    if(d->channel->hasInterface(TP_QT_IFACE_CHANNEL_INTERFACE_SERVICE_POINT))
+    {
+        DEBUG_T("Constructing service point interface.");
+        d->iServicePoint = new 
Tp::Client::ChannelInterfaceServicePointInterface(d->channel.data());
+    }
+
+    QObject::connect(d->channel.data(),
+                     SIGNAL(streamAdded(Tp::StreamedMediaStreamPtr)),
+                     SLOT(onStreamAdded(Tp::StreamedMediaStreamPtr)));
+
+    QObject::connect(d->channel.data(),
+                     SIGNAL(streamRemoved(Tp::StreamedMediaStreamPtr)),
+                     SLOT(onStreamRemoved(Tp::StreamedMediaStreamPtr)));
+
+    QObject::connect(d->channel.data(),
+                     
SIGNAL(streamError(Tp::StreamedMediaStreamPtr,Tp::MediaStreamError,QString)),
+                     
SLOT(onStreamError(Tp::StreamedMediaStreamPtr,Tp::MediaStreamError,QString)));
+
+    QObject::connect(d->channel.data(),
+                     
SIGNAL(streamStateChanged(Tp::StreamedMediaStreamPtr,Tp::MediaStreamState)),
+                     
SLOT(onStreamStateChanged(Tp::StreamedMediaStreamPtr,Tp::MediaStreamState)));
+
+    //FIXME: Doesn't work, probably not the right way to do things anyway 
(interface access is better)
+    QObject::connect(d->channel.data(), SIGNAL(propertyChanged(QString)), 
SLOT(onChannelPropertyChanged(QString)));
+
+
+    if(d->channel->awaitingLocalAnswer())
+    {
+        d->status = STATUS_INCOMING;
+    }
+    else if(d->channel->awaitingRemoteAnswer())
+    {
+        d->status = STATUS_ALERTING;
+    }
+
+    if(d->channel->handlerStreamingRequired())
+    {
+        //TODO: Implement farsight support for SIP and Video calls.
+    }
+
+    emit this->statusChanged();
+}
+
+void TelepathyHandler::onChannelPropertyChanged(const QString &property)
+{
+    TRACE
+    DEBUG_T(QString("Channel property changed: ") + property);
+}
+
+void TelepathyHandler::onChannelInvalidated(Tp::DBusProxy *, const QString 
&errorName, const QString &errorMessage)
+{
+    TRACE
+    Q_D(TelepathyHandler);
+
+    DEBUG_T(QString("Channel invalidated: ") + errorName + ": " + 
errorMessage);
+
+    // It seems to get called twice.
+    QObject::disconnect(d->channel.data(),
+                        SIGNAL(invalidated(Tp::DBusProxy*,QString,QString)),
+                        this,
+                        
SLOT(onChannelInvalidated(Tp::DBusProxy*,QString,QString)));
+
+    emit this->invalidated(errorName, errorMessage);
+}
+
+void TelepathyHandler::onStreamAdded(const Tp::StreamedMediaStreamPtr &stream)
+{
+    TRACE
+    Q_UNUSED(stream)
+}
+
+void TelepathyHandler::onStreamRemoved(const Tp::StreamedMediaStreamPtr 
&stream)
+{
+    TRACE
+    Q_UNUSED(stream)
+}
+
+void TelepathyHandler::onStreamError(const Tp::StreamedMediaStreamPtr &stream, 
Tp::MediaStreamError errorCode, const QString &errorMessage)
+{
+    TRACE
+    Q_UNUSED(stream)
+    Q_UNUSED(errorCode)
+
+    emit this->error(QString("Telepathy Stream Error: %1").arg(errorMessage));
+}
+
+void TelepathyHandler::onStreamStateChanged(const Tp::StreamedMediaStreamPtr 
&stream, Tp::MediaStreamState state)
+{
+    TRACE
+    Q_UNUSED(stream)
+    Q_D(TelepathyHandler);
+
+    switch(state)
+    {
+    case Tp::MediaStreamStateDisconnected:
+        DEBUG_T("Media stream state disconnected.");
+        d->status = STATUS_DISCONNECTED;
+        emit this->statusChanged();
+        break;
+
+    case Tp::MediaStreamStateConnecting:
+        DEBUG_T("Media stream state connecting.");
+        break;
+
+    case Tp::MediaStreamStateConnected:
+        DEBUG_T("Media stream state connected.");
+        d->status = STATUS_ACTIVE;
+        emit this->statusChanged();
+        break;
+
+    default:
+        break;
+    }
+}
+
+void TelepathyHandler::onAcceptCallFinished(Tp::PendingOperation *op)
+{
+    TRACE
+    Q_D(TelepathyHandler);
+    if(op->isError())
+    {
+        WARNING_T(QString("Operation failed: ") + op->errorName() + ": " + 
op->errorMessage());
+        emit this->error(QString("Telepathy Operation Failed: %1 - 
%2").arg(op->errorName(), op->errorMessage()));
+        return;
+    }
+
+    d->status = STATUS_ACTIVE;
+    emit this->statusChanged();
+}
+
+void TelepathyHandler::onHangupCallFinished(Tp::PendingOperation *op)
+{
+    TRACE
+    Q_D(TelepathyHandler);
+    if(op->isError())
+    {
+        WARNING_T(QString("Operation failed: ") + op->errorName() + ": " + 
op->errorMessage());
+        emit this->error(QString("Telepathy Operation Failed: %1 - 
%2").arg(op->errorName(), op->errorMessage()));
+        return;
+    }
+
+    d->status = STATUS_DISCONNECTED;
+    emit this->statusChanged();
+
+    emit this->invalidated("closed", "user");
+}
+
+void TelepathyHandler::onCallStateChanged(uint contact, uint state)
+{
+    TRACE
+    DEBUG_T(QString("Call state changed for contact %1 to state 
%2").arg(contact).arg(state));
+}
--- plugins/telepathy/src/telepathyhandler.h
+++ plugins/telepathy/src/telepathyhandler.h
@@ -0,0 +1,66 @@
+#ifndef TELEPATHYHANDLER_H
+#define TELEPATHYHANDLER_H
+
+#include <abstractvoicecallhandler.h>
+
+#include <TelepathyQt/StreamedMediaChannel>
+
+class TelepathyProvider;
+
+class TelepathyHandler : public AbstractVoiceCallHandler
+{
+    Q_OBJECT
+
+public:
+    explicit TelepathyHandler(const QString &id, Tp::StreamedMediaChannelPtr 
channel, const QDateTime &userActionTime, TelepathyProvider *provider = 0);
+            ~TelepathyHandler();
+
+    /*** AbstractVoiceCallHandler Implementation ***/
+    AbstractVoiceCallProvider* provider() const;
+    QString handlerId() const;
+    QString lineId() const;
+    QDateTime startedAt() const;
+    int duration() const;
+    bool isMultiparty() const;
+    bool isEmergency() const;
+
+    VoiceCallStatus status() const;
+    QString statusText() const;
+
+    /*** TelepathyHandler Implementation ***/
+    Tp::StreamedMediaChannel channel() const;
+
+Q_SIGNALS:
+    /*** TelepathyHandler Implementation ***/
+    void error(const QString &errorMessage);
+    void invalidated(const QString &errorName, const QString &errorMessage);
+
+public Q_SLOTS:
+    /*** AbstractVoiceCallHandler Implementation ***/
+    void answer();
+    void hangup();
+    void deflect(const QString &target);
+
+protected Q_SLOTS:
+    void onChannelReady(Tp::PendingOperation *op);
+    void onChannelPropertyChanged(const QString &property);
+    void onChannelInvalidated(Tp::DBusProxy*,const QString &errorName, const 
QString &errorMessage);
+
+    void onStreamAdded(const Tp::StreamedMediaStreamPtr &stream);
+    void onStreamRemoved(const Tp::StreamedMediaStreamPtr &stream);
+    void onStreamStateChanged(const Tp::StreamedMediaStreamPtr &stream, 
Tp::MediaStreamState state);
+    void onStreamError(const Tp::StreamedMediaStreamPtr &stream, 
Tp::MediaStreamError errorCode, const QString &errorMessage);
+
+    void onAcceptCallFinished(Tp::PendingOperation *op);
+    void onHangupCallFinished(Tp::PendingOperation *op);
+
+    void onCallStateChanged(uint contact, uint state);
+
+private:
+    class TelepathyHandlerPrivate *d_ptr;
+
+    Q_DISABLE_COPY(TelepathyHandler)
+    Q_DECLARE_PRIVATE(TelepathyHandler)
+};
+
+#endif // TELEPATHYHANDLER_H
--- plugins/telepathy/src/telepathyprovider.cpp
+++ plugins/telepathy/src/telepathyprovider.cpp
@@ -0,0 +1,199 @@
+#include "common.h"
+
+#include "telepathyhandler.h"
+#include "telepathyprovider.h"
+
+#include <TelepathyQt/AbstractClient>
+#include <TelepathyQt/ClientRegistrar>
+#include <TelepathyQt/ChannelClassSpec>
+
+#include <TelepathyQt/PendingReady>
+#include <TelepathyQt/PendingChannel>
+#include <TelepathyQt/PendingChannelRequest>
+
+class TelepathyProviderPrivate
+{
+    Q_DECLARE_PUBLIC(TelepathyProvider)
+
+public:
+    TelepathyProviderPrivate(Tp::AccountPtr a, VoiceCallManagerInterface *m, 
TelepathyProvider *q)
+        : q_ptr(q), manager(m), account(a),
+          errorString(QString::null),
+          tpClientHandler(NULL), tpClientRegistrar(NULL), 
tpPendingChannel(NULL)
+    { /* ... */ }
+
+    TelepathyProvider           *q_ptr;
+    VoiceCallManagerInterface   *manager;
+
+    Tp::AccountPtr               account;
+
+    QString                      errorString;
+
+    QHash<QString,AbstractVoiceCallHandler*> voiceCalls;
+
+    Tp::AbstractClientPtr    tpClientHandler;
+    Tp::ClientRegistrarPtr   tpClientRegistrar;
+
+    Tp::PendingChannel      *tpPendingChannel;
+
+    static const Tp::ChannelClassSpecList CHANNEL_SPECS;
+};
+
+const Tp::ChannelClassSpecList TelepathyProviderPrivate::CHANNEL_SPECS =
+        (Tp::ChannelClassSpecList()
+         << Tp::ChannelClassSpec::audioCall()
+         << Tp::ChannelClassSpec::streamedMediaCall()
+         << Tp::ChannelClassSpec::unnamedStreamedMediaCall()
+         << Tp::ChannelClassSpec::streamedMediaAudioCall()
+         << Tp::ChannelClassSpec::unnamedStreamedMediaCall());
+
+TelepathyProvider::TelepathyProvider(Tp::AccountPtr account, 
VoiceCallManagerInterface *manager, QObject *parent)
+    : AbstractVoiceCallProvider(parent),
+      Tp::AbstractClientHandler(TelepathyProviderPrivate::CHANNEL_SPECS),
+      d_ptr(new TelepathyProviderPrivate(account, manager, this))
+{
+    TRACE
+    Q_D(TelepathyProvider);
+
+    d->tpClientHandler = Tp::AbstractClientPtr(this);
+    d->tpClientRegistrar = Tp::ClientRegistrar::create();
+
+    if(!d->tpClientRegistrar->registerClient(d->tpClientHandler, "voicecall", 
true))
+    {
+        WARNING_T("Failed to register telepathy client!");
+        d->errorString = "Failed to register telepathy client!";
+        emit this->error(d->errorString);
+    }
+}
+
+TelepathyProvider::~TelepathyProvider()
+{
+    TRACE
+    Q_D(TelepathyProvider);
+    d->tpClientRegistrar->unregisterClient(d->tpClientHandler);
+    delete d;
+}
+
+QString TelepathyProvider::errorString() const
+{
+    TRACE
+    Q_D(const TelepathyProvider);
+    return d->errorString;
+}
+
+QString TelepathyProvider::providerId() const
+{
+    TRACE
+    Q_D(const TelepathyProvider);
+    return QString("telepathy-") + d->account->uniqueIdentifier();
+}
+
+QString TelepathyProvider::providerType() const
+{
+    TRACE
+    return "cellular";
+}
+
+QList<AbstractVoiceCallHandler*> TelepathyProvider::voiceCalls() const
+{
+    TRACE
+    Q_D(const TelepathyProvider);
+    return d->voiceCalls.values();
+}
+
+bool TelepathyProvider::dial(const QString &msisdn)
+{
+    TRACE
+    Q_D(TelepathyProvider);
+    if(d->tpPendingChannel)
+    {
+        d->errorString = "Can't initiate a call when one is pending!";
+        WARNING_T(d->errorString);
+        emit this->error(d->errorString);
+        return false;
+    }
+
+    d->tpPendingChannel = 
d->account->ensureAndHandleStreamedMediaAudioCall(msisdn);
+    QObject::connect(d->tpPendingChannel,
+                     SIGNAL(finished(Tp::PendingOperation*)),
+                     SLOT(onDialFinished(Tp::PendingOperation*)));
+    return true;
+}
+
+void TelepathyProvider::handleChannels(const Tp::MethodInvocationContextPtr<> 
&context,
+                                       const Tp::AccountPtr &account,
+                                       const Tp::ConnectionPtr &connection,
+                                       const QList<Tp::ChannelPtr> &channels,
+                                       const QList<Tp::ChannelRequestPtr> 
&requestsSatisfied,
+                                       const QDateTime &userActionTime,
+                                       const HandlerInfo &handlerInfo)
+{
+    TRACE
+    Q_UNUSED(account)
+    Q_UNUSED(account)
+    Q_UNUSED(connection)
+    Q_UNUSED(requestsSatisfied)
+    Q_UNUSED(handlerInfo)
+
+    DEBUG_T(QString("Found %1 channel/s.").arg(channels.size()));
+
+    foreach(Tp::ChannelPtr ch, channels)
+    {
+        this->createHandler(ch, userActionTime);
+    }
+
+    emit this->voiceCallsChanged();
+    context->setFinished();
+}
+
+void TelepathyProvider::createHandler(Tp::ChannelPtr ch, const QDateTime 
&userActionTime)
+{
+    TRACE
+    Q_D(TelepathyProvider);
+    DEBUG_T(QString("\tProcessing channel: %1").arg(ch->objectPath()));
+    TelepathyHandler *handler = new 
TelepathyHandler(d->manager->generateHandlerId(), 
Tp::StreamedMediaChannelPtr::staticCast(ch), userActionTime, this);
+    d->voiceCalls.insert(handler->handlerId(), handler);
+
+    QObject::connect(handler, SIGNAL(error(QString)), SIGNAL(error(QString)));
+
+    QObject::connect(handler,
+                     SIGNAL(invalidated(QString,QString)),
+                     SLOT(onHandlerInvalidated(QString,QString)));
+
+    emit this->voiceCallAdded(handler);
+}
+
+void TelepathyProvider::onDialFinished(Tp::PendingOperation *op)
+{
+    TRACE
+    Q_D(TelepathyProvider);
+    if(op->isError())
+    {
+        WARNING_T(QString("Operation failed: ") + op->errorName() + ": " + 
op->errorMessage());
+        d->tpPendingChannel = NULL;
+        d->errorString = QString("Telepathy Operation Failed: %1 - 
%2").arg(op->errorName(), op->errorMessage());
+        emit this->error(d->errorString);
+        return;
+    }
+
+    this->createHandler(d->tpPendingChannel->channel(), QDateTime());
+    d->tpPendingChannel = NULL;
+
+    emit this->voiceCallsChanged();
+}
+
+void TelepathyProvider::onHandlerInvalidated(const QString &errorName, const 
QString &errorMessage)
+{
+    TRACE
+    Q_UNUSED(errorName)
+    Q_UNUSED(errorMessage)
+    Q_D(TelepathyProvider);
+
+    TelepathyHandler *handler = 
qobject_cast<TelepathyHandler*>(QObject::sender());
+    d->voiceCalls.remove(handler->handlerId());
+
+    emit this->voiceCallRemoved(handler->handlerId());
+    emit this->voiceCallsChanged();
+
+    handler->deleteLater();
+}
--- plugins/telepathy/src/telepathyprovider.h
+++ plugins/telepathy/src/telepathyprovider.h
@@ -0,0 +1,51 @@
+#ifndef TELEPATHYPROVIDER_H
+#define TELEPATHYPROVIDER_H
+
+#include <abstractvoicecallprovider.h>
+#include <voicecallmanagerinterface.h>
+
+#include <TelepathyQt/AbstractClientHandler>
+#include <TelepathyQt/MethodInvocationContext>
+#include <TelepathyQt/PendingOperation>
+
+class TelepathyProvider : public AbstractVoiceCallProvider, public 
Tp::AbstractClientHandler
+{
+    Q_OBJECT
+public:
+    explicit TelepathyProvider(Tp::AccountPtr account, 
VoiceCallManagerInterface *manager, QObject *parent = 0);
+            ~TelepathyProvider();
+
+    QString errorString() const;
+
+    QString providerId() const;
+    QString providerType() const;
+
+    QList<AbstractVoiceCallHandler*> voiceCalls() const;
+
+    bool bypassApproval() const {return true;}
+    void handleChannels(const Tp::MethodInvocationContextPtr<> &context,
+                        const Tp::AccountPtr &account,
+                        const Tp::ConnectionPtr &connection,
+                        const QList<Tp::ChannelPtr> &channels,
+                        const QList<Tp::ChannelRequestPtr> &requestsSatisfied,
+                        const QDateTime &userActionTime,
+                        const HandlerInfo &handlerInfo);
+
+public Q_SLOTS:
+    bool dial(const QString &msisdn);
+
+protected Q_SLOTS:
+    void onDialFinished(Tp::PendingOperation *op);
+    void onHandlerInvalidated(const QString &errorName, const QString 
&errorMessage);
+
+protected:
+    void createHandler(Tp::ChannelPtr ch, const QDateTime &userActionTime);
+
+private:
+    class TelepathyProviderPrivate *d_ptr;
+
+    Q_DISABLE_COPY(TelepathyProvider)
+    Q_DECLARE_PRIVATE(TelepathyProvider)
+};
+
+#endif // TELEPATHYPROVIDER_H
--- plugins/telepathy/src/telepathyproviderplugin.cpp
+++ plugins/telepathy/src/telepathyproviderplugin.cpp
@@ -19,10 +19,23 @@
  *
  */
 #include "common.h"
+
 #include "telepathyproviderplugin.h"
+#include "telepathyprovider.h"
+
+#include <voicecallmanagerinterface.h>
 
 #include <QtPlugin>
 
+#include <TelepathyQt/Types>
+
+#include <TelepathyQt/Account>
+#include <TelepathyQt/AccountSet>
+#include <TelepathyQt/AccountManager>
+
+#include <TelepathyQt/PendingReady>
+#include <TelepathyQt/PendingStringList>
+
 class TelepathyProviderPluginPrivate
 {
     Q_DECLARE_PUBLIC(TelepathyProviderPlugin)
@@ -32,13 +45,18 @@
         : q_ptr(q), manager(NULL)
     {/* ... */}
 
-    TelepathyProviderPlugin *q_ptr;
+    TelepathyProviderPlugin     *q_ptr;
 
     VoiceCallManagerInterface   *manager;
+
+    Tp::AccountManagerPtr am;
+
+    QHash<QString,TelepathyProvider*>    providers;
 };
 
 TelepathyProviderPlugin::TelepathyProviderPlugin(QObject *parent)
-    : AbstractVoiceCallManagerPlugin(parent), d_ptr(new 
TelepathyProviderPluginPrivate(this))
+    : AbstractVoiceCallManagerPlugin(parent),
+      d_ptr(new TelepathyProviderPluginPrivate(this))
 {
     TRACE
 }
@@ -46,8 +64,7 @@
 TelepathyProviderPlugin::~TelepathyProviderPlugin()
 {
     TRACE
-    Q_D(TelepathyProviderPlugin);
-    delete d;
+    delete this->d_ptr;
 }
 
 QString TelepathyProviderPlugin::pluginId() const
@@ -65,6 +82,9 @@
 bool TelepathyProviderPlugin::initialize()
 {
     TRACE
+    Q_D(TelepathyProviderPlugin);
+    Tp::registerTypes();
+    d->am = Tp::AccountManager::create();
     return true;
 }
 
@@ -72,8 +92,10 @@
 {
     TRACE
     Q_D(TelepathyProviderPlugin);
-
     d->manager = manager;
+    QObject::connect(d->am->becomeReady(),
+                     SIGNAL(finished(Tp::PendingOperation*)),
+                     SLOT(onAccountManagerReady(Tp::PendingOperation*)));
 
     return true;
 }
@@ -101,4 +123,41 @@
     TRACE
 }
 
+void TelepathyProviderPlugin::onAccountManagerReady(Tp::PendingOperation *op)
+{
+    TRACE
+    Q_D(TelepathyProviderPlugin);
+    if(op->isError())
+    {
+        WARNING_T(QString("Operation failed: ") + op->errorName() + ": " + 
op->errorMessage());
+        return;
+    }
+
+    foreach(Tp::AccountPtr account, d->am->allAccounts())
+    {
+        qDebug() << "Found account:" << account->displayName();
+        qDebug() << "\tManager Name:" << account->cmName();
+        qDebug() << "\tProtocol Name:" << account->protocolName();
+        qDebug() << "\tService Name:" << account->serviceName();
+
+        if(account->protocolName() == "tel")
+        {
+            if(d->providers.contains(account->uniqueIdentifier()))
+            {
+                DEBUG_T("Ignoring already registered account.");
+                continue;
+            }
+
+            DEBUG_T(QString("Registering provider: ") + 
account->uniqueIdentifier());
+            TelepathyProvider *tp = new TelepathyProvider(account, d->manager, 
this);
+            d->providers.insert(account->uniqueIdentifier(), tp);
+            d->manager->appendProvider(tp);
+        }
+        else
+        {
+            DEBUG_T("Ignoring account due to unrecognised protocol.");
+        }
+    }
+}
+
 Q_EXPORT_PLUGIN2(voicecall-telepathy-plugin, TelepathyProviderPlugin)
--- plugins/telepathy/src/telepathyproviderplugin.h
+++ plugins/telepathy/src/telepathyproviderplugin.h
@@ -3,6 +3,8 @@
 
 #include <abstractvoicecallmanagerplugin.h>
 
+#include <TelepathyQt/PendingOperation>
+
 class TelepathyProviderPlugin : public AbstractVoiceCallManagerPlugin
 {
     Q_OBJECT
@@ -24,6 +26,9 @@
     bool resume();
     void finalize();
 
+protected Q_SLOTS:
+    void onAccountManagerReady(Tp::PendingOperation *op);
+
 private:
     class TelepathyProviderPluginPrivate *d_ptr;
 



Reply via email to