1 /*
2 * SingleApplicationDBus.cpp
3 * Copyright (C) 2017 Belledonne Communications, Grenoble, France
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 * Created on: June 20, 2017
20 * Author: Ghislain MARY
21 */
22
23 #include <cstdlib>
24 #include <iostream>
25
26 #include <QtCore/QByteArray>
27 #include <QtDBus/QtDBus>
28
29 #include "SingleApplication.hpp"
30 #include "SingleApplicationDBusPrivate.hpp"
31
32 // =============================================================================
33
34 const char *SERVICE_NAME = "org.linphone.SingleApplication";
35
SingleApplicationPrivate(SingleApplication * q_ptr)36 SingleApplicationPrivate::SingleApplicationPrivate (SingleApplication *q_ptr)
37 : QDBusAbstractAdaptor(q_ptr), q_ptr(q_ptr) {}
38
getBus() const39 QDBusConnection SingleApplicationPrivate::getBus () const {
40 if (options & SingleApplication::Mode::User)
41 return QDBusConnection::sessionBus();
42
43 return QDBusConnection::systemBus();
44 }
45
startPrimary()46 void SingleApplicationPrivate::startPrimary () {
47 if (!getBus().registerObject("/", this, QDBusConnection::ExportAllSlots))
48 qWarning() << QStringLiteral("Failed to register single application object on DBus.");
49 instanceNumber = 0;
50 }
51
startSecondary()52 void SingleApplicationPrivate::startSecondary () {
53 instanceNumber = 1;
54 }
55
SingleApplication(int & argc,char * argv[],bool allowSecondary,Options options,int)56 SingleApplication::SingleApplication (int &argc, char *argv[], bool allowSecondary, Options options, int)
57 : QApplication(argc, argv), d_ptr(new SingleApplicationPrivate(this)) {
58 Q_D(SingleApplication);
59
60 // Store the current mode of the program
61 d->options = options;
62
63 if (!d->getBus().isConnected()) {
64 qWarning() << QStringLiteral("Cannot connect to the D-Bus session bus.");
65 delete d;
66 ::exit(EXIT_FAILURE);
67 }
68
69 if (d->getBus().registerService(SERVICE_NAME)) {
70 d->startPrimary();
71 return;
72 }
73
74 if (allowSecondary) {
75 d->startSecondary();
76 return;
77 }
78
79 delete d;
80 ::exit(EXIT_SUCCESS);
81 }
82
~SingleApplication()83 SingleApplication::~SingleApplication () {
84 Q_D(SingleApplication);
85 delete d;
86 }
87
isPrimary()88 bool SingleApplication::isPrimary () {
89 Q_D(SingleApplication);
90 return d->instanceNumber == 0;
91 }
92
isSecondary()93 bool SingleApplication::isSecondary () {
94 Q_D(SingleApplication);
95 return d->instanceNumber != 0;
96 }
97
instanceId()98 quint32 SingleApplication::instanceId () {
99 Q_D(SingleApplication);
100 return d->instanceNumber;
101 }
102
sendMessage(QByteArray message,int timeout)103 bool SingleApplication::sendMessage (QByteArray message, int timeout) {
104 Q_D(SingleApplication);
105
106 if (isPrimary()) return false;
107
108 QDBusInterface iface(SERVICE_NAME, "/", "", d->getBus());
109 if (iface.isValid()) {
110 iface.setTimeout(timeout);
111 QDBusMessage msg = iface.call(QDBus::Block, "messageReceived", instanceId(), message);
112 return true;
113 }
114
115 return false;
116 }
117
messageReceived(quint32 instanceId,QByteArray message)118 void SingleApplicationPrivate::messageReceived (quint32 instanceId, QByteArray message) {
119 Q_Q(SingleApplication);
120 Q_EMIT q->receivedMessage(instanceId, message);
121 }
122
quit()123 void SingleApplication::quit () {
124 QCoreApplication::quit();
125 }
126