mirror of
https://github.com/iDescriptor/iDescriptor.git
synced 2026-06-21 19:35:49 +08:00
feat: introduce Rust into the codebase
- Rewrite DeviceMonitorThread in Rust (idevice_monitor) - Enhanced ServiceManager to check for application shutdown before executing operations. - Introduced auto-connect feature for wireless devices in SettingsManager. - Updated SettingsWidget to include UI elements for auto-connecting wireless devices. - Make import button work in gallerywidget
This commit is contained in:
@@ -317,6 +317,27 @@ endif()
|
||||
# Make sure idevice_cpp depends on the Rust library being built
|
||||
add_dependencies(idevice_cpp idevice_rs_build)
|
||||
|
||||
|
||||
set(RUST_MONITOR_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/rust)
|
||||
set(RUST_MONITOR_LIB_PATH ${RUST_MONITOR_SOURCE_DIR}/target/debug/libidevice_monitor.a)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${RUST_MONITOR_LIB_PATH}
|
||||
COMMAND ${CARGO_EXECUTABLE} build --manifest-path ${RUST_MONITOR_SOURCE_DIR}/Cargo.toml
|
||||
WORKING_DIRECTORY ${RUST_MONITOR_SOURCE_DIR}
|
||||
COMMENT "Building Rust device monitor library"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
add_custom_target(rust_device_monitor_build DEPENDS ${RUST_MONITOR_LIB_PATH})
|
||||
|
||||
add_library(idevice_monitor STATIC IMPORTED GLOBAL)
|
||||
set_target_properties(idevice_monitor PROPERTIES
|
||||
IMPORTED_LOCATION "${RUST_MONITOR_LIB_PATH}"
|
||||
)
|
||||
|
||||
add_dependencies(idevice_monitor rust_device_monitor_build)
|
||||
|
||||
target_link_libraries(iDescriptor PRIVATE
|
||||
Qt6::Widgets
|
||||
Qt6::Multimedia
|
||||
@@ -347,6 +368,7 @@ target_link_libraries(iDescriptor PRIVATE
|
||||
# ZToast
|
||||
${IDEVICE_IMPLEMENTATION_LIBS}
|
||||
SQLite::SQLite3
|
||||
idevice_monitor
|
||||
)
|
||||
|
||||
if(ENABLE_RECOVERY_DEVICE_SUPPORT)
|
||||
@@ -363,6 +385,7 @@ target_include_directories(iDescriptor PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/zupdater/src
|
||||
# System includes last
|
||||
${IDEVICE_IMPLEMENTATION_INCLUDES}
|
||||
${RUST_MONITOR_SOURCE_DIR}/include
|
||||
)
|
||||
|
||||
|
||||
|
||||
+16
-19
@@ -18,16 +18,6 @@
|
||||
*/
|
||||
|
||||
#include "appcontext.h"
|
||||
#include "devicemonitor.h"
|
||||
#include "iDescriptor.h"
|
||||
#include "mainwindow.h"
|
||||
#include "settingsmanager.h"
|
||||
#include <QDebug>
|
||||
#include <QMessageBox>
|
||||
#include <QThreadPool>
|
||||
#include <QTimer>
|
||||
#include <QUuid>
|
||||
#include <thread>
|
||||
|
||||
AppContext *AppContext::sharedInstance()
|
||||
{
|
||||
@@ -186,7 +176,7 @@ void AppContext::cachePairedDevices()
|
||||
}
|
||||
|
||||
void AppContext::addDevice(iDescriptor::Uniq uniq,
|
||||
DeviceMonitorThread::IdeviceConnectionType conn_type,
|
||||
iDescriptor::IdeviceConnectionType conn_type,
|
||||
AddType addType, QString wifiMacAddress,
|
||||
QString ipAddress)
|
||||
{
|
||||
@@ -524,8 +514,8 @@ void AppContext::tryToConnectToNetworkDevice(const NetworkDevice &device)
|
||||
QMetaObject::invokeMethod(
|
||||
AppContext::sharedInstance(), "addDevice", Qt::QueuedConnection,
|
||||
Q_ARG(iDescriptor::Uniq, iDescriptor::Uniq(device.macAddress, true)),
|
||||
Q_ARG(DeviceMonitorThread::IdeviceConnectionType,
|
||||
DeviceMonitorThread::CONNECTION_NETWORK),
|
||||
Q_ARG(iDescriptor::IdeviceConnectionType,
|
||||
iDescriptor::CONNECTION_NETWORK),
|
||||
Q_ARG(AddType, AddType::Wireless), Q_ARG(QString, device.macAddress),
|
||||
Q_ARG(QString, device.address));
|
||||
}
|
||||
@@ -552,6 +542,7 @@ void AppContext::freeDevice(iDescriptorDevice *device)
|
||||
lockdownd_client_free(device->lockdown);
|
||||
idevice_provider_free(device->provider);
|
||||
delete device;
|
||||
device = nullptr;
|
||||
}
|
||||
|
||||
void AppContext::handlePairing(iDescriptorInitDeviceResult *initResult,
|
||||
@@ -559,10 +550,16 @@ void AppContext::handlePairing(iDescriptorInitDeviceResult *initResult,
|
||||
{
|
||||
qDebug() << "[handlePairing] for device" << uniq;
|
||||
emit initFailed(uniq);
|
||||
if (initResult->error &&
|
||||
initResult->error->code == PairingDialogResponsePending ||
|
||||
initResult->error->code == InvalidHostID ||
|
||||
initResult->error->code == PasswordProtected) {
|
||||
|
||||
if (!initResult || !initResult->error) {
|
||||
qDebug() << "[handlePairing] initResult->error is null for" << uniq
|
||||
<< "- skipping pairing handling";
|
||||
return;
|
||||
}
|
||||
|
||||
const auto code = initResult->error->code;
|
||||
if (code == PairingDialogResponsePending || code == InvalidHostID ||
|
||||
code == PasswordProtected) {
|
||||
if (addType == AddType::Regular) {
|
||||
m_pendingDevices.append(uniq);
|
||||
emit devicePasswordProtected(uniq);
|
||||
@@ -687,8 +684,8 @@ void AppContext::handlePairing(iDescriptorInitDeviceResult *initResult,
|
||||
AppContext::sharedInstance(), "addDevice",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(iDescriptor::Uniq, uniq),
|
||||
Q_ARG(DeviceMonitorThread::IdeviceConnectionType,
|
||||
DeviceMonitorThread::IdeviceConnectionType::
|
||||
Q_ARG(iDescriptor::IdeviceConnectionType,
|
||||
iDescriptor::IdeviceConnectionType::
|
||||
CONNECTION_NETWORK),
|
||||
Q_ARG(AddType, AddType::Regular));
|
||||
ok = true;
|
||||
|
||||
+10
-3
@@ -20,11 +20,18 @@
|
||||
#ifndef APPCONTEXT_H
|
||||
#define APPCONTEXT_H
|
||||
|
||||
#include "devicemonitor.h"
|
||||
#include "devicesidebarwidget.h"
|
||||
#include "heartbeat.h"
|
||||
#include "iDescriptor.h"
|
||||
#include "mainwindow.h"
|
||||
#include "settingsmanager.h"
|
||||
#include <QDebug>
|
||||
#include <QMessageBox>
|
||||
#include <QObject>
|
||||
#include <QThreadPool>
|
||||
#include <QTimer>
|
||||
#include <QUuid>
|
||||
#include <thread>
|
||||
|
||||
class AppContext : public QObject
|
||||
{
|
||||
@@ -96,8 +103,8 @@ signals:
|
||||
public slots:
|
||||
void removeDevice(iDescriptor::Uniq uniq);
|
||||
void addDevice(iDescriptor::Uniq udid,
|
||||
DeviceMonitorThread::IdeviceConnectionType connType,
|
||||
AddType addType, QString wifiMacAddress = QString(),
|
||||
iDescriptor::IdeviceConnectionType connType, AddType addType,
|
||||
QString wifiMacAddress = QString(),
|
||||
QString ipAddress = QString());
|
||||
void heartbeatFailed(const QString &macAddress, int tries);
|
||||
// void heartbeatThreadExited(const QString &macAddress);
|
||||
|
||||
@@ -42,7 +42,7 @@ DeviceManagerWidget::DeviceManagerWidget(QWidget *parent)
|
||||
DeviceSelection(device->udid));
|
||||
});
|
||||
|
||||
emit updateNoDevicesConnected();
|
||||
updateUI();
|
||||
});
|
||||
|
||||
connect(AppContext::sharedInstance(), &AppContext::deviceRemoved, this,
|
||||
@@ -52,19 +52,19 @@ DeviceManagerWidget::DeviceManagerWidget(QWidget *parent)
|
||||
if (!devices.isEmpty())
|
||||
AppContext::sharedInstance()->setCurrentDeviceSelection(
|
||||
DeviceSelection(devices.first()->udid));
|
||||
emit updateNoDevicesConnected();
|
||||
updateUI();
|
||||
});
|
||||
|
||||
connect(AppContext::sharedInstance(), &AppContext::devicePairPending, this,
|
||||
[this](const QString &udid) {
|
||||
addPendingDevice(udid, false);
|
||||
emit updateNoDevicesConnected();
|
||||
updateUI();
|
||||
});
|
||||
|
||||
connect(AppContext::sharedInstance(), &AppContext::devicePasswordProtected,
|
||||
this, [this](const QString &udid) {
|
||||
addPendingDevice(udid, true);
|
||||
emit updateNoDevicesConnected();
|
||||
updateUI();
|
||||
});
|
||||
|
||||
connect(AppContext::sharedInstance(), &AppContext::devicePaired, this,
|
||||
@@ -77,27 +77,27 @@ DeviceManagerWidget::DeviceManagerWidget(QWidget *parent)
|
||||
// DeviceSelection(device->udid));
|
||||
// });
|
||||
|
||||
emit updateNoDevicesConnected();
|
||||
updateUI();
|
||||
});
|
||||
|
||||
#ifdef ENABLE_RECOVERY_DEVICE_SUPPORT
|
||||
connect(AppContext::sharedInstance(), &AppContext::recoveryDeviceAdded,
|
||||
this, [this](const iDescriptorRecoveryDevice *recoveryDeviceInfo) {
|
||||
addRecoveryDevice(recoveryDeviceInfo);
|
||||
emit updateNoDevicesConnected();
|
||||
updateUI();
|
||||
});
|
||||
|
||||
connect(AppContext::sharedInstance(), &AppContext::recoveryDeviceRemoved,
|
||||
this, [this](uint64_t ecid) {
|
||||
removeRecoveryDevice(ecid);
|
||||
emit updateNoDevicesConnected();
|
||||
updateUI();
|
||||
});
|
||||
#endif
|
||||
|
||||
connect(AppContext::sharedInstance(), &AppContext::devicePairingExpired,
|
||||
this, [this](const QString &udid) {
|
||||
removePendingDevice(udid);
|
||||
emit updateNoDevicesConnected();
|
||||
updateUI();
|
||||
});
|
||||
onDeviceSelectionChanged(
|
||||
AppContext::sharedInstance()->getCurrentDeviceSelection());
|
||||
@@ -109,6 +109,11 @@ void DeviceManagerWidget::setupUI()
|
||||
m_mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
m_mainLayout->setSpacing(0);
|
||||
|
||||
m_noDevicesLabel = new QLabel("This is where devices will appear", this);
|
||||
m_noDevicesLabel->setFont(QFont("", 20, QFont::Bold));
|
||||
m_noDevicesLabel->setAlignment(Qt::AlignCenter);
|
||||
m_noDevicesLabel->setWordWrap(true);
|
||||
|
||||
// Create sidebar
|
||||
m_sidebar = new DeviceSidebarWidget();
|
||||
|
||||
@@ -353,4 +358,31 @@ void DeviceManagerWidget::onDeviceSelectionChanged(
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceManagerWidget::updateUI()
|
||||
{
|
||||
emit updateNoDevicesConnected();
|
||||
m_noDevicesLabel->setVisible(
|
||||
AppContext::sharedInstance()->noDevicesConnected());
|
||||
}
|
||||
|
||||
void DeviceManagerWidget::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QWidget::resizeEvent(event);
|
||||
|
||||
if (!m_noDevicesLabel)
|
||||
return;
|
||||
|
||||
const int margin = 10;
|
||||
int maxWidth = qMax(0, width() - 2 * margin);
|
||||
m_noDevicesLabel->setMaximumWidth(maxWidth);
|
||||
m_noDevicesLabel->adjustSize();
|
||||
|
||||
int x = (width() - m_noDevicesLabel->width()) / 2;
|
||||
int y = (height() - m_noDevicesLabel->height()) / 2;
|
||||
x = qMax(margin, x);
|
||||
y = qMax(margin, y);
|
||||
|
||||
m_noDevicesLabel->move(x, y);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#ifndef DEVICEMANAGERWIDGET_H
|
||||
#define DEVICEMANAGERWIDGET_H
|
||||
|
||||
class DeviceMenuWidget;
|
||||
|
||||
#include "devicemenuwidget.h"
|
||||
#include "devicependingwidget.h"
|
||||
#include "devicesidebarwidget.h"
|
||||
@@ -52,9 +54,12 @@ signals:
|
||||
private slots:
|
||||
void onDeviceSelectionChanged(const DeviceSelection &selection);
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
private:
|
||||
void setupUI();
|
||||
|
||||
void updateUI();
|
||||
void addDevice(const iDescriptorDevice *device);
|
||||
void removeDevice(const std::string &uuid);
|
||||
#ifdef ENABLE_RECOVERY_DEVICE_SUPPORT
|
||||
@@ -83,6 +88,7 @@ private:
|
||||
#endif
|
||||
|
||||
std::string m_currentDeviceUuid;
|
||||
QLabel *m_noDevicesLabel = nullptr;
|
||||
};
|
||||
|
||||
#endif // DEVICEMANAGERWIDGET_H
|
||||
@@ -1,126 +0,0 @@
|
||||
#ifndef DEVICEMONITOR_H
|
||||
#define DEVICEMONITOR_H
|
||||
#include <QDebug>
|
||||
#include <QThread>
|
||||
#include <idevice++/bindings.hpp>
|
||||
#include <idevice++/core_device_proxy.hpp>
|
||||
#include <idevice++/dvt/remote_server.hpp>
|
||||
#include <idevice++/dvt/screenshot.hpp>
|
||||
#include <idevice++/ffi.hpp>
|
||||
#include <idevice++/provider.hpp>
|
||||
#include <idevice++/readwrite.hpp>
|
||||
#include <idevice++/rsd.hpp>
|
||||
#include <idevice++/usbmuxd.hpp>
|
||||
|
||||
using namespace IdeviceFFI;
|
||||
|
||||
class DeviceMonitorThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DeviceMonitorThread(QObject *parent = nullptr) : QThread(parent) {}
|
||||
|
||||
void run() override
|
||||
{
|
||||
while (!isInterruptionRequested()) {
|
||||
// Create connection
|
||||
UsbmuxdConnectionHandle *usbmuxd_conn;
|
||||
IdeviceFfiError *err =
|
||||
idevice_usbmuxd_new_default_connection(0, &usbmuxd_conn);
|
||||
if (err) {
|
||||
idevice_error_free(err);
|
||||
QThread::msleep(1000); // Wait before retry
|
||||
continue;
|
||||
}
|
||||
|
||||
UsbmuxdListenerHandle *listener;
|
||||
err = idevice_usbmuxd_listen(usbmuxd_conn, &listener);
|
||||
if (err) {
|
||||
idevice_usbmuxd_connection_free(usbmuxd_conn);
|
||||
idevice_error_free(err);
|
||||
QThread::msleep(1000);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Monitor loop
|
||||
while (!isInterruptionRequested()) {
|
||||
bool connect = false;
|
||||
UsbmuxdDeviceHandle *device;
|
||||
uint32_t disconnect_id;
|
||||
|
||||
err = idevice_usbmuxd_listener_next(listener, &connect, &device,
|
||||
&disconnect_id);
|
||||
qDebug() << "Listening for device connections..." << err
|
||||
<< connect;
|
||||
if (err) {
|
||||
// Check if it's just the stream ending (no devices)
|
||||
if (err->code == -1) { // Socket error code
|
||||
qDebug() << "Listener stream ended, reconnecting...";
|
||||
idevice_error_free(err);
|
||||
break; // Break inner loop to reconnect
|
||||
} else {
|
||||
qDebug() << "Real error:" << err->message;
|
||||
idevice_error_free(err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (connect) {
|
||||
const char *udid = idevice_usbmuxd_device_get_udid(device);
|
||||
uint32_t device_id =
|
||||
idevice_usbmuxd_device_get_device_id(device);
|
||||
uint8_t conn_type =
|
||||
idevice_usbmuxd_device_get_connection_type(device);
|
||||
|
||||
// Skip network devices (same as original callback)
|
||||
if (conn_type == CONNECTION_NETWORK) {
|
||||
qDebug() << "Skipping network device:" << QString(udid);
|
||||
idevice_usbmuxd_device_free(device);
|
||||
continue;
|
||||
}
|
||||
|
||||
deviceMap[device_id] = QString(udid);
|
||||
qDebug()
|
||||
<< "[DeviceMonitor] Device connected:" << QString(udid);
|
||||
|
||||
emit deviceEvent(IDEVICE_DEVICE_ADD, QString(udid),
|
||||
conn_type, AddType::Regular);
|
||||
idevice_usbmuxd_device_free(device);
|
||||
} else {
|
||||
QString udid = deviceMap.value(disconnect_id, QString());
|
||||
if (!udid.isEmpty()) {
|
||||
emit deviceEvent(IDEVICE_DEVICE_REMOVE, udid,
|
||||
CONNECTION_USB, AddType::Regular);
|
||||
deviceMap.remove(disconnect_id);
|
||||
} else {
|
||||
qDebug() << "Unknown device disconnected please report "
|
||||
"this issue: "
|
||||
<< disconnect_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup before reconnecting
|
||||
idevice_usbmuxd_listener_handle_free(listener);
|
||||
idevice_usbmuxd_connection_free(usbmuxd_conn);
|
||||
}
|
||||
}
|
||||
|
||||
enum IdeviceEventType {
|
||||
IDEVICE_DEVICE_ADD = 1,
|
||||
IDEVICE_DEVICE_REMOVE = 2,
|
||||
IDEVICE_DEVICE_PAIRED = 3
|
||||
};
|
||||
|
||||
enum IdeviceConnectionType { CONNECTION_USB = 1, CONNECTION_NETWORK = 2 };
|
||||
|
||||
enum AddType { Regular = 0, Pairing = 1 };
|
||||
|
||||
signals:
|
||||
void deviceEvent(int event, const QString &udid, int conn_type,
|
||||
int addType);
|
||||
|
||||
private:
|
||||
QMap<uint32_t, QString> deviceMap;
|
||||
};
|
||||
#endif // DEVICEMONITOR_H
|
||||
@@ -174,6 +174,9 @@ void GalleryWidget::setupControlsLayout()
|
||||
connect(m_backButton, &ZIconWidget::clicked, this,
|
||||
&GalleryWidget::onBackToAlbums);
|
||||
|
||||
connect(m_importButton, &QPushButton::clicked, this,
|
||||
&GalleryWidget::handleImport);
|
||||
|
||||
// Add widgets to layout
|
||||
m_controlsLayout->addWidget(m_backButton);
|
||||
m_controlsLayout->addWidget(m_importButton);
|
||||
@@ -700,6 +703,23 @@ void GalleryWidget::onPhotoContextMenu(const QPoint &pos)
|
||||
contextMenu.exec(m_listView->viewport()->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void GalleryWidget::handleImport()
|
||||
{
|
||||
QStringList filePaths = QFileDialog::getOpenFileNames(
|
||||
this, "Select Photos to Import",
|
||||
QStandardPaths::writableLocation(QStandardPaths::PicturesLocation),
|
||||
"Images (*.jpg *.jpeg *.png *.heic);;All Files (*)");
|
||||
|
||||
if (filePaths.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "Selected files for import:" << filePaths;
|
||||
|
||||
PhotoImportDialog dialog(filePaths, this);
|
||||
dialog.exec();
|
||||
}
|
||||
|
||||
GalleryWidget::~GalleryWidget()
|
||||
{
|
||||
qDebug() << "GalleryWidget destructor called";
|
||||
|
||||
@@ -23,8 +23,10 @@
|
||||
#include "exportalbum.h"
|
||||
#include "iDescriptor-ui.h"
|
||||
#include "iDescriptor.h"
|
||||
#include "photoimportdialog.h"
|
||||
#include "photomodel.h"
|
||||
#include "zloadingwidget.h"
|
||||
#include <QStringList>
|
||||
#include <QWidget>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@@ -72,6 +74,7 @@ private:
|
||||
void loadAlbumThumbnailAsync(const QString &albumPath, QStandardItem *item);
|
||||
void onPhotoContextMenu(const QPoint &pos);
|
||||
PhotoModel::FilterType getCurrentFilterType() const;
|
||||
void handleImport();
|
||||
|
||||
const iDescriptorDevice *m_device;
|
||||
bool m_loaded = false;
|
||||
|
||||
+11
-3
@@ -26,7 +26,6 @@
|
||||
#include <QThread>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
// #include "idevice.h"
|
||||
#include <idevice++/bindings.hpp>
|
||||
#include <idevice++/core_device_proxy.hpp>
|
||||
#include <idevice++/diagnostics_relay.hpp>
|
||||
@@ -67,7 +66,6 @@
|
||||
#define POSSIBLE_ROOT "../../../../"
|
||||
#define IDEVICE_DEVICE_VERSION(maj, min, patch) \
|
||||
((((maj) & 0xFF) << 16) | (((min) & 0xFF) << 8) | ((patch) & 0xFF))
|
||||
#include "devicemonitor.h"
|
||||
#include "iDescriptor-utils.h"
|
||||
#ifdef ENABLE_RECOVERY_DEVICE_SUPPORT
|
||||
#include <libirecovery.h>
|
||||
@@ -98,6 +96,16 @@
|
||||
#define LOCKDOWN_PATH qgetenv("PROGRAMDATA") + "/Apple/Lockdown"
|
||||
#endif
|
||||
|
||||
// idevice_monitor (rust ffi)
|
||||
extern "C" {
|
||||
#include "idevice_monitor.h"
|
||||
}
|
||||
namespace iDescriptor
|
||||
{
|
||||
enum IdeviceConnectionType { CONNECTION_USB = 1, CONNECTION_NETWORK = 2 };
|
||||
}
|
||||
using namespace IdeviceFFI;
|
||||
|
||||
struct BatteryInfo {
|
||||
QString health;
|
||||
uint64_t cycleCount;
|
||||
@@ -231,7 +239,7 @@ class HeartbeatThread;
|
||||
|
||||
struct iDescriptorDevice {
|
||||
std::string udid;
|
||||
DeviceMonitorThread::IdeviceConnectionType conn_type;
|
||||
iDescriptor::IdeviceConnectionType conn_type;
|
||||
IdeviceProviderHandle *provider;
|
||||
DeviceInfo deviceInfo;
|
||||
AfcClientHandle *afcClient;
|
||||
|
||||
@@ -166,6 +166,14 @@ InstalledAppsWidget::InstalledAppsWidget(const iDescriptorDevice *device,
|
||||
|
||||
InstalledAppsWidget::~InstalledAppsWidget()
|
||||
{
|
||||
if (m_watcher) {
|
||||
m_watcher->cancel();
|
||||
m_watcher->waitForFinished();
|
||||
}
|
||||
if (m_containerWatcher) {
|
||||
m_containerWatcher->cancel();
|
||||
m_containerWatcher->waitForFinished();
|
||||
}
|
||||
cleanupHouseArrestClients();
|
||||
if (m_springboardClient) {
|
||||
springboard_services_free(m_springboardClient);
|
||||
@@ -290,6 +298,12 @@ void InstalledAppsWidget::fetchInstalledApps()
|
||||
// todo maybe clear m_watcher ?
|
||||
QFuture<QVariantMap> future = QtConcurrent::run([this]() -> QVariantMap {
|
||||
QVariantMap result;
|
||||
|
||||
if (QCoreApplication::closingDown() || !m_device) {
|
||||
return result;
|
||||
}
|
||||
std::lock_guard<std::recursive_mutex> lock(m_device->mutex);
|
||||
|
||||
QVariantList apps;
|
||||
// fetch icon from springboard service
|
||||
IdeviceFfiError *err = nullptr;
|
||||
|
||||
+33
-63
@@ -73,6 +73,30 @@ void handleCallbackRecovery(const irecv_device_event_t *event, void *userData)
|
||||
irecv_device_event_context_t context;
|
||||
#endif
|
||||
|
||||
void handleCallback(const IdeviceEvent *e)
|
||||
{
|
||||
QString udid = QString::fromUtf8(e->udid);
|
||||
qDebug() << "Device event: "
|
||||
<< (e->kind == 1 ? "Connected" : "Disconnected")
|
||||
<< ", UDID: " << udid;
|
||||
free(e->udid);
|
||||
bool isConnected = (e->kind == 1);
|
||||
|
||||
if (isConnected) {
|
||||
QMetaObject::invokeMethod(
|
||||
AppContext::sharedInstance(), "addDevice", Qt::QueuedConnection,
|
||||
Q_ARG(iDescriptor::Uniq, iDescriptor::Uniq(udid)),
|
||||
Q_ARG(iDescriptor::IdeviceConnectionType,
|
||||
static_cast<iDescriptor::IdeviceConnectionType>(
|
||||
iDescriptor::CONNECTION_USB)),
|
||||
Q_ARG(AddType, AddType::Regular));
|
||||
} else {
|
||||
QMetaObject::invokeMethod(
|
||||
AppContext::sharedInstance(), "removeDevice", Qt::QueuedConnection,
|
||||
Q_ARG(iDescriptor::Uniq, iDescriptor::Uniq(udid)));
|
||||
}
|
||||
}
|
||||
|
||||
MainWindow *MainWindow::sharedInstance()
|
||||
{
|
||||
static MainWindow instance;
|
||||
@@ -333,65 +357,10 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
|
||||
m_updater->checkForUpdates();
|
||||
});
|
||||
|
||||
m_deviceMonitor = new DeviceMonitorThread(this);
|
||||
connect(
|
||||
m_deviceMonitor, &DeviceMonitorThread::deviceEvent, this,
|
||||
[this](int event, const QString &udid, int conn_type, int addType) {
|
||||
// Handle device connection
|
||||
switch (event) {
|
||||
case DeviceMonitorThread::IDEVICE_DEVICE_ADD: {
|
||||
/* never gets fired on any platform */
|
||||
if (conn_type == DeviceMonitorThread::CONNECTION_NETWORK) {
|
||||
return;
|
||||
}
|
||||
qDebug() << "Device event received: " << udid;
|
||||
|
||||
QMetaObject::invokeMethod(
|
||||
AppContext::sharedInstance(), "addDevice",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(iDescriptor::Uniq, iDescriptor::Uniq(udid)),
|
||||
Q_ARG(
|
||||
DeviceMonitorThread::IdeviceConnectionType,
|
||||
static_cast<DeviceMonitorThread::IdeviceConnectionType>(
|
||||
conn_type)),
|
||||
Q_ARG(AddType, AddType::Regular));
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceMonitorThread::IDEVICE_DEVICE_REMOVE: {
|
||||
QMetaObject::invokeMethod(
|
||||
AppContext::sharedInstance(), "removeDevice",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(iDescriptor::Uniq, iDescriptor::Uniq(udid)));
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceMonitorThread::IDEVICE_DEVICE_PAIRED: {
|
||||
/* never gets fired on any platform */
|
||||
if (conn_type == DeviceMonitorThread::CONNECTION_NETWORK) {
|
||||
return;
|
||||
}
|
||||
qDebug() << "Device paired: " << udid;
|
||||
|
||||
QMetaObject::invokeMethod(
|
||||
AppContext::sharedInstance(), "addDevice",
|
||||
Qt::QueuedConnection, Q_ARG(QString, udid),
|
||||
Q_ARG(
|
||||
DeviceMonitorThread::IdeviceConnectionType,
|
||||
static_cast<DeviceMonitorThread::IdeviceConnectionType>(
|
||||
conn_type)),
|
||||
Q_ARG(AddType, AddType::Pairing));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
qDebug() << "Unhandled event: " << event;
|
||||
}
|
||||
});
|
||||
|
||||
/* If a device is connected before starting the app on slower machines ui
|
||||
* takes a lot of time to render so delay the monitoring a bit */
|
||||
QTimer::singleShot(std::chrono::seconds(1), this,
|
||||
[this]() { m_deviceMonitor->start(); });
|
||||
[this]() { idevice_event_subscribe(handleCallback); });
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════
|
||||
// Upgrade to wireless when a "WIRED" device is removed
|
||||
@@ -404,11 +373,12 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
|
||||
return;
|
||||
qDebug() << "Upgrading device to wireless connection for UDID"
|
||||
<< QString::fromStdString(udid);
|
||||
// FIXME: ignore iOS 15 and lower
|
||||
QMetaObject::invokeMethod(
|
||||
AppContext::sharedInstance(), "addDevice", Qt::QueuedConnection,
|
||||
Q_ARG(iDescriptor::Uniq, iDescriptor::Uniq(udid, wasWireless)),
|
||||
Q_ARG(DeviceMonitorThread::IdeviceConnectionType,
|
||||
DeviceMonitorThread::CONNECTION_NETWORK),
|
||||
Q_ARG(iDescriptor::IdeviceConnectionType,
|
||||
iDescriptor::CONNECTION_NETWORK),
|
||||
Q_ARG(AddType, AddType::UpgradeToWireless),
|
||||
Q_ARG(QString, QString::fromStdString(wifiMacAddress)),
|
||||
Q_ARG(QString, QString::fromStdString(ipAddress)));
|
||||
@@ -420,6 +390,9 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
|
||||
connect(NetworkDeviceProvider::sharedInstance(),
|
||||
&NetworkDeviceProvider::deviceAdded, this,
|
||||
[this](const NetworkDevice &device) {
|
||||
if (!SettingsManager::sharedInstance()
|
||||
->autoConnectWirelessDevices())
|
||||
return;
|
||||
if (auto existingDevice =
|
||||
AppContext::sharedInstance()->getDeviceByMacAddress(
|
||||
device.macAddress)) {
|
||||
@@ -442,8 +415,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
|
||||
AppContext::sharedInstance(), "addDevice",
|
||||
Q_ARG(iDescriptor::Uniq,
|
||||
iDescriptor::Uniq(device.macAddress, true)),
|
||||
Q_ARG(DeviceMonitorThread::IdeviceConnectionType,
|
||||
DeviceMonitorThread::CONNECTION_NETWORK),
|
||||
Q_ARG(iDescriptor::IdeviceConnectionType,
|
||||
iDescriptor::CONNECTION_NETWORK),
|
||||
Q_ARG(AddType, AddType::Wireless),
|
||||
Q_ARG(QString, device.macAddress),
|
||||
Q_ARG(QString, device.address));
|
||||
@@ -528,9 +501,6 @@ MainWindow::~MainWindow()
|
||||
#ifdef ENABLE_RECOVERY_DEVICE_SUPPORT
|
||||
irecv_device_event_unsubscribe(context);
|
||||
#endif
|
||||
m_deviceMonitor->requestInterruption();
|
||||
m_deviceMonitor->wait();
|
||||
delete m_deviceMonitor;
|
||||
delete m_updater;
|
||||
// sleep(2);
|
||||
}
|
||||
@@ -21,7 +21,6 @@
|
||||
#define MAINWINDOW_H
|
||||
#include "ZDownloader.h"
|
||||
#include "ZUpdater.h"
|
||||
#include "devicemonitor.h"
|
||||
#include "iDescriptor-ui.h"
|
||||
#include "iDescriptor.h"
|
||||
#include "ztabwidget.h"
|
||||
@@ -51,7 +50,6 @@ private:
|
||||
DeviceManagerWidget *m_deviceManager;
|
||||
QStackedWidget *m_mainStackedWidget;
|
||||
QLabel *m_connectedDeviceCountLabel;
|
||||
DeviceMonitorThread *m_deviceMonitor;
|
||||
QLabel *m_titleLabel;
|
||||
QPushButton *m_minBtn;
|
||||
QPushButton *m_maxBtn;
|
||||
|
||||
Generated
+730
@@ -0,0 +1,730 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aws-lc-rs"
|
||||
version = "1.16.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc"
|
||||
dependencies = [
|
||||
"aws-lc-sys",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-lc-sys"
|
||||
version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fa7e52a4c5c547c741610a2c6f123f3881e409b714cd27e6798ef020c514f0a"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cmake",
|
||||
"dunce",
|
||||
"fs_extra",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
"libc",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "cmake"
|
||||
version = "0.1.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dunce"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||
|
||||
[[package]]
|
||||
name = "fs_extra"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-io",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-macro",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"memchr",
|
||||
"pin-project-lite",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi",
|
||||
"wasip2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
||||
|
||||
[[package]]
|
||||
name = "idevice"
|
||||
version = "0.1.53"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"futures",
|
||||
"plist",
|
||||
"plist-macro",
|
||||
"rustls",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-rustls",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idevice_monitor"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"idevice",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
|
||||
dependencies = [
|
||||
"getrandom 0.3.4",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.183"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
||||
|
||||
[[package]]
|
||||
name = "plist"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"indexmap",
|
||||
"quick-xml",
|
||||
"serde",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plist-macro"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82c39e020f2d8d361e91a434cfe26bc7c3e21ae54414379816d0110f3f7ca121"
|
||||
dependencies = [
|
||||
"plist",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.38.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "5.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"getrandom 0.2.17",
|
||||
"libc",
|
||||
"untrusted",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"once_cell",
|
||||
"rustls-pki-types",
|
||||
"rustls-webpki",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pki-types"
|
||||
version = "1.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd"
|
||||
dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.103.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "2.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"num-conv",
|
||||
"powerfmt",
|
||||
"serde_core",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215"
|
||||
dependencies = [
|
||||
"num-conv",
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.50.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
"mio",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.26.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61"
|
||||
dependencies = [
|
||||
"rustls",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
|
||||
dependencies = [
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-attributes"
|
||||
version = "0.1.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "wasip2"
|
||||
version = "1.0.2+wasi-0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
|
||||
dependencies = [
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen"
|
||||
version = "0.51.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
|
||||
@@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "idevice_monitor"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[lib]
|
||||
name = "idevice_monitor"
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1", features = ["rt", "time", "sync", "macros"] }
|
||||
futures = "0.3"
|
||||
idevice = { path = "../../lib/idevice-rs/idevice", features = ["usbmuxd"] }
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int kind; // 1 = connected, 2 = disconnected
|
||||
char *udid;
|
||||
} IdeviceEvent;
|
||||
|
||||
typedef void (*IdeviceEventCallback)(const IdeviceEvent *event);
|
||||
|
||||
void idevice_event_subscribe(IdeviceEventCallback cb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,77 @@
|
||||
use futures::StreamExt;
|
||||
use idevice::usbmuxd::{Connection, UsbmuxdConnection, UsbmuxdListenEvent};
|
||||
use std::collections::HashMap;
|
||||
use std::os::raw::c_char;
|
||||
use std::{ffi::CString, thread};
|
||||
use tokio::runtime::Builder;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct IdeviceEvent {
|
||||
pub kind: i32, // 1 = connected, 2 = disconnected
|
||||
pub udid: *mut c_char,
|
||||
}
|
||||
|
||||
pub type IdeviceEventCallback = extern "C" fn(event: *const IdeviceEvent);
|
||||
|
||||
fn make_event(kind: i32, udid: &str) -> IdeviceEvent {
|
||||
let c_udid = CString::new(udid).unwrap_or_default();
|
||||
IdeviceEvent {
|
||||
kind,
|
||||
udid: c_udid.into_raw(),
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn idevice_event_subscribe(cb: IdeviceEventCallback) {
|
||||
thread::spawn(move || {
|
||||
let rt = Builder::new_current_thread().enable_all().build().unwrap();
|
||||
rt.block_on(async move {
|
||||
let mut device_map: HashMap<u32, String> = HashMap::new();
|
||||
|
||||
loop {
|
||||
match UsbmuxdConnection::default().await {
|
||||
Ok(mut uc) => match uc.listen().await {
|
||||
Ok(mut stream) => {
|
||||
while let Some(evt) = stream.next().await {
|
||||
match evt {
|
||||
Ok(UsbmuxdListenEvent::Connected(d)) => {
|
||||
// ignore non-USB connections
|
||||
if d.connection_type != Connection::Usb {
|
||||
continue;
|
||||
}
|
||||
|
||||
let udid = d.udid.clone();
|
||||
let device_id = d.device_id;
|
||||
|
||||
device_map.insert(device_id, udid.clone());
|
||||
|
||||
let ev = make_event(1, &udid);
|
||||
cb(&ev);
|
||||
}
|
||||
Ok(UsbmuxdListenEvent::Disconnected(device_id)) => {
|
||||
if let Some(udid) = device_map.remove(&device_id) {
|
||||
let ev = make_event(2, &udid);
|
||||
cb(&ev);
|
||||
} else {
|
||||
eprintln!("Unknown device disconnected: {device_id}");
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("usbmuxd listen error: {e:?}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => eprintln!("Failed to start usbmuxd listen: {e:?}"),
|
||||
},
|
||||
// Safe to ignore as it likely means usbmuxd isn't running
|
||||
// usbmuxd is killed when the last device disconnects
|
||||
Err(_) => {}
|
||||
}
|
||||
|
||||
tokio::time::sleep(std::time::Duration::from_millis(2000)).await;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
+10
-15
@@ -21,6 +21,7 @@
|
||||
#define SERVICEMANAGER_H
|
||||
|
||||
#include "iDescriptor.h"
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QFuture>
|
||||
#include <functional>
|
||||
@@ -31,9 +32,7 @@
|
||||
* @brief Centralized manager for device service operations with thread safety
|
||||
*
|
||||
* This class provides thread-safe wrappers for all device operations to prevent
|
||||
* crashes when devices are unplugged during active operations. It uses a
|
||||
* per-device recursive mutex to ensure that device cleanup waits for all
|
||||
* operations to complete.
|
||||
* crashes when devices are unplugged during active operations
|
||||
*/
|
||||
class ServiceManager
|
||||
{
|
||||
@@ -44,7 +43,7 @@ public:
|
||||
std::function<T(AfcClientHandle *)> operation,
|
||||
std::optional<AfcClientHandle *> altAfc = std::nullopt)
|
||||
{
|
||||
if (!device) {
|
||||
if (QCoreApplication::closingDown() || !device) {
|
||||
return T{}; // Return default-constructed value for the type
|
||||
}
|
||||
|
||||
@@ -73,7 +72,7 @@ public:
|
||||
std::function<T()> operation,
|
||||
std::optional<AfcClientHandle *> altAfc = std::nullopt)
|
||||
{
|
||||
if (!device) {
|
||||
if (QCoreApplication::closingDown() || !device) {
|
||||
qDebug() << "[executeOperation] Device or mutex is null";
|
||||
return T{}; // Return default-constructed value for the type
|
||||
}
|
||||
@@ -101,7 +100,7 @@ public:
|
||||
std::function<T()> operation, T failureValue,
|
||||
std::optional<AfcClientHandle *> altAfc = std::nullopt)
|
||||
{
|
||||
if (!device) {
|
||||
if (QCoreApplication::closingDown() || !device) {
|
||||
return failureValue;
|
||||
}
|
||||
|
||||
@@ -126,7 +125,7 @@ public:
|
||||
std::function<void()> operation,
|
||||
std::optional<AfcClientHandle *> altAfc = std::nullopt)
|
||||
{
|
||||
if (!device) {
|
||||
if (QCoreApplication::closingDown() || !device) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -151,7 +150,7 @@ public:
|
||||
std::function<void()> operation,
|
||||
std::optional<AfcClientHandle *> altAfc = std::nullopt)
|
||||
{
|
||||
if (!device) {
|
||||
if (QCoreApplication::closingDown() || !device) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -177,14 +176,12 @@ public:
|
||||
AfcFileHandle *handle)
|
||||
{
|
||||
try {
|
||||
if (!device) {
|
||||
// FIXME: we have to free error
|
||||
if (QCoreApplication::closingDown() || !device) {
|
||||
return new IdeviceFfiError{1, "DEVICE_OR_MUTEX_IS_NULL"};
|
||||
}
|
||||
|
||||
std::lock_guard<std::recursive_mutex> lock(device->mutex);
|
||||
|
||||
// Double-check device is still valid after acquiring lock
|
||||
if (!device->afcClient) {
|
||||
return new IdeviceFfiError{1, "AFC_CLIENT_IS_NULL"};
|
||||
}
|
||||
@@ -206,8 +203,7 @@ public:
|
||||
std::optional<AfcClientHandle *> altAfc = std::nullopt)
|
||||
{
|
||||
try {
|
||||
if (!device) {
|
||||
// FIXME: we have to free error
|
||||
if (QCoreApplication::closingDown() || !device) {
|
||||
qDebug()
|
||||
<< "[executeAfcClientOperation] Device or mutex is null";
|
||||
return new IdeviceFfiError{1, "DEVICE_OR_MUTEX_IS_NULL"};
|
||||
@@ -215,7 +211,6 @@ public:
|
||||
|
||||
std::lock_guard<std::recursive_mutex> lock(device->mutex);
|
||||
|
||||
// Double-check device is still valid after acquiring lock
|
||||
if (!device->afcClient) {
|
||||
qDebug() << "[executeAfcClientOperation] AFC client is null";
|
||||
return new IdeviceFfiError{1, "AFC_CLIENT_IS_NULL"};
|
||||
@@ -245,7 +240,7 @@ public:
|
||||
std::optional<AfcClientHandle *> altAfc = std::nullopt)
|
||||
{
|
||||
try {
|
||||
if (!device) {
|
||||
if (QCoreApplication::closingDown() || !device) {
|
||||
return T{};
|
||||
}
|
||||
|
||||
|
||||
@@ -122,6 +122,17 @@ void SettingsManager::setSwitchToNewDevice(bool enabled)
|
||||
m_settings->sync();
|
||||
}
|
||||
|
||||
bool SettingsManager::autoConnectWirelessDevices() const
|
||||
{
|
||||
return m_settings->value("autoConnectWirelessDevices", true).toBool();
|
||||
}
|
||||
|
||||
void SettingsManager::setAutoConnectWirelessDevices(bool enabled)
|
||||
{
|
||||
m_settings->setValue("autoConnectWirelessDevices", enabled);
|
||||
m_settings->sync();
|
||||
}
|
||||
|
||||
#ifndef __APPLE__
|
||||
bool SettingsManager::unmountiFuseOnExit() const
|
||||
{
|
||||
@@ -238,6 +249,7 @@ void SettingsManager::resetToDefaults()
|
||||
setAutoCheckUpdates(true);
|
||||
setAutoRaiseWindow(true);
|
||||
setSwitchToNewDevice(true);
|
||||
setAutoConnectWirelessDevices(true);
|
||||
#ifndef __APPLE__
|
||||
setUnmountiFuseOnExit(false);
|
||||
#endif
|
||||
|
||||
@@ -77,6 +77,9 @@ public:
|
||||
bool switchToNewDevice() const;
|
||||
void setSwitchToNewDevice(bool enabled);
|
||||
|
||||
bool autoConnectWirelessDevices() const;
|
||||
void setAutoConnectWirelessDevices(bool enabled);
|
||||
|
||||
#ifndef __APPLE__
|
||||
bool unmountiFuseOnExit() const;
|
||||
void setUnmountiFuseOnExit(bool enabled);
|
||||
|
||||
@@ -156,6 +156,10 @@ void SettingsWidget::setupUI()
|
||||
m_switchToNewDevice = new QCheckBox("Switch to newly connected device");
|
||||
deviceLayout->addWidget(m_switchToNewDevice);
|
||||
|
||||
m_autoConnectWirelessDevices =
|
||||
new QCheckBox("Automatically connect to wireless devices");
|
||||
deviceLayout->addWidget(m_autoConnectWirelessDevices);
|
||||
|
||||
// Connection timeout
|
||||
auto *timeoutLayout = new QHBoxLayout();
|
||||
timeoutLayout->addWidget(new QLabel("Connection Timeout:"));
|
||||
@@ -302,6 +306,7 @@ void SettingsWidget::loadSettings()
|
||||
m_autoUpdateCheck->setChecked(sm->autoCheckUpdates());
|
||||
m_autoRaiseWindow->setChecked(sm->autoRaiseWindow());
|
||||
m_switchToNewDevice->setChecked(sm->switchToNewDevice());
|
||||
m_autoConnectWirelessDevices->setChecked(sm->autoConnectWirelessDevices());
|
||||
m_wirelessFileServerPort->setValue(sm->wirelessFileServerPort());
|
||||
|
||||
#ifndef __APPLE__
|
||||
@@ -352,6 +357,8 @@ void SettingsWidget::connectSignals()
|
||||
&SettingsWidget::onSettingChanged);
|
||||
connect(m_switchToNewDevice, &QCheckBox::toggled, this,
|
||||
&SettingsWidget::onSettingChanged);
|
||||
connect(m_autoConnectWirelessDevices, &QCheckBox::toggled, this,
|
||||
&SettingsWidget::onSettingChanged);
|
||||
#ifndef __APPLE__
|
||||
connect(m_unmount_iFuseDrives, &QCheckBox::toggled, this,
|
||||
&SettingsWidget::onSettingChanged);
|
||||
@@ -486,6 +493,8 @@ void SettingsWidget::saveSettings()
|
||||
sm->setAutoCheckUpdates(m_autoUpdateCheck->isChecked());
|
||||
sm->setAutoRaiseWindow(m_autoRaiseWindow->isChecked());
|
||||
sm->setSwitchToNewDevice(m_switchToNewDevice->isChecked());
|
||||
sm->setAutoConnectWirelessDevices(
|
||||
m_autoConnectWirelessDevices->isChecked());
|
||||
sm->setWirelessFileServerPort(m_wirelessFileServerPort->value());
|
||||
|
||||
#ifndef __APPLE__
|
||||
|
||||
@@ -62,6 +62,7 @@ private:
|
||||
#endif
|
||||
QCheckBox *m_useUnsecureBackend;
|
||||
// Device Connection
|
||||
QCheckBox *m_autoConnectWirelessDevices;
|
||||
QSpinBox *m_connectionTimeout;
|
||||
|
||||
// Jailbroken
|
||||
|
||||
Reference in New Issue
Block a user