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