add onShown eventlist for executing stuff after the screen is drawn
[enigma2.git] / lib / driver / rc.cpp
1 #include <lib/driver/rc.h>
2
3 #include <asm/types.h>
4 #include <stdio.h>
5 #include <fcntl.h>
6 #include <unistd.h>
7 #include <linux/input.h>
8
9 #include <lib/base/init.h>
10 #include <lib/base/init_num.h>
11 #include <lib/base/econfig.h>
12 #include <lib/base/eerror.h>
13
14 /*
15  *  note on the enigma input layer:
16  *  the enigma input layer (rc*) supports n different devices which
17  *  all have completely different interfaces, mapped down to 32bit + 
18  *  make/break/release codes mapped down (via xml files) to "actions".
19  *  this was necessary to support multiple remote controls with proprietary
20  *  interfaces. now everybody is using input devices, and thus adding
21  *  another input layer seems to be a bit overkill. BUT:
22  *  image a remote control with two hundred buttons. each and every function
23  *  in enigma can be bound to a button. no need to use them twice. 
24  *  for example, you would have KEY_MENU assigned to a menu for setup etc.,
25  *  but no audio and video settings, since you have special keys for that,
26  *  and you don't want to display a big menu with entries that are available
27  *  with another single key.
28  *  then image a remote control with ten buttons. do you really want to waste
29  *  KEY_MENU for a simple menu? you need the audio/video settings there too.
30  *  take this just as a (bad) example. another (better) example might be front-
31  *  button-keys. usually you have KEY_UP, KEY_DOWN, KEY_POWER. you don't want
32  *  them to behave like the remote-control-KEY_UP, KEY_DOWN and KEY_POWER,
33  *  don't you? 
34  *  so here we can map same keys of different input devices to different 
35  *  actions. have fun.
36  */
37
38 eRCDevice::eRCDevice(std::string id, eRCDriver *driver): driver(driver), id(id)
39 {
40         input=driver->getInput();
41         driver->addCodeListener(this);
42         eRCInput::getInstance()->addDevice(id, this);
43 }
44
45 eRCDevice::~eRCDevice()
46 {
47         driver->removeCodeListener(this);
48         eRCInput::getInstance()->removeDevice(id.c_str());
49 }
50
51 eRCDriver::eRCDriver(eRCInput *input): input(input), enabled(1)
52 {
53 }
54
55 eRCDriver::~eRCDriver()
56 {
57         for (std::list<eRCDevice*>::iterator i=listeners.begin(); i!=listeners.end(); ++i)
58                 delete *i;
59 }
60
61 void eRCShortDriver::keyPressed(int)
62 {
63         __u16 rccode;
64         while (1)
65         {
66                 if (read(handle, &rccode, 2)!=2)
67                         break;
68                 if (enabled && !input->islocked())
69                         for (std::list<eRCDevice*>::iterator i(listeners.begin()); i!=listeners.end(); ++i)
70                                 (*i)->handleCode(rccode);
71         }
72 }
73
74 eRCShortDriver::eRCShortDriver(const char *filename): eRCDriver(eRCInput::getInstance())
75 {
76         handle=open(filename, O_RDONLY|O_NONBLOCK);
77         if (handle<0)
78         {
79                 eDebug("failed to open %s", filename);
80                 sn=0;
81         } else
82         {
83                 sn=new eSocketNotifier(eApp, handle, eSocketNotifier::Read);
84                 CONNECT(sn->activated, eRCShortDriver::keyPressed);
85                 eRCInput::getInstance()->setFile(handle);
86         }
87 }
88
89 eRCShortDriver::~eRCShortDriver()
90 {
91         if (handle>=0)
92                 close(handle);
93         if (sn)
94                 delete sn;
95 }
96
97 void eRCInputEventDriver::keyPressed(int)
98 {
99         struct input_event ev;
100         while (1)
101         {
102                 if (read(handle, &ev, sizeof(struct input_event))!=sizeof(struct input_event))
103                         break;
104                 if (enabled && !input->islocked())
105                         for (std::list<eRCDevice*>::iterator i(listeners.begin()); i!=listeners.end(); ++i)
106                                 (*i)->handleCode((int)&ev);
107         }
108 }
109
110 eRCInputEventDriver::eRCInputEventDriver(const char *filename): eRCDriver(eRCInput::getInstance())
111 {
112         handle=open(filename, O_RDONLY|O_NONBLOCK);
113         if (handle<0)
114         {
115                 eDebug("failed to open %s", filename);
116                 sn=0;
117         } else
118         {
119                 sn=new eSocketNotifier(eApp, handle, eSocketNotifier::Read);
120                 CONNECT(sn->activated, eRCInputEventDriver::keyPressed);
121                 eRCInput::getInstance()->setFile(handle);
122         }
123 }
124
125 std::string eRCInputEventDriver::getDeviceName()
126 {
127         char name[128]="";
128         if (handle >= 0)
129                 ::ioctl(handle, EVIOCGNAME(128), name);
130         return name;
131 }
132
133 eRCInputEventDriver::~eRCInputEventDriver()
134 {
135         if (handle>=0)
136                 close(handle);
137         if (sn)
138                 delete sn;
139 }
140
141 eRCConfig::eRCConfig()
142 {
143         reload();
144 }
145
146 eRCConfig::~eRCConfig()
147 {
148         save();
149 }
150
151 void eRCConfig::set( int delay, int repeat )
152 {
153         rdelay = delay;
154         rrate = repeat;
155 }
156
157 void eRCConfig::reload()
158 {
159         rdelay=500;
160         rrate=100;
161         if ( eConfig::getInstance()->getKey("/ezap/rc/repeatRate", rrate) )
162                 save();
163         eConfig::getInstance()->getKey("/ezap/rc/repeatDelay", rdelay);
164 }
165
166 void eRCConfig::save()
167 {
168         eConfig::getInstance()->setKey("/ezap/rc/repeatRate", rrate);
169         eConfig::getInstance()->setKey("/ezap/rc/repeatDelay", rdelay);
170 }
171
172 eRCInput *eRCInput::instance;
173
174 eRCInput::eRCInput()
175 {
176         ASSERT( !instance);
177         instance=this;
178         handle = -1;
179         locked = 0;
180         keyboardMode = kmAll;
181 }
182
183 eRCInput::~eRCInput()
184 {
185 }
186
187 void eRCInput::close()
188 {
189 }
190
191 bool eRCInput::open()
192 {
193         return false;
194 }
195
196 int eRCInput::lock()
197 {
198         locked=1;
199         return handle;
200 }
201
202 void eRCInput::unlock()
203 {
204         if (locked)
205                 locked=0;
206 }
207
208 void eRCInput::setFile(int newh)
209 {
210         handle=newh;
211 }
212
213 void eRCInput::addDevice(const std::string &id, eRCDevice *dev)
214 {
215         devices.insert(std::pair<std::string,eRCDevice*>(id, dev));
216 }
217
218 void eRCInput::removeDevice(const std::string &id)
219 {
220         devices.erase(id);
221 }
222
223 eRCDevice *eRCInput::getDevice(const std::string &id)
224 {
225         std::map<std::string,eRCDevice*>::iterator i=devices.find(id);
226         if (i == devices.end())
227         {
228                 eDebug("failed, possible choices are:");
229                 for (std::map<std::string,eRCDevice*>::iterator i=devices.begin(); i != devices.end(); ++i)     
230                         eDebug("%s", i->first.c_str());
231                 return 0;
232         }
233         return i->second;
234 }
235
236 std::map<std::string,eRCDevice*,eRCInput::lstr> &eRCInput::getDevices()
237 {
238         return devices;
239 }
240
241 eAutoInitP0<eRCInput> init_rcinput(eAutoInitNumbers::rc, "RC Input layer");