/* * 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 . */ #include "cmaclient.h" #include "capability.h" #include "avdecoder.h" #include "cmaevent.h" #include "utils.h" #include "QApplication" #include #include #include #include #include #include QMutex CmaClient::mutex; QMutex CmaClient::runner; QMutex CmaClient::eloop; bool CmaClient::is_running = true; bool CmaClient::event_loop_enabled = true; CmaClient *CmaClient::this_object = NULL; CmaClient::CmaClient(QObject *parent) : QObject(parent) { 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) { cancel_wireless = 1; processNewConnection(vita); } else { //qDebug("No Vita detected via USB, attempt %i", +num_tries++); if(mutex.tryLock()) { mutex.unlock(); Sleeper::msleep(2000); } else { mutex.lock(); mutex.unlock(); } } } 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; cancel_wireless = 0; qDebug() << "Starting wireless_thread:" << QThread::currentThreadId(); while(isRunning()) { if((vita = VitaMTP_Get_First_Wireless_Vita(&host, 0, &cancel_wireless, CC::deviceRegistered, CC::generatePin)) != NULL) { processNewConnection(vita); } else { qDebug("Wireless listener was cancelled"); // wait until the event loop of the usb thread is finished mutex.lock(); cancel_wireless = 0; 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) { qDebug("Got connection request from %s", deviceid); return 1; } int CmaClient::generatePin(wireless_vita_info_t *info, int *p_err) { qDebug("Registration request from %s (MAC: %s)", info->name, info->mac_addr); int pin = qrand() % 100000000; qDebug("Your registration PIN for %s is: %08d", info->name, pin); *p_err = 0; emit this_object->receivedPin(pin); return pin; } void CmaClient::enterEventLoop() { vita_event_t event; qDebug("Starting event loop"); event_loop_enabled = true; while(isEventLoopEnabled()) { if(VitaMTP_Read_Event(device, &event) < 0) { qWarning("Error reading event from Vita."); break; } CmaEvent *vita_event = new CmaEvent(device, event); connect(vita_event, SIGNAL(finishedEventLoop()), this, SLOT(finishEventLoop())); connect(vita_event, SIGNAL(refreshDatabase()), this, SIGNAL(refreshDatabase())); vita_event->start("cma_event"); } } bool CmaClient::isEventLoopEnabled() { QMutexLocker locker(&eloop); return event_loop_enabled; } void CmaClient::finishEventLoop() { QMutexLocker locker(&eloop); event_loop_enabled = false; } void CmaClient::close() { if(device) { VitaMTP_SendHostStatus(device, VITA_HOST_STATUS_EndConnection); VitaMTP_Release_Device(device); device = NULL; } } void CmaClient::stop() { CmaClient::setRunning(false); CmaClient::finishEventLoop(); } CmaClient::~CmaClient() { close(); }