[dialer] Add basic Telepathy Channel Handler

This commit is contained in:
Martin Klapetek 2015-06-18 21:25:59 +00:00
parent 2092cbc59a
commit 958983df42
10 changed files with 444 additions and 2 deletions

View file

@ -2,5 +2,7 @@
kpackage_install_package(package org.kde.phone.dialer genericqml) kpackage_install_package(package org.kde.phone.dialer genericqml)
install(FILES package/metadata.desktop DESTINATION ${XDG_APPS_INSTALL_DIR} RENAME org.kde.phone.dialer.desktop) install(FILES package/metadata.desktop DESTINATION ${XDG_APPS_INSTALL_DIR} RENAME org.kde.phone.dialer.desktop)
include_directories(${TELEPATHY_QT5_INCLUDE_DIR})
add_subdirectory(src) add_subdirectory(src)
add_subdirectory(plugin) add_subdirectory(plugin)

View file

@ -1,5 +1,3 @@
include_directories(${TELEPATHY_QT5_INCLUDE_DIR})
set(tpcallerplugin_SRCS set(tpcallerplugin_SRCS
tp-call-plugin.cpp tp-call-plugin.cpp
tp-caller.cpp tp-caller.cpp

View file

@ -3,6 +3,8 @@
set(plasmaphonedialer_SRCS set(plasmaphonedialer_SRCS
main.cpp main.cpp
dialerutils.cpp dialerutils.cpp
call-handler.cpp
call-manager.cpp
) )
add_executable(plasmaphonedialer ${plasmaphonedialer_SRCS}) add_executable(plasmaphonedialer ${plasmaphonedialer_SRCS})
@ -20,7 +22,15 @@ target_link_libraries(plasmaphonedialer
KF5::QuickAddons KF5::QuickAddons
KF5::DBusAddons KF5::DBusAddons
KF5::Notifications KF5::Notifications
${TELEPATHY_QT5_LIBRARIES}
) )
install(TARGETS plasmaphonedialer ${INSTALL_TARGETS_DEFAULT_ARGS}) install(TARGETS plasmaphonedialer ${INSTALL_TARGETS_DEFAULT_ARGS})
install(FILES plasma_dialer.notifyrc DESTINATION ${KDE_INSTALL_KNOTIFY5RCDIR}) install(FILES plasma_dialer.notifyrc DESTINATION ${KDE_INSTALL_KNOTIFY5RCDIR})
configure_file(org.freedesktop.Telepathy.Client.Plasma.Dialer.service.in
org.freedesktop.Telepathy.Client.Plasma.Dialer.service)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.Telepathy.Client.Plasma.Dialer.service
DESTINATION ${DBUS_SERVICES_INSTALL_DIR})
install(FILES Plasma.Dialer.client DESTINATION ${SHARE_INSTALL_PREFIX}/telepathy/clients/)

View file

@ -0,0 +1,27 @@
[org.freedesktop.Telepathy.Client]
Interfaces=org.freedesktop.Telepathy.Client.Handler
[org.freedesktop.Telepathy.Client.Handler.HandlerChannelFilter 0]
org.freedesktop.Telepathy.Channel.ChannelType s=org.freedesktop.Telepathy.Channel.Type.Call1
org.freedesktop.Telepathy.Channel.TargetHandleType u=1
[org.freedesktop.Telepathy.Client.Handler.HandlerChannelFilter 1]
org.freedesktop.Telepathy.Channel.ChannelType s=org.freedesktop.Telepathy.Channel.Type.Call1
org.freedesktop.Telepathy.Channel.TargetHandleType u=1
org.freedesktop.Telepathy.Channel.Type.Call1.InitialAudio b=true
[org.freedesktop.Telepathy.Client.Handler.HandlerChannelFilter 2]
org.freedesktop.Telepathy.Channel.ChannelType s=org.freedesktop.Telepathy.Channel.Type.Call1
org.freedesktop.Telepathy.Channel.TargetHandleType u=1
org.freedesktop.Telepathy.Channel.Type.Call1.InitialVideo b=true
[org.freedesktop.Telepathy.Client.Handler]
BypassApproval=true
[org.freedesktop.Telepathy.Client.Handler.Capabilities]
org.freedesktop.Telepathy.Channel.Type.Call1/audio=true
org.freedesktop.Telepathy.Channel.Type.Call1/video=true
org.freedesktop.Telepathy.Channel.Type.Call1/ice=true
org.freedesktop.Telepathy.Channel.Type.Call1/gtalk-p2p=true
org.freedesktop.Telepathy.Channel.Type.Call1/shm=true
org.freedesktop.Telepathy.Channel.Type.Call1/video/h264=true

View file

@ -0,0 +1,92 @@
/*
Copyright (C) 2009-2012 George Kiagiadakis <kiagiadakis.george@gmail.com>
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, see <http://www.gnu.org/licenses/>.
*/
#include "call-handler.h"
#include "call-manager.h"
#include "dialerutils.h"
#include <TelepathyQt/CallChannel>
#include <TelepathyQt/ChannelClassSpec>
static inline Tp::ChannelClassSpecList channelClassSpecList()
{
return Tp::ChannelClassSpecList() << Tp::ChannelClassSpec::audioCall();
}
static inline Tp::AbstractClientHandler::Capabilities capabilities()
{
Tp::AbstractClientHandler::Capabilities caps;
//we support both audio and video in calls
caps.setToken(TP_QT_IFACE_CHANNEL_TYPE_CALL + QLatin1String("/audio"));
// caps.setToken(TP_QT_IFACE_CHANNEL_TYPE_CALL + QLatin1String("/video"));
//transport methods - farstream supports them all
caps.setToken(TP_QT_IFACE_CHANNEL_TYPE_CALL + QLatin1String("/ice"));
caps.setToken(TP_QT_IFACE_CHANNEL_TYPE_CALL + QLatin1String("/gtalk-p2p"));
caps.setToken(TP_QT_IFACE_CHANNEL_TYPE_CALL + QLatin1String("/shm"));
//significant codecs
caps.setToken(TP_QT_IFACE_CHANNEL_TYPE_CALL + QLatin1String("/video/h264"));
return caps;
}
CallHandler::CallHandler(DialerUtils *utils)
: Tp::AbstractClientHandler(channelClassSpecList(), capabilities())
{
m_dialerUtils = utils;
qDebug() << "Call handler ready";
}
CallHandler::~CallHandler()
{
}
bool CallHandler::bypassApproval() const
{
return true;
}
void CallHandler::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 Tp::AbstractClientHandler::HandlerInfo & handlerInfo)
{
Q_UNUSED(account);
Q_UNUSED(connection);
Q_UNUSED(requestsSatisfied);
Q_UNUSED(userActionTime);
Q_UNUSED(handlerInfo);
Q_FOREACH(const Tp::ChannelPtr & channel, channels) {
Tp::CallChannelPtr callChannel = Tp::CallChannelPtr::qObjectCast(channel);
if (!callChannel) {
qDebug() << "Channel is not a Call channel. Ignoring";
continue;
}
//check if any call manager is already handling this channel
if (!handledCallChannels.contains(callChannel)) {
handledCallChannels.append(callChannel);
new CallManager(callChannel, m_dialerUtils, this);
}
}
context->setFinished();
}

44
dialer/src/call-handler.h Normal file
View file

@ -0,0 +1,44 @@
/*
Copyright (C) 2009 George Kiagiadakis <kiagiadakis.george@gmail.com>
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, see <http://www.gnu.org/licenses/>.
*/
#ifndef CALL_HANDLER_H
#define CALL_HANDLER_H
#include <TelepathyQt/AbstractClientHandler>
class DialerUtils;
class CallHandler : public QObject, public Tp::AbstractClientHandler
{
Q_OBJECT
public:
CallHandler(DialerUtils *utils);
virtual ~CallHandler();
virtual bool bypassApproval() const;
virtual 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 Tp::AbstractClientHandler::HandlerInfo & handlerInfo);
private:
QList<Tp::CallChannelPtr> handledCallChannels;
DialerUtils *m_dialerUtils;
};
#endif

182
dialer/src/call-manager.cpp Normal file
View file

@ -0,0 +1,182 @@
/*
Copyright (C) 2012 George Kiagiadakis <kiagiadakis.george@gmail.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "call-manager.h"
#include "dialerutils.h"
// #include "call-window.h"
// #include "approver.h"
// #include "../libktpcall/call-channel-handler.h"
// #include "ktp_call_ui_debug.h"
// #include <KTp/telepathy-handler-application.h>
struct CallManager::Private
{
Tp::CallChannelPtr callChannel;
// CallChannelHandler *channelHandler;
// QPointer<CallWindow> callWindow;
// QPointer<Approver> approver;
DialerUtils *dialerUtils;
};
CallManager::CallManager(const Tp::CallChannelPtr &callChannel, DialerUtils *dialerUtils, QObject *parent)
: QObject(parent), d(new Private)
{
// KTp::TelepathyHandlerApplication::newJob();
d->dialerUtils = dialerUtils;
d->callChannel = callChannel;
connect(callChannel.data(), SIGNAL(callStateChanged(Tp::CallState)),
SLOT(onCallStateChanged(Tp::CallState)));
//create the channel handler
// d->channelHandler = new CallChannelHandler(callChannel, this);
//delete the CallManager when the channel has closed
//and the farstream side has safely shut down.
//NOTE this MUST be used with Qt::QueuedConnection because of
// https://bugreports.qt-project.org/browse/QTBUG-24571
// connect(d->channelHandler, SIGNAL(channelClosed()),
// this, SLOT(deleteLater()), Qt::QueuedConnection);
//bring us up-to-date with the current call state
onCallStateChanged(d->callChannel->callState());
}
CallManager::~CallManager()
{
qDebug() << "Deleting CallManager";
//delete the window just in case CallManager was deleted
//before the channel entered CallStateEnded
// delete d->callWindow.data();
// delete d;
// KTp::TelepathyHandlerApplication::jobFinished();
}
void CallManager::onCallStateChanged(Tp::CallState state)
{
qDebug() << "new call state:" << state;
switch (state) {
case Tp::CallStatePendingInitiator:
Q_ASSERT(d->callChannel->isRequested());
(void) d->callChannel->accept();
break;
case Tp::CallStateInitialising:
if (d->callChannel->isRequested()) {
d->dialerUtils->setCallState("dialing");
//show status that the call is conneting
// ensureCallWindow();
// d->callWindow.data()->setStatus(CallWindow::StatusConnecting);
} else {
qDebug() << "Call is initialising";
}
break;
case Tp::CallStateInitialised:
if (d->callChannel->isRequested()) {
d->dialerUtils->setCallState("dialing");
//show status that the remote end is ringing
// ensureCallWindow();
// d->callWindow.data()->setStatus(CallWindow::StatusRemoteRinging);
} else {
d->dialerUtils->setCallState("incoming");
connect(d->dialerUtils, &DialerUtils::acceptCall, this, &CallManager::onCallAccepted);
connect(d->dialerUtils, &DialerUtils::rejectCall, this, &CallManager::onCallRejected);
//show approver;
(void) d->callChannel->setRinging();
}
break;
case Tp::CallStateAccepted:
if (d->callChannel->isRequested()) {
d->dialerUtils->setCallState("answered");
//show status that the remote end accepted the call
// ensureCallWindow();
// d->callWindow.data()->setStatus(CallWindow::StatusRemoteAccepted);
} else {
//hide approver & show call window
// delete d->approver.data();
// ensureCallWindow();
// d->callWindow.data()->setStatus(CallWindow::StatusConnecting);
}
break;
case Tp::CallStateActive:
//normally the approver is already deleted and the call window
//already exists at this point, but we just want to be safe
//in case the CM decides to do a weird state jump
if (!d->callChannel->isRequested()) {
// delete d->approver.data();
}
d->dialerUtils->setCallState("active");
// ensureCallWindow();
// d->callWindow.data()->setStatus(CallWindow::StatusActive);
break;
case Tp::CallStateEnded:
d->dialerUtils->setCallState("ended");
//if we requested the call, make sure we have a window to show the error (if any)
// if (d->callChannel->isRequested()) {
// ensureCallWindow();
// }
// if (d->callWindow) {
// Tp::CallStateReason reason = d->callChannel->callStateReason();
// d->callWindow.data()->setStatus(CallWindow::StatusDisconnected, reason);
//
// //kill the call manager when the call window is closed,
// //after shutting down the channelHandler
// connect(d->callWindow.data(), SIGNAL(destroyed()), d->channelHandler, SLOT(shutdown()));
// } else {
// //missed the call
// qCDebug(KTP_CALL_UI) << "missed call";
// delete d->approver.data();
// d->channelHandler->shutdown();
// }
break;
default:
Q_ASSERT(false);
}
}
void CallManager::onCallAccepted()
{
(void) d->callChannel->accept();
}
void CallManager::onCallRejected()
{
(void) d->callChannel->hangup(Tp::CallStateChangeReasonRejected, TP_QT_ERROR_REJECTED);
}
void CallManager::ensureCallWindow()
{
// if (!d->callWindow) {
// d->callWindow = new CallWindow(d->callChannel);
// d->callWindow.data()->show();
// d->callWindow.data()->setAttribute(Qt::WA_DeleteOnClose);
//
// connect(d->channelHandler, SIGNAL(contentAdded(CallContentHandler*)),
// d->callWindow.data(), SLOT(onContentAdded(CallContentHandler*)));
// connect(d->channelHandler, SIGNAL(contentRemoved(CallContentHandler*)),
// d->callWindow.data(), SLOT(onContentRemoved(CallContentHandler*)));
//
// //inform the ui about already existing contents
// Q_FOREACH(CallContentHandler *content, d->channelHandler->contents()) {
// d->callWindow.data()->onContentAdded(content);
// }
// }
}

45
dialer/src/call-manager.h Normal file
View file

@ -0,0 +1,45 @@
/*
Copyright (C) 2012 George Kiagiadakis <kiagiadakis.george@gmail.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CALL_MANAGER_H
#define CALL_MANAGER_H
#include <QObject>
#include <TelepathyQt/CallChannel>
class DialerUtils;
class CallManager : public QObject
{
Q_OBJECT
public:
explicit CallManager(const Tp::CallChannelPtr &callChannel, DialerUtils *dialerUtils, QObject *parent = 0);
virtual ~CallManager();
private Q_SLOTS:
void onCallStateChanged(Tp::CallState state);
void onCallAccepted();
void onCallRejected();
private:
void ensureCallWindow();
private:
struct Private;
Private *const d;
};
#endif // CALL_MANAGER_H

View file

@ -20,6 +20,14 @@
#include <QApplication> #include <QApplication>
#include "dialerutils.h" #include "dialerutils.h"
#include "call-handler.h"
#include <TelepathyQt/Types>
#include <TelepathyQt/Debug>
#include <TelepathyQt/ClientRegistrar>
#include <TelepathyQt/CallChannel>
#include <TelepathyQt/ChannelClassSpec>
#include <TelepathyQt/ChannelFactory>
#include <klocalizedstring.h> #include <klocalizedstring.h>
#include <qcommandlineparser.h> #include <qcommandlineparser.h>
@ -125,6 +133,37 @@ int main(int argc, char **argv)
qWarning() << "Error loading the ApplicationWindow"; qWarning() << "Error loading the ApplicationWindow";
} }
Tp::AccountFactoryPtr accountFactory = Tp::AccountFactory::create(QDBusConnection::sessionBus(),
Tp::Features() << Tp::Account::FeatureCore
);
Tp::ConnectionFactoryPtr connectionFactory = Tp::ConnectionFactory::create(QDBusConnection::sessionBus(),
Tp::Features() << Tp::Connection::FeatureCore
<< Tp::Connection::FeatureSelfContact
);
Tp::ChannelFactoryPtr channelFactory = Tp::ChannelFactory::create(QDBusConnection::sessionBus());
channelFactory->addCommonFeatures(Tp::Channel::FeatureCore);
channelFactory->addFeaturesForCalls(Tp::Features() << Tp::CallChannel::FeatureContents
<< Tp::CallChannel::FeatureCallState
<< Tp::CallChannel::FeatureCallMembers
<< Tp::CallChannel::FeatureLocalHoldState
);
Tp::ContactFactoryPtr contactFactory = Tp::ContactFactory::create(Tp::Features() << Tp::Contact::FeatureAlias
<< Tp::Contact::FeatureAvatarData
);
// app.setQuitOnLastWindowClosed(true);
Tp::ClientRegistrarPtr registrar =
Tp::ClientRegistrar::create(accountFactory, connectionFactory,
channelFactory, contactFactory);
Tp::SharedPtr<CallHandler> callHandler(new CallHandler(dialerUtils));
registrar->registerClient(Tp::AbstractClientPtr::dynamicCast(callHandler), "Phone.Dialer");
return app.exec(); return app.exec();
} }

View file

@ -0,0 +1,3 @@
[D-BUS Service]
Name=org.freedesktop.Telepathy.Client.Plasma.Dialer
Exec=@CMAKE_INSTALL_PREFIX@/plasmaphonedialer