summaryrefslogtreecommitdiff
path: root/src/lib/emotion/emotion_webcam.c
diff options
context:
space:
mode:
authorGustavo Sverzut Barbieri <barbieri@gmail.com>2013-01-10 21:50:02 +0000
committerGustavo Sverzut Barbieri <barbieri@gmail.com>2013-01-10 21:50:02 +0000
commitd1341cc826481f6c17ce82bf251e9a2a1b75ea8b (patch)
treedf706cef19f35cbab88dc06e8052500118ec8363 /src/lib/emotion/emotion_webcam.c
parent6140f1045db57f09a4d318282f9641690890b396 (diff)
efl/emotion: move webcam stuff out of main file.
SVN revision: 82591
Diffstat (limited to '')
-rw-r--r--src/lib/emotion/emotion_webcam.c309
1 files changed, 309 insertions, 0 deletions
diff --git a/src/lib/emotion/emotion_webcam.c b/src/lib/emotion/emotion_webcam.c
new file mode 100644
index 0000000000..d5c75af429
--- /dev/null
+++ b/src/lib/emotion/emotion_webcam.c
@@ -0,0 +1,309 @@
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4
5#ifdef HAVE_EEZE
6# include <sys/types.h>
7# include <sys/stat.h>
8# include <fcntl.h>
9# ifdef HAVE_V4L2
10# include <sys/ioctl.h>
11# include <linux/videodev2.h>
12# endif
13# include <Eeze.h>
14#endif
15
16#include <Ecore.h>
17
18#include "emotion_private.h"
19
20EAPI int EMOTION_WEBCAM_UPDATE = 0;
21
22typedef struct _Emotion_Webcams Emotion_Webcams;
23
24struct _Emotion_Webcams
25{
26 Eina_List *webcams;
27};
28
29struct _Emotion_Webcam
30{
31 EINA_REFCOUNT;
32
33 const char *syspath;
34 const char *device;
35 const char *name;
36
37 const char *custom;
38
39 const char *filename;
40};
41
42static Eet_Data_Descriptor *_webcam_edd;
43static Eet_Data_Descriptor *_webcams_edd;
44
45static Emotion_Webcams *_emotion_webcams = NULL;
46
47static Eet_Data_Descriptor *
48_emotion_webcams_edds_new(void)
49{
50 Eet_Data_Descriptor_Class eddc;
51
52 EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Emotion_Webcam);
53 _webcam_edd = eet_data_descriptor_file_new(&eddc);
54 EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "device", device, EET_T_STRING);
55 EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "name", name, EET_T_STRING);
56 EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "custom", custom, EET_T_STRING);
57 EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "filename", filename, EET_T_STRING);
58
59 EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Emotion_Webcams);
60 _webcams_edd = eet_data_descriptor_file_new(&eddc);
61 EET_DATA_DESCRIPTOR_ADD_LIST(_webcams_edd, Emotion_Webcams, "webcams", webcams, _webcam_edd);
62
63 return _webcams_edd;
64}
65
66static void
67_emotion_webcams_edds_free(void)
68{
69 eet_data_descriptor_free(_webcams_edd);
70 _webcams_edd = NULL;
71
72 eet_data_descriptor_free(_webcam_edd);
73 _webcam_edd = NULL;
74}
75
76static void
77emotion_webcam_destroy(Emotion_Webcam *ew)
78{
79 if (!ew->custom)
80 {
81 eina_stringshare_del(ew->syspath);
82 eina_stringshare_del(ew->device);
83 eina_stringshare_del(ew->name);
84 }
85 free(ew);
86}
87
88#ifdef HAVE_EEZE
89static Eeze_Udev_Watch *eeze_watcher = NULL;
90
91static void
92_emotion_check_device(Emotion_Webcam *ew)
93{
94#ifdef HAVE_V4L2
95 Emotion_Webcam *check;
96 Eina_List *l;
97 struct v4l2_capability caps;
98 int fd;
99#endif
100
101 if (!ew) return ;
102#ifdef HAVE_V4L2
103 if (!ew->device) goto on_error;
104
105 fd = open(ew->filename, O_RDONLY);
106 if (fd < 0) goto on_error;
107
108 if (ioctl(fd, VIDIOC_QUERYCAP, &caps) == -1) goto on_error;
109
110 /* Likely not a webcam */
111 if (!caps.capabilities & V4L2_CAP_VIDEO_CAPTURE) goto on_error;
112 if (caps.capabilities & V4L2_CAP_TUNER
113 || caps.capabilities & V4L2_CAP_RADIO
114 || caps.capabilities & V4L2_CAP_MODULATOR)
115 goto on_error;
116
117 EINA_LIST_FOREACH(_emotion_webcams->webcams, l, check)
118 if (check->device == ew->device)
119 goto on_error;
120
121 _emotion_webcams->webcams = eina_list_append(_emotion_webcams->webcams, ew);
122
123 EINA_REFCOUNT_INIT(ew);
124
125 return ;
126
127 on_error:
128#endif
129 EINA_LOG_ERR("'%s' is not a webcam ['%s']", ew->name, strerror(errno));
130 eina_stringshare_del(ew->syspath);
131 eina_stringshare_del(ew->device);
132 eina_stringshare_del(ew->name);
133 free(ew);
134}
135
136static Emotion_Webcam *
137_emotion_webcam_new(const char *syspath)
138{
139 Emotion_Webcam *test;
140 const char *device;
141 char *local;
142
143 test = malloc(sizeof (Emotion_Webcam));
144 if (!test) return NULL;
145
146 test->custom = NULL;
147 test->syspath = eina_stringshare_ref(syspath);
148 test->name = eeze_udev_syspath_get_sysattr(syspath, "name");
149
150 device = eeze_udev_syspath_get_property(syspath, "DEVNAME");
151 local = alloca(eina_stringshare_strlen(device) + 8);
152 snprintf(local, eina_stringshare_strlen(device) + 8, "v4l2://%s", device);
153 test->device = eina_stringshare_add(local);
154 eina_stringshare_del(device);
155 test->filename = test->device + 7;
156
157 return test;
158}
159
160static void
161_emotion_enumerate_all_webcams(void)
162{
163 Eina_List *devices;
164 const char *syspath;
165
166 devices = eeze_udev_find_by_type(EEZE_UDEV_TYPE_V4L, NULL);
167
168 EINA_LIST_FREE(devices, syspath)
169 {
170 Emotion_Webcam *test;
171
172 test = _emotion_webcam_new(syspath);
173 if (test) _emotion_check_device(test);
174
175 eina_stringshare_del(syspath);
176 }
177}
178
179static void
180_emotion_eeze_events(const char *syspath,
181 Eeze_Udev_Event ev,
182 void *data EINA_UNUSED,
183 Eeze_Udev_Watch *watcher EINA_UNUSED)
184{
185 if (ev == EEZE_UDEV_EVENT_REMOVE)
186 {
187 Emotion_Webcam *check;
188 Eina_List *l;
189
190 EINA_LIST_FOREACH(_emotion_webcams->webcams, l, check)
191 if (check->syspath == syspath)
192 {
193 _emotion_webcams->webcams = eina_list_remove_list(_emotion_webcams->webcams, l);
194 EINA_REFCOUNT_UNREF(check)
195 emotion_webcam_destroy(check);
196 break ;
197 }
198 }
199 else if (ev == EEZE_UDEV_EVENT_ADD)
200 {
201 Emotion_Webcam *test;
202
203 test = _emotion_webcam_new(syspath);
204 if (test) _emotion_check_device(test);
205 }
206 ecore_event_add(EMOTION_WEBCAM_UPDATE, NULL, NULL, NULL);
207}
208
209#endif
210
211Eina_Bool emotion_webcam_init(void)
212{
213 EMOTION_WEBCAM_UPDATE = ecore_event_type_new();
214
215 eet_init();
216 _emotion_webcams_edds_new();
217
218#ifdef HAVE_EEZE
219 eeze_init();
220
221 _emotion_enumerate_all_webcams();
222
223 eeze_watcher = eeze_udev_watch_add(EEZE_UDEV_TYPE_V4L,
224 (EEZE_UDEV_EVENT_ADD | EEZE_UDEV_EVENT_REMOVE),
225 _emotion_eeze_events, NULL);
226#endif
227
228 return EINA_TRUE;
229}
230
231void
232emotion_webcam_shutdown(void)
233{
234 Emotion_Webcam *ew;
235
236 EINA_LIST_FREE(_emotion_webcams->webcams, ew)
237 {
238 /* There is currently no way to refcount from the outside, this help, but could lead to some issue */
239 EINA_REFCOUNT_UNREF(ew)
240 emotion_webcam_destroy(ew);
241 }
242 free(_emotion_webcams);
243 _emotion_webcams = NULL;
244
245#ifdef HAVE_EEZE
246 eeze_udev_watch_del(eeze_watcher);
247 eeze_watcher = NULL;
248
249 eeze_shutdown();
250#endif
251
252 _emotion_webcams_edds_free();
253 eet_shutdown();
254}
255
256Eina_Bool
257emotion_webcam_config_load(Eet_File *ef)
258{
259 if (ef)
260 {
261 _emotion_webcams = eet_data_read(ef, _webcams_edd, "config");
262 INF("Loaded config %p from eet %s", _emotion_webcams, eet_file_get(ef));
263 }
264
265 if (!_emotion_webcams)
266 {
267 DBG("No config, create empty");
268 _emotion_webcams = calloc(1, sizeof (Emotion_Webcams));
269 EINA_SAFETY_ON_NULL_RETURN_VAL(_emotion_webcams, EINA_FALSE);
270 }
271
272 return EINA_TRUE;
273}
274
275EAPI const Eina_List *
276emotion_webcams_get(void)
277{
278 EINA_SAFETY_ON_NULL_RETURN_VAL(_emotion_webcams, NULL);
279 return _emotion_webcams->webcams;
280}
281
282EAPI const char *
283emotion_webcam_name_get(const Emotion_Webcam *ew)
284{
285 EINA_SAFETY_ON_NULL_RETURN_VAL(ew, NULL);
286 return ew->name;
287}
288
289EAPI const char *
290emotion_webcam_device_get(const Emotion_Webcam *ew)
291{
292 EINA_SAFETY_ON_NULL_RETURN_VAL(ew, NULL);
293 return ew->device;
294}
295
296EAPI const char *
297emotion_webcam_custom_get(const char *device)
298{
299 const Emotion_Webcam *ew;
300 const Eina_List *l;
301
302 EINA_SAFETY_ON_NULL_RETURN_VAL(_emotion_webcams, NULL);
303
304 EINA_LIST_FOREACH(_emotion_webcams->webcams, l, ew)
305 if (ew->device && strcmp(device, ew->device) == 0)
306 return ew->custom;
307
308 return NULL;
309}