diff -r ce961d2c008b -r 6745d806c5ff qtmobility/src/systeminfo/qsysteminfo_mac.mm --- a/qtmobility/src/systeminfo/qsysteminfo_mac.mm Mon Jun 21 22:38:54 2010 +0100 +++ b/qtmobility/src/systeminfo/qsysteminfo_mac.mm Thu Jul 22 16:42:52 2010 +0100 @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -123,6 +123,7 @@ #include #include + static QString stringFromCFString(CFStringRef value) { QString retVal; if(CFStringGetLength(value) > 1) { @@ -306,6 +307,8 @@ QTM_BEGIN_NAMESPACE +Q_GLOBAL_STATIC(QSystemDeviceInfoPrivate, qsystemDeviceInfoPrivate) + QSystemInfoPrivate *QSystemInfoPrivate::self = 0; QSystemInfoPrivate::QSystemInfoPrivate(QObject *parent) @@ -319,7 +322,6 @@ { if(langloopThread->isRunning()) { langloopThread->quit(); - langloopThread->wait(); } } @@ -523,7 +525,10 @@ } #ifdef MAC_SDK_10_6 +QtMLangListener *langListener; #endif + + QLangLoopThread::QLangLoopThread(QObject *parent) :QThread(parent) { @@ -537,7 +542,12 @@ { mutex.lock(); keepRunning = false; + CFRunLoopStop(CFRunLoopGetCurrent()); +#ifdef MAC_SDK_10_6 + [langListener release]; +#endif mutex.unlock(); + wait(); } void QLangLoopThread::run() @@ -548,8 +558,7 @@ mutex.unlock(); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - QtMLangListener *listener; - listener = [[QtMLangListener alloc] init]; + langListener = [[QtMLangListener alloc] init]; NSDate *loopUntil = [NSDate dateWithTimeIntervalSinceNow:1.0]; while (keepRunning && @@ -571,18 +580,24 @@ QRunLoopThread::~QRunLoopThread() { -#ifdef MAC_SDK_10_6 - [listener dealloc]; -#endif } -void QRunLoopThread::quit() +void QRunLoopThread::stop() { - CFRelease(runloopSource); mutex.lock(); keepRunning = false; mutex.unlock(); - CFRelease(storeSession); +#ifdef MAC_SDK_10_6 + [listener release]; + [delegate release]; +#endif + if(currentThread() != this) { + QMetaObject::invokeMethod(this, "quit", + Qt::QueuedConnection); + } else { + quit(); + } + wait(); } @@ -600,11 +615,11 @@ listener = [[QtMNSListener alloc] init]; - NSDate *loopUntil = [NSDate dateWithTimeIntervalSinceNow:1.0]; + SInt32 result; while (keepRunning && - [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: loopUntil]) { - loopUntil = [NSDate dateWithTimeIntervalSinceNow:1.0]; + (result = CFRunLoopRunInMode(kCFRunLoopDefaultMode ,5, YES))) { } + CFRunLoopStop(CFRunLoopGetCurrent()); [pool release]; #endif } @@ -687,16 +702,161 @@ } CFRunLoopAddSource(CFRunLoopGetCurrent(), runloopSource, kCFRunLoopDefaultMode); + CFRelease(runloopSource); + CFRelease(storeSession); return; } +static bool isBtPowerOn() +{ + //depreciated yes, but what's the replacement? + BluetoothHCIPowerState powerState; + IOBluetoothLocalDeviceGetPowerState(&powerState); + if(powerState == kBluetoothHCIPowerStateON) + return true; + return false; +} + +void btPowerStateChange(void *ref, io_service_t /*service*/, natural_t messageType, void */*info*/) +{ + QBluetoothListenerThread * thread = reinterpret_cast< QBluetoothListenerThread *>(ref); + switch (messageType) { + case kIOMessageDeviceWillPowerOff: + { + if(!isBtPowerOn()) + thread->emitBtPower(false); + } + break; + case kIOMessageDeviceHasPoweredOn: + { + if(isBtPowerOn()) + thread->emitBtPower(true); + } + break; + } +} + +QBluetoothListenerThread::QBluetoothListenerThread(QObject *parent) + :QThread(parent) +{ + setTerminationEnabled(true); +} + +QBluetoothListenerThread::~QBluetoothListenerThread() +{ + if(isRunning()) { + terminate(); + wait(); + } +} + +void QBluetoothListenerThread::stop() +{ + mutex.lock(); + keepRunning = false; + mutex.unlock(); + + if(CFRunLoopContainsSource(rl,rls,kCFRunLoopDefaultMode)) { + CFRunLoopRemoveSource(rl, + rls, + kCFRunLoopDefaultMode); + CFRunLoopStop(rl); + } + if(currentThread() != this) { + QMetaObject::invokeMethod(this, "quit", + Qt::QueuedConnection); + } else { + quit(); + } + mutex.lock(); + IONotificationPortDestroy(port); + mutex.unlock(); +} + +void QBluetoothListenerThread::run() +{ +#ifdef MAC_SDK_10_6 + mutex.lock(); + keepRunning = true; + mutex.unlock(); + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + io_object_t notifyObject; + io_service_t bluetoothservice; + + io_iterator_t ioIterator; + mach_port_t masterPort; + CFMutableDictionaryRef serviceMatchDict; + + if (0 != IOMasterPort(MACH_PORT_NULL, &masterPort)) { + qDebug() << "IOMasterPort failed"; + } + + serviceMatchDict = IOServiceMatching("IOBluetoothHCIController"); + if (NULL == serviceMatchDict) { + qDebug() << "IOServiceMatching failed"; + } + + if (0 != IOServiceGetMatchingServices(masterPort, serviceMatchDict, &ioIterator)) { + qDebug() << "IOServiceGetMatchingServices failed"; + } + + IOReturn ret; + + bluetoothservice = IOIteratorNext(ioIterator); + if (0 == bluetoothservice) { + IOObjectRelease(ioIterator); + qDebug() << "IOIteratorNext failed"; + } + IOObjectRelease(ioIterator); + + port = IONotificationPortCreate(masterPort); + if (0 == port) { + qDebug() << "IONotificationPortCreate failed"; + } + + ret = IOServiceAddInterestNotification(port, bluetoothservice, + kIOGeneralInterest, btPowerStateChange, + this, ¬ifyObject); + if(ret != kIOReturnSuccess) { + qDebug() << "IOServiceAddInterestNotification failed"; + return; + } + + rl = CFRunLoopGetCurrent(); + rls = IONotificationPortGetRunLoopSource(port); + + CFRunLoopAddSource(rl, + rls, + kCFRunLoopDefaultMode); + SInt32 result; + while (keepRunning && + (result = CFRunLoopRunInMode(kCFRunLoopDefaultMode ,1, NO))) { + } + + CFRunLoopStop(rl); + + IOObjectRelease(bluetoothservice); + CFRunLoopRemoveSource(rl, + rls, + kCFRunLoopDefaultMode); + [pool release]; +#endif +} + +void QBluetoothListenerThread::emitBtPower(bool b) +{ + Q_EMIT bluetoothPower(b); +} + + QSystemNetworkInfoPrivate::QSystemNetworkInfoPrivate(QObject *parent) : QObject(parent), signalStrengthCache(0) { defaultInterface = ""; qRegisterMetaType("QSystemNetworkInfo::NetworkMode"); qRegisterMetaType("QSystemNetworkInfo::NetworkStatus"); + #ifdef MAC_SDK_10_6 if([[CWInterface supportedInterfaces] count] > 0 ) { hasWifi = true; @@ -715,9 +875,7 @@ { #ifdef MAC_SDK_10_6 if(hasWifi && runloopThread->isRunning()) { - runloopThread->quit(); - runloopThread->wait(); - [delegate release]; + runloopThread->stop(); } #endif } @@ -1377,8 +1535,6 @@ return drivesList; } -QSystemDeviceInfoPrivate *QSystemDeviceInfoPrivate::self = 0; - void powerInfoChanged(void* runLoopInfo) { Q_UNUSED(runLoopInfo) @@ -1387,24 +1543,52 @@ } QSystemDeviceInfoPrivate::QSystemDeviceInfoPrivate(QObject *parent) - : QObject(parent) + : QObject(parent),btThread(0) { batteryLevelCache = 0; currentPowerStateCache = QSystemDeviceInfo::UnknownPower; batteryStatusCache = QSystemDeviceInfo::NoBatteryLevel; - CFRunLoopSourceRef runLoopSource = (CFRunLoopSourceRef)IOPSNotificationCreateRunLoopSource(powerInfoChanged, this); - if (runLoopSource) { - CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode); - CFRelease(runLoopSource); - } - if(!self) - self = this; } QSystemDeviceInfoPrivate::~QSystemDeviceInfoPrivate() { + btThread->stop(); } +QSystemDeviceInfoPrivate *QSystemDeviceInfoPrivate::instance() +{ + return qsystemDeviceInfoPrivate(); +} + +void QSystemDeviceInfoPrivate::connectNotify(const char *signal) +{ + if (QLatin1String(signal) == SIGNAL(bluetoothStateChanged(bool))) { + if(!btThread) { + btThread = new QBluetoothListenerThread(this); + btThread->start(); + connect(btThread,SIGNAL(bluetoothPower(bool)), this, SIGNAL(bluetoothStateChanged(bool))); + } + } + + if (QLatin1String(signal) == SIGNAL(powerStateChanged(QSystemDeviceInfo::PowerState))) { + CFRunLoopSourceRef runLoopSource = (CFRunLoopSourceRef)IOPSNotificationCreateRunLoopSource(powerInfoChanged, this); + if (runLoopSource) { + CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode); + CFRelease(runLoopSource); + } + } +} + +void QSystemDeviceInfoPrivate::disconnectNotify(const char *signal) +{ + if (QLatin1String(signal) == SIGNAL(bluetoothStateChanged(bool))) { + if(btThread->isRunning()) { + btThread->stop(); + } + } +} + + QSystemDeviceInfo::Profile QSystemDeviceInfoPrivate::currentProfile() { return QSystemDeviceInfo::UnknownProfile;