Ticket #11338: libcec2.patch
File libcec2.patch, 21.4 KB (added by , 10 years ago) |
---|
-
mythtv/configure
diff --git a/mythtv/configure b/mythtv/configure index 519d352..aa086c5 100755
a b int main(void) { 5477 5477 if (CEC_LIB_VERSION_MAJOR < 1 || (CEC_LIB_VERSION_MAJOR == 1 && 5478 5478 CEC_LIB_VERSION_MINOR < 5)) 5479 5479 return 0; 5480 return (long) LibCecInit;5480 return 1; 5481 5481 } 5482 5482 EOF 5483 5483 fi -
mythtv/libs/libmythui/cecadapter.cpp
diff --git a/mythtv/libs/libmythui/cecadapter.cpp b/mythtv/libs/libmythui/cecadapter.cpp index edad8f6..61ffb72 100644
a b 1 1 // Qt 2 2 #include <QApplication> 3 #include <QTimer>4 3 #include <QKeyEvent> 5 4 #include <QString> 6 5 … … 14 13 #include "cecadapter.h" 15 14 #include <vector> 16 15 17 #define MIN_LIBCEC_VERSION 118 16 #define MAX_CEC_DEVICES 10 19 17 #define LOC QString("CECAdapter: ") 20 18 … … using namespace CEC; 24 22 using namespace std; 25 23 #include <libcec/cecloader.h> 26 24 27 QMutex* CECAdapter::gLock = new QMutex(QMutex::Recursive); 25 QMutex* CECAdapter::gLock = new QMutex(QMutex::Recursive); 26 QMutex* CECAdapter::gHandleActionsLock = new QMutex(); 27 QWaitCondition* CECAdapter::gActionsReady = new QWaitCondition(); 28 29 #if CEC_LIB_VERSION_MAJOR < 2 30 // A few defines taken from libcec.h v2 31 #define CEC_MIN_HDMI_PORTNUMBER 1 32 #define CEC_MAX_HDMI_PORTNUMBER 15 33 // libcec1's callback parameters are pass-by-ref 34 #define CEC_CALLBACK_PARAM_TYPE & 35 #else 36 // libcec2's callback parameters are pass-by-value 37 #define CEC_CALLBACK_PARAM_TYPE 38 #endif 39 40 // The libCEC callback functions 41 static int CECLogMessageCallback(void *adapter, const cec_log_message CEC_CALLBACK_PARAM_TYPE message); 42 static int CECKeyPressCallback(void *adapter, const cec_keypress CEC_CALLBACK_PARAM_TYPE keypress); 43 static int CECCommandCallback(void *adapter, const cec_command CEC_CALLBACK_PARAM_TYPE command); 44 45 #if CEC_LIB_VERSION_MAJOR >= 2 46 static int CECAlertCallback(void *adapter, const libcec_alert alert, const libcec_parameter CEC_CALLBACK_PARAM_TYPE data); 47 static void CECSourceActivatedCallback(void *adapter, const cec_logical_address address, const uint8_t activated); 48 #endif 28 49 29 50 class CECAdapterPriv 30 51 { 31 52 public: 32 53 CECAdapterPriv() 33 : adapter(NULL), defaultDevice("auto"), defaultHDMIPort(1), 34 defaultDeviceID(CECDEVICE_PLAYBACKDEVICE1), timer(NULL), valid(false), 54 : adapter(NULL), valid(false), 35 55 powerOffTV(false), powerOffTVAllowed(false), powerOffTVOnExit(false), 36 56 powerOnTV(false), powerOnTVAllowed(false), powerOnTVOnStart(false), 37 57 switchInput(false), switchInputAllowed(true) 38 58 { 39 } 40 41 static QString addressToString(enum cec_logical_address addr, bool source) 42 { 43 switch (addr) 44 { 45 case CECDEVICE_UNKNOWN: return QString("Unknown"); 46 case CECDEVICE_TV: return QString("TV"); 47 case CECDEVICE_RECORDINGDEVICE1: return QString("RecordingDevice1"); 48 case CECDEVICE_RECORDINGDEVICE2: return QString("RecordingDevice2"); 49 case CECDEVICE_RECORDINGDEVICE3: return QString("RecordingDevice3"); 50 case CECDEVICE_TUNER1: return QString("Tuner1"); 51 case CECDEVICE_TUNER2: return QString("Tuner2"); 52 case CECDEVICE_TUNER3: return QString("Tuner3"); 53 case CECDEVICE_TUNER4: return QString("Tuner4"); 54 case CECDEVICE_PLAYBACKDEVICE1: return QString("PlaybackDevice1"); 55 case CECDEVICE_PLAYBACKDEVICE2: return QString("PlaybackDevice2"); 56 case CECDEVICE_PLAYBACKDEVICE3: return QString("PlaybackDevice3"); 57 case CECDEVICE_AUDIOSYSTEM: return QString("Audiosystem"); 58 case CECDEVICE_RESERVED1: return QString("Reserved1"); 59 case CECDEVICE_RESERVED2: return QString("Reserved2"); 60 case CECDEVICE_FREEUSE: return QString("FreeUse"); 61 case CECDEVICE_UNREGISTERED: 62 //case CECDEVICE_BROADCAST: 63 return source ? QString("Unregistered") : QString("Broadcast"); 64 } 65 return QString("Invalid"); 66 } 67 68 // N.B. This may need revisiting when the UI is added 69 static QStringList GetDeviceList(void) 70 { 71 QStringList results; 72 cec_device_type_list list; 73 list.Clear(); 74 list.Add(CEC_DEVICE_TYPE_PLAYBACK_DEVICE); 75 ICECAdapter *adapter = LibCecInit("MythTV", list); 76 if (!adapter) 77 return results; 78 cec_adapter *devices = new cec_adapter[MAX_CEC_DEVICES]; 79 uint8_t num_devices = adapter->FindAdapters(devices, MAX_CEC_DEVICES, NULL); 80 if (num_devices < 1) 81 return results; 82 for (uint8_t i = 0; i < num_devices; i++) 83 results << QString::fromAscii(devices[i].comm); 84 UnloadLibCec(adapter); 85 return results; 59 #if CEC_LIB_VERSION_MAJOR < 2 60 // libcec1 has this as a POD struct, with no 61 // automatic initialisation. 62 // And no .Clear() method... 63 memset(&callbacks, 0, sizeof(callbacks)); 64 #endif 86 65 } 87 66 88 67 bool Open(void) 89 68 { 90 69 // get settings 91 // N.B. these do not currently work as there is no UI 92 defaultDevice = gCoreContext->GetSetting(LIBCEC_DEVICE, "auto").trimmed(); 93 QString hdmi_port = gCoreContext->GetSetting(LIBCEC_PORT, "auto"); 94 QString device_id = gCoreContext->GetSetting(LIBCEC_DEVICEID, "auto"); 70 // N.B. these need to be set manually since there is no UI 71 QString defaultDevice = gCoreContext->GetSetting(LIBCEC_DEVICE, "auto").trimmed(); 72 // Note - if libcec supports automatic detection via EDID then 73 // these settings are not used 74 // The logical address of the HDMI device Myth is connected to 75 QString base_dev = gCoreContext->GetSetting(LIBCEC_BASE, "auto").trimmed(); 76 // The number of the HDMI port Myth is connected to 77 QString hdmi_port = gCoreContext->GetSetting(LIBCEC_PORT, "auto").trimmed(); 78 95 79 powerOffTVAllowed = (bool)gCoreContext->GetNumSetting(POWEROFFTV_ALLOWED, 1); 96 80 powerOffTVOnExit = (bool)gCoreContext->GetNumSetting(POWEROFFTV_ONEXIT, 1); 97 81 powerOnTVAllowed = (bool)gCoreContext->GetNumSetting(POWERONTV_ALLOWED, 1); 98 82 powerOnTVOnStart = (bool)gCoreContext->GetNumSetting(POWERONTV_ONSTART, 1); 99 83 100 defaultHDMIPort = 1; 101 if ("auto" != hdmi_port) 84 // create adapter interface 85 libcec_configuration configuration; 86 #if CEC_LIB_VERSION_MAJOR < 2 87 // libcec1 has this as a POD struct, with no 88 // automatic initialisation 89 configuration.Clear(); 90 #endif 91 strcpy(configuration.strDeviceName, "MythTV"); 92 configuration.deviceTypes.Add(CEC_DEVICE_TYPE_PLAYBACK_DEVICE); 93 94 if ("auto" != base_dev) 102 95 { 103 defaultHDMIPort = hdmi_port.toInt(); 104 if (defaultHDMIPort < 1 || defaultHDMIPort > 3) 105 defaultHDMIPort = 1; 96 int base = base_dev.toInt(); 97 if (base >= 0 && base < CECDEVICE_BROADCAST) { 98 configuration.baseDevice = (cec_logical_address)base; 99 } 106 100 } 107 defaultHDMIPort = defaultHDMIPort << 12;108 101 109 defaultDeviceID = CECDEVICE_PLAYBACKDEVICE1; 110 if ("auto" != device_id) 102 if ("auto" != hdmi_port) 111 103 { 112 int id = device_id.toInt(); 113 if (id < 1 || id > 3) 114 id = 1; 115 defaultDeviceID = (id == 1) ? CECDEVICE_PLAYBACKDEVICE1 : 116 ((id == 2) ? CECDEVICE_PLAYBACKDEVICE2 : 117 CECDEVICE_PLAYBACKDEVICE3); 104 int defaultHDMIPort = hdmi_port.toInt(); 105 if (defaultHDMIPort >= CEC_MIN_HDMI_PORTNUMBER && defaultHDMIPort <= CEC_MAX_HDMI_PORTNUMBER) { 106 configuration.iHDMIPort = defaultHDMIPort; 107 } 118 108 } 119 109 120 // create adapter interface 121 cec_device_type_list list; 122 list.Clear(); 123 list.Add(CEC_DEVICE_TYPE_PLAYBACK_DEVICE); 124 adapter = LibCecInit("MythTV", list); 110 // Set up the callbacks 111 callbacks.CBCecLogMessage = &CECLogMessageCallback; 112 callbacks.CBCecKeyPress = &CECKeyPressCallback; 113 callbacks.CBCecCommand = &CECCommandCallback; 114 #if CEC_LIB_VERSION_MAJOR >= 2 115 callbacks.CBCecAlert = &CECAlertCallback; 116 callbacks.CBCecSourceActivated = &CECSourceActivatedCallback; 117 #endif 118 configuration.callbackParam = this; 119 configuration.callbacks = &callbacks; 120 121 // and initialise 122 adapter = LibCecInitialise(&configuration); 125 123 126 124 if (!adapter) 127 125 { … … class CECAdapterPriv 129 127 return false; 130 128 } 131 129 132 if (adapter->GetMinLibVersion() > MIN_LIBCEC_VERSION)133 {134 LOG(VB_GENERAL, LOG_ERR, LOC +135 QString("The installed libCEC supports version %1 and above. "136 "This version of MythTV only supports version %2.")137 .arg(adapter->GetMinLibVersion()).arg(MIN_LIBCEC_VERSION));138 return false;139 }140 141 130 // find adapters 142 131 cec_adapter *devices = new cec_adapter[MAX_CEC_DEVICES]; 143 132 uint8_t num_devices = adapter->FindAdapters(devices, MAX_CEC_DEVICES, NULL); … … class CECAdapterPriv 178 167 179 168 LOG(VB_GENERAL, LOG_INFO, LOC + "Opened CEC device."); 180 169 170 // all good to go 171 valid = true; 172 181 173 // turn on tv (if configured) 182 174 powerOnTV = powerOnTVOnStart; 183 HandleActions();184 185 // get the vendor ID (for non-standard implementations)186 adapter->GetDeviceVendorId(CECDEVICE_TV);187 188 // set the physical address189 adapter->SetPhysicalAddress(defaultHDMIPort);190 191 // set the logical address192 adapter->SetLogicalAddress(defaultDeviceID);193 175 194 176 // switch input (if configured) 195 177 switchInput = true; 178 196 179 HandleActions(); 197 180 198 valid = true;199 181 return true; 200 182 } 201 183 … … class CECAdapterPriv 210 192 211 193 // delete adapter 212 194 adapter->Close(); 213 LogMessages();214 195 UnloadLibCec(adapter); 215 196 216 197 LOG(VB_GENERAL, LOG_INFO, LOC + "Closing down CEC."); … … class CECAdapterPriv 219 200 adapter = NULL; 220 201 } 221 202 222 void LogMessages(void)203 int LogMessage(const cec_log_message &message) 223 204 { 224 if (!adapter || !valid) 225 return; 226 227 cec_log_message message; 228 while (adapter->GetNextLogMessage(&message)) 205 QString msg(message.message); 206 int lvl = LOG_UNKNOWN; 207 switch (message.level) 229 208 { 230 QString msg(message.message);231 int lvl = LOG_UNKNOWN;232 switch (message.level)233 {234 209 case CEC_LOG_ERROR: lvl = LOG_ERR; break; 235 210 case CEC_LOG_WARNING: lvl = LOG_WARNING; break; 236 211 case CEC_LOG_NOTICE: lvl = LOG_INFO; break; 237 212 case CEC_LOG_DEBUG: lvl = LOG_DEBUG; break; 238 }239 LOG(VB_GENERAL, lvl, LOC + QString("%1").arg(msg));240 213 } 214 LOG(VB_GENERAL, lvl, LOC + QString("%1").arg(msg)); 215 return 1; 241 216 } 242 217 243 void HandleCommands(void) 218 // NOTE - libcec2 changes the callbacks 219 // to be pass-by-value. 220 // For simplicity, this function remains as pass-by-ref 221 int HandleCommand(const cec_command &command) 244 222 { 245 223 if (!adapter || !valid) 246 return ;224 return 0; 247 225 248 LogMessages(); 226 LOG(VB_GENERAL, LOG_DEBUG, LOC + 227 QString("Command %1 from '%2' (%3) - destination '%4' (%5)") 228 .arg(command.opcode) 229 .arg(adapter->ToString(command.initiator)) 230 .arg(command.initiator) 231 .arg(adapter->ToString(command.destination)) 232 .arg(command.destination)); 249 233 250 cec_command command; 251 while (adapter->GetNextCommand(&command)) 234 switch (command.opcode) 252 235 { 253 LOG(VB_GENERAL, LOG_DEBUG, LOC + 254 QString("Command %1 from '%2' (%3) - destination '%4' (%5)") 255 .arg(command.opcode) 256 .arg(addressToString(command.initiator, true)) 257 .arg(command.initiator) 258 .arg(addressToString(command.destination, false)) 259 .arg(command.destination)); 260 261 switch (command.opcode) 262 { 263 // TODO 264 default: 265 break; 266 } 236 // TODO 237 default: 238 break; 267 239 } 268 269 LogMessages(); 240 return 1; 270 241 } 271 242 272 void HandleKeyPresses(void)243 int HandleKeyPress(const cec_keypress &key) 273 244 { 274 245 if (!adapter || !valid) 275 return; 276 277 cec_keypress key; 278 if (!adapter->GetNextKeypress(&key)) 279 return; 246 return 0; 280 247 281 248 // Ignore key down events and wait for the key 'up' 282 249 if (key.duration < 1) 283 return ;250 return 1; 284 251 285 252 QString code; 286 253 int action = 0; … … class CECAdapterPriv 595 562 .arg(code).arg(0 == action ? "(Not actioned)" : "")); 596 563 597 564 if (0 == action) 598 return ;565 return 1; 599 566 600 567 GetMythUI()->ResetScreensaver(); 601 568 QKeyEvent* ke = new QKeyEvent(QEvent::KeyPress, action, Qt::NoModifier); 602 569 qApp->postEvent(GetMythMainWindow(), (QEvent*)ke); 603 570 604 LogMessages();571 return 1; 605 572 } 606 573 574 #if CEC_LIB_VERSION_MAJOR >= 2 575 int HandleAlert(const libcec_alert alert, const libcec_parameter &data) 576 { 577 // These aren't handled yet 578 // Note that we *DON'T* want to just show these 579 // to the user in a popup, because some (eg prompting about firmware 580 // upgrades) aren't appropriate. 581 // Ideally we'd try to handle this, eg by reopening the adapter 582 // in a separate thread if it lost the connection.... 583 584 QString param; 585 switch (data.paramType) 586 { 587 case CEC_PARAMETER_TYPE_STRING: 588 param = QString(": %1").arg((char*)data.paramData); 589 break; 590 case CEC_PARAMETER_TYPE_UNKOWN: /* libcec typo */ 591 default: 592 if (data.paramData != NULL) 593 { 594 param = QString(": UNKNOWN param has type %1").arg(data.paramType); 595 } 596 break; 597 } 598 599 // There is no ToString method for libcec_alert... 600 // Plus libcec adds new values in minor releases (eg 2.1.1) 601 // but doesn't provide a #define for the last digit... 602 // Besides, it makes sense to do this, since we could be compiling 603 // against an older version than we're running against 604 #if CEC_LIB_VERSION_MAJOR == 2 && CEC_LIB_VERSION_MINOR < 1 605 // since 2.0.4 606 #define CEC_ALERT_PHYSICAL_ADDRESS_ERROR 4 607 #endif 608 #if CEC_LIB_VERSION_MAJOR == 2 && CEC_LIB_VERSION_MINOR < 2 609 // since 2.1.1 610 #define CEC_ALERT_TV_POLL_FAILED 5 611 #endif 612 switch (alert) 613 { 614 case CEC_ALERT_SERVICE_DEVICE: 615 LOG(VB_GENERAL, LOG_INFO, LOC + QString("CEC device service message") + param); 616 break; 617 case CEC_ALERT_CONNECTION_LOST: 618 LOG(VB_GENERAL, LOG_ERR, LOC + QString("CEC device connection list") + param); 619 break; 620 case CEC_ALERT_PERMISSION_ERROR: 621 case CEC_ALERT_PORT_BUSY: 622 /* Don't log due to possible false positives on the initial 623 * open. libcec will log via the logging callback anyway 624 */ 625 break; 626 case CEC_ALERT_PHYSICAL_ADDRESS_ERROR: 627 LOG(VB_GENERAL, LOG_ERR, LOC + QString("CEC physical address error") + param); 628 break; 629 case CEC_ALERT_TV_POLL_FAILED: 630 LOG(VB_GENERAL, LOG_WARNING, LOC + QString("CEC device can't poll TV") + param); 631 break; 632 default: 633 LOG(VB_GENERAL, LOG_WARNING, LOC + QString("UNKNOWN CEC device alert %1").arg(alert) + param); 634 break; 635 } 636 637 return 1; 638 } 639 640 void HandleSourceActivated(const cec_logical_address address, const uint8_t activated) 641 { 642 if (!adapter || !valid) 643 return; 644 645 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Source %1 %2").arg(adapter->ToString(address)).arg(activated ? "Activated" : "Deactivated")); 646 647 if (activated) 648 GetMythUI()->ResetScreensaver(); 649 } 650 #endif 651 652 ICECAdapter *adapter; 607 653 void HandleActions(void) 608 654 { 609 655 if (!adapter || !valid) … … class CECAdapterPriv 629 675 // HDMI input 630 676 if (switchInput && switchInputAllowed) 631 677 { 632 if (adapter->SetActive View())678 if (adapter->SetActiveSource()) 633 679 LOG(VB_GENERAL, LOG_INFO, LOC + "Asked TV to switch to this input."); 634 680 else 635 681 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to switch to this input."); … … class CECAdapterPriv 638 684 powerOffTV = false; 639 685 powerOnTV = false; 640 686 switchInput = false; 641 642 LogMessages();643 687 } 644 688 645 ICECAdapter *adapter; 646 QString defaultDevice; 647 int defaultHDMIPort; 648 cec_logical_address defaultDeviceID; 649 QTimer *timer; 689 ICECCallbacks callbacks; 650 690 bool valid; 651 691 bool powerOffTV; 652 692 bool powerOffTVAllowed; … … class CECAdapterPriv 658 698 bool switchInputAllowed; 659 699 }; 660 700 661 QStringList CECAdapter::GetDeviceList(void)662 {663 QMutexLocker lock(gLock);664 return CECAdapterPriv::GetDeviceList();665 }666 667 701 CECAdapter::CECAdapter() : MThread("CECAdapter"), m_priv(new CECAdapterPriv) 668 702 { 669 703 QMutexLocker lock(gLock); … … CECAdapter::CECAdapter() : MThread("CECAdapter"), m_priv(new CECAdapterPriv) 679 713 if (!m_priv->Open()) 680 714 return; 681 715 682 // create process timer683 m_priv->timer = new QTimer(this);684 QObject::connect(m_priv->timer, SIGNAL(timeout()), this, SLOT(Process()));685 m_priv->timer->start(10);686 687 716 // start thread 688 717 LOG(VB_GENERAL, LOG_DEBUG, LOC + "Starting thread."); 689 718 start(); 690 719 } 691 720 721 void CECAdapter::run() 722 { 723 for (;;) { 724 // Note that a lock is used because the QWaitCondition needs it 725 // None of the other HandleActions callers need the lock because 726 // they call HandleActions at open/close time, when 727 // nothing else can be calling it.... 728 gHandleActionsLock->lock(); 729 gActionsReady->wait(gHandleActionsLock); 730 m_priv->HandleActions(); 731 gHandleActionsLock->unlock(); 732 } 733 } 734 692 735 CECAdapter::~CECAdapter() 693 736 { 694 737 QMutexLocker lock(gLock); 695 738 696 // delete process timer697 if (m_priv->timer)698 m_priv->timer->stop();699 delete m_priv->timer;700 m_priv->timer = NULL;701 702 739 // stop thread 703 740 if (isRunning()) 704 741 { … … void CECAdapter::Action(const QString &action) 723 760 m_priv->powerOnTV = true; 724 761 else if (ACTION_TVPOWEROFF == action) 725 762 m_priv->powerOffTV = true; 763 gActionsReady->wakeAll(); 764 } 765 766 static int CECLogMessageCallback(void *adapter, const cec_log_message CEC_CALLBACK_PARAM_TYPE message) 767 { 768 return ((CECAdapterPriv*)adapter)->LogMessage(message); 769 } 770 771 static int CECKeyPressCallback(void *adapter, const cec_keypress CEC_CALLBACK_PARAM_TYPE keypress) 772 { 773 return ((CECAdapterPriv*)adapter)->HandleKeyPress(keypress); 774 } 775 776 static int CECCommandCallback(void *adapter, const cec_command CEC_CALLBACK_PARAM_TYPE command) 777 { 778 return ((CECAdapterPriv*)adapter)->HandleCommand(command); 779 } 780 781 #if CEC_LIB_VERSION_MAJOR >= 2 782 static int CECAlertCallback(void *adapter, const libcec_alert alert, const libcec_parameter CEC_CALLBACK_PARAM_TYPE data) 783 { 784 return ((CECAdapterPriv*)adapter)->HandleAlert(alert, data); 726 785 } 727 786 728 void CECAdapter::Process(void)787 static void CECSourceActivatedCallback(void *adapter, const cec_logical_address address, const uint8_t activated) 729 788 { 730 gLock->lock(); 731 m_priv->HandleCommands(); 732 m_priv->HandleKeyPresses(); 733 m_priv->HandleActions(); 734 gLock->unlock(); 789 ((CECAdapterPriv*)adapter)->HandleSourceActivated(address, activated); 735 790 } 791 #endif -
mythtv/libs/libmythui/cecadapter.h
diff --git a/mythtv/libs/libmythui/cecadapter.h b/mythtv/libs/libmythui/cecadapter.h index e9cf6d6..06e55d2 100644
a b 2 2 #define CECADAPTER_H_ 3 3 4 4 #include <QMutex> 5 #include <QWaitCondition> 5 6 #include "mthread.h" 6 7 7 8 #define LIBCEC_ENABLED QString("libCECEnabled") 8 9 #define LIBCEC_DEVICE QString("libCECDevice") 10 #define LIBCEC_BASE QString("libCECBase") 9 11 #define LIBCEC_PORT QString("libCECPort") 10 #define LIBCEC_DEVICEID QString("libCECDeviceID")11 12 #define POWEROFFTV_ALLOWED QString("PowerOffTVAllowed") 12 13 #define POWEROFFTV_ONEXIT QString("PowerOffTVOnExit") 13 14 #define POWERONTV_ALLOWED QString("PowerOnTVAllowed") … … class CECAdapter : public QObject, public MThread 20 21 Q_OBJECT 21 22 22 23 public: 23 static QStringList GetDeviceList(void);24 25 24 CECAdapter(); 26 25 virtual ~CECAdapter(); 27 26 bool IsValid(); 28 27 void Action(const QString &action); 29 28 30 p ublic slots:31 v oid Process();29 protected: 30 virtual void run(); 32 31 33 32 private: 34 33 CECAdapterPriv *m_priv; 35 34 static QMutex *gLock; 35 static QMutex *gHandleActionsLock; 36 static QWaitCondition *gActionsReady; 36 37 }; 37 38 38 39 #endif