Fix exiting macos devicelister

This commit is contained in:
Jonas Kvinge
2019-09-15 01:12:05 +02:00
parent 9972124aa1
commit 83e10aac27
3 changed files with 103 additions and 28 deletions

View File

@@ -43,7 +43,7 @@ class DeviceLister : public QObject {
// Tries to start the thread and initialise the engine. This object will be moved to the new thread. // Tries to start the thread and initialise the engine. This object will be moved to the new thread.
void Start(); void Start();
void ExitAsync(); virtual void ExitAsync();
// If two listers know about the same device, then the metadata will get taken from the one with the highest priority. // If two listers know about the same device, then the metadata will get taken from the one with the highest priority.
virtual int priority() const { return 100; } virtual int priority() const { return 100; }
@@ -70,14 +70,12 @@ class DeviceLister : public QObject {
// Do whatever needs to be done to safely remove the device. // Do whatever needs to be done to safely remove the device.
virtual void UnmountDeviceAsync(const QString &id); virtual void UnmountDeviceAsync(const QString &id);
private slots:
void Exit();
public slots: public slots:
virtual void UpdateDeviceFreeSpace(const QString &id) = 0; virtual void UpdateDeviceFreeSpace(const QString &id) = 0;
virtual void ShutDown() {} virtual void ShutDown() {}
virtual void MountDevice(const QString &id, const int ret); virtual void MountDevice(const QString &id, const int ret);
virtual void UnmountDevice(const QString &id) {} virtual void UnmountDevice(const QString &id) {}
virtual void Exit();
signals: signals:
void DeviceAdded(const QString &id); void DeviceAdded(const QString &id);

View File

@@ -1,3 +1,23 @@
/*
* Strawberry Music Player
* This file was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com>
*
* Strawberry 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.
*
* Strawberry 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 Strawberry. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef MACDEVICELISTER_H #ifndef MACDEVICELISTER_H
#define MACDEVICELISTER_H #define MACDEVICELISTER_H
@@ -20,22 +40,23 @@
class MacOsDeviceLister : public DeviceLister { class MacOsDeviceLister : public DeviceLister {
Q_OBJECT Q_OBJECT
public: public:
MacOsDeviceLister(); MacOsDeviceLister();
~MacOsDeviceLister(); ~MacOsDeviceLister();
virtual QStringList DeviceUniqueIDs(); QStringList DeviceUniqueIDs();
virtual QVariantList DeviceIcons(const QString &id); QVariantList DeviceIcons(const QString &id);
virtual QString DeviceManufacturer(const QString &id); QString DeviceManufacturer(const QString &id);
virtual QString DeviceModel(const QString &id); QString DeviceModel(const QString &id);
virtual quint64 DeviceCapacity(const QString &id); quint64 DeviceCapacity(const QString &id);
virtual quint64 DeviceFreeSpace(const QString &id); quint64 DeviceFreeSpace(const QString &id);
virtual QVariantMap DeviceHardwareInfo(const QString &id); QVariantMap DeviceHardwareInfo(const QString &id);
virtual bool AskForScan(const QString &serial) const; bool AskForScan(const QString &serial) const;
virtual QString MakeFriendlyName(const QString &id); QString MakeFriendlyName(const QString &id);
virtual QList<QUrl> MakeDeviceUrls(const QString &id); QList<QUrl> MakeDeviceUrls(const QString &id);
virtual void UpdateDeviceFreeSpace(const QString &id); void UpdateDeviceFreeSpace(const QString &id);
struct MTPDevice { struct MTPDevice {
MTPDevice() : capacity(0), free_space(0) {} MTPDevice() : capacity(0), free_space(0) {}
@@ -52,12 +73,14 @@ class MacOsDeviceLister : public DeviceLister {
quint64 free_space; quint64 free_space;
}; };
void ExitAsync();
public slots: public slots:
virtual void UnmountDevice(const QString &id); void UnmountDevice(const QString &id);
virtual void ShutDown(); void ShutDown();
private: private:
virtual bool Init(); bool Init();
static void DiskAddedCallback(DADiskRef disk, void* context); static void DiskAddedCallback(DADiskRef disk, void* context);
static void DiskRemovedCallback(DADiskRef disk, void* context); static void DiskRemovedCallback(DADiskRef disk, void* context);

View File

@@ -109,6 +109,7 @@ MacOsDeviceLister::MacOsDeviceLister() {}
MacOsDeviceLister::~MacOsDeviceLister() { CFRelease(loop_session_); } MacOsDeviceLister::~MacOsDeviceLister() { CFRelease(loop_session_); }
bool MacOsDeviceLister::Init() { bool MacOsDeviceLister::Init() {
ScopedNSAutoreleasePool pool; ScopedNSAutoreleasePool pool;
// Populate MTP Device list. // Populate MTP Device list.
@@ -188,6 +189,11 @@ bool MacOsDeviceLister::Init() {
CFRunLoopRun(); CFRunLoopRun();
return true; return true;
}
void MacOsDeviceLister::ExitAsync() {
emit ExitFinished();
} }
void MacOsDeviceLister::ShutDown() { CFRunLoopStop(run_loop_); } void MacOsDeviceLister::ShutDown() { CFRunLoopStop(run_loop_); }
@@ -233,6 +239,7 @@ QString GetUSBRegistryEntryString(io_object_t device, CFStringRef key) {
} }
NSObject* GetPropertyForDevice(io_object_t device, CFStringRef key) { NSObject* GetPropertyForDevice(io_object_t device, CFStringRef key) {
CFMutableDictionaryRef properties; CFMutableDictionaryRef properties;
kern_return_t ret = IORegistryEntryCreateCFProperties(device, &properties, kCFAllocatorDefault, 0); kern_return_t ret = IORegistryEntryCreateCFProperties(device, &properties, kCFAllocatorDefault, 0);
@@ -255,9 +262,11 @@ NSObject* GetPropertyForDevice(io_object_t device, CFStringRef key) {
} }
return nil; return nil;
} }
int GetUSBDeviceClass(io_object_t device) { int GetUSBDeviceClass(io_object_t device) {
ScopedCFTypeRef<CFTypeRef> interface_class(IORegistryEntrySearchCFProperty( ScopedCFTypeRef<CFTypeRef> interface_class(IORegistryEntrySearchCFProperty(
device, device,
kIOServicePlane, kIOServicePlane,
@@ -270,9 +279,11 @@ int GetUSBDeviceClass(io_object_t device) {
return ret; return ret;
} }
return 0; return 0;
} }
QString GetIconForDevice(io_object_t device) { QString GetIconForDevice(io_object_t device) {
scoped_nsobject<NSDictionary> media_icon((NSDictionary*)GetPropertyForDevice(device, CFSTR("IOMediaIcon"))); scoped_nsobject<NSDictionary> media_icon((NSDictionary*)GetPropertyForDevice(device, CFSTR("IOMediaIcon")));
if (media_icon) { if (media_icon) {
NSString* bundle = (NSString*)[media_icon objectForKey:@"CFBundleIdentifier"]; NSString* bundle = (NSString*)[media_icon objectForKey:@"CFBundleIdentifier"];
@@ -280,39 +291,48 @@ QString GetIconForDevice(io_object_t device) {
scoped_nsobject<NSURL> bundle_url((NSURL*)KextManagerCreateURLForBundleIdentifier(kCFAllocatorDefault, (CFStringRef)bundle)); scoped_nsobject<NSURL> bundle_url((NSURL*)KextManagerCreateURLForBundleIdentifier(kCFAllocatorDefault, (CFStringRef)bundle));
QString path = QString::fromUtf8([[bundle_url path] UTF8String]); QString path = QString::fromUtf8([ [bundle_url path] UTF8String]);
path += "/Contents/Resources/"; path += "/Contents/Resources/";
path += QString::fromUtf8([file UTF8String]); path += QString::fromUtf8([file UTF8String]);
return path; return path;
} }
return QString(); return QString();
} }
QString GetSerialForDevice(io_object_t device) { QString GetSerialForDevice(io_object_t device) {
QString serial = GetUSBRegistryEntryString(device, CFSTR(kUSBSerialNumberString)); QString serial = GetUSBRegistryEntryString(device, CFSTR(kUSBSerialNumberString));
if (!serial.isEmpty()) { if (!serial.isEmpty()) {
return "USB/" + serial; return "USB/" + serial;
} }
return QString(); return QString();
} }
QString GetSerialForMTPDevice(io_object_t device) { QString GetSerialForMTPDevice(io_object_t device) {
scoped_nsobject<NSString> serial((NSString*) GetPropertyForDevice(device, CFSTR(kUSBSerialNumberString))); scoped_nsobject<NSString> serial((NSString*) GetPropertyForDevice(device, CFSTR(kUSBSerialNumberString)));
return QString(QString("MTP/") + QString::fromUtf8([serial UTF8String])); return QString(QString("MTP/") + QString::fromUtf8([serial UTF8String]));
} }
QString FindDeviceProperty(const QString& bsd_name, CFStringRef property) { QString FindDeviceProperty(const QString& bsd_name, CFStringRef property) {
ScopedCFTypeRef<DASessionRef> session(DASessionCreate(kCFAllocatorDefault)); ScopedCFTypeRef<DASessionRef> session(DASessionCreate(kCFAllocatorDefault));
ScopedCFTypeRef<DADiskRef> disk(DADiskCreateFromBSDName(kCFAllocatorDefault, session.get(), bsd_name.toLatin1().constData())); ScopedCFTypeRef<DADiskRef> disk(DADiskCreateFromBSDName(kCFAllocatorDefault, session.get(), bsd_name.toLatin1().constData()));
ScopedIOObject device(DADiskCopyIOMedia(disk.get())); ScopedIOObject device(DADiskCopyIOMedia(disk.get()));
QString ret = GetUSBRegistryEntryString(device.get(), property); QString ret = GetUSBRegistryEntryString(device.get(), property);
return ret; return ret;
}
} }
} // namespace
quint64 MacOsDeviceLister::GetFreeSpace(const QUrl& url) { quint64 MacOsDeviceLister::GetFreeSpace(const QUrl& url) {
QMutexLocker l(&libmtp_mutex_); QMutexLocker l(&libmtp_mutex_);
MtpConnection connection(url); MtpConnection connection(url);
if (!connection.is_valid()) { if (!connection.is_valid()) {
@@ -326,9 +346,11 @@ quint64 MacOsDeviceLister::GetFreeSpace(const QUrl& url) {
storage = storage->next; storage = storage->next;
} }
return free_bytes; return free_bytes;
} }
quint64 MacOsDeviceLister::GetCapacity(const QUrl& url) { quint64 MacOsDeviceLister::GetCapacity(const QUrl& url) {
QMutexLocker l(&libmtp_mutex_); QMutexLocker l(&libmtp_mutex_);
MtpConnection connection(url); MtpConnection connection(url);
if (!connection.is_valid()) { if (!connection.is_valid()) {
@@ -342,9 +364,11 @@ quint64 MacOsDeviceLister::GetCapacity(const QUrl& url) {
storage = storage->next; storage = storage->next;
} }
return capacity_bytes; return capacity_bytes;
} }
void MacOsDeviceLister::DiskAddedCallback(DADiskRef disk, void* context) { void MacOsDeviceLister::DiskAddedCallback(DADiskRef disk, void* context) {
MacOsDeviceLister* me = reinterpret_cast<MacOsDeviceLister*>(context); MacOsDeviceLister* me = reinterpret_cast<MacOsDeviceLister*>(context);
scoped_nsobject<NSDictionary> properties((NSDictionary*)DADiskCopyDescription(disk)); scoped_nsobject<NSDictionary> properties((NSDictionary*)DADiskCopyDescription(disk));
@@ -360,8 +384,7 @@ void MacOsDeviceLister::DiskAddedCallback(DADiskRef disk, void* context) {
} }
#endif #endif
NSURL* volume_path = NSURL* volume_path = [ [properties objectForKey:(NSString*)kDADiskDescriptionVolumePathKey] copy];
[[properties objectForKey:(NSString*)kDADiskDescriptionVolumePathKey] copy];
if (volume_path) { if (volume_path) {
ScopedIOObject device(DADiskCopyIOMedia(disk)); ScopedIOObject device(DADiskCopyIOMedia(disk));
@@ -375,7 +398,7 @@ void MacOsDeviceLister::DiskAddedCallback(DADiskRef disk, void* context) {
if (ret == KERN_SUCCESS) { if (ret == KERN_SUCCESS) {
scoped_nsobject<NSDictionary> dict((NSDictionary*)cf_properties); // Takes ownership. scoped_nsobject<NSDictionary> dict((NSDictionary*)cf_properties); // Takes ownership.
if ([[dict objectForKey:@"Removable"] intValue] == 1) { if ([ [dict objectForKey:@"Removable"] intValue] == 1) {
QString serial = GetSerialForDevice(device.get()); QString serial = GetSerialForDevice(device.get());
if (!serial.isEmpty()) { if (!serial.isEmpty()) {
me->current_devices_[serial] = QString(DADiskGetBSDName(disk)); me->current_devices_[serial] = QString(DADiskGetBSDName(disk));
@@ -385,9 +408,11 @@ void MacOsDeviceLister::DiskAddedCallback(DADiskRef disk, void* context) {
} }
} }
} }
} }
void MacOsDeviceLister::DiskRemovedCallback(DADiskRef disk, void* context) { void MacOsDeviceLister::DiskRemovedCallback(DADiskRef disk, void* context) {
MacOsDeviceLister* me = reinterpret_cast<MacOsDeviceLister*>(context); MacOsDeviceLister* me = reinterpret_cast<MacOsDeviceLister*>(context);
// We cannot access the USB tree when the disk is removed but we still get // We cannot access the USB tree when the disk is removed but we still get
// the BSD disk name. // the BSD disk name.
@@ -405,6 +430,7 @@ void MacOsDeviceLister::DiskRemovedCallback(DADiskRef disk, void* context) {
break; break;
} }
} }
} }
bool DeviceRequest(IOUSBDeviceInterface** dev, bool DeviceRequest(IOUSBDeviceInterface** dev,
@@ -416,6 +442,7 @@ bool DeviceRequest(IOUSBDeviceInterface** dev,
quint16 index, quint16 index,
quint16 length, quint16 length,
QByteArray* data) { QByteArray* data) {
IOUSBDevRequest req; IOUSBDevRequest req;
req.bmRequestType = USBmakebmRequestType(direction, type, recipient); req.bmRequestType = USBmakebmRequestType(direction, type, recipient);
req.bRequest = request_code; req.bRequest = request_code;
@@ -430,9 +457,11 @@ bool DeviceRequest(IOUSBDeviceInterface** dev,
} }
data->resize(req.wLenDone); data->resize(req.wLenDone);
return true; return true;
} }
int GetBusNumber(io_object_t o) { int GetBusNumber(io_object_t o) {
io_iterator_t it; io_iterator_t it;
kern_return_t err = IORegistryEntryGetParentIterator(o, kIOServicePlane, &it); kern_return_t err = IORegistryEntryGetParentIterator(o, kIOServicePlane, &it);
if (err != KERN_SUCCESS) { if (err != KERN_SUCCESS) {
@@ -447,9 +476,11 @@ int GetBusNumber(io_object_t o) {
} }
return -1; return -1;
} }
void MacOsDeviceLister::USBDeviceAddedCallback(void* refcon, io_iterator_t it) { void MacOsDeviceLister::USBDeviceAddedCallback(void* refcon, io_iterator_t it) {
MacOsDeviceLister* me = reinterpret_cast<MacOsDeviceLister*>(refcon); MacOsDeviceLister* me = reinterpret_cast<MacOsDeviceLister*>(refcon);
io_object_t object; io_object_t object;
@@ -584,9 +615,11 @@ void MacOsDeviceLister::USBDeviceAddedCallback(void* refcon, io_iterator_t it) {
} }
} }
} }
} }
void MacOsDeviceLister::USBDeviceRemovedCallback(void* refcon, io_iterator_t it) { void MacOsDeviceLister::USBDeviceRemovedCallback(void* refcon, io_iterator_t it) {
MacOsDeviceLister* me = reinterpret_cast<MacOsDeviceLister*>(refcon); MacOsDeviceLister* me = reinterpret_cast<MacOsDeviceLister*>(refcon);
io_object_t object; io_object_t object;
while ((object = IOIteratorNext(it))) { while ((object = IOIteratorNext(it))) {
@@ -610,17 +643,21 @@ void MacOsDeviceLister::USBDeviceRemovedCallback(void* refcon, io_iterator_t it)
me->RemovedMTPDevice(serial); me->RemovedMTPDevice(serial);
} }
} }
} }
void MacOsDeviceLister::RemovedMTPDevice(const QString& serial) { void MacOsDeviceLister::RemovedMTPDevice(const QString& serial) {
int count = mtp_devices_.remove(serial); int count = mtp_devices_.remove(serial);
if (count) { if (count) {
qLog(Debug) << "MTP device removed:" << serial; qLog(Debug) << "MTP device removed:" << serial;
emit DeviceRemoved(serial); emit DeviceRemoved(serial);
} }
} }
void MacOsDeviceLister::FoundMTPDevice(const MTPDevice& device, const QString& serial) { void MacOsDeviceLister::FoundMTPDevice(const MTPDevice& device, const QString& serial) {
qLog(Debug) << "New MTP device detected!" << device.bus << device.address; qLog(Debug) << "New MTP device detected!" << device.bus << device.address;
mtp_devices_[serial] = device; mtp_devices_[serial] = device;
QList<QUrl> urls = MakeDeviceUrls(serial); QList<QUrl> urls = MakeDeviceUrls(serial);
@@ -628,6 +665,7 @@ void MacOsDeviceLister::FoundMTPDevice(const MTPDevice& device, const QString& s
d->capacity = GetCapacity(urls[0]); d->capacity = GetCapacity(urls[0]);
d->free_space = GetFreeSpace(urls[0]); d->free_space = GetFreeSpace(urls[0]);
emit DeviceAdded(serial); emit DeviceAdded(serial);
} }
bool IsMTPSerial(const QString& serial) { return serial.startsWith("MTP"); } bool IsMTPSerial(const QString& serial) { return serial.startsWith("MTP"); }
@@ -637,6 +675,7 @@ bool MacOsDeviceLister::IsCDDevice(const QString& serial) const {
} }
QString MacOsDeviceLister::MakeFriendlyName(const QString& serial) { QString MacOsDeviceLister::MakeFriendlyName(const QString& serial) {
if (IsMTPSerial(serial)) { if (IsMTPSerial(serial)) {
const MTPDevice& device = mtp_devices_[serial]; const MTPDevice& device = mtp_devices_[serial];
if (device.vendor.isEmpty()) { if (device.vendor.isEmpty()) {
@@ -667,9 +706,11 @@ QString MacOsDeviceLister::MakeFriendlyName(const QString& serial) {
return product; return product;
} }
return vendor + " " + product; return vendor + " " + product;
} }
QList<QUrl> MacOsDeviceLister::MakeDeviceUrls(const QString& serial) { QList<QUrl> MacOsDeviceLister::MakeDeviceUrls(const QString& serial) {
if (IsMTPSerial(serial)) { if (IsMTPSerial(serial)) {
const MTPDevice& device = mtp_devices_[serial]; const MTPDevice& device = mtp_devices_[serial];
QString str; QString str;
@@ -694,12 +735,13 @@ QList<QUrl> MacOsDeviceLister::MakeDeviceUrls(const QString& serial) {
ScopedCFTypeRef<DADiskRef> disk(DADiskCreateFromBSDName(kCFAllocatorDefault, session.get(), bsd_name.toLatin1().constData())); ScopedCFTypeRef<DADiskRef> disk(DADiskCreateFromBSDName(kCFAllocatorDefault, session.get(), bsd_name.toLatin1().constData()));
scoped_nsobject<NSDictionary> properties((NSDictionary*)DADiskCopyDescription(disk.get())); scoped_nsobject<NSDictionary> properties((NSDictionary*)DADiskCopyDescription(disk.get()));
scoped_nsobject<NSURL> volume_path([[properties objectForKey:(NSString*)kDADiskDescriptionVolumePathKey] copy]); scoped_nsobject<NSURL> volume_path([ [properties objectForKey:(NSString*)kDADiskDescriptionVolumePathKey] copy]);
QString path = QString::fromUtf8([[volume_path path] UTF8String]); QString path = QString::fromUtf8([ [volume_path path] UTF8String]);
QUrl ret = MakeUrlFromLocalPath(path); QUrl ret = MakeUrlFromLocalPath(path);
return QList<QUrl>() << ret; return QList<QUrl>() << ret;
} }
QStringList MacOsDeviceLister::DeviceUniqueIDs() { QStringList MacOsDeviceLister::DeviceUniqueIDs() {
@@ -707,6 +749,7 @@ QStringList MacOsDeviceLister::DeviceUniqueIDs() {
} }
QVariantList MacOsDeviceLister::DeviceIcons(const QString& serial) { QVariantList MacOsDeviceLister::DeviceIcons(const QString& serial) {
if (IsMTPSerial(serial)) { if (IsMTPSerial(serial)) {
return QVariantList(); return QVariantList();
} }
@@ -723,9 +766,9 @@ QVariantList MacOsDeviceLister::DeviceIcons(const QString& serial) {
QString icon = GetIconForDevice(device.get()); QString icon = GetIconForDevice(device.get());
scoped_nsobject<NSDictionary> properties((NSDictionary*)DADiskCopyDescription(disk)); scoped_nsobject<NSDictionary> properties((NSDictionary*)DADiskCopyDescription(disk));
scoped_nsobject<NSURL> volume_path([[properties objectForKey:(NSString*)kDADiskDescriptionVolumePathKey] copy]); scoped_nsobject<NSURL> volume_path([ [properties objectForKey:(NSString*)kDADiskDescriptionVolumePathKey] copy]);
QString path = QString::fromUtf8([[volume_path path] UTF8String]); QString path = QString::fromUtf8([ [volume_path path] UTF8String]);
QVariantList ret; QVariantList ret;
ret << GuessIconForPath(path); ret << GuessIconForPath(path);
@@ -734,6 +777,7 @@ QVariantList MacOsDeviceLister::DeviceIcons(const QString& serial) {
ret << icon; ret << icon;
} }
return ret; return ret;
} }
QString MacOsDeviceLister::DeviceManufacturer(const QString& serial) { QString MacOsDeviceLister::DeviceManufacturer(const QString& serial) {
@@ -751,6 +795,7 @@ QString MacOsDeviceLister::DeviceModel(const QString& serial) {
} }
quint64 MacOsDeviceLister::DeviceCapacity(const QString& serial) { quint64 MacOsDeviceLister::DeviceCapacity(const QString& serial) {
if (IsMTPSerial(serial)) { if (IsMTPSerial(serial)) {
QList<QUrl> urls = MakeDeviceUrls(serial); QList<QUrl> urls = MakeDeviceUrls(serial);
return mtp_devices_[serial].capacity; return mtp_devices_[serial].capacity;
@@ -768,9 +813,11 @@ quint64 MacOsDeviceLister::DeviceCapacity(const QString& serial) {
IOObjectRelease(device); IOObjectRelease(device);
return ret; return ret;
} }
quint64 MacOsDeviceLister::DeviceFreeSpace(const QString& serial) { quint64 MacOsDeviceLister::DeviceFreeSpace(const QString& serial) {
if (IsMTPSerial(serial)) { if (IsMTPSerial(serial)) {
QList<QUrl> urls = MakeDeviceUrls(serial); QList<QUrl> urls = MakeDeviceUrls(serial);
return mtp_devices_[serial].free_space; return mtp_devices_[serial].free_space;
@@ -780,7 +827,7 @@ quint64 MacOsDeviceLister::DeviceFreeSpace(const QString& serial) {
ScopedCFTypeRef<DADiskRef> disk(DADiskCreateFromBSDName(kCFAllocatorDefault, session.get(), bsd_name.toLatin1().constData())); ScopedCFTypeRef<DADiskRef> disk(DADiskCreateFromBSDName(kCFAllocatorDefault, session.get(), bsd_name.toLatin1().constData()));
scoped_nsobject<NSDictionary> properties((NSDictionary*)DADiskCopyDescription(disk)); scoped_nsobject<NSDictionary> properties((NSDictionary*)DADiskCopyDescription(disk));
scoped_nsobject<NSURL> volume_path([[properties objectForKey:(NSString*)kDADiskDescriptionVolumePathKey] copy]); scoped_nsobject<NSURL> volume_path([ [properties objectForKey:(NSString*)kDADiskDescriptionVolumePathKey] copy]);
NSNumber* value = nil; NSNumber* value = nil;
NSError* error = nil; NSError* error = nil;
@@ -788,6 +835,7 @@ quint64 MacOsDeviceLister::DeviceFreeSpace(const QString& serial) {
return [value unsignedLongLongValue]; return [value unsignedLongLongValue];
} }
return 0; return 0;
} }
QVariantMap MacOsDeviceLister::DeviceHardwareInfo(const QString& serial){return QVariantMap();} QVariantMap MacOsDeviceLister::DeviceHardwareInfo(const QString& serial){return QVariantMap();}
@@ -797,24 +845,29 @@ bool MacOsDeviceLister::AskForScan(const QString& serial) const {
} }
void MacOsDeviceLister::UnmountDevice(const QString& serial) { void MacOsDeviceLister::UnmountDevice(const QString& serial) {
if (IsMTPSerial(serial)) return; if (IsMTPSerial(serial)) return;
QString bsd_name = current_devices_[serial]; QString bsd_name = current_devices_[serial];
ScopedCFTypeRef<DADiskRef> disk(DADiskCreateFromBSDName(kCFAllocatorDefault, loop_session_, bsd_name.toLatin1().constData())); ScopedCFTypeRef<DADiskRef> disk(DADiskCreateFromBSDName(kCFAllocatorDefault, loop_session_, bsd_name.toLatin1().constData()));
DADiskUnmount(disk, kDADiskUnmountOptionDefault, &DiskUnmountCallback, this); DADiskUnmount(disk, kDADiskUnmountOptionDefault, &DiskUnmountCallback, this);
} }
void MacOsDeviceLister::DiskUnmountCallback(DADiskRef disk, DADissenterRef dissenter, void* context) { void MacOsDeviceLister::DiskUnmountCallback(DADiskRef disk, DADissenterRef dissenter, void* context) {
if (dissenter) { if (dissenter) {
qLog(Warning) << "Another app blocked the unmount"; qLog(Warning) << "Another app blocked the unmount";
} }
else { else {
DiskRemovedCallback(disk, context); DiskRemovedCallback(disk, context);
} }
} }
void MacOsDeviceLister::UpdateDeviceFreeSpace(const QString& serial) { void MacOsDeviceLister::UpdateDeviceFreeSpace(const QString& serial) {
if (IsMTPSerial(serial)) { if (IsMTPSerial(serial)) {
if (mtp_devices_.contains(serial)) { if (mtp_devices_.contains(serial)) {
QList<QUrl> urls = MakeDeviceUrls(serial); QList<QUrl> urls = MakeDeviceUrls(serial);
@@ -823,4 +876,5 @@ void MacOsDeviceLister::UpdateDeviceFreeSpace(const QString& serial) {
} }
} }
emit DeviceChanged(serial); emit DeviceChanged(serial);
} }