Reimplemented CmaClient (again) to support concurrent connections.

This commit is contained in:
codestation
2013-08-20 16:53:38 -04:30
parent b23c009caf
commit bdb854808b
4 changed files with 148 additions and 123 deletions

View File

@@ -30,16 +30,97 @@
#include <QSettings> #include <QSettings>
#include <QUrl> #include <QUrl>
#include <MediaInfo/MediaInfo.h> QMutex CmaClient::mutex;
#include <MediaInfo/File__Analyse_Automatic.h> QMutex CmaClient::runner;
Database CmaClient::db;
bool CmaClient::is_running = true;
metadata_t CmaClient::g_thumbmeta = {0, 0, 0, NULL, NULL, 0, 0, 0, Thumbnail, {{18, 144, 80, 0, 1, 1.0f, 2}}, NULL}; metadata_t CmaClient::g_thumbmeta = {0, 0, 0, NULL, NULL, 0, 0, 0, Thumbnail, {{18, 144, 80, 0, 1, 1.0f, 2}}, NULL};
CmaClient *CmaClient::this_object = NULL; CmaClient *CmaClient::this_object = NULL;
CmaClient::CmaClient(QObject *parent) : CmaClient::CmaClient(QObject *parent) :
BaseWorker(parent) QObject(parent)
{ {
this_object = this; this_object = this;
device = NULL;
}
bool CmaClient::isRunning()
{
QMutexLocker locker(&runner);
return is_running;
}
void CmaClient::setRunning(bool state)
{
QMutexLocker locker(&runner);
is_running = state;
}
void CmaClient::connectUsb()
{
vita_device_t *vita;
int num_tries = 0;
qDebug() << "Starting usb_thread:" << QThread::currentThreadId();
while(isRunning()) {
if((vita = VitaMTP_Get_First_USB_Vita()) !=NULL) {
processNewConnection(vita);
} else {
qDebug("No Vita detected via USB, attempt %i", ++num_tries);
if(mutex.tryLock()) {
mutex.unlock();
Sleeper::msleep(2000);
}
}
}
qDebug("Finishing usb_thread");
emit finished();
}
void CmaClient::connectWireless()
{
vita_device_t *vita;
wireless_host_info_t host;
host.port = QCMA_REQUEST_PORT;
typedef CmaClient CC;
qDebug() << "Starting wireless_thread:" << QThread::currentThreadId();
while(isRunning()) {
if((vita = VitaMTP_Get_First_Wireless_Vita(&host, 0, 2, CC::deviceRegistered, CC::generatePin)) != NULL) {
processNewConnection(vita);
} else {
qDebug("Wireless listener was cancelled");
mutex.lock();
// wait until the event loop of the usb thread is finished
mutex.unlock();
}
}
qDebug("Finishing wireless_thread");
emit finished();
}
void CmaClient::processNewConnection(vita_device_t *device)
{
QMutexLocker locker(&mutex);
broadcast.setUnavailable();
this->device = device;
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");
} else {
// Conection successful, inform the user
emit deviceConnected(QString(tr("Connected to ")) + vita_info->getOnlineId());
enterEventLoop();
}
broadcast.setAvailable();
} }
int CmaClient::deviceRegistered(const char *deviceid) int CmaClient::deviceRegistered(const char *deviceid)
@@ -58,72 +139,16 @@ int CmaClient::generatePin(wireless_vita_info_t *info, int *p_err)
return pin; return pin;
} }
vita_device_t *CmaClient::getDeviceConnection()
{
int num_tries = 0;
vita_device_t *vita;
wireless_host_info_t host;
host.port = QCMA_REQUEST_PORT;
while(active) {
vita = VitaMTP_Get_First_USB_Vita();
if(vita || !active) {
break;
}
qDebug("No Vita detected via USB, attempt %i", ++num_tries);
vita = VitaMTP_Get_First_Wireless_Vita(&host, 0, 3, CmaClient::deviceRegistered, CmaClient::generatePin);
if(vita || !active) {
break;
}
qDebug("No Vita detected via wireless, attempt %i", ++num_tries);
}
return vita;
}
void CmaClient::process()
{
qDebug() << "Starting CmaClient:" << QThread::currentThreadId();
connect(&broadcast, SIGNAL(receivedPin(int)), this, SIGNAL(receivedPin(int)));
active = true;
while(active) {
if((device = getDeviceConnection()) == NULL) {
break;
}
broadcast.setUnavailable();
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();
broadcast.setAvailable();
continue;
}
// Conection successful, inform the user
emit deviceConnected(QString(tr("Connected to ")) + vita_info->getOnlineId());
connected = true;
enterEventLoop();
broadcast.setAvailable();
}
emit finished();
}
void CmaClient::enterEventLoop() void CmaClient::enterEventLoop()
{ {
vita_event_t event; vita_event_t event;
qDebug("Starting event loop"); qDebug("Starting event loop");
while(connected) { while(isRunning()) {
if(VitaMTP_Read_Event(device, &event) < 0) { if(VitaMTP_Read_Event(device, &event) < 0) {
qWarning("Error reading event from Vita."); qWarning("Error reading event from Vita.");
connected = false; setRunning(false);
break; break;
} }
@@ -372,7 +397,7 @@ 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; setRunning(false);
} }
void CmaClient::vitaEventUnimplementated(vita_event_t *event, int eventId) void CmaClient::vitaEventUnimplementated(vita_event_t *event, int eventId)
@@ -505,7 +530,7 @@ void CmaClient::vitaEventCancelTask(vita_event_t *event, int eventId)
int eventIdToCancel = event->Param2; int eventIdToCancel = event->Param2;
VitaMTP_CancelTask(device, eventIdToCancel); VitaMTP_CancelTask(device, eventIdToCancel);
qWarning("Event CancelTask (0x%x) unimplemented!", event->Code); qWarning("Event CancelTask (0x%x) unimplemented!", event->Code);
connected = false; setRunning(false);
} }
void CmaClient::vitaEventSendHttpObjectFromURL(vita_event_t *event, int eventId) void CmaClient::vitaEventSendHttpObjectFromURL(vita_event_t *event, int eventId)
@@ -951,20 +976,19 @@ void CmaClient::vitaEventCheckExistance(vita_event_t *event, int eventId)
void CmaClient::close() void CmaClient::close()
{ {
if(device) {
VitaMTP_SendHostStatus(device, VITA_HOST_STATUS_EndConnection); VitaMTP_SendHostStatus(device, VITA_HOST_STATUS_EndConnection);
VitaMTP_Release_Device(device); VitaMTP_Release_Device(device);
device = NULL;
}
} }
void CmaClient::stop() void CmaClient::stop()
{ {
active = false; CmaClient::setRunning(false);
connected = false;
waitCondition.wakeAll();
} }
CmaClient::~CmaClient() CmaClient::~CmaClient()
{ {
if(device) {
close(); close();
}
} }

View File

@@ -33,18 +33,23 @@ extern "C" {
#include <vitamtp.h> #include <vitamtp.h>
} }
class CmaClient : public BaseWorker class CmaClient : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CmaClient(QObject *parent = 0); explicit CmaClient(QObject *parent = 0);
~CmaClient(); ~CmaClient();
Database db; void launch();
static Database db;
private: private:
static bool isRunning();
static void setRunning(bool state);
void enterEventLoop(); void enterEventLoop();
vita_device_t *getDeviceConnection();
void processNewConnection(vita_device_t *device);
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);
@@ -72,13 +77,13 @@ private:
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);
QWaitCondition waitCondition;
CmaBroadcast broadcast; CmaBroadcast broadcast;
vita_device_t *device; vita_device_t *device;
volatile bool active; static bool is_running;
volatile bool connected;
static metadata_t g_thumbmeta; static metadata_t g_thumbmeta;
static CmaClient *this_object; static CmaClient *this_object;
static QMutex mutex;
static QMutex runner;
signals: signals:
void receivedPin(int); void receivedPin(int);
@@ -86,13 +91,15 @@ signals:
void deviceConnected(QString); void deviceConnected(QString);
void deviceDisconnected(); void deviceDisconnected();
void refreshDatabase(); void refreshDatabase();
void finished();
public slots: public slots:
void close(); void close();
void stop(); static void stop();
private slots: private slots:
void process(); void connectUsb();
void connectWireless();
}; };
#endif // CMACLIENT_H #endif // CMACLIENT_H

View File

@@ -65,22 +65,46 @@ void MainWidget::dialogResult(int result)
void MainWidget::startServer() void MainWidget::startServer()
{ {
qDebug("Starting cma event loop"); qDebug("Starting cma threads");
clientLoop.start("CmaClient"); QThread *thread;
CmaClient *client;
thread = new QThread();
client = new CmaClient();
thread->setObjectName("usb_thread");
connect(thread, SIGNAL(started()), client, SLOT(connectUsb()));
connect(client, SIGNAL(receivedPin(int)), this, SLOT(showPin(int)));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), client, SLOT(deleteLater()));
connectClientSignals(client);
client->moveToThread(thread);
thread->start();
thread = new QThread();
client = new CmaClient();
thread->setObjectName("wireless_thread");
connect(thread, SIGNAL(started()), client, SLOT(connectWireless()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), client, SLOT(deleteLater()));
connectClientSignals(client);
client->moveToThread(thread);
thread->start();
} }
void MainWidget::stopServer() void MainWidget::stopServer()
{ {
clientLoop.stop(); CmaClient::stop();
qApp->quit();
} }
void MainWidget::refreshDatabase() void MainWidget::refreshDatabase()
{ {
clientLoop.db.mutex.lock(); QMutexLocker locker(&CmaClient::db.mutex);
clientLoop.db.destroy();
int count = clientLoop.db.create(); CmaClient::db.destroy();
int count = CmaClient::db.create();
qDebug("Added %i entries to the database", count); qDebug("Added %i entries to the database", count);
clientLoop.db.mutex.unlock();
} }
void MainWidget::deviceDisconnect() void MainWidget::deviceDisconnect()
@@ -89,15 +113,12 @@ void MainWidget::deviceDisconnect()
receiveMessage(tr("The device has been disconnected")); receiveMessage(tr("The device has been disconnected"));
} }
void MainWidget::connectSignals() void MainWidget::connectClientSignals(CmaClient *client)
{ {
connect(&dialog, SIGNAL(finished(int)), this, SLOT(dialogResult(int))); connect(client, SIGNAL(deviceConnected(QString)), this, SLOT(receiveMessage(QString)));
connect(&clientLoop, SIGNAL(receivedPin(int)), this, SLOT(showPin(int))); connect(client, SIGNAL(deviceConnected(QString)), this, SLOT(setTrayTooltip(QString)));
connect(&clientLoop, SIGNAL(deviceConnected(QString)), this, SLOT(receiveMessage(QString))); connect(client, SIGNAL(deviceDisconnected()), this, SLOT(deviceDisconnect()));
connect(&clientLoop, SIGNAL(deviceConnected(QString)), this, SLOT(setTrayTooltip(QString))); connect(client, SIGNAL(refreshDatabase()), this, SLOT(refreshDatabase()));
connect(&clientLoop, SIGNAL(deviceDisconnected()), this, SLOT(deviceDisconnect()));
connect(&clientLoop, SIGNAL(refreshDatabase()), this, SLOT(refreshDatabase()));
connect(&clientLoop, SIGNAL(finished()), qApp, SLOT(quit()));
} }
void MainWidget::showPin(int pin) void MainWidget::showPin(int pin)
@@ -107,7 +128,7 @@ void MainWidget::showPin(int pin)
void MainWidget::prepareApplication() void MainWidget::prepareApplication()
{ {
connectSignals(); connect(&dialog, SIGNAL(finished(int)), this, SLOT(dialogResult(int)));
createTrayIcon(); createTrayIcon();
checkSettings(); checkSettings();
refreshDatabase(); refreshDatabase();
@@ -118,31 +139,8 @@ void MainWidget::setTrayTooltip(QString message)
trayIcon->setToolTip(message); trayIcon->setToolTip(message);
} }
void MainWidget::toggleWireless()
{
QSettings settings;
if(wireless->isChecked()) {
wireless->setText(tr("&Wireless enabled"));
settings.setValue("wireless", true);
} else {
wireless->setText(tr("&Wireless disabled"));
settings.setValue("wireless", false);
}
}
void MainWidget::createTrayIcon() void MainWidget::createTrayIcon()
{ {
QSettings settings;
wireless = new QAction(this);
wireless->setCheckable(true);
if(settings.value("wireless", false).toBool()) {
wireless->setText(tr("&Wireless enabled"));
wireless->setChecked(true);
} else {
wireless->setText(tr("&Wireless disabled"));
}
options = new QAction(tr("&Settings"), this); options = new QAction(tr("&Settings"), this);
reload = new QAction(tr("&Refresh database"), this); reload = new QAction(tr("&Refresh database"), this);
quit = new QAction(tr("&Quit"), this); quit = new QAction(tr("&Quit"), this);
@@ -150,12 +148,10 @@ void MainWidget::createTrayIcon()
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()), this, SLOT(stopServer())); connect(quit, SIGNAL(triggered()), this, SLOT(stopServer()));
connect(wireless, SIGNAL(triggered()), this, SLOT(toggleWireless()));
QMenu *trayIconMenu = new QMenu(this); QMenu *trayIconMenu = new QMenu(this);
trayIconMenu->addAction(options); trayIconMenu->addAction(options);
trayIconMenu->addAction(reload); trayIconMenu->addAction(reload);
trayIconMenu->addAction(wireless);
trayIconMenu->addSeparator(); trayIconMenu->addSeparator();
trayIconMenu->addAction(quit); trayIconMenu->addAction(quit);

View File

@@ -46,7 +46,7 @@ public:
private: private:
void createTrayIcon(); void createTrayIcon();
void checkSettings(); void checkSettings();
void connectSignals(); void connectClientSignals(CmaClient *client);
bool first_run; bool first_run;
ConfigWidget dialog; ConfigWidget dialog;
@@ -54,7 +54,6 @@ private:
QAction *quit; QAction *quit;
QAction *reload; QAction *reload;
QAction *options; QAction *options;
QAction *wireless;
CmaClient clientLoop; CmaClient clientLoop;
const static QStringList path_list; const static QStringList path_list;
@@ -63,7 +62,6 @@ private slots:
void dialogResult(int result); void dialogResult(int result);
void receiveMessage(QString message); void receiveMessage(QString message);
void setTrayTooltip(QString message); void setTrayTooltip(QString message);
void toggleWireless();
void showPin(int pin); void showPin(int pin);
void refreshDatabase(); void refreshDatabase();
void startServer(); void startServer();