Moved conection logic from Qcma/ListenerWorker to CmaServer/CmaClient.

Added tray icon.
Quit now really quits the application.
This commit is contained in:
codestation
2013-08-13 10:22:45 -04:30
parent f9347f37cc
commit 6b17d2bc94
17 changed files with 354 additions and 452 deletions

View File

@@ -1,74 +1,64 @@
/* #include "cmaclient.h"
* QCMA: Cross-platform content manager assistant for the PS Vita #include "capability.h"
* #include "utils.h"
* 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 "listenerworker.h"
#include <locale.h>
#include <QBuffer> #include <QBuffer>
#include <QDateTime> #include <QDateTime>
#include <QDebug>
#include <QDir> #include <QDir>
#include <QImage> #include <QImage>
#include <QSettings> #include <QSettings>
#include <QUrl> #include <QUrl>
#include <QMutexLocker>
#include <QDebug>
#include "utils.h" const metadata_t CmaClient::g_thumbmeta = {0, 0, 0, NULL, NULL, 0, 0, 0, Thumbnail, {{18, 144, 80, 0, 1, 1.0f, 2}}, NULL};
#define CALL_MEMBER_FUNC(obj,memberptr) ((obj).*(memberptr)) CmaClient::CmaClient(QObject *parent) :
const metadata_t ListenerWorker::g_thumbmeta = {0, 0, 0, NULL, NULL, 0, 0, 0, Thumbnail, {{18, 144, 80, 0, 1, 1.0f, 2}}, NULL};
ListenerWorker::ListenerWorker(QObject *parent) :
BaseWorker(parent) BaseWorker(parent)
{ {
}
CmaClient::CmaClient(Database *database, vita_device_t *device, QObject *parent) :
BaseWorker(parent), db(database), device(device)
{
}
CmaClient::~CmaClient()
{
if(device) {
close();
}
}
void CmaClient::close()
{
VitaMTP_SendHostStatus(device, VITA_HOST_STATUS_EndConnection);
VitaMTP_Release_Device(device);
device = NULL;
}
void CmaClient::process()
{
qDebug("Vita connected: id %s", VitaMTP_Get_Identification(device));
DeviceCapability *vita_info = new DeviceCapability();
if(!vita_info->exchangeInfo(device)) {
qCritical("Error while exchanging info with the vita");
close();
}
// Conection successful, inform the user
emit deviceConnected(QString(tr("Connected to ")) + vita_info->getOnlineId());
connected = true; connected = true;
enterEventLoop();
} }
int ListenerWorker::rebuildDatabase()
{
db.destroy();
return db.create();
}
void ListenerWorker::setDevice(vita_device_t *device) void CmaClient::enterEventLoop()
{
this->device = device;
}
bool ListenerWorker::isConnected()
{
return connected;
}
void ListenerWorker::disconnect()
{
qDebug("Stopping event listener");
connected = false;
}
void ListenerWorker::process()
{ {
vita_event_t event; vita_event_t event;
qDebug() << "From listener: "<< QThread::currentThreadId(); qDebug() << "From listener:"<< QThread::currentThreadId();
while(connected) { while(connected) {
if(VitaMTP_Read_Event(device, &event) < 0) { if(VitaMTP_Read_Event(device, &event) < 0) {
@@ -147,10 +137,11 @@ void ListenerWorker::process()
vitaEventUnimplementated(&event, event.Param1); vitaEventUnimplementated(&event, event.Param1);
} }
} }
qDebug() << "Finished event thread for:" << QThread::currentThreadId();
emit finished(); emit finished();
} }
quint16 ListenerWorker::processAllObjects(CMAObject *parent, quint32 handle) quint16 CmaClient::processAllObjects(CMAObject *parent, quint32 handle)
{ {
union { union {
unsigned char *fileData; unsigned char *fileData;
@@ -165,13 +156,12 @@ quint16 ListenerWorker::processAllObjects(CMAObject *parent, quint32 handle)
return PTP_RC_VITA_Invalid_Data; return PTP_RC_VITA_Invalid_Data;
} }
CMAObject *object = db->pathToObject(remote_meta.name, parent->metadata.ohfi);
CMAObject *object = db.pathToObject(remote_meta.name, parent->metadata.ohfi);
if(object) { if(object) {
qDebug("Deleting %s", object->path.toStdString().c_str()); qDebug("Deleting %s", object->path.toStdString().c_str());
removeRecursively(object->path); removeRecursively(object->path);
db.remove(object); db->remove(object);
} }
QDir dir(parent->path); QDir dir(parent->path);
@@ -200,7 +190,7 @@ quint16 ListenerWorker::processAllObjects(CMAObject *parent, quint32 handle)
object = new CMAObject(parent); object = new CMAObject(parent);
object->initObject(info); object->initObject(info);
object->metadata.handle = remote_meta.handle; object->metadata.handle = remote_meta.handle;
db.append(parent->metadata.ohfi, object); db->append(parent->metadata.ohfi, object);
free(remote_meta.name); free(remote_meta.name);
qDebug("Added object %s with OHFI %i to database", object->metadata.path, object->metadata.ohfi); qDebug("Added object %s with OHFI %i to database", object->metadata.path, object->metadata.ohfi);
@@ -211,7 +201,7 @@ quint16 ListenerWorker::processAllObjects(CMAObject *parent, quint32 handle)
if(ret != PTP_RC_OK) { if(ret != PTP_RC_OK) {
qDebug("Deleteting object with OHFI %d", object->metadata.ohfi); qDebug("Deleteting object with OHFI %d", object->metadata.ohfi);
db.remove(object); db->remove(object);
free(data.fileData); free(data.fileData);
return ret; return ret;
} }
@@ -222,7 +212,7 @@ quint16 ListenerWorker::processAllObjects(CMAObject *parent, quint32 handle)
return PTP_RC_OK; return PTP_RC_OK;
} }
void ListenerWorker::vitaEventGetTreatObject(vita_event_t *event, int eventId) void CmaClient::vitaEventGetTreatObject(vita_event_t *event, int eventId)
{ {
qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId); qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId);
@@ -233,9 +223,9 @@ void ListenerWorker::vitaEventGetTreatObject(vita_event_t *event, int eventId)
return; return;
} }
QMutexLocker locker(&db.mutex); QMutexLocker locker(&db->mutex);
CMAObject *parent = db.ohfiToObject(treatObject.ohfiParent); CMAObject *parent = db->ohfiToObject(treatObject.ohfiParent);
if(parent == NULL) { if(parent == NULL) {
qWarning("Cannot find parent OHFI %d", treatObject.ohfiParent); qWarning("Cannot find parent OHFI %d", treatObject.ohfiParent);
@@ -246,7 +236,7 @@ void ListenerWorker::vitaEventGetTreatObject(vita_event_t *event, int eventId)
VitaMTP_ReportResult(device, eventId, processAllObjects(parent, treatObject.handle)); VitaMTP_ReportResult(device, eventId, processAllObjects(parent, treatObject.handle));
} }
void ListenerWorker::vitaEventSendCopyConfirmationInfo(vita_event_t *event, int eventId) void CmaClient::vitaEventSendCopyConfirmationInfo(vita_event_t *event, int eventId)
{ {
qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId); qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId);
@@ -256,14 +246,14 @@ void ListenerWorker::vitaEventSendCopyConfirmationInfo(vita_event_t *event, int
return; return;
} }
QMutexLocker locker(&db.mutex); QMutexLocker locker(&db->mutex);
quint64 size = 0; quint64 size = 0;
for(quint32 i = 0; i < info->count; i++) { for(quint32 i = 0; i < info->count; i++) {
CMAObject *object; CMAObject *object;
if((object = db.ohfiToObject(info->ohfi[i])) == NULL) { if((object = db->ohfiToObject(info->ohfi[i])) == NULL) {
qWarning("Cannot find OHFI %d", info->ohfi[i]); qWarning("Cannot find OHFI %d", info->ohfi[i]);
free(info); free(info);
return; return;
@@ -281,7 +271,7 @@ void ListenerWorker::vitaEventSendCopyConfirmationInfo(vita_event_t *event, int
free(info); free(info);
} }
void ListenerWorker::vitaEventSendObjectMetadataItems(vita_event_t *event, int eventId) void CmaClient::vitaEventSendObjectMetadataItems(vita_event_t *event, int eventId)
{ {
qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId); qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId);
@@ -291,9 +281,9 @@ void ListenerWorker::vitaEventSendObjectMetadataItems(vita_event_t *event, int e
return; return;
} }
QMutexLocker locker(&db.mutex); QMutexLocker locker(&db->mutex);
CMAObject *object = db.ohfiToObject(ohfi); CMAObject *object = db->ohfiToObject(ohfi);
if(object == NULL) { if(object == NULL) {
qWarning("Cannot find OHFI %d in database", ohfi); qWarning("Cannot find OHFI %d in database", ohfi);
@@ -312,33 +302,34 @@ void ListenerWorker::vitaEventSendObjectMetadataItems(vita_event_t *event, int e
} }
} }
void ListenerWorker::vitaEventSendNPAccountInfo(vita_event_t *event, int eventId) void CmaClient::vitaEventSendNPAccountInfo(vita_event_t *event, int eventId)
{ {
qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId); qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId);
// AFAIK, Sony hasn't even implemented this in their CMA // AFAIK, Sony hasn't even implemented this in their CMA
qWarning("Event 0x%x unimplemented!", event->Code); qWarning("Event 0x%x unimplemented!", event->Code);
} }
void ListenerWorker::vitaEventRequestTerminate(vita_event_t *event, int eventId) void CmaClient::vitaEventRequestTerminate(vita_event_t *event, int eventId)
{ {
qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId); qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId);
qWarning("Event 0x%x unimplemented!", event->Code); //qWarning("Event 0x%x unimplemented!", event->Code);
connected = false;
} }
void ListenerWorker::vitaEventUnimplementated(vita_event_t *event, int eventId) void CmaClient::vitaEventUnimplementated(vita_event_t *event, int eventId)
{ {
qWarning("Unknown event not handled, code: 0x%x, id: %d", event->Code, eventId); qWarning("Unknown event not handled, code: 0x%x, id: %d", event->Code, eventId);
qWarning("Param1: 0x%08X, Param2: 0x%08X, Param3: 0x%08X", event->Param1, event->Param2, event->Param3); qWarning("Param1: 0x%08X, Param2: 0x%08X, Param3: 0x%08X", event->Param1, event->Param2, event->Param3);
} }
void ListenerWorker::vitaEventSendNumOfObject(vita_event_t *event, int eventId) void CmaClient::vitaEventSendNumOfObject(vita_event_t *event, int eventId)
{ {
qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId); qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId);
QMutexLocker locker(&db.mutex); QMutexLocker locker(&db->mutex);
uint ohfi = event->Param2; uint ohfi = event->Param2;
int items = db.filterObjects(ohfi, NULL); int items = db->filterObjects(ohfi, NULL);
if(VitaMTP_SendNumOfObject(device, eventId, items) != PTP_RC_OK) { if(VitaMTP_SendNumOfObject(device, eventId, items) != PTP_RC_OK) {
qWarning("Error occured receiving object count for OHFI parent %d", ohfi); qWarning("Error occured receiving object count for OHFI parent %d", ohfi);
@@ -348,7 +339,7 @@ void ListenerWorker::vitaEventSendNumOfObject(vita_event_t *event, int eventId)
} }
} }
void ListenerWorker::vitaEventSendObjectMetadata(vita_event_t *event, int eventId) void CmaClient::vitaEventSendObjectMetadata(vita_event_t *event, int eventId)
{ {
qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId); qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId);
@@ -358,10 +349,10 @@ void ListenerWorker::vitaEventSendObjectMetadata(vita_event_t *event, int eventI
qWarning("GetBrowseInfo failed"); qWarning("GetBrowseInfo failed");
return; return;
} }
QMutexLocker locker(&db.mutex); QMutexLocker locker(&db->mutex);
metadata_t *meta; metadata_t *meta;
int count = db.filterObjects(browse.ohfiParent, &meta); // if meta is null, will return empty XML int count = db->filterObjects(browse.ohfiParent, &meta); // if meta is null, will return empty XML
qDebug("Sending %i metadata filtered objects for OHFI %id", count, browse.ohfiParent); qDebug("Sending %i metadata filtered objects for OHFI %id", count, browse.ohfiParent);
if(VitaMTP_SendObjectMetadata(device, eventId, meta) != PTP_RC_OK) { // send all objects with OHFI parent if(VitaMTP_SendObjectMetadata(device, eventId, meta) != PTP_RC_OK) { // send all objects with OHFI parent
@@ -371,16 +362,16 @@ void ListenerWorker::vitaEventSendObjectMetadata(vita_event_t *event, int eventI
} }
} }
void ListenerWorker::vitaEventSendObject(vita_event_t *event, int eventId) void CmaClient::vitaEventSendObject(vita_event_t *event, int eventId)
{ {
qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId); qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId);
int ohfi = event->Param2; int ohfi = event->Param2;
QMutexLocker locker(&db.mutex); QMutexLocker locker(&db->mutex);
Database::find_data iters; Database::find_data iters;
if(!db.find(ohfi, iters)) { if(!db->find(ohfi, iters)) {
qWarning("Failed to find OHFI %d", ohfi); qWarning("Failed to find OHFI %d", ohfi);
VitaMTP_ReportResult(device, eventId, PTP_RC_VITA_Invalid_OHFI); VitaMTP_ReportResult(device, eventId, PTP_RC_VITA_Invalid_OHFI);
return; return;
@@ -435,7 +426,7 @@ void ListenerWorker::vitaEventSendObject(vita_event_t *event, int eventId)
VitaMTP_ReportResult(device, eventId, PTP_RC_VITA_Invalid_Data); // TODO: Send thumbnail VitaMTP_ReportResult(device, eventId, PTP_RC_VITA_Invalid_Data); // TODO: Send thumbnail
} }
void ListenerWorker::vitaEventCancelTask(vita_event_t *event, int eventId) void CmaClient::vitaEventCancelTask(vita_event_t *event, int eventId)
{ {
qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId); qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId);
@@ -444,7 +435,7 @@ void ListenerWorker::vitaEventCancelTask(vita_event_t *event, int eventId)
qWarning("Event CancelTask (0x%x) unimplemented!", event->Code); qWarning("Event CancelTask (0x%x) unimplemented!", event->Code);
} }
void ListenerWorker::vitaEventSendHttpObjectFromURL(vita_event_t *event, int eventId) void CmaClient::vitaEventSendHttpObjectFromURL(vita_event_t *event, int eventId)
{ {
qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId); qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId);
@@ -487,7 +478,7 @@ void ListenerWorker::vitaEventSendHttpObjectFromURL(vita_event_t *event, int eve
free(url); free(url);
} }
void ListenerWorker::vitaEventSendObjectStatus(vita_event_t *event, int eventId) void CmaClient::vitaEventSendObjectStatus(vita_event_t *event, int eventId)
{ {
qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId); qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId);
@@ -498,9 +489,9 @@ void ListenerWorker::vitaEventSendObjectStatus(vita_event_t *event, int eventId)
return; return;
} }
QMutexLocker locker(&db.mutex); QMutexLocker locker(&db->mutex);
CMAObject *object = db.pathToObject(objectstatus.title, objectstatus.ohfiRoot); CMAObject *object = db->pathToObject(objectstatus.title, objectstatus.ohfiRoot);
if(object == NULL) { // not in database, don't return metadata if(object == NULL) { // not in database, don't return metadata
qDebug("Object %s not in database (OHFI: %i). Sending OK response for non-existence", objectstatus.title, objectstatus.ohfiRoot); qDebug("Object %s not in database (OHFI: %i). Sending OK response for non-existence", objectstatus.title, objectstatus.ohfiRoot);
@@ -520,14 +511,14 @@ void ListenerWorker::vitaEventSendObjectStatus(vita_event_t *event, int eventId)
free(objectstatus.title); free(objectstatus.title);
} }
void ListenerWorker::vitaEventSendObjectThumb(vita_event_t *event, int eventId) void CmaClient::vitaEventSendObjectThumb(vita_event_t *event, int eventId)
{ {
qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId); qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId);
QMutexLocker locker(&db.mutex); QMutexLocker locker(&db->mutex);
int ohfi = event->Param2; int ohfi = event->Param2;
CMAObject *object = db.ohfiToObject(ohfi); CMAObject *object = db->ohfiToObject(ohfi);
if(object == NULL) { if(object == NULL) {
qWarning("Cannot find OHFI %d in database.", ohfi); qWarning("Cannot find OHFI %d in database.", ohfi);
@@ -579,14 +570,14 @@ void ListenerWorker::vitaEventSendObjectThumb(vita_event_t *event, int eventId)
free(locale); free(locale);
} }
void ListenerWorker::vitaEventDeleteObject(vita_event_t *event, int eventId) void CmaClient::vitaEventDeleteObject(vita_event_t *event, int eventId)
{ {
qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId); qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId);
QMutexLocker locker(&db.mutex); QMutexLocker locker(&db->mutex);
int ohfi = event->Param2; int ohfi = event->Param2;
CMAObject *object = db.ohfiToObject(ohfi); CMAObject *object = db->ohfiToObject(ohfi);
if(object == NULL) { if(object == NULL) {
qWarning("OHFI %d not found", ohfi); qWarning("OHFI %d not found", ohfi);
@@ -595,13 +586,13 @@ void ListenerWorker::vitaEventDeleteObject(vita_event_t *event, int eventId)
} }
qDebug("Deleting %s, OHFI: %i", object->metadata.path, object->metadata.ohfi); qDebug("Deleting %s, OHFI: %i", object->metadata.path, object->metadata.ohfi);
removeRecursively(object->path); removeRecursively(object->path);
db.remove(object); db->remove(object);
VitaMTP_ReportResult(device, eventId, PTP_RC_OK); VitaMTP_ReportResult(device, eventId, PTP_RC_OK);
} }
void ListenerWorker::vitaEventGetSettingInfo(vita_event_t *event, int eventId) void CmaClient::vitaEventGetSettingInfo(vita_event_t *event, int eventId)
{ {
qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId); qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId);
@@ -613,9 +604,9 @@ void ListenerWorker::vitaEventGetSettingInfo(vita_event_t *event, int eventId)
qDebug("Current account id: %s", settingsinfo->current_account.accountId); qDebug("Current account id: %s", settingsinfo->current_account.accountId);
db.setUUID(settingsinfo->current_account.accountId); db->setUUID(settingsinfo->current_account.accountId);
// set the database to be updated ASAP // set the database to be updated ASAP
emit refreshDatabase(); emit refreshDatabase();
// free all the information // free all the information
@@ -623,7 +614,7 @@ void ListenerWorker::vitaEventGetSettingInfo(vita_event_t *event, int eventId)
VitaMTP_ReportResult(device, eventId, PTP_RC_OK); VitaMTP_ReportResult(device, eventId, PTP_RC_OK);
} }
void ListenerWorker::vitaEventSendHttpObjectPropFromURL(vita_event_t *event, int eventId) void CmaClient::vitaEventSendHttpObjectPropFromURL(vita_event_t *event, int eventId)
{ {
qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId); qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId);
@@ -659,7 +650,7 @@ void ListenerWorker::vitaEventSendHttpObjectPropFromURL(vita_event_t *event, int
free(url); free(url);
} }
void ListenerWorker::vitaEventSendPartOfObject(vita_event_t *event, int eventId) void CmaClient::vitaEventSendPartOfObject(vita_event_t *event, int eventId)
{ {
qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId); qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId);
@@ -670,9 +661,9 @@ void ListenerWorker::vitaEventSendPartOfObject(vita_event_t *event, int eventId)
return; return;
} }
QMutexLocker locker(&db.mutex); QMutexLocker locker(&db->mutex);
CMAObject *object = db.ohfiToObject(part_init.ohfi); CMAObject *object = db->ohfiToObject(part_init.ohfi);
if(object == NULL) { if(object == NULL) {
qWarning("Cannot find object for OHFI %d", part_init.ohfi); qWarning("Cannot find object for OHFI %d", part_init.ohfi);
@@ -699,7 +690,7 @@ void ListenerWorker::vitaEventSendPartOfObject(vita_event_t *event, int eventId)
} }
} }
void ListenerWorker::vitaEventOperateObject(vita_event_t *event, int eventId) void CmaClient::vitaEventOperateObject(vita_event_t *event, int eventId)
{ {
qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId); qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId);
@@ -710,9 +701,9 @@ void ListenerWorker::vitaEventOperateObject(vita_event_t *event, int eventId)
return; return;
} }
QMutexLocker locker(&db.mutex); QMutexLocker locker(&db->mutex);
CMAObject *root = db.ohfiToObject(operateobject.ohfi); CMAObject *root = db->ohfiToObject(operateobject.ohfi);
// end for renaming only // end for renaming only
if(root == NULL) { if(root == NULL) {
@@ -731,7 +722,7 @@ void ListenerWorker::vitaEventOperateObject(vita_event_t *event, int eventId)
} else { } else {
CMAObject *newobj = new CMAObject(root); CMAObject *newobj = new CMAObject(root);
newobj->initObject(QFileInfo(dir, operateobject.title)); newobj->initObject(QFileInfo(dir, operateobject.title));
db.append(operateobject.ohfi, newobj); db->append(operateobject.ohfi, newobj);
qDebug("Created folder %s with OHFI %d under parent %s", newobj->metadata.path, newobj->metadata.ohfi, root->metadata.path); qDebug("Created folder %s with OHFI %d under parent %s", newobj->metadata.path, newobj->metadata.ohfi, root->metadata.path);
VitaMTP_ReportResultWithParam(device, eventId, PTP_RC_OK, newobj->metadata.ohfi); VitaMTP_ReportResultWithParam(device, eventId, PTP_RC_OK, newobj->metadata.ohfi);
} }
@@ -747,7 +738,7 @@ void ListenerWorker::vitaEventOperateObject(vita_event_t *event, int eventId)
} else { } else {
CMAObject *newobj = new CMAObject(root); CMAObject *newobj = new CMAObject(root);
newobj->initObject(file); newobj->initObject(file);
db.append(root->metadata.ohfi, newobj); db->append(root->metadata.ohfi, newobj);
qDebug("Created file %s with OHFI %d under parent %s", newobj->metadata.path, newobj->metadata.ohfi, root->metadata.path); qDebug("Created file %s with OHFI %d under parent %s", newobj->metadata.path, newobj->metadata.ohfi, root->metadata.path);
VitaMTP_ReportResultWithParam(device, eventId, PTP_RC_OK, newobj->metadata.ohfi); VitaMTP_ReportResultWithParam(device, eventId, PTP_RC_OK, newobj->metadata.ohfi);
} }
@@ -762,7 +753,7 @@ void ListenerWorker::vitaEventOperateObject(vita_event_t *event, int eventId)
//rename the current object //rename the current object
root->rename(operateobject.title); root->rename(operateobject.title);
Database::find_data iters; Database::find_data iters;
db.find(root->metadata.ohfi, iters); db->find(root->metadata.ohfi, iters);
// rename the rest of the list only if has the renamed parent in some part of the chain // rename the rest of the list only if has the renamed parent in some part of the chain
while(iters.it != iters.end) { while(iters.it != iters.end) {
@@ -794,7 +785,7 @@ void ListenerWorker::vitaEventOperateObject(vita_event_t *event, int eventId)
free(operateobject.title); free(operateobject.title);
} }
void ListenerWorker::vitaEventGetPartOfObject(vita_event_t *event, int eventId) void CmaClient::vitaEventGetPartOfObject(vita_event_t *event, int eventId)
{ {
qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId); qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId);
@@ -806,8 +797,8 @@ void ListenerWorker::vitaEventGetPartOfObject(vita_event_t *event, int eventId)
return; return;
} }
QMutexLocker locker(&db.mutex); QMutexLocker locker(&db->mutex);
CMAObject *object = db.ohfiToObject(part_init.ohfi); CMAObject *object = db->ohfiToObject(part_init.ohfi);
if(object == NULL) { if(object == NULL) {
qWarning("Cannot find OHFI %d", part_init.ohfi); qWarning("Cannot find OHFI %d", part_init.ohfi);
@@ -834,14 +825,14 @@ void ListenerWorker::vitaEventGetPartOfObject(vita_event_t *event, int eventId)
free(data); free(data);
} }
void ListenerWorker::vitaEventSendStorageSize(vita_event_t *event, int eventId) void CmaClient::vitaEventSendStorageSize(vita_event_t *event, int eventId)
{ {
qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId); qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId);
QMutexLocker locker(&db.mutex); QMutexLocker locker(&db->mutex);
int ohfi = event->Param2; int ohfi = event->Param2;
CMAObject *object = db.ohfiToObject(ohfi); CMAObject *object = db->ohfiToObject(ohfi);
if(object == NULL) { if(object == NULL) {
qWarning("Error: Cannot find OHFI %d", ohfi); qWarning("Error: Cannot find OHFI %d", ohfi);
@@ -880,7 +871,7 @@ void ListenerWorker::vitaEventSendStorageSize(vita_event_t *event, int eventId)
} }
} }
void ListenerWorker::vitaEventCheckExistance(vita_event_t *event, int eventId) void CmaClient::vitaEventCheckExistance(vita_event_t *event, int eventId)
{ {
qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId); qDebug("Event recieved in %s, code: 0x%x, id: %d", Q_FUNC_INFO, event->Code, eventId);
@@ -892,9 +883,9 @@ void ListenerWorker::vitaEventCheckExistance(vita_event_t *event, int eventId)
return; return;
} }
QMutexLocker locker(&db.mutex); QMutexLocker locker(&db->mutex);
CMAObject *object = db.pathToObject(existance.name, 0); CMAObject *object = db->pathToObject(existance.name, 0);
if(object == NULL) { if(object == NULL) {
VitaMTP_ReportResult(device, eventId, PTP_RC_VITA_Different_Object); VitaMTP_ReportResult(device, eventId, PTP_RC_VITA_Different_Object);

View File

@@ -1,50 +1,28 @@
/* #ifndef CMACLIENT_H
* QCMA: Cross-platform content manager assistant for the PS Vita #define CMACLIENT_H
*
* 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 LISTENERWORKER_H
#define LISTENERWORKER_H
#include "database.h"
#include "baseworker.h" #include "baseworker.h"
#include "cmaobject.h"
#include "database.h"
#include <QObject> #include <QObject>
#include <QString>
#include <stdint.h>
extern "C" { extern "C" {
#include <vitamtp.h> #include <vitamtp.h>
} }
class ListenerWorker : public BaseWorker class CmaClient : public BaseWorker
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ListenerWorker(QObject *parent = 0); explicit CmaClient(QObject *parent = 0);
explicit CmaClient(Database *database, vita_device_t *device, QObject *parent = 0);
void setDevice(vita_device_t *device); ~CmaClient();
bool isConnected();
void disconnect();
int rebuildDatabase();
Database db;
private: private:
void enterEventLoop();
uint16_t processAllObjects(CMAObject *parent, uint32_t handle); uint16_t processAllObjects(CMAObject *parent, uint32_t handle);
void vitaEventSendObject(vita_event_t *event, int eventId); void vitaEventSendObject(vita_event_t *event, int eventId);
void vitaEventSendObjectMetadata(vita_event_t *event, int eventId); void vitaEventSendObjectMetadata(vita_event_t *event, int eventId);
@@ -68,15 +46,21 @@ private:
void vitaEventSendNPAccountInfo(vita_event_t *event, int eventId); void vitaEventSendNPAccountInfo(vita_event_t *event, int eventId);
void vitaEventRequestTerminate(vita_event_t *event, int eventId); void vitaEventRequestTerminate(vita_event_t *event, int eventId);
Database *db;
vita_device_t *device; vita_device_t *device;
volatile bool connected; volatile bool connected;
static const metadata_t g_thumbmeta; static const metadata_t g_thumbmeta;
signals: signals:
void deviceConnected(QString);
void refreshDatabase(); void refreshDatabase();
void terminate();
public slots:
void close();
private slots: private slots:
void process(); void process();
}; };
#endif // LISTENERWORKER_H #endif // CMACLIENT_H

72
cmaserver.cpp Normal file
View File

@@ -0,0 +1,72 @@
#include "cmaserver.h"
#include "wirelessworker.h"
#include <QDebug>
#include <QHostInfo>
#include <QMutex>
#include <QSettings>
CmaServer::CmaServer(QObject *parent) :
QObject(parent), num_retries(0)
{
strcpy(hostname, QHostInfo::localHostName().toStdString().c_str());
BroadcastSignal::info.name = hostname;
}
void CmaServer::listen()
{
QThread *thread = new QThread();
if(QSettings().value("wireless", false).toBool()) {
connect(&timer, SIGNAL(timeout()), this, SLOT(connectWireless()));
broadcast.start();
timer.setSingleShot(true);
} else {
timer.setSingleShot(false);
connect(&timer, SIGNAL(timeout()), this, SLOT(connectUsb()));
}
moveToThread(thread);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
timer.start(2000);
thread->start();
}
void CmaServer::connectUsb()
{
qDebug() << "From connectUsb: "<< QThread::currentThreadId();
vita_device_t *vita = VitaMTP_Get_First_USB_Vita();
if(vita) {
qDebug("Detected PS Vita via USB");
timer.stop();
emit newConnection(vita);
} else {
qDebug("No PS Vita found. Attempt %d", ++num_retries);
}
}
void CmaServer::connectWireless()
{
typedef BroadcastSignal BS;
qDebug() << "From connectWireless: "<< QThread::currentThreadId();
vita_device_t *vita = VitaMTP_Get_First_Wireless_Vita(&BS::info, 0, 0, BS::deviceRegistered, BS::generatePin);
if(vita) {
qDebug("Detected PS Vita in wireless mode");
emit newConnection(vita);
} else {
qDebug("PS Vita couldn't be detected. Attempt %d", ++num_retries);
}
}
void CmaServer::continueProcess()
{
qDebug("Restarting CmaServer thread");
num_retries = 0;
timer.start();
}
void CmaServer::stopProcess()
{
timer.stop();
}

45
cmaserver.h Normal file
View File

@@ -0,0 +1,45 @@
#ifndef CMASERVER_H
#define CMASERVER_H
#include "wirelessworker.h"
extern "C" {
#include <vitamtp.h>
}
#include <limits.h>
#include <QObject>
#include <QTimer>
#include <QThread>
#include <QWaitCondition>
class CmaServer : public QObject
{
Q_OBJECT
public:
explicit CmaServer(QObject *parent = 0);
void listen();
void close();
int num_retries;
QTimer timer;
QThread *thread;
char hostname[256];
BroadcastSignal broadcast;
signals:
void newConnection(vita_device_t *);
void createdPin(int);
void finished();
public slots:
void continueProcess();
void stopProcess();
private slots:
void connectWireless();
void connectUsb();
};
#endif // CMASERVER_H

View File

@@ -18,6 +18,7 @@
*/ */
#include <QDebug> #include <QDebug>
#include <QThread>
#include "singleapplication.h" #include "singleapplication.h"
#include "mainwidget.h" #include "mainwidget.h"
@@ -42,12 +43,17 @@ int main(int argc, char *argv[])
SingleApplication app(argc, argv); SingleApplication app(argc, argv);
if(!app.arguments().contains("--with-debug")) { if(!app.arguments().contains("--with-debug")) {
VitaMTP_Set_Logging(VitaMTP_NONE);
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
qInstallMessageHandler(noMessageOutput); qInstallMessageHandler(noMessageOutput);
#else #else
qInstallMsgHandler(noMessageOutput); qInstallMsgHandler(noMessageOutput);
#endif #endif
} else {
VitaMTP_Set_Logging(VitaMTP_DEBUG);
} }
qDebug()<<"From main thread: "<<QThread::currentThreadId(); qDebug()<<"From main thread: "<<QThread::currentThreadId();

View File

@@ -18,10 +18,12 @@
*/ */
#include "mainwidget.h" #include "mainwidget.h"
#include "qcma.h" #include "cmaclient.h"
#include "utils.h"
#include <QAction> #include <QAction>
#include <QApplication> #include <QApplication>
#include <QDebug>
#include <QDir> #include <QDir>
#include <QMenu> #include <QMenu>
#include <QSettings> #include <QSettings>
@@ -45,7 +47,7 @@ void MainWidget::checkSettings()
return; return;
} }
} }
CmaWorker.start(); startServer();
} }
void MainWidget::dialogResult(int result) void MainWidget::dialogResult(int result)
@@ -53,13 +55,44 @@ void MainWidget::dialogResult(int result)
if(result == QDialog::Accepted) { if(result == QDialog::Accepted) {
if(first_run) { if(first_run) {
first_run = false; first_run = false;
CmaWorker.start(); startServer();
} }
} else if(first_run) { } else if(first_run) {
qApp->quit(); qApp->quit();
} }
} }
void MainWidget::startServer()
{
connect(&server, SIGNAL(newConnection(vita_device_t *)), this, SLOT(startClient(vita_device_t*)));
connect(&server, SIGNAL(createdPin(int)), this, SLOT(showPin(int)));
//connect(&server, SIGNAL(finished()), qApp, SLOT(quit()));
qDebug("Starting cma server");
server.listen();
}
void MainWidget::refreshDatabase()
{
db.mutex.lock();
db.destroy();
db.create();
db.mutex.unlock();
}
void MainWidget::startClient(vita_device_t *device)
{
server.stopProcess();
qDebug() << "From startClient: "<< QThread::currentThreadId();
qDebug("Starting new client connection");
CmaClient *client = new CmaClient(&db, device);
connect(client, SIGNAL(deviceConnected(QString)), this, SLOT(receiveMessage(QString)));
connect(client, SIGNAL(deviceConnected(QString)), this, SLOT(setTrayTooltip(QString)));
connect(client, SIGNAL(refreshDatabase()), this, SLOT(refreshDatabase()));
connect(client, SIGNAL(finished()), &server, SLOT(continueProcess()));
client->start();
}
void MainWidget::deviceDisconnect() void MainWidget::deviceDisconnect()
{ {
setTrayTooltip(tr("Disconnected")); setTrayTooltip(tr("Disconnected"));
@@ -69,12 +102,6 @@ void MainWidget::deviceDisconnect()
void MainWidget::connectSignals() void MainWidget::connectSignals()
{ {
connect(&dialog, SIGNAL(finished(int)), this, SLOT(dialogResult(int))); connect(&dialog, SIGNAL(finished(int)), this, SLOT(dialogResult(int)));
connect(&CmaWorker, SIGNAL(createdPin(int)), this, SLOT(showPin(int)));
connect(&CmaWorker, SIGNAL(deviceConnected(QString)), this, SLOT(receiveMessage(QString)));
connect(&CmaWorker, SIGNAL(deviceConnected(QString)), this, SLOT(setTrayTooltip(QString)));
connect(&CmaWorker, SIGNAL(statusUpdated(QString)), this, SLOT(receiveMessage(QString)));
connect(&CmaWorker, SIGNAL(deviceDisconnected()), this, SLOT(deviceDisconnect()));
connect(&CmaWorker, SIGNAL(finished()), qApp, SLOT(quit()));
} }
void MainWidget::showPin(int pin) void MainWidget::showPin(int pin)
@@ -86,7 +113,6 @@ void MainWidget::prepareApplication()
{ {
connectSignals(); connectSignals();
createTrayIcon(); createTrayIcon();
trayIcon->show();
checkSettings(); checkSettings();
} }
@@ -105,7 +131,6 @@ void MainWidget::toggleWireless()
wireless->setText(tr("&Wireless disabled")); wireless->setText(tr("&Wireless disabled"));
settings.setValue("wireless", false); settings.setValue("wireless", false);
} }
CmaWorker.reload();
} }
void MainWidget::createTrayIcon() void MainWidget::createTrayIcon()
@@ -126,8 +151,8 @@ void MainWidget::createTrayIcon()
quit = new QAction(tr("&Quit"), this); quit = new QAction(tr("&Quit"), this);
connect(options, SIGNAL(triggered()), &dialog, SLOT(open())); connect(options, SIGNAL(triggered()), &dialog, SLOT(open()));
connect(reload, SIGNAL(triggered()), &CmaWorker, SLOT(allowRefresh()), Qt::DirectConnection); //connect(reload, SIGNAL(triggered()), &CmaWorker, SLOT(allowRefresh()), Qt::DirectConnection);
connect(quit, SIGNAL(triggered()), &CmaWorker, SLOT(stop()), Qt::DirectConnection); connect(quit, SIGNAL(triggered()), qApp, SLOT(quit()));
connect(wireless, SIGNAL(triggered()), this, SLOT(toggleWireless())); connect(wireless, SIGNAL(triggered()), this, SLOT(toggleWireless()));
QMenu *trayIconMenu = new QMenu(this); QMenu *trayIconMenu = new QMenu(this);
@@ -139,7 +164,10 @@ void MainWidget::createTrayIcon()
trayIcon = new QSystemTrayIcon(this); trayIcon = new QSystemTrayIcon(this);
trayIcon->setContextMenu(trayIconMenu); trayIcon->setContextMenu(trayIconMenu);
trayIcon->setIcon(QIcon::fromTheme("image-loading")); trayIcon->setIcon(QIcon(":/main/resources/psv_icon.png"));
trayIcon->show();
// try to avoid the iconTray Qt bug
//Sleeper::sleep(1);
} }
void MainWidget::receiveMessage(QString message) void MainWidget::receiveMessage(QString message)

View File

@@ -21,19 +21,20 @@
#define MAINWIDGET_H #define MAINWIDGET_H
#include "configwidget.h" #include "configwidget.h"
#include "qcma.h" #include "cmaserver.h"
#include "database.h"
#include <QAction> #include <QAction>
#include <QWidget> #include <QWidget>
#include <QSystemTrayIcon> #include <QSystemTrayIcon>
class QMenu; extern "C" {
#include <vitamtp.h>
namespace Ui
{
class MainWidget;
} }
class QMenu;
class MainWidget : public QWidget class MainWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
@@ -49,13 +50,14 @@ private:
void connectSignals(); void connectSignals();
bool first_run; bool first_run;
QCMA CmaWorker;
ConfigWidget dialog; ConfigWidget dialog;
QSystemTrayIcon *trayIcon; QSystemTrayIcon *trayIcon;
QAction *quit; QAction *quit;
QAction *reload; QAction *reload;
QAction *options; QAction *options;
QAction *wireless; QAction *wireless;
Database db;
CmaServer server;
const static QStringList path_list; const static QStringList path_list;
private slots: private slots:
@@ -65,6 +67,9 @@ private slots:
void setTrayTooltip(QString message); void setTrayTooltip(QString message);
void toggleWireless(); void toggleWireless();
void showPin(int pin); void showPin(int pin);
void startClient(vita_device_t *device);
void refreshDatabase();
void startServer();
}; };
#endif // MAINWIDGET_H #endif // MAINWIDGET_H

174
qcma.cpp
View File

@@ -1,174 +0,0 @@
/*
* 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 "qcma.h"
#include "capability.h"
#include "listenerworker.h"
#include "wirelessworker.h"
#include <QApplication>
#include <QDebug>
#include <QDir>
#include <QSettings>
#include <QWaitCondition>
#include <QElapsedTimer>
#include <QHostInfo>
#include <unistd.h>
#define RETRY_TIMEOUT 2000
QCMA::QCMA(QObject *parent) :
BaseWorker(parent)
{
exit_thread = false;
}
vita_device_t *QCMA::connectWireless()
{
int num_tries = 0;
vita_device_t *vita = NULL;
WirelessWorker *broadcast = new WirelessWorker();
// bubble up the pin received signal
connect(broadcast, SIGNAL(createdPin(int)), this, SIGNAL(createdPin(int)));
qDebug("Starting broadcast");
broadcast->start();
QMutex mutex;
QString hostname = QHostInfo::localHostName();
WirelessWorker::info.name = hostname.toUtf8().data();
while(!break_loop && (vita = VitaMTP_Get_First_Wireless_Vita(
&WirelessWorker::info, 0, 10,
WirelessWorker::deviceRegistered,
WirelessWorker::generatePin)) == NULL) {
qDebug("Error connecting to device. Attempt %d", ++num_tries);
//FIXME: use a proper sleep function
mutex.lock();
waitCondition.wait(&mutex, RETRY_TIMEOUT);
mutex.unlock();
}
qDebug("Stopping broadcast");
broadcast->stopBroadcast();
return vita;
}
vita_device_t *QCMA::connectUsb()
{
int num_tries = 0;
vita_device_t *vita = NULL;
QMutex mutex;
while(!break_loop && (vita = VitaMTP_Get_First_USB_Vita()) == NULL) {
qDebug("No Vita found. Attempt %d", ++num_tries);
//FIXME: use a proper sleep function
mutex.lock();
waitCondition.wait(&mutex, RETRY_TIMEOUT);
mutex.unlock();
}
return vita;
}
void QCMA::process()
{
QSettings settings;
qDebug() << "From QCMA: "<< QThread::currentThreadId();
while(!exit_thread) {
break_loop = false;
VitaMTP_Set_Logging(VitaMTP_NONE);
bool wireless = settings.value("wireless", false).toBool();
emit statusUpdated("Searching for device...");
vita_device_t *device = wireless ? connectWireless() : connectUsb();
if(!device) {
continue;
}
qDebug("Vita connected: id %s", VitaMTP_Get_Identification(device));
// create a listener thread to receive the vita events
ListenerWorker *listener = new ListenerWorker();
listener->setDevice(device);
connect(listener, SIGNAL(refreshDatabase()), this, SLOT(allowRefresh()), Qt::DirectConnection);
connect(listener, SIGNAL(finished()), this, SIGNAL(deviceDisconnected()), Qt::DirectConnection);
connect(listener, SIGNAL(finished()), this, SLOT(reload()), Qt::DirectConnection);
listener->start();
qDebug("Exchanging info with vita");
DeviceCapability *vita_info = new DeviceCapability();
if(!vita_info->exchangeInfo(device)) {
qCritical("Error while exchanging info with the vita");
VitaMTP_SendHostStatus(device, VITA_HOST_STATUS_EndConnection);
VitaMTP_Release_Device(device);
sleep(RETRY_TIMEOUT);
continue;
}
// Conection successful, inform the user
emit deviceConnected(QString(tr("Connected to ")) + vita_info->getOnlineId());
delete vita_info;
QElapsedTimer timer;
qint64 sec;
while(listener->isConnected()) {
sema.acquire();
if(break_loop) {
break;
}
qDebug("Updating database");
timer.start();
int scanned_objects = listener->rebuildDatabase();
sec = timer.elapsed();
qDebug("Scanned %i objects in %lli milliseconds", scanned_objects, sec);
emit statusUpdated(QString("Scanned %1 objects in %2 milliseconds").arg(scanned_objects, sec));
}
qDebug("Ending device connection...");
VitaMTP_SendHostStatus(device, VITA_HOST_STATUS_EndConnection);
VitaMTP_Release_Device(device);
}
qDebug("QCMA thread end");
emit finished();
}
void QCMA::allowRefresh()
{
sema.release();
}
void QCMA::reload()
{
qDebug("Stopping QCMA workers...");
break_loop = true;
waitCondition.wakeAll();
sema.release();
}
void QCMA::stop()
{
exit_thread = true;
reload();
qDebug("Stopping QCMA thread...");
emit stopCMA();
}

70
qcma.h
View File

@@ -1,70 +0,0 @@
/*
* 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 QCMA_H
#define QCMA_H
#include "baseworker.h"
#include <QSystemTrayIcon>
#include <QThread>
#include <QWidget>
#include <QMenu>
#include <QWaitCondition>
#include <QSemaphore>
class QMenu;
extern "C" {
#include <vitamtp.h>
}
#define QCMA_VERSION_STRING "QCMA 0.1"
class QCMA : public BaseWorker
{
Q_OBJECT
public:
explicit QCMA(QObject *parent = 0);
private:
QSemaphore sema;
QWaitCondition waitCondition;
volatile bool break_loop;
volatile bool exit_thread;
vita_device_t *connectUsb();
vita_device_t *connectWireless();
signals:
void createdPin(int);
void deviceConnected(QString);
void statusUpdated(QString);
void deviceDisconnected();
void stopCMA();
public slots:
void stop();
void reload();
protected slots:
void allowRefresh();
virtual void process();
};
#endif // QCMA_H

View File

@@ -14,9 +14,7 @@ TARGET = qcma
TEMPLATE = app TEMPLATE = app
SOURCES += main.cpp \ SOURCES += main.cpp \
qcma.cpp \
wirelessworker.cpp \ wirelessworker.cpp \
listenerworker.cpp \
capability.cpp \ capability.cpp \
database.cpp \ database.cpp \
cmaobject.cpp \ cmaobject.cpp \
@@ -26,12 +24,12 @@ SOURCES += main.cpp \
configwidget.cpp \ configwidget.cpp \
singleapplication.cpp \ singleapplication.cpp \
baseworker.cpp \ baseworker.cpp \
sforeader.cpp sforeader.cpp \
cmaserver.cpp \
cmaclient.cpp
HEADERS += \ HEADERS += \
qcma.h \
wirelessworker.h \ wirelessworker.h \
listenerworker.h \
capability.h \ capability.h \
database.h \ database.h \
cmaobject.h \ cmaobject.h \
@@ -41,7 +39,9 @@ HEADERS += \
configwidget.h \ configwidget.h \
singleapplication.h \ singleapplication.h \
baseworker.h \ baseworker.h \
sforeader.h sforeader.h \
cmaserver.h \
cmaclient.h
CONFIG += link_pkgconfig CONFIG += link_pkgconfig
PKGCONFIG += libvitamtp libmediainfo PKGCONFIG += libvitamtp libmediainfo
@@ -52,7 +52,8 @@ RESOURCES += \
qcmares.qrc qcmares.qrc
OTHER_FILES += \ OTHER_FILES += \
psp2-updatelist.xml resources/psp2-updatelist.xml \
resources/psv_icon.png
FORMS += \ FORMS += \
configwidget.ui configwidget.ui

View File

@@ -1,5 +1,6 @@
<RCC> <RCC>
<qresource prefix="/main"> <qresource prefix="/main">
<file>psp2-updatelist.xml</file> <file>resources/psp2-updatelist.xml</file>
<file>resources/psv_icon.png</file>
</qresource> </qresource>
</RCC> </RCC>

BIN
resources/psv_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

View File

@@ -20,7 +20,6 @@
#include "singleapplication.h" #include "singleapplication.h"
#include <QDebug> #include <QDebug>
#include <QFile>
const int SingleApplication::timeout = 500; const int SingleApplication::timeout = 500;
const QString SingleApplication::SHARED_KEY = "QCMA_KEY"; const QString SingleApplication::SHARED_KEY = "QCMA_KEY";
@@ -30,15 +29,7 @@ SingleApplication::SingleApplication(int &argc, char **argv) :
{ {
server = new QLocalServer(this); server = new QLocalServer(this);
connect(server, SIGNAL(newConnection()), this, SLOT(receiveMessage())); connect(server, SIGNAL(newConnection()), this, SLOT(receiveMessage()));
#ifdef Q_OS_UNIX QLocalServer::removeServer(SHARED_KEY);
// Make sure that the socket file is deleted
QFile address(QString("/tmp/" + SHARED_KEY));
if(address.exists()) {
address.remove();
}
#endif
server->listen(SHARED_KEY); server->listen(SHARED_KEY);
} }

14
utils.h
View File

@@ -21,6 +21,20 @@
#define UTILS_H #define UTILS_H
#include <QString> #include <QString>
#include <QThread>
// Qt4 doesn't have public methods for Thread::*sleep
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
typedef QThread Sleeper;
#else
class Sleeper : QThread
{
public:
static void sleep(unsigned long secs) { QThread::sleep(secs); }
static void msleep(unsigned long msecs) { QThread::msleep(msecs); }
static void usleep(unsigned long usecs) { QThread::usleep(usecs); }
};
#endif
bool removeRecursively(const QString &dirName); bool removeRecursively(const QString &dirName);
bool getDiskSpace(const QString &dir, quint64 *free, quint64 *total); bool getDiskSpace(const QString &dir, quint64 *free, quint64 *total);

View File

@@ -17,32 +17,38 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "qcma.h"
#include "wirelessworker.h" #include "wirelessworker.h"
#include "utils.h"
#include <QTime> #include <QTime>
#include <QHostInfo> #include <QHostInfo>
#define QCMA_REQUEST_PORT 9309 #define QCMA_REQUEST_PORT 9309
wireless_host_info_t WirelessWorker::info = {"00000000-0000-0000-0000-000000000000", "win", NULL, QCMA_REQUEST_PORT}; wireless_host_info_t BroadcastSignal::info = {"00000000-0000-0000-0000-000000000000", "win", NULL, QCMA_REQUEST_PORT};
WirelessWorker *WirelessWorker::this_object = NULL; BroadcastSignal *BroadcastSignal::this_object = NULL;
WirelessWorker::WirelessWorker(QObject *parent) : BroadcastSignal::BroadcastSignal(QObject *parent) :
BaseWorker(parent) BaseWorker(parent)
{ {
qsrand(QTime::currentTime().msec()); qsrand(QTime::currentTime().msec());
this_object = this; this_object = this;
started = false;
} }
int WirelessWorker::deviceRegistered(const char *deviceid) BroadcastSignal::~BroadcastSignal()
{
VitaMTP_Stop_Broadcast();
}
int BroadcastSignal::deviceRegistered(const char *deviceid)
{ {
qDebug("Got connection request from %s", deviceid); qDebug("Got connection request from %s", deviceid);
return 1; return 1;
} }
int WirelessWorker::generatePin(wireless_vita_info_t *info, int *p_err) int BroadcastSignal::generatePin(wireless_vita_info_t *info, int *p_err)
{ {
qDebug("Registration request from %s (MAC: %s)", info->name, info->mac_addr); qDebug("Registration request from %s (MAC: %s)", info->name, info->mac_addr);
int pin = qrand() % 100000000; int pin = qrand() % 100000000;
@@ -52,25 +58,24 @@ int WirelessWorker::generatePin(wireless_vita_info_t *info, int *p_err)
return pin; return pin;
} }
void WirelessWorker::process() void BroadcastSignal::process()
{ {
qDebug() <<" Wireless thread ID: "<< QThread::currentThreadId(); qDebug() <<"Broadcast thread ID: "<< QThread::currentThreadId();
wireless_host_info_t broadcast_info = info;
QString hostname = QHostInfo::localHostName();
broadcast_info.name = hostname.toUtf8().data();
qDebug("Starting CMA wireless broadcast..."); qDebug("Starting CMA wireless broadcast...");
if(VitaMTP_Broadcast_Host(&broadcast_info, 0) < 0) {
started = true;
if(VitaMTP_Broadcast_Host(&info, 0) < 0) {
qCritical( "An error occured during broadcast. Exiting."); qCritical( "An error occured during broadcast. Exiting.");
} else { } else {
qDebug("Broadcast ended."); qDebug("Broadcast ended.");
} }
qDebug("WirelessrWorker thread end."); qDebug("Broadcast thread end.");
emit finished(); emit finished();
} }
void WirelessWorker::stopBroadcast() void BroadcastSignal::stopBroadcast()
{ {
qDebug("Stopping broadcast");
VitaMTP_Stop_Broadcast(); VitaMTP_Stop_Broadcast();
started = false;
} }

View File

@@ -29,21 +29,24 @@ extern "C" {
#include <vitamtp.h> #include <vitamtp.h>
} }
class WirelessWorker : public BaseWorker class BroadcastSignal : public BaseWorker
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit WirelessWorker(QObject *parent = 0); explicit BroadcastSignal(QObject *parent = 0);
~BroadcastSignal();
static int deviceRegistered(const char *deviceid); static int deviceRegistered(const char *deviceid);
static int generatePin(wireless_vita_info_t *info, int *p_err); static int generatePin(wireless_vita_info_t *info, int *p_err);
bool isRunning() { return started; }
static wireless_host_info_t info; static wireless_host_info_t info;
private: private:
volatile bool started;
//used to emit a signal from a static method //used to emit a signal from a static method
static WirelessWorker *this_object; static BroadcastSignal *this_object;
signals: signals:
void createdPin(int); void createdPin(int);