#CXX=clang++-9
#LD=clang++-9
-vomp_options += -DIPV6
LDFLAGS = -fuse-ld=gold $(PICTURES)
+#-fuse-ld=gold
+
+vomp_options += -DIPV6
LIBPATHS = -L/opt/vc/lib -L/usr/lib/arm-linux-gnueabihf
LIBS = -lpthread -lrt -lbrcmEGL -lbrcmOpenVG -lopenmaxil -lbcm_host -lavformat -lavcodec -lavutil -lavresample
LIBS += -ldl -lfontconfig -lfreetype -lMagick++-6.Q16
along with VOMP. If not, see <https://www.gnu.org/licenses/>.
*/
+// FIXME rename to Control and move stuff from main to here
+
+
#include "command.h"
#ifdef WIN32
-#include "remotewin.h"
+#include "inputManwin.h"
#endif
#ifdef __ANDROID__
-#include "remoteandroid.h"
+#include "inputManandroid.h"
#endif
#include "led.h"
#include "wol.h"
#include "vconnect.h"
#include "message.h"
+#include "inputman.h"
#include "input.h"
#include "vinfo.h"
#include "boxx.h"
Command::~Command()
{
+ flushMessageQueue();
instance = NULL;
}
logger = Log::getInstance();
boxstack = BoxStack::getInstance();
- remote = Input::getInstance();
+ inputMan = InputMan::getInstance();
- remote->InitHWCListwithDefaults();
-
- if (!logger || !boxstack || !remote)
+ if (!logger || !boxstack || !inputMan)
{
initted = false;
return 0;
vconnect->run();
}
- // Start remote thread loop
- remote->start();
-
- // Start method 2 of getting commands in...
- udp.run(this);
// FIXME Input::NA_SIGNAL is possibly obsolete now
std::unique_lock<std::mutex> lockWrapper(messageQueueMutex); // locks. unlocks on out-of-scope
+ inputMan->start();
+
+ // Start method 2 of getting commands in... // FIXME move this inside input
+ udp.run(this);
+
while(irun)
{
messageQueueCond.wait(lockWrapper, [&] { return !irun || !messages.empty(); });
}
}
- remote->stop();
+ inputMan->stop();
boxstack->removeAllExceptWallpaper();
boxstack->remove(wallpaper);
switch(button)
{
- case Input::DF_LEFT:
- case Input::DF_RIGHT:
case Input::VOLUMEUP:
case Input::VOLUMEDOWN:
{
- if (remote->handlesVolume())
+ if (inputMan->handlesVolume()) // CEC volume handler?
{
- if (button==Input::DF_LEFT || button==Input::VOLUMEDOWN)
- remote->volumeDown();
+ if (button == Input::VOLUMEDOWN)
+ inputMan->volumeDown();
else
- remote->volumeUp();
+ inputMan->volumeUp();
}
else
{
}
case Input::MUTE:
{
- if (remote->handlesVolume())
+ if (inputMan->handlesVolume())
{
- remote->volumeMute();
+ inputMan->volumeMute();
}
else
{
{
Video::getInstance()->signalOn();
Led::getInstance()->on();
- Input::getInstance()->changePowerState(true);
+ InputMan::getInstance()->changePowerState(true);
isStandby = false;
VConnect* vconnect = new VConnect(server);
logger->unsetExternLogger();
VDR::getInstance()->disconnect();
Led::getInstance()->off();
- Input::getInstance()->changePowerState(false);
+ InputMan::getInstance()->changePowerState(false);
isStandby = true;
Sleeptimer::getInstance()->shutdown();
#ifdef WIN32
Osd::getInstance()->shutdown();
Audio::getInstance()->shutdown();
Video::getInstance()->shutdown();
- Input::getInstance()->shutdown();
+ InputMan::getInstance()->shutdown();
reboot(LINUX_REBOOT_CMD_RESTART);
// if reboot is not allowed -> stop
#endif
video->shutdown();
- remote->shutdown(); // need on raspberry shut not do any harm, hopefully
- remote->init(RemoteStartDev);
+ inputMan->shutdown(); // need on raspberry shut not do any harm, hopefully
+ inputMan->init(); // FIXME this breaks badly now
// Get video and osd back up with the new mode
if (!strcmp(config, "PAL"))
{
if (!STRCASECMP(config, "On"))
{
- logger->log("Command", Log::INFO, "Shutdown VDR when shutting down vomp");
+ logger->log("Command", Log::INFO, "Shutdown VDR when shutting down vomp");
vdr->setVDRShutdown(true);
}
else if (!STRCASECMP(config, "Off"))
vdr->setVDRShutdown(false); // Default
}
- // Set remote type
-
- config = vdr->configLoad("General", "Remote type");
-
- if (config)
- {
- if (!STRCASECMP(config, "New"))
- {
- logger->log("Command", Log::INFO, "Switching to New remote type");
- remote->setRemoteType(Input::NEWREMOTE);
- }
- else
- {
- logger->log("Command", Log::INFO, "Switching to Old remote type");
- remote->setRemoteType(Input::OLDREMOTE);
- }
- delete[] config;
- }
- else
- {
- logger->log("Command", Log::INFO, "Config General/Remote type not found");
- remote->setRemoteType(Input::OLDREMOTE);
- }
-
-
-
// Get TV aspect ratio
config = vdr->configLoad("TV", "Aspect");
/* device dependend config */
audio->loadOptionsfromServer(vdr);
video->loadOptionsfromServer(vdr);
- remote->loadOptionsfromServer(vdr);
+ inputMan->loadOptionsfromServer(vdr);
video->executePendingModeChanges();
// config done
class VConnect;
class Message;
-class Input;
+class InputMan;
class Boxx;
class BoxStack;
class Log;
Log* logger;
BoxStack* boxstack;
- Input* remote;
+ InputMan* inputMan;
bool initted{};
bool irun{};
#define VOMP_LINUX_CLOCK CLOCK_MONOTONIC
#endif
-#ifdef VOMP_PLATTFORM_MVP
+#ifdef VOMP_PLATTFORM_MVP // FIXME OBSOLETE
#define Remote_TYPE RemoteMVP
#define RemoteStartDev "/dev/rawir"
#define Led_TYPE
#include "log.h"
#include "vdr.h"
#include "wtabbar.h"
+#include "inputman.h"
#include "input.h"
-Input* Input::instance = NULL;
-
Input::Input()
{
- if (instance) return;
- instance = this;
- remoteType = OLDREMOTE;
learnmode = NOLEARNMODE;
}
Input::~Input()
{
- instance = NULL;
-}
-
-Input* Input::getInstance()
-{
- return instance;
-}
-
-void Input::setRemoteType(UCHAR newType)
-{
- if ((newType != OLDREMOTE) && (newType != NEWREMOTE)) return;
- remoteType = newType;
}
void Input::EnterLearningMode(UCHAR command)
InitHWCListwithDefaults();
}
-
+/*
UCHAR Input::TranslateHWCFixed(ULLONG code)
{
switch (code)
return LEFT;
case RIGHT:
return RIGHT;
- case DF_DOWN:
- return DOWN;
- case DF_UP:
- return UP;
- case DF_LEFT:
- return LEFT;
- case DF_RIGHT:
- return RIGHT;
case MENU:
return MENU;
case BACK:
return NA_UNKNOWN;
}
}
+*/
const char* Input::HardcodedTranslateStr(UCHAR command)
{
}
}
-UCHAR Input::TranslateHWCList(ULLONG code)
+UCHAR Input::TranslateHWCList(int code)
{
if (learnmode != NOLEARNMODE)
{
}
}
-UCHAR Input::TranslateHWC(ULLONG code)
+UCHAR Input::TranslateHWC(int code)
{
UCHAR ret = TranslateHWCFixed(code);
if (ret == NA_UNKNOWN)
VDR::getInstance()->configSave("General","RemoteKeyNum",buffer);
}
-
-void Input::InitHWCListwithDefaults()
-{
- translist[VOLUMEUP] = VOLUMEUP;
- translist[VOLUMEDOWN] = VOLUMEDOWN;
- translist[CHANNELUP] = CHANNELUP;
- translist[CHANNELDOWN] = CHANNELDOWN;
-
- // Common buttons
- translist[ZERO] = ZERO;
- translist[ONE] = ONE;
- translist[TWO] = TWO;
- translist[THREE] = THREE;
- translist[FOUR] = FOUR;
- translist[FIVE] = FIVE;
- translist[SIX] = SIX;
- translist[SEVEN] = SEVEN;
- translist[EIGHT] = EIGHT;
- translist[NINE] = NINE;
- translist[POWER] = POWER;
- translist[GO] = GO;
- translist[RED] = RED;
- translist[GREEN] = GREEN;
- translist[YELLOW] = YELLOW;
- translist[BLUE] = BLUE;
-
- translist[MUTE] = MUTE;
- translist[RADIO] = RADIO;
- translist[REVERSE] = REVERSE;
- translist[FORWARD] = FORWARD;
- translist[RECORD] = RECORD;
- translist[STOP] = STOP;
- translist[PAUSE] = PAUSE;
- translist[PLAY] = PLAY;
- translist[SKIPBACK] = SKIPBACK;
- translist[SKIPFORWARD] = SKIPFORWARD;
-
- // Old remote only
- translist[FULL] = FULL;
-
- // New remote only
- translist[TV] = TV;
- translist[VIDEOS] = VIDEOS;
- translist[MUSIC] = MUSIC;
- translist[PICTURES] = PICTURES;
- translist[GUIDE] = GUIDE;
- translist[PREVCHANNEL] = PREVCHANNEL;
- translist[STAR] = STAR;
- translist[HASH] = HASH;
-}
-
-const char* Input::CommandDesc(UCHAR number)
-{
- switch (number)
- {
- case VOLUMEUP:
- return tr("Volume Up");
-
- case VOLUMEDOWN:
- return tr("Volume Down");
- case CHANNELUP:
- return tr("Channel up");
- case CHANNELDOWN:
- return tr("Channel down");
- case ZERO:
- return "0";
- case ONE:
- return "1";
- case TWO:
- return "2";
- case THREE:
- return "3";
- case FOUR:
- return "4";
- case FIVE:
- return "5";
- case SIX:
- return "6";
- case SEVEN:
- return "7";
- case EIGHT:
- return "8";
- case NINE:
- return "9";
- case POWER:
- return tr("Power");
- case GO:
- return tr("Go");
- case BACK:
- return tr("Back");
- case MENU:
- return tr("Menu");
- case RED:
- return tr("Red");
- case GREEN:
- return tr("Green");
- case YELLOW:
- return tr("Yellow");
- case BLUE:
- return tr("Blue");
- case MUTE:
- return tr("Mute");
- case RADIO:
- return tr("Radio");
- case REVERSE:
- return tr("Reverse");
- case PLAY:
- return tr("Play");
- case FORWARD:
- return tr("Forward");
- case RECORD:
- return tr("Record");
- case STOP:
- return tr("Stop");
- case PAUSE:
- return tr("Pause");
- case SKIPBACK:
- return tr("Skip back");
- case SKIPFORWARD:
- return tr("Skip forward");
- case OK:
- return tr("Ok");
- case FULL:
- return tr("Fullscreen");
- case TV:
- return tr("TV");
- case VIDEOS:
- return tr("Videos");
- case MUSIC:
- return tr("Music");
- case PICTURES:
- return tr("Pictures");
- case GUIDE:
- return tr("Guide");
- case UP:
- return tr("Up");
- case DOWN:
- return tr("Down");
- case LEFT:
- return tr("Left");
- case RIGHT:
- return tr("Right");
- case PREVCHANNEL:
- return tr("Previous Channel");
- case STAR:
- return tr("Star");
- case HASH:
- return tr("Hash");
- case PLAYPAUSE:
- return tr("Play/Pause");
-
- default:
- return NULL;
- }
-}
-
char* Input::HCWDesc(ULLONG hcw)
{
- char *dest,*temp;
- temp=(char*)CommandDesc((UCHAR)hcw);
+ char *dest;
+ const char* temp = InputMan::CommandDesc((UCHAR)hcw);
if (temp != NULL)
{
dest=new char[strlen(temp)+1];
char* Input::CommandTranslateStr(UCHAR command)
{
- char *desc;
- int length=5;//:+\t+0
- int keys=0; //max 10;
- char *commanddesc=(char*)CommandDesc(command);
- if (commanddesc != NULL)
- {
- length+=strlen(commanddesc);
- }
- char *preassigneddesc=(char*)HardcodedTranslateStr(command);
- if (preassigneddesc != NULL)
- {
- length+=strlen(preassigneddesc);
- }
+ char* desc;
+ int length = 5; //:+\t+0
+
+ const char* commanddesc = InputMan::CommandDesc(command);
+ if (commanddesc != NULL) length += strlen(commanddesc);
+
+ const char* preassigneddesc = HardcodedTranslateStr(command);
+ if (preassigneddesc != NULL) length += strlen(preassigneddesc);
- char *keydesc[10];
+ char* keydesc[10];
+ int keys = 0; // max 10
RemoteTranslationList::const_iterator it;
for (it = translist.begin(); it != translist.end(); it++)
{
{
keydesc[keys] = HCWDesc(it->first);
length += strlen(keydesc[keys])+2;
- keys ++;
+ keys++;
if (keys == 10) break;
}
}
- desc=new char [length];
- char *current=desc;
+ desc = new char[length];
+ char* current = desc;
if (commanddesc != NULL)
{
- current+=sprintf(current,"%s:\t ",commanddesc);
+ current += sprintf(current, "%s:\t ", commanddesc);
}
else
{
- current+=sprintf(current,":\t ");
+ current += sprintf(current,":\t ");
}
+
if (preassigneddesc != NULL)
{
- current+=sprintf(current,"%s\t",preassigneddesc);
+ current += sprintf(current, "%s\t", preassigneddesc);
}
else
{
current+=sprintf(current,"\t");
}
- for (int i = 0;i < keys; i++)
+
+ for (int i = 0; i < keys; i++)
{
- current += sprintf(current,"%s, ",keydesc[i]);
- delete [] keydesc[i];
+ current += sprintf(current, "%s, ", keydesc[i]);
+ delete[] keydesc[i];
}
+
return desc;
}
-bool Input::addOptionPagesToWTB(WTabBar *wtb)
-{
- WRemoteConfig* wrc = new WRemoteConfig();
- wtb->addTab(tr("Remote Control"), wrc);
- return true;
-}
+// bool Input::addOptionPagesToWTB(WTabBar *wtb)
+// {
+// WRemoteConfig* wrc = new WRemoteConfig();
+// wtb->addTab(tr("Remote Control"), wrc);
+// return true;
+// }
bool Input::loadOptionsfromServer(VDR* vdr)
{
SaveKeysConfig();
return true;
}
-
-bool Input::start()
-{
- Log::getInstance()->log("Input", Log::INFO, "start called");
-
- threadStartProtect.lock();
- listenThread = std::thread( [this ]
- {
- threadStartProtect.lock();
- threadStartProtect.unlock();
- // FIXME block signals
-
- eventLoop();
- });
- threadStartProtect.unlock();
- return true;
-}
-
-void Input::stop()
-{
- listenLoopStop = true;
- informStopEventLoop();
- listenThread.join();
-}
#include "defines.h"
#include "abstractoption.h"
+// FIXME make common base class sendKey function
-typedef std::map<ULLONG,UCHAR> RemoteTranslationList;
+
+typedef std::map<ULLONG, UCHAR> RemoteTranslationList;
class Input: public AbstractOption
{
public:
Input();
virtual ~Input();
- static Input* getInstance();
- bool start();
- void stop();
+ virtual bool start() { return false; }
+ virtual void stop() {}
- bool addOptionPagesToWTB(WTabBar *wtb);
- bool loadOptionsfromServer(VDR* vdr);
- bool saveOptionstoServer();
+ // Abstract Option interface
+ // virtual bool addOptionPagesToWTB(WTabBar *wtb);
+ virtual bool loadOptionsfromServer(VDR* vdr);
+ virtual bool saveOptionstoServer();
- void setRemoteType(UCHAR type);
- void setHWCtoCommand(ULLONG hcw,UCHAR command);
+ void setHWCtoCommand(ULLONG hcw, UCHAR command);
void unsetHWC(ULLONG hcw);
- void LoadKeysConfig(VDR *vdr,const char*keynum);
+ void LoadKeysConfig(VDR* vdr, const char* keynum);
void SaveKeysConfig();
void EnterLearningMode(UCHAR command);
- virtual int init(const char *devName)=0;
- virtual int shutdown()=0;
- virtual UCHAR getButtonPress(int how)=0; // DEPRECATED
-
- virtual bool mayHaveFewButtons() {return false;};
+ virtual int init()=0;
+ virtual void shutdown()=0;
virtual bool handlesVolume() {return false;};
virtual void volumeUp() {};
virtual void volumeDown() {};
virtual void volumeMute() {};
+ virtual void changePowerState(bool /* poweron */) {}; //informs the remote control, that about vomp's power state, this is important e.g. for cec
- virtual void InitHWCListwithDefaults();
+ virtual void InitHWCListwithDefaults()=0;
virtual char* HCWDesc(ULLONG hcw);
- const char *CommandDesc(UCHAR number);
- char *CommandTranslateStr(UCHAR command);
- virtual const char*HardcodedTranslateStr(UCHAR command);
+ char* CommandTranslateStr(UCHAR command);
+ static const char* HardcodedTranslateStr(UCHAR command);
void EnterLearnMode(UCHAR command);
void ResetToDefault();
- virtual void changePowerState(bool /* poweron */) {}; //informs the remote control, that about vomp's power state, this is important e.g. for cec
const static ULONG NOLEARNMODE = 256;
// Not buttons
const static UCHAR NA_NONE = 98;
const static UCHAR NA_UNKNOWN = 99;
const static UCHAR NA_SIGNAL = 100;
- const static UCHAR DF_UP = 94;
- const static UCHAR DF_DOWN = 95;
- const static UCHAR DF_LEFT = 96;
- const static UCHAR DF_RIGHT = 97;
// Problem common buttons
const static UCHAR VOLUMEUP = 16;
const static UCHAR POWERON = 202;
const static UCHAR POWEROFF = 203;
-
- // Remote types
- const static UCHAR OLDREMOTE = 1;
- const static UCHAR NEWREMOTE = 2;
-
protected:
- virtual UCHAR TranslateHWCFixed(ULLONG code);
- UCHAR TranslateHWCList(ULLONG code);
- UCHAR TranslateHWC(ULLONG code);
+ virtual UCHAR TranslateHWCFixed(int code)=0;
+ UCHAR TranslateHWCList(int code);
+ UCHAR TranslateHWC(int code);
- static Input* instance;
ULONG learnmode;
- UCHAR remoteType;
RemoteTranslationList translist;
-
- std::thread listenThread;
- std::mutex threadStartProtect;
-
- virtual void eventLoop() {}; // FIXME change to abstract
- virtual void informStopEventLoop() {}; // abstract
-
- bool listenLoopStop{};
};
#endif
-
-// FIXME rename all remote stuff to some sort of INPUT
-// Roll in UDP receiver
-
-// FIXME have Top remote system create new listeners for various devices? Hot plug?
-// Where remotelinux has multi listeners, move that to top?
--- /dev/null
+ /*
+ Copyright 2004-2020 Chris Tallon; 2012 Marten Richter
+
+ This file is part of VOMP.
+
+ VOMP 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ VOMP 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 VOMP. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+#include <iostream>
+#include <libcec/cec.h>
+#include <libcec/cecloader.h>
+using namespace CEC;
+
+#include <bcm_host.h>
+
+#include "log.h"
+#include "message.h"
+#include "messagequeue.h"
+#include "vdr.h"
+#include "woptionpane.h"
+#include "inputcec.h"
+
+
+//#define W_G_HCW(type,code) ((static_cast<ULLONG>(type) << 32) | code)
+
+//#define W_HCW_KC 1 /* key code as defined by kernel for keyboard and remotes through /dev/input */
+//#define W_HCW_CEC 2 /* HDMI_CEC */
+//#define W_HCW_LIRC 3 /* remote control LIRC*/
+
+
+InputCEC* InputCEC::instance = NULL;
+
+int InputCEC::init()
+{
+ InitHWCListwithDefaults();
+ InitKeymap();
+
+ // bcm_host_init(); //may be move to custom hardware init?
+ // now init cec
+ Log::getInstance()->log("InputCEC", Log::NOTICE, "Init LibCEC");
+ instance = this;
+
+ cec_config.Clear();
+ cec_callbacks.Clear();
+ cec_callbacks.logMessage = cecLogMessage;
+ cec_callbacks.keyPress = cecKeyPress;
+ cec_callbacks.commandReceived = cecCommand;
+ cec_callbacks.configurationChanged = cecConfigurationChanged;
+ cec_callbacks.sourceActivated = cecSourceActivated;
+ cec_config.clientVersion = LIBCEC_VERSION_CURRENT;
+ cec_config.bActivateSource = 1;
+ //cec_config.deviceTypes.Add(CEC_DEVICE_TYPE_PLAYBACK_DEVICE);
+ cec_config.deviceTypes.Add(CEC_DEVICE_TYPE_RECORDING_DEVICE);
+ //cec_config.deviceTypes.Add(CEC_DEVICE_TYPE_TUNER);
+
+ strncpy(cec_config.strDeviceName, "vomp", sizeof(cec_config.strDeviceName));
+
+ cec_config.callbackParam = NULL; // I do not care
+ cec_config.callbacks = &cec_callbacks;
+
+ cec_adap = LibCecInitialise(&cec_config);
+ if (!cec_adap)
+ {
+ Log::getInstance()->log("InputCEC", Log::ERR, "Init LibCEC failed");
+ return 1;
+ }
+
+ cec_adap->InitVideoStandalone();
+
+ cec_adapter_descriptor cec_adapter_descriptors[10];
+ int adap_num = cec_adap->DetectAdapters(cec_adapter_descriptors, 10);
+ if (adap_num < 0)
+ {
+ Log::getInstance()->log("InputCEC", Log::ERR, "CEC:Failed to find adapter");
+ return 1;
+ }
+
+ if (adap_num == 0)
+ {
+ Log::getInstance()->log("InputCEC", Log::NOTICE, "CEC: No adapter found");
+ return 1;
+ }
+
+ if (!cec_adap->Open(cec_adapter_descriptors[0].strComName))
+ {
+ Log::getInstance()->log("InputCEC", Log::ERR, "CEC:Failed to open adapter");
+ return 1;
+ }
+
+ if (!cec_adap->SetActiveSource(cec_config.deviceTypes[0]))
+ {
+ Log::getInstance()->log("InputCEC", Log::ERR, "CEC:Failed set active source");
+ return 1;
+ }
+
+ return 1;
+}
+
+void InputCEC::shutdown()
+{
+ if (cec_adap)
+ {
+ Log::getInstance()->log("InputCEC", Log::NOTICE, "Shutdown libcec begin");
+ cec_adap->SetInactiveView();
+ cec_adap->Close();
+ vc_cec_register_callback(NULL, NULL); //deactivate callback!
+ UnloadLibCec(cec_adap);
+ cec_adap = NULL;
+ Log::getInstance()->log("InputCEC", Log::NOTICE, "Shutdown libcec end");
+ }
+
+ instance = NULL;
+}
+
+void InputCEC::changePowerState(bool poweron)
+{
+ if (cec_adap)
+ {
+ if (poweron)
+ {
+ //Log::getInstance()->log("InputCEC", Log::DEBUG, "CEC set active source");
+ cec_adap->SetActiveSource(cec_config.deviceTypes[0]);
+ }
+ else
+ {
+ //Log::getInstance()->log("InputCEC", Log::DEBUG, "CEC set inactive view");
+ cec_adap->SetInactiveView();
+ }
+ }
+}
+
+void InputCEC::incomingCECkey(int keys)
+{
+ // Send INPUT message
+ Message* m = new Message();
+ m->message = Message::INPUT_EVENT;
+ m->to = Command::getInstance();
+ m->from = this;
+ m->parameter = TranslateHWC(keys);
+ MessageQueue::getInstance()->postMessage(m);
+}
+
+void InputCEC::incomingPowerkey(UCHAR key)
+{
+ // Send INPUT message
+ Message* m = new Message();
+ m->message = Message::INPUT_EVENT;
+ m->to = Command::getInstance();
+ m->from = this;
+ m->parameter = key;
+ MessageQueue::getInstance()->postMessage(m);
+}
+
+void InputCEC::volumeUp()
+{
+ cec_adap->VolumeUp();
+}
+
+void InputCEC::volumeDown()
+{
+ cec_adap->VolumeDown();
+}
+
+void InputCEC::volumeMute()
+{
+ cec_adap->AudioToggleMute();
+}
+
+bool InputCEC::loadOptionsfromServer(VDR* vdr)
+{
+ // Set remote keys
+ char* name;
+ name = vdr->configLoad("InputCEC", "HandleVolume");
+
+ if (name != NULL)
+ {
+ if (STRCASECMP(name, "Vomp") == 0) cechandlesvolume = false;
+ else if (STRCASECMP(name, "Cec") == 0) cechandlesvolume = true;
+ delete[] name;
+ }
+ return Input::loadOptionsfromServer(vdr);
+}
+
+bool InputCEC::saveOptionstoServer()
+{
+ if (cechandlesvolume) VDR::getInstance()->configSave("InputCEC", "HandleVolume","Cec");
+ else VDR::getInstance()->configSave("InputCEC", "HandleVolume","Vomp");
+
+ return Input::saveOptionstoServer();
+}
+
+bool InputCEC::addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane)
+{
+ //if (!Input::addOptionsToPanes(panenumber, options, pane)) return false;
+
+ Option* option;
+ if (panenumber == 2)
+ {
+ static const char* volumeopts[]={"Vomp","Cec"};
+ option = new Option(100,tr("Volume handled by"), "InputCEC","HandleVolume",Option::TYPE_TEXT,/*4,2*/2,0,0,volumeopts,NULL,false,this);
+ options->push_back(option);
+ pane->addOptionLine(option);
+ }
+
+ return true;
+}
+
+bool InputCEC::handleOptionChanges(Option* option)
+{
+ if (Input::handleOptionChanges(option))
+ return true;
+ switch (option->id) {
+ case 100: {
+ if (STRCASECMP(option->options[option->userSetChoice], "Vomp") == 0) {
+ cechandlesvolume=false;
+ } else if (STRCASECMP(option->options[option->userSetChoice], "Cec")
+ == 0) {
+ cechandlesvolume=true;
+ }
+ Log::getInstance()->log("InputCEC", Log::DEBUG, "Set volume handling to to %s %d",option->options[option->userSetChoice],cechandlesvolume);
+ return true;
+ }
+ break;
+ };
+ return false;
+}
+
+// STATIC FUNCTIONS FOLLOW
+
+void InputCEC::cecLogMessage(void* /* param */, const cec_log_message* message)
+{
+ Log::getInstance()->log("InputCEC", Log::DEBUG, "CECLOG: %lld %d %s", message->time, message->level, message->message);
+}
+
+void InputCEC::cecKeyPress(void* /* param */, const cec_keypress* key)
+{
+ //Log::getInstance()->log("InputCEC", Log::DEBUG, "Incoming cec key %d %d", key->keycode,key->duration);
+ if (key->duration == 0) instance->incomingCECkey(key->keycode);
+}
+
+void InputCEC::cecCommand(void* /* param */, const cec_command* command)
+{
+ Log::getInstance()->log("InputCEC", Log::DEBUG, "CECCommand: %d", command->opcode);
+ switch (command->opcode)
+ {
+ case CEC_OPCODE_STANDBY:
+ {
+ if (command->initiator==CECDEVICE_TV)
+ {
+ instance->incomingPowerkey(POWEROFF);
+ }
+ break;
+ }
+ case CEC_OPCODE_DECK_CONTROL:
+ {
+ if (command->initiator == CECDEVICE_TV && command->parameters.size == 1
+ && command->parameters[0] == CEC_DECK_CONTROL_MODE_STOP)
+ {
+ instance->incomingCECkey(CEC_USER_CONTROL_CODE_STOP);
+ }
+ break;
+ }
+ case CEC_OPCODE_PLAY:
+ {
+ if (command->initiator == CECDEVICE_TV && command->parameters.size == 1)
+ {
+ if (command->parameters[0] == CEC_PLAY_MODE_PLAY_FORWARD)
+ {
+ instance->incomingCECkey(CEC_USER_CONTROL_CODE_PLAY);
+ }
+ else if (command->parameters[0] == CEC_PLAY_MODE_PLAY_STILL)
+ {
+ instance->incomingCECkey(CEC_USER_CONTROL_CODE_PAUSE);
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void InputCEC::cecConfigurationChanged(void* /* param */, const libcec_configuration*)
+{
+ Log::getInstance()->log("InputCEC", Log::DEBUG, "CECConfig:"/*,config->string()*/);
+}
+
+void InputCEC::cecSourceActivated(void* /* param */, const cec_logical_address address, const uint8_t activated)
+{
+ Log::getInstance()->log("InputCEC", Log::DEBUG, "CECSourceActivated: %d %d", address, activated);
+ if (activated == 1)
+ {
+ instance->incomingPowerkey(POWERON);
+ }
+}
+
+void InputCEC::InitHWCListwithDefaults()
+{
+ //Processing CEC_Messages
+ translist[CEC_USER_CONTROL_CODE_NUMBER9] = NINE;
+ translist[CEC_USER_CONTROL_CODE_NUMBER8] = EIGHT;
+ translist[CEC_USER_CONTROL_CODE_NUMBER7] = SEVEN;
+ translist[CEC_USER_CONTROL_CODE_NUMBER6] = SIX;
+ translist[CEC_USER_CONTROL_CODE_NUMBER5] = FIVE;
+ translist[CEC_USER_CONTROL_CODE_NUMBER4] = FOUR;
+ translist[CEC_USER_CONTROL_CODE_NUMBER3] = THREE;
+ translist[CEC_USER_CONTROL_CODE_NUMBER2] = TWO;
+ translist[CEC_USER_CONTROL_CODE_NUMBER1] = ONE;
+ translist[CEC_USER_CONTROL_CODE_NUMBER0] = ZERO;
+ //translist[KEY_KPDOT] = STAR;
+
+ //translist[KEY_J] = GO; //j for JUMP TO instead of go to
+ translist[CEC_USER_CONTROL_CODE_F2_RED] = RED;
+ translist[CEC_USER_CONTROL_CODE_F3_GREEN] = GREEN;
+ translist[CEC_USER_CONTROL_CODE_F4_YELLOW] = YELLOW;
+ translist[CEC_USER_CONTROL_CODE_F1_BLUE] = BLUE;
+ //Processing Remote Style Messages
+ translist[CEC_USER_CONTROL_CODE_FAVORITE_MENU] = MENU;
+
+ translist[CEC_USER_CONTROL_CODE_RECORD] = RECORD;
+ translist[CEC_USER_CONTROL_CODE_PLAY] = PLAY; //Playback Televison
+ translist[CEC_USER_CONTROL_CODE_PAUSE] = PAUSE;
+ translist[CEC_USER_CONTROL_CODE_STOP] = STOP;
+ translist[CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION] = PLAYPAUSE;
+ translist[CEC_USER_CONTROL_CODE_FORWARD] = SKIPFORWARD;
+ translist[CEC_USER_CONTROL_CODE_BACKWARD] = SKIPBACK;
+ translist[CEC_USER_CONTROL_CODE_FAST_FORWARD ] = FORWARD;
+ translist[CEC_USER_CONTROL_CODE_REWIND] = REVERSE;
+ translist[CEC_USER_CONTROL_CODE_MUTE] = MUTE;
+ translist[CEC_USER_CONTROL_CODE_VOLUME_UP] = VOLUMEUP;
+ translist[CEC_USER_CONTROL_CODE_VOLUME_DOWN] = VOLUMEDOWN;
+ translist[CEC_USER_CONTROL_CODE_CHANNEL_UP ] = CHANNELUP;
+ translist[CEC_USER_CONTROL_CODE_CHANNEL_DOWN] = CHANNELDOWN;
+}
+
+UCHAR InputCEC::TranslateHWCFixed(int code)
+{
+ switch (code)
+ {
+ case CEC_USER_CONTROL_CODE_DOWN: return DOWN;
+ case CEC_USER_CONTROL_CODE_UP: return UP;
+ case CEC_USER_CONTROL_CODE_LEFT: return LEFT;
+ case CEC_USER_CONTROL_CODE_RIGHT: return RIGHT;
+ case CEC_USER_CONTROL_CODE_ROOT_MENU:
+ case CEC_USER_CONTROL_CODE_CONTENTS_MENU:
+ case CEC_USER_CONTROL_CODE_SETUP_MENU: return MENU;
+ case CEC_USER_CONTROL_CODE_EXIT: return BACK;
+ case CEC_USER_CONTROL_CODE_ENTER:
+ case CEC_USER_CONTROL_CODE_SELECT:
+ case CEC_USER_CONTROL_CODE_AN_RETURN: return OK;
+ case CEC_USER_CONTROL_CODE_POWER:
+ case POWER: return POWER; //?
+ default:
+ return NA_UNKNOWN;
+ }
+}
+
+
+#define NAMETRICK2(pre, code) cec_keymap[pre ## code]= #code
+static const char * cec_keymap[CEC_USER_CONTROL_CODE_MAX+1];
+
+void InputCEC::InitKeymap()
+{
+ for (int i=0; i < CEC_USER_CONTROL_CODE_MAX + 1; i++)
+ {
+ cec_keymap[i] = NULL;
+ }
+
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,SELECT);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,UP);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,DOWN);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,LEFT);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,RIGHT);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,RIGHT_UP);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,RIGHT_DOWN);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,LEFT_UP);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,LEFT_DOWN);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,ROOT_MENU);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,SETUP_MENU);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,CONTENTS_MENU);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,FAVORITE_MENU);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,EXIT);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER0);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER1);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER2);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER3);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER4);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER5);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER6);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER7);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER8);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER9);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,DOT);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,ENTER);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,CLEAR);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,NEXT_FAVORITE);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,CHANNEL_UP);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,CHANNEL_DOWN);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,PREVIOUS_CHANNEL);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,SOUND_SELECT);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,INPUT_SELECT);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,DISPLAY_INFORMATION);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,HELP);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,PAGE_UP);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,PAGE_DOWN);
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,POWER );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,VOLUME_UP );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,VOLUME_DOWN );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,MUTE );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,PLAY );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,STOP );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,PAUSE );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,RECORD );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,REWIND );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,FAST_FORWARD );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,EJECT );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,FORWARD );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,BACKWARD );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,STOP_RECORD );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,PAUSE_RECORD );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,ANGLE );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,SUB_PICTURE );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,VIDEO_ON_DEMAND );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,ELECTRONIC_PROGRAM_GUIDE );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,TIMER_PROGRAMMING );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,INITIAL_CONFIGURATION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,PLAY_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,PAUSE_PLAY_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,RECORD_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,PAUSE_RECORD_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,STOP_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,MUTE_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,RESTORE_VOLUME_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,TUNE_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,SELECT_MEDIA_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,SELECT_AV_INPUT_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,SELECT_AUDIO_INPUT_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,POWER_TOGGLE_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,POWER_OFF_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,POWER_ON_FUNCTION );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,F1_BLUE );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,F2_RED );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,F3_GREEN );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,F4_YELLOW );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,F5 );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,DATA );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,AN_RETURN );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,AN_CHANNELS_LIST );
+ NAMETRICK2(CEC_USER_CONTROL_CODE_,MAX );
+}
--- /dev/null
+ /*
+ Copyright 2004-2020 Chris Tallon; 2012 Marten Richter
+
+ This file is part of VOMP.
+
+ VOMP 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ VOMP 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 VOMP. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef INPUTCEC_H
+#define INPUTCEC_H
+
+#include <libcec/cec.h>
+
+#include "input.h"
+
+class InputCEC : public Input
+{
+ public:
+ int init();
+ void shutdown();
+
+ bool handlesVolume() { return cechandlesvolume; };
+ void volumeUp();
+ void volumeDown();
+ void volumeMute();
+ void changePowerState(bool poweron);
+
+ bool loadOptionsfromServer(VDR* vdr);
+ bool saveOptionstoServer();
+ bool addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane);
+ bool handleOptionChanges(Option* option);
+
+ private:
+ void InitKeymap();
+ void InitHWCListwithDefaults();
+ UCHAR TranslateHWCFixed(int code);
+
+ bool cechandlesvolume{};
+
+ CEC::ICECAdapter* cec_adap{};
+ CEC::libcec_configuration cec_config;
+ CEC::ICECCallbacks cec_callbacks;
+
+ void incomingCECkey(int keys);
+ void incomingPowerkey(UCHAR key);
+
+ static InputCEC* instance;
+ static void cecLogMessage(void *param, const CEC::cec_log_message* message);
+ static void cecKeyPress(void*param, const CEC::cec_keypress* key);
+ static void cecCommand(void *param, const CEC::cec_command* command);
+ static void cecConfigurationChanged(void *param, const CEC::libcec_configuration* config);
+ static void cecSourceActivated(void*param, const CEC::cec_logical_address address, const uint8_t activated);
+};
+
+#endif
#include <iostream>
#include <ostream>
-#include <bcm_host.h>
-
-#include <libcec/cec.h>
-#include <libcec/cecloader.h>
-using namespace CEC;
-
#include "i18n.h"
#include "vdr.h"
#include "woptionpane.h"
#include "inputlinux.h"
-#define W_G_HCW(type,code) ((static_cast<ULLONG>(type) << 32) | code)
-
-#define W_HCW_KC 1 /* key code as defined by kernel for keyboard and remotes through /dev/input */
-#define W_HCW_CEC 2 /* HDMI_CEC */
-#define W_HCW_LIRC 3 /* remote control LIRC*/
-
-
-InputLinux::InputLinux()
-{
-}
-
-InputLinux::~InputLinux()
-{
- for (unsigned int i = 0; i < devices.size(); i++)
- {
- close(devices[i]);
- }
-}
-
#define test_bit(input,b) ((1 << ((b) % 8))&(input)[b / 8] )
-int InputLinux::init(const char*)
+int InputLinux::init()
{
if (initted) return 0;
initted = 1;
+ InitHWCListwithDefaults();
InitKeymap();
for (int eventid = 0; eventid < 100; eventid++)
}
}
}
- return initCec();
-}
-
-int InputLinux::initCec() {
-
- // bcm_host_init(); //may be move to custom hardware init?
-// now init cec
- Log::getInstance()->log("InputLinux", Log::NOTICE, "Init LibCEC");
- cec_config.Clear();
- cec_callbacks.Clear();
-#if CEC_LIB_VERSION_MAJOR >= 4
- cec_callbacks.logMessage = cecLogMessage;
- cec_callbacks.keyPress = cecKeyPress;
- cec_callbacks.commandReceived = cecCommand;
- cec_callbacks.configurationChanged = cecConfigurationChanged;
- cec_callbacks.sourceActivated = cecSourceActivated;
-#else
- cec_callbacks.CBCecLogMessage = cecLogMessage;
- cec_callbacks.CBCecKeyPress = cecKeyPress;
- cec_callbacks.CBCecCommand = cecCommand;
- cec_callbacks.CBCecConfigurationChanged = cecConfigurationChanged;
- cec_callbacks.CBCecSourceActivated = cecSourceActivated;
- cec_config.bUseTVMenuLanguage=1;
-#endif
- cec_config.clientVersion=LIBCEC_VERSION_CURRENT;
- cec_config.bActivateSource=1;
- //cec_config.deviceTypes.Add(CEC_DEVICE_TYPE_PLAYBACK_DEVICE);
- cec_config.deviceTypes.Add(CEC_DEVICE_TYPE_RECORDING_DEVICE);
- //cec_config.deviceTypes.Add(CEC_DEVICE_TYPE_TUNER);
-
- strncpy(cec_config.strDeviceName,"vomp",sizeof(cec_config.strDeviceName));
-
-
- cec_config.callbackParam = NULL; // I do not care
- cec_config.callbacks = &cec_callbacks;
-
- cec_adap = LibCecInitialise(&cec_config);
- if (!cec_adap) {
- Log::getInstance()->log("InputLinux", Log::ERR, "Init LibCEC failed");
- return 1;
- }
- cec_adap->InitVideoStandalone();
-
-
-#if CEC_LIB_VERSION_MAJOR >= 4
- cec_adapter_descriptor cec_adapter_descriptors[10];
- int adap_num=cec_adap->DetectAdapters(cec_adapter_descriptors, 10);
-#else
- cec_adapter cec_devices[10];
- int adap_num=cec_adap->FindAdapters(cec_devices,10,NULL);
-#endif
- if (adap_num<0) {
- Log::getInstance()->log("InputLinux", Log::ERR, "CEC:Failed to find adapter");
- return 1;
-
- }
- if (adap_num==0) {
- Log::getInstance()->log("InputLinux", Log::NOTICE, "CEC: No adapter found");
- return 1;
-
- }
-#if CEC_LIB_VERSION_MAJOR >= 4
- if (!cec_adap->Open(cec_adapter_descriptors[0].strComName)) {
-#else
- if (!cec_adap->Open(cec_devices[0].comm)) {
-#endif
- Log::getInstance()->log("InputLinux", Log::ERR, "CEC:Failed to open adapter");
- return 1;
- }
-
- if (!cec_adap->SetActiveSource(cec_config.deviceTypes[0])) {
- Log::getInstance()->log("InputLinux", Log::ERR, "CEC:Failed set active source");
- return 1;
- }
-
-
-
-
return 1;
}
-int InputLinux::shutdown()
+void InputLinux::shutdown()
{
- if (!initted) return 0;
+ if (!initted) return;
- deinitCec();
while (devices.size())
{
int cur_fd = devices.back();
}
initted = 0;
- return 1;
-}
-
-void InputLinux::deinitCec()
-{
- if (cec_adap) {
- Log::getInstance()->log("InputLinux", Log::NOTICE, "Shutdown libcec begin");
- cec_adap->SetInactiveView();
- cec_adap->Close();
- vc_cec_register_callback(NULL, NULL);//deactivate callback!
- UnloadLibCec(cec_adap);
- cec_adap = NULL;
- Log::getInstance()->log("InputLinux", Log::NOTICE, "Shutdown libcec end");
- }
-
-}
-
-UCHAR InputLinux::TranslateHWCFixed(ULLONG code)
-{
- switch (code)
- {
- case W_G_HCW(W_HCW_KC, KEY_DOWN):
- return DOWN;
- case W_G_HCW(W_HCW_KC, KEY_UP):
- return UP;
- case W_G_HCW(W_HCW_KC, KEY_LEFT):
- return LEFT;
- case W_G_HCW(W_HCW_KC, KEY_RIGHT):
- return RIGHT;
- case W_G_HCW(W_HCW_KC, KEY_M):
- case W_G_HCW(W_HCW_KC, KEY_MEDIA):
- return MENU;
- case W_G_HCW(W_HCW_KC, KEY_BACKSPACE):
- case W_G_HCW(W_HCW_KC, KEY_EXIT):
- return BACK;
- case W_G_HCW(W_HCW_KC, KEY_ENTER):
- case W_G_HCW(W_HCW_KC, KEY_SPACE):
- case W_G_HCW(W_HCW_KC, KEY_OK):
- return OK;
-
- //CEC
- case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_DOWN):
- return DOWN;
- case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_UP):
- return UP;
- case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_LEFT):
- return LEFT;
- case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_RIGHT):
- return RIGHT;
- case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_ROOT_MENU):
- case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_CONTENTS_MENU):
- case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_SETUP_MENU):
- return MENU;
- case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_EXIT ):
- return BACK;
- case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_ENTER):
- case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_SELECT):
- case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_AN_RETURN):
- return OK;
- case W_G_HCW(W_HCW_KC, KEY_SLEEP):
- case W_G_HCW(W_HCW_KC, KEY_POWER):
- case W_G_HCW(W_HCW_KC, KEY_ESC):
- case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_POWER):
- case POWER:
- return POWER;
- default:
- return NA_UNKNOWN;
- };
}
-const char* InputLinux::HardcodedTranslateStr(UCHAR command)
+UCHAR InputLinux::TranslateHWCFixed(int code)
{
- switch (command)
+ // Translate /dev/input codes to VOMP codes for the hard coded buttons
+ switch (code)
{
- case DOWN:
- return tr("Down");
- case UP:
- return tr("Up");
- case LEFT:
- return tr("Left");
- case RIGHT:
- return tr("Right");
- case MENU:
- return tr("M");
- case BACK:
- return tr("Backspace, Back");
- case OK:
- return tr("Return, Space");
+ case KEY_DOWN: return DOWN;
+ case KEY_UP: return UP;
+ case KEY_LEFT: return LEFT;
+ case KEY_RIGHT: return RIGHT;
+ case KEY_M:
+ case KEY_MEDIA: return MENU;
+ case KEY_BACKSPACE:
+ case KEY_EXIT: return BACK;
+ case KEY_ENTER:
+ case KEY_SPACE:
+ case KEY_OK: return OK;
+ case KEY_SLEEP:
+ case KEY_POWER:
+ case KEY_ESC: return POWER;
+ case POWER: return POWER; // Where does this come from?
default:
- return NULL;
+ return NA_UNKNOWN;
}
}
-
void InputLinux::InitHWCListwithDefaults()
{
// Processing VK_Messages
- translist[W_G_HCW(W_HCW_KC,KEY_9)] = NINE;
- translist[W_G_HCW(W_HCW_KC,KEY_8)] = EIGHT;
- translist[W_G_HCW(W_HCW_KC,KEY_7)] = SEVEN;
- translist[W_G_HCW(W_HCW_KC,KEY_6)] = SIX;
- translist[W_G_HCW(W_HCW_KC,KEY_5)] = FIVE;
- translist[W_G_HCW(W_HCW_KC,KEY_4)] = FOUR;
- translist[W_G_HCW(W_HCW_KC,KEY_3)] = THREE;
- translist[W_G_HCW(W_HCW_KC,KEY_2)] = TWO;
- translist[W_G_HCW(W_HCW_KC,KEY_1)] = ONE;
- translist[W_G_HCW(W_HCW_KC,KEY_0)] = ZERO;
- translist[W_G_HCW(W_HCW_KC,KEY_KPDOT)] = STAR;
- // translist[W_G_HCW(W_HCW_KC,KEY_#)] = HASH;
-
- translist[W_G_HCW(W_HCW_KC,KEY_KP9)] = NINE;
- translist[W_G_HCW(W_HCW_KC,KEY_KP8)] = EIGHT;
- translist[W_G_HCW(W_HCW_KC,KEY_KP7)] = SEVEN;
- translist[W_G_HCW(W_HCW_KC,KEY_KP6)] = SIX;
- translist[W_G_HCW(W_HCW_KC,KEY_KP5)] = FIVE;
- translist[W_G_HCW(W_HCW_KC,KEY_KP4)] = FOUR;
- translist[W_G_HCW(W_HCW_KC,KEY_KP3)] = THREE;
- translist[W_G_HCW(W_HCW_KC,KEY_KP2)] = TWO;
- translist[W_G_HCW(W_HCW_KC,KEY_KP1)] = ONE;
- translist[W_G_HCW(W_HCW_KC,KEY_KP0)] = ZERO;
-
- translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_9)] = NINE;
- translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_8)] = EIGHT;
- translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_7)] = SEVEN;
- translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_6)] = SIX;
- translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_5)] = FIVE;
- translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_4)] = FOUR;
- translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_3)] = THREE;
- translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_2)] = TWO;
- translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_1)] = ONE;
- translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_0)] = ZERO;
- translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_STAR)] = STAR;
- translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_POUND)] = HASH;
-
-
- translist[W_G_HCW(W_HCW_KC,KEY_J)] = GO; //j for JUMP TO instead of go to
- translist[W_G_HCW(W_HCW_KC,KEY_R)] = RED;
- translist[W_G_HCW(W_HCW_KC,KEY_G)] = GREEN;
- translist[W_G_HCW(W_HCW_KC,KEY_Y)] = YELLOW;
- translist[W_G_HCW(W_HCW_KC,KEY_B)] = BLUE;
+ translist[KEY_9] = NINE;
+ translist[KEY_8] = EIGHT;
+ translist[KEY_7] = SEVEN;
+ translist[KEY_6] = SIX;
+ translist[KEY_5] = FIVE;
+ translist[KEY_4] = FOUR;
+ translist[KEY_3] = THREE;
+ translist[KEY_2] = TWO;
+ translist[KEY_1] = ONE;
+ translist[KEY_0] = ZERO;
+ translist[KEY_KPDOT] = STAR;
+ // translist[KEY_#] = HASH;
+
+ translist[KEY_KP9] = NINE;
+ translist[KEY_KP8] = EIGHT;
+ translist[KEY_KP7] = SEVEN;
+ translist[KEY_KP6] = SIX;
+ translist[KEY_KP5] = FIVE;
+ translist[KEY_KP4] = FOUR;
+ translist[KEY_KP3] = THREE;
+ translist[KEY_KP2] = TWO;
+ translist[KEY_KP1] = ONE;
+ translist[KEY_KP0] = ZERO;
+
+ translist[KEY_NUMERIC_9] = NINE;
+ translist[KEY_NUMERIC_8] = EIGHT;
+ translist[KEY_NUMERIC_7] = SEVEN;
+ translist[KEY_NUMERIC_6] = SIX;
+ translist[KEY_NUMERIC_5] = FIVE;
+ translist[KEY_NUMERIC_4] = FOUR;
+ translist[KEY_NUMERIC_3] = THREE;
+ translist[KEY_NUMERIC_2] = TWO;
+ translist[KEY_NUMERIC_1] = ONE;
+ translist[KEY_NUMERIC_0] = ZERO;
+ translist[KEY_NUMERIC_STAR] = STAR;
+ translist[KEY_NUMERIC_POUND] = HASH;
+
+
+ translist[KEY_J] = GO; //j for JUMP TO instead of go to
+ translist[KEY_R] = RED;
+ translist[KEY_G] = GREEN;
+ translist[KEY_Y] = YELLOW;
+ translist[KEY_B] = BLUE;
//Processing Remote Style Messages
- translist[W_G_HCW(W_HCW_KC,KEY_GREEN)] = GREEN;
- translist[W_G_HCW(W_HCW_KC,KEY_RED)] = RED;
- translist[W_G_HCW(W_HCW_KC,KEY_YELLOW)] = YELLOW;
- translist[W_G_HCW(W_HCW_KC,KEY_BLUE)] = BLUE;
- translist[W_G_HCW(W_HCW_KC,KEY_MENU)] = MENU;
-
- translist[W_G_HCW(W_HCW_KC,KEY_RECORD)] = RECORD;
- translist[W_G_HCW(W_HCW_KC,KEY_PLAY)] = PLAY; //Playback Televison
- translist[W_G_HCW(W_HCW_KC,KEY_PAUSE)] = PAUSE;
- translist[W_G_HCW(W_HCW_KC,KEY_STOP)] = STOP;
- translist[W_G_HCW(W_HCW_KC,KEY_PLAYPAUSE)] = PLAYPAUSE;
- translist[W_G_HCW(W_HCW_KC,KEY_P)] = PLAYPAUSE;
- translist[W_G_HCW(W_HCW_KC,KEY_NEXT)] = SKIPFORWARD;
- translist[W_G_HCW(W_HCW_KC,KEY_F2)] = SKIPFORWARD;
- translist[W_G_HCW(W_HCW_KC,KEY_PREVIOUS)] = SKIPBACK;
- translist[W_G_HCW(W_HCW_KC,KEY_F1)] = SKIPBACK;
- translist[W_G_HCW(W_HCW_KC,KEY_FORWARD)] = FORWARD;
- translist[W_G_HCW(W_HCW_KC,KEY_FASTFORWARD)] = FORWARD;
- translist[W_G_HCW(W_HCW_KC,KEY_F)] = FORWARD;
- translist[W_G_HCW(W_HCW_KC,KEY_BACK)] = REVERSE;
- translist[W_G_HCW(W_HCW_KC,KEY_REWIND)] = REVERSE;
- translist[W_G_HCW(W_HCW_KC,KEY_T)] = REVERSE;
- translist[W_G_HCW(W_HCW_KC,KEY_MUTE)] = MUTE;
- translist[W_G_HCW(W_HCW_KC,KEY_F8)] = MUTE;
- translist[W_G_HCW(W_HCW_KC,KEY_F10)] = VOLUMEUP;
- translist[W_G_HCW(W_HCW_KC,KEY_F9)] = VOLUMEDOWN;
- translist[W_G_HCW(W_HCW_KC,KEY_VOLUMEUP)] = VOLUMEUP;
- translist[W_G_HCW(W_HCW_KC,KEY_VOLUMEDOWN)] = VOLUMEDOWN;
- translist[W_G_HCW(W_HCW_KC,KEY_CHANNELUP)] = CHANNELUP;
- translist[W_G_HCW(W_HCW_KC,KEY_CHANNELDOWN)] = CHANNELDOWN;
- translist[W_G_HCW(W_HCW_KC,KEY_PAGEUP)] = CHANNELUP;
- translist[W_G_HCW(W_HCW_KC,KEY_PAGEDOWN)] = CHANNELDOWN;
-
-
- //Processing CEC_Messages
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER9)] = NINE;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER8)] = EIGHT;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER7)] = SEVEN;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER6)] = SIX;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER5)] = FIVE;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER4)] = FOUR;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER3)] = THREE;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER2)] = TWO;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER1)] = ONE;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER0)] = ZERO;
- //translist[W_G_HCW(W_HCW_CEC,KEY_KPDOT)] = STAR;
-
-
-
- //translist[W_G_HCW(W_HCW_CEC,KEY_J)] = GO; //j for JUMP TO instead of go to
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_F2_RED)] = RED;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_F3_GREEN)] = GREEN;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_F4_YELLOW)] = YELLOW;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_F1_BLUE)] = BLUE;
- //Processing Remote Style Messages
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_FAVORITE_MENU)] = MENU;
-
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_RECORD)] = RECORD;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_PLAY)] = PLAY; //Playback Televison
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_PAUSE)] = PAUSE;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_STOP)] = STOP;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION)] = PLAYPAUSE;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_FORWARD)] = SKIPFORWARD;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_BACKWARD)] = SKIPBACK;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_FAST_FORWARD )] = FORWARD;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_REWIND)] = REVERSE;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_MUTE)] = MUTE;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_VOLUME_UP)] = VOLUMEUP;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_VOLUME_DOWN)] = VOLUMEDOWN;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_CHANNEL_UP )] = CHANNELUP;
- translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_CHANNEL_DOWN)] = CHANNELDOWN;
+ translist[KEY_GREEN] = GREEN;
+ translist[KEY_RED] = RED;
+ translist[KEY_YELLOW] = YELLOW;
+ translist[KEY_BLUE] = BLUE;
+ translist[KEY_MENU] = MENU;
+
+ translist[KEY_RECORD] = RECORD;
+ translist[KEY_PLAY] = PLAY; //Playback Televison
+ translist[KEY_PAUSE] = PAUSE;
+ translist[KEY_STOP] = STOP;
+ translist[KEY_PLAYPAUSE] = PLAYPAUSE;
+ translist[KEY_P] = PLAYPAUSE;
+ translist[KEY_NEXT] = SKIPFORWARD;
+ translist[KEY_F2] = SKIPFORWARD;
+ translist[KEY_PREVIOUS] = SKIPBACK;
+ translist[KEY_F1] = SKIPBACK;
+ translist[KEY_FORWARD] = FORWARD;
+ translist[KEY_FASTFORWARD] = FORWARD;
+ translist[KEY_F] = FORWARD;
+ translist[KEY_BACK] = REVERSE;
+ translist[KEY_REWIND] = REVERSE;
+ translist[KEY_T] = REVERSE;
+ translist[KEY_MUTE] = MUTE;
+ translist[KEY_F8] = MUTE;
+ translist[KEY_F10] = VOLUMEUP;
+ translist[KEY_F9] = VOLUMEDOWN;
+ translist[KEY_VOLUMEUP] = VOLUMEUP;
+ translist[KEY_VOLUMEDOWN] = VOLUMEDOWN;
+ translist[KEY_CHANNELUP] = CHANNELUP;
+ translist[KEY_CHANNELDOWN] = CHANNELDOWN;
+ translist[KEY_PAGEUP] = CHANNELUP;
+ translist[KEY_PAGEDOWN] = CHANNELDOWN;
}
#define NAMETRICK(pre, code) linux_keymap[pre ## code]= #code
-#define NAMETRICK2(pre, code) cec_keymap[pre ## code]= #code
//extracte from linux/input.h
static const char * linux_keymap[KEY_MAX+1];
-static const char * cec_keymap[CEC_USER_CONTROL_CODE_MAX+1];
void InputLinux::InitKeymap()
{
NAMETRICK(KEY_,NUMERIC_9);
NAMETRICK(KEY_,NUMERIC_STAR);
NAMETRICK(KEY_,NUMERIC_POUND);
-
- for (int i=0; i < CEC_USER_CONTROL_CODE_MAX + 1; i++)
- {
- cec_keymap[i] = NULL;
- }
-
- NAMETRICK2(CEC_USER_CONTROL_CODE_,SELECT);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,UP);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,DOWN);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,LEFT);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,RIGHT);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,RIGHT_UP);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,RIGHT_DOWN);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,LEFT_UP);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,LEFT_DOWN);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,ROOT_MENU);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,SETUP_MENU);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,CONTENTS_MENU);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,FAVORITE_MENU);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,EXIT);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER0);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER1);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER2);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER3);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER4);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER5);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER6);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER7);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER8);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER9);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,DOT);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,ENTER);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,CLEAR);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,NEXT_FAVORITE);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,CHANNEL_UP);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,CHANNEL_DOWN);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,PREVIOUS_CHANNEL);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,SOUND_SELECT);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,INPUT_SELECT);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,DISPLAY_INFORMATION);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,HELP);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,PAGE_UP);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,PAGE_DOWN);
- NAMETRICK2(CEC_USER_CONTROL_CODE_,POWER );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,VOLUME_UP );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,VOLUME_DOWN );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,MUTE );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,PLAY );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,STOP );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,PAUSE );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,RECORD );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,REWIND );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,FAST_FORWARD );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,EJECT );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,FORWARD );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,BACKWARD );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,STOP_RECORD );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,PAUSE_RECORD );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,ANGLE );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,SUB_PICTURE );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,VIDEO_ON_DEMAND );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,ELECTRONIC_PROGRAM_GUIDE );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,TIMER_PROGRAMMING );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,INITIAL_CONFIGURATION );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,PLAY_FUNCTION );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,PAUSE_PLAY_FUNCTION );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,RECORD_FUNCTION );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,PAUSE_RECORD_FUNCTION );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,STOP_FUNCTION );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,MUTE_FUNCTION );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,RESTORE_VOLUME_FUNCTION );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,TUNE_FUNCTION );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,SELECT_MEDIA_FUNCTION );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,SELECT_AV_INPUT_FUNCTION );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,SELECT_AUDIO_INPUT_FUNCTION );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,POWER_TOGGLE_FUNCTION );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,POWER_OFF_FUNCTION );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,POWER_ON_FUNCTION );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,F1_BLUE );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,F2_RED );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,F3_GREEN );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,F4_YELLOW );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,F5 );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,DATA );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,AN_RETURN );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,AN_CHANNELS_LIST );
- NAMETRICK2(CEC_USER_CONTROL_CODE_,MAX );
}
-
-
char* InputLinux::HCWDesc(unsigned long long hcw)
{
- //Determine type
- unsigned int type = static_cast<unsigned int>(hcw >> 32);
- unsigned int vk = static_cast<ULONG>(hcw);
- char* rt = NULL;
-
- switch(type)
- {
- case W_HCW_KC:
- {
- rt = new char[10];
- const char *desc=linux_keymap[vk];
- if (desc)
- strncpy(rt, desc, 9);
- else
- sprintf(rt, "0x%x", vk);
- break;
- }
- case W_HCW_CEC:
- {
- rt = new char[10];
- const char* desc = cec_keymap[vk];
- if (desc)
- strncpy(rt, desc, 9);
- else
- sprintf(rt, "0x%x", vk);
- break;
- }
- /*
- case W_HCW_LIRC:{
- ULONG ri=(ULONG)hcw;
- rt=new char[10];
- sprintf(rt,"R: %X",ri);
- }break;*/
- }
+ unsigned int vk = static_cast<ULONG>(hcw); // FIXME
+ char* rt = new char[10];
+ const char* desc = linux_keymap[vk];
+ if (desc)
+ strncpy(rt, desc, 9);
+ else
+ sprintf(rt, "0x%x", vk);
- return rt;
+ return rt;
}
-void InputLinux::changePowerState(bool poweron)
+bool InputLinux::start()
{
- if (cec_adap)
- {
- if (poweron)
- {
- //Log::getInstance()->log("InputLinux", Log::DEBUG, "CEC set active source");
- cec_adap->SetActiveSource(cec_config.deviceTypes[0]);
- }
- else
- {
- //Log::getInstance()->log("InputLinux", Log::DEBUG, "CEC set inactive view");
- cec_adap->SetInactiveView();
- }
- }
-}
-
-#if CEC_LIB_VERSION_MAJOR >= 4
+ Log::getInstance()->log("Input", Log::INFO, "start called");
-// libcec4 API changed these params to pointers rather than copies, and the returns to void
-// Otherwise, these two blocks of code are the same
-
-void InputLinux::cecLogMessage(void* /* param */, const cec_log_message* message)
-{
- Log::getInstance()->log("InputLinux", Log::DEBUG, "CECLOG: %lld %d %s", message->time, message->level, message->message);
-}
-
-void InputLinux::cecKeyPress(void* /* param */, const cec_keypress* key)
-{
- //Log::getInstance()->log("InputLinux", Log::DEBUG, "Incoming cec key %d %d", key->keycode,key->duration);
- if (key->duration == 0) static_cast<InputLinux*>(Input::getInstance())->incomingCECkey(key->keycode);
-}
-
-void InputLinux::cecCommand(void* /* param */, const cec_command* command)
-{
- Log::getInstance()->log("InputLinux", Log::DEBUG, "CECCommand: %d",command->opcode);
- switch (command->opcode) {
- case CEC_OPCODE_STANDBY: {
- if (command->initiator==CECDEVICE_TV) {
- static_cast<InputLinux*>(Input::getInstance())->incomingPowerkey(POWEROFF);
- }
- } break;
- case CEC_OPCODE_DECK_CONTROL: {
- if (command->initiator==CECDEVICE_TV && command->parameters.size == 1
- && command->parameters[0]==CEC_DECK_CONTROL_MODE_STOP) {
- static_cast<InputLinux*>(Input::getInstance())->incomingCECkey(CEC_USER_CONTROL_CODE_STOP);
-
- }
-
- } break;
- case CEC_OPCODE_PLAY: {
- if (command->initiator==CECDEVICE_TV && command->parameters.size == 1) {
- if (command->parameters[0]==CEC_PLAY_MODE_PLAY_FORWARD) {
- static_cast<InputLinux*>(Input::getInstance())->incomingCECkey(CEC_USER_CONTROL_CODE_PLAY);
- } else if (command->parameters[0]==CEC_PLAY_MODE_PLAY_STILL) {
- static_cast<InputLinux*>(Input::getInstance())->incomingCECkey(CEC_USER_CONTROL_CODE_PAUSE);
- }
- }
-
-
- } break;
- default:
- break;
- };
-}
-
-void InputLinux::cecConfigurationChanged(void* /* param */, const libcec_configuration*)
-{
- Log::getInstance()->log("InputLinux", Log::DEBUG, "CECConfig:"/*,config->string()*/);
-}
-
-#else
-
-int InputLinux::cecLogMessage(void *param, const cec_log_message message)
-{
- Log::getInstance()->log("InputLinux", Log::DEBUG, "CECLOG: %lld %d %s", message.time, message.level, message.message);
- return 0;
-}
-
-int InputLinux::cecKeyPress(void*param, const cec_keypress key)
-{
- //Log::getInstance()->log("InputLinux", Log::DEBUG, "Incoming cec key %d %d", key.keycode,key.duration);
- if (key.duration == 0) ((InputLinux*)Input::getInstance())->incomingCECkey(key.keycode);
- return 1;
-}
-
-int InputLinux::cecCommand(void *param, const cec_command command)
-{
- Log::getInstance()->log("InputLinux", Log::DEBUG, "CECCommand: %d",command.opcode);
- switch (command.opcode) {
- case CEC_OPCODE_STANDBY: {
- if (command.initiator==CECDEVICE_TV) {
- ((InputLinux*)Input::getInstance())->incomingPowerkey(POWEROFF);
- }
- } break;
- case CEC_OPCODE_DECK_CONTROL: {
- if (command.initiator==CECDEVICE_TV && command.parameters.size == 1
- && command.parameters[0]==CEC_DECK_CONTROL_MODE_STOP) {
- ((InputLinux*)Input::getInstance())->incomingCECkey(CEC_USER_CONTROL_CODE_STOP);
-
- }
-
- } break;
- case CEC_OPCODE_PLAY: {
- if (command.initiator==CECDEVICE_TV && command.parameters.size == 1) {
- if (command.parameters[0]==CEC_PLAY_MODE_PLAY_FORWARD) {
- ((InputLinux*)Input::getInstance())->incomingCECkey(CEC_USER_CONTROL_CODE_PLAY);
- } else if (command.parameters[0]==CEC_PLAY_MODE_PLAY_STILL) {
- ((InputLinux*)Input::getInstance())->incomingCECkey(CEC_USER_CONTROL_CODE_PAUSE);
- }
- }
-
-
- } break;
- default:
- break;
- };
- return 1;
-}
-
-int InputLinux::cecConfigurationChanged(void *param, const libcec_configuration config)
-{
- Log::getInstance()->log("InputLinux", Log::DEBUG, "CECConfig:"/*,config.string()*/);
- return 1;
-
-}
-
-#endif
-
-void InputLinux::cecSourceActivated(void* /* param */, const cec_logical_address address, const uint8_t activated)
-{
- Log::getInstance()->log("InputLinux", Log::DEBUG, "CECSourceActivated: %d %d", address, activated);
- if (activated == 1)
- {
- static_cast<InputLinux*>(Input::getInstance())->incomingPowerkey(POWERON);
- }
-}
-
-void InputLinux::incomingCECkey(int keys)
-{
- // Send INPUT message
- Message* m = new Message();
- m->message = Message::INPUT_EVENT;
- m->to = Command::getInstance();
- m->from = this;
- m->parameter = static_cast<UCHAR>(TranslateHWC(W_G_HCW(W_HCW_CEC, keys)));
- MessageQueue::getInstance()->postMessage(m);
-}
-
-void InputLinux::incomingPowerkey(UCHAR key)
-{
- // Send INPUT message
- Message* m = new Message();
- m->message = Message::INPUT_EVENT;
- m->to = Command::getInstance();
- m->from = this;
- m->parameter = key;
- MessageQueue::getInstance()->postMessage(m);
-}
-
-bool InputLinux::loadOptionsfromServer(VDR* vdr)
-{
- // Set remote keys
- char* name;
- name = vdr->configLoad("InputLinux", "HandleVolume");
-
- if (name != NULL)
+ threadStartProtect.lock(); // Make sure listenThread is fully initted before start returns
+ listenThread = std::thread( [this]
{
- if (STRCASECMP(name, "Vomp") == 0) cechandlesvolume = false;
- else if (STRCASECMP(name, "Cec") == 0) cechandlesvolume = true;
- delete[] name;
- }
- return Input::loadOptionsfromServer(vdr);
-}
-
-bool InputLinux::saveOptionstoServer()
-{
- if (cechandlesvolume) VDR::getInstance()->configSave("InputLinux", "HandleVolume","Cec");
- else VDR::getInstance()->configSave("InputLinux", "HandleVolume","Vomp");
-
- return Input::saveOptionstoServer();
+ threadStartProtect.lock();
+ threadStartProtect.unlock();
+ listenLoop();
+ });
+ threadStartProtect.unlock();
+ return true;
}
-bool InputLinux::addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane)
+void InputLinux::stop()
{
- if (!Input::addOptionsToPanes(panenumber, options, pane)) return false;
+ threadStartProtect.lock(); // Also use it to protect against starting while stopping
- Option* option;
- if (panenumber == 2)
+ if (listenThread.joinable())
{
- static const char* volumeopts[]={"Vomp","Cec"};
- option = new Option(100,tr("Volume handled by"), "InputLinux","HandleVolume",Option::TYPE_TEXT,/*4,2*/2,0,0,volumeopts,NULL,false,this);
- options->push_back(option);
- pane->addOptionLine(option);
+ listenLoopStop = true;
+ write(pfds[1], "1", 1); // break the select in listenLoop
+ listenThread.join();
}
- return true;
-}
-
-bool InputLinux::handleOptionChanges(Option* option)
-{
- if (Input::handleOptionChanges(option))
- return true;
- switch (option->id) {
- case 100: {
- if (STRCASECMP(option->options[option->userSetChoice], "Vomp") == 0) {
- cechandlesvolume=false;
- } else if (STRCASECMP(option->options[option->userSetChoice], "Cec")
- == 0) {
- cechandlesvolume=true;
- }
- Log::getInstance()->log("InputLinux", Log::DEBUG, "Set volume handling to to %s %d",option->options[option->userSetChoice],cechandlesvolume);
- return true;
- }
- break;
- };
- return false;
-
-}
-
-void InputLinux::volumeUp()
-{
- cec_adap->VolumeUp();
-}
-
-void InputLinux::volumeDown()
-{
- cec_adap->VolumeDown();
-}
-
-void InputLinux::volumeMute()
-{
-#if CEC_LIB_VERSION_MAJOR >= 4
- cec_adap->AudioToggleMute();
-#else
- cec_adap->MuteAudio();
-#endif
-}
-
-void InputLinux::informStopEventLoop()
-{
- listenLoopStop = true;
- write(pfds[1], "1", 1); // break the select in getButtonPress
+ threadStartProtect.unlock();
}
-void InputLinux::eventLoop()
+void InputLinux::listenLoop()
{
fd_set readfds;
int maxfd;
m->message = Message::INPUT_EVENT;
m->to = Command::getInstance();
m->from = this;
- m->parameter = static_cast<UCHAR>(TranslateHWC(W_G_HCW(W_HCW_KC,ev.code)));
+// m->parameter = static_cast<UCHAR>(TranslateHWC_KC(ev.code));
+ m->parameter = TranslateHWC(ev.code);
MessageQueue::getInstance()->postMessage(m);
}
}
#define INPUTLINUX_H
#include <stdio.h>
-#include <libcec/cec.h>
#include <vector>
#include "defines.h"
-#include "log.h"
#include "input.h"
class InputLinux : public Input
{
public:
- InputLinux();
- virtual ~InputLinux();
+ int init();
+ void shutdown();
- int init(const char *devName);
- int shutdown();
- int getDevice();
- UCHAR getButtonPress(int) { return NA_UNKNOWN; } // DEPRECATED
- // void Signal();
-
-// void SendPower();
- void InitHWCListwithDefaults();
- const char*HardcodedTranslateStr(UCHAR command);
char* HCWDesc(ULLONG hcw);
-
- void changePowerState(bool poweron);
-
- bool loadOptionsfromServer(VDR* vdr);
- bool saveOptionstoServer();
- bool addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane);
- bool handleOptionChanges(Option* option);
- bool mayHaveFewButtons() {return true;};
+ bool start();
+ void stop();
- virtual bool handlesVolume() { return cechandlesvolume; };
- virtual void volumeUp();
- virtual void volumeDown();
- virtual void volumeMute();
-
- int initCec();
- void deinitCec();
-
- private:
+ private:
int initted{};
- bool signal{};
- bool cechandlesvolume{};
- UCHAR TranslateHWCFixed(ULLONG code);
void InitKeymap();
- std::vector<int> devices;
- int num_loop{};
-
- CEC::ICECAdapter* cec_adap{};
- CEC::libcec_configuration cec_config;
- CEC::ICECCallbacks cec_callbacks;
-
- void incomingCECkey(int keys);
- void incomingPowerkey(UCHAR key);
-
-#if CEC_LIB_VERSION_MAJOR >= 4
- static void cecLogMessage(void *param, const CEC::cec_log_message* message);
- static void cecKeyPress(void*param, const CEC::cec_keypress* key);
- static void cecCommand(void *param, const CEC::cec_command* command);
- static void cecConfigurationChanged(void *param, const CEC::libcec_configuration* config);
-#else
- static int cecLogMessage(void *param, const CEC::cec_log_message message);
- static int cecKeyPress(void*param, const CEC::cec_keypress key);
- static int cecCommand(void *param, const CEC::cec_command command);
- static int cecConfigurationChanged(void *param, const CEC::libcec_configuration config);
-#endif
- static void cecSourceActivated(void*param, const CEC::cec_logical_address address, const uint8_t activated);
+ void InitHWCListwithDefaults();
+ UCHAR TranslateHWCFixed(int code);
- void eventLoop();
- void informStopEventLoop();
+ std::vector<int> devices;
+ std::thread listenThread;
+ std::mutex threadStartProtect;
+ void listenLoop();
+ bool listenLoopStop{};
int pfds[2];
};
--- /dev/null
+/*
+ Copyright 2020 Chris Tallon; 2012 Marten Richter
+
+ This file is part of VOMP.
+
+ VOMP 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ VOMP 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 VOMP. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "log.h"
+#include "wremoteconfig.h"
+#include "wtabbar.h"
+#include "inputlinux.h"
+#include "inputcec.h"
+#include "i18n.h"
+#include "input.h"
+
+#include "inputman.h"
+
+InputMan* InputMan::instance = NULL;
+
+InputMan::InputMan()
+{
+ instance = this;
+}
+
+InputMan::~InputMan()
+{
+ instance = NULL;
+}
+
+InputMan* InputMan::getInstance()
+{
+ return instance;
+}
+
+bool InputMan::init()
+{
+ bool i1{}, i2{};
+
+#ifdef VOMP_PLATFORM_RASPBERRY
+ inputLinux = new InputLinux();
+ i1 = inputLinux->init();
+ if (!i1) { delete inputLinux; inputLinux = NULL; }
+
+// inputCEC = new InputCEC();
+// i2 = inputCEC->init();
+// if (!i2) { delete inputCEC; inputCEC = NULL; }
+#endif
+
+ if (!i1 && !i2)
+ {
+ Log::getInstance()->log("InputMan", Log::CRIT, "InputMan could not init any input module");
+ return false;
+ }
+
+ initted = true;
+ return true;
+}
+
+bool InputMan::start()
+{
+ bool i1{};
+
+ if (inputLinux)
+ {
+ i1 = inputLinux->start();
+ }
+
+ return i1;
+}
+
+void InputMan::stop()
+{
+ if (inputLinux) inputLinux->stop();
+}
+
+void InputMan::shutdown()
+{
+ Log::getInstance()->log("InputMan", Log::DEBUG, "Shutdown start");
+
+ if (inputLinux)
+ {
+ Log::getInstance()->log("InputMan", Log::DEBUG, "Shutdown start - Linux");
+ inputLinux->stop();
+ inputLinux->shutdown();
+ delete inputLinux;
+ inputLinux = NULL;
+ }
+
+ if (inputCEC)
+ {
+ Log::getInstance()->log("InputMan", Log::DEBUG, "Shutdown start - CEC");
+ inputCEC->shutdown();
+ delete inputCEC;
+ inputCEC = NULL;
+ }
+
+ initted = false;
+}
+
+bool InputMan::mayHaveFewButtons()
+{
+ // 052 returned true if remotelinux was in effect - linux or CEC. What was it for?
+
+ if (inputLinux || inputCEC) return true;
+ return false;
+}
+
+bool InputMan::handlesVolume()
+{
+ if (!inputCEC) return false;
+ return inputCEC->handlesVolume();
+}
+
+void InputMan::volumeUp()
+{
+ if (inputCEC) inputCEC->volumeUp();
+}
+
+void InputMan::volumeDown()
+{
+ if (inputCEC) inputCEC->volumeDown();
+}
+
+void InputMan::volumeMute()
+{
+ if (inputCEC) inputCEC->volumeMute();
+}
+
+void InputMan::changePowerState(bool powerOn)
+{
+ if (inputCEC) inputCEC->changePowerState(powerOn);
+}
+
+bool InputMan::addOptionsToPanes(int panenumber, Options* options, WOptionPane* pane)
+{
+ if (inputLinux) inputLinux->addOptionsToPanes(panenumber, options, pane);
+ if (inputCEC) inputCEC->addOptionsToPanes(panenumber, options, pane);
+
+ return true; // FIXME
+}
+
+bool InputMan::addOptionPagesToWTB(WTabBar *wtb)
+{
+ //if (inputLinux) inputLinux->addOptionPagesToWTB(wtb);
+ //if (inputCEC) inputCEC->addOptionPagesToWTB(wtb);
+
+ WRemoteConfig* wrc = new WRemoteConfig();
+ wtb->addTab(tr("Remote Control"), wrc);
+
+ return true; // FIXME
+}
+
+bool InputMan::saveOptionstoServer()
+{
+ if (inputLinux) inputLinux->saveOptionstoServer();
+ if (inputCEC) inputCEC->saveOptionstoServer();
+
+ return true; // FIXME
+}
+
+const char* InputMan::CommandDesc(UCHAR number)
+{
+ switch (number)
+ {
+ case Input::VOLUMEUP:
+ return tr("Volume Up");
+ case Input::VOLUMEDOWN:
+ return tr("Volume Down");
+ case Input::CHANNELUP:
+ return tr("Channel up");
+ case Input::CHANNELDOWN:
+ return tr("Channel down");
+ case Input::ZERO:
+ return "0";
+ case Input::ONE:
+ return "1";
+ case Input::TWO:
+ return "2";
+ case Input::THREE:
+ return "3";
+ case Input::FOUR:
+ return "4";
+ case Input::FIVE:
+ return "5";
+ case Input::SIX:
+ return "6";
+ case Input::SEVEN:
+ return "7";
+ case Input::EIGHT:
+ return "8";
+ case Input::NINE:
+ return "9";
+ case Input::POWER:
+ return tr("Power");
+ case Input::GO:
+ return tr("Go");
+ case Input::BACK:
+ return tr("Back");
+ case Input::MENU:
+ return tr("Menu");
+ case Input::RED:
+ return tr("Red");
+ case Input::GREEN:
+ return tr("Green");
+ case Input::YELLOW:
+ return tr("Yellow");
+ case Input::BLUE:
+ return tr("Blue");
+ case Input::MUTE:
+ return tr("Mute");
+ case Input::RADIO:
+ return tr("Radio");
+ case Input::REVERSE:
+ return tr("Reverse");
+ case Input::PLAY:
+ return tr("Play");
+ case Input::FORWARD:
+ return tr("Forward");
+ case Input::RECORD:
+ return tr("Record");
+ case Input::STOP:
+ return tr("Stop");
+ case Input::PAUSE:
+ return tr("Pause");
+ case Input::SKIPBACK:
+ return tr("Skip back");
+ case Input::SKIPFORWARD:
+ return tr("Skip forward");
+ case Input::OK:
+ return tr("Ok");
+ case Input::FULL:
+ return tr("Fullscreen");
+ case Input::TV:
+ return tr("TV");
+ case Input::VIDEOS:
+ return tr("Videos");
+ case Input::MUSIC:
+ return tr("Music");
+ case Input::PICTURES:
+ return tr("Pictures");
+ case Input::GUIDE:
+ return tr("Guide");
+ case Input::UP:
+ return tr("Up");
+ case Input::DOWN:
+ return tr("Down");
+ case Input::LEFT:
+ return tr("Left");
+ case Input::RIGHT:
+ return tr("Right");
+ case Input::PREVCHANNEL:
+ return tr("Previous Channel");
+ case Input::STAR:
+ return tr("Star");
+ case Input::HASH:
+ return tr("Hash");
+ case Input::PLAYPAUSE:
+ return tr("Play/Pause");
+
+ default:
+ return NULL;
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 Chris Tallon
+
+ This file is part of VOMP.
+
+ VOMP 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ VOMP 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 VOMP. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef INPUTMAN_H
+#define INPUTMAN_H
+
+/*
+The plan:
+
+The old design had an abstract Remote class with a single Remote* (RemoteWin, RemoteLinux, RemoteLirc)
+instantiating.
+
+The new design is:
+
+A single RemoteMan object will look after several Input devices. RemoteMan will have getInstance().
+
+An abstract Input class (old Remote) defines common stuff about input devices.
+
+Many Input* objects may exist at the same time. They will be:
+
+InputLinux
+InputCEC
+InputUDP
+InputWin
+InputLirc
+
+Obviously Linux and Win won't be active simultaneously. UDP will roll in the UDP button receiver
+into this input system.
+
+The old design grew out of the fact the main thread waited on Remote::getButtonPress. Now the main
+thread waits on the MessageQueue. The input system should be separate, run in its own threads and
+should insert messages to the queue on input.
+
+Benefits:
+
+It would be nice if the input system could boot up in its own time, not delaying the rest of the
+program, but this may not be achievable.
+
+In the future it will be possible to implement hot plugging of USB input devices. (Currently vomp
+only uses what is present at vomp-startup).
+
+The CEC code can be removed from InputLinux. Under the new design they are nothing to do with
+each other.
+
+Direct Lirc input can be brought back - probably very easily. TODO
+
+Input objects can be easily and individually enabled / disabled.
+
+New types of input can be implemented much easier.
+
+For now, two decisions to make things a bit easier:
+
+1. InputMan will hardcode knowledge about the Input types with hard pointers to each. In future
+ perhaps this will change to a dynamic list of Input objects where InputMan refers to them
+ through the Input interface only.
+
+2. InputLinux will continue to represent all devices found in /dev/input. If there is a good
+ reason in future then this should switch to several InputLinux objects representing one
+ device each.
+
+*/
+
+#include "defines.h"
+#include "abstractoption.h"
+
+class InputLinux;
+class InputCEC;
+class InputWin;
+class InputUDP;
+class InputLirc;
+
+class InputMan: public AbstractOption
+{
+ public:
+ InputMan();
+ virtual ~InputMan();
+ static InputMan* getInstance();
+
+ bool init();
+ void shutdown();
+
+ bool start(); // MessageQueue should be ready before this is called
+ void stop(); // Nothing should be sent to MQ after this
+
+ bool mayHaveFewButtons();
+
+ bool handlesVolume(); // Returns true if we have an InputCEC willing to handle volume
+ void volumeUp();
+ void volumeDown();
+ void volumeMute();
+ void changePowerState(bool powerOn);
+
+ // Abstract Option interface
+ bool addOptionPagesToWTB(WTabBar* wtb);
+ bool addOptionsToPanes(int panenumber, Options* options, WOptionPane* pane);
+ bool saveOptionstoServer();
+
+ static const char* CommandDesc(UCHAR number);
+
+ private:
+ static InputMan* instance;
+
+ InputLinux* inputLinux{};
+ InputCEC* inputCEC{};
+ InputWin* inputWin{};
+ InputUDP* inputUDP{};
+ InputLirc* inputLirc{};
+
+ bool initted{};
+};
+
+#endif
+
+// TODO idea:
+// don't have Input inherit AbstractOption, just individual inputs. Then one day could test with
+// dynamic_cast whether to call the AO IF stuff on them
+// could also have a CEC IF and do the same?
#include <unistd.h>
#include <endian.h>
#endif
+#include <thread>
#include "defines.h"
#ifdef VOMP_PLATTFORM_NMT
-#include "remotelirc.h"
#include "lednmt.h"
#include "osddirectfb.h"
#include "audionmt.h"
#ifdef VOMP_PLATFORM_RASPBERRY
-#include "inputlinux.h"
#include "ledraspberry.h"
#include "osdopenvg.h"
#include "audioomx.h"
#endif
-
+#include "inputman.h"
#include "wol.h"
#include "vsleeptimer.h"
// Global variables --------------------------------------------------------------------------------------------------
Log* logger;
-Input* remote;
+InputMan* inputMan;
Led* led;
Osd* osd;
Timers* timers;
logger = new Log();
timers = new Timers();
vdr = new VDR();
+ inputMan = new InputMan();
- remote = new Remote_TYPE();
led = new Led_TYPE();
osd = new Osd_TYPE();
audio = new Audio_TYPE();
video = new Video_TYPE();
-
-
boxstack = new BoxStack();
command = new Command();
wol = new Wol();
sleeptimer = new Sleeptimer();
- if (!logger || !remote || !led || !osd || !video || !audio || !boxstack || !command || !wol || !sleeptimer)
+ if (!logger || !inputMan || !led || !osd || !video || !audio || !boxstack || !command || !wol || !sleeptimer)
{
printf("Could not create objects. Memory problems?\n");
shutdown(1);
std::thread threadSignalReceiver(threadSignalReceiverFunction);
threadSignalReceiver.detach();
- /*
- sighandler_t sigtest;
+ logger->log("Core", Log::INFO, "Signal handlers set up successfully");
- sigtest = signal(SIGPIPE, SIG_IGN);
- if (sigtest == SIG_ERR)
- {
- logger->log("Core", Log::EMERG, "Could not set up signal handler for SIGPIPE. Aborting.");
- shutdown(1);
- }
- sigtest = signal(SIGINT, sighandler);
- if (sigtest == SIG_ERR)
- {
- logger->log("Core", Log::EMERG, "Could not set up signal handler for SIGINT. Aborting.");
- shutdown(1);
- }
- sigtest = signal(SIGTERM, sighandler);
- if (sigtest == SIG_ERR)
- {
- logger->log("Core", Log::EMERG, "Could not set up signal handler for SIGTERM. Aborting.");
- shutdown(1);
- }
- sigtest = signal(SIGUSR1, sighandler);
- if (sigtest == SIG_ERR)
- {
- logger->log("Core", Log::EMERG, "Could not set up signal handler for SIGUSR1. Aborting.");
- shutdown(1);
- }
- sigtest = signal(SIGUSR2, sighandler);
- if (sigtest == SIG_ERR)
+ // VT Switching -----------------------------------------------------------------------------------------------
+
+#ifdef HANDLE_VT_SWITCHING
+ if (
+
+
+ (fdtty = open("/dev/tty", O_WRONLY),0) == -1 // FIXME. Why the ,0 ? Surely this kills the log line below
+
+
+ )
{
- logger->log("Core", Log::EMERG, "Could not set up signal handler for SIGUSR2. Aborting.");
- shutdown(1);
+ logger->log("Core", Log::EMERG, "Could not open /dev/tty. Please change permissions");
}
- sigtest = signal(SIGURG, sighandler);
- if (sigtest == SIG_ERR)
+ else
{
- logger->log("Core", Log::EMERG, "Could not set up signal handler for SIGURG. Aborting.");
- shutdown(1);
- }
- */
-
- logger->log("Core", Log::INFO, "Signal handlers set up successfully");
-
-#ifdef HANDLE_VT_SWITCHING
- if ((fdtty = open("/dev/tty", O_WRONLY),0) == -1) {
- logger->log("Core", Log::EMERG, "Could not open /dev/tty. Please change permissions");
- } else {
- int free_vt;
- if (ioctl(fdtty,VT_OPENQRY,&free_vt)==-1 || free_vt==-1){
- logger->log("Core", Log::EMERG, "Could not retrieve free virtual console, please change permissions");
- } else {
- ioctl(fdtty,VT_ACTIVATE,free_vt);
- ioctl(fdtty,VT_WAITACTIVE,free_vt);
- ioctl(fdtty, VT_LOCKSWITCH, 1);
- }
+ int free_vt;
+ if (ioctl(fdtty, VT_OPENQRY, &free_vt) == -1 || free_vt == -1)
+ {
+ logger->log("Core", Log::EMERG, "Could not retrieve free virtual console, please change permissions");
+ }
+ else
+ {
+ ioctl(fdtty, VT_ACTIVATE, free_vt);
+ ioctl(fdtty, VT_WAITACTIVE, free_vt);
+ ioctl(fdtty, VT_LOCKSWITCH, 1);
+ }
}
-
#endif
// Init modules ----------------------------------------------------------------------------------------------------
int success;
- success = remote->init(RemoteStartDev);
+ success = inputMan->init();
if (success)
{
- logger->log("Core", Log::INFO, "Remote module initialised");
+ logger->log("Core", Log::INFO, "InputMan module initialised");
}
else
{
- logger->log("Core", Log::EMERG, "Remote module failed to initialise");
+ logger->log("Core", Log::EMERG, "InputMan module failed to initialise");
shutdown(1);
}
logger->log("Core", Log::NOTICE, "LED module shut down");
}
- if (remote)
+ if (inputMan)
{
- remote->shutdown();
- delete remote;
- logger->log("Core", Log::NOTICE, "Remote module shut down");
+ inputMan->shutdown();
+ delete inputMan;
+ logger->log("Core", Log::NOTICE, "InputMan module shut down");
}
if (wol)
message.o messagequeue.o udp.o wol.o audio.o video.o log.o mutex.o \
vdr.o recman.o recording.o recinfo.o channel.o rectimer.o event.o \
directory.o mark.o option.o player.o playerradio.o vfeed.o afeed.o \
- demuxer.o demuxervdr.o demuxerts.o stream.o \
+ demuxer.o demuxervdr.o demuxerts.o stream.o inputman.o \
region.o colour.o boxstack.o boxx.o tbboxx.o vrecording.o \
vinfo.o vquestion.o vrecordinglist.o vrecordinglistclassic.o \
vrecordinglistadvanced.o vepgsummary.o vepglistadvanced.o \
OBJ_RASPBERRY = main.o threadp.o osdopenvg.o \
ledraspberry.o videoomx.o audioomx.o imageomx.o \
- wjpegsimple.o inputlinux.o signal.o
+ wjpegsimple.o inputlinux.o inputcec.o signal.o
OBJ_WINDOWS = winmain.o threadwin.o remotewin.o ledwin.o videowin.o \
audiowin.o windowsosd.o dsallocator.o dssourcefilter.o dssourcepin.o \
{
return 4;
}
- case Input::DF_UP:
case Input::UP:
{
if (editsubtitles) {
return 2;
}
- case Input::DF_DOWN:
case Input::DOWN:
{
if (editsubtitles) {
return 2;
}
case Input::LEFT:
- case Input::DF_LEFT:
{
if (editsubtitles && subtitles) {
ssl.setDarkSelOption(true);
return 2;
}
case Input::RIGHT:
- case Input::DF_RIGHT:
{
if (!editsubtitles && subtitles) {
ssl.setDarkSelOption(false);
{
switch(command)
{
- case Input::DF_UP:
case Input::UP:
{
sl.up();
boxstack->update(this);
return 2;
}
- case Input::DF_DOWN:
case Input::DOWN:
{
sl.down();
{
switch(command)
{
- case Input::DF_UP:
case Input::UP:
{ // cursor up the channel list
chanListbox.up();
boxstack->update(this);
return 2;
}
- case Input::DF_DOWN:
case Input::DOWN:
{ // cursor down the channel list
Log::getInstance()->log("VEPG", Log::DEBUG, "Down start");
return 2;
}
- case Input::DF_LEFT:
case Input::LEFT:
{ // cursor left through time
selTime = thisEvent.time - 1;
boxstack->update(this);
return 2;
}
- case Input::DF_RIGHT:
case Input::RIGHT:
{
// cursor right through time
{
switch(command)
{
- case Input::DF_UP:
case Input::UP:
{
sl.up();
boxstack->update(this);
return 2;
}
- case Input::DF_DOWN:
case Input::DOWN:
{
sl.down();
{
switch(command)
{
- case Input::DF_LEFT:
case Input::LEFT:
{
swap();
boxstack->update(this);
return 2;
}
- case Input::DF_RIGHT:
case Input::RIGHT:
{
swap();
#include "woptionpane.h"
#include "osdopenvg.h"
#include "boxstack.h"
-#include "input.h"
+#include "inputman.h"
#include <bcm_host.h>
}
}
- Input::getInstance()->shutdown();
+ InputMan::getInstance()->shutdown();
vc_tv_power_off();
if (mymode) {
Log::getInstance()->log("Video", Log::NOTICE, "Switch to optimum mode");
} else {
/* analog tv case */
Log::getInstance()->log("Video", Log::NOTICE, "Analog tv case");
- Input::getInstance()->shutdown();
+ InputMan::getInstance()->shutdown();
vc_tv_power_off();
SDTV_MODE_T setmode=SDTV_MODE_PAL;
SDTV_OPTIONS_T options;
hdmi=false;
}
- Input::getInstance()->init("");
+ InputMan::getInstance()->init(); // FIXME complete shutdown and reinit maybe heavy handed.
+ // If this was just to reinit CEC then funcitons should be made to do that
signalon=true;
//TODO reinit osd
Log::getInstance()->log("Video", Log::NOTICE, "signalOff");
Osd::getInstance()->stopUpdate(); // turn off drawing thread
- Input::getInstance()->shutdown();
+ InputMan::getInstance()->shutdown();
vc_tv_power_off();
- Input::getInstance()->init("");
+ InputMan::getInstance()->init(); // FIXME
signalon=false;
return 1;
}
boxstack->update(this);
return 2;
}
- case Input::DF_UP:
case Input::UP:
{
sl.up();
boxstack->update(this);
return 2;
}
- case Input::DF_DOWN:
case Input::DOWN:
{
sl.down();
int rt=1;
switch(command)
{
- case Input::DF_UP:
case Input::UP:
case Input::SKIPBACK:
rotate=WJpegComplex::ROT_0;
if (showtime > 1) showtime--;
updatePictureBanner(true);
break;
- case Input::DF_DOWN:
case Input::DOWN:
case Input::SKIPFORWARD:
rotate=WJpegComplex::ROT_0;
setAudioMode(false);
rt=2;
break;
- case Input::DF_UP:
case Input::UP:
play(playall,false,VMediaList::MV_PREV);
rt= 2;
updateInfo=true;
rt=2;
break;
- case Input::DF_DOWN:
case Input::DOWN:
play(playall,false,VMediaList::MV_NEXT);
rt= 2;
#include "osd.h"
#include "audio.h"
#include "input.h"
+#include "inputman.h"
#include "boxstack.h"
#include "woptionpane.h"
#include "wremoteconfig.h"
options.push_back(option);
wop->addOptionLine(option);
- Input::getInstance()->addOptionsToPanes(0,&options,wop);
+ InputMan::getInstance()->addOptionsToPanes(0,&options,wop);
Video::getInstance()->addOptionsToPanes(0,&options,wop);
Audio::getInstance()->addOptionsToPanes(0,&options,wop);
/* WRemoteConfig* wrc = new WRemoteConfig();
tabbar.addTab(tr("Remote Control"), wrc);*/
- Input::getInstance()->addOptionPagesToWTB(&tabbar);
+ InputMan::getInstance()->addOptionPagesToWTB(&tabbar);
// panes[1] = wrc;
Video::getInstance()->addOptionPagesToWTB(&tabbar);
options.push_back(option);
wop->addOptionLine(option);
- Input::getInstance()->addOptionsToPanes(1,&options,wop);
+ InputMan::getInstance()->addOptionsToPanes(1,&options,wop);
Video::getInstance()->addOptionsToPanes(1,&options,wop);
Audio::getInstance()->addOptionsToPanes(1,&options,wop);
wop->addOptionLine(option);
#endif
- Input::getInstance()->addOptionsToPanes(2,&options,wop);
+ InputMan::getInstance()->addOptionsToPanes(2,&options,wop);
Video::getInstance()->addOptionsToPanes(2,&options,wop);
Audio::getInstance()->addOptionsToPanes(2,&options,wop);
}
{
VDR* vdr = VDR::getInstance();
- Input::getInstance()->saveOptionstoServer(); //Remote
+ InputMan::getInstance()->saveOptionstoServer(); //Remote
Video::getInstance()->saveOptionstoServer(); //Video
Audio::getInstance()->saveOptionstoServer(); //Remote
#ifdef VOMP_PLATTFORM_MVP
{
switch(command)
{
- case Input::DF_LEFT:
case Input::LEFT:
{
swap();
BoxStack::getInstance()->update(this);
return 2;
}
- case Input::DF_RIGHT:
case Input::RIGHT:
{
swap();
{
switch(command)
{
- case Input::DF_UP:
case Input::UP:
{
sl.up();
BoxStack::getInstance()->update(this);
return 2;
}
- case Input::DF_DOWN:
case Input::DOWN:
{
sl.down();
if (buttons) {
switch(command)
{
- case Input::DF_UP:
case Input::UP:
{
tabbar.activateFocus(false);
return 2;
}
- case Input::DF_DOWN:
case Input::DOWN:
{
tabbar.activateFocus(false);
return 2;
}
case Input::LEFT:
- case Input::DF_LEFT:
case Input::RIGHT:
- case Input::DF_RIGHT:
{
buttons = false;
button[selected].setActive(0);
else if (retval == 2)
{
// command was taken and actively ignored
- if (command==Input::LEFT || command==Input::DF_LEFT
- || command==Input::RIGHT || command==Input::DF_RIGHT)
+ if (command==Input::LEFT || command==Input::RIGHT)
{
buttons=true;
button[selected].setActive(1);
{
switch(command)
{
- case Input::DF_UP:
case Input::UP:
{
sl.up();
boxstack->update(this);
return 2;
}
- case Input::DF_DOWN:
case Input::DOWN:
{
sl.down();
{
switch(command)
{
- case Input::DF_UP:
case Input::UP:
{
sl.up();
BoxStack::getInstance()->update(this);
return 2;
}
- case Input::DF_DOWN:
case Input::DOWN:
{
sl.down();
{
switch(command)
{
- case Input::DF_UP:
case Input::UP:
{
sl.up();
BoxStack::getInstance()->update(this);
return 2;
}
- case Input::DF_DOWN:
case Input::DOWN:
{
sl.down();
+
/*
Copyright 2004-2005 Chris Tallon
switch(command)
{
/*
- case Input::DF_UP:
case Input::UP:
{
ViewMan::getInstance()->updateView(this);
return 2;
}
- case Input::DF_DOWN:
case Input::DOWN:
{
}
*/
case Input::LEFT:
- case Input::DF_RIGHT:
{
swap();
buttonBack.draw();
return 2;
}
case Input::RIGHT:
- case Input::DF_LEFT:
{
swap();
buttonBack.draw();
{
switch(command)
{
- case Input::DF_UP:
case Input::UP:
{
sl.up();
BoxStack::getInstance()->update(this);
return 2;
}
- case Input::DF_DOWN:
case Input::DOWN:
{
sl.down();
#include "i18n.h"
#include "wtextbox.h"
#include "input.h"
+#include "inputman.h"
#include "vaudioselector.h"
#include "colour.h"
#include "event.h"
return 4;
}
- // NEW REMOTE ONLY - navigate EPG, bring it onscreen if it's not there
+ // navigate EPG, bring it onscreen if it's not there
case Input::UP:
{
- if (Input::getInstance()->mayHaveFewButtons())
+ if (InputMan::getInstance()->mayHaveFewButtons())
{
if (okTriggeredOSD) doUpDown(false);
else doChanUpDown(UP);
}
case Input::DOWN:
{
- if (Input::getInstance()->mayHaveFewButtons())
+ if (InputMan::getInstance()->mayHaveFewButtons())
{
if (okTriggeredOSD) doUpDown(true);
else doChanUpDown(DOWN);
doLeftRight(true);
return 2;
}
- // Continue new remote only...
case Input::CHANNELUP:
{
doChanUpDown(UP);
doChanUpDown(DOWN);
return 2;
}
-
- // END NEW REMOTE ONLY, START OLD REMOTE ONLY
-
- // DF_LEFT and DF_RIGHT never get here because they are stolen
- // by command as vol- and vol+
-
- // Old remote. Decide what to do based on whether
- // OK was pressed - osd shown manually, use up/down for epg nav
- // UP/DOWN was pressed to change channel, osd was shown auto, use up/down for ch+/ch-
-
- case Input::DF_UP:
- {
- // Old remote, decide what to do based on okTriggeredOSD
- if (okTriggeredOSD) doUpDown(false);
- else doChanUpDown(UP);
- return 2;
- }
- case Input::DF_DOWN:
- {
- // Old remote, decide what to do based on okTriggeredOSD
- if (okTriggeredOSD) doUpDown(true);
- else doChanUpDown(DOWN);
- return 2;
- }
-
- // END NEW/OLD REMOTE STUFF
-
case Input::PREVCHANNEL:
{
channelChange(PREVIOUS, 0);
{
switch(command)
{
- case Input::DF_LEFT:
case Input::VOLUMEDOWN:
{
displayVolume = Audio::getInstance()->volumeDown();
// handled
return 2;
}
- case Input::DF_RIGHT:
case Input::VOLUMEUP:
{
displayVolume = Audio::getInstance()->volumeUp();
{
switch(command)
{
- case Input::DF_UP:
case Input::UP:
{
sl.up();
boxstack->update(this);
return 2;
}
- case Input::DF_DOWN:
case Input::DOWN:
{
sl.down();
{
switch(command)
{
- case Input::DF_UP:
case Input::UP:
{
if (selectedOption > 0)
return 1;
}
}
- case Input::DF_DOWN:
case Input::DOWN:
{
if (selectedOption < (numOptions - 1))
return 4; // Signal return control to parent
}
}
- case Input::DF_LEFT:
case Input::LEFT:
{
optionBoxes[selectedOption]->left();
return 1;
}
- case Input::DF_RIGHT:
case Input::RIGHT:
{
optionBoxes[selectedOption]->right();
{
switch(command)
{
- case Input::DF_UP:
case Input::UP:
{
if (cur_scroll_line > 0)
return 4; // Signal return control to parent
}
}
- case Input::DF_DOWN:
case Input::DOWN:
{
if (rem_scroll_line > 0)
}
case Input::LEFT:
case Input::RIGHT:
- case Input::DF_LEFT:
- case Input::DF_RIGHT:
{
return 5;
}
#include "wremoteconfig.h"
#include "input.h"
+#include "inputman.h"
#include "wsymbol.h"
#include "colour.h"
#include "i18n.h"
WRemoteConfig::WRemoteConfig()
{
- remote = Input::getInstance();
+ remote = InputMan::getInstance();
learnmode = false;
active = false;
ULONG i;
for (i = 0; i < 256; i++)
{
- const char * name = remote->CommandDesc((UCHAR)i);
+ const char * name = InputMan::CommandDesc((UCHAR)i);
if (name != NULL)
{
- char *line = remote->CommandTranslateStr((UCHAR)i);
+ //char *line = remote->CommandTranslateStr((UCHAR)i);
+
+ const char* line = "UNK,FIXME";
+
sl.addOption(line,i,0);
}
}
}
switch(command)
{
- case Input::DF_UP:
case Input::UP:
{
if (sl.getCurrentOption() != 0)
return 4; // return control to vopts
}
}
- case Input::DF_DOWN:
case Input::DOWN:
{
if (!active)
case Input::OK:
{
learnmode = true;
- remote->EnterLearningMode(sl.getCurrentOptionData());
+ // remote->EnterLearningMode(sl.getCurrentOptionData()); FIXME
return 1;
}
case Input::BACK:
}
case Input::MENU:
{
- remote->ResetToDefault();
+ // remote->ResetToDefault(); FIXME
initSelectList(false);
return 1;
}
private:
WSelectList sl;
- Input* remote;
+ InputMan* remote;
bool learnmode;
void initSelectList(bool startup);
bool active;
{
switch(command)
{
- case Input::DF_LEFT:
case Input::LEFT:
{
if (!left()) return 2;
draw();
return 1;
}
- case Input::DF_RIGHT:
case Input::RIGHT:
{
if (!right()) return 2;
return 1;
}
case Input::UP:
- case Input::DF_UP:
case Input::DOWN:
- case Input::DF_DOWN:
{
int handleResult = tabs[visiblePane].pane->handleCommand(command);
// A WOptionPane will accept control being passed into it from inactive, up or down (== 1).
{
switch(command)
{
- case Input::DF_UP:
case Input::UP:
{
if (cur_scroll_line > 0)
return 4; // Signal return control to parent
}
}
- case Input::DF_DOWN:
case Input::DOWN:
{
if (rem_scroll_line > 0)
}
case Input::LEFT:
case Input::RIGHT:
- case Input::DF_LEFT:
- case Input::DF_RIGHT:
{
return 5;
}
switch(command)
{
- case Input::DF_UP:
case Input::UP:
{
if (sl.getCurrentOption() != 0)
return 4; //Control to vopts control
}
}
- case Input::DF_DOWN:
case Input::DOWN:
{
Log::getInstance()->log("P", Log::DEBUG, "1");
switch(command)
{
- case Input::DF_UP:
case Input::UP:
{
if (sl.getCurrentOption() != 0)
return 4; //Control to vpots control
}
}
- case Input::DF_DOWN:
case Input::DOWN:
{
switch(command)
{
- case Input::DF_UP:
case Input::UP:
{
if (sl.getCurrentOption() != 0)
return 4; //Control to vopts control
}
}
- case Input::DF_DOWN:
case Input::DOWN:
{
sl.down();
switch(command)
{
- case Input::DF_UP:
case Input::UP:
{
if (sl.getCurrentOption() != 0)
return 4; //Control to vopts control
}
}
- case Input::DF_DOWN:
case Input::DOWN:
{
sl.down();