mirror of
https://github.com/clementine-player/Clementine
synced 2024-12-16 11:19:18 +01:00
Messy mac device listing code using three different APIs. At least the IOKit one will probably go away.
This commit is contained in:
parent
d8b60e7f60
commit
dd3182ad70
@ -409,6 +409,8 @@ endif(HAVE_GSTREAMER)
|
|||||||
if(APPLE)
|
if(APPLE)
|
||||||
list(APPEND SOURCES widgets/osd_mac.mm)
|
list(APPEND SOURCES widgets/osd_mac.mm)
|
||||||
list(APPEND SOURCES core/macglobalshortcutbackend.mm)
|
list(APPEND SOURCES core/macglobalshortcutbackend.mm)
|
||||||
|
list(APPEND SOURCES devices/macdevicelister.mm)
|
||||||
|
list(APPEND HEADERS devices/macdevicelister.h)
|
||||||
list(APPEND SOURCES ui/macsystemtrayicon.mm)
|
list(APPEND SOURCES ui/macsystemtrayicon.mm)
|
||||||
list(APPEND HEADERS core/macglobalshortcutbackend.h)
|
list(APPEND HEADERS core/macglobalshortcutbackend.h)
|
||||||
list(APPEND HEADERS ui/macsystemtrayicon.h)
|
list(APPEND HEADERS ui/macsystemtrayicon.h)
|
||||||
@ -562,9 +564,11 @@ if (APPLE)
|
|||||||
${GROWL}
|
${GROWL}
|
||||||
${SPARKLE}
|
${SPARKLE}
|
||||||
z
|
z
|
||||||
/System/Library/Frameworks/Carbon.framework
|
|
||||||
/System/Library/Frameworks/Foundation.framework
|
|
||||||
/System/Library/Frameworks/AppKit.framework
|
/System/Library/Frameworks/AppKit.framework
|
||||||
|
/System/Library/Frameworks/Carbon.framework
|
||||||
|
/System/Library/Frameworks/DiskArbitration.framework
|
||||||
|
/System/Library/Frameworks/Foundation.framework
|
||||||
|
/System/Library/Frameworks/IOKit.framework
|
||||||
)
|
)
|
||||||
include_directories(${SPARKLE}/Headers)
|
include_directories(${SPARKLE}/Headers)
|
||||||
else (APPLE)
|
else (APPLE)
|
||||||
|
@ -30,7 +30,7 @@ class DeviceLister : public QObject {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
DeviceLister();
|
DeviceLister();
|
||||||
~DeviceLister();
|
virtual ~DeviceLister();
|
||||||
|
|
||||||
// Tries to start the thread and initialise the engine. This object will be
|
// Tries to start the thread and initialise the engine. This object will be
|
||||||
// moved to the new thread.
|
// moved to the new thread.
|
||||||
|
@ -26,6 +26,10 @@
|
|||||||
#include "core/utilities.h"
|
#include "core/utilities.h"
|
||||||
#include "ui/iconloader.h"
|
#include "ui/iconloader.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_DARWIN
|
||||||
|
#include "macdevicelister.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
@ -158,6 +162,9 @@ DeviceManager::DeviceManager(BackgroundThread<Database>* database,
|
|||||||
#ifdef HAVE_GIO
|
#ifdef HAVE_GIO
|
||||||
AddLister(new GioLister);
|
AddLister(new GioLister);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef Q_OS_DARWIN
|
||||||
|
AddLister(new MacDeviceLister);
|
||||||
|
#endif
|
||||||
|
|
||||||
AddDeviceClass<FilesystemDevice>();
|
AddDeviceClass<FilesystemDevice>();
|
||||||
|
|
||||||
|
55
src/devices/macdevicelister.h
Normal file
55
src/devices/macdevicelister.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#ifndef MACDEVICELISTER_H
|
||||||
|
#define MACDEVICELISTER_H
|
||||||
|
|
||||||
|
#include "devicelister.h"
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
|
#include <DiskArbitration/DADisk.h>
|
||||||
|
#include <DiskArbitration/DADissenter.h>
|
||||||
|
#include <IOKit/IOKitLib.h>
|
||||||
|
|
||||||
|
#include <boost/scoped_ptr.hpp>
|
||||||
|
|
||||||
|
class MacDeviceListerPrivate;
|
||||||
|
|
||||||
|
class MacDeviceLister : public DeviceLister {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
MacDeviceLister();
|
||||||
|
~MacDeviceLister();
|
||||||
|
|
||||||
|
virtual QStringList DeviceUniqueIDs();
|
||||||
|
virtual QStringList DeviceIcons(const QString& id);
|
||||||
|
virtual QString DeviceManufacturer(const QString& id);
|
||||||
|
virtual QString DeviceModel(const QString& id);
|
||||||
|
virtual quint64 DeviceCapacity(const QString& id);
|
||||||
|
virtual quint64 DeviceFreeSpace(const QString& id);
|
||||||
|
virtual QVariantMap DeviceHardwareInfo(const QString& id);
|
||||||
|
virtual QString MakeFriendlyName(const QString& id);
|
||||||
|
virtual QUrl MakeDeviceUrl(const QString& id);
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void Init();
|
||||||
|
|
||||||
|
bool AddNotification(
|
||||||
|
const io_name_t type,
|
||||||
|
const char* class_name,
|
||||||
|
IOServiceMatchingCallback callback);
|
||||||
|
|
||||||
|
static void DeviceAddedCallback(void* refcon, io_iterator_t it);
|
||||||
|
static void DeviceRemovedCallback(void* refcon, io_iterator_t it);
|
||||||
|
|
||||||
|
static void StorageAddedCallback(void* refcon, io_iterator_t it);
|
||||||
|
|
||||||
|
static void DiskAddedCallback(DADiskRef disk, void* context);
|
||||||
|
static void DiskRemovedCallback(DADiskRef disk, void* context);
|
||||||
|
|
||||||
|
static DADissenterRef DiskMountCallback(DADiskRef disk, void* context);
|
||||||
|
|
||||||
|
IONotificationPortRef notification_port_;
|
||||||
|
|
||||||
|
boost::scoped_ptr<MacDeviceListerPrivate> p_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
227
src/devices/macdevicelister.mm
Normal file
227
src/devices/macdevicelister.mm
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
#include "macdevicelister.h"
|
||||||
|
|
||||||
|
#include <CoreFoundation/CFRunLoop.h>
|
||||||
|
#include <DiskArbitration/DiskArbitration.h>
|
||||||
|
#include <IOKit/storage/IOBlockStorageDevice.h>
|
||||||
|
#include <IOKit/storage/IOStorage.h>
|
||||||
|
#include <IOKit/usb/IOUSBLib.h>
|
||||||
|
|
||||||
|
#import <AppKit/NSWorkspace.h>
|
||||||
|
#import <Foundation/NSNotification.h>
|
||||||
|
#import <Foundation/NSString.h>
|
||||||
|
|
||||||
|
#include <QtDebug>
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
@interface NotificationTarget :NSObject {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) mediaMounted: (NSNotification*) notification;
|
||||||
|
- (void) mediaUnmounted: (NSNotification*) notification;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation NotificationTarget
|
||||||
|
|
||||||
|
- (id) init {
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
if ((self = [super init])) {
|
||||||
|
[[[NSWorkspace sharedWorkspace] notificationCenter]
|
||||||
|
addObserver:self
|
||||||
|
selector:@selector(mediaMounted:)
|
||||||
|
name:NSWorkspaceDidMountNotification
|
||||||
|
object:[NSWorkspace sharedWorkspace]];
|
||||||
|
|
||||||
|
[[[NSWorkspace sharedWorkspace] notificationCenter]
|
||||||
|
addObserver:self
|
||||||
|
selector:@selector(mediaUnmounted:)
|
||||||
|
name:NSWorkspaceDidUnmountNotification
|
||||||
|
object:[NSWorkspace sharedWorkspace]];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) mediaMounted: (NSNotification*) notification {
|
||||||
|
NSString* path = [[notification userInfo] objectForKey:@"NSDevicePath"];
|
||||||
|
qDebug() << Q_FUNC_INFO << QString::fromUtf8([path UTF8String]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) mediaUnmounted: (NSNotification*) notification {
|
||||||
|
NSString* path = [[notification userInfo] objectForKey:@"NSDevicePath"];
|
||||||
|
qDebug() << Q_FUNC_INFO << QString::fromUtf8([path UTF8String]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
class MacDeviceListerPrivate {
|
||||||
|
public:
|
||||||
|
MacDeviceListerPrivate() {
|
||||||
|
target_ = [[NotificationTarget alloc] init];
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
NotificationTarget* target_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
MacDeviceLister::MacDeviceLister() : p_(new MacDeviceListerPrivate) {
|
||||||
|
}
|
||||||
|
|
||||||
|
MacDeviceLister::~MacDeviceLister() {
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacDeviceLister::Init() {
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
notification_port_ = IONotificationPortCreate(kIOMasterPortDefault);
|
||||||
|
CFRunLoopSourceRef loop_source =
|
||||||
|
IONotificationPortGetRunLoopSource(notification_port_);
|
||||||
|
|
||||||
|
CFRunLoopRef run_loop = CFRunLoopGetCurrent();
|
||||||
|
CFRunLoopAddSource(run_loop, loop_source, kCFRunLoopDefaultMode);
|
||||||
|
|
||||||
|
AddNotification(
|
||||||
|
kIOFirstMatchNotification,
|
||||||
|
kIOUSBDeviceClassName,
|
||||||
|
&DeviceAddedCallback);
|
||||||
|
AddNotification(
|
||||||
|
kIOTerminatedNotification,
|
||||||
|
kIOUSBDeviceClassName,
|
||||||
|
&DeviceRemovedCallback);
|
||||||
|
|
||||||
|
AddNotification(
|
||||||
|
kIOFirstMatchNotification,
|
||||||
|
kIOBlockStorageDeviceClass,
|
||||||
|
&StorageAddedCallback);
|
||||||
|
|
||||||
|
|
||||||
|
DASessionRef da_session = DASessionCreate(kCFAllocatorDefault);
|
||||||
|
DARegisterDiskAppearedCallback(
|
||||||
|
da_session, NULL, &DiskAddedCallback, reinterpret_cast<void*>(this));
|
||||||
|
DARegisterDiskDisappearedCallback(
|
||||||
|
da_session, NULL, &DiskRemovedCallback, reinterpret_cast<void*>(this));
|
||||||
|
DAApprovalSessionRef approval_session = DAApprovalSessionCreate(kCFAllocatorDefault);
|
||||||
|
DARegisterDiskMountApprovalCallback(
|
||||||
|
approval_session, NULL, &DiskMountCallback, reinterpret_cast<void*>(this));
|
||||||
|
DASessionScheduleWithRunLoop(da_session, run_loop, kCFRunLoopDefaultMode);
|
||||||
|
DAApprovalSessionScheduleWithRunLoop(approval_session, run_loop, kCFRunLoopDefaultMode);
|
||||||
|
CFRelease(da_session);
|
||||||
|
CFRelease(approval_session);
|
||||||
|
|
||||||
|
|
||||||
|
qDebug() << "STARTING LOOP";
|
||||||
|
CFRunLoopRun();
|
||||||
|
qDebug() << "ENDING LOOP";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacDeviceLister::AddNotification(
|
||||||
|
const io_name_t type,
|
||||||
|
const char* class_name,
|
||||||
|
IOServiceMatchingCallback callback) {
|
||||||
|
CFMutableDictionaryRef matching_dict = IOServiceMatching(class_name);
|
||||||
|
io_iterator_t it;
|
||||||
|
kern_return_t ret = IOServiceAddMatchingNotification(
|
||||||
|
notification_port_,
|
||||||
|
type,
|
||||||
|
matching_dict,
|
||||||
|
callback,
|
||||||
|
reinterpret_cast<void*>(this),
|
||||||
|
&it);
|
||||||
|
if (ret != KERN_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (IOIteratorNext(it));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacDeviceLister::DeviceAddedCallback(void* refcon, io_iterator_t it) {
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
io_object_t object;
|
||||||
|
while ((object = IOIteratorNext(it))) {
|
||||||
|
io_name_t class_name;
|
||||||
|
IOObjectGetClass(object, class_name);
|
||||||
|
qDebug() << class_name;
|
||||||
|
|
||||||
|
IOObjectRelease(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacDeviceLister::DeviceRemovedCallback(void* refcon, io_iterator_t it) {
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
while (IOIteratorNext(it));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacDeviceLister::StorageAddedCallback(void* refcon, io_iterator_t it) {
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
io_object_t object;
|
||||||
|
while ((object = IOIteratorNext(it))) {
|
||||||
|
io_name_t class_name;
|
||||||
|
IOObjectGetClass(object, class_name);
|
||||||
|
qDebug() << class_name;
|
||||||
|
|
||||||
|
io_iterator_t registry_it;
|
||||||
|
kern_return_t ret = IORegistryEntryGetParentEntry(
|
||||||
|
object, kIOServicePlane, ®istry_it);
|
||||||
|
|
||||||
|
io_object_t registry_entry;
|
||||||
|
while ((registry_entry = IOIteratorNext(registry_it))) {
|
||||||
|
io_name_t name;
|
||||||
|
IORegistryEntryGetName(registry_entry, name);
|
||||||
|
qDebug() << name;
|
||||||
|
|
||||||
|
IOObjectRelease(registry_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IOObjectRelease(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacDeviceLister::DiskAddedCallback(DADiskRef disk, void* context) {
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
io_service_t service = DADiskCopyIOMedia(disk);
|
||||||
|
io_iterator_t registry_it;
|
||||||
|
IORegistryEntryGetParentEntry(
|
||||||
|
service, kIOServicePlane, ®istry_it);
|
||||||
|
|
||||||
|
io_object_t registry_entry;
|
||||||
|
while ((registry_entry = IOIteratorNext(registry_it))) {
|
||||||
|
io_name_t name;
|
||||||
|
IORegistryEntryGetName(registry_entry, name);
|
||||||
|
qDebug() << name;
|
||||||
|
|
||||||
|
IOObjectRelease(registry_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << DADiskGetBSDName(disk);
|
||||||
|
|
||||||
|
IOObjectRelease(service);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacDeviceLister::DiskRemovedCallback(DADiskRef, void* context) {
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
DADissenterRef MacDeviceLister::DiskMountCallback(DADiskRef disk, void* context) {
|
||||||
|
qDebug() << Q_FUNC_INFO << DADiskGetBSDName(disk);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList MacDeviceLister::DeviceUniqueIDs(){return QStringList();}
|
||||||
|
QStringList MacDeviceLister::DeviceIcons(const QString& id){return QStringList();}
|
||||||
|
QString MacDeviceLister::DeviceManufacturer(const QString& id){return QString();}
|
||||||
|
QString MacDeviceLister::DeviceModel(const QString& id){return QString();}
|
||||||
|
quint64 MacDeviceLister::DeviceCapacity(const QString& id){return 0;}
|
||||||
|
quint64 MacDeviceLister::DeviceFreeSpace(const QString& id){return 0;}
|
||||||
|
QVariantMap MacDeviceLister::DeviceHardwareInfo(const QString& id){return QVariantMap();}
|
||||||
|
QString MacDeviceLister::MakeFriendlyName(const QString& id){return QString();}
|
||||||
|
QUrl MacDeviceLister::MakeDeviceUrl(const QString& id){return QUrl();}
|
Loading…
Reference in New Issue
Block a user