--- a/qtmobility/src/systeminfo/qsysteminfo_mac.mm Fri Jun 11 14:26:25 2010 +0300
+++ b/qtmobility/src/systeminfo/qsysteminfo_mac.mm Wed Jun 23 19:08:38 2010 +0300
@@ -123,6 +123,7 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
+
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>("QSystemNetworkInfo::NetworkMode");
qRegisterMetaType<QSystemNetworkInfo::NetworkStatus>("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;