Ticket #11338: libcec2-upstream.2.patch
File libcec2-upstream.2.patch, 17.3 KB (added by , 9 years ago) |
---|
-
b/mythtv/libs/libmythui/cecadapter.cpp
diff -u b/mythtv/libs/libmythui/cecadapter.cpp b/mythtv/libs/libmythui/cecadapter.cpp
13 13 #include "cecadapter.h" 14 14 #include <vector> 15 15 16 #define MIN_LIBCEC_VERSION 117 16 #define MAX_CEC_DEVICES 10 18 17 #define LOC QString("CECAdapter: ") 19 18 … … 27 26 QMutex* CECAdapter::gHandleActionsLock = new QMutex(); 28 27 QWaitCondition* CECAdapter::gActionsReady = new QWaitCondition(); 29 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 30 40 // The libCEC callback functions 31 static int CECLogMessageCallback(void *adapter, const cec_log_message &message); 32 static int CECKeyPressCallback(void *adapter, const cec_keypress &keypress); 33 static int CECCommandCallback(void *adapter, const cec_command &command); 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 34 49 35 50 class CECAdapterPriv 36 51 { 37 52 public: 38 53 CECAdapterPriv() 39 : adapter(NULL), defaultDevice("auto"), defaultHDMIPort(1), 40 defaultDeviceID(CECDEVICE_PLAYBACKDEVICE1), valid(false), 54 : adapter(NULL), valid(false), 41 55 powerOffTV(false), powerOffTVAllowed(false), powerOffTVOnExit(false), 42 56 powerOnTV(false), powerOnTVAllowed(false), powerOnTVOnStart(false), 43 57 switchInput(false), switchInputAllowed(true) 44 58 { 45 // libcec2's ICECCallbacks has a constructor that clears 46 // all the entries. We're using 1.x.... 47 memset(&callbacks, 0, sizeof(callbacks)); 48 callbacks.CBCecLogMessage = &CECLogMessageCallback; 49 callbacks.CBCecKeyPress = &CECKeyPressCallback; 50 callbacks.CBCecCommand = &CECCommandCallback; 51 } 52 53 static QString addressToString(enum cec_logical_address addr, bool source) 54 { 55 switch (addr) 56 { 57 case CECDEVICE_UNKNOWN: return QString("Unknown"); 58 case CECDEVICE_TV: return QString("TV"); 59 case CECDEVICE_RECORDINGDEVICE1: return QString("RecordingDevice1"); 60 case CECDEVICE_RECORDINGDEVICE2: return QString("RecordingDevice2"); 61 case CECDEVICE_RECORDINGDEVICE3: return QString("RecordingDevice3"); 62 case CECDEVICE_TUNER1: return QString("Tuner1"); 63 case CECDEVICE_TUNER2: return QString("Tuner2"); 64 case CECDEVICE_TUNER3: return QString("Tuner3"); 65 case CECDEVICE_TUNER4: return QString("Tuner4"); 66 case CECDEVICE_PLAYBACKDEVICE1: return QString("PlaybackDevice1"); 67 case CECDEVICE_PLAYBACKDEVICE2: return QString("PlaybackDevice2"); 68 case CECDEVICE_PLAYBACKDEVICE3: return QString("PlaybackDevice3"); 69 case CECDEVICE_AUDIOSYSTEM: return QString("Audiosystem"); 70 case CECDEVICE_RESERVED1: return QString("Reserved1"); 71 case CECDEVICE_RESERVED2: return QString("Reserved2"); 72 case CECDEVICE_FREEUSE: return QString("FreeUse"); 73 case CECDEVICE_UNREGISTERED: 74 //case CECDEVICE_BROADCAST: 75 return source ? QString("Unregistered") : QString("Broadcast"); 76 } 77 return QString("Invalid"); 78 } 79 80 // N.B. This may need revisiting when the UI is added 81 static QStringList GetDeviceList(void) 82 { 83 QStringList results; 84 cec_device_type_list list; 85 list.Clear(); 86 list.Add(CEC_DEVICE_TYPE_PLAYBACK_DEVICE); 87 ICECAdapter *adapter = LibCecInit("MythTV", list); 88 if (!adapter) 89 return results; 90 cec_adapter *devices = new cec_adapter[MAX_CEC_DEVICES]; 91 uint8_t num_devices = adapter->FindAdapters(devices, MAX_CEC_DEVICES, NULL); 92 if (num_devices < 1) 93 return results; 94 for (uint8_t i = 0; i < num_devices; i++) 95 results << QString::fromAscii(devices[i].comm); 96 UnloadLibCec(adapter); 97 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 98 65 } 99 66 100 67 bool Open(void) 101 68 { 102 69 // get settings 103 // N.B. these do not currently work as there is no UI 104 defaultDevice = gCoreContext->GetSetting(LIBCEC_DEVICE, "auto").trimmed(); 105 QString hdmi_port = gCoreContext->GetSetting(LIBCEC_PORT, "auto"); 106 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 107 79 powerOffTVAllowed = (bool)gCoreContext->GetNumSetting(POWEROFFTV_ALLOWED, 1); 108 80 powerOffTVOnExit = (bool)gCoreContext->GetNumSetting(POWEROFFTV_ONEXIT, 1); 109 81 powerOnTVAllowed = (bool)gCoreContext->GetNumSetting(POWERONTV_ALLOWED, 1); 110 82 powerOnTVOnStart = (bool)gCoreContext->GetNumSetting(POWERONTV_ONSTART, 1); 111 83 112 defaultHDMIPort = 1; 113 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) 114 95 { 115 defaultHDMIPort = hdmi_port.toInt(); 116 if (defaultHDMIPort < 1 || defaultHDMIPort > 4) 117 defaultHDMIPort = 1; 96 int base = base_dev.toInt(); 97 if (base >= 0 && base < CECDEVICE_BROADCAST) { 98 configuration.baseDevice = (cec_logical_address)base; 99 } 118 100 } 119 defaultHDMIPort = defaultHDMIPort << 12;120 101 121 defaultDeviceID = CECDEVICE_PLAYBACKDEVICE1; 122 if ("auto" != device_id) 102 if ("auto" != hdmi_port) 123 103 { 124 int id = device_id.toInt(); 125 if (id < 1 || id > 3) 126 id = 1; 127 defaultDeviceID = (id == 1) ? CECDEVICE_PLAYBACKDEVICE1 : 128 ((id == 2) ? CECDEVICE_PLAYBACKDEVICE2 : 129 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 } 130 108 } 131 109 132 // create adapter interface 133 cec_device_type_list list; 134 list.Clear(); 135 list.Add(CEC_DEVICE_TYPE_PLAYBACK_DEVICE); 136 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); 137 123 138 124 if (!adapter) 139 125 { … … 141 127 return false; 142 128 } 143 129 144 if (adapter->GetMinLibVersion() > MIN_LIBCEC_VERSION)145 {146 LOG(VB_GENERAL, LOG_ERR, LOC +147 QString("The installed libCEC supports version %1 and above. "148 "This version of MythTV only supports version %2.")149 .arg(adapter->GetMinLibVersion()).arg(MIN_LIBCEC_VERSION));150 return false;151 }152 153 130 // find adapters 154 131 cec_adapter *devices = new cec_adapter[MAX_CEC_DEVICES]; 155 132 uint8_t num_devices = adapter->FindAdapters(devices, MAX_CEC_DEVICES, NULL); … … 182 159 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Trying to open device %1 (%2).") 183 160 .arg(path).arg(comm)); 184 161 185 // set the callbacks186 // don't error check - versions < 1.6.3 always return187 // false. And newer versions always return true, so188 // there's not much point anyway189 adapter->EnableCallbacks(this, &callbacks);190 191 162 if (!adapter->Open(devices[devicenum].comm)) 192 163 { 193 164 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to open device."); … … 196 167 197 168 LOG(VB_GENERAL, LOG_INFO, LOC + "Opened CEC device."); 198 169 199 // get the vendor ID (for non-standard implementations)200 adapter->GetDeviceVendorId(CECDEVICE_TV);201 202 // set the physical address203 adapter->SetPhysicalAddress(defaultHDMIPort);204 205 // set the logical address206 adapter->SetLogicalAddress(defaultDeviceID);207 208 170 // all good to go 209 171 valid = true; 210 172 … … 219 181 return true; 220 182 } 221 183 222 223 184 void Close(void) 224 185 { 225 186 if (adapter) … … 253 214 return 1; 254 215 } 255 216 217 // NOTE - libcec2 changes the callbacks 218 // to be pass-by-value. 219 // For simplicity, this function remains as pass-by-ref 256 220 int HandleCommand(const cec_command &command) 257 221 { 258 222 if (!adapter || !valid) … … 261 225 LOG(VB_GENERAL, LOG_DEBUG, LOC + 262 226 QString("Command %1 from '%2' (%3) - destination '%4' (%5)") 263 227 .arg(command.opcode) 264 .arg(ad dressToString(command.initiator, true))228 .arg(adapter->ToString(command.initiator)) 265 229 .arg(command.initiator) 266 .arg(ad dressToString(command.destination, false))230 .arg(adapter->ToString(command.destination)) 267 231 .arg(command.destination)); 268 232 269 233 switch (command.opcode) … … 606 570 return 1; 607 571 } 608 572 573 #if CEC_LIB_VERSION_MAJOR >= 2 574 int HandleAlert(const libcec_alert alert, const libcec_parameter &data) 575 { 576 // These aren't handled yet 577 // Note that we *DON'T* want to just show these 578 // to the user in a popup, because some (eg prompting about firmware 579 // upgrades) aren't appropriate. 580 // Ideally we'd try to handle this, eg by reopening the adapter 581 // in a separate thread if it lost the connection.... 582 583 QString param; 584 switch (data.paramType) 585 { 586 case CEC_PARAMETER_TYPE_STRING: 587 param = QString(": %1").arg((char*)data.paramData); 588 break; 589 case CEC_PARAMETER_TYPE_UNKOWN: /* libcec typo */ 590 default: 591 if (data.paramData != NULL) 592 { 593 param = QString(": UNKNOWN param has type %1").arg(data.paramType); 594 } 595 break; 596 } 597 598 // There is no ToString method for libcec_alert... 599 // Plus libcec adds new values in minor releases (eg 2.1.1) 600 // but doesn't provide a #define for the last digit... 601 // Besides, it makes sense to do this, since we could be compiling 602 // against an older version than we're running against 603 #if CEC_LIB_VERSION_MAJOR == 2 && CEC_LIB_VERSION_MINOR < 1 604 // since 2.0.4 605 #define CEC_ALERT_PHYSICAL_ADDRESS_ERROR 4 606 #endif 607 #if CEC_LIB_VERSION_MAJOR == 2 && CEC_LIB_VERSION_MINOR < 2 608 // since 2.1.1 609 #define CEC_ALERT_TV_POLL_FAILED 5 610 #endif 611 switch (alert) 612 { 613 case CEC_ALERT_SERVICE_DEVICE: 614 LOG(VB_GENERAL, LOG_INFO, LOC + QString("CEC device service message") + param); 615 break; 616 case CEC_ALERT_CONNECTION_LOST: 617 LOG(VB_GENERAL, LOG_ERR, LOC + QString("CEC device connection list") + param); 618 break; 619 case CEC_ALERT_PERMISSION_ERROR: 620 case CEC_ALERT_PORT_BUSY: 621 /* Don't log due to possible false positives on the initial 622 * open. libcec will log via the logging callback anyway 623 */ 624 break; 625 case CEC_ALERT_PHYSICAL_ADDRESS_ERROR: 626 LOG(VB_GENERAL, LOG_ERR, LOC + QString("CEC physical address error") + param); 627 break; 628 case CEC_ALERT_TV_POLL_FAILED: 629 LOG(VB_GENERAL, LOG_WARNING, LOC + QString("CEC device can't poll TV") + param); 630 break; 631 default: 632 LOG(VB_GENERAL, LOG_WARNING, LOC + QString("UNKNOWN CEC device alert %1").arg(alert) + param); 633 break; 634 } 635 636 return 1; 637 } 638 639 void HandleSourceActivated(const cec_logical_address address, const uint8_t activated) 640 { 641 if (!adapter || !valid) 642 return; 643 644 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Source %1 %2").arg(adapter->ToString(address)).arg(activated ? "Activated" : "Deactivated")); 645 646 if (activated) 647 GetMythUI()->ResetScreensaver(); 648 } 649 #endif 650 609 651 void HandleActions(void) 610 652 { 611 653 if (!adapter || !valid) … … 631 673 // HDMI input 632 674 if (switchInput && switchInputAllowed) 633 675 { 634 if (adapter->SetActive View())676 if (adapter->SetActiveSource()) 635 677 LOG(VB_GENERAL, LOG_INFO, LOC + "Asked TV to switch to this input."); 636 678 else 637 679 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to switch to this input."); … … 644 686 645 687 ICECAdapter *adapter; 646 688 ICECCallbacks callbacks; 647 QString defaultDevice;648 int defaultHDMIPort;649 cec_logical_address defaultDeviceID;650 689 bool valid; 651 690 bool powerOffTV; 652 691 bool powerOffTVAllowed; … … 658 697 bool switchInputAllowed; 659 698 }; 660 699 661 QStringList CECAdapter::GetDeviceList(void)662 {663 QMutexLocker lock(gLock);664 return CECAdapterPriv::GetDeviceList();665 }666 667 700 CECAdapter::CECAdapter() : MThread("CECAdapter"), m_priv(new CECAdapterPriv) 668 701 { 669 702 QMutexLocker lock(gLock); … … 732 static int CECLogMessageCallback(void *adapter, const cec_log_message &message)765 static int CECLogMessageCallback(void *adapter, const cec_log_message CEC_CALLBACK_PARAM_TYPE message) 733 766 { 734 767 return ((CECAdapterPriv*)adapter)->LogMessage(message); 735 768 } 736 769 737 static int CECKeyPressCallback(void *adapter, const cec_keypress &keypress)770 static int CECKeyPressCallback(void *adapter, const cec_keypress CEC_CALLBACK_PARAM_TYPE keypress) 738 771 { 739 772 return ((CECAdapterPriv*)adapter)->HandleKeyPress(keypress); 740 773 } 741 774 742 static int CECCommandCallback(void *adapter, const cec_command &command)775 static int CECCommandCallback(void *adapter, const cec_command CEC_CALLBACK_PARAM_TYPE command) 743 776 { 744 777 return ((CECAdapterPriv*)adapter)->HandleCommand(command); 745 778 } 746 779 780 #if CEC_LIB_VERSION_MAJOR >= 2 781 static int CECAlertCallback(void *adapter, const libcec_alert alert, const libcec_parameter CEC_CALLBACK_PARAM_TYPE data) 782 { 783 return ((CECAdapterPriv*)adapter)->HandleAlert(alert, data); 784 } 785 786 static void CECSourceActivatedCallback(void *adapter, const cec_logical_address address, const uint8_t activated) 787 { 788 ((CECAdapterPriv*)adapter)->HandleSourceActivated(address, activated); 789 } 790 #endif -
b/mythtv/libs/libmythui/cecadapter.h
diff -u b/mythtv/libs/libmythui/cecadapter.h b/mythtv/libs/libmythui/cecadapter.h
7 7 8 8 #define LIBCEC_ENABLED QString("libCECEnabled") 9 9 #define LIBCEC_DEVICE QString("libCECDevice") 10 #define LIBCEC_BASE QString("libCECBase") 10 11 #define LIBCEC_PORT QString("libCECPort") 11 #define LIBCEC_DEVICEID QString("libCECDeviceID")12 12 #define POWEROFFTV_ALLOWED QString("PowerOffTVAllowed") 13 13 #define POWEROFFTV_ONEXIT QString("PowerOffTVOnExit") 14 14 #define POWERONTV_ALLOWED QString("PowerOnTVAllowed") … … 21 21 Q_OBJECT 22 22 23 23 public: 24 static QStringList GetDeviceList(void);25 26 24 CECAdapter(); 27 25 virtual ~CECAdapter(); 28 26 bool IsValid(); -
mythtv/configure
only in patch2: unchanged:
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