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
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
&)));
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() {
59 QDBusReply
<bool> exists
= dbus
.interface()->isServiceRegistered(skypeServiceName
);
61 if (!exists
.isValid() || !exists
.value()) {
64 debug(QString("Service %1 not found on DBus").arg(skypeServiceName
));
68 if (!timer
->isActive())
71 sendWithAsyncReply("NAME SkypeCallRecorder");
75 void Skype::serviceOwnerChanged(const QString
&name
, const QString
&oldOwner
, const QString
&newOwner
) {
76 if (name
!= skypeServiceName
)
79 if (oldOwner
.isEmpty()) {
80 debug(QString("DBUS: Skype API service appeared as %1").arg(newOwner
));
81 if (connectionState
!= 3)
83 } else if (newOwner
.isEmpty()) {
84 debug("DBUS: Skype API service disappeared");
85 if (connectionState
== 3)
86 emit
connected(false);
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");
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
;
109 msg
.setArguments(args
);
111 msg
= dbus
.call(msg
, QDBus::Block
, timeout
);
113 if (msg
.type() != QDBusMessage::ReplyMessage
) {
114 debug(QString("SKYPE <R- (failed)"));
118 QString ret
= msg
.arguments().value(0).toString();
119 debug(QString("SKYPE <R- %1").arg(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
;
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
))
138 return ret
.mid(object
.size() + 1);
141 void Skype::methodCallback(const QDBusMessage
&msg
) {
142 if (msg
.type() != QDBusMessage::ReplyMessage
) {
144 emit
connectionFailed("Cannot communicate with Skype");
148 QString s
= msg
.arguments().value(0).toString();
149 debug(QString("SKYPE <R- %1").arg(s
));
151 if (connectionState
== 1) {
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
164 emit
connectionFailed("Skype denied access");
166 } else if (connectionState
== 2) {
167 if (s
== "PROTOCOL 5") {
169 emit
connected(true);
172 emit
connectionFailed("Skype handshake error");
177 void Skype::methodError(const QDBusError
&error
, const QDBusMessage
&) {
179 emit
connectionFailed(error
.message());
182 void Skype::doNotify(const QString
&s
) {
183 if (connectionState
!= 3)
186 debug(QString("SKYPE <-- %1").arg(s
));
188 if (s
.startsWith("CURRENTUSERHANDLE "))
189 skypeName
= s
.mid(18);
195 if (connectionState
== 0) {
197 } else if (connectionState
== 3) {
198 if (sendWithReply("PING", 2000) != "PONG") {
199 debug("Skype didn't reply with PONG to our PING");
201 emit
connected(false);
206 // ---- SkypeExport ----
208 SkypeExport::SkypeExport(Skype
*p
) : QDBusAbstractAdaptor(p
), parent(p
) {
211 void SkypeExport::Notify(const QString
&s
) {