diff options
author | Carsten Haitzler (Rasterman) <raster@rasterman.com> | 2020-03-25 16:46:27 +0000 |
---|---|---|
committer | Carsten Haitzler (Rasterman) <raster@rasterman.com> | 2020-03-25 17:11:28 +0000 |
commit | 030ef36c72b721de487ca3bb940d4f22a58e745c (patch) | |
tree | 0a2fc74d53716ca19ea0c96599a855ef6cec10ec /src/lib/emotion/emotion_webcam.c | |
parent | 6068cc9039243d493d001df7a35426cd7c5acfea (diff) |
emotion - webcam - fix segv on webcam plug/unplug and clean
well hunting was fun... custom webcams i just cant see being used. no
api to add them - have to hand craft a config file .. and udev/eeze
provide info on webcam devices anyway at runtime with plug/unplug etc.
... so this should be the only ay (for now) and it keesp the code
simpler and less bug-prone
now issue was some nasty skipping unref as opposed to destroy. in
chasing i simplified the code to help me narrow it down and not chase
the same logic in multiple places. shorter cleaere, simpler and minux
one bug.
@fix
Diffstat (limited to '')
-rw-r--r-- | src/lib/emotion/emotion_webcam.c | 284 |
1 files changed, 95 insertions, 189 deletions
diff --git a/src/lib/emotion/emotion_webcam.c b/src/lib/emotion/emotion_webcam.c index d29110aa23..8b46b9a724 100644 --- a/src/lib/emotion/emotion_webcam.c +++ b/src/lib/emotion/emotion_webcam.c | |||
@@ -27,11 +27,9 @@ typedef struct _Emotion_Webcams Emotion_Webcams; | |||
27 | struct _Emotion_Webcams | 27 | struct _Emotion_Webcams |
28 | { | 28 | { |
29 | Eina_List *webcams; | 29 | Eina_List *webcams; |
30 | |||
31 | Ecore_Idler *idler; | 30 | Ecore_Idler *idler; |
32 | Eina_List *check_list; | 31 | Eina_List *check_list; |
33 | 32 | Eina_Bool init : 1; | |
34 | Eina_Bool init; | ||
35 | }; | 33 | }; |
36 | 34 | ||
37 | struct _Emotion_Webcam | 35 | struct _Emotion_Webcam |
@@ -41,56 +39,18 @@ struct _Emotion_Webcam | |||
41 | const char *syspath; | 39 | const char *syspath; |
42 | const char *device; | 40 | const char *device; |
43 | const char *name; | 41 | const char *name; |
44 | |||
45 | const char *custom; | ||
46 | |||
47 | const char *filename; | 42 | const char *filename; |
43 | Eina_Bool in_list : 1; | ||
48 | }; | 44 | }; |
49 | 45 | ||
50 | static Eet_Data_Descriptor *_webcam_edd; | ||
51 | static Eet_Data_Descriptor *_webcams_edd; | ||
52 | |||
53 | static Emotion_Webcams *_emotion_webcams = NULL; | 46 | static Emotion_Webcams *_emotion_webcams = NULL; |
54 | 47 | ||
55 | static Eet_Data_Descriptor * | ||
56 | _emotion_webcams_edds_new(void) | ||
57 | { | ||
58 | Eet_Data_Descriptor_Class eddc; | ||
59 | |||
60 | EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Emotion_Webcam); | ||
61 | _webcam_edd = eet_data_descriptor_file_new(&eddc); | ||
62 | EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "device", device, EET_T_STRING); | ||
63 | EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "name", name, EET_T_STRING); | ||
64 | EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "custom", custom, EET_T_STRING); | ||
65 | EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "filename", filename, EET_T_STRING); | ||
66 | |||
67 | EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Emotion_Webcams); | ||
68 | _webcams_edd = eet_data_descriptor_file_new(&eddc); | ||
69 | EET_DATA_DESCRIPTOR_ADD_LIST(_webcams_edd, Emotion_Webcams, "webcams", webcams, _webcam_edd); | ||
70 | EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcams, "init", init, EET_T_CHAR); | ||
71 | |||
72 | return _webcams_edd; | ||
73 | } | ||
74 | |||
75 | static void | ||
76 | _emotion_webcams_edds_free(void) | ||
77 | { | ||
78 | eet_data_descriptor_free(_webcams_edd); | ||
79 | _webcams_edd = NULL; | ||
80 | |||
81 | eet_data_descriptor_free(_webcam_edd); | ||
82 | _webcam_edd = NULL; | ||
83 | } | ||
84 | |||
85 | static void | 48 | static void |
86 | emotion_webcam_destroy(Emotion_Webcam *ew) | 49 | emotion_webcam_destroy(Emotion_Webcam *ew) |
87 | { | 50 | { |
88 | if (!ew->custom) | 51 | eina_stringshare_del(ew->syspath); |
89 | { | 52 | eina_stringshare_del(ew->device); |
90 | eina_stringshare_del(ew->syspath); | 53 | eina_stringshare_del(ew->name); |
91 | eina_stringshare_del(ew->device); | ||
92 | eina_stringshare_del(ew->name); | ||
93 | } | ||
94 | free(ew); | 54 | free(ew); |
95 | } | 55 | } |
96 | 56 | ||
@@ -116,33 +76,25 @@ _emotion_check_device(Emotion_Webcam *ew) | |||
116 | 76 | ||
117 | if (ioctl(fd, VIDIOC_QUERYCAP, &caps) == -1) goto on_error; | 77 | if (ioctl(fd, VIDIOC_QUERYCAP, &caps) == -1) goto on_error; |
118 | 78 | ||
119 | /* Likely not a webcam */ | 79 | // Likely not a webcam |
120 | if (!(caps.capabilities & V4L2_CAP_VIDEO_CAPTURE)) goto on_error; | 80 | if (!(caps.capabilities & V4L2_CAP_VIDEO_CAPTURE)) goto on_error; |
121 | if (caps.capabilities & V4L2_CAP_TUNER | 81 | if (caps.capabilities & |
122 | || caps.capabilities & V4L2_CAP_RADIO | 82 | (V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_MODULATOR)) |
123 | || caps.capabilities & V4L2_CAP_MODULATOR) | ||
124 | goto on_error; | 83 | goto on_error; |
125 | 84 | ||
126 | EINA_LIST_FOREACH(_emotion_webcams->webcams, l, check) | 85 | EINA_LIST_FOREACH(_emotion_webcams->webcams, l, check) |
127 | if (check->device == ew->device) | 86 | { |
128 | goto on_error; | 87 | if (check->device == ew->device) goto on_error; |
129 | 88 | } | |
130 | _emotion_webcams->webcams = eina_list_append(_emotion_webcams->webcams, ew); | 89 | _emotion_webcams->webcams = eina_list_append(_emotion_webcams->webcams, ew); |
131 | 90 | ew->in_list = EINA_TRUE; | |
132 | EINA_REFCOUNT_INIT(ew); | ||
133 | |||
134 | if (fd >= 0) close(fd); | 91 | if (fd >= 0) close(fd); |
135 | |||
136 | return EINA_TRUE; | 92 | return EINA_TRUE; |
137 | 93 | ||
138 | on_error: | 94 | on_error: |
139 | #endif | 95 | #endif |
140 | INF("'%s' is not a webcam ['%s']", ew->name, strerror(errno)); | 96 | INF("'%s' is not a webcam ['%s']", ew->name, strerror(errno)); |
141 | _emotion_webcams->webcams = eina_list_remove(_emotion_webcams->webcams, ew); | 97 | emotion_webcam_destroy(ew); |
142 | eina_stringshare_del(ew->syspath); | ||
143 | eina_stringshare_del(ew->device); | ||
144 | eina_stringshare_del(ew->name); | ||
145 | free(ew); | ||
146 | #ifdef HAVE_V4L2 | 98 | #ifdef HAVE_V4L2 |
147 | if (fd >= 0) close(fd); | 99 | if (fd >= 0) close(fd); |
148 | #endif | 100 | #endif |
@@ -152,109 +104,113 @@ _emotion_check_device(Emotion_Webcam *ew) | |||
152 | static Emotion_Webcam * | 104 | static Emotion_Webcam * |
153 | _emotion_webcam_new(const char *syspath) | 105 | _emotion_webcam_new(const char *syspath) |
154 | { | 106 | { |
155 | Emotion_Webcam *test; | 107 | Emotion_Webcam *ew; |
156 | const char *device; | 108 | const char *device; |
157 | char *local; | 109 | char *local; |
158 | 110 | ||
159 | test = malloc(sizeof (Emotion_Webcam)); | 111 | ew = calloc(1, sizeof(Emotion_Webcam)); |
160 | if (!test) return NULL; | 112 | if (!ew) return NULL; |
161 | 113 | ||
162 | test->custom = NULL; | 114 | EINA_REFCOUNT_INIT(ew); |
163 | test->syspath = eina_stringshare_ref(syspath); | 115 | ew->syspath = eina_stringshare_ref(syspath); |
164 | test->name = eeze_udev_syspath_get_sysattr(syspath, "name"); | 116 | ew->name = eeze_udev_syspath_get_sysattr(syspath, "name"); |
165 | 117 | ||
166 | device = eeze_udev_syspath_get_property(syspath, "DEVNAME"); | 118 | device = eeze_udev_syspath_get_property(syspath, "DEVNAME"); |
167 | local = alloca(eina_stringshare_strlen(device) + 8); | 119 | local = alloca(eina_stringshare_strlen(device) + 8); |
168 | snprintf(local, eina_stringshare_strlen(device) + 8, "v4l2://%s", device); | 120 | snprintf(local, eina_stringshare_strlen(device) + 8, "v4l2://%s", device); |
169 | test->device = eina_stringshare_add(local); | 121 | ew->device = eina_stringshare_add(local); |
170 | eina_stringshare_del(device); | 122 | eina_stringshare_del(device); |
171 | test->filename = test->device + 7; | 123 | ew->filename = ew->device + 7; |
172 | 124 | ||
173 | return test; | 125 | return ew; |
174 | } | 126 | } |
175 | 127 | ||
176 | static void | 128 | static void |
177 | _emotion_webcam_remove_cb(void *user_data, void *func_data EINA_UNUSED) | 129 | _emotion_webcam_unref(Emotion_Webcam *ew) |
178 | { | 130 | { |
179 | Emotion_Webcam *webcam; | 131 | EINA_REFCOUNT_UNREF(ew) |
180 | |||
181 | /* called at the end of EMOTION_WEBCAM_ADD event, to prevent the free */ | ||
182 | if (!user_data) | ||
183 | return; | ||
184 | |||
185 | webcam = user_data; | ||
186 | |||
187 | EINA_REFCOUNT_UNREF(webcam) | ||
188 | { | 132 | { |
189 | if (_emotion_webcams) | 133 | if ((ew->in_list) && (_emotion_webcams)) |
190 | _emotion_webcams->webcams = | 134 | { |
191 | eina_list_remove(_emotion_webcams->webcams, webcam); | 135 | _emotion_webcams->webcams = |
192 | emotion_webcam_destroy(webcam); | 136 | eina_list_remove(_emotion_webcams->webcams, ew); |
137 | ew->in_list = EINA_FALSE; | ||
138 | } | ||
139 | emotion_webcam_destroy(ew); | ||
193 | } | 140 | } |
194 | } | 141 | } |
195 | 142 | ||
143 | static void | ||
144 | _emotion_eeze_event_free(void *data EINA_UNUSED, void *ev) | ||
145 | { | ||
146 | _emotion_webcam_unref(ev); | ||
147 | } | ||
148 | |||
149 | static void | ||
150 | _emotion_webcam_ev_add(const char *syspath) | ||
151 | { | ||
152 | Emotion_Webcam *ew = _emotion_webcam_new(syspath); | ||
153 | if (!ew) return; | ||
154 | if (!_emotion_check_device(ew)) return; | ||
155 | EINA_REFCOUNT_REF(ew); | ||
156 | ecore_event_add(EMOTION_WEBCAM_ADD, ew, _emotion_eeze_event_free, NULL); | ||
157 | } | ||
158 | |||
196 | static Eina_Bool | 159 | static Eina_Bool |
197 | _emotion_process_webcam(void *data) | 160 | _emotion_process_webcam(void *data) |
198 | { | 161 | { |
199 | Emotion_Webcams *webcams; | 162 | Emotion_Webcams *webcams = data; |
200 | Emotion_Webcam *test; | ||
201 | const char *syspath; | 163 | const char *syspath; |
202 | 164 | ||
203 | webcams = data; | ||
204 | syspath = eina_list_data_get(webcams->check_list); | 165 | syspath = eina_list_data_get(webcams->check_list); |
205 | if (!syspath) | 166 | if (!syspath) |
206 | { | 167 | { |
207 | webcams->idler = NULL; | 168 | webcams->idler = NULL; |
208 | webcams->init = EINA_TRUE; | 169 | webcams->init = EINA_TRUE; |
209 | return EINA_FALSE; | 170 | return EINA_FALSE; |
210 | } | 171 | } |
211 | |||
212 | webcams->check_list = eina_list_remove_list(webcams->check_list, | 172 | webcams->check_list = eina_list_remove_list(webcams->check_list, |
213 | webcams->check_list); | 173 | webcams->check_list); |
214 | 174 | _emotion_webcam_ev_add(syspath); | |
215 | test = _emotion_webcam_new(syspath); | ||
216 | if (test) | ||
217 | { | ||
218 | if (_emotion_check_device(test)) | ||
219 | ecore_event_add(EMOTION_WEBCAM_ADD, test, NULL, NULL); | ||
220 | } | ||
221 | |||
222 | eina_stringshare_del(syspath); | 175 | eina_stringshare_del(syspath); |
223 | |||
224 | return EINA_TRUE; | 176 | return EINA_TRUE; |
225 | } | 177 | } |
226 | 178 | ||
227 | static void | 179 | static void |
228 | _emotion_eeze_events(const char *syspath, | 180 | _emotion_webcam_remove_cb(void *data EINA_UNUSED, void *ev) |
229 | Eeze_Udev_Event ev, | 181 | { |
182 | _emotion_webcam_unref(ev); | ||
183 | } | ||
184 | |||
185 | static void | ||
186 | _emotion_eeze_events(const char *syspath, Eeze_Udev_Event ev, | ||
230 | void *data EINA_UNUSED, | 187 | void *data EINA_UNUSED, |
231 | Eeze_Udev_Watch *watcher EINA_UNUSED) | 188 | Eeze_Udev_Watch *watcher EINA_UNUSED) |
232 | { | 189 | { |
233 | if (ev == EEZE_UDEV_EVENT_REMOVE) | 190 | if (ev == EEZE_UDEV_EVENT_REMOVE) |
234 | { | 191 | { |
235 | Emotion_Webcam *check; | 192 | Emotion_Webcam *ew; |
236 | Eina_List *l; | 193 | Eina_List *l; |
237 | 194 | ||
238 | EINA_LIST_FOREACH(_emotion_webcams->webcams, l, check) | 195 | EINA_LIST_FOREACH(_emotion_webcams->webcams, l, ew) |
239 | if (check->syspath == syspath) | 196 | { |
240 | { | 197 | if (ew->syspath == syspath) |
241 | _emotion_webcams->webcams = | 198 | { |
242 | eina_list_remove_list(_emotion_webcams->webcams, l); | 199 | if (ew->in_list) |
243 | ecore_event_add(EMOTION_WEBCAM_DEL, check, | 200 | { |
244 | _emotion_webcam_remove_cb, check); | 201 | _emotion_webcams->webcams = |
245 | break ; | 202 | eina_list_remove_list(_emotion_webcams->webcams, l); |
246 | } | 203 | ew->in_list = EINA_FALSE; |
204 | } | ||
205 | ecore_event_add(EMOTION_WEBCAM_DEL, ew, | ||
206 | _emotion_webcam_remove_cb, NULL); | ||
207 | break; | ||
208 | } | ||
209 | } | ||
247 | } | 210 | } |
248 | else if (ev == EEZE_UDEV_EVENT_ADD) | 211 | else if (ev == EEZE_UDEV_EVENT_ADD) |
249 | { | 212 | { |
250 | Emotion_Webcam *test; | 213 | _emotion_webcam_ev_add(syspath); |
251 | |||
252 | test = _emotion_webcam_new(syspath); | ||
253 | if (test) | ||
254 | { | ||
255 | if (_emotion_check_device(test)) | ||
256 | ecore_event_add(EMOTION_WEBCAM_ADD, test, NULL, NULL); | ||
257 | } | ||
258 | } | 214 | } |
259 | ecore_event_add(EMOTION_WEBCAM_UPDATE, NULL, NULL, NULL); | 215 | ecore_event_add(EMOTION_WEBCAM_UPDATE, NULL, NULL, NULL); |
260 | } | 216 | } |
@@ -266,12 +222,11 @@ _emotion_enumerate_all_webcams(void) | |||
266 | { | 222 | { |
267 | #ifdef HAVE_EEZE | 223 | #ifdef HAVE_EEZE |
268 | Eina_List *devices; | 224 | Eina_List *devices; |
269 | if (_emotion_webcams->init) return ; | 225 | if (_emotion_webcams->init) return; |
270 | devices = eeze_udev_find_by_type(EEZE_UDEV_TYPE_V4L, NULL); | 226 | devices = eeze_udev_find_by_type(EEZE_UDEV_TYPE_V4L, NULL); |
271 | |||
272 | _emotion_webcams->check_list = devices; | 227 | _emotion_webcams->check_list = devices; |
273 | _emotion_webcams->idler = ecore_idler_add(_emotion_process_webcam, | 228 | _emotion_webcams->idler = ecore_idler_add(_emotion_process_webcam, |
274 | _emotion_webcams); | 229 | _emotion_webcams); |
275 | #endif | 230 | #endif |
276 | } | 231 | } |
277 | 232 | ||
@@ -282,9 +237,6 @@ Eina_Bool emotion_webcam_init(void) | |||
282 | EMOTION_WEBCAM_ADD = ecore_event_type_new(); | 237 | EMOTION_WEBCAM_ADD = ecore_event_type_new(); |
283 | EMOTION_WEBCAM_DEL = ecore_event_type_new(); | 238 | EMOTION_WEBCAM_DEL = ecore_event_type_new(); |
284 | 239 | ||
285 | eet_init(); | ||
286 | _emotion_webcams_edds_new(); | ||
287 | |||
288 | if (!_emotion_webcams) | 240 | if (!_emotion_webcams) |
289 | { | 241 | { |
290 | _emotion_webcams = calloc(1, sizeof (Emotion_Webcams)); | 242 | _emotion_webcams = calloc(1, sizeof (Emotion_Webcams)); |
@@ -293,10 +245,9 @@ Eina_Bool emotion_webcam_init(void) | |||
293 | 245 | ||
294 | #ifdef HAVE_EEZE | 246 | #ifdef HAVE_EEZE |
295 | eeze_init(); | 247 | eeze_init(); |
296 | 248 | eeze_watcher = eeze_udev_watch_add | |
297 | eeze_watcher = eeze_udev_watch_add(EEZE_UDEV_TYPE_V4L, | 249 | (EEZE_UDEV_TYPE_V4L, (EEZE_UDEV_EVENT_ADD | EEZE_UDEV_EVENT_REMOVE), |
298 | (EEZE_UDEV_EVENT_ADD | EEZE_UDEV_EVENT_REMOVE), | 250 | _emotion_eeze_events, NULL); |
299 | _emotion_eeze_events, NULL); | ||
300 | #endif | 251 | #endif |
301 | 252 | ||
302 | return EINA_TRUE; | 253 | return EINA_TRUE; |
@@ -308,8 +259,7 @@ emotion_webcam_shutdown(void) | |||
308 | Emotion_Webcam *ew; | 259 | Emotion_Webcam *ew; |
309 | const char *syspath; | 260 | const char *syspath; |
310 | 261 | ||
311 | ecore_event_type_flush(EMOTION_WEBCAM_UPDATE, | 262 | ecore_event_type_flush(EMOTION_WEBCAM_UPDATE, EMOTION_WEBCAM_ADD, |
312 | EMOTION_WEBCAM_ADD, | ||
313 | EMOTION_WEBCAM_DEL); | 263 | EMOTION_WEBCAM_DEL); |
314 | 264 | ||
315 | if (_emotion_webcams->idler) | 265 | if (_emotion_webcams->idler) |
@@ -319,15 +269,21 @@ emotion_webcam_shutdown(void) | |||
319 | } | 269 | } |
320 | 270 | ||
321 | EINA_LIST_FREE(_emotion_webcams->check_list, syspath) | 271 | EINA_LIST_FREE(_emotion_webcams->check_list, syspath) |
322 | eina_stringshare_del(syspath); | 272 | { |
273 | eina_stringshare_del(syspath); | ||
274 | } | ||
323 | 275 | ||
324 | _emotion_webcams->init = EINA_FALSE; | 276 | _emotion_webcams->init = EINA_FALSE; |
325 | 277 | ||
326 | EINA_LIST_FREE(_emotion_webcams->webcams, ew) | 278 | EINA_LIST_FREE(_emotion_webcams->webcams, ew) |
327 | { | 279 | { |
328 | /* There is currently no way to refcount from the outside, this help, but could lead to some issue */ | 280 | ew->in_list = EINA_FALSE; |
281 | // There is currently no way to refcount from the outside, this helps | ||
282 | // but could lead to some issues | ||
329 | EINA_REFCOUNT_UNREF(ew) | 283 | EINA_REFCOUNT_UNREF(ew) |
330 | emotion_webcam_destroy(ew); | 284 | { |
285 | emotion_webcam_destroy(ew); | ||
286 | } | ||
331 | } | 287 | } |
332 | free(_emotion_webcams); | 288 | free(_emotion_webcams); |
333 | _emotion_webcams = NULL; | 289 | _emotion_webcams = NULL; |
@@ -335,54 +291,15 @@ emotion_webcam_shutdown(void) | |||
335 | #ifdef HAVE_EEZE | 291 | #ifdef HAVE_EEZE |
336 | eeze_udev_watch_del(eeze_watcher); | 292 | eeze_udev_watch_del(eeze_watcher); |
337 | eeze_watcher = NULL; | 293 | eeze_watcher = NULL; |
338 | |||
339 | eeze_shutdown(); | 294 | eeze_shutdown(); |
340 | #endif | 295 | #endif |
341 | |||
342 | _emotion_webcams_edds_free(); | ||
343 | eet_shutdown(); | ||
344 | } | ||
345 | |||
346 | Eina_Bool | ||
347 | emotion_webcam_config_load(Eet_File *ef) | ||
348 | { | ||
349 | Emotion_Webcams *emotion_webcams = NULL; | ||
350 | |||
351 | if (ef) | ||
352 | { | ||
353 | emotion_webcams = eet_data_read(ef, _webcams_edd, "config"); | ||
354 | INF("Loaded config %p from eet %s", _emotion_webcams, eet_file_get(ef)); | ||
355 | } | ||
356 | |||
357 | if (emotion_webcams) | ||
358 | { | ||
359 | if (_emotion_webcams) | ||
360 | { | ||
361 | emotion_webcam_shutdown(); | ||
362 | _emotion_webcams = emotion_webcams; | ||
363 | emotion_webcam_init(); | ||
364 | } | ||
365 | else | ||
366 | _emotion_webcams = emotion_webcams; | ||
367 | } | ||
368 | |||
369 | if (!_emotion_webcams) | ||
370 | { | ||
371 | DBG("No config, create empty"); | ||
372 | _emotion_webcams = calloc(1, sizeof (Emotion_Webcams)); | ||
373 | EINA_SAFETY_ON_NULL_RETURN_VAL(_emotion_webcams, EINA_FALSE); | ||
374 | } | ||
375 | |||
376 | return EINA_TRUE; | ||
377 | } | 296 | } |
378 | 297 | ||
379 | EAPI const Eina_List * | 298 | EAPI const Eina_List * |
380 | emotion_webcams_get(void) | 299 | emotion_webcams_get(void) |
381 | { | 300 | { |
382 | EINA_SAFETY_ON_NULL_RETURN_VAL(_emotion_webcams, NULL); | 301 | EINA_SAFETY_ON_NULL_RETURN_VAL(_emotion_webcams, NULL); |
383 | |||
384 | _emotion_enumerate_all_webcams(); | 302 | _emotion_enumerate_all_webcams(); |
385 | |||
386 | return _emotion_webcams->webcams; | 303 | return _emotion_webcams->webcams; |
387 | } | 304 | } |
388 | 305 | ||
@@ -401,18 +318,7 @@ emotion_webcam_device_get(const Emotion_Webcam *ew) | |||
401 | } | 318 | } |
402 | 319 | ||
403 | EAPI const char * | 320 | EAPI const char * |
404 | emotion_webcam_custom_get(const char *device) | 321 | emotion_webcam_custom_get(const char *device EINA_UNUSED) |
405 | { | 322 | { |
406 | const Emotion_Webcam *ew; | ||
407 | const Eina_List *l; | ||
408 | |||
409 | EINA_SAFETY_ON_NULL_RETURN_VAL(_emotion_webcams, NULL); | ||
410 | |||
411 | _emotion_enumerate_all_webcams(); | ||
412 | |||
413 | EINA_LIST_FOREACH(_emotion_webcams->webcams, l, ew) | ||
414 | if (ew->device && strcmp(device, ew->device) == 0) | ||
415 | return ew->custom; | ||
416 | |||
417 | return NULL; | 323 | return NULL; |
418 | } | 324 | } |