Reimplemented CmaClient (again) to support concurrent connections.
This commit is contained in:
160
cmaclient.cpp
160
cmaclient.cpp
@@ -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();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
23
cmaclient.h
23
cmaclient.h
@@ -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
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
@@ -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();
|
||||||
|
Reference in New Issue
Block a user