New qcma headless app.
Updated changelog. Bumped version to 0.3.0.
This commit is contained in:
135
src/cli/headlessmanager.cpp
Normal file
135
src/cli/headlessmanager.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* QCMA: Cross-platform content manager assistant for the PS Vita
|
||||
*
|
||||
* Copyright (C) 2013 Codestation
|
||||
*
|
||||
* 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 3 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 "cmaclient.h"
|
||||
#include "cmautils.h"
|
||||
#include "sqlitedb.h"
|
||||
#include "qlistdb.h"
|
||||
#include "headlessmanager.h"
|
||||
#include "headlessmanager_adaptor.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QSettings>
|
||||
#include <vitamtp.h>
|
||||
|
||||
HeadlessManager::HeadlessManager(QObject *parent) :
|
||||
QObject(parent), dbus_conn(QDBusConnection::sessionBus())
|
||||
{
|
||||
new HeadlessManagerAdaptor(this);
|
||||
QDBusConnection dbus = QDBusConnection::sessionBus();
|
||||
// expose qcma over dbus so the database update can be triggered
|
||||
dbus.registerObject("/HeadlessManager", this);
|
||||
dbus.registerService("org.qcma.HeadlessManager");
|
||||
}
|
||||
|
||||
HeadlessManager::~HeadlessManager()
|
||||
{
|
||||
VitaMTP_Cleanup();
|
||||
delete m_db;
|
||||
}
|
||||
|
||||
void HeadlessManager::refreshDatabase()
|
||||
{
|
||||
if(m_db->load()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!m_db->rescan()) {
|
||||
qDebug("No PS Vita system has been registered");
|
||||
}
|
||||
}
|
||||
|
||||
void HeadlessManager::start()
|
||||
{
|
||||
if(VitaMTP_Init() < 0) {
|
||||
qDebug("Cannot initialize VitaMTP library");
|
||||
return;
|
||||
}
|
||||
|
||||
if(QSettings().value("useMemoryStorage", true).toBool()) {
|
||||
m_db = new QListDB();
|
||||
} else {
|
||||
m_db = new SQLiteDB();
|
||||
}
|
||||
|
||||
// initializing database for the first use
|
||||
refreshDatabase();
|
||||
|
||||
// send a signal over dbus of the connected peers knows when the update is finished
|
||||
connect(m_db, SIGNAL(updated(int)), this, SIGNAL(databaseUpdated(int)));
|
||||
|
||||
thread_count = 0;
|
||||
qDebug("Starting cma threads");
|
||||
CmaClient *client;
|
||||
QSettings settings;
|
||||
|
||||
if(!settings.value("disableUSB", false).toBool()) {
|
||||
usb_thread = new QThread();
|
||||
client = new CmaClient(m_db);
|
||||
usb_thread->setObjectName("usb_thread");
|
||||
connect(usb_thread, SIGNAL(started()), client, SLOT(connectUsb()));
|
||||
connect(client, SIGNAL(finished()), usb_thread, SLOT(quit()), Qt::DirectConnection);
|
||||
connect(usb_thread, SIGNAL(finished()), usb_thread, SLOT(deleteLater()));
|
||||
connect(usb_thread, SIGNAL(finished()), this, SLOT(threadStopped()));
|
||||
connect(usb_thread, SIGNAL(finished()), client, SLOT(deleteLater()));
|
||||
|
||||
connect(client, SIGNAL(refreshDatabase()), this, SLOT(refreshDatabase()));
|
||||
|
||||
client->moveToThread(usb_thread);
|
||||
usb_thread->start();
|
||||
thread_count++;
|
||||
}
|
||||
|
||||
if(!settings.value("disableWireless", false).toBool()) {
|
||||
wireless_thread = new QThread();
|
||||
client = new CmaClient(m_db);
|
||||
wireless_thread->setObjectName("wireless_thread");
|
||||
connect(wireless_thread, SIGNAL(started()), client, SLOT(connectWireless()));
|
||||
connect(client, SIGNAL(finished()), wireless_thread, SLOT(quit()), Qt::DirectConnection);
|
||||
connect(wireless_thread, SIGNAL(finished()), wireless_thread, SLOT(deleteLater()));
|
||||
connect(wireless_thread, SIGNAL(finished()), this, SLOT(threadStopped()));
|
||||
connect(wireless_thread, SIGNAL(finished()), client, SLOT(deleteLater()));
|
||||
|
||||
connect(client, SIGNAL(refreshDatabase()), this, SLOT(refreshDatabase()));
|
||||
|
||||
client->moveToThread(wireless_thread);
|
||||
wireless_thread->start();
|
||||
thread_count++;
|
||||
}
|
||||
|
||||
if(thread_count == 0) {
|
||||
qDebug("You must enable at least USB or Wireless monitoring");
|
||||
}
|
||||
}
|
||||
|
||||
void HeadlessManager::stop()
|
||||
{
|
||||
if(CmaClient::stop() < 0) {
|
||||
QCoreApplication::quit();
|
||||
}
|
||||
}
|
||||
|
||||
void HeadlessManager::threadStopped()
|
||||
{
|
||||
mutex.lock();
|
||||
if(--thread_count == 0) {
|
||||
QCoreApplication::quit();
|
||||
}
|
||||
mutex.unlock();
|
||||
}
|
||||
62
src/cli/headlessmanager.h
Normal file
62
src/cli/headlessmanager.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* QCMA: Cross-platform content manager assistant for the PS Vita
|
||||
*
|
||||
* Copyright (C) 2013 Codestation
|
||||
*
|
||||
* 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 3 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 HEADLESSMANAGER_H
|
||||
#define HEADLESSMANAGER_H
|
||||
|
||||
#include "database.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include <QDBusConnection>
|
||||
|
||||
class HeadlessManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.qcma.HeadlessManager")
|
||||
|
||||
public:
|
||||
explicit HeadlessManager(QObject *parent = 0);
|
||||
~HeadlessManager();
|
||||
|
||||
void start();
|
||||
|
||||
private:
|
||||
int thread_count;
|
||||
QMutex mutex;
|
||||
|
||||
Database *m_db;
|
||||
|
||||
QThread *usb_thread;
|
||||
QThread *wireless_thread;
|
||||
QDBusConnection dbus_conn;
|
||||
|
||||
signals:
|
||||
void stopped();
|
||||
Q_SCRIPTABLE void databaseUpdated(int count);
|
||||
|
||||
public slots:
|
||||
void refreshDatabase();
|
||||
void stop();
|
||||
|
||||
private slots:
|
||||
void threadStopped();
|
||||
};
|
||||
|
||||
#endif // HEADLESSMANAGER_H
|
||||
115
src/cli/main_cli.cpp
Normal file
115
src/cli/main_cli.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* QCMA: Cross-platform content manager assistant for the PS Vita
|
||||
*
|
||||
* Copyright (C) 2013 Codestation
|
||||
*
|
||||
* 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 3 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 Q_OS_WIN32
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include <QDebug>
|
||||
#include <QLibraryInfo>
|
||||
#include <QLocale>
|
||||
#include <QTextCodec>
|
||||
#include <QThread>
|
||||
#include <QTranslator>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <vitamtp.h>
|
||||
|
||||
#include "singlecoreapplication.h"
|
||||
#include "headlessmanager.h"
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
void noMessageOutput(QtMsgType type, const QMessageLogContext &, const QString & str)
|
||||
{
|
||||
const char * msg = str.toStdString().c_str();
|
||||
#else
|
||||
void noMessageOutput(QtMsgType type, const char *msg)
|
||||
{
|
||||
#endif
|
||||
Q_UNUSED(type);
|
||||
Q_UNUSED(msg);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if(SingleCoreApplication::sendMessage(QObject::tr("A instance of QCMA is already running"))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
SingleCoreApplication app(argc, argv);
|
||||
|
||||
#ifndef Q_OS_WIN32
|
||||
// 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
|
||||
// SIGPIPE on the socket
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
|
||||
if(app.arguments().contains("--with-debug")) {
|
||||
VitaMTP_Set_Logging(VitaMTP_DEBUG);
|
||||
} else if(app.arguments().contains("--verbose")) {
|
||||
VitaMTP_Set_Logging(VitaMTP_VERBOSE);
|
||||
} else {
|
||||
VitaMTP_Set_Logging(VitaMTP_NONE);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
qInstallMessageHandler(noMessageOutput);
|
||||
#else
|
||||
qInstallMsgHandler(noMessageOutput);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
|
||||
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
|
||||
#endif
|
||||
|
||||
qDebug("Starting QCMA %s", QCMA_VER);
|
||||
|
||||
QTranslator translator;
|
||||
QString locale = QLocale().system().name();
|
||||
qDebug() << "Current locale:" << locale;
|
||||
|
||||
if(app.arguments().contains("--set-locale")) {
|
||||
int index = app.arguments().indexOf("--set-locale");
|
||||
if(index + 1 < app.arguments().length()) {
|
||||
qDebug("Enforcing locale: %s", app.arguments().at(index + 1).toUtf8().data());
|
||||
locale = app.arguments().at(index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if(translator.load("qcma_" + locale, ":/resources/translations")) {
|
||||
app.installTranslator(&translator);
|
||||
} else {
|
||||
qDebug() << "Cannot load translation for locale:" << locale;
|
||||
}
|
||||
|
||||
QTranslator system_translator;
|
||||
system_translator.load("qt_" + locale, QLibraryInfo::location(QLibraryInfo::TranslationsPath));
|
||||
app.installTranslator(&system_translator);
|
||||
|
||||
qDebug("Starting main thread: 0x%016" PRIxPTR, (uintptr_t)QThread::currentThreadId());
|
||||
|
||||
// set the organization/application for QSettings to work properly
|
||||
app.setOrganizationName("qcma");
|
||||
app.setApplicationName("qcma");
|
||||
|
||||
HeadlessManager manager;
|
||||
manager.start();
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
69
src/cli/singlecoreapplication.cpp
Normal file
69
src/cli/singlecoreapplication.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* QCMA: Cross-platform content manager assistant for the PS Vita
|
||||
*
|
||||
* Copyright (C) 2013 Codestation
|
||||
*
|
||||
* 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 3 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 "singlecoreapplication.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
const int SingleCoreApplication::timeout = 500;
|
||||
const QString SingleCoreApplication::SHARED_KEY = "QCMA_KEY";
|
||||
|
||||
SingleCoreApplication::SingleCoreApplication(int &argc, char **argv) :
|
||||
QCoreApplication(argc, argv)
|
||||
{
|
||||
server = new QLocalServer(this);
|
||||
connect(server, SIGNAL(newConnection()), this, SLOT(receiveMessage()));
|
||||
QLocalServer::removeServer(SHARED_KEY);
|
||||
server->listen(SHARED_KEY);
|
||||
}
|
||||
|
||||
void SingleCoreApplication::receiveMessage()
|
||||
{
|
||||
QLocalSocket *socket = server->nextPendingConnection();
|
||||
|
||||
if(!socket->waitForReadyRead(timeout)) {
|
||||
qDebug() << socket->errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray byteArray = socket->readAll();
|
||||
QString message = QString::fromUtf8(byteArray.constData());
|
||||
emit messageAvailable(message);
|
||||
socket->disconnectFromServer();
|
||||
}
|
||||
|
||||
bool SingleCoreApplication::sendMessage(const QString &message)
|
||||
{
|
||||
QLocalSocket socket;
|
||||
socket.connectToServer(SHARED_KEY, QIODevice::WriteOnly);
|
||||
|
||||
if(!socket.waitForConnected(timeout)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
socket.write(message.toUtf8());
|
||||
|
||||
if(!socket.waitForBytesWritten(timeout)) {
|
||||
qDebug() << socket.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
socket.disconnectFromServer();
|
||||
return true;
|
||||
}
|
||||
50
src/cli/singlecoreapplication.h
Normal file
50
src/cli/singlecoreapplication.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* QCMA: Cross-platform content manager assistant for the PS Vita
|
||||
*
|
||||
* Copyright (C) 2013 Codestation
|
||||
*
|
||||
* 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 3 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 SINGLECOREAPPLICATION_H
|
||||
#define SINGLECOREAPPLICATION_H
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QLocalSocket>
|
||||
#include <QLocalServer>
|
||||
#include <QSharedMemory>
|
||||
|
||||
class SingleCoreApplication : public QCoreApplication
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SingleCoreApplication(int &argc, char **argv);
|
||||
|
||||
static bool sendMessage(const QString &message);
|
||||
|
||||
private:
|
||||
QLocalServer *server;
|
||||
|
||||
static const int timeout;
|
||||
static const QString SHARED_KEY;
|
||||
|
||||
signals:
|
||||
void messageAvailable(QString message);
|
||||
|
||||
|
||||
public slots:
|
||||
void receiveMessage();
|
||||
};
|
||||
|
||||
#endif // SINGLECOREAPPLICATION_H
|
||||
Reference in New Issue
Block a user