]> git.vomp.tv Git - vompclient.git/blob - inputlinux.cc
Rename Remote class to Input, RemoteLinux to InputLinux
[vompclient.git] / inputlinux.cc
1 /*
2     Copyright 2004-2020 Chris Tallon; 2012 Marten Richter
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include <linux/input.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <sys/ioctl.h>
24 #include <fcntl.h>
25 #include <errno.h>
26
27 #include <cstdio>
28 #include <iostream>
29 #include <ostream>
30
31 #include <bcm_host.h>
32
33 #include <libcec/cec.h>
34 #include <libcec/cecloader.h>
35 using namespace CEC;
36
37 #include "i18n.h"
38 #include "vdr.h"
39 #include "woptionpane.h"
40 #include "message.h"
41 #include "messagequeue.h"
42 #include "command.h" // FIXME - get rid after predefined message targets
43
44 #include "inputlinux.h"
45
46 #define W_G_HCW(type,code) ((static_cast<ULLONG>(type) << 32) | code)
47
48 #define W_HCW_KC 1 /* key code as defined by kernel for keyboard and remotes through /dev/input */
49 #define W_HCW_CEC 2 /* HDMI_CEC */
50 #define W_HCW_LIRC 3 /* remote control LIRC*/
51
52
53 InputLinux::InputLinux()
54 {
55 }
56
57 InputLinux::~InputLinux()
58 {
59   for (unsigned int i = 0; i < devices.size(); i++)
60   {
61     close(devices[i]);
62   }
63 }
64
65 #define test_bit(input,b)  ((1 << ((b) % 8))&(input)[b / 8] )
66
67 int InputLinux::init(const char*)
68 {
69   if (initted) return 0;
70   initted = 1;
71
72   InitKeymap();
73
74   for (int eventid = 0; eventid < 100; eventid++)
75   {
76     char buffer[1024];
77     sprintf(buffer,"/dev/input/event%d", eventid);
78
79     struct stat test_buf;
80     if (stat(buffer, &test_buf) == 0)
81     {
82       Log::getInstance()->log("InputLinux", Log::NOTICE, "Probe /dev/input/event%d", eventid);
83       // file exists
84       unsigned long ev_type = 0;
85       int new_fd = open(buffer, O_RDONLY);
86       if (new_fd < 0)
87       {
88         Log::getInstance()->log("InputLinux", Log::NOTICE, "Can not open /dev/input/event%d", eventid);
89         continue;
90       }
91
92       if (ioctl(new_fd, EVIOCGBIT(0, EV_MAX), &ev_type) < 0)
93       {
94         Log::getInstance()->log("InputLinux", Log::NOTICE, "Ioctl failed /dev/input/event%d %d", eventid, errno);
95         close(new_fd);
96       }
97
98       //Now test if it generates keyboard presses
99       if (test_bit(reinterpret_cast<char*>(&ev_type), EV_KEY))
100       {
101         Log::getInstance()->log("InputLinux", Log::NOTICE, "Add /dev/input/event%d to List", eventid);
102         devices.push_back(new_fd);
103
104         // Grab the device - make it exclusive to vomp. Fixes rubbish input going to console in background
105         ioctl(new_fd, EVIOCGRAB, 1);
106       }
107       else
108       {
109         close(new_fd);
110       }
111     }
112   }
113   return initCec();
114 }
115
116 int InputLinux::initCec() {
117
118   // bcm_host_init(); //may be move to custom hardware init?
119 // now init cec
120         Log::getInstance()->log("InputLinux", Log::NOTICE, "Init LibCEC");
121         cec_config.Clear();
122         cec_callbacks.Clear();
123 #if CEC_LIB_VERSION_MAJOR >= 4
124         cec_callbacks.logMessage = cecLogMessage;
125         cec_callbacks.keyPress = cecKeyPress;
126         cec_callbacks.commandReceived = cecCommand;
127         cec_callbacks.configurationChanged = cecConfigurationChanged;
128         cec_callbacks.sourceActivated = cecSourceActivated;
129 #else
130         cec_callbacks.CBCecLogMessage = cecLogMessage;
131         cec_callbacks.CBCecKeyPress = cecKeyPress;
132         cec_callbacks.CBCecCommand = cecCommand;
133         cec_callbacks.CBCecConfigurationChanged = cecConfigurationChanged;
134         cec_callbacks.CBCecSourceActivated = cecSourceActivated;
135         cec_config.bUseTVMenuLanguage=1;
136 #endif
137     cec_config.clientVersion=LIBCEC_VERSION_CURRENT;
138         cec_config.bActivateSource=1;
139         //cec_config.deviceTypes.Add(CEC_DEVICE_TYPE_PLAYBACK_DEVICE);
140         cec_config.deviceTypes.Add(CEC_DEVICE_TYPE_RECORDING_DEVICE);
141         //cec_config.deviceTypes.Add(CEC_DEVICE_TYPE_TUNER);
142
143         strncpy(cec_config.strDeviceName,"vomp",sizeof(cec_config.strDeviceName));
144
145
146         cec_config.callbackParam = NULL; // I do not care
147         cec_config.callbacks = &cec_callbacks;
148
149         cec_adap = LibCecInitialise(&cec_config);
150         if (!cec_adap) {
151                 Log::getInstance()->log("InputLinux", Log::ERR, "Init LibCEC failed");
152                 return 1;
153         }
154         cec_adap->InitVideoStandalone();
155
156
157 #if CEC_LIB_VERSION_MAJOR >= 4
158         cec_adapter_descriptor cec_adapter_descriptors[10];
159         int adap_num=cec_adap->DetectAdapters(cec_adapter_descriptors, 10);
160 #else
161         cec_adapter  cec_devices[10];
162         int adap_num=cec_adap->FindAdapters(cec_devices,10,NULL);
163 #endif
164         if (adap_num<0) {
165                 Log::getInstance()->log("InputLinux", Log::ERR, "CEC:Failed to find adapter");
166                 return 1;
167
168         }
169         if (adap_num==0) {
170                 Log::getInstance()->log("InputLinux", Log::NOTICE, "CEC: No adapter found");
171                 return 1;
172
173         }
174 #if CEC_LIB_VERSION_MAJOR >= 4
175         if (!cec_adap->Open(cec_adapter_descriptors[0].strComName)) {
176 #else
177         if (!cec_adap->Open(cec_devices[0].comm)) {
178 #endif
179       Log::getInstance()->log("InputLinux", Log::ERR, "CEC:Failed to open adapter");
180                 return 1;
181         }
182
183         if (!cec_adap->SetActiveSource(cec_config.deviceTypes[0])) {
184                 Log::getInstance()->log("InputLinux", Log::ERR, "CEC:Failed set active source");
185                 return 1;
186         }
187
188
189
190
191   return 1;
192 }
193
194 int InputLinux::shutdown()
195 {
196   if (!initted) return 0;
197
198   deinitCec();
199   while (devices.size())
200   {
201     int cur_fd = devices.back();
202     devices.pop_back();
203     ioctl(cur_fd, EVIOCGRAB, 0);
204     close(cur_fd);
205   }
206
207   initted = 0;
208   return 1;
209 }
210
211 void InputLinux::deinitCec()
212 {
213         if (cec_adap) {
214                 Log::getInstance()->log("InputLinux", Log::NOTICE, "Shutdown libcec begin");
215                 cec_adap->SetInactiveView();
216                 cec_adap->Close();
217                 vc_cec_register_callback(NULL, NULL);//deactivate callback!
218                 UnloadLibCec(cec_adap);
219                 cec_adap = NULL;
220                 Log::getInstance()->log("InputLinux", Log::NOTICE, "Shutdown libcec end");
221         }
222
223 }
224
225 UCHAR InputLinux::TranslateHWCFixed(ULLONG code)
226 {
227     switch (code) 
228     {
229     case W_G_HCW(W_HCW_KC, KEY_DOWN):
230         return DOWN;
231     case W_G_HCW(W_HCW_KC, KEY_UP):
232         return UP;
233     case W_G_HCW(W_HCW_KC, KEY_LEFT):
234         return LEFT;
235     case W_G_HCW(W_HCW_KC, KEY_RIGHT):
236         return RIGHT;
237     case W_G_HCW(W_HCW_KC, KEY_M):
238     case W_G_HCW(W_HCW_KC, KEY_MEDIA):
239         return MENU;
240     case W_G_HCW(W_HCW_KC, KEY_BACKSPACE):
241     case W_G_HCW(W_HCW_KC, KEY_EXIT):
242         return BACK;
243     case W_G_HCW(W_HCW_KC, KEY_ENTER):
244     case W_G_HCW(W_HCW_KC, KEY_SPACE):
245     case W_G_HCW(W_HCW_KC, KEY_OK):
246         return OK;
247
248     //CEC
249     case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_DOWN):
250         return DOWN;
251     case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_UP):
252         return UP;
253     case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_LEFT):
254         return LEFT;
255     case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_RIGHT):
256         return RIGHT;
257     case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_ROOT_MENU):
258     case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_CONTENTS_MENU):
259     case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_SETUP_MENU):
260         return MENU;
261     case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_EXIT ):
262         return BACK;
263     case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_ENTER):
264     case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_SELECT):
265     case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_AN_RETURN):
266         return OK;
267     case W_G_HCW(W_HCW_KC, KEY_SLEEP):
268     case W_G_HCW(W_HCW_KC, KEY_POWER):
269     case W_G_HCW(W_HCW_KC, KEY_ESC):
270     case W_G_HCW(W_HCW_CEC, CEC_USER_CONTROL_CODE_POWER):
271     case POWER:
272         return POWER;
273     default:
274         return NA_UNKNOWN;
275     };
276 }
277
278 const char* InputLinux::HardcodedTranslateStr(UCHAR command)
279 {
280   switch (command)
281   {
282     case DOWN:
283       return tr("Down");
284     case UP:
285       return tr("Up");
286     case LEFT:
287       return tr("Left");
288     case RIGHT:
289       return tr("Right");
290     case MENU:
291       return tr("M");
292     case BACK:
293       return tr("Backspace, Back");
294     case OK:
295       return tr("Return, Space");
296     default:
297       return NULL;
298   }
299 }
300
301
302 void InputLinux::InitHWCListwithDefaults()
303 {
304   // Processing VK_Messages
305   translist[W_G_HCW(W_HCW_KC,KEY_9)] = NINE;
306   translist[W_G_HCW(W_HCW_KC,KEY_8)] = EIGHT;
307   translist[W_G_HCW(W_HCW_KC,KEY_7)] = SEVEN;
308   translist[W_G_HCW(W_HCW_KC,KEY_6)] = SIX;
309   translist[W_G_HCW(W_HCW_KC,KEY_5)] = FIVE;
310   translist[W_G_HCW(W_HCW_KC,KEY_4)] = FOUR;
311   translist[W_G_HCW(W_HCW_KC,KEY_3)] = THREE;
312   translist[W_G_HCW(W_HCW_KC,KEY_2)] = TWO;
313   translist[W_G_HCW(W_HCW_KC,KEY_1)] = ONE;
314   translist[W_G_HCW(W_HCW_KC,KEY_0)] = ZERO;
315   translist[W_G_HCW(W_HCW_KC,KEY_KPDOT)] = STAR;
316   // translist[W_G_HCW(W_HCW_KC,KEY_#)] = HASH;
317
318   translist[W_G_HCW(W_HCW_KC,KEY_KP9)] = NINE;
319   translist[W_G_HCW(W_HCW_KC,KEY_KP8)] = EIGHT;
320   translist[W_G_HCW(W_HCW_KC,KEY_KP7)] = SEVEN;
321   translist[W_G_HCW(W_HCW_KC,KEY_KP6)] = SIX;
322   translist[W_G_HCW(W_HCW_KC,KEY_KP5)] = FIVE;
323   translist[W_G_HCW(W_HCW_KC,KEY_KP4)] = FOUR;
324   translist[W_G_HCW(W_HCW_KC,KEY_KP3)] = THREE;
325   translist[W_G_HCW(W_HCW_KC,KEY_KP2)] = TWO;
326   translist[W_G_HCW(W_HCW_KC,KEY_KP1)] = ONE;
327   translist[W_G_HCW(W_HCW_KC,KEY_KP0)] = ZERO;
328
329   translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_9)] = NINE;
330   translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_8)] = EIGHT;
331   translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_7)] = SEVEN;
332   translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_6)] = SIX;
333   translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_5)] = FIVE;
334   translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_4)] = FOUR;
335   translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_3)] = THREE;
336   translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_2)] = TWO;
337   translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_1)] = ONE;
338   translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_0)] = ZERO;
339   translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_STAR)] = STAR;
340   translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_POUND)] = HASH;
341
342
343   translist[W_G_HCW(W_HCW_KC,KEY_J)] = GO; //j for JUMP TO instead of go to
344   translist[W_G_HCW(W_HCW_KC,KEY_R)] = RED;
345   translist[W_G_HCW(W_HCW_KC,KEY_G)] = GREEN;
346   translist[W_G_HCW(W_HCW_KC,KEY_Y)] = YELLOW;
347   translist[W_G_HCW(W_HCW_KC,KEY_B)] = BLUE;
348   //Processing Remote Style Messages
349   translist[W_G_HCW(W_HCW_KC,KEY_GREEN)] = GREEN;
350   translist[W_G_HCW(W_HCW_KC,KEY_RED)] = RED;
351   translist[W_G_HCW(W_HCW_KC,KEY_YELLOW)] = YELLOW;
352   translist[W_G_HCW(W_HCW_KC,KEY_BLUE)] = BLUE;
353   translist[W_G_HCW(W_HCW_KC,KEY_MENU)] = MENU;
354
355   translist[W_G_HCW(W_HCW_KC,KEY_RECORD)] = RECORD;
356   translist[W_G_HCW(W_HCW_KC,KEY_PLAY)] = PLAY; //Playback Televison
357   translist[W_G_HCW(W_HCW_KC,KEY_PAUSE)] = PAUSE;
358   translist[W_G_HCW(W_HCW_KC,KEY_STOP)] = STOP;
359   translist[W_G_HCW(W_HCW_KC,KEY_PLAYPAUSE)] = PLAYPAUSE;
360   translist[W_G_HCW(W_HCW_KC,KEY_P)] = PLAYPAUSE;
361   translist[W_G_HCW(W_HCW_KC,KEY_NEXT)] = SKIPFORWARD;
362   translist[W_G_HCW(W_HCW_KC,KEY_F2)] = SKIPFORWARD;
363   translist[W_G_HCW(W_HCW_KC,KEY_PREVIOUS)] = SKIPBACK;
364   translist[W_G_HCW(W_HCW_KC,KEY_F1)] = SKIPBACK;
365   translist[W_G_HCW(W_HCW_KC,KEY_FORWARD)] = FORWARD;
366   translist[W_G_HCW(W_HCW_KC,KEY_FASTFORWARD)] = FORWARD;
367   translist[W_G_HCW(W_HCW_KC,KEY_F)] = FORWARD;
368   translist[W_G_HCW(W_HCW_KC,KEY_BACK)] = REVERSE;
369   translist[W_G_HCW(W_HCW_KC,KEY_REWIND)] = REVERSE;
370   translist[W_G_HCW(W_HCW_KC,KEY_T)] = REVERSE;
371   translist[W_G_HCW(W_HCW_KC,KEY_MUTE)] = MUTE;
372   translist[W_G_HCW(W_HCW_KC,KEY_F8)] = MUTE;
373   translist[W_G_HCW(W_HCW_KC,KEY_F10)] = VOLUMEUP;
374   translist[W_G_HCW(W_HCW_KC,KEY_F9)] = VOLUMEDOWN;
375   translist[W_G_HCW(W_HCW_KC,KEY_VOLUMEUP)] = VOLUMEUP;
376   translist[W_G_HCW(W_HCW_KC,KEY_VOLUMEDOWN)] = VOLUMEDOWN;
377   translist[W_G_HCW(W_HCW_KC,KEY_CHANNELUP)] = CHANNELUP;
378   translist[W_G_HCW(W_HCW_KC,KEY_CHANNELDOWN)] = CHANNELDOWN;
379   translist[W_G_HCW(W_HCW_KC,KEY_PAGEUP)] = CHANNELUP;
380   translist[W_G_HCW(W_HCW_KC,KEY_PAGEDOWN)] = CHANNELDOWN;
381
382
383   //Processing CEC_Messages
384   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER9)] = NINE;
385   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER8)] = EIGHT;
386   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER7)] = SEVEN;
387   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER6)] = SIX;
388   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER5)] = FIVE;
389   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER4)] = FOUR;
390   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER3)] = THREE;
391   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER2)] = TWO;
392   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER1)] = ONE;
393   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_NUMBER0)] = ZERO;
394   //translist[W_G_HCW(W_HCW_CEC,KEY_KPDOT)] = STAR;
395
396
397
398   //translist[W_G_HCW(W_HCW_CEC,KEY_J)] = GO; //j for JUMP TO instead of go to
399   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_F2_RED)] = RED;
400   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_F3_GREEN)] = GREEN;
401   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_F4_YELLOW)] = YELLOW;
402   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_F1_BLUE)] = BLUE;
403   //Processing Remote Style Messages
404   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_FAVORITE_MENU)] = MENU;
405
406   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_RECORD)] = RECORD;
407   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_PLAY)] = PLAY; //Playback Televison
408   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_PAUSE)] = PAUSE;
409   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_STOP)] = STOP;
410   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION)] = PLAYPAUSE;
411   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_FORWARD)] = SKIPFORWARD;
412   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_BACKWARD)] = SKIPBACK;
413   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_FAST_FORWARD )] = FORWARD;
414   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_REWIND)] = REVERSE;
415   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_MUTE)] = MUTE;
416   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_VOLUME_UP)] = VOLUMEUP;
417   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_VOLUME_DOWN)] = VOLUMEDOWN;
418   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_CHANNEL_UP )] = CHANNELUP;
419   translist[W_G_HCW(W_HCW_CEC,CEC_USER_CONTROL_CODE_CHANNEL_DOWN)] = CHANNELDOWN;
420 }
421
422 #define NAMETRICK(pre, code) linux_keymap[pre ## code]=  #code
423 #define NAMETRICK2(pre, code) cec_keymap[pre ## code]=  #code
424 //extracte from linux/input.h
425
426 static const char * linux_keymap[KEY_MAX+1];
427 static const char * cec_keymap[CEC_USER_CONTROL_CODE_MAX+1];
428
429 void InputLinux::InitKeymap()
430 {
431   for (int i=0;i<KEY_MAX+1;i++)
432   {
433     linux_keymap[i] = NULL;
434   }
435
436   NAMETRICK(KEY_,RESERVED);
437   NAMETRICK(KEY_,ESC);
438   NAMETRICK(KEY_,1);
439   NAMETRICK(KEY_,2);
440   NAMETRICK(KEY_,3);
441   NAMETRICK(KEY_,4);
442   NAMETRICK(KEY_,5);
443   NAMETRICK(KEY_,6);
444   NAMETRICK(KEY_,7);
445   NAMETRICK(KEY_,8);
446   NAMETRICK(KEY_,9);
447   NAMETRICK(KEY_,0);
448   NAMETRICK(KEY_,MINUS);
449   NAMETRICK(KEY_,EQUAL);
450   NAMETRICK(KEY_,BACKSPACE);
451   NAMETRICK(KEY_,TAB);
452   NAMETRICK(KEY_,Q);
453   NAMETRICK(KEY_,W);
454   NAMETRICK(KEY_,E);
455   NAMETRICK(KEY_,R);
456   NAMETRICK(KEY_,T);
457   NAMETRICK(KEY_,Y);
458   NAMETRICK(KEY_,U);
459   NAMETRICK(KEY_,I);
460   NAMETRICK(KEY_,O);
461   NAMETRICK(KEY_,P);
462   NAMETRICK(KEY_,LEFTBRACE);
463   NAMETRICK(KEY_,RIGHTBRACE);
464   NAMETRICK(KEY_,ENTER);
465   NAMETRICK(KEY_,LEFTCTRL);
466   NAMETRICK(KEY_,A);
467   NAMETRICK(KEY_,S);
468   NAMETRICK(KEY_,D);
469   NAMETRICK(KEY_,F);
470   NAMETRICK(KEY_,G);
471   NAMETRICK(KEY_,H);
472   NAMETRICK(KEY_,J);
473   NAMETRICK(KEY_,K);
474   NAMETRICK(KEY_,L);
475   NAMETRICK(KEY_,SEMICOLON);
476   NAMETRICK(KEY_,APOSTROPHE);
477   NAMETRICK(KEY_,GRAVE);
478   NAMETRICK(KEY_,LEFTSHIFT);
479   NAMETRICK(KEY_,BACKSLASH);
480   NAMETRICK(KEY_,Z);
481   NAMETRICK(KEY_,X);
482   NAMETRICK(KEY_,C);
483   NAMETRICK(KEY_,V);
484   NAMETRICK(KEY_,B);
485   NAMETRICK(KEY_,N);
486   NAMETRICK(KEY_,M);
487   NAMETRICK(KEY_,COMMA);
488   NAMETRICK(KEY_,DOT);
489   NAMETRICK(KEY_,SLASH);
490   NAMETRICK(KEY_,RIGHTSHIFT);
491   NAMETRICK(KEY_,KPASTERISK);
492   NAMETRICK(KEY_,LEFTALT);
493   NAMETRICK(KEY_,SPACE);
494   NAMETRICK(KEY_,CAPSLOCK);
495   NAMETRICK(KEY_,F1);
496   NAMETRICK(KEY_,F2);
497   NAMETRICK(KEY_,F3);
498   NAMETRICK(KEY_,F4);
499   NAMETRICK(KEY_,F5);
500   NAMETRICK(KEY_,F6);
501   NAMETRICK(KEY_,F7);
502   NAMETRICK(KEY_,F8);
503   NAMETRICK(KEY_,F9);
504   NAMETRICK(KEY_,F10);
505   NAMETRICK(KEY_,NUMLOCK);
506   NAMETRICK(KEY_,SCROLLLOCK);
507   NAMETRICK(KEY_,KP7);
508   NAMETRICK(KEY_,KP8);
509   NAMETRICK(KEY_,KP9);
510   NAMETRICK(KEY_,KPMINUS);
511   NAMETRICK(KEY_,KP4);
512   NAMETRICK(KEY_,KP5);
513   NAMETRICK(KEY_,KP6);
514   NAMETRICK(KEY_,KPPLUS);
515   NAMETRICK(KEY_,KP1);
516   NAMETRICK(KEY_,KP2);
517   NAMETRICK(KEY_,KP3);
518   NAMETRICK(KEY_,KP0);
519   NAMETRICK(KEY_,KPDOT);
520   NAMETRICK(KEY_,F11);
521   NAMETRICK(KEY_,F12);
522   NAMETRICK(KEY_,KPENTER);
523   NAMETRICK(KEY_,RIGHTCTRL);
524   NAMETRICK(KEY_,KPSLASH);
525   NAMETRICK(KEY_,SYSRQ);
526   NAMETRICK(KEY_,RIGHTALT);
527   NAMETRICK(KEY_,LINEFEED);
528   NAMETRICK(KEY_,HOME);
529   NAMETRICK(KEY_,UP);
530   NAMETRICK(KEY_,PAGEUP);
531   NAMETRICK(KEY_,LEFT);
532   NAMETRICK(KEY_,RIGHT);
533   NAMETRICK(KEY_,END);
534   NAMETRICK(KEY_,DOWN);
535   NAMETRICK(KEY_,PAGEDOWN);
536   NAMETRICK(KEY_,INSERT);
537   NAMETRICK(KEY_,DELETE);
538   NAMETRICK(KEY_,MACRO);
539   NAMETRICK(KEY_,MUTE);
540   NAMETRICK(KEY_,VOLUMEDOWN);
541   NAMETRICK(KEY_,VOLUMEUP);
542   NAMETRICK(KEY_,POWER);
543   NAMETRICK(KEY_,KPEQUAL);
544   NAMETRICK(KEY_,KPPLUSMINUS);
545   NAMETRICK(KEY_,PLAY);
546   NAMETRICK(KEY_,PAUSE);
547   NAMETRICK(KEY_,SCALE);
548   NAMETRICK(KEY_,KPCOMMA);
549   NAMETRICK(KEY_,YEN);
550   NAMETRICK(KEY_,LEFTMETA);
551   NAMETRICK(KEY_,RIGHTMETA);
552   NAMETRICK(KEY_,COMPOSE);
553   NAMETRICK(KEY_,STOP);
554   NAMETRICK(KEY_,AGAIN);
555   NAMETRICK(KEY_,PROPS);
556   NAMETRICK(KEY_,UNDO);
557   NAMETRICK(KEY_,FRONT);
558   NAMETRICK(KEY_,COPY);
559   NAMETRICK(KEY_,OPEN);
560   NAMETRICK(KEY_,PASTE);
561   NAMETRICK(KEY_,FIND);
562   NAMETRICK(KEY_,CUT);
563   NAMETRICK(KEY_,HELP);
564   NAMETRICK(KEY_,MENU);
565   NAMETRICK(KEY_,CALC);
566   NAMETRICK(KEY_,SETUP);
567   NAMETRICK(KEY_,SLEEP);
568   NAMETRICK(KEY_,WAKEUP);
569   NAMETRICK(KEY_,FILE);
570   NAMETRICK(KEY_,SENDFILE);
571   NAMETRICK(KEY_,DELETEFILE);
572   NAMETRICK(KEY_,XFER);
573   NAMETRICK(KEY_,PROG1);
574   NAMETRICK(KEY_,PROG2);
575   NAMETRICK(KEY_,WWW);
576   NAMETRICK(KEY_,MSDOS);
577   NAMETRICK(KEY_,COFFEE);
578   NAMETRICK(KEY_,DIRECTION);
579   NAMETRICK(KEY_,CYCLEWINDOWS);
580   NAMETRICK(KEY_,MAIL);
581   NAMETRICK(KEY_,BOOKMARKS);
582   NAMETRICK(KEY_,COMPUTER);
583   NAMETRICK(KEY_,BACK);
584   NAMETRICK(KEY_,FORWARD);
585   NAMETRICK(KEY_,FASTFORWARD);
586   NAMETRICK(KEY_,CLOSECD);
587   NAMETRICK(KEY_,EJECTCD);
588   NAMETRICK(KEY_,EJECTCLOSECD);
589   NAMETRICK(KEY_,NEXTSONG);
590   NAMETRICK(KEY_,PLAYPAUSE);
591   NAMETRICK(KEY_,PREVIOUSSONG);
592   NAMETRICK(KEY_,STOPCD);
593   NAMETRICK(KEY_,RECORD);
594   NAMETRICK(KEY_,REWIND);
595   NAMETRICK(KEY_,PHONE);
596   NAMETRICK(KEY_,ISO);
597   NAMETRICK(KEY_,CONFIG);
598   NAMETRICK(KEY_,HOMEPAGE);
599   NAMETRICK(KEY_,REFRESH);
600   NAMETRICK(KEY_,EXIT);
601   NAMETRICK(KEY_,MOVE);
602   NAMETRICK(KEY_,EDIT);
603   NAMETRICK(KEY_,SCROLLUP);
604   NAMETRICK(KEY_,SCROLLDOWN);
605   NAMETRICK(KEY_,KPLEFTPAREN);
606   NAMETRICK(KEY_,KPRIGHTPAREN);
607   NAMETRICK(KEY_,NEW);
608   NAMETRICK(KEY_,REDO);
609   NAMETRICK(KEY_,OK);
610   NAMETRICK(KEY_,SELECT);
611   NAMETRICK(KEY_,GOTO);
612   NAMETRICK(KEY_,CLEAR);
613   NAMETRICK(KEY_,POWER2);
614   NAMETRICK(KEY_,OPTION);
615   NAMETRICK(KEY_,INFO);
616   NAMETRICK(KEY_,TIME);
617   NAMETRICK(KEY_,VENDOR);
618   NAMETRICK(KEY_,ARCHIVE);
619   NAMETRICK(KEY_,PROGRAM);
620   NAMETRICK(KEY_,CHANNEL);
621   NAMETRICK(KEY_,FAVORITES);
622   NAMETRICK(KEY_,EPG);
623   NAMETRICK(KEY_,PVR);
624   NAMETRICK(KEY_,MHP);
625   NAMETRICK(KEY_,LANGUAGE);
626   NAMETRICK(KEY_,TITLE);
627   NAMETRICK(KEY_,SUBTITLE);
628   NAMETRICK(KEY_,ANGLE);
629   NAMETRICK(KEY_,ZOOM);
630   NAMETRICK(KEY_,MODE);
631   NAMETRICK(KEY_,KEYBOARD);
632   NAMETRICK(KEY_,SCREEN);
633   NAMETRICK(KEY_,RED);
634   NAMETRICK(KEY_,GREEN);
635   NAMETRICK(KEY_,YELLOW);
636   NAMETRICK(KEY_,BLUE);
637   NAMETRICK(KEY_,CHANNELUP);
638   NAMETRICK(KEY_,CHANNELDOWN);
639   NAMETRICK(KEY_,FIRST);
640   NAMETRICK(KEY_,LAST);
641   NAMETRICK(KEY_,AB);
642   NAMETRICK(KEY_,NEXT);
643   NAMETRICK(KEY_,RESTART);
644   NAMETRICK(KEY_,SLOW);
645   NAMETRICK(KEY_,SHUFFLE);
646   NAMETRICK(KEY_,BREAK);
647   NAMETRICK(KEY_,PREVIOUS);
648   NAMETRICK(KEY_,DIGITS);
649   NAMETRICK(KEY_,TEEN);
650   NAMETRICK(KEY_,TWEN);
651   NAMETRICK(KEY_,VIDEOPHONE);
652   NAMETRICK(KEY_,GAMES);
653   NAMETRICK(KEY_,ZOOMIN);
654   NAMETRICK(KEY_,ZOOMOUT);
655   NAMETRICK(KEY_,ZOOMRESET);
656   NAMETRICK(KEY_,DOLLAR);
657   NAMETRICK(KEY_,EURO);
658   NAMETRICK(KEY_,MEDIA);
659   NAMETRICK(KEY_,FRAMEBACK);
660   NAMETRICK(KEY_,FRAMEFORWARD);
661   NAMETRICK(KEY_,CONTEXT_MENU);
662   NAMETRICK(KEY_,MEDIA_REPEAT);
663   NAMETRICK(KEY_,NUMERIC_0);
664   NAMETRICK(KEY_,NUMERIC_1);
665   NAMETRICK(KEY_,NUMERIC_2);
666   NAMETRICK(KEY_,NUMERIC_3);
667   NAMETRICK(KEY_,NUMERIC_4);
668   NAMETRICK(KEY_,NUMERIC_5);
669   NAMETRICK(KEY_,NUMERIC_6);
670   NAMETRICK(KEY_,NUMERIC_7);
671   NAMETRICK(KEY_,NUMERIC_8);
672   NAMETRICK(KEY_,NUMERIC_9);
673   NAMETRICK(KEY_,NUMERIC_STAR);
674   NAMETRICK(KEY_,NUMERIC_POUND);
675
676   for (int i=0; i < CEC_USER_CONTROL_CODE_MAX + 1; i++)
677   {
678     cec_keymap[i] = NULL;
679   }
680
681   NAMETRICK2(CEC_USER_CONTROL_CODE_,SELECT);
682   NAMETRICK2(CEC_USER_CONTROL_CODE_,UP);
683   NAMETRICK2(CEC_USER_CONTROL_CODE_,DOWN);
684   NAMETRICK2(CEC_USER_CONTROL_CODE_,LEFT);
685   NAMETRICK2(CEC_USER_CONTROL_CODE_,RIGHT);
686   NAMETRICK2(CEC_USER_CONTROL_CODE_,RIGHT_UP);
687   NAMETRICK2(CEC_USER_CONTROL_CODE_,RIGHT_DOWN);
688   NAMETRICK2(CEC_USER_CONTROL_CODE_,LEFT_UP);
689   NAMETRICK2(CEC_USER_CONTROL_CODE_,LEFT_DOWN);
690   NAMETRICK2(CEC_USER_CONTROL_CODE_,ROOT_MENU);
691   NAMETRICK2(CEC_USER_CONTROL_CODE_,SETUP_MENU);
692   NAMETRICK2(CEC_USER_CONTROL_CODE_,CONTENTS_MENU);
693   NAMETRICK2(CEC_USER_CONTROL_CODE_,FAVORITE_MENU);
694   NAMETRICK2(CEC_USER_CONTROL_CODE_,EXIT);
695   NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER0);
696   NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER1);
697   NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER2);
698   NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER3);
699   NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER4);
700   NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER5);
701   NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER6);
702   NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER7);
703   NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER8);
704   NAMETRICK2(CEC_USER_CONTROL_CODE_,NUMBER9);
705   NAMETRICK2(CEC_USER_CONTROL_CODE_,DOT);
706   NAMETRICK2(CEC_USER_CONTROL_CODE_,ENTER);
707   NAMETRICK2(CEC_USER_CONTROL_CODE_,CLEAR);
708   NAMETRICK2(CEC_USER_CONTROL_CODE_,NEXT_FAVORITE);
709   NAMETRICK2(CEC_USER_CONTROL_CODE_,CHANNEL_UP);
710   NAMETRICK2(CEC_USER_CONTROL_CODE_,CHANNEL_DOWN);
711   NAMETRICK2(CEC_USER_CONTROL_CODE_,PREVIOUS_CHANNEL);
712   NAMETRICK2(CEC_USER_CONTROL_CODE_,SOUND_SELECT);
713   NAMETRICK2(CEC_USER_CONTROL_CODE_,INPUT_SELECT);
714   NAMETRICK2(CEC_USER_CONTROL_CODE_,DISPLAY_INFORMATION);
715   NAMETRICK2(CEC_USER_CONTROL_CODE_,HELP);
716   NAMETRICK2(CEC_USER_CONTROL_CODE_,PAGE_UP);
717   NAMETRICK2(CEC_USER_CONTROL_CODE_,PAGE_DOWN);
718   NAMETRICK2(CEC_USER_CONTROL_CODE_,POWER );
719   NAMETRICK2(CEC_USER_CONTROL_CODE_,VOLUME_UP );
720   NAMETRICK2(CEC_USER_CONTROL_CODE_,VOLUME_DOWN );
721   NAMETRICK2(CEC_USER_CONTROL_CODE_,MUTE );
722   NAMETRICK2(CEC_USER_CONTROL_CODE_,PLAY );
723   NAMETRICK2(CEC_USER_CONTROL_CODE_,STOP );
724   NAMETRICK2(CEC_USER_CONTROL_CODE_,PAUSE );
725   NAMETRICK2(CEC_USER_CONTROL_CODE_,RECORD );
726   NAMETRICK2(CEC_USER_CONTROL_CODE_,REWIND );
727   NAMETRICK2(CEC_USER_CONTROL_CODE_,FAST_FORWARD );
728   NAMETRICK2(CEC_USER_CONTROL_CODE_,EJECT );
729   NAMETRICK2(CEC_USER_CONTROL_CODE_,FORWARD );
730   NAMETRICK2(CEC_USER_CONTROL_CODE_,BACKWARD );
731   NAMETRICK2(CEC_USER_CONTROL_CODE_,STOP_RECORD );
732   NAMETRICK2(CEC_USER_CONTROL_CODE_,PAUSE_RECORD );
733   NAMETRICK2(CEC_USER_CONTROL_CODE_,ANGLE );
734   NAMETRICK2(CEC_USER_CONTROL_CODE_,SUB_PICTURE );
735   NAMETRICK2(CEC_USER_CONTROL_CODE_,VIDEO_ON_DEMAND );
736   NAMETRICK2(CEC_USER_CONTROL_CODE_,ELECTRONIC_PROGRAM_GUIDE );
737   NAMETRICK2(CEC_USER_CONTROL_CODE_,TIMER_PROGRAMMING );
738   NAMETRICK2(CEC_USER_CONTROL_CODE_,INITIAL_CONFIGURATION );
739   NAMETRICK2(CEC_USER_CONTROL_CODE_,PLAY_FUNCTION );
740   NAMETRICK2(CEC_USER_CONTROL_CODE_,PAUSE_PLAY_FUNCTION );
741   NAMETRICK2(CEC_USER_CONTROL_CODE_,RECORD_FUNCTION );
742   NAMETRICK2(CEC_USER_CONTROL_CODE_,PAUSE_RECORD_FUNCTION );
743   NAMETRICK2(CEC_USER_CONTROL_CODE_,STOP_FUNCTION );
744   NAMETRICK2(CEC_USER_CONTROL_CODE_,MUTE_FUNCTION );
745   NAMETRICK2(CEC_USER_CONTROL_CODE_,RESTORE_VOLUME_FUNCTION );
746   NAMETRICK2(CEC_USER_CONTROL_CODE_,TUNE_FUNCTION );
747   NAMETRICK2(CEC_USER_CONTROL_CODE_,SELECT_MEDIA_FUNCTION );
748   NAMETRICK2(CEC_USER_CONTROL_CODE_,SELECT_AV_INPUT_FUNCTION );
749   NAMETRICK2(CEC_USER_CONTROL_CODE_,SELECT_AUDIO_INPUT_FUNCTION );
750   NAMETRICK2(CEC_USER_CONTROL_CODE_,POWER_TOGGLE_FUNCTION );
751   NAMETRICK2(CEC_USER_CONTROL_CODE_,POWER_OFF_FUNCTION );
752   NAMETRICK2(CEC_USER_CONTROL_CODE_,POWER_ON_FUNCTION );
753   NAMETRICK2(CEC_USER_CONTROL_CODE_,F1_BLUE );
754   NAMETRICK2(CEC_USER_CONTROL_CODE_,F2_RED );
755   NAMETRICK2(CEC_USER_CONTROL_CODE_,F3_GREEN );
756   NAMETRICK2(CEC_USER_CONTROL_CODE_,F4_YELLOW );
757   NAMETRICK2(CEC_USER_CONTROL_CODE_,F5 );
758   NAMETRICK2(CEC_USER_CONTROL_CODE_,DATA );
759   NAMETRICK2(CEC_USER_CONTROL_CODE_,AN_RETURN );
760   NAMETRICK2(CEC_USER_CONTROL_CODE_,AN_CHANNELS_LIST );
761   NAMETRICK2(CEC_USER_CONTROL_CODE_,MAX );
762 }
763
764
765
766 char* InputLinux::HCWDesc(unsigned long long hcw)
767 {
768     //Determine type
769     unsigned int type = static_cast<unsigned int>(hcw >> 32);
770     unsigned int vk = static_cast<ULONG>(hcw);
771     char* rt = NULL;
772
773     switch(type)
774     {
775       case W_HCW_KC:
776       {
777         rt = new char[10];
778         const char *desc=linux_keymap[vk];
779         if (desc)
780           strncpy(rt, desc, 9);
781         else
782           sprintf(rt, "0x%x", vk);
783         break;
784       }
785       case W_HCW_CEC:
786       {
787         rt = new char[10];
788         const char* desc = cec_keymap[vk];
789         if (desc)
790           strncpy(rt, desc, 9);
791         else
792           sprintf(rt, "0x%x", vk);
793         break;
794       }
795   /*
796     case W_HCW_LIRC:{
797         ULONG ri=(ULONG)hcw;
798         rt=new char[10];
799         sprintf(rt,"R: %X",ri);
800                   }break;*/
801     }
802
803     return rt;
804 }
805
806 void InputLinux::changePowerState(bool poweron)
807 {
808   if (cec_adap)
809   {
810     if (poweron)
811     {
812       //Log::getInstance()->log("InputLinux", Log::DEBUG, "CEC set active source");
813       cec_adap->SetActiveSource(cec_config.deviceTypes[0]);
814     }
815     else
816     {
817       //Log::getInstance()->log("InputLinux", Log::DEBUG, "CEC set inactive view");
818       cec_adap->SetInactiveView();
819     }
820   }
821 }
822
823 #if CEC_LIB_VERSION_MAJOR >= 4
824
825 // libcec4 API changed these params to pointers rather than copies, and the returns to void
826 // Otherwise, these two blocks of code are the same
827
828 void InputLinux::cecLogMessage(void* /* param */, const cec_log_message* message)
829 {
830   Log::getInstance()->log("InputLinux", Log::DEBUG, "CECLOG: %lld %d %s", message->time, message->level, message->message);
831 }
832
833 void InputLinux::cecKeyPress(void* /* param */, const cec_keypress* key)
834 {
835   //Log::getInstance()->log("InputLinux", Log::DEBUG, "Incoming cec key %d %d", key->keycode,key->duration);
836   if (key->duration == 0) static_cast<InputLinux*>(Input::getInstance())->incomingCECkey(key->keycode);
837 }
838
839 void InputLinux::cecCommand(void* /* param */, const cec_command* command)
840 {
841         Log::getInstance()->log("InputLinux", Log::DEBUG, "CECCommand: %d",command->opcode);
842         switch (command->opcode) {
843         case CEC_OPCODE_STANDBY: {
844                 if (command->initiator==CECDEVICE_TV) {
845                         static_cast<InputLinux*>(Input::getInstance())->incomingPowerkey(POWEROFF);
846                 }
847         } break;
848         case CEC_OPCODE_DECK_CONTROL: {
849                 if (command->initiator==CECDEVICE_TV && command->parameters.size == 1
850                                 && command->parameters[0]==CEC_DECK_CONTROL_MODE_STOP) {
851                         static_cast<InputLinux*>(Input::getInstance())->incomingCECkey(CEC_USER_CONTROL_CODE_STOP);
852
853                 }
854
855         } break;
856         case CEC_OPCODE_PLAY: {
857                 if (command->initiator==CECDEVICE_TV && command->parameters.size == 1) {
858                         if (command->parameters[0]==CEC_PLAY_MODE_PLAY_FORWARD) {
859                                 static_cast<InputLinux*>(Input::getInstance())->incomingCECkey(CEC_USER_CONTROL_CODE_PLAY);
860                         } else if (command->parameters[0]==CEC_PLAY_MODE_PLAY_STILL) {
861                                 static_cast<InputLinux*>(Input::getInstance())->incomingCECkey(CEC_USER_CONTROL_CODE_PAUSE);
862                         }
863                 }
864
865
866         } break;
867         default:
868                 break;
869         };
870 }
871
872 void InputLinux::cecConfigurationChanged(void* /* param */, const libcec_configuration*)
873 {
874         Log::getInstance()->log("InputLinux", Log::DEBUG, "CECConfig:"/*,config->string()*/);
875 }
876
877 #else
878
879 int InputLinux::cecLogMessage(void *param, const cec_log_message message)
880 {
881   Log::getInstance()->log("InputLinux", Log::DEBUG, "CECLOG: %lld %d %s", message.time, message.level, message.message);
882   return 0;
883 }
884
885 int InputLinux::cecKeyPress(void*param, const cec_keypress key)
886 {
887   //Log::getInstance()->log("InputLinux", Log::DEBUG, "Incoming cec key %d %d", key.keycode,key.duration);
888   if (key.duration == 0) ((InputLinux*)Input::getInstance())->incomingCECkey(key.keycode);
889   return 1;
890 }
891
892 int InputLinux::cecCommand(void *param, const cec_command command)
893 {
894         Log::getInstance()->log("InputLinux", Log::DEBUG, "CECCommand: %d",command.opcode);
895         switch (command.opcode) {
896         case CEC_OPCODE_STANDBY: {
897                 if (command.initiator==CECDEVICE_TV) {
898                         ((InputLinux*)Input::getInstance())->incomingPowerkey(POWEROFF);
899                 }
900         } break;
901         case CEC_OPCODE_DECK_CONTROL: {
902                 if (command.initiator==CECDEVICE_TV && command.parameters.size == 1
903                                 && command.parameters[0]==CEC_DECK_CONTROL_MODE_STOP) {
904                         ((InputLinux*)Input::getInstance())->incomingCECkey(CEC_USER_CONTROL_CODE_STOP);
905
906                 }
907
908         } break;
909         case CEC_OPCODE_PLAY: {
910                 if (command.initiator==CECDEVICE_TV && command.parameters.size == 1) {
911                         if (command.parameters[0]==CEC_PLAY_MODE_PLAY_FORWARD) {
912                                 ((InputLinux*)Input::getInstance())->incomingCECkey(CEC_USER_CONTROL_CODE_PLAY);
913                         } else if (command.parameters[0]==CEC_PLAY_MODE_PLAY_STILL) {
914                                 ((InputLinux*)Input::getInstance())->incomingCECkey(CEC_USER_CONTROL_CODE_PAUSE);
915                         }
916                 }
917
918
919         } break;
920         default:
921                 break;
922         };
923         return 1;
924 }
925
926 int InputLinux::cecConfigurationChanged(void *param, const libcec_configuration config)
927 {
928         Log::getInstance()->log("InputLinux", Log::DEBUG, "CECConfig:"/*,config.string()*/);
929         return 1;
930
931 }
932
933 #endif
934
935 void  InputLinux::cecSourceActivated(void* /* param */, const cec_logical_address address, const uint8_t activated)
936 {
937   Log::getInstance()->log("InputLinux", Log::DEBUG, "CECSourceActivated: %d %d", address, activated);
938   if (activated == 1)
939   {
940     static_cast<InputLinux*>(Input::getInstance())->incomingPowerkey(POWERON);
941   }
942 }
943
944 void InputLinux::incomingCECkey(int keys)
945 {
946   // Send INPUT message
947   Message* m = new Message();
948   m->message = Message::INPUT_EVENT;
949   m->to = Command::getInstance();
950   m->from = this;
951   m->parameter = static_cast<UCHAR>(TranslateHWC(W_G_HCW(W_HCW_CEC, keys)));
952   MessageQueue::getInstance()->postMessage(m);
953 }
954
955 void InputLinux::incomingPowerkey(UCHAR key)
956 {
957   // Send INPUT message
958   Message* m = new Message();
959   m->message = Message::INPUT_EVENT;
960   m->to = Command::getInstance();
961   m->from = this;
962   m->parameter = key;
963   MessageQueue::getInstance()->postMessage(m);
964 }
965
966 bool InputLinux::loadOptionsfromServer(VDR* vdr)
967 {
968    // Set remote keys
969   char* name;
970   name = vdr->configLoad("InputLinux", "HandleVolume");
971
972   if (name != NULL)
973   {
974     if      (STRCASECMP(name, "Vomp") == 0) cechandlesvolume = false;
975     else if (STRCASECMP(name, "Cec") == 0) cechandlesvolume = true;
976     delete[] name;
977   }
978   return Input::loadOptionsfromServer(vdr);
979 }
980
981 bool InputLinux::saveOptionstoServer()
982 {
983   if (cechandlesvolume) VDR::getInstance()->configSave("InputLinux", "HandleVolume","Cec");
984   else VDR::getInstance()->configSave("InputLinux", "HandleVolume","Vomp");
985
986   return Input::saveOptionstoServer();
987 }
988
989 bool InputLinux::addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane)
990 {
991   if (!Input::addOptionsToPanes(panenumber, options, pane)) return false;
992
993   Option* option;
994   if (panenumber == 2)
995   {
996     static const char* volumeopts[]={"Vomp","Cec"};
997     option = new Option(100,tr("Volume handled by"), "InputLinux","HandleVolume",Option::TYPE_TEXT,/*4,2*/2,0,0,volumeopts,NULL,false,this);
998     options->push_back(option);
999     pane->addOptionLine(option);
1000   }
1001
1002   return true;
1003 }
1004
1005 bool InputLinux::handleOptionChanges(Option* option)
1006 {
1007     if (Input::handleOptionChanges(option))
1008                 return true;
1009         switch (option->id) {
1010         case 100: {
1011                 if (STRCASECMP(option->options[option->userSetChoice], "Vomp") == 0) {
1012                         cechandlesvolume=false;
1013                 }  else if (STRCASECMP(option->options[option->userSetChoice], "Cec")
1014                                 == 0) {
1015                         cechandlesvolume=true;
1016                 }
1017                 Log::getInstance()->log("InputLinux", Log::DEBUG, "Set volume handling to to %s %d",option->options[option->userSetChoice],cechandlesvolume);
1018                 return true;
1019         }
1020         break;
1021         };
1022         return false;
1023
1024 }
1025
1026 void InputLinux::volumeUp()
1027 {
1028   cec_adap->VolumeUp();
1029 }
1030
1031 void InputLinux::volumeDown()
1032 {
1033   cec_adap->VolumeDown();
1034 }
1035
1036 void InputLinux::volumeMute()
1037 {
1038 #if CEC_LIB_VERSION_MAJOR >= 4
1039   cec_adap->AudioToggleMute();
1040 #else
1041   cec_adap->MuteAudio();
1042 #endif
1043 }
1044
1045 void InputLinux::informStopEventLoop()
1046 {
1047   listenLoopStop = true;
1048   write(pfds[1], "1", 1); // break the select in getButtonPress
1049 }
1050
1051 void InputLinux::eventLoop()
1052 {
1053   fd_set readfds;
1054   int maxfd;
1055
1056   if (pipe2(pfds, O_NONBLOCK) == -1)
1057   {
1058     Log::getInstance()->log("InputLinux", Log::ERR, "pipe2() fail");
1059     return;
1060   }
1061
1062   Log::getInstance()->log("InputLinux", Log::INFO, "Listen loop");
1063
1064   while(1)
1065   {
1066     if (listenLoopStop) break;
1067
1068     FD_ZERO(&readfds);
1069
1070     maxfd = 0;
1071     for (unsigned int i = 0; i < devices.size(); i++)
1072     {
1073       int cur_fd = devices[i];
1074       maxfd = max(cur_fd, maxfd);
1075       FD_SET(cur_fd, &readfds);
1076     }
1077
1078     FD_SET(pfds[0], &readfds);
1079     maxfd = max(pfds[0], maxfd);
1080
1081     // 0 = nothing happened and timeout expired
1082     // >0 = num of descriptors that changed
1083     // -1 = error
1084     if (select(maxfd + 1, &readfds, NULL, NULL, NULL) < 1)
1085     {
1086       Log::getInstance()->log("InputLinux", Log::ERR, "Select fail");
1087       break;
1088     }
1089
1090     if (FD_ISSET(pfds[0], &readfds))
1091     {
1092       // assume quit signal
1093       Log::getInstance()->log("InputLinux", Log::NOTICE, "pfds quit");
1094       break;
1095
1096       // FUTURE: read the byte and do different things? Read listenLoopStop and maybe other bools?
1097     }
1098
1099     for (unsigned int i = 0; i < devices.size(); i++)
1100     {
1101       int cur_fd = devices[i];
1102       if (FD_ISSET(cur_fd, &readfds))
1103       {
1104         struct input_event ev;
1105         int count = read(cur_fd, &ev, sizeof(ev));
1106         if (count == sizeof(ev))
1107         {
1108           if (ev.type == EV_KEY && ev.value == 1)
1109           {
1110             // Send INPUT message
1111             Message* m = new Message();
1112             m->message = Message::INPUT_EVENT;
1113             m->to = Command::getInstance();
1114             m->from = this;
1115             m->parameter = static_cast<UCHAR>(TranslateHWC(W_G_HCW(W_HCW_KC,ev.code)));
1116             MessageQueue::getInstance()->postMessage(m);
1117           }
1118         }
1119       }
1120     }
1121   }
1122
1123   close(pfds[1]);
1124   close(pfds[0]);
1125 }
1126
1127 // FIXME surely NA_SIGNAL can go