- add *.pyc to .cvsignore
[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 int eRCDevice::getKeyCompatibleCode(const eRCKey &) const
39 {
40         return -1;
41 }
42
43 eRCDevice::eRCDevice(std::string id, eRCDriver *driver): driver(driver), id(id)
44 {
45         input=driver->getInput();
46         driver->addCodeListener(this);
47         eRCInput::getInstance()->addDevice(id, this);
48 }
49
50 eRCDevice::~eRCDevice()
51 {
52         driver->removeCodeListener(this);
53         eRCInput::getInstance()->removeDevice(id.c_str());
54 }
55
56 eRCDriver::eRCDriver(eRCInput *input): input(input), enabled(1)
57 {
58 }
59
60 eRCDriver::~eRCDriver()
61 {
62         for (std::list<eRCDevice*>::iterator i=listeners.begin(); i!=listeners.end(); ++i)
63                 delete *i;
64 }
65
66 void eRCShortDriver::keyPressed(int)
67 {
68         __u16 rccode;
69         while (1)
70         {
71                 if (read(handle, &rccode, 2)!=2)
72                         break;
73                 if (enabled && !input->islocked())
74                         for (std::list<eRCDevice*>::iterator i(listeners.begin()); i!=listeners.end(); ++i)
75                                 (*i)->handleCode(rccode);
76         }
77 }
78
79 eRCShortDriver::eRCShortDriver(const char *filename): eRCDriver(eRCInput::getInstance())
80 {
81         handle=open(filename, O_RDONLY|O_NONBLOCK);
82         if (handle<0)
83         {
84                 eDebug("failed to open %s", filename);
85                 sn=0;
86         } else
87         {
88                 sn=new eSocketNotifier(eApp, handle, eSocketNotifier::Read);
89                 CONNECT(sn->activated, eRCShortDriver::keyPressed);
90                 eRCInput::getInstance()->setFile(handle);
91         }
92 }
93
94 eRCShortDriver::~eRCShortDriver()
95 {
96         if (handle>=0)
97                 close(handle);
98         if (sn)
99                 delete sn;
100 }
101
102 void eRCInputEventDriver::keyPressed(int)
103 {
104         struct input_event ev;
105         while (1)
106         {
107                 if (read(handle, &ev, sizeof(struct input_event))!=sizeof(struct input_event))
108                         break;
109                 if (enabled && !input->islocked())
110                         for (std::list<eRCDevice*>::iterator i(listeners.begin()); i!=listeners.end(); ++i)
111                                 (*i)->handleCode((int)&ev);
112         }
113 }
114
115 eRCInputEventDriver::eRCInputEventDriver(const char *filename): eRCDriver(eRCInput::getInstance())
116 {
117         handle=open(filename, O_RDONLY|O_NONBLOCK);
118         if (handle<0)
119         {
120                 eDebug("failed to open %s", filename);
121                 sn=0;
122         } else
123         {
124                 sn=new eSocketNotifier(eApp, handle, eSocketNotifier::Read);
125                 CONNECT(sn->activated, eRCInputEventDriver::keyPressed);
126                 eRCInput::getInstance()->setFile(handle);
127         }
128 }
129
130 std::string eRCInputEventDriver::getDeviceName()
131 {
132         char name[128]="";
133         if (handle >= 0)
134                 ::ioctl(handle, EVIOCGNAME(128), name);
135         return name;
136 }
137
138 eRCInputEventDriver::~eRCInputEventDriver()
139 {
140         if (handle>=0)
141                 close(handle);
142         if (sn)
143                 delete sn;
144 }
145
146 eRCConfig::eRCConfig()
147 {
148         reload();
149 }
150
151 eRCConfig::~eRCConfig()
152 {
153         save();
154 }
155
156 void eRCConfig::set( int delay, int repeat )
157 {
158         rdelay = delay;
159         rrate = repeat;
160 }
161
162 void eRCConfig::reload()
163 {
164         rdelay=500;
165         rrate=100;
166         if ( eConfig::getInstance()->getKey("/ezap/rc/repeatRate", rrate) )
167                 save();
168         eConfig::getInstance()->getKey("/ezap/rc/repeatDelay", rdelay);
169 }
170
171 void eRCConfig::save()
172 {
173         eConfig::getInstance()->setKey("/ezap/rc/repeatRate", rrate);
174         eConfig::getInstance()->setKey("/ezap/rc/repeatDelay", rdelay);
175 }
176
177 eRCInput *eRCInput::instance;
178
179 eRCInput::eRCInput()
180 {
181         ASSERT( !instance);
182         instance=this;
183         handle = -1;
184         locked = 0;
185 }
186
187 eRCInput::~eRCInput()
188 {
189 }
190
191 void eRCInput::close()
192 {
193 }
194
195 bool eRCInput::open()
196 {
197         return false;
198 }
199
200 int eRCInput::lock()
201 {
202         locked=1;
203         return handle;
204 }
205
206 void eRCInput::unlock()
207 {
208         if (locked)
209                 locked=0;
210 }
211
212 void eRCInput::setFile(int newh)
213 {
214         handle=newh;
215 }
216
217 void eRCInput::addDevice(const std::string &id, eRCDevice *dev)
218 {
219         devices.insert(std::pair<std::string,eRCDevice*>(id, dev));
220 }
221
222 void eRCInput::removeDevice(const std::string &id)
223 {
224         devices.erase(id);
225 }
226
227 eRCDevice *eRCInput::getDevice(const std::string &id)
228 {
229         std::map<std::string,eRCDevice*>::iterator i=devices.find(id);
230         if (i == devices.end())
231         {
232                 eDebug("failed, possible choices are:");
233                 for (std::map<std::string,eRCDevice*>::iterator i=devices.begin(); i != devices.end(); ++i)     
234                         eDebug("%s", i->first.c_str());
235                 return 0;
236         }
237         return i->second;
238 }
239
240 std::map<std::string,eRCDevice*,eRCInput::lstr> &eRCInput::getDevices()
241 {
242         return devices;
243 }
244
245 eAutoInitP0<eRCInput> init_rcinput(eAutoInitNumbers::rc, "RC Input layer");