00001
00002 #include <QApplication>
00003 #include <QTimer>
00004 #include <QKeyEvent>
00005 #include <QString>
00006
00007
00008 #include "mythcorecontext.h"
00009 #include "mythlogging.h"
00010 #include "mythevent.h"
00011 #include "mythuihelper.h"
00012 #include "mythmainwindow.h"
00013
00014 #include "cecadapter.h"
00015 #include <vector>
00016
00017 #define MIN_LIBCEC_VERSION 1
00018 #define MAX_CEC_DEVICES 10
00019 #define LOC QString("CECAdapter: ")
00020
00021 #include <libcec/cec.h>
00022 #include <iostream>
00023 using namespace CEC;
00024 using namespace std;
00025 #include <libcec/cecloader.h>
00026
00027 QMutex* CECAdapter::gLock = new QMutex(QMutex::Recursive);
00028
00029 class CECAdapterPriv
00030 {
00031 public:
00032 CECAdapterPriv()
00033 : adapter(NULL), defaultDevice("auto"), defaultHDMIPort(1),
00034 defaultDeviceID(CECDEVICE_PLAYBACKDEVICE1), timer(NULL), valid(false),
00035 powerOffTV(false), powerOffTVAllowed(false), powerOffTVOnExit(false),
00036 powerOnTV(false), powerOnTVAllowed(false), powerOnTVOnStart(false),
00037 switchInput(false), switchInputAllowed(true)
00038 {
00039 }
00040
00041 static QString addressToString(enum cec_logical_address addr, bool source)
00042 {
00043 switch (addr)
00044 {
00045 case CECDEVICE_UNKNOWN: return QString("Unknown");
00046 case CECDEVICE_TV: return QString("TV");
00047 case CECDEVICE_RECORDINGDEVICE1: return QString("RecordingDevice1");
00048 case CECDEVICE_RECORDINGDEVICE2: return QString("RecordingDevice2");
00049 case CECDEVICE_RECORDINGDEVICE3: return QString("RecordingDevice3");
00050 case CECDEVICE_TUNER1: return QString("Tuner1");
00051 case CECDEVICE_TUNER2: return QString("Tuner2");
00052 case CECDEVICE_TUNER3: return QString("Tuner3");
00053 case CECDEVICE_TUNER4: return QString("Tuner4");
00054 case CECDEVICE_PLAYBACKDEVICE1: return QString("PlaybackDevice1");
00055 case CECDEVICE_PLAYBACKDEVICE2: return QString("PlaybackDevice2");
00056 case CECDEVICE_PLAYBACKDEVICE3: return QString("PlaybackDevice3");
00057 case CECDEVICE_AUDIOSYSTEM: return QString("Audiosystem");
00058 case CECDEVICE_RESERVED1: return QString("Reserved1");
00059 case CECDEVICE_RESERVED2: return QString("Reserved2");
00060 case CECDEVICE_FREEUSE: return QString("FreeUse");
00061 case CECDEVICE_UNREGISTERED:
00062
00063 return source ? QString("Unregistered") : QString("Broadcast");
00064 }
00065 return QString("Invalid");
00066 }
00067
00068
00069 static QStringList GetDeviceList(void)
00070 {
00071 QStringList results;
00072 cec_device_type_list list;
00073 list.Clear();
00074 list.Add(CEC_DEVICE_TYPE_PLAYBACK_DEVICE);
00075 ICECAdapter *adapter = LibCecInit("MythTV", list);
00076 if (!adapter)
00077 return results;
00078 cec_adapter *devices = new cec_adapter[MAX_CEC_DEVICES];
00079 uint8_t num_devices = adapter->FindAdapters(devices, MAX_CEC_DEVICES, NULL);
00080 if (num_devices < 1)
00081 return results;
00082 for (uint8_t i = 0; i < num_devices; i++)
00083 results << QString::fromAscii(devices[i].comm);
00084 UnloadLibCec(adapter);
00085 return results;
00086 }
00087
00088 bool Open(void)
00089 {
00090
00091
00092 defaultDevice = gCoreContext->GetSetting(LIBCEC_DEVICE, "auto").trimmed();
00093 QString hdmi_port = gCoreContext->GetSetting(LIBCEC_PORT, "auto");
00094 QString device_id = gCoreContext->GetSetting(LIBCEC_DEVICEID, "auto");
00095 powerOffTVAllowed = (bool)gCoreContext->GetNumSetting(POWEROFFTV_ALLOWED, 1);
00096 powerOffTVOnExit = (bool)gCoreContext->GetNumSetting(POWEROFFTV_ONEXIT, 1);
00097 powerOnTVAllowed = (bool)gCoreContext->GetNumSetting(POWERONTV_ALLOWED, 1);
00098 powerOnTVOnStart = (bool)gCoreContext->GetNumSetting(POWERONTV_ONSTART, 1);
00099
00100 defaultHDMIPort = 1;
00101 if ("auto" != hdmi_port)
00102 {
00103 defaultHDMIPort = hdmi_port.toInt();
00104 if (defaultHDMIPort < 1 || defaultHDMIPort > 3)
00105 defaultHDMIPort = 1;
00106 }
00107 defaultHDMIPort = defaultHDMIPort << 12;
00108
00109 defaultDeviceID = CECDEVICE_PLAYBACKDEVICE1;
00110 if ("auto" != device_id)
00111 {
00112 int id = device_id.toInt();
00113 if (id < 1 || id > 3)
00114 id = 1;
00115 defaultDeviceID = (id == 1) ? CECDEVICE_PLAYBACKDEVICE1 :
00116 ((id == 2) ? CECDEVICE_PLAYBACKDEVICE2 :
00117 CECDEVICE_PLAYBACKDEVICE3);
00118 }
00119
00120
00121 cec_device_type_list list;
00122 list.Clear();
00123 list.Add(CEC_DEVICE_TYPE_PLAYBACK_DEVICE);
00124 adapter = LibCecInit("MythTV", list);
00125
00126 if (!adapter)
00127 {
00128 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to load libcec.");
00129 return false;
00130 }
00131
00132 if (adapter->GetMinLibVersion() > MIN_LIBCEC_VERSION)
00133 {
00134 LOG(VB_GENERAL, LOG_ERR, LOC +
00135 QString("The installed libCEC supports version %1 and above. "
00136 "This version of MythTV only supports version %2.")
00137 .arg(adapter->GetMinLibVersion()).arg(MIN_LIBCEC_VERSION));
00138 return false;
00139 }
00140
00141
00142 cec_adapter *devices = new cec_adapter[MAX_CEC_DEVICES];
00143 uint8_t num_devices = adapter->FindAdapters(devices, MAX_CEC_DEVICES, NULL);
00144 if (num_devices < 1)
00145 {
00146 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to find any CEC devices.");
00147 return false;
00148 }
00149
00150
00151 int devicenum = 0;
00152 bool find = defaultDevice != "auto";
00153
00154 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Found %1 CEC devices(s).")
00155 .arg(num_devices));
00156 for (uint8_t i = 0; i < num_devices; i++)
00157 {
00158 QString comm = QString::fromAscii(devices[i].comm);
00159 bool match = find ? (comm == defaultDevice) : (i == 0);
00160 devicenum = match ? i : devicenum;
00161 LOG(VB_GENERAL, LOG_INFO, LOC +
00162 QString("Device %1: path '%2' com port '%3' %4").arg(i + 1)
00163 .arg(QString::fromAscii(devices[i].path)).arg(comm)
00164 .arg(match ? "SELECTED" : ""));
00165 }
00166
00167
00168 QString path = QString::fromAscii(devices[devicenum].path);
00169 QString comm = QString::fromAscii(devices[devicenum].comm);
00170 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Trying to open device %1 (%2).")
00171 .arg(path).arg(comm));
00172
00173 if (!adapter->Open(devices[devicenum].comm))
00174 {
00175 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to open device.");
00176 return false;
00177 }
00178
00179 LOG(VB_GENERAL, LOG_INFO, LOC + "Opened CEC device.");
00180
00181
00182 powerOnTV = powerOnTVOnStart;
00183 HandleActions();
00184
00185
00186 adapter->GetDeviceVendorId(CECDEVICE_TV);
00187
00188
00189 adapter->SetPhysicalAddress(defaultHDMIPort);
00190
00191
00192 adapter->SetLogicalAddress(defaultDeviceID);
00193
00194
00195 switchInput = true;
00196 HandleActions();
00197
00198 valid = true;
00199 return true;
00200 }
00201
00202
00203 void Close(void)
00204 {
00205 if (adapter)
00206 {
00207
00208 powerOffTV = powerOffTVOnExit;
00209 HandleActions();
00210
00211
00212 adapter->Close();
00213 LogMessages();
00214 UnloadLibCec(adapter);
00215
00216 LOG(VB_GENERAL, LOG_INFO, LOC + "Closing down CEC.");
00217 }
00218 valid = false;
00219 adapter = NULL;
00220 }
00221
00222 void LogMessages(void)
00223 {
00224 if (!adapter || !valid)
00225 return;
00226
00227 cec_log_message message;
00228 while (adapter->GetNextLogMessage(&message))
00229 {
00230 QString msg(message.message);
00231 int lvl = LOG_UNKNOWN;
00232 switch (message.level)
00233 {
00234 case CEC_LOG_ERROR: lvl = LOG_ERR; break;
00235 case CEC_LOG_WARNING: lvl = LOG_WARNING; break;
00236 case CEC_LOG_NOTICE: lvl = LOG_INFO; break;
00237 case CEC_LOG_DEBUG: lvl = LOG_DEBUG; break;
00238 }
00239 LOG(VB_GENERAL, lvl, LOC + QString("%1").arg(msg));
00240 }
00241 }
00242
00243 void HandleCommands(void)
00244 {
00245 if (!adapter || !valid)
00246 return;
00247
00248 LogMessages();
00249
00250 cec_command command;
00251 while (adapter->GetNextCommand(&command))
00252 {
00253 LOG(VB_GENERAL, LOG_DEBUG, LOC +
00254 QString("Command %1 from '%2' (%3) - destination '%4' (%5)")
00255 .arg(command.opcode)
00256 .arg(addressToString(command.initiator, true))
00257 .arg(command.initiator)
00258 .arg(addressToString(command.destination, false))
00259 .arg(command.destination));
00260
00261 switch (command.opcode)
00262 {
00263
00264 default:
00265 break;
00266 }
00267 }
00268
00269 LogMessages();
00270 }
00271
00272 void HandleKeyPresses(void)
00273 {
00274 if (!adapter || !valid)
00275 return;
00276
00277 cec_keypress key;
00278 if (!adapter->GetNextKeypress(&key))
00279 return;
00280
00281
00282 if (key.duration < 1)
00283 return;
00284
00285 QString code;
00286 int action = 0;
00287 switch (key.keycode)
00288 {
00289 case CEC_USER_CONTROL_CODE_NUMBER0:
00290 action = Qt::Key_0;
00291 code = "0";
00292 break;
00293 case CEC_USER_CONTROL_CODE_NUMBER1:
00294 action = Qt::Key_1;
00295 code = "1";
00296 break;
00297 case CEC_USER_CONTROL_CODE_NUMBER2:
00298 action = Qt::Key_2;
00299 code = "2";
00300 break;
00301 case CEC_USER_CONTROL_CODE_NUMBER3:
00302 action = Qt::Key_3;
00303 code = "3";
00304 break;
00305 case CEC_USER_CONTROL_CODE_NUMBER4:
00306 action = Qt::Key_4;
00307 code = "4";
00308 break;
00309 case CEC_USER_CONTROL_CODE_NUMBER5:
00310 action = Qt::Key_5;
00311 code = "5";
00312 break;
00313 case CEC_USER_CONTROL_CODE_NUMBER6:
00314 action = Qt::Key_6;
00315 code = "6";
00316 break;
00317 case CEC_USER_CONTROL_CODE_NUMBER7:
00318 action = Qt::Key_7;
00319 code = "7";
00320 break;
00321 case CEC_USER_CONTROL_CODE_NUMBER8:
00322 action = Qt::Key_8;
00323 code = "8";
00324 break;
00325 case CEC_USER_CONTROL_CODE_NUMBER9:
00326 action = Qt::Key_9;
00327 code = "9";
00328 break;
00329 case CEC_USER_CONTROL_CODE_SELECT:
00330 action = Qt::Key_Select;
00331 code = "SELECT";
00332 break;
00333 case CEC_USER_CONTROL_CODE_ENTER:
00334 action = Qt::Key_Enter;
00335 code = "ENTER";
00336 break;
00337 case CEC_USER_CONTROL_CODE_UP:
00338 action = Qt::Key_Up;
00339 code = "UP";
00340 break;
00341 case CEC_USER_CONTROL_CODE_DOWN:
00342 action = Qt::Key_Down;
00343 code = "DOWN";
00344 break;
00345 case CEC_USER_CONTROL_CODE_LEFT:
00346 action = Qt::Key_Left;
00347 code = "LEFT";
00348 break;
00349 case CEC_USER_CONTROL_CODE_LEFT_UP:
00350 action = Qt::Key_Left;
00351 code = "LEFT_UP";
00352 break;
00353 case CEC_USER_CONTROL_CODE_LEFT_DOWN:
00354 action = Qt::Key_Left;
00355 code = "LEFT_DOWN";
00356 break;
00357 case CEC_USER_CONTROL_CODE_RIGHT:
00358 action = Qt::Key_Right;
00359 code = "RIGHT";
00360 break;
00361 case CEC_USER_CONTROL_CODE_RIGHT_UP:
00362 action = Qt::Key_Right;
00363 code = "RIGHT_UP";
00364 break;
00365 case CEC_USER_CONTROL_CODE_RIGHT_DOWN:
00366 action = Qt::Key_Right;
00367 code = "RIGHT_DOWN";
00368 break;
00369 case CEC_USER_CONTROL_CODE_ROOT_MENU:
00370 action = Qt::Key_M;
00371 code = "ROOT_MENU";
00372 break;
00373 case CEC_USER_CONTROL_CODE_EXIT:
00374 action = Qt::Key_Escape;
00375 code = "EXIT";
00376 break;
00377 case CEC_USER_CONTROL_CODE_PREVIOUS_CHANNEL:
00378 action = Qt::Key_H;
00379 code = "PREVIOUS_CHANNEL";
00380 break;
00381 case CEC_USER_CONTROL_CODE_SOUND_SELECT:
00382 action = Qt::Key_Plus;
00383 code = "SOUND_SELECT";
00384 break;
00385 case CEC_USER_CONTROL_CODE_VOLUME_UP:
00386 action = Qt::Key_VolumeUp;
00387 code = "VOLUME_UP";
00388 break;
00389 case CEC_USER_CONTROL_CODE_VOLUME_DOWN:
00390 action = Qt::Key_VolumeDown;
00391 code = "VOLUME_DOWN";
00392 break;
00393 case CEC_USER_CONTROL_CODE_MUTE:
00394 action = Qt::Key_VolumeMute;
00395 code = "MUTE";
00396 break;
00397 case CEC_USER_CONTROL_CODE_PLAY:
00398 action = Qt::Key_P;
00399 code = "PLAY";
00400 break;
00401 case CEC_USER_CONTROL_CODE_PAUSE:
00402 action = Qt::Key_P;
00403 code = "PAUSE";
00404 break;
00405 case CEC_USER_CONTROL_CODE_STOP:
00406 action = Qt::Key_Stop;
00407 code = "STOP";
00408 break;
00409 case CEC_USER_CONTROL_CODE_RECORD:
00410 action = Qt::Key_R;
00411 code = "RECORD";
00412 break;
00413 case CEC_USER_CONTROL_CODE_CLEAR:
00414 action = Qt::Key_Clear;
00415 code = "CLEAR";
00416 break;
00417 case CEC_USER_CONTROL_CODE_DISPLAY_INFORMATION:
00418 action = Qt::Key_I;
00419 code = "DISPLAY_INFORMATION";
00420 break;
00421 case CEC_USER_CONTROL_CODE_PAGE_UP:
00422 action = Qt::Key_PageUp;
00423 code = "PAGE_UP";
00424 break;
00425 case CEC_USER_CONTROL_CODE_PAGE_DOWN:
00426 action = Qt::Key_PageDown;
00427 code = "PAGE_DOWN";
00428 break;
00429 case CEC_USER_CONTROL_CODE_EJECT:
00430 action = Qt::Key_Eject;
00431 code = "EJECT";
00432 break;
00433 case CEC_USER_CONTROL_CODE_FORWARD:
00434 action = Qt::Key_Forward;
00435 code = "FORWARD";
00436 break;
00437 case CEC_USER_CONTROL_CODE_BACKWARD:
00438 action = Qt::Key_Back;
00439 code = "BACKWARD";
00440 break;
00441 case CEC_USER_CONTROL_CODE_F1_BLUE:
00442 action = Qt::Key_F5;
00443 code = "F1_BLUE";
00444 break;
00445 case CEC_USER_CONTROL_CODE_F2_RED:
00446 action = Qt::Key_F2;
00447 code = "F2_RED";
00448 break;
00449 case CEC_USER_CONTROL_CODE_F3_GREEN:
00450 action = Qt::Key_F3;
00451 code = "F3_GREEN";
00452 break;
00453 case CEC_USER_CONTROL_CODE_F4_YELLOW:
00454 action = Qt::Key_F4;
00455 code = "F4_YELLOW";
00456 break;
00457 case CEC_USER_CONTROL_CODE_SETUP_MENU:
00458 action = Qt::Key_M;
00459 code = "SETUP_MENU";
00460 break;
00461 case CEC_USER_CONTROL_CODE_CONTENTS_MENU:
00462 action = Qt::Key_M;
00463 code = "CONTENTS_MENU";
00464 break;
00465 case CEC_USER_CONTROL_CODE_FAVORITE_MENU:
00466 action = Qt::Key_M;
00467 code = "FAVORITE_MENU";
00468 break;
00469 case CEC_USER_CONTROL_CODE_DOT:
00470 action = Qt::Key_Period;
00471 code = "DOT";
00472 break;
00473 case CEC_USER_CONTROL_CODE_NEXT_FAVORITE:
00474 action = Qt::Key_Slash;
00475 code = "NEXT_FAVORITE";
00476 break;
00477 case CEC_USER_CONTROL_CODE_INPUT_SELECT:
00478 action = Qt::Key_C;
00479 code = "INPUT_SELECT";
00480 break;
00481 case CEC_USER_CONTROL_CODE_HELP:
00482 action = Qt::Key_F1;
00483 code = "HELP";
00484 break;
00485 case CEC_USER_CONTROL_CODE_STOP_RECORD:
00486 action = Qt::Key_R;
00487 code = "STOP_RECORD";
00488 break;
00489 case CEC_USER_CONTROL_CODE_SUB_PICTURE:
00490 action = Qt::Key_V;
00491 code = "SUB_PICTURE";
00492 break;
00493 case CEC_USER_CONTROL_CODE_ELECTRONIC_PROGRAM_GUIDE:
00494 action = Qt::Key_S;
00495 code = "ELECTRONIC_PROGRAM_GUIDE";
00496 break;
00497 case CEC_USER_CONTROL_CODE_POWER:
00498 action = Qt::Key_PowerOff;
00499 code = "POWER";
00500 break;
00501
00502
00503
00504 case CEC_USER_CONTROL_CODE_CHANNEL_DOWN:
00505 action = Qt::Key_F20;
00506 code = "CHANNEL_DOWN";
00507 break;
00508 case CEC_USER_CONTROL_CODE_CHANNEL_UP:
00509 action = Qt::Key_F21;
00510 code = "CHANNEL_UP";
00511 break;
00512 case CEC_USER_CONTROL_CODE_REWIND:
00513 action = Qt::Key_F22;
00514 code = "REWIND";
00515 break;
00516 case CEC_USER_CONTROL_CODE_FAST_FORWARD:
00517 action = Qt::Key_F23;
00518 code = "FAST_FORWARD";
00519 break;
00520 case CEC_USER_CONTROL_CODE_ANGLE:
00521 action = Qt::Key_F24;
00522 code = "ANGLE";
00523 break;
00524 case CEC_USER_CONTROL_CODE_F5:
00525 action = Qt::Key_F6;
00526 code = "F5";
00527 break;
00528
00529
00530 case CEC_USER_CONTROL_CODE_INITIAL_CONFIGURATION:
00531 code = "INITIAL_CONFIGURATION";
00532 break;
00533 case CEC_USER_CONTROL_CODE_PAUSE_RECORD:
00534 code = "PAUSE_RECORD";
00535 break;
00536 case CEC_USER_CONTROL_CODE_VIDEO_ON_DEMAND:
00537 code = "VIDEO_ON_DEMAND";
00538 break;
00539 case CEC_USER_CONTROL_CODE_TIMER_PROGRAMMING:
00540 code = "TIMER_PROGRAMMING";
00541 break;
00542 case CEC_USER_CONTROL_CODE_UNKNOWN:
00543 code = "UNKOWN";
00544 break;
00545 case CEC_USER_CONTROL_CODE_DATA:
00546 code = "DATA";
00547 break;
00548
00549
00550 case CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION:
00551 code = "POWER_ON_FUNCTION";
00552 break;
00553 case CEC_USER_CONTROL_CODE_PLAY_FUNCTION:
00554 code = "PLAY_FUNCTION";
00555 break;
00556 case CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION:
00557 code = "PAUSE_PLAY_FUNCTION";
00558 break;
00559 case CEC_USER_CONTROL_CODE_RECORD_FUNCTION:
00560 code = "RECORD_FUNCTION";
00561 break;
00562 case CEC_USER_CONTROL_CODE_PAUSE_RECORD_FUNCTION:
00563 code = "PAUSE_RECORD_FUNCTION";
00564 break;
00565 case CEC_USER_CONTROL_CODE_STOP_FUNCTION:
00566 code = "STOP_FUNCTION";
00567 break;
00568 case CEC_USER_CONTROL_CODE_MUTE_FUNCTION:
00569 code = "MUTE_FUNCTION";
00570 break;
00571 case CEC_USER_CONTROL_CODE_RESTORE_VOLUME_FUNCTION:
00572 code = "RESTORE_VOLUME_FUNCTION";
00573 break;
00574 case CEC_USER_CONTROL_CODE_TUNE_FUNCTION:
00575 code = "TUNE_FUNCTION";
00576 break;
00577 case CEC_USER_CONTROL_CODE_SELECT_MEDIA_FUNCTION:
00578 code = "SELECT_MEDIA_FUNCTION";
00579 break;
00580 case CEC_USER_CONTROL_CODE_SELECT_AV_INPUT_FUNCTION:
00581 code = "SELECT_AV_INPUT_FUNCTION";
00582 break;
00583 case CEC_USER_CONTROL_CODE_SELECT_AUDIO_INPUT_FUNCTION:
00584 code = "SELECT_AUDIO_INPUT_FUNCTION";
00585 break;
00586 case CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION:
00587 code = "POWER_TOGGLE_FUNCTION";
00588 break;
00589 case CEC_USER_CONTROL_CODE_POWER_OFF_FUNCTION:
00590 code = "POWER_OFF_FUNCTION";
00591 break;
00592 }
00593
00594 LOG(VB_GENERAL, LOG_DEBUG, LOC + QString("Keypress %1 %2")
00595 .arg(code).arg(0 == action ? "(Not actioned)" : ""));
00596
00597 if (0 == action)
00598 return;
00599
00600 GetMythUI()->ResetScreensaver();
00601 QKeyEvent* ke = new QKeyEvent(QEvent::KeyPress, action, Qt::NoModifier);
00602 qApp->postEvent(GetMythMainWindow(), (QEvent*)ke);
00603
00604 LogMessages();
00605 }
00606
00607 void HandleActions(void)
00608 {
00609 if (!adapter || !valid)
00610 return;
00611
00612
00613 if (powerOffTV && powerOffTVAllowed)
00614 {
00615 if (adapter->StandbyDevices(CECDEVICE_TV))
00616 LOG(VB_GENERAL, LOG_INFO, LOC + "Asked TV to turn off.");
00617 else
00618 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to turn TV off.");
00619 }
00620
00621 if (powerOnTV && powerOnTVAllowed)
00622 {
00623 if (adapter->PowerOnDevices(CECDEVICE_TV))
00624 LOG(VB_GENERAL, LOG_INFO, LOC + "Asked TV to turn on.");
00625 else
00626 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to turn TV on.");
00627 }
00628
00629
00630 if (switchInput && switchInputAllowed)
00631 {
00632 if (adapter->SetActiveView())
00633 LOG(VB_GENERAL, LOG_INFO, LOC + "Asked TV to switch to this input.");
00634 else
00635 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to switch to this input.");
00636 }
00637
00638 powerOffTV = false;
00639 powerOnTV = false;
00640 switchInput = false;
00641
00642 LogMessages();
00643 }
00644
00645 ICECAdapter *adapter;
00646 QString defaultDevice;
00647 int defaultHDMIPort;
00648 cec_logical_address defaultDeviceID;
00649 QTimer *timer;
00650 bool valid;
00651 bool powerOffTV;
00652 bool powerOffTVAllowed;
00653 bool powerOffTVOnExit;
00654 bool powerOnTV;
00655 bool powerOnTVAllowed;
00656 bool powerOnTVOnStart;
00657 bool switchInput;
00658 bool switchInputAllowed;
00659 };
00660
00661 QStringList CECAdapter::GetDeviceList(void)
00662 {
00663 QMutexLocker lock(gLock);
00664 return CECAdapterPriv::GetDeviceList();
00665 }
00666
00667 CECAdapter::CECAdapter() : MThread("CECAdapter"), m_priv(new CECAdapterPriv)
00668 {
00669 QMutexLocker lock(gLock);
00670
00671
00672 if (!gCoreContext->GetNumSetting(LIBCEC_ENABLED, 1))
00673 {
00674 LOG(VB_GENERAL, LOG_INFO, LOC + "libCEC support is disabled.");
00675 return;
00676 }
00677
00678
00679 if (!m_priv->Open())
00680 return;
00681
00682
00683 m_priv->timer = new QTimer(this);
00684 QObject::connect(m_priv->timer, SIGNAL(timeout()), this, SLOT(Process()));
00685 m_priv->timer->start(10);
00686
00687
00688 LOG(VB_GENERAL, LOG_DEBUG, LOC + "Starting thread.");
00689 start();
00690 }
00691
00692 CECAdapter::~CECAdapter()
00693 {
00694 QMutexLocker lock(gLock);
00695
00696
00697 if (m_priv->timer)
00698 m_priv->timer->stop();
00699 delete m_priv->timer;
00700 m_priv->timer = NULL;
00701
00702
00703 if (isRunning())
00704 {
00705 LOG(VB_GENERAL, LOG_DEBUG, LOC + "Stopping thread.");
00706 exit();
00707 }
00708
00709
00710 m_priv->Close();
00711 }
00712
00713 bool CECAdapter::IsValid(void)
00714 {
00715 QMutexLocker lock(gLock);
00716 return m_priv->valid;
00717 }
00718
00719 void CECAdapter::Action(const QString &action)
00720 {
00721 QMutexLocker lock(gLock);
00722 if (ACTION_TVPOWERON == action)
00723 m_priv->powerOnTV = true;
00724 else if (ACTION_TVPOWEROFF == action)
00725 m_priv->powerOffTV = true;
00726 }
00727
00728 void CECAdapter::Process(void)
00729 {
00730 gLock->lock();
00731 m_priv->HandleCommands();
00732 m_priv->HandleKeyPresses();
00733 m_priv->HandleActions();
00734 gLock->unlock();
00735 }