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