diff --git a/data/locale/deutsch.locale b/data/locale/deutsch.locale index 90d22c5cf..777663926 100644 --- a/data/locale/deutsch.locale +++ b/data/locale/deutsch.locale @@ -1300,9 +1300,11 @@ menu.hint_buildinfo Informationen über Compiler, Compilerflags, Kernel menu.hint_ca_init Konfiguration der CA-Systemhardware, CA-Modul und Kartenschächte menu.hint_cache_txt Startet das Zwischenspeichern des Videotextes nach einem Kanalwechsel menu.hint_cec_mode CEC-Modus +menu.hint_cec_sleep CEC-Standby bei HDMI Eingangswechsel menu.hint_cec_standby CEC-Standby menu.hint_cec_view_on CEC view ON -menu.hint_cec_volume Beim Betätigen der Lautstärketasten wird die Lautstärke an angeschlossenen Audiogerät reguliert +menu.hint_cec_volume Beim Betätigen der Lautstärketasten wird die Lautstärke am angeschlossenen Audiogerät reguliert +menu.hint_cec_wakeup CEC-Aufwachen bei HDMI Eingangswechsel menu.hint_channellist_additional Definiert, ob zusätzliche Informationen im Hauptfenster angezeigt werden sollen menu.hint_channellist_enablesdt Ermöglicht die dynamische Senderaktualisierung im laufenden Betrieb menu.hint_channellist_epg_align Legen Sie fest, wie der Text für das EPG in der Liste rechts vom Programmnamen ausgerichtet wird @@ -2866,6 +2868,7 @@ videomenu.hdmi_cec_mode Receiver verwenden videomenu.hdmi_cec_mode_off nein videomenu.hdmi_cec_mode_recorder als Sat/Kabel PVR videomenu.hdmi_cec_mode_tuner als Sat/Kabel STB +videomenu.hdmi_cec_sleep Box in Standby bei HDMI Eingangswechsel videomenu.hdmi_cec_standby Aktiviere CEC Standby videomenu.hdmi_cec_view_on Aktiviere CEC View on videomenu.hdmi_cec_vol_audiosystem Audiosystem diff --git a/src/driver/Makefile.am b/src/driver/Makefile.am index 72a1c19bf..a1dee03cc 100644 --- a/src/driver/Makefile.am +++ b/src/driver/Makefile.am @@ -118,15 +118,21 @@ endif if BOXTYPE_ARMBOX if ENABLE_LCD libneutrino_driver_a_SOURCES += \ + hdmi_cec.cpp \ + fb_accel_arm.cpp \ lcdd.cpp else libneutrino_driver_a_SOURCES += \ + hdmi_cec.cpp \ + fb_accel_arm.cpp \ simple_display.cpp endif endif if BOXTYPE_MIPSBOX libneutrino_driver_a_SOURCES += \ + hdmi_cec.cpp \ + fb_accel_mips.cpp \ simple_display.cpp endif # end display drivers diff --git a/src/driver/hdmi_cec.cpp b/src/driver/hdmi_cec.cpp new file mode 100644 index 000000000..7870f3c77 --- /dev/null +++ b/src/driver/hdmi_cec.cpp @@ -0,0 +1,844 @@ +/* + Copyright (C) 2018-2022 TangoCash + + License: GPLv2 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "hdmi_cec.h" +#include "hdmi_cec_types.h" + +#include +#include +#include + +#define RED "\x1B[31m" +#define GREEN "\x1B[32m" +#define YELLOW "\x1B[33m" +#define BLUE "\x1b[34m" +#define MAGENTA "\x1b[35m" +#define CYAN "\x1b[36m" +#define WHITE "\x1b[37m" +#define NORMAL "\x1B[0m" + +#define EPOLL_WAIT_TIMEOUT (1000) +#define EPOLL_MAX_EVENTS (1) + +#define CEC_HDMIDEV "/dev/hdmi_cec" +#if BOXMODEL_H7 || BOXMODEL_H9COMBO || BOXMODEL_H9 +#define RC_DEVICE "/dev/input/event2" +#elif BOXMODEL_OSMIO4K || BOXMODEL_OSMIO4KPLUS +#define RC_DEVICE "/dev/input/event0" +#else +#define RC_DEVICE "/dev/input/event1" +#endif + +hdmi_cec::hdmi_cec() +{ + standby_cec_activ = autoview_cec_activ = muted = false; + hdmiFd = -1; + volume = 0; + tv_off = true; + deviceType = CECDEVICE_UNREGISTERED; + audio_destination = CECDEVICE_AUDIOSYSTEM; + strcpy(osdname, "neutrino"); + running = false; + active_source = false; +} + +hdmi_cec::~hdmi_cec() +{ + if (standby_cec_activ && hdmiFd >= 0) + SetCECState(true); + + Stop(); + + if (hdmiFd >= 0) + { + close(hdmiFd); + hdmiFd = -1; + } +} + +bool hdmi_cec::SetCECMode(VIDEO_HDMI_CEC_MODE cecOnOff) +{ + physicalAddress[0] = 0x10; + physicalAddress[1] = 0x00; + logicalAddress = 1; + + if (cecOnOff == VIDEO_HDMI_CEC_MODE_OFF) + { + Stop(); + dprintf(DEBUG_NORMAL, GREEN"[CEC] switch off %s\n"NORMAL, __func__); + return false; + } + + dprintf(DEBUG_NORMAL, GREEN"[CEC] switch on %s\n"NORMAL, __func__); + + if (hdmiFd == -1) + { + hdmiFd = ::open(CEC_HDMIDEV, O_RDWR | O_NONBLOCK | O_CLOEXEC); + + if (hdmiFd >= 0) + { + ::ioctl(hdmiFd, 0); /* flush old messages */ + } + } + + if (hdmiFd >= 0) + { + GetCECAddressInfo(); + + if (autoview_cec_activ) + SetCECState(false); + + return Start(); + } + + return false; +} + +void hdmi_cec::GetCECAddressInfo() +{ + if (hdmiFd >= 0) + { + struct addressinfo addressinfo; + + if (::ioctl(hdmiFd, 1, &addressinfo) >= 0) + { + deviceType = addressinfo.type; + logicalAddress = addressinfo.logical; + dprintf(DEBUG_NORMAL, GREEN"[CEC] %s: detected physical address: 0x%02X:0x%02X (Type: 0x%02X/Logical: 0x%02X)\n"NORMAL, __func__, physicalAddress[0], physicalAddress[1], deviceType, logicalAddress); + + if (memcmp(physicalAddress, addressinfo.physical, sizeof(physicalAddress))) + { + dprintf(DEBUG_NORMAL, YELLOW"[CEC] %s: detected physical address change: 0x%02X:0x%02X --> 0x%02X:0x%02X\n"NORMAL, __func__, physicalAddress[0], physicalAddress[1], addressinfo.physical[0], addressinfo.physical[1]); + memcpy(physicalAddress, addressinfo.physical, sizeof(physicalAddress)); + ReportPhysicalAddress(); + } + } + } +} + +void hdmi_cec::ReportPhysicalAddress() +{ + struct cec_message txmessage; + txmessage.initiator = logicalAddress; + txmessage.destination = CECDEVICE_BROADCAST; + txmessage.data[0] = CEC_OPCODE_REPORT_PHYSICAL_ADDRESS; + txmessage.data[1] = physicalAddress[0]; + txmessage.data[2] = physicalAddress[1]; + txmessage.data[3] = deviceType; + txmessage.length = 4; + SendCECMessage(txmessage); +} + +void hdmi_cec::SendCECMessage(struct cec_message &txmessage, int sleeptime) +{ + char str[txmessage.length * 6]; + + for (int i = 0; i < txmessage.length; i++) + { + sprintf(str + (i * 6), "[0x%02X]", txmessage.data[i]); + } + + dprintf(DEBUG_NORMAL, YELLOW"[CEC] send message %s to %s (0x%02X>>0x%02X) '%s' (%s)\n"NORMAL, ToString((cec_logical_address)txmessage.initiator), txmessage.destination == 0xf ? "all" : ToString((cec_logical_address)txmessage.destination), txmessage.initiator, txmessage.destination, ToString((cec_opcode)txmessage.data[0]), str); + struct cec_message_fb message; + message.address = txmessage.destination; + message.length = txmessage.length; + memcpy(&message.data, txmessage.data, txmessage.length); + mutex.lock(); + msg_que.push_back(message); + mutex.unlock(); +} + +void hdmi_cec::SetCECAutoStandby(bool state) +{ + standby_cec_activ = state; +} + +void hdmi_cec::SetCECAutoView(bool state) +{ + autoview_cec_activ = state; +} + +void hdmi_cec::SetCECState(bool state) +{ + if ((standby_cec_activ) && state) + { + SendStandBy(); + } + + if ((autoview_cec_activ) && !state) + { + RequestTVPowerStatus(); + SendViewOn(); + active_source = true; + SendAnnounce(); + } +} + +void hdmi_cec::SendStandBy() +{ + struct cec_message message; + message.initiator = logicalAddress; + message.destination = CECDEVICE_BROADCAST; + message.data[0] = CEC_OPCODE_STANDBY; + message.length = 1; + SendCECMessage(message); + message.initiator = logicalAddress; + message.destination = CECDEVICE_TV; + message.data[0] = CEC_OPCODE_GIVE_DEVICE_POWER_STATUS; + message.length = 1; + SendCECMessage(message); +} + +void hdmi_cec::SendViewOn() +{ + struct cec_message message; + message.initiator = logicalAddress; + message.destination = CECDEVICE_TV; + message.data[0] = CEC_OPCODE_IMAGE_VIEW_ON; + message.length = 1; + SendCECMessage(message); + message.initiator = logicalAddress; + message.destination = CECDEVICE_TV; + message.data[0] = CEC_OPCODE_GIVE_DEVICE_POWER_STATUS; + message.length = 1; + SendCECMessage(message); +} + +void hdmi_cec::SendAnnounce() +{ + GetCECAddressInfo(); + struct cec_message message; + message.initiator = logicalAddress; + message.destination = CECDEVICE_TV; + message.data[0] = CEC_OPCODE_GET_CEC_VERSION; + message.length = 1; + SendCECMessage(message); + SendActiveSource(); + message.initiator = logicalAddress; + message.destination = CECDEVICE_BROADCAST; + message.data[0] = CEC_OPCODE_SET_OSD_NAME; + memcpy(message.data + 1, osdname, strlen(osdname)); + message.length = strlen(osdname) + 1; + SendCECMessage(message); + message.initiator = logicalAddress; + message.destination = CECDEVICE_TV; + message.data[0] = CEC_OPCODE_GIVE_OSD_NAME; + message.length = 1; + SendCECMessage(message); + request_audio_status(); +} + +void hdmi_cec::SendActiveSource() +{ + struct cec_message message; + message.destination = CECDEVICE_BROADCAST; + message.initiator = logicalAddress; + message.data[0] = CEC_OPCODE_ACTIVE_SOURCE; + message.data[1] = physicalAddress[0]; + message.data[2] = physicalAddress[1]; + message.length = 3; + + if (CNeutrinoApp::getInstance()->getMode() != NeutrinoModes::mode_standby && active_source) + SendCECMessage(message); +} + +void hdmi_cec::RequestTVPowerStatus() +{ + struct cec_message message; + message.initiator = logicalAddress; + message.destination = CECDEVICE_TV; + message.data[0] = CEC_OPCODE_GIVE_DEVICE_POWER_STATUS; + message.length = 1; + SendCECMessage(message); +} + +long hdmi_cec::translateKey(unsigned char code) +{ + long key = 0; + + switch (code) + { + case CEC_USER_CONTROL_CODE_PREVIOUS_CHANNEL: + key = KEY_MENU; + break; + + case CEC_USER_CONTROL_CODE_NUMBER0: + key = KEY_0; + break; + + case CEC_USER_CONTROL_CODE_NUMBER1: + key = KEY_1; + break; + + case CEC_USER_CONTROL_CODE_NUMBER2: + key = KEY_2; + break; + + case CEC_USER_CONTROL_CODE_NUMBER3: + key = KEY_3; + break; + + case CEC_USER_CONTROL_CODE_NUMBER4: + key = KEY_4; + break; + + case CEC_USER_CONTROL_CODE_NUMBER5: + key = KEY_5; + break; + + case CEC_USER_CONTROL_CODE_NUMBER6: + key = KEY_6; + break; + + case CEC_USER_CONTROL_CODE_NUMBER7: + key = KEY_7; + break; + + case CEC_USER_CONTROL_CODE_NUMBER8: + key = KEY_8; + break; + + case CEC_USER_CONTROL_CODE_NUMBER9: + key = KEY_9; + break; + + case CEC_USER_CONTROL_CODE_CHANNEL_UP: + key = KEY_CHANNELUP; + break; + + case CEC_USER_CONTROL_CODE_CHANNEL_DOWN: + key = KEY_CHANNELDOWN; + break; +#if BOXMODEL_HD51 || BOXMODEL_MULTIBOX || BOXMODEL_MULTIBOXSE || BOXMODEL_HD60 || BOXMODEL_HD61 || BOXMODEL_BRE2ZE4K || BOXMODEL_H7 || BOXMODEL_OSMIO4K || BOXMODEL_OSMIO4KPLUS || BOXMODEL_SF8008 || BOXMODEL_SF8008M || BOXMODEL_USTYM4KPRO || BOXMODEL_H9COMBO || BOXMODEL_H9 + + case CEC_USER_CONTROL_CODE_PLAY: + case CEC_USER_CONTROL_CODE_PAUSE: + key = KEY_PLAYPAUSE; + break; +#elif BOXMODEL_VUPLUS_ALL + + case CEC_USER_CONTROL_CODE_PLAY: + key = KEY_PLAY; + break; + + case CEC_USER_CONTROL_CODE_PAUSE: + key = KEY_PLAYPAUSE; + break; +#else + + case CEC_USER_CONTROL_CODE_PLAY: + key = KEY_PLAY; + break; + + case CEC_USER_CONTROL_CODE_PAUSE: + key = KEY_PAUSE; + break; +#endif + + case CEC_USER_CONTROL_CODE_STOP: + key = KEY_STOP; + break; + + case CEC_USER_CONTROL_CODE_RECORD: + key = KEY_RECORD; + break; + + case CEC_USER_CONTROL_CODE_REWIND: + key = KEY_REWIND; + break; + + case CEC_USER_CONTROL_CODE_FAST_FORWARD: + key = KEY_FASTFORWARD; + break; + + case CEC_USER_CONTROL_CODE_ELECTRONIC_PROGRAM_GUIDE: + key = KEY_INFO; + break; + + case CEC_USER_CONTROL_CODE_TIMER_PROGRAMMING: + key = KEY_PROGRAM; + break; + + case CEC_USER_CONTROL_CODE_PLAY_FUNCTION: + key = KEY_PLAY; + break; + + case CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION: + key = KEY_PLAYPAUSE; + break; + + case CEC_USER_CONTROL_CODE_RECORD_FUNCTION: + key = KEY_RECORD; + break; + + case CEC_USER_CONTROL_CODE_STOP_FUNCTION: + key = KEY_STOP; + break; + + case CEC_USER_CONTROL_CODE_SELECT: + key = KEY_OK; + break; + + case CEC_USER_CONTROL_CODE_LEFT: + key = KEY_LEFT; + break; + + case CEC_USER_CONTROL_CODE_RIGHT: + key = KEY_RIGHT; + break; + + case CEC_USER_CONTROL_CODE_UP: + key = KEY_UP; + break; + + case CEC_USER_CONTROL_CODE_DOWN: + key = KEY_DOWN; + break; + + case CEC_USER_CONTROL_CODE_EXIT: + key = KEY_EXIT; + break; + + case CEC_USER_CONTROL_CODE_F2_RED: + key = KEY_RED; + break; + + case CEC_USER_CONTROL_CODE_F3_GREEN: + key = KEY_GREEN; + break; + + case CEC_USER_CONTROL_CODE_F4_YELLOW: + key = KEY_YELLOW; + break; + + case CEC_USER_CONTROL_CODE_F1_BLUE: + key = KEY_BLUE; + break; + + case CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION: + key = KEY_POWER; + break; + + default: + key = KEY_MENU; + break; + } + + return key; +} + +bool hdmi_cec::Start() +{ + if (running) + return false; + + if (hdmiFd == -1) + return false; + + dprintf(DEBUG_NORMAL, GREEN"[CEC] thread starting...\n"NORMAL); + running = true; + OpenThreads::Thread::setSchedulePriority(THREAD_PRIORITY_MIN); + return (OpenThreads::Thread::start() == 0); +} + +bool hdmi_cec::Stop() +{ + if (!running) + return false; + + running = false; + OpenThreads::Thread::cancel(); + + if (hdmiFd >= 0) + { + close(hdmiFd); + hdmiFd = -1; + } + + return (OpenThreads::Thread::join() == 0); +} + +void hdmi_cec::run() +{ + OpenThreads::Thread::setCancelModeAsynchronous(); + int n; + int epollfd = epoll_create1(0); + struct epoll_event event; + event.data.fd = hdmiFd; + event.events = EPOLLPRI | EPOLLIN | EPOLLOUT; + epoll_ctl(epollfd, EPOLL_CTL_ADD, hdmiFd, &event); + std::array events; + dprintf(DEBUG_NORMAL, GREEN"[CEC] thread started...\n"NORMAL); + + while (running) + { + n = epoll_wait(epollfd, events.data(), EPOLL_MAX_EVENTS, EPOLL_WAIT_TIMEOUT); + + for (int i = 0; i < n; ++i) + { + if (events[i].events & EPOLLOUT) + { + mutex.lock(); + + for (std::vector::iterator it = msg_que.begin(); it != msg_que.end(); ++it) + ::write(events[i].data.fd, &(*it), 2 + (*it).length); + + msg_que.clear(); + mutex.unlock(); + } + + if (events[i].events & EPOLLPRI) + { + GetCECAddressInfo(); + } + + if (events[i].events & EPOLLIN) + { + bool hasdata = false; + struct cec_message rxmessage; + struct cec_message txmessage; + struct cec_message_fb rx_message; + + if (::read(events[i].data.fd, &rx_message, 2) == 2) + { + if (::read(events[i].data.fd, &rx_message.data, rx_message.length) == rx_message.length) + { + rxmessage.length = rx_message.length; + rxmessage.initiator = rx_message.address; + rxmessage.destination = logicalAddress; + rxmessage.opcode = rx_message.data[0]; + memcpy(&rxmessage.data, rx_message.data, rx_message.length); + hasdata = true; + } + } + + if (hasdata) + { + bool keypressed = false; + static unsigned char pressedkey = 0; + char str[rxmessage.length * 6]; + + for (int i = 0; i < rxmessage.length; i++) + { + sprintf(str + (i * 6), "[0x%02X]", rxmessage.data[i]); + } + + dprintf(DEBUG_NORMAL, GREEN"[CEC] received message %s to %s (0x%02X>>0x%02X) '%s' (%s)\n"NORMAL, ToString((cec_logical_address)rxmessage.initiator), rxmessage.destination == 0xf ? "all" : ToString((cec_logical_address)rxmessage.destination), rxmessage.initiator, rxmessage.destination, ToString((cec_opcode)rxmessage.opcode), str); + + switch (rxmessage.opcode) + { + case CEC_OPCODE_GET_CEC_VERSION: + { + txmessage.initiator = logicalAddress; + txmessage.destination = rxmessage.initiator; + txmessage.data[0] = CEC_OPCODE_CEC_VERSION; + txmessage.data[1] = CEC_OP_CEC_VERSION_2_0; + txmessage.length = 2; + SendCECMessage(txmessage); + break; + } + + case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS: + { + ReportPhysicalAddress(); + break; + } + + case CEC_OPCODE_GIVE_OSD_NAME: + { + txmessage.initiator = logicalAddress; + txmessage.destination = CECDEVICE_BROADCAST; + txmessage.data[0] = CEC_OPCODE_SET_OSD_NAME; + memcpy(txmessage.data + 1, osdname, strlen(osdname)); + txmessage.length = strlen(osdname) + 1; + SendCECMessage(txmessage); + break; + } + + case CEC_OPCODE_FEATURE_ABORT: + { + dprintf(DEBUG_NORMAL, GREEN"[CEC] decoded message feature '%s' not supported (%s)\n"NORMAL, ToString((cec_opcode)rxmessage.data[1]), ToString((cec_error_id)rxmessage.data[2])); + break; + } + + case CEC_OPCODE_SET_OSD_NAME: + { + dprintf(DEBUG_NORMAL, GREEN"[CEC] decoded message '%s' \n"NORMAL, (char *)rxmessage.data + 1); + break; + } + + case CEC_OPCODE_REQUEST_ACTIVE_SOURCE: + { + SendActiveSource(); + break; + } + + case CEC_OPCODE_REPORT_AUDIO_STATUS: + { + muted = ((rxmessage.data[1] & 0x80) == 0x80); + volume = ((rxmessage.data[1] & 0x7F) / 127.0) * 100.0; + + if (muted) + dprintf(DEBUG_NORMAL, GREEN"[CEC] %s volume muted\n"NORMAL, ToString((cec_logical_address)rxmessage.initiator)); + else + dprintf(DEBUG_NORMAL, GREEN"[CEC] %s volume %d \n"NORMAL, ToString((cec_logical_address)rxmessage.initiator), volume); + + break; + } + + case CEC_OPCODE_DEVICE_VENDOR_ID: + case CEC_OPCODE_VENDOR_COMMAND_WITH_ID: + { + uint64_t iVendorId = ((uint64_t)rxmessage.data[1] << 16) + + ((uint64_t)rxmessage.data[2] << 8) + + (uint64_t)rxmessage.data[3]; + dprintf(DEBUG_NORMAL, GREEN"[CEC] decoded message '%s' (%s)\n"NORMAL, ToString((cec_opcode)rxmessage.opcode), ToString((cec_vendor_id)iVendorId)); + break; + } + + case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS: + { + txmessage.destination = rxmessage.initiator; + txmessage.initiator = rxmessage.destination; + txmessage.data[0] = GetResponseOpcode((cec_opcode)rxmessage.opcode); + txmessage.data[1] = (CNeutrinoApp::getInstance()->getMode() == NeutrinoModes::mode_standby) ? CEC_POWER_STATUS_STANDBY : CEC_POWER_STATUS_ON; + txmessage.length = 2; + SendCECMessage(txmessage); + break; + } + + case CEC_OPCODE_REPORT_POWER_STATUS: + { + if ((rxmessage.data[1] == CEC_POWER_STATUS_ON) || (rxmessage.data[1] == CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON)) + { + dprintf(DEBUG_NORMAL, GREEN"[CEC] %s reporting state on (%d)\n"NORMAL, ToString((cec_logical_address)rxmessage.initiator), rxmessage.data[1]); + + if (rxmessage.initiator == CECDEVICE_TV) + tv_off = false; + } + else + { + dprintf(DEBUG_NORMAL, GREEN"[CEC] %s reporting state off (%d)\n"NORMAL, ToString((cec_logical_address)rxmessage.initiator), rxmessage.data[1]); + + if (rxmessage.initiator == CECDEVICE_TV) + tv_off = true; + } + + break; + } + + case CEC_OPCODE_STANDBY: + { + if (rxmessage.initiator == CECDEVICE_TV) + { + RequestTVPowerStatus(); + + if (CNeutrinoApp::getInstance()->getMode() != NeutrinoModes::mode_standby) + g_RCInput->postMsg(NeutrinoMessages::STANDBY_ON, (neutrino_msg_data_t)"cec"); + } + + break; + } + + case CEC_OPCODE_SET_STREAM_PATH: + { + char msgpath[8]; + char phypath[8]; + sprintf(msgpath, "%02X:%02X", rxmessage.data[1], rxmessage.data[2]); + sprintf(phypath, "%02X:%02X", physicalAddress[0], physicalAddress[1]); + + if (strcmp(msgpath, phypath) == 0) + { + dprintf(DEBUG_NORMAL, CYAN"[CEC] received streampath (%s) change to me (%s) -> wake up \n"NORMAL, msgpath, phypath); + + if (CNeutrinoApp::getInstance()->getMode() == NeutrinoModes::mode_standby && g_settings.hdmi_cec_wakeup) + g_RCInput->postMsg(NeutrinoMessages::STANDBY_OFF, (neutrino_msg_data_t)"cec"); + + active_source = true; + SendActiveSource(); + } + else + { + dprintf(DEBUG_NORMAL, CYAN"[CEC] received streampath (%s) change away from me (%s) -> go to sleep\n"NORMAL, msgpath, phypath); + + if (CNeutrinoApp::getInstance()->getMode() != NeutrinoModes::mode_standby && g_settings.hdmi_cec_sleep) + g_RCInput->postMsg(NeutrinoMessages::STANDBY_ON, (neutrino_msg_data_t)"cec"); + + active_source = false; + } + + break; + } + + case CEC_OPCODE_USER_CONTROL_PRESSED: /* key pressed */ + { + keypressed = true; + pressedkey = rxmessage.data[1]; + } // fall through + + case CEC_OPCODE_USER_CONTROL_RELEASE: /* key released */ + { + long code = translateKey(pressedkey); + dprintf(DEBUG_NORMAL, GREEN"[CEC] decoded key %s (%ld)\n"NORMAL, ToString((cec_user_control_code)pressedkey), code); + + if (code == KEY_POWER) + { + if (CNeutrinoApp::getInstance()->getMode() == NeutrinoModes::mode_standby) + g_RCInput->postMsg(NeutrinoMessages::STANDBY_OFF, (neutrino_msg_data_t)"cec"); + } + else + handleCode(code, keypressed); + + break; + } + } + } + } + } + } +} + +void hdmi_cec::handleCode(long code, bool keypressed) +{ + int evd = open(RC_DEVICE, O_RDWR); + + if (evd < 0) + { + dprintf(DEBUG_NORMAL, RED"[CEC] opening " RC_DEVICE " failed"NORMAL); + return; + } + + if (keypressed) + { + if (rc_send(evd, code, CEC_KEY_PRESSED) < 0) + { + dprintf(DEBUG_NORMAL, RED"[CEC] writing 'KEY_PRESSED' event failed"NORMAL); + close(evd); + return; + } + + rc_sync(evd); + } + else + { + if (rc_send(evd, code, CEC_KEY_RELEASED) < 0) + { + dprintf(DEBUG_NORMAL, RED"[CEC] writing 'KEY_RELEASED' event failed"NORMAL); + close(evd); + return; + } + + rc_sync(evd); + } + + close(evd); +} + +int hdmi_cec::rc_send(int fd, unsigned int code, unsigned int value) +{ + struct input_event ev; + ev.type = EV_KEY; + ev.code = code; + ev.value = value; + return write(fd, &ev, sizeof(ev)); +} + +void hdmi_cec::rc_sync(int fd) +{ + struct input_event ev; + gettimeofday(&ev.time, NULL); + ev.type = EV_SYN; + ev.code = SYN_REPORT; + ev.value = 0; + write(fd, &ev, sizeof(ev)); +} + +void hdmi_cec::send_key(unsigned char key, unsigned char destination) +{ + struct cec_message txmessage; + txmessage.destination = destination; + txmessage.initiator = logicalAddress; + txmessage.data[0] = CEC_OPCODE_USER_CONTROL_PRESSED; + txmessage.data[1] = key; + txmessage.length = 2; + SendCECMessage(txmessage); + txmessage.destination = destination; + txmessage.initiator = logicalAddress; + txmessage.data[0] = CEC_OPCODE_USER_CONTROL_RELEASE; + txmessage.length = 1; + SendCECMessage(txmessage); +} + +void hdmi_cec::request_audio_status() +{ + struct cec_message txmessage; + txmessage.destination = audio_destination; + txmessage.initiator = logicalAddress; + txmessage.data[0] = CEC_OPCODE_GIVE_AUDIO_STATUS; + txmessage.length = 1; + SendCECMessage(txmessage); +} + +void hdmi_cec::vol_up() +{ + send_key(CEC_USER_CONTROL_CODE_VOLUME_UP, audio_destination); +} +void hdmi_cec::vol_down() +{ + send_key(CEC_USER_CONTROL_CODE_VOLUME_DOWN, audio_destination); +} +void hdmi_cec::toggle_mute() +{ + send_key(CEC_USER_CONTROL_CODE_MUTE, audio_destination); + request_audio_status(); +} + +void hdmi_cec::SetAudioDestination(int audio_dest) +{ + switch (audio_dest) + { + case 2: + audio_destination = CECDEVICE_TV; + break; + + case 1: + default: + audio_destination = CECDEVICE_AUDIOSYSTEM; + break; + } +} + diff --git a/src/driver/hdmi_cec.h b/src/driver/hdmi_cec.h new file mode 100644 index 000000000..1a452d760 --- /dev/null +++ b/src/driver/hdmi_cec.h @@ -0,0 +1,123 @@ +#ifndef __HDMI_CEC_H__ +#define __HDMI_CEC_H__ + +/* + Copyright (C) 2018-2022 TangoCash + + License: GPLv2 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include + + +typedef enum +{ + VIDEO_HDMI_CEC_MODE_OFF = 0, + VIDEO_HDMI_CEC_MODE_ON = 1, +} VIDEO_HDMI_CEC_MODE; + +typedef enum +{ + VIDEO_HDMI_CEC_VOL_OFF = 0, + VIDEO_HDMI_CEC_VOL_AUDIOSYSTEM = 1, + VIDEO_HDMI_CEC_VOL_TV = 2 +} VIDEO_HDMI_CEC_VOL; + +struct cec_message +{ + unsigned char initiator; + unsigned char destination; + unsigned char opcode; + unsigned char data[256]; + unsigned char length; +} __attribute__((packed)); + +struct cec_message_fb +{ + unsigned char address; + unsigned char length; + unsigned char data[256]; +} __attribute__((packed)); + +struct addressinfo +{ + unsigned char logical; + unsigned char physical[2]; + unsigned char type; +}; + +enum +{ + CEC_KEY_RELEASED = 0, + CEC_KEY_PRESSED, + CEC_KEY_AUTOREPEAT +}; + +class hdmi_cec : public OpenThreads::Thread +{ + private: + void run(); + bool Start(); + bool Stop(); + unsigned char physicalAddress[2]; + bool autoview_cec_activ; + unsigned char deviceType, logicalAddress; + int hdmiFd; + long translateKey(unsigned char code); + void handleCode(long code, bool keypressed); + int rc_send(int fd, unsigned int code, unsigned int value); + void rc_sync(int fd); + void send_key(unsigned char key, unsigned char destination); + void request_audio_status(); + bool muted; + int volume; + bool tv_off; + bool active_source; + unsigned char audio_destination; + char osdname[14]; + std::vector msg_que; + OpenThreads::Mutex mutex; + protected: + bool running; + public: + hdmi_cec(); + ~hdmi_cec(); + bool SetCECMode(VIDEO_HDMI_CEC_MODE); + void SetCECAutoView(bool); + void SetCECAutoStandby(bool); + void SendAnnounce(); + void SendViewOn(); + void SendStandBy(); + void SendActiveSource(); + void RequestTVPowerStatus(); + void GetCECAddressInfo(); + void SendCECMessage(struct cec_message &message, int sleeptime = 250); + void SetCECState(bool state); + void ReportPhysicalAddress(); + bool standby_cec_activ; + void vol_up(); + void vol_down(); + void toggle_mute(); + int GetVolume() { request_audio_status(); return volume; }; + bool isMuted() { return muted; }; + int GetAudioDestination() { return (int)audio_destination; } + void SetAudioDestination(int audio_dest); +}; + +#endif // __HDMI_CEC_H__ diff --git a/src/driver/hdmi_cec_types.h b/src/driver/hdmi_cec_types.h new file mode 100644 index 000000000..61f6eae18 --- /dev/null +++ b/src/driver/hdmi_cec_types.h @@ -0,0 +1,953 @@ +#ifndef __HDMI_CEC_TYPES_H__ +#define __HDMI_CEC_TYPES_H__ + +typedef enum cec_version +{ + CEC_OP_CEC_VERSION_1_3A = 4, + CEC_OP_CEC_VERSION_1_4 = 5, + CEC_OP_CEC_VERSION_2_0 = 6 +} cec_version; + +typedef enum cec_vendor_id +{ + CEC_VENDOR_TOSHIBA = 0x000039, + CEC_VENDOR_SAMSUNG = 0x0000F0, + CEC_VENDOR_DENON = 0x0005CD, + CEC_VENDOR_MARANTZ = 0x000678, + CEC_VENDOR_LOEWE = 0x000982, + CEC_VENDOR_ONKYO = 0x0009B0, + CEC_VENDOR_MEDION = 0x000CB8, + CEC_VENDOR_TOSHIBA2 = 0x000CE7, + CEC_VENDOR_PULSE_EIGHT = 0x001582, + CEC_VENDOR_HARMAN_KARDON2 = 0x001950, + CEC_VENDOR_GOOGLE = 0x001A11, + CEC_VENDOR_AKAI = 0x0020C7, + CEC_VENDOR_AOC = 0x002467, + CEC_VENDOR_PANASONIC = 0x008045, + CEC_VENDOR_PHILIPS = 0x00903E, + CEC_VENDOR_DAEWOO = 0x009053, + CEC_VENDOR_YAMAHA = 0x00A0DE, + CEC_VENDOR_GRUNDIG = 0x00D0D5, + CEC_VENDOR_PIONEER = 0x00E036, + CEC_VENDOR_LG = 0x00E091, + CEC_VENDOR_SHARP = 0x08001F, + CEC_VENDOR_SONY = 0x080046, + CEC_VENDOR_BROADCOM = 0x18C086, + CEC_VENDOR_SHARP2 = 0x534850, + CEC_VENDOR_VIZIO = 0x6B746D, + CEC_VENDOR_BENQ = 0x8065E9, + CEC_VENDOR_HARMAN_KARDON = 0x9C645E, + CEC_VENDOR_UNKNOWN = 0 +} cec_vendor_id; + +typedef enum cec_user_control_code +{ + CEC_USER_CONTROL_CODE_SELECT = 0x00, + CEC_USER_CONTROL_CODE_UP = 0x01, + CEC_USER_CONTROL_CODE_DOWN = 0x02, + CEC_USER_CONTROL_CODE_LEFT = 0x03, + CEC_USER_CONTROL_CODE_RIGHT = 0x04, + CEC_USER_CONTROL_CODE_RIGHT_UP = 0x05, + CEC_USER_CONTROL_CODE_RIGHT_DOWN = 0x06, + CEC_USER_CONTROL_CODE_LEFT_UP = 0x07, + CEC_USER_CONTROL_CODE_LEFT_DOWN = 0x08, + CEC_USER_CONTROL_CODE_ROOT_MENU = 0x09, + CEC_USER_CONTROL_CODE_SETUP_MENU = 0x0A, + CEC_USER_CONTROL_CODE_CONTENTS_MENU = 0x0B, + CEC_USER_CONTROL_CODE_FAVORITE_MENU = 0x0C, + CEC_USER_CONTROL_CODE_EXIT = 0x0D, + // reserved: 0x0E, 0x0F + CEC_USER_CONTROL_CODE_TOP_MENU = 0x10, + CEC_USER_CONTROL_CODE_DVD_MENU = 0x11, + // reserved: 0x12 ... 0x1C + CEC_USER_CONTROL_CODE_NUMBER_ENTRY_MODE = 0x1D, + CEC_USER_CONTROL_CODE_NUMBER11 = 0x1E, + CEC_USER_CONTROL_CODE_NUMBER12 = 0x1F, + CEC_USER_CONTROL_CODE_NUMBER0 = 0x20, + CEC_USER_CONTROL_CODE_NUMBER1 = 0x21, + CEC_USER_CONTROL_CODE_NUMBER2 = 0x22, + CEC_USER_CONTROL_CODE_NUMBER3 = 0x23, + CEC_USER_CONTROL_CODE_NUMBER4 = 0x24, + CEC_USER_CONTROL_CODE_NUMBER5 = 0x25, + CEC_USER_CONTROL_CODE_NUMBER6 = 0x26, + CEC_USER_CONTROL_CODE_NUMBER7 = 0x27, + CEC_USER_CONTROL_CODE_NUMBER8 = 0x28, + CEC_USER_CONTROL_CODE_NUMBER9 = 0x29, + CEC_USER_CONTROL_CODE_DOT = 0x2A, + CEC_USER_CONTROL_CODE_ENTER = 0x2B, + CEC_USER_CONTROL_CODE_CLEAR = 0x2C, + CEC_USER_CONTROL_CODE_NEXT_FAVORITE = 0x2F, + CEC_USER_CONTROL_CODE_CHANNEL_UP = 0x30, + CEC_USER_CONTROL_CODE_CHANNEL_DOWN = 0x31, + CEC_USER_CONTROL_CODE_PREVIOUS_CHANNEL = 0x32, + CEC_USER_CONTROL_CODE_SOUND_SELECT = 0x33, + CEC_USER_CONTROL_CODE_INPUT_SELECT = 0x34, + CEC_USER_CONTROL_CODE_DISPLAY_INFORMATION = 0x35, + CEC_USER_CONTROL_CODE_HELP = 0x36, + CEC_USER_CONTROL_CODE_PAGE_UP = 0x37, + CEC_USER_CONTROL_CODE_PAGE_DOWN = 0x38, + // reserved: 0x39 ... 0x3F + CEC_USER_CONTROL_CODE_POWER = 0x40, + CEC_USER_CONTROL_CODE_VOLUME_UP = 0x41, + CEC_USER_CONTROL_CODE_VOLUME_DOWN = 0x42, + CEC_USER_CONTROL_CODE_MUTE = 0x43, + CEC_USER_CONTROL_CODE_PLAY = 0x44, + CEC_USER_CONTROL_CODE_STOP = 0x45, + CEC_USER_CONTROL_CODE_PAUSE = 0x46, + CEC_USER_CONTROL_CODE_RECORD = 0x47, + CEC_USER_CONTROL_CODE_REWIND = 0x48, + CEC_USER_CONTROL_CODE_FAST_FORWARD = 0x49, + CEC_USER_CONTROL_CODE_EJECT = 0x4A, + CEC_USER_CONTROL_CODE_FORWARD = 0x4B, + CEC_USER_CONTROL_CODE_BACKWARD = 0x4C, + CEC_USER_CONTROL_CODE_STOP_RECORD = 0x4D, + CEC_USER_CONTROL_CODE_PAUSE_RECORD = 0x4E, + // reserved: 0x4F + CEC_USER_CONTROL_CODE_ANGLE = 0x50, + CEC_USER_CONTROL_CODE_SUB_PICTURE = 0x51, + CEC_USER_CONTROL_CODE_VIDEO_ON_DEMAND = 0x52, + CEC_USER_CONTROL_CODE_ELECTRONIC_PROGRAM_GUIDE = 0x53, + CEC_USER_CONTROL_CODE_TIMER_PROGRAMMING = 0x54, + CEC_USER_CONTROL_CODE_INITIAL_CONFIGURATION = 0x55, + CEC_USER_CONTROL_CODE_SELECT_BROADCAST_TYPE = 0x56, + CEC_USER_CONTROL_CODE_SELECT_SOUND_PRESENTATION = 0x57, + // reserved: 0x58 ... 0x5F + CEC_USER_CONTROL_CODE_PLAY_FUNCTION = 0x60, + CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION = 0x61, + CEC_USER_CONTROL_CODE_RECORD_FUNCTION = 0x62, + CEC_USER_CONTROL_CODE_PAUSE_RECORD_FUNCTION = 0x63, + CEC_USER_CONTROL_CODE_STOP_FUNCTION = 0x64, + CEC_USER_CONTROL_CODE_MUTE_FUNCTION = 0x65, + CEC_USER_CONTROL_CODE_RESTORE_VOLUME_FUNCTION = 0x66, + CEC_USER_CONTROL_CODE_TUNE_FUNCTION = 0x67, + CEC_USER_CONTROL_CODE_SELECT_MEDIA_FUNCTION = 0x68, + CEC_USER_CONTROL_CODE_SELECT_AV_INPUT_FUNCTION = 0x69, + CEC_USER_CONTROL_CODE_SELECT_AUDIO_INPUT_FUNCTION = 0x6A, + CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION = 0x6B, + CEC_USER_CONTROL_CODE_POWER_OFF_FUNCTION = 0x6C, + CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION = 0x6D, + // reserved: 0x6E ... 0x70 + CEC_USER_CONTROL_CODE_F1_BLUE = 0x71, + CEC_USER_CONTROL_CODE_F2_RED = 0X72, + CEC_USER_CONTROL_CODE_F3_GREEN = 0x73, + CEC_USER_CONTROL_CODE_F4_YELLOW = 0x74, + CEC_USER_CONTROL_CODE_F5 = 0x75, + CEC_USER_CONTROL_CODE_DATA = 0x76, + // reserved: 0x77 ... 0xFF + CEC_USER_CONTROL_CODE_AN_RETURN = 0x91, // return (Samsung) + CEC_USER_CONTROL_CODE_AN_CHANNELS_LIST = 0x96, // channels list (Samsung) + CEC_USER_CONTROL_CODE_MAX = 0x96, + CEC_USER_CONTROL_CODE_UNKNOWN = 0xFF +} cec_user_control_code; + +typedef enum cec_opcode +{ + CEC_OPCODE_ACTIVE_SOURCE = 0x82, + CEC_OPCODE_IMAGE_VIEW_ON = 0x04, + CEC_OPCODE_TEXT_VIEW_ON = 0x0D, + CEC_OPCODE_INACTIVE_SOURCE = 0x9D, + CEC_OPCODE_REQUEST_ACTIVE_SOURCE = 0x85, + CEC_OPCODE_ROUTING_CHANGE = 0x80, + CEC_OPCODE_ROUTING_INFORMATION = 0x81, + CEC_OPCODE_SET_STREAM_PATH = 0x86, + CEC_OPCODE_STANDBY = 0x36, + CEC_OPCODE_RECORD_OFF = 0x0B, + CEC_OPCODE_RECORD_ON = 0x09, + CEC_OPCODE_RECORD_STATUS = 0x0A, + CEC_OPCODE_RECORD_TV_SCREEN = 0x0F, + CEC_OPCODE_CLEAR_ANALOGUE_TIMER = 0x33, + CEC_OPCODE_CLEAR_DIGITAL_TIMER = 0x99, + CEC_OPCODE_CLEAR_EXTERNAL_TIMER = 0xA1, + CEC_OPCODE_SET_ANALOGUE_TIMER = 0x34, + CEC_OPCODE_SET_DIGITAL_TIMER = 0x97, + CEC_OPCODE_SET_EXTERNAL_TIMER = 0xA2, + CEC_OPCODE_SET_TIMER_PROGRAM_TITLE = 0x67, + CEC_OPCODE_TIMER_CLEARED_STATUS = 0x43, + CEC_OPCODE_TIMER_STATUS = 0x35, + CEC_OPCODE_CEC_VERSION = 0x9E, + CEC_OPCODE_GET_CEC_VERSION = 0x9F, + CEC_OPCODE_GIVE_PHYSICAL_ADDRESS = 0x83, + CEC_OPCODE_GET_MENU_LANGUAGE = 0x91, + CEC_OPCODE_REPORT_PHYSICAL_ADDRESS = 0x84, + CEC_OPCODE_SET_MENU_LANGUAGE = 0x32, + CEC_OPCODE_DECK_CONTROL = 0x42, + CEC_OPCODE_DECK_STATUS = 0x1B, + CEC_OPCODE_GIVE_DECK_STATUS = 0x1A, + CEC_OPCODE_PLAY = 0x41, + CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS = 0x08, + CEC_OPCODE_SELECT_ANALOGUE_SERVICE = 0x92, + CEC_OPCODE_SELECT_DIGITAL_SERVICE = 0x93, + CEC_OPCODE_TUNER_DEVICE_STATUS = 0x07, + CEC_OPCODE_TUNER_STEP_DECREMENT = 0x06, + CEC_OPCODE_TUNER_STEP_INCREMENT = 0x05, + CEC_OPCODE_DEVICE_VENDOR_ID = 0x87, + CEC_OPCODE_GIVE_DEVICE_VENDOR_ID = 0x8C, + CEC_OPCODE_VENDOR_COMMAND = 0x89, + CEC_OPCODE_VENDOR_COMMAND_WITH_ID = 0xA0, + CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN = 0x8A, + CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP = 0x8B, + CEC_OPCODE_SET_OSD_STRING = 0x64, + CEC_OPCODE_GIVE_OSD_NAME = 0x46, + CEC_OPCODE_SET_OSD_NAME = 0x47, + CEC_OPCODE_MENU_REQUEST = 0x8D, + CEC_OPCODE_MENU_STATUS = 0x8E, + CEC_OPCODE_USER_CONTROL_PRESSED = 0x44, + CEC_OPCODE_USER_CONTROL_RELEASE = 0x45, + CEC_OPCODE_GIVE_DEVICE_POWER_STATUS = 0x8F, + CEC_OPCODE_REPORT_POWER_STATUS = 0x90, + CEC_OPCODE_FEATURE_ABORT = 0x00, + CEC_OPCODE_ABORT = 0xFF, + CEC_OPCODE_GIVE_AUDIO_STATUS = 0x71, + CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS = 0x7D, + CEC_OPCODE_REPORT_AUDIO_STATUS = 0x7A, + CEC_OPCODE_SET_SYSTEM_AUDIO_MODE = 0x72, + CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST = 0x70, + CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS = 0x7E, + CEC_OPCODE_SET_AUDIO_RATE = 0x9A, + + /* CEC 1.4 */ + CEC_OPCODE_START_ARC = 0xC0, + CEC_OPCODE_REPORT_ARC_STARTED = 0xC1, + CEC_OPCODE_REPORT_ARC_ENDED = 0xC2, + CEC_OPCODE_REQUEST_ARC_START = 0xC3, + CEC_OPCODE_REQUEST_ARC_END = 0xC4, + CEC_OPCODE_END_ARC = 0xC5, + CEC_OPCODE_CDC = 0xF8, + /* when this opcode is set, no opcode will be sent to the device. this is one of the reserved numbers */ + CEC_OPCODE_NONE = 0xFD +} cec_opcode; + +typedef enum cec_logical_address +{ + CECDEVICE_UNKNOWN = -1, //not a valid logical address + CECDEVICE_TV = 0, + CECDEVICE_RECORDINGDEVICE1 = 1, + CECDEVICE_RECORDINGDEVICE2 = 2, + CECDEVICE_TUNER1 = 3, + CECDEVICE_PLAYBACKDEVICE1 = 4, + CECDEVICE_AUDIOSYSTEM = 5, + CECDEVICE_TUNER2 = 6, + CECDEVICE_TUNER3 = 7, + CECDEVICE_PLAYBACKDEVICE2 = 8, + CECDEVICE_RECORDINGDEVICE3 = 9, + CECDEVICE_TUNER4 = 10, + CECDEVICE_PLAYBACKDEVICE3 = 11, + CECDEVICE_RESERVED1 = 12, + CECDEVICE_RESERVED2 = 13, + CECDEVICE_FREEUSE = 14, + CECDEVICE_UNREGISTERED = 15, + CECDEVICE_BROADCAST = 15 +} cec_logical_address; + +typedef enum cec_power_status +{ + CEC_POWER_STATUS_ON = 0x00, + CEC_POWER_STATUS_STANDBY = 0x01, + CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON = 0x02, + CEC_POWER_STATUS_IN_TRANSITION_ON_TO_STANDBY = 0x03, + CEC_POWER_STATUS_UNKNOWN = 0x99 +} cec_power_status; + +typedef unsigned char cec_error_id; + +static const char *ToString(const cec_opcode opcode) +{ + switch (opcode) + { + case CEC_OPCODE_ACTIVE_SOURCE: + return "active source"; + + case CEC_OPCODE_IMAGE_VIEW_ON: + return "image view on"; + + case CEC_OPCODE_TEXT_VIEW_ON: + return "text view on"; + + case CEC_OPCODE_INACTIVE_SOURCE: + return "inactive source"; + + case CEC_OPCODE_REQUEST_ACTIVE_SOURCE: + return "request active source"; + + case CEC_OPCODE_ROUTING_CHANGE: + return "routing change"; + + case CEC_OPCODE_ROUTING_INFORMATION: + return "routing information"; + + case CEC_OPCODE_SET_STREAM_PATH: + return "set stream path"; + + case CEC_OPCODE_STANDBY: + return "standby"; + + case CEC_OPCODE_RECORD_OFF: + return "record off"; + + case CEC_OPCODE_RECORD_ON: + return "record on"; + + case CEC_OPCODE_RECORD_STATUS: + return "record status"; + + case CEC_OPCODE_RECORD_TV_SCREEN: + return "record tv screen"; + + case CEC_OPCODE_CLEAR_ANALOGUE_TIMER: + return "clear analogue timer"; + + case CEC_OPCODE_CLEAR_DIGITAL_TIMER: + return "clear digital timer"; + + case CEC_OPCODE_CLEAR_EXTERNAL_TIMER: + return "clear external timer"; + + case CEC_OPCODE_SET_ANALOGUE_TIMER: + return "set analogue timer"; + + case CEC_OPCODE_SET_DIGITAL_TIMER: + return "set digital timer"; + + case CEC_OPCODE_SET_EXTERNAL_TIMER: + return "set external timer"; + + case CEC_OPCODE_SET_TIMER_PROGRAM_TITLE: + return "set timer program title"; + + case CEC_OPCODE_TIMER_CLEARED_STATUS: + return "timer cleared status"; + + case CEC_OPCODE_TIMER_STATUS: + return "timer status"; + + case CEC_OPCODE_CEC_VERSION: + return "cec version"; + + case CEC_OPCODE_GET_CEC_VERSION: + return "get cec version"; + + case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS: + return "give physical address"; + + case CEC_OPCODE_GET_MENU_LANGUAGE: + return "get menu language"; + + case CEC_OPCODE_REPORT_PHYSICAL_ADDRESS: + return "report physical address"; + + case CEC_OPCODE_SET_MENU_LANGUAGE: + return "set menu language"; + + case CEC_OPCODE_DECK_CONTROL: + return "deck control"; + + case CEC_OPCODE_DECK_STATUS: + return "deck status"; + + case CEC_OPCODE_GIVE_DECK_STATUS: + return "give deck status"; + + case CEC_OPCODE_PLAY: + return "play"; + + case CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS: + return "give tuner status"; + + case CEC_OPCODE_SELECT_ANALOGUE_SERVICE: + return "select analogue service"; + + case CEC_OPCODE_SELECT_DIGITAL_SERVICE: + return "set digital service"; + + case CEC_OPCODE_TUNER_DEVICE_STATUS: + return "tuner device status"; + + case CEC_OPCODE_TUNER_STEP_DECREMENT: + return "tuner step decrement"; + + case CEC_OPCODE_TUNER_STEP_INCREMENT: + return "tuner step increment"; + + case CEC_OPCODE_DEVICE_VENDOR_ID: + return "device vendor id"; + + case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID: + return "give device vendor id"; + + case CEC_OPCODE_VENDOR_COMMAND: + return "vendor command"; + + case CEC_OPCODE_VENDOR_COMMAND_WITH_ID: + return "vendor command with id"; + + case CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN: + return "vendor remote button down"; + + case CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP: + return "vendor remote button up"; + + case CEC_OPCODE_SET_OSD_STRING: + return "set osd string"; + + case CEC_OPCODE_GIVE_OSD_NAME: + return "give osd name"; + + case CEC_OPCODE_SET_OSD_NAME: + return "set osd name"; + + case CEC_OPCODE_MENU_REQUEST: + return "menu request"; + + case CEC_OPCODE_MENU_STATUS: + return "menu status"; + + case CEC_OPCODE_USER_CONTROL_PRESSED: + return "user control pressed"; + + case CEC_OPCODE_USER_CONTROL_RELEASE: + return "user control release"; + + case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS: + return "give device power status"; + + case CEC_OPCODE_REPORT_POWER_STATUS: + return "report power status"; + + case CEC_OPCODE_FEATURE_ABORT: + return "feature abort"; + + case CEC_OPCODE_ABORT: + return "abort"; + + case CEC_OPCODE_GIVE_AUDIO_STATUS: + return "give audio status"; + + case CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS: + return "give audio mode status"; + + case CEC_OPCODE_REPORT_AUDIO_STATUS: + return "report audio status"; + + case CEC_OPCODE_SET_SYSTEM_AUDIO_MODE: + return "set system audio mode"; + + case CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST: + return "system audio mode request"; + + case CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS: + return "system audio mode status"; + + case CEC_OPCODE_SET_AUDIO_RATE: + return "set audio rate"; + + case CEC_OPCODE_START_ARC: + return "start ARC"; + + case CEC_OPCODE_REPORT_ARC_STARTED: + return "report ARC started"; + + case CEC_OPCODE_REPORT_ARC_ENDED: + return "report ARC ended"; + + case CEC_OPCODE_REQUEST_ARC_START: + return "request ARC start"; + + case CEC_OPCODE_REQUEST_ARC_END: + return "request ARC end"; + + case CEC_OPCODE_END_ARC: + return "end ARC"; + + case CEC_OPCODE_CDC: + return "CDC"; + + case CEC_OPCODE_NONE: + return "poll"; + + default: + return "UNKNOWN"; + } +} + +static const char *ToString(const cec_vendor_id vendor) +{ + switch (vendor) + { + case CEC_VENDOR_SAMSUNG: + return "Samsung"; + + case CEC_VENDOR_LG: + return "LG"; + + case CEC_VENDOR_PANASONIC: + return "Panasonic"; + + case CEC_VENDOR_PIONEER: + return "Pioneer"; + + case CEC_VENDOR_ONKYO: + return "Onkyo"; + + case CEC_VENDOR_YAMAHA: + return "Yamaha"; + + case CEC_VENDOR_PHILIPS: + return "Philips"; + + case CEC_VENDOR_SONY: + return "Sony"; + + case CEC_VENDOR_TOSHIBA: + case CEC_VENDOR_TOSHIBA2: + return "Toshiba"; + + case CEC_VENDOR_AKAI: + return "Akai"; + + case CEC_VENDOR_AOC: + return "AOC"; + + case CEC_VENDOR_BENQ: + return "Benq"; + + case CEC_VENDOR_DAEWOO: + return "Daewoo"; + + case CEC_VENDOR_GRUNDIG: + return "Grundig"; + + case CEC_VENDOR_MEDION: + return "Medion"; + + case CEC_VENDOR_SHARP: + case CEC_VENDOR_SHARP2: + return "Sharp"; + + case CEC_VENDOR_VIZIO: + return "Vizio"; + + case CEC_VENDOR_BROADCOM: + return "Broadcom"; + + case CEC_VENDOR_LOEWE: + return "Loewe"; + + case CEC_VENDOR_DENON: + return "Denon"; + + case CEC_VENDOR_MARANTZ: + return "Marantz"; + + case CEC_VENDOR_HARMAN_KARDON: + case CEC_VENDOR_HARMAN_KARDON2: + return "Harman/Kardon"; + + case CEC_VENDOR_PULSE_EIGHT: + return "Pulse Eight"; + + case CEC_VENDOR_GOOGLE: + return "Google"; + + default: + return "Unknown"; + } +} + +static const char *ToString(const cec_user_control_code key) +{ + switch (key) + { + case CEC_USER_CONTROL_CODE_SELECT: + return "select"; + + case CEC_USER_CONTROL_CODE_UP: + return "up"; + + case CEC_USER_CONTROL_CODE_DOWN: + return "down"; + + case CEC_USER_CONTROL_CODE_LEFT: + return "left"; + + case CEC_USER_CONTROL_CODE_RIGHT: + return "right"; + + case CEC_USER_CONTROL_CODE_RIGHT_UP: + return "right+up"; + + case CEC_USER_CONTROL_CODE_RIGHT_DOWN: + return "right+down"; + + case CEC_USER_CONTROL_CODE_LEFT_UP: + return "left+up"; + + case CEC_USER_CONTROL_CODE_LEFT_DOWN: + return "left+down"; + + case CEC_USER_CONTROL_CODE_ROOT_MENU: + return "root menu"; + + case CEC_USER_CONTROL_CODE_SETUP_MENU: + return "setup menu"; + + case CEC_USER_CONTROL_CODE_CONTENTS_MENU: + return "contents menu"; + + case CEC_USER_CONTROL_CODE_FAVORITE_MENU: + return "favourite menu"; + + case CEC_USER_CONTROL_CODE_EXIT: + return "exit"; + + case CEC_USER_CONTROL_CODE_TOP_MENU: + return "top menu"; + + case CEC_USER_CONTROL_CODE_DVD_MENU: + return "dvd menu"; + + case CEC_USER_CONTROL_CODE_NUMBER_ENTRY_MODE: + return "number entry mode"; + + case CEC_USER_CONTROL_CODE_NUMBER11: + return "11"; + + case CEC_USER_CONTROL_CODE_NUMBER12: + return "12"; + + case CEC_USER_CONTROL_CODE_NUMBER0: + return "0"; + + case CEC_USER_CONTROL_CODE_NUMBER1: + return "1"; + + case CEC_USER_CONTROL_CODE_NUMBER2: + return "2"; + + case CEC_USER_CONTROL_CODE_NUMBER3: + return "3"; + + case CEC_USER_CONTROL_CODE_NUMBER4: + return "4"; + + case CEC_USER_CONTROL_CODE_NUMBER5: + return "5"; + + case CEC_USER_CONTROL_CODE_NUMBER6: + return "6"; + + case CEC_USER_CONTROL_CODE_NUMBER7: + return "7"; + + case CEC_USER_CONTROL_CODE_NUMBER8: + return "8"; + + case CEC_USER_CONTROL_CODE_NUMBER9: + return "9"; + + case CEC_USER_CONTROL_CODE_DOT: + return "."; + + case CEC_USER_CONTROL_CODE_ENTER: + return "enter"; + + case CEC_USER_CONTROL_CODE_CLEAR: + return "clear"; + + case CEC_USER_CONTROL_CODE_NEXT_FAVORITE: + return "next favourite"; + + case CEC_USER_CONTROL_CODE_CHANNEL_UP: + return "channel up"; + + case CEC_USER_CONTROL_CODE_CHANNEL_DOWN: + return "channel down"; + + case CEC_USER_CONTROL_CODE_PREVIOUS_CHANNEL: + return "previous channel"; + + case CEC_USER_CONTROL_CODE_SOUND_SELECT: + return "sound select"; + + case CEC_USER_CONTROL_CODE_INPUT_SELECT: + return "input select"; + + case CEC_USER_CONTROL_CODE_DISPLAY_INFORMATION: + return "display information"; + + case CEC_USER_CONTROL_CODE_HELP: + return "help"; + + case CEC_USER_CONTROL_CODE_PAGE_UP: + return "page up"; + + case CEC_USER_CONTROL_CODE_PAGE_DOWN: + return "page down"; + + case CEC_USER_CONTROL_CODE_POWER: + return "power"; + + case CEC_USER_CONTROL_CODE_VOLUME_UP: + return "volume up"; + + case CEC_USER_CONTROL_CODE_VOLUME_DOWN: + return "volume down"; + + case CEC_USER_CONTROL_CODE_MUTE: + return "mute"; + + case CEC_USER_CONTROL_CODE_PLAY: + return "play"; + + case CEC_USER_CONTROL_CODE_STOP: + return "stop"; + + case CEC_USER_CONTROL_CODE_PAUSE: + return "pause"; + + case CEC_USER_CONTROL_CODE_RECORD: + return "record"; + + case CEC_USER_CONTROL_CODE_REWIND: + return "rewind"; + + case CEC_USER_CONTROL_CODE_FAST_FORWARD: + return "Fast forward"; + + case CEC_USER_CONTROL_CODE_EJECT: + return "eject"; + + case CEC_USER_CONTROL_CODE_FORWARD: + return "forward"; + + case CEC_USER_CONTROL_CODE_BACKWARD: + return "backward"; + + case CEC_USER_CONTROL_CODE_STOP_RECORD: + return "stop record"; + + case CEC_USER_CONTROL_CODE_PAUSE_RECORD: + return "pause record"; + + case CEC_USER_CONTROL_CODE_ANGLE: + return "angle"; + + case CEC_USER_CONTROL_CODE_SUB_PICTURE: + return "sub picture"; + + case CEC_USER_CONTROL_CODE_VIDEO_ON_DEMAND: + return "video on demand"; + + case CEC_USER_CONTROL_CODE_ELECTRONIC_PROGRAM_GUIDE: + return "electronic program guide"; + + case CEC_USER_CONTROL_CODE_TIMER_PROGRAMMING: + return "timer programming"; + + case CEC_USER_CONTROL_CODE_INITIAL_CONFIGURATION: + return "initial configuration"; + + case CEC_USER_CONTROL_CODE_SELECT_BROADCAST_TYPE: + return "select broadcast type"; + + case CEC_USER_CONTROL_CODE_SELECT_SOUND_PRESENTATION: + return "select sound presentation"; + + case CEC_USER_CONTROL_CODE_PLAY_FUNCTION: + return "play (function)"; + + case CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION: + return "pause play (function)"; + + case CEC_USER_CONTROL_CODE_RECORD_FUNCTION: + return "record (function)"; + + case CEC_USER_CONTROL_CODE_PAUSE_RECORD_FUNCTION: + return "pause record (function)"; + + case CEC_USER_CONTROL_CODE_STOP_FUNCTION: + return "stop (function)"; + + case CEC_USER_CONTROL_CODE_MUTE_FUNCTION: + return "mute (function)"; + + case CEC_USER_CONTROL_CODE_RESTORE_VOLUME_FUNCTION: + return "restore volume"; + + case CEC_USER_CONTROL_CODE_TUNE_FUNCTION: + return "tune"; + + case CEC_USER_CONTROL_CODE_SELECT_MEDIA_FUNCTION: + return "select media"; + + case CEC_USER_CONTROL_CODE_SELECT_AV_INPUT_FUNCTION: + return "select AV input"; + + case CEC_USER_CONTROL_CODE_SELECT_AUDIO_INPUT_FUNCTION: + return "select audio input"; + + case CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION: + return "power toggle"; + + case CEC_USER_CONTROL_CODE_POWER_OFF_FUNCTION: + return "power off"; + + case CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION: + return "power on"; + + case CEC_USER_CONTROL_CODE_F1_BLUE: + return "F1 (blue)"; + + case CEC_USER_CONTROL_CODE_F2_RED: + return "F2 (red)"; + + case CEC_USER_CONTROL_CODE_F3_GREEN: + return "F3 (green)"; + + case CEC_USER_CONTROL_CODE_F4_YELLOW: + return "F4 (yellow)"; + + case CEC_USER_CONTROL_CODE_F5: + return "F5"; + + case CEC_USER_CONTROL_CODE_DATA: + return "data"; + + case CEC_USER_CONTROL_CODE_AN_RETURN: + return "return (Samsung)"; + + case CEC_USER_CONTROL_CODE_AN_CHANNELS_LIST: + return "channels list (Samsung)"; + + default: + return "unknown"; + } +} + +static const char *ToString(cec_logical_address la) +{ + switch (la & 0xf) + { + case CECDEVICE_TV: + return "TV"; + + case CECDEVICE_RECORDINGDEVICE1: + return "Recording Device 1"; + + case CECDEVICE_RECORDINGDEVICE2: + return "Recording Device 2"; + + case CECDEVICE_TUNER1: + return "Tuner 1"; + + case CECDEVICE_PLAYBACKDEVICE1: + return "Playback Device 1"; + + case CECDEVICE_AUDIOSYSTEM: + return "Audio System"; + + case CECDEVICE_TUNER2: + return "Tuner 2"; + + case CECDEVICE_TUNER3: + return "Tuner 3"; + + case CECDEVICE_PLAYBACKDEVICE2: + return "Playback Device 2"; + + case CECDEVICE_RECORDINGDEVICE3: + return "Recording Device 3"; + + case CECDEVICE_TUNER4: + return "Tuner 4"; + + case CECDEVICE_PLAYBACKDEVICE3: + return "Playback Device 3"; + + case CECDEVICE_RESERVED1: + return "Reserved 1"; + + case CECDEVICE_RESERVED2: + return "Reserved 2"; + + case CECDEVICE_FREEUSE: + return "Free use"; + + case CECDEVICE_UNREGISTERED: + default: + return "Unregistered"; + } +} + +static const char *ToString(cec_error_id reason) +{ + switch (reason & 0x0f) + { + case 0x00: + return "unrecognized opcode"; + + case 0x01: + return "not in correct mode to response"; + + case 0x02: + return "cannot provide source"; + + case 0x03: + return "invalid operand"; + + case 0x04: + default: + return "refused"; + } +} + +static cec_opcode GetResponseOpcode(cec_opcode opcode) +{ + switch (opcode) + { + case CEC_OPCODE_REQUEST_ACTIVE_SOURCE: + return CEC_OPCODE_ACTIVE_SOURCE; + + case CEC_OPCODE_GET_CEC_VERSION: + return CEC_OPCODE_CEC_VERSION; + + case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS: + return CEC_OPCODE_REPORT_PHYSICAL_ADDRESS; + + case CEC_OPCODE_GET_MENU_LANGUAGE: + return CEC_OPCODE_SET_MENU_LANGUAGE; + + case CEC_OPCODE_GIVE_DECK_STATUS: + return CEC_OPCODE_DECK_STATUS; + + case CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS: + return CEC_OPCODE_TUNER_DEVICE_STATUS; + + case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID: + return CEC_OPCODE_DEVICE_VENDOR_ID; + + case CEC_OPCODE_GIVE_OSD_NAME: + return CEC_OPCODE_SET_OSD_NAME; + + case CEC_OPCODE_MENU_REQUEST: + return CEC_OPCODE_MENU_STATUS; + + case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS: + return CEC_OPCODE_REPORT_POWER_STATUS; + + case CEC_OPCODE_GIVE_AUDIO_STATUS: + return CEC_OPCODE_REPORT_AUDIO_STATUS; + + case CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS: + return CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS; + + case CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST: + return CEC_OPCODE_SET_SYSTEM_AUDIO_MODE; + + default: + break; + } + + return CEC_OPCODE_NONE; +} + +#endif // __HDMI_CEC_TYPES_H__ diff --git a/src/driver/volume.cpp b/src/driver/volume.cpp index 1548ae973..69c377cb3 100644 --- a/src/driver/volume.cpp +++ b/src/driver/volume.cpp @@ -33,13 +33,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include #include #include @@ -113,10 +113,6 @@ void CVolume::setVolume(const neutrino_msg_t key) neutrino_msg_data_t data = 0; uint64_t timeoutEnd = 0; -#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE - if (g_settings.hdmi_cec_volume) - g_settings.current_volume = hdmi_cec::getInstance()->GetVolume(); -#endif int vol = g_settings.current_volume; do { @@ -140,9 +136,9 @@ void CVolume::setVolume(const neutrino_msg_t key) } else if (g_settings.hdmi_cec_volume) { - (dir > 0) ? hdmi_cec::getInstance()->vol_up() : hdmi_cec::getInstance()->vol_down(); + (dir > 0) ? g_hdmicec->vol_up() : g_hdmicec->vol_down(); do_vol = false; - g_settings.current_volume = hdmi_cec::getInstance()->GetVolume(); + g_settings.current_volume = g_hdmicec->GetVolume(); printf("Volume: %d\n", g_settings.current_volume); #endif } else diff --git a/src/global.h b/src/global.h index 51bc7b665..a222435a7 100644 --- a/src/global.h +++ b/src/global.h @@ -108,6 +108,11 @@ NEUTRINO_CPP CRadioText *g_Radiotext; class CRadioTextGUI; NEUTRINO_CPP CRadioTextGUI *g_RadiotextWin; +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE +class hdmi_cec; +NEUTRINO_CPP hdmi_cec *g_hdmicec; +#endif + #ifndef DISABLE_GUI_MOUNT #define ENABLE_GUI_MOUNT #endif diff --git a/src/gui/audiomute.cpp b/src/gui/audiomute.cpp index 361c95a35..868e6aa24 100644 --- a/src/gui/audiomute.cpp +++ b/src/gui/audiomute.cpp @@ -30,14 +30,11 @@ #endif #include #include -#include #include +#include #include #include #include - -#include - #include CAudioMute::CAudioMute():CComponentsPicture(0, 0, NEUTRINO_ICON_MUTED) @@ -70,8 +67,8 @@ void CAudioMute::AudioMute(int newValue, bool isEvent) #endif neutrino->setCurrentMuted(newValue); #if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE - if (g_settings.hdmi_cec_volume) - hdmi_cec::getInstance()->toggle_mute(); + if (g_settings.hdmi_cec_volume && !doInit) + g_hdmicec->toggle_mute(); else #endif g_Zapit->muteAudio(newValue); diff --git a/src/gui/cec_setup.cpp b/src/gui/cec_setup.cpp index f87a790db..f0135d0f5 100644 --- a/src/gui/cec_setup.cpp +++ b/src/gui/cec_setup.cpp @@ -45,9 +45,12 @@ #include #include +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE +#include +#else #include - extern cVideo *videoDecoder; +#endif CCECSetup::CCECSetup() { @@ -55,6 +58,8 @@ CCECSetup::CCECSetup() cec1 = NULL; cec2 = NULL; cec3 = NULL; + cec4 = NULL; + cec5 = NULL; } CCECSetup::~CCECSetup() @@ -75,6 +80,7 @@ int CCECSetup::exec(CMenuTarget* parent, const std::string &/*actionKey*/) return res; } +#if !HAVE_ARM_HARDWARE && !HAVE_MIPS_HARDWARE #define VIDEOMENU_HDMI_CEC_MODE_OPTION_COUNT 3 const CMenuOptionChooser::keyval VIDEOMENU_HDMI_CEC_MODE_OPTIONS[VIDEOMENU_HDMI_CEC_MODE_OPTION_COUNT] = { @@ -82,6 +88,7 @@ const CMenuOptionChooser::keyval VIDEOMENU_HDMI_CEC_MODE_OPTIONS[VIDEOMENU_HDMI_ { VIDEO_HDMI_CEC_MODE_TUNER , LOCALE_VIDEOMENU_HDMI_CEC_MODE_TUNER }, { VIDEO_HDMI_CEC_MODE_RECORDER , LOCALE_VIDEOMENU_HDMI_CEC_MODE_RECORDER } }; +#endif #if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE #define VIDEOMENU_HDMI_CEC_VOL_OPTION_COUNT 3 @@ -100,15 +107,24 @@ int CCECSetup::showMenu() cec->addIntroItems(LOCALE_VIDEOMENU_HDMI_CEC); //cec - CMenuOptionChooser *cec_ch = new CMenuOptionChooser(LOCALE_VIDEOMENU_HDMI_CEC_MODE, &g_settings.hdmi_cec_mode, VIDEOMENU_HDMI_CEC_MODE_OPTIONS, VIDEOMENU_HDMI_CEC_MODE_OPTION_COUNT, true, this); - cec_ch->setHint("", LOCALE_MENU_HINT_CEC_MODE); cec1 = new CMenuOptionChooser(LOCALE_VIDEOMENU_HDMI_CEC_VIEW_ON, &g_settings.hdmi_cec_view_on, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, g_settings.hdmi_cec_mode != VIDEO_HDMI_CEC_MODE_OFF, this); cec1->setHint("", LOCALE_MENU_HINT_CEC_VIEW_ON); cec2 = new CMenuOptionChooser(LOCALE_VIDEOMENU_HDMI_CEC_STANDBY, &g_settings.hdmi_cec_standby, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, g_settings.hdmi_cec_mode != VIDEO_HDMI_CEC_MODE_OFF, this); cec2->setHint("", LOCALE_MENU_HINT_CEC_STANDBY); #if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE - cec3 = new CMenuOptionChooser(LOCALE_VIDEOMENU_HDMI_CEC_VOLUME, &g_settings.hdmi_cec_volume, VIDEOMENU_HDMI_CEC_VOL_OPTIONS, VIDEOMENU_HDMI_CEC_VOL_OPTION_COUNT, g_settings.hdmi_cec_mode != VIDEO_HDMI_CEC_MODE_OFF, this); - cec3->setHint("", LOCALE_MENU_HINT_CEC_VOLUME); + if (g_settings.hdmi_cec_mode > 0) + g_settings.hdmi_cec_mode = 1; + CMenuOptionChooser *cec_ch = new CMenuOptionChooser(LOCALE_VIDEOMENU_HDMI_CEC_MODE, &g_settings.hdmi_cec_mode, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true, this); + cec_ch->setHint("", LOCALE_MENU_HINT_CEC_MODE); + cec3 = new CMenuOptionChooser(LOCALE_VIDEOMENU_HDMI_CEC_WAKEUP, &g_settings.hdmi_cec_wakeup, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, g_settings.hdmi_cec_mode != VIDEO_HDMI_CEC_MODE_OFF, this); + cec3->setHint("", LOCALE_MENU_HINT_CEC_WAKEUP); + cec4 = new CMenuOptionChooser(LOCALE_VIDEOMENU_HDMI_CEC_SLEEP, &g_settings.hdmi_cec_sleep, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, g_settings.hdmi_cec_mode != VIDEO_HDMI_CEC_MODE_OFF, this); + cec4->setHint("", LOCALE_MENU_HINT_CEC_SLEEP); + cec5 = new CMenuOptionChooser(LOCALE_VIDEOMENU_HDMI_CEC_VOLUME, &g_settings.hdmi_cec_volume, VIDEOMENU_HDMI_CEC_VOL_OPTIONS, VIDEOMENU_HDMI_CEC_VOL_OPTION_COUNT, g_settings.hdmi_cec_mode != VIDEO_HDMI_CEC_MODE_OFF, this); + cec5->setHint("", LOCALE_MENU_HINT_CEC_VOLUME); +#else + CMenuOptionChooser *cec_ch = new CMenuOptionChooser(LOCALE_VIDEOMENU_HDMI_CEC_MODE, &g_settings.hdmi_cec_mode, VIDEOMENU_HDMI_CEC_MODE_OPTIONS, VIDEOMENU_HDMI_CEC_MODE_OPTION_COUNT, true, this); + cec_ch->setHint("", LOCALE_MENU_HINT_CEC_MODE); #endif cec->addItem(cec_ch); @@ -118,6 +134,8 @@ int CCECSetup::showMenu() cec->addItem(cec2); #if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE cec->addItem(cec3); + cec->addItem(cec4); + cec->addItem(cec5); #endif int res = cec->exec(NULL, ""); @@ -129,12 +147,19 @@ int CCECSetup::showMenu() void CCECSetup::setCECSettings() { printf("[neutrino CEC Settings] %s init CEC settings...\n", __FUNCTION__); +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE + if (g_hdmicec == NULL) + g_hdmicec = new hdmi_cec(); + g_hdmicec->SetCECAutoStandby(g_settings.hdmi_cec_standby == 1); + g_hdmicec->SetCECAutoView(g_settings.hdmi_cec_view_on == 1); + g_hdmicec->SetAudioDestination(g_settings.hdmi_cec_volume); + g_hdmicec->SetCECMode((VIDEO_HDMI_CEC_MODE)g_settings.hdmi_cec_mode); +#else videoDecoder->SetCECAutoStandby(g_settings.hdmi_cec_standby == 1); videoDecoder->SetCECAutoView(g_settings.hdmi_cec_view_on == 1); -#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE videoDecoder->SetAudioDestination(g_settings.hdmi_cec_volume); -#endif videoDecoder->SetCECMode((VIDEO_HDMI_CEC_MODE)g_settings.hdmi_cec_mode); +#endif } bool CCECSetup::changeNotify(const neutrino_locale_t OptionName, void * /*data*/) @@ -146,27 +171,43 @@ bool CCECSetup::changeNotify(const neutrino_locale_t OptionName, void * /*data*/ cec2->setActive(g_settings.hdmi_cec_mode != VIDEO_HDMI_CEC_MODE_OFF); #if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE cec3->setActive(g_settings.hdmi_cec_mode != VIDEO_HDMI_CEC_MODE_OFF); + cec4->setActive(g_settings.hdmi_cec_mode != VIDEO_HDMI_CEC_MODE_OFF); + cec5->setActive(g_settings.hdmi_cec_mode != VIDEO_HDMI_CEC_MODE_OFF); #endif +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE + g_hdmicec->SetCECMode((VIDEO_HDMI_CEC_MODE)g_settings.hdmi_cec_mode); +#else videoDecoder->SetCECMode((VIDEO_HDMI_CEC_MODE)g_settings.hdmi_cec_mode); +#endif } else if (ARE_LOCALES_EQUAL(OptionName, LOCALE_VIDEOMENU_HDMI_CEC_STANDBY)) { +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE + g_hdmicec->SetCECAutoStandby(g_settings.hdmi_cec_standby == 1); +#else videoDecoder->SetCECAutoStandby(g_settings.hdmi_cec_standby == 1); +#endif } else if (ARE_LOCALES_EQUAL(OptionName, LOCALE_VIDEOMENU_HDMI_CEC_VIEW_ON)) { +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE + g_hdmicec->SetCECAutoView(g_settings.hdmi_cec_view_on == 1); +#else videoDecoder->SetCECAutoView(g_settings.hdmi_cec_view_on == 1); +#endif } +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE else if (ARE_LOCALES_EQUAL(OptionName, LOCALE_VIDEOMENU_HDMI_CEC_VOLUME)) { #if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE if (g_settings.hdmi_cec_mode != VIDEO_HDMI_CEC_MODE_OFF) { g_settings.current_volume = 100; - videoDecoder->SetAudioDestination(g_settings.hdmi_cec_volume); + g_hdmicec->SetAudioDestination(g_settings.hdmi_cec_volume); } #endif } +#endif return false; } diff --git a/src/gui/cec_setup.h b/src/gui/cec_setup.h index c5aa3f1b5..9160e1827 100644 --- a/src/gui/cec_setup.h +++ b/src/gui/cec_setup.h @@ -36,7 +36,7 @@ class CCECSetup : public CMenuTarget, CChangeObserver { private: - CMenuOptionChooser *cec1, *cec2, *cec3; + CMenuOptionChooser *cec1, *cec2, *cec3, *cec4, *cec5; int width; diff --git a/src/gui/miscsettings_menu.cpp b/src/gui/miscsettings_menu.cpp index 13c223f7f..2661e0abb 100644 --- a/src/gui/miscsettings_menu.cpp +++ b/src/gui/miscsettings_menu.cpp @@ -33,7 +33,7 @@ #include #include #include -#include "gui/weather_setup.h" +#include #include #include @@ -56,12 +56,16 @@ #include #include +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE +#include +#else #include +extern cVideo *videoDecoder; +#endif #include extern CPlugins *g_Plugins; -extern cVideo *videoDecoder; CMiscMenue::CMiscMenue() { @@ -786,14 +790,20 @@ bool CMiscMenue::changeNotify(const neutrino_locale_t OptionName, void */*data*/ { g_settings.hdmi_cec_standby = 1; g_settings.hdmi_cec_view_on = 1; +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE + g_settings.hdmi_cec_mode = VIDEO_HDMI_CEC_MODE_OFF; + } + g_hdmicec->SetCECAutoStandby(g_settings.hdmi_cec_standby == 1); + g_hdmicec->SetCECAutoView(g_settings.hdmi_cec_view_on == 1); + g_hdmicec->SetAudioDestination(g_settings.hdmi_cec_volume); + g_hdmicec->SetCECMode((VIDEO_HDMI_CEC_MODE)g_settings.hdmi_cec_mode); +#else g_settings.hdmi_cec_mode = VIDEO_HDMI_CEC_MODE_TUNER; } videoDecoder->SetCECAutoStandby(g_settings.hdmi_cec_standby == 1); videoDecoder->SetCECAutoView(g_settings.hdmi_cec_view_on == 1); -#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE - videoDecoder->SetAudioDestination(g_settings.hdmi_cec_volume); -#endif videoDecoder->SetCECMode((VIDEO_HDMI_CEC_MODE)g_settings.hdmi_cec_mode); +#endif } else if (ARE_LOCALES_EQUAL(OptionName, LOCALE_MISCSETTINGS_CHANNELLIST_ENABLESDT)) { diff --git a/src/gui/update.cpp b/src/gui/update.cpp index 1dff60fda..e11a17a8e 100644 --- a/src/gui/update.cpp +++ b/src/gui/update.cpp @@ -82,8 +82,7 @@ #include #if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE -#include -extern cVideo *videoDecoder; +#include #endif #include @@ -376,6 +375,7 @@ bool CFlashUpdate::selectHttpImage(void) } } #endif + #if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE if (gotImage && (filename.substr(filename.find_last_of(".") + 1) == "tgz" || filename.substr(filename.find_last_of(".") + 1) == "zip")) { @@ -729,7 +729,7 @@ int CFlashUpdate::exec(CMenuTarget *parent, const std::string &actionKey) { if (g_settings.hdmi_cec_standby) { - videoDecoder->SetCECMode((VIDEO_HDMI_CEC_MODE)0); + g_hdmicec->SetCECMode((VIDEO_HDMI_CEC_MODE)0); } std::string startup_new("/boot/"); startup_new += g_info.hw_caps->startup_file; diff --git a/src/neutrino.cpp b/src/neutrino.cpp index 4294dfe35..a10ec7cd9 100644 --- a/src/neutrino.cpp +++ b/src/neutrino.cpp @@ -63,6 +63,9 @@ #include #include #include +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE +#include +#endif #if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE #include "gui/psisetup.h" @@ -467,10 +470,12 @@ int CNeutrinoApp::loadSetup(const char *fname) #endif // hdmi cec - g_settings.hdmi_cec_mode = configfile.getInt32("hdmi_cec_mode", 0); - g_settings.hdmi_cec_view_on = configfile.getInt32("hdmi_cec_view_on", 0); - g_settings.hdmi_cec_standby = configfile.getInt32("hdmi_cec_standby", 0); - g_settings.hdmi_cec_volume = configfile.getInt32("hdmi_cec_volume", 0); + g_settings.hdmi_cec_mode = configfile.getInt32("hdmi_cec_mode", 1); + g_settings.hdmi_cec_view_on = configfile.getInt32("hdmi_cec_view_on", 1); + g_settings.hdmi_cec_sleep = configfile.getInt32("hdmi_cec_sleep", 1); + g_settings.hdmi_cec_standby = configfile.getInt32("hdmi_cec_standby", 1); + g_settings.hdmi_cec_volume = configfile.getInt32("hdmi_cec_volume", 1); + g_settings.hdmi_cec_wakeup = configfile.getInt32("hdmi_cec_wakeup", 1); // volume g_settings.current_volume = configfile.getInt32("current_volume", 75); @@ -1571,8 +1576,10 @@ void CNeutrinoApp::saveSetup(const char *fname) // hdmi cec configfile.setInt32("hdmi_cec_mode", g_settings.hdmi_cec_mode); configfile.setInt32("hdmi_cec_view_on", g_settings.hdmi_cec_view_on); + configfile.setInt32("hdmi_cec_sleep", g_settings.hdmi_cec_sleep); configfile.setInt32("hdmi_cec_standby", g_settings.hdmi_cec_standby); configfile.setInt32("hdmi_cec_volume", g_settings.hdmi_cec_volume); + configfile.setInt32("hdmi_cec_wakeup", g_settings.hdmi_cec_wakeup); // volume configfile.setInt32( "current_volume", g_settings.current_volume ); @@ -4485,6 +4492,11 @@ int CNeutrinoApp::handleMsg(const neutrino_msg_t _msg, neutrino_msg_data_t data) } else if( msg == NeutrinoMessages::STANDBY_ON ) { if( mode != NeutrinoModes::mode_standby ) { +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE + if (data) + standbyModeFromCEC( true ); + else +#endif standbyMode( true ); } g_RCInput->clearRCMsg(); @@ -4492,6 +4504,11 @@ int CNeutrinoApp::handleMsg(const neutrino_msg_t _msg, neutrino_msg_data_t data) } else if( msg == NeutrinoMessages::STANDBY_OFF ) { if( mode == NeutrinoModes::mode_standby ) { +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE + if (data) + standbyModeFromCEC( false ); + else +#endif standbyMode( false ); } g_RCInput->clearRCMsg(); @@ -4657,13 +4674,21 @@ int CNeutrinoApp::handleMsg(const neutrino_msg_t _msg, neutrino_msg_data_t data) } else if (msg == NeutrinoMessages::EVT_HDMI_CEC_VIEW_ON) { if(g_settings.hdmi_cec_view_on) +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE + g_hdmicec->SetCECAutoView(g_settings.hdmi_cec_view_on); +#else videoDecoder->SetCECAutoView(g_settings.hdmi_cec_view_on); +#endif return messages_return::handled; } else if (msg == NeutrinoMessages::EVT_HDMI_CEC_STANDBY) { if(g_settings.hdmi_cec_standby) - videoDecoder->SetCECAutoStandby(g_settings.hdmi_cec_standby); +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE + g_hdmicec->SetCECAutoStandby(g_settings.hdmi_cec_standby); +#else + videoDecoder->SetCECAutoStandby(g_settings.hdmi_cec_standby); +#endif return messages_return::handled; } @@ -4934,6 +4959,9 @@ void CNeutrinoApp::tvMode( bool rezap ) if( mode == NeutrinoModes::mode_standby ) { CVFD::getInstance()->setMode(CVFD::MODE_TVRADIO); videoDecoder->Standby(false); +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE + g_hdmicec->SetCECState(false); +#endif } #if ENABLE_PIP @@ -5010,8 +5038,16 @@ void CNeutrinoApp::AVInputMode(bool bOnOff) (void)bOnOff; // avoid compiler warning #endif // !HAVE_CST_HARDWARE && !HAVE_GENERIC_HARDWARE } +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE +void CNeutrinoApp::standbyModeFromCEC( bool bOnOff ) +{ + standbyMode(bOnOff, false, true); +} +void CNeutrinoApp::standbyMode( bool bOnOff, bool fromDeepStandby, bool fromcec ) +#else void CNeutrinoApp::standbyMode( bool bOnOff, bool fromDeepStandby ) +#endif { //static bool wasshift = false; INFO("%s", bOnOff ? "ON" : "OFF" ); @@ -5059,6 +5095,10 @@ void CNeutrinoApp::standbyMode( bool bOnOff, bool fromDeepStandby ) videoDecoder->Standby(true); +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE + if (!fromcec) + g_hdmicec->SetCECState(true); +#endif g_Sectionsd->setServiceChanged(0, false); g_Sectionsd->setPauseScanning(!fromDeepStandby); @@ -5116,6 +5156,10 @@ void CNeutrinoApp::standbyMode( bool bOnOff, bool fromDeepStandby ) if (cpuFreq) cpuFreq->SetCpuFreq(g_settings.cpufreq * 1000 * 1000); videoDecoder->Standby(false); +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE + if (!fromcec) + g_hdmicec->SetCECState(false); +#endif CEpgScan::getInstance()->Stop(); CSectionsdClient::CurrentNextInfo dummy; g_InfoViewer->getEPG(0, dummy); @@ -5352,7 +5396,11 @@ int CNeutrinoApp::exec(CMenuTarget* parent, const std::string & actionKey) } // else if (actionKey=="restart") // { +//#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE +// g_hdmicec->SetCECMode((VIDEO_HDMI_CEC_MODE)0); +//#else // videoDecoder->SetCECMode((VIDEO_HDMI_CEC_MODE)0); +//#endif // ExitRun(CNeutrinoApp::EXIT_RESTART); // returnval = menu_return::RETURN_NONE; // } @@ -5462,7 +5510,11 @@ int CNeutrinoApp::exec(CMenuTarget* parent, const std::string & actionKey) else if (actionKey=="restart") { //usage of slots from any classes OnBeforeRestart(); - +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE + g_hdmicec->SetCECMode((VIDEO_HDMI_CEC_MODE)0); +#else + videoDecoder->SetCECMode((VIDEO_HDMI_CEC_MODE)0); +#endif //cleanup progress bar cache CProgressBarCache::pbcClear(); @@ -5624,8 +5676,13 @@ void stop_daemons(bool stopall, bool for_flash) #endif tuxtx_stop_subtitle(); printf("zapit shutdown\n"); - if(!for_flash && !stopall && g_settings.hdmi_cec_mode && g_settings.hdmi_cec_standby){ - videoDecoder->SetCECMode((VIDEO_HDMI_CEC_MODE)0); + if(!for_flash && !stopall && g_settings.hdmi_cec_mode && g_settings.hdmi_cec_standby) + { +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE + g_hdmicec->SetCECMode((VIDEO_HDMI_CEC_MODE)0); +#else + videoDecoder->SetCECMode((VIDEO_HDMI_CEC_MODE)0); +#endif } if(InfoClock) delete InfoClock; diff --git a/src/neutrino.h b/src/neutrino.h index 76d153027..08952cb1b 100644 --- a/src/neutrino.h +++ b/src/neutrino.h @@ -118,7 +118,12 @@ private: void tvMode( bool rezap = true ); void radioMode( bool rezap = true ); void AVInputMode( bool bOnOff ); +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE + void standbyModeFromCEC( bool bOnOff ); + void standbyMode( bool bOnOff, bool fromDeepStandby = false, bool fromcec = false ); +#else void standbyMode( bool bOnOff, bool fromDeepStandby = false ); +#endif void getAnnounceEpgName(CTimerd::RecordingInfo * eventinfo, std::string &name); void ExitRun(int can_shutdown = 0); diff --git a/src/nhttpd/tuxboxapi/controlapi.cpp b/src/nhttpd/tuxboxapi/controlapi.cpp index 8790be89f..f432a8650 100644 --- a/src/nhttpd/tuxboxapi/controlapi.cpp +++ b/src/nhttpd/tuxboxapi/controlapi.cpp @@ -51,10 +51,14 @@ extern CPictureViewer *g_PicViewer; // nhttpd #include "neutrinoapi.h" #include "controlapi.h" -#include #include +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE +#include +#else +#include extern cVideo * videoDecoder; +#endif extern CPlugins *g_Plugins;//for relodplugins extern CBouquetManager *g_bouquetManager; @@ -589,7 +593,11 @@ void CControlAPI::StandbyCGI(CyhookHandler *hh) { //dont use CEC with standbyoff (TV off) --- use: control/standby?off&cec=off if(g_settings.hdmi_cec_standby && CEC_HDMI_off){ +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE + g_hdmicec->SetCECAutoStandby(0); +#else videoDecoder->SetCECAutoStandby(0); +#endif } if(CNeutrinoApp::getInstance()->getMode() != 4) @@ -604,7 +612,11 @@ void CControlAPI::StandbyCGI(CyhookHandler *hh) { //dont use CEC with with view on (TV on) --- use: control/standby?off&cec=off if(g_settings.hdmi_cec_view_on && CEC_HDMI_off){ +#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE + g_hdmicec->SetCECAutoView(0); +#else videoDecoder->SetCECAutoView(0); +#endif } NeutrinoAPI->Zapit->setStandby(false); diff --git a/src/system/locals.h b/src/system/locals.h index abf13badd..39eb56bf9 100644 --- a/src/system/locals.h +++ b/src/system/locals.h @@ -1328,9 +1328,11 @@ typedef enum LOCALE_MENU_HINT_CA_INIT, LOCALE_MENU_HINT_CACHE_TXT, LOCALE_MENU_HINT_CEC_MODE, + LOCALE_MENU_HINT_CEC_SLEEP, LOCALE_MENU_HINT_CEC_STANDBY, LOCALE_MENU_HINT_CEC_VIEW_ON, LOCALE_MENU_HINT_CEC_VOLUME, + LOCALE_MENU_HINT_CEC_WAKEUP, LOCALE_MENU_HINT_CHANNELLIST_ADDITIONAL, LOCALE_MENU_HINT_CHANNELLIST_ENABLESDT, LOCALE_MENU_HINT_CHANNELLIST_EPG_ALIGN, @@ -2894,6 +2896,7 @@ typedef enum LOCALE_VIDEOMENU_HDMI_CEC_MODE_OFF, LOCALE_VIDEOMENU_HDMI_CEC_MODE_RECORDER, LOCALE_VIDEOMENU_HDMI_CEC_MODE_TUNER, + LOCALE_VIDEOMENU_HDMI_CEC_SLEEP, LOCALE_VIDEOMENU_HDMI_CEC_STANDBY, LOCALE_VIDEOMENU_HDMI_CEC_VIEW_ON, LOCALE_VIDEOMENU_HDMI_CEC_VOL_AUDIOSYSTEM, diff --git a/src/system/locals_intern.h b/src/system/locals_intern.h index 37de3d68f..e3a994e8a 100644 --- a/src/system/locals_intern.h +++ b/src/system/locals_intern.h @@ -1328,9 +1328,11 @@ const char * locale_real_names[] = "menu.hint_ca_init", "menu.hint_cache_txt", "menu.hint_cec_mode", + "menu.hint_cec_sleep", "menu.hint_cec_standby", "menu.hint_cec_view_on", "menu.hint_cec_volume", + "menu.hint_cec_wakeup", "menu.hint_channellist_additional", "menu.hint_channellist_enablesdt", "menu.hint_channellist_epg_align", @@ -2894,6 +2896,7 @@ const char * locale_real_names[] = "videomenu.hdmi_cec_mode_off", "videomenu.hdmi_cec_mode_recorder", "videomenu.hdmi_cec_mode_tuner", + "videomenu.hdmi_cec_sleep", "videomenu.hdmi_cec_standby", "videomenu.hdmi_cec_view_on", "videomenu.hdmi_cec_vol_audiosystem", diff --git a/src/system/settings.h b/src/system/settings.h index e9eecca8a..08df76db4 100644 --- a/src/system/settings.h +++ b/src/system/settings.h @@ -372,8 +372,10 @@ struct SNeutrinoSettings // hdmi cec int hdmi_cec_mode; int hdmi_cec_view_on; + int hdmi_cec_sleep; int hdmi_cec_standby; int hdmi_cec_volume; + int hdmi_cec_wakeup; // volume char current_volume;