Removed dbus support.
Added unix signals support.
This commit is contained in:
26
README.md
26
README.md
@@ -29,37 +29,32 @@ official CMA and also offer some features missing in the original one.
|
|||||||
## Headless version
|
## Headless version
|
||||||
|
|
||||||
There is a qcma_cli binary that doesn't need a X session running (useful for servers).
|
There is a qcma_cli binary that doesn't need a X session running (useful for servers).
|
||||||
The daemon provides minimal interaction via dbus. Here are some usage examples:
|
The daemon provides minimal interaction via unix signals. Here are some usage examples:
|
||||||
|
|
||||||
#### Send a signal to refresh the database
|
#### Send a signal to refresh the database
|
||||||
|
|
||||||
```
|
```
|
||||||
dbus-send --session --type=method_call --dest=org.qcma.HeadlessManager /HeadlessManager org.qcma.HeadlessManager.refreshDatabase
|
kill -HUP $(pgrep qcma_cli)
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Send a signal to stop the daemon
|
#### Send a signal to stop the daemon
|
||||||
|
|
||||||
```
|
```
|
||||||
dbus-send --session --type=method_call --dest=org.qcma.HeadlessManager /HeadlessManager org.qcma.HeadlessManager.stop
|
kill $(pgrep qcma_cli)
|
||||||
```
|
|
||||||
|
|
||||||
#### Receive confirmation when the database finished updating
|
|
||||||
|
|
||||||
```
|
|
||||||
dbus-monitor "type='signal',sender='org.qcma.HeadlessManager',member='databaseUpdated'"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
* [Qt 4.x or 5.x](http://qt-project.org/)
|
* [Qt 4.x or 5.x](http://www.qt.io/)
|
||||||
|
|
||||||
* [VitaMTP fork](https://github.com/codestation/VitaMTP)
|
* [VitaMTP fork](https://github.com/codestation/vitamtp)
|
||||||
|
|
||||||
* [FFmpeg](http://www.ffmpeg.org/)
|
* [FFmpeg](http://www.ffmpeg.org/)
|
||||||
|
|
||||||
* [libnotify](http://library.gnome.org/devel/notification-spec/)
|
* [libnotify](http://library.gnome.org/devel/notification-spec/)
|
||||||
|
|
||||||
* [libappindicator](https://launchpad.net/libappindicator)
|
* [libappindicator (optional)](https://launchpad.net/libappindicator)
|
||||||
|
|
||||||
|
* [KNotifications (optional)](https://projects.kde.org/projects/frameworks/knotifications)
|
||||||
|
|
||||||
#### Where do I get the source code?
|
#### Where do I get the source code?
|
||||||
Check the GitHub repo here: https://github.com/codestation/qcma
|
Check the GitHub repo here: https://github.com/codestation/qcma
|
||||||
@@ -71,10 +66,7 @@ Contact me on [GitHub](https://github.com/codestation/)
|
|||||||
[Yifan Lu](https://github.com/yifanlu/vitamtp/) - for the vitamtp library and
|
[Yifan Lu](https://github.com/yifanlu/vitamtp/) - for the vitamtp library and
|
||||||
the reference implementation of OpenCMA.
|
the reference implementation of OpenCMA.
|
||||||
|
|
||||||
[Xian Nox] (https://github.com/xiannox) - for the Wiki and various contributions.
|
Other contributors: check [here](https://github.com/codestation/qcma/graphs/contributors)
|
||||||
|
|
||||||
[173210] (https://github.com/173210) - japanese translations.
|
|
||||||
|
|
||||||
#### License
|
#### License
|
||||||
GPL v3: since some parts of QCMA are based on the reference implementation of
|
GPLv3
|
||||||
OpenCMA.
|
|
||||||
|
2
qcma.6
2
qcma.6
@@ -8,7 +8,7 @@ qcma \- Content manager for the PlayStation Vita
|
|||||||
\fBqcma\fR is a cross-platform application to provide an Open Source implementation
|
\fBqcma\fR is a cross-platform application to provide an Open Source implementation
|
||||||
of the original Content Manager Assistant that comes with the PS Vita.
|
of the original Content Manager Assistant that comes with the PS Vita.
|
||||||
.TP
|
.TP
|
||||||
QCMA will let you backup your games, songs, photos & videos via USB or wireless.
|
Qcma will let you backup your games, songs, photos & videos via USB or wireless.
|
||||||
|
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
.I /usr/share/doc/qcma/README.md
|
.I /usr/share/doc/qcma/README.md
|
||||||
|
2
qcma.pro
2
qcma.pro
@@ -12,7 +12,7 @@ android {
|
|||||||
SUBDIRS = qcma_gui.pro
|
SUBDIRS = qcma_gui.pro
|
||||||
}
|
}
|
||||||
|
|
||||||
# Compile the headless binary only on Linux because it depends on dbus
|
# Compile the headless binary only on Linux
|
||||||
unix:!macx:!android {
|
unix:!macx:!android {
|
||||||
SUBDIRS += qcma_cli.pro
|
SUBDIRS += qcma_cli.pro
|
||||||
# The appindicator and kde extensions are linux only too
|
# The appindicator and kde extensions are linux only too
|
||||||
|
21
qcma_cli.6
21
qcma_cli.6
@@ -8,23 +8,26 @@ qcma-cli \- Content manager for the PlayStation Vita
|
|||||||
.B \-\-verbose
|
.B \-\-verbose
|
||||||
print detailed output
|
print detailed output
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-\-with-debug
|
||||||
|
print very verbose output (including hexdump transfers)
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
\fBqcma_cli\fR is a cross-platform application to provide an Open Source implementation
|
\fBqcma_cli\fR is a cross-platform application to provide an Open Source implementation
|
||||||
of the original Content Manager Assistant that comes with the PS Vita.
|
of the original Content Manager Assistant that comes with the PS Vita.
|
||||||
.TP
|
.TP
|
||||||
QCMA will let you backup your games, songs, photos & videos via USB or wireless.
|
Qcma will let you backup your games, songs, photos & videos via USB or wireless.
|
||||||
|
|
||||||
.SH COMMANDS
|
.SH SIGNALS
|
||||||
You can control qcma_cli over DBus:
|
You can control \fBqcma_cli\fR using signals, i.e. using the \fBkill\fR command to send a signal to the process.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
Send a signal to refresh the database:
|
.B SIGHUP
|
||||||
.BR
|
Refreshes the database.
|
||||||
dbus-send \-\-session \-\-type=method_call \-\-dest=org.qcma.HeadlessManager /HeadlessManager org.qcma.HeadlessManager.refreshDatabase
|
|
||||||
.TP
|
.TP
|
||||||
Send a signal to stop the daemon:
|
.B SIGTERM
|
||||||
.BR
|
Shuts down the process but waits until the current event is finished.
|
||||||
dbus-send \-\-session \-\-type=method_call \-\-dest=org.qcma.HeadlessManager /HeadlessManager org.qcma.HeadlessManager.stop
|
|
||||||
|
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
.I /usr/share/doc/qcma/README.md
|
.I /usr/share/doc/qcma/README.md
|
||||||
|
12
qcma_cli.pro
12
qcma_cli.pro
@@ -1,7 +1,5 @@
|
|||||||
include(qcma_common.pri)
|
include(qcma_common.pri)
|
||||||
|
|
||||||
unix:!macx:QT += dbus
|
|
||||||
|
|
||||||
TARGET = qcma_cli
|
TARGET = qcma_cli
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
@@ -19,13 +17,3 @@ unix:!macx {
|
|||||||
|
|
||||||
INSTALLS += target
|
INSTALLS += target
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create the introspection XML
|
|
||||||
QT5_SUFFIX {
|
|
||||||
system(qdbuscpp2xml-qt5 -M -s src/cli/headlessmanager.h -o org.qcma.HeadlessManager.xml)
|
|
||||||
} else {
|
|
||||||
system(qdbuscpp2xml -M -s src/cli/headlessmanager.h -o org.qcma.HeadlessManager.xml)
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create the helper class
|
|
||||||
DBUS_ADAPTORS = org.qcma.HeadlessManager.xml
|
|
||||||
|
12
qcma_gui.pro
12
qcma_gui.pro
@@ -59,15 +59,3 @@ unix:!macx {
|
|||||||
|
|
||||||
INSTALLS += target desktop icon64
|
INSTALLS += target desktop icon64
|
||||||
}
|
}
|
||||||
|
|
||||||
unix:!macx {
|
|
||||||
QT += dbus
|
|
||||||
# Create the introspection XML
|
|
||||||
QT5_SUFFIX {
|
|
||||||
system(qdbuscpp2xml-qt5 -M -s src/gui/mainwidget.h -o org.qcma.ClientManager.xml)
|
|
||||||
} else {
|
|
||||||
system(qdbuscpp2xml -M -s src/gui/mainwidget.h -o org.qcma.ClientManager.xml)
|
|
||||||
}
|
|
||||||
# Create the helper class
|
|
||||||
DBUS_ADAPTORS = org.qcma.ClientManager.xml
|
|
||||||
}
|
|
||||||
|
@@ -22,20 +22,29 @@
|
|||||||
#include "sqlitedb.h"
|
#include "sqlitedb.h"
|
||||||
#include "qlistdb.h"
|
#include "qlistdb.h"
|
||||||
#include "headlessmanager.h"
|
#include "headlessmanager.h"
|
||||||
#include "headlessmanager_adaptor.h"
|
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <vitamtp.h>
|
#include <vitamtp.h>
|
||||||
|
|
||||||
|
int HeadlessManager::sighup_fd[2];
|
||||||
|
int HeadlessManager::sigterm_fd[2];
|
||||||
|
|
||||||
HeadlessManager::HeadlessManager(QObject *obj_parent) :
|
HeadlessManager::HeadlessManager(QObject *obj_parent) :
|
||||||
QObject(obj_parent), dbus_conn(QDBusConnection::sessionBus())
|
QObject(obj_parent)
|
||||||
{
|
{
|
||||||
new HeadlessManagerAdaptor(this);
|
if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sighup_fd))
|
||||||
QDBusConnection dbus = QDBusConnection::sessionBus();
|
qFatal("Couldn't create HUP socketpair");
|
||||||
// expose qcma over dbus so the database update can be triggered
|
|
||||||
dbus.registerObject("/HeadlessManager", this);
|
if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigterm_fd))
|
||||||
dbus.registerService("org.qcma.HeadlessManager");
|
qFatal("Couldn't create TERM socketpair");
|
||||||
|
|
||||||
|
sn_hup = new QSocketNotifier(sighup_fd[1], QSocketNotifier::Read, this);
|
||||||
|
connect(sn_hup, SIGNAL(activated(int)), this, SLOT(handleSigHup()));
|
||||||
|
sn_term = new QSocketNotifier(sigterm_fd[1], QSocketNotifier::Read, this);
|
||||||
|
connect(sn_term, SIGNAL(activated(int)), this, SLOT(handleSigTerm()));
|
||||||
}
|
}
|
||||||
|
|
||||||
HeadlessManager::~HeadlessManager()
|
HeadlessManager::~HeadlessManager()
|
||||||
@@ -71,7 +80,7 @@ void HeadlessManager::start()
|
|||||||
// initializing database for the first use
|
// initializing database for the first use
|
||||||
refreshDatabase();
|
refreshDatabase();
|
||||||
|
|
||||||
// send a signal over dbus of the connected peers knows when the update is finished
|
// send a signal when the update is finished
|
||||||
connect(m_db, SIGNAL(updated(int)), this, SIGNAL(databaseUpdated(int)));
|
connect(m_db, SIGNAL(updated(int)), this, SIGNAL(databaseUpdated(int)));
|
||||||
|
|
||||||
thread_count = 0;
|
thread_count = 0;
|
||||||
@@ -134,3 +143,37 @@ void HeadlessManager::threadStopped()
|
|||||||
}
|
}
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HeadlessManager::hupSignalHandler(int)
|
||||||
|
{
|
||||||
|
char a = 1;
|
||||||
|
::write(sighup_fd[0], &a, sizeof(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeadlessManager::termSignalHandler(int)
|
||||||
|
{
|
||||||
|
char a = 1;
|
||||||
|
::write(sigterm_fd[0], &a, sizeof(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeadlessManager::handleSigTerm()
|
||||||
|
{
|
||||||
|
sn_term->setEnabled(false);
|
||||||
|
char tmp;
|
||||||
|
::read(sigterm_fd[1], &tmp, sizeof(tmp));
|
||||||
|
|
||||||
|
stop();
|
||||||
|
|
||||||
|
sn_term->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeadlessManager::handleSigHup()
|
||||||
|
{
|
||||||
|
sn_hup->setEnabled(false);
|
||||||
|
char tmp;
|
||||||
|
::read(sighup_fd[1], &tmp, sizeof(tmp));
|
||||||
|
|
||||||
|
refreshDatabase();
|
||||||
|
|
||||||
|
sn_hup->setEnabled(true);
|
||||||
|
}
|
||||||
|
@@ -24,12 +24,11 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QDBusConnection>
|
#include <QSocketNotifier>
|
||||||
|
|
||||||
class HeadlessManager : public QObject
|
class HeadlessManager : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_CLASSINFO("D-Bus Interface", "org.qcma.HeadlessManager")
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit HeadlessManager(QObject *parent = 0);
|
explicit HeadlessManager(QObject *parent = 0);
|
||||||
@@ -37,6 +36,10 @@ public:
|
|||||||
|
|
||||||
void start();
|
void start();
|
||||||
|
|
||||||
|
// unix signal handlers
|
||||||
|
static void hupSignalHandler(int);
|
||||||
|
static void termSignalHandler(int);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int thread_count;
|
int thread_count;
|
||||||
QMutex mutex;
|
QMutex mutex;
|
||||||
@@ -45,16 +48,26 @@ private:
|
|||||||
|
|
||||||
QThread *usb_thread;
|
QThread *usb_thread;
|
||||||
QThread *wireless_thread;
|
QThread *wireless_thread;
|
||||||
QDBusConnection dbus_conn;
|
|
||||||
|
// signal handling
|
||||||
|
static int sighup_fd[2];
|
||||||
|
static int sigterm_fd[2];
|
||||||
|
|
||||||
|
QSocketNotifier *sn_hup;
|
||||||
|
QSocketNotifier *sn_term;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void stopped();
|
void stopped();
|
||||||
Q_SCRIPTABLE void databaseUpdated(int count);
|
void databaseUpdated(int count);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void refreshDatabase();
|
void refreshDatabase();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
// Qt signal handlers
|
||||||
|
void handleSigHup();
|
||||||
|
void handleSigTerm();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void threadStopped();
|
void threadStopped();
|
||||||
};
|
};
|
||||||
|
@@ -47,20 +47,47 @@ static void noMessageOutput(QtMsgType type, const char *msg)
|
|||||||
Q_UNUSED(msg);
|
Q_UNUSED(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool setup_handlers()
|
||||||
|
{
|
||||||
|
struct sigaction hup, term;
|
||||||
|
|
||||||
|
hup.sa_handler = HeadlessManager::hupSignalHandler;
|
||||||
|
sigemptyset(&hup.sa_mask);
|
||||||
|
hup.sa_flags = 0;
|
||||||
|
hup.sa_flags |= SA_RESTART;
|
||||||
|
|
||||||
|
if (sigaction(SIGHUP, &hup, NULL) != 0) {
|
||||||
|
qCritical("SIGHUP signal handle failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
term.sa_handler = HeadlessManager::termSignalHandler;
|
||||||
|
sigemptyset(&term.sa_mask);
|
||||||
|
term.sa_flags |= SA_RESTART;
|
||||||
|
|
||||||
|
if (sigaction(SIGTERM, &term, NULL) != 0) {
|
||||||
|
qCritical("SIGTERM signal handle failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
if(SingleCoreApplication::sendMessage(QObject::tr("A instance of QCMA is already running"))) {
|
if(SingleCoreApplication::sendMessage(QObject::tr("An instance of Qcma is already running"))) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SingleCoreApplication app(argc, argv);
|
SingleCoreApplication app(argc, argv);
|
||||||
|
|
||||||
#ifndef Q_OS_WIN32
|
|
||||||
// FIXME: libmtp sends SIGPIPE if a socket write fails crashing the whole app
|
// FIXME: libmtp sends SIGPIPE if a socket write fails crashing the whole app
|
||||||
// the proper fix is to libmtp to handle the cancel properly or ignoring
|
// the proper fix is to libmtp to handle the cancel properly or ignoring
|
||||||
// SIGPIPE on the socket
|
// SIGPIPE on the socket
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
#endif
|
|
||||||
|
if(!setup_handlers())
|
||||||
|
return 1;
|
||||||
|
|
||||||
if(app.arguments().contains("--with-debug")) {
|
if(app.arguments().contains("--with-debug")) {
|
||||||
VitaMTP_Set_Logging(VitaMTP_DEBUG);
|
VitaMTP_Set_Logging(VitaMTP_DEBUG);
|
||||||
@@ -79,7 +106,7 @@ int main(int argc, char *argv[])
|
|||||||
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
|
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
qDebug("Starting QCMA %s", QCMA_VER);
|
QTextStream(stdout) << "Starting Qcma " << QCMA_VER << endl;
|
||||||
|
|
||||||
QTranslator translator;
|
QTranslator translator;
|
||||||
QString locale = QLocale().system().name();
|
QString locale = QLocale().system().name();
|
||||||
|
@@ -26,9 +26,29 @@
|
|||||||
|
|
||||||
#include <vitamtp.h>
|
#include <vitamtp.h>
|
||||||
|
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int ClientManager::sighup_fd[2];
|
||||||
|
int ClientManager::sigterm_fd[2];
|
||||||
|
#endif
|
||||||
|
|
||||||
ClientManager::ClientManager(Database *db, QObject *obj_parent) :
|
ClientManager::ClientManager(Database *db, QObject *obj_parent) :
|
||||||
QObject(obj_parent), m_db(db)
|
QObject(obj_parent), m_db(db)
|
||||||
{
|
{
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sighup_fd))
|
||||||
|
qFatal("Couldn't create HUP socketpair");
|
||||||
|
|
||||||
|
if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigterm_fd))
|
||||||
|
qFatal("Couldn't create TERM socketpair");
|
||||||
|
|
||||||
|
sn_hup = new QSocketNotifier(sighup_fd[1], QSocketNotifier::Read, this);
|
||||||
|
connect(sn_hup, SIGNAL(activated(int)), this, SLOT(handleSigHup()));
|
||||||
|
sn_term = new QSocketNotifier(sigterm_fd[1], QSocketNotifier::Read, this);
|
||||||
|
connect(sn_term, SIGNAL(activated(int)), this, SLOT(handleSigTerm()));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientManager::~ClientManager()
|
ClientManager::~ClientManager()
|
||||||
@@ -150,3 +170,39 @@ void ClientManager::threadStopped()
|
|||||||
}
|
}
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
void ClientManager::hupSignalHandler(int)
|
||||||
|
{
|
||||||
|
char a = 1;
|
||||||
|
::write(sighup_fd[0], &a, sizeof(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientManager::termSignalHandler(int)
|
||||||
|
{
|
||||||
|
char a = 1;
|
||||||
|
::write(sigterm_fd[0], &a, sizeof(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientManager::handleSigTerm()
|
||||||
|
{
|
||||||
|
sn_term->setEnabled(false);
|
||||||
|
char tmp;
|
||||||
|
::read(sigterm_fd[1], &tmp, sizeof(tmp));
|
||||||
|
|
||||||
|
stop();
|
||||||
|
|
||||||
|
sn_term->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientManager::handleSigHup()
|
||||||
|
{
|
||||||
|
sn_hup->setEnabled(false);
|
||||||
|
char tmp;
|
||||||
|
::read(sighup_fd[1], &tmp, sizeof(tmp));
|
||||||
|
|
||||||
|
refreshDatabase();
|
||||||
|
|
||||||
|
sn_hup->setEnabled(true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@@ -27,6 +27,10 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
#include <QSocketNotifier>
|
||||||
|
#endif
|
||||||
|
|
||||||
class ClientManager : public QObject
|
class ClientManager : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -37,6 +41,12 @@ public:
|
|||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
// unix signal handlers
|
||||||
|
static void hupSignalHandler(int);
|
||||||
|
static void termSignalHandler(int);
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int thread_count;
|
int thread_count;
|
||||||
QMutex mutex;
|
QMutex mutex;
|
||||||
@@ -49,6 +59,15 @@ private:
|
|||||||
QThread *usb_thread;
|
QThread *usb_thread;
|
||||||
QThread *wireless_thread;
|
QThread *wireless_thread;
|
||||||
|
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
// signal handling
|
||||||
|
static int sighup_fd[2];
|
||||||
|
static int sigterm_fd[2];
|
||||||
|
|
||||||
|
QSocketNotifier *sn_hup;
|
||||||
|
QSocketNotifier *sn_term;
|
||||||
|
#endif
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void updated(int);
|
void updated(int);
|
||||||
void stopped();
|
void stopped();
|
||||||
@@ -60,6 +79,12 @@ signals:
|
|||||||
public slots:
|
public slots:
|
||||||
void refreshDatabase();
|
void refreshDatabase();
|
||||||
|
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
// Qt signal handlers
|
||||||
|
void handleSigHup();
|
||||||
|
void handleSigTerm();
|
||||||
|
#endif
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void threadStopped();
|
void threadStopped();
|
||||||
void databaseUpdated(int count);
|
void databaseUpdated(int count);
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
#include <QLibraryInfo>
|
#include <QLibraryInfo>
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
#include <QTextCodec>
|
#include <QTextCodec>
|
||||||
|
#include <QTextStream>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QTranslator>
|
#include <QTranslator>
|
||||||
|
|
||||||
@@ -45,9 +46,36 @@ static void noMessageOutput(QtMsgType type, const char *msg)
|
|||||||
Q_UNUSED(msg);
|
Q_UNUSED(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool setup_handlers()
|
||||||
|
{
|
||||||
|
struct sigaction hup, term;
|
||||||
|
|
||||||
|
hup.sa_handler = ClientManager::hupSignalHandler;
|
||||||
|
sigemptyset(&hup.sa_mask);
|
||||||
|
hup.sa_flags = 0;
|
||||||
|
hup.sa_flags |= SA_RESTART;
|
||||||
|
|
||||||
|
if (sigaction(SIGHUP, &hup, NULL) != 0) {
|
||||||
|
qCritical("SIGHUP signal handle failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
term.sa_handler = ClientManager::termSignalHandler;
|
||||||
|
sigemptyset(&term.sa_mask);
|
||||||
|
term.sa_flags |= SA_RESTART;
|
||||||
|
|
||||||
|
if (sigaction(SIGTERM, &term, NULL) != 0) {
|
||||||
|
qCritical("SIGTERM signal handle failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
if(SingleApplication::sendMessage(QObject::tr("A instance of QCMA is already running"))) {
|
if(SingleApplication::sendMessage(QObject::tr("An instance of Qcma is already running"))) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,6 +88,8 @@ int main(int argc, char *argv[])
|
|||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
setup_handlers();
|
||||||
|
|
||||||
if(app.arguments().contains("--with-debug")) {
|
if(app.arguments().contains("--with-debug")) {
|
||||||
VitaMTP_Set_Logging(VitaMTP_DEBUG);
|
VitaMTP_Set_Logging(VitaMTP_DEBUG);
|
||||||
} else if(app.arguments().contains("--verbose")) {
|
} else if(app.arguments().contains("--verbose")) {
|
||||||
@@ -77,7 +107,7 @@ int main(int argc, char *argv[])
|
|||||||
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
|
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
qDebug("Starting QCMA %s", QCMA_VER);
|
QTextStream(stdout) << "Starting Qcma " << QCMA_VER << endl;
|
||||||
|
|
||||||
QTranslator translator;
|
QTranslator translator;
|
||||||
QString locale = QLocale().system().name();
|
QString locale = QLocale().system().name();
|
||||||
|
@@ -21,10 +21,6 @@
|
|||||||
#include "cmaclient.h"
|
#include "cmaclient.h"
|
||||||
#include "cmautils.h"
|
#include "cmautils.h"
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
#include "clientmanager_adaptor.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "qlistdb.h"
|
#include "qlistdb.h"
|
||||||
#include "sqlitedb.h"
|
#include "sqlitedb.h"
|
||||||
|
|
||||||
@@ -34,6 +30,7 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
|
#include <QLibrary>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
@@ -44,24 +41,11 @@ const QStringList MainWidget::path_list = QStringList() << "photoPath" << "music
|
|||||||
|
|
||||||
bool sleptOnce = false;
|
bool sleptOnce = false;
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
MainWidget::MainWidget(QWidget *obj_parent) :
|
MainWidget::MainWidget(QWidget *obj_parent) :
|
||||||
QWidget(obj_parent), db(NULL), configForm(NULL), managerForm(NULL), backupForm(NULL), dbus_conn(QDBusConnection::sessionBus())
|
QWidget(obj_parent), db(NULL), configForm(NULL), managerForm(NULL), backupForm(NULL)
|
||||||
{
|
|
||||||
new ClientManagerAdaptor(this);
|
|
||||||
QDBusConnection dbus = QDBusConnection::sessionBus();
|
|
||||||
// expose qcma over dbus so the database update can be triggered
|
|
||||||
dbus.registerObject("/ClientManager", this);
|
|
||||||
dbus.registerService("org.qcma.ClientManager");
|
|
||||||
trayIcon = NULL;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
MainWidget::MainWidget(QWidget *parent) :
|
|
||||||
QWidget(parent), db(NULL), configForm(NULL), managerForm(NULL), backupForm(NULL)
|
|
||||||
{
|
{
|
||||||
trayIcon = NULL;
|
trayIcon = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void MainWidget::checkSettings()
|
void MainWidget::checkSettings()
|
||||||
{
|
{
|
||||||
|
@@ -31,10 +31,6 @@
|
|||||||
|
|
||||||
#include <QSystemTrayIcon>
|
#include <QSystemTrayIcon>
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
#include <QDBusConnection>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <vitamtp.h>
|
#include <vitamtp.h>
|
||||||
|
|
||||||
class TrayIndicator;
|
class TrayIndicator;
|
||||||
@@ -42,7 +38,6 @@ class TrayIndicator;
|
|||||||
class MainWidget : public QWidget
|
class MainWidget : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_CLASSINFO("D-Bus Interface", "org.qcma.ClientManager")
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit MainWidget(QWidget *parent = 0);
|
explicit MainWidget(QWidget *parent = 0);
|
||||||
@@ -66,19 +61,15 @@ private:
|
|||||||
ClientManager *managerForm;
|
ClientManager *managerForm;
|
||||||
BackupManagerForm *backupForm;
|
BackupManagerForm *backupForm;
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
QDBusConnection dbus_conn;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
TrayIndicator *trayIcon;
|
TrayIndicator *trayIcon;
|
||||||
|
|
||||||
const static QStringList path_list;
|
const static QStringList path_list;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
Q_SCRIPTABLE void deviceConnected(QString);
|
void deviceConnected(QString);
|
||||||
Q_SCRIPTABLE void deviceDisconnected();
|
void deviceDisconnected();
|
||||||
Q_SCRIPTABLE void databaseUpdated(int count);
|
void databaseUpdated(int count);
|
||||||
Q_SCRIPTABLE void messageReceived(QString message);
|
void messageReceived(QString message);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void openConfig();
|
void openConfig();
|
||||||
|
@@ -1,11 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=D-Bus User Message Bus
|
|
||||||
Documentation=man:dbus-daemon(1)
|
|
||||||
Requires=dbus.socket
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
ExecStart=/usr/bin/dbus-daemon --session --address=systemd: --nofork --systemd-activation
|
|
||||||
ExecReload=/usr/bin/dbus-send --print-reply --session --type=method_call --dest=org.freedesktop.DBus / org.freedesktop.DBus.ReloadConfig
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
Also=dbus.socket
|
|
@@ -1,9 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=D-Bus User Message Bus Socket
|
|
||||||
|
|
||||||
[Socket]
|
|
||||||
ListenStream=%t/bus
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=sockets.target
|
|
||||||
Also=dbus.service
|
|
@@ -5,7 +5,7 @@ ConditionPathExists=%h/.config/codestation/qcma.conf
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
ExecStart=/usr/bin/qcma_cli --verbose
|
ExecStart=/usr/bin/qcma_cli --verbose
|
||||||
ExecStop=/usr/bin/dbus-send --print-reply --session --type=method_call --dest=org.qcma.HeadlessManager /HeadlessManager org.qcma.HeadlessManager.stop
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
Alias=qcma_cli.service
|
Alias=qcma_cli.service
|
||||||
|
Reference in New Issue
Block a user