Files
qcma/qcma.cpp
codestation f9347f37cc First commit
2013-08-11 17:12:00 -04:30

175 lines
5.2 KiB
C++

/*
* 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();
}