Replace closePreferences with closePerCallerDialog
[skype-call-recorder.git] / skype.cpp
blob9824bb0d5635df23906bac6f8bace6c2411a95b3
1 /*
2 Skype Call Recorder
3 Copyright (C) 2008 jlh (jlh at gmx dot ch)
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2 of the License, version 3 of
8 the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 The GNU General Public License version 2 is included with the source of
20 this program under the file name COPYING. You can also get a copy on
21 http://www.fsf.org/
24 #include <QList>
25 #include <QVariant>
26 #include <QTimer>
27 #include <QtDBus>
29 #include "skype.h"
30 #include "common.h"
32 namespace {
33 const QString skypeServiceName("com.Skype.API");
34 const QString skypeInterfaceName("com.Skype.API");
37 Skype::Skype(QObject *parent) : QObject(parent), dbus("SkypeRecorder"), connectionState(0) {
38 dbus = QDBusConnection::connectToBus(QDBusConnection::SessionBus, "SkypeRecorder");
40 connect(dbus.interface(), SIGNAL(serviceOwnerChanged(const QString &, const QString &, const QString &)),
41 this, SLOT(serviceOwnerChanged(const QString &, const QString &, const QString &)));
43 // export our object
44 exported = new SkypeExport(this);
45 if (!dbus.registerObject("/com/Skype/Client", this))
46 debug("Cannot register object /com/Skype/Client");
48 timer = new QTimer(this);
49 timer->setInterval(5000);
50 connect(timer, SIGNAL(timeout()), this, SLOT(poll()));
52 QTimer::singleShot(0, this, SLOT(connectToSkype()));
55 void Skype::connectToSkype() {
56 if (connectionState)
57 return;
59 QDBusReply<bool> exists = dbus.interface()->isServiceRegistered(skypeServiceName);
61 if (!exists.isValid() || !exists.value()) {
62 timer->stop();
64 debug(QString("Service %1 not found on DBus").arg(skypeServiceName));
65 return;
68 if (!timer->isActive())
69 timer->start();
71 sendWithAsyncReply("NAME SkypeCallRecorder");
72 connectionState = 1;
75 void Skype::serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner) {
76 if (name != skypeServiceName)
77 return;
79 if (oldOwner.isEmpty()) {
80 debug(QString("DBUS: Skype API service appeared as %1").arg(newOwner));
81 if (connectionState != 3)
82 connectToSkype();
83 } else if (newOwner.isEmpty()) {
84 debug("DBUS: Skype API service disappeared");
85 if (connectionState == 3)
86 emit connected(false);
87 timer->stop();
88 connectionState = 0;
92 void Skype::sendWithAsyncReply(const QString &s) {
93 debug(QString("SKYPE --> %1 (async reply)").arg(s));
95 QDBusMessage msg = QDBusMessage::createMethodCall(skypeServiceName, "/com/Skype", skypeInterfaceName, "Invoke");
96 QList<QVariant> args;
97 args.append(s);
98 msg.setArguments(args);
100 dbus.callWithCallback(msg, this, SLOT(methodCallback(const QDBusMessage &)), SLOT(methodError(const QDBusError &, const QDBusMessage &)), 3600000);
103 QString Skype::sendWithReply(const QString &s, int timeout) {
104 debug(QString("SKYPE --> %1 (sync reply)").arg(s));
106 QDBusMessage msg = QDBusMessage::createMethodCall(skypeServiceName, "/com/Skype", skypeInterfaceName, "Invoke");
107 QList<QVariant> args;
108 args.append(s);
109 msg.setArguments(args);
111 msg = dbus.call(msg, QDBus::Block, timeout);
113 if (msg.type() != QDBusMessage::ReplyMessage) {
114 debug(QString("SKYPE <R- (failed)"));
115 return QString();
118 QString ret = msg.arguments().value(0).toString();
119 debug(QString("SKYPE <R- %1").arg(ret));
120 return ret;
123 void Skype::send(const QString &s) {
124 debug(QString("SKYPE --> %1 (no reply)").arg(s));
126 QDBusMessage msg = QDBusMessage::createMethodCall(skypeServiceName, "/com/Skype", skypeInterfaceName, "Invoke");
127 QList<QVariant> args;
128 args.append(s);
129 msg.setArguments(args);
131 dbus.call(msg, QDBus::NoBlock);
134 QString Skype::getObject(const QString &object) {
135 QString ret = sendWithReply("GET " + object);
136 if (!ret.startsWith(object))
137 return QString();
138 return ret.mid(object.size() + 1);
141 void Skype::methodCallback(const QDBusMessage &msg) {
142 if (msg.type() != QDBusMessage::ReplyMessage) {
143 connectionState = 0;
144 emit connectionFailed("Cannot communicate with Skype");
145 return;
148 QString s = msg.arguments().value(0).toString();
149 debug(QString("SKYPE <R- %1").arg(s));
151 if (connectionState == 1) {
152 if (s == "OK") {
153 connectionState = 2;
154 sendWithAsyncReply("PROTOCOL 5");
155 } else if (s == "CONNSTATUS OFFLINE") {
156 // no user logged in, cannot connect now. from now on,
157 // we have no way of knowing when the user has logged
158 // in and we may again try to connect. this is an
159 // annoying limitation of the Skype API which we work
160 // around be polling
161 connectionState = 0;
162 } else {
163 connectionState = 0;
164 emit connectionFailed("Skype denied access");
166 } else if (connectionState == 2) {
167 if (s == "PROTOCOL 5") {
168 connectionState = 3;
169 emit connected(true);
170 } else {
171 connectionState = 0;
172 emit connectionFailed("Skype handshake error");
177 void Skype::methodError(const QDBusError &error, const QDBusMessage &) {
178 connectionState = 0;
179 emit connectionFailed(error.message());
182 void Skype::doNotify(const QString &s) {
183 if (connectionState != 3)
184 return;
186 debug(QString("SKYPE <-- %1").arg(s));
188 if (s.startsWith("CURRENTUSERHANDLE "))
189 skypeName = s.mid(18);
191 emit notify(s);
194 void Skype::poll() {
195 if (connectionState == 0) {
196 connectToSkype();
197 } else if (connectionState == 3) {
198 if (sendWithReply("PING", 2000) != "PONG") {
199 debug("Skype didn't reply with PONG to our PING");
200 connectionState = 0;
201 emit connected(false);
206 // ---- SkypeExport ----
208 SkypeExport::SkypeExport(Skype *p) : QDBusAbstractAdaptor(p), parent(p) {
211 void SkypeExport::Notify(const QString &s) {
212 parent->doNotify(s);