summaryrefslogtreecommitdiff
path: root/src/lib/emotion/emotion_main.c
diff options
context:
space:
mode:
authorGustavo Sverzut Barbieri <barbieri@gmail.com>2013-01-10 03:43:32 +0000
committerGustavo Sverzut Barbieri <barbieri@gmail.com>2013-01-10 03:43:32 +0000
commitdfb84c1657bfb14a5236b881193b81f4c0b8a69b (patch)
treeb51b210fc88a21eec8e5907b8bbfe12ebc669f90 /src/lib/emotion/emotion_main.c
parent532284dbbe4259a9f2291f44d3eff376849e8031 (diff)
efl: merge emotion.
this one was quite a huge work, but hopefully it's correct. NOTES: * removed vlc generic module, it should go into a separate package. * gstreamer is enabled by default (see --disable-gstreamer) * xine is disabled by default (see --enable-gstreamer) * generic is always built statically if supported * gstreamer and xine can't be configured as static (just lacks command line options, build system supports it) * v4l2 is enabled by default on linux if eeze is built (see --disable-v4l2) * emotion_test moved to src/tests/emotion and depends on EFL_ENABLE_TESTS (--with-tests), but is still installed if enabled. TODO (need your help!): * fix warnings with gstreamer and xine engine * call engine shutdown functions if building as static * remove direct usage of PACKAGE_*_DIR and use eina_prefix * add eina_prefix checkme file as evas and others * add support for $EFL_RUN_IN_TREE * create separate package for emotion_generic_modules * check docs hierarchy (doxygen is segv'in here) SVN revision: 82501
Diffstat (limited to 'src/lib/emotion/emotion_main.c')
-rw-r--r--src/lib/emotion/emotion_main.c464
1 files changed, 464 insertions, 0 deletions
diff --git a/src/lib/emotion/emotion_main.c b/src/lib/emotion/emotion_main.c
new file mode 100644
index 0000000000..8416f50b1c
--- /dev/null
+++ b/src/lib/emotion/emotion_main.c
@@ -0,0 +1,464 @@
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4
5#ifdef STDC_HEADERS
6# include <stdlib.h>
7# include <stddef.h>
8#else
9# ifdef HAVE_STDLIB_H
10# include <stdlib.h>
11# endif
12#endif
13
14#include <stdio.h>
15
16#ifdef HAVE_EEZE
17# include <sys/types.h>
18# include <sys/stat.h>
19# include <fcntl.h>
20# ifdef HAVE_V4L2
21# include <sys/ioctl.h>
22# include <linux/videodev2.h>
23# endif
24# include <Eeze.h>
25#endif
26
27#include <Ecore.h>
28#include <Eet.h>
29
30#include "Emotion.h"
31#include "emotion_private.h"
32
33static Emotion_Version _version = { VMAJ, VMIN, VMIC, VREV };
34static int emotion_pending_objects = 0;
35EAPI Emotion_Version *emotion_version = &_version;
36
37EAPI int EMOTION_WEBCAM_UPDATE = 0;
38
39struct ext_match_s
40{
41 unsigned int length;
42 const char *extension;
43};
44
45#define MATCHING(Ext) \
46 { sizeof (Ext), Ext }
47
48static const struct ext_match_s matchs[] =
49{ /* map extensions to know if it's a emotion playable content for good first-guess tries */
50 MATCHING(".264"),
51 MATCHING(".3g2"),
52 MATCHING(".3gp"),
53 MATCHING(".3gp2"),
54 MATCHING(".3gpp"),
55 MATCHING(".3gpp2"),
56 MATCHING(".3p2"),
57 MATCHING(".asf"),
58 MATCHING(".avi"),
59 MATCHING(".bdm"),
60 MATCHING(".bdmv"),
61 MATCHING(".clpi"),
62 MATCHING(".clp"),
63 MATCHING(".fla"),
64 MATCHING(".flv"),
65 MATCHING(".m1v"),
66 MATCHING(".m2v"),
67 MATCHING(".m2t"),
68 MATCHING(".m4v"),
69 MATCHING(".mkv"),
70 MATCHING(".mov"),
71 MATCHING(".mp2"),
72 MATCHING(".mp2ts"),
73 MATCHING(".mp4"),
74 MATCHING(".mpe"),
75 MATCHING(".mpeg"),
76 MATCHING(".mpg"),
77 MATCHING(".mpl"),
78 MATCHING(".mpls"),
79 MATCHING(".mts"),
80 MATCHING(".mxf"),
81 MATCHING(".nut"),
82 MATCHING(".nuv"),
83 MATCHING(".ogg"),
84 MATCHING(".ogm"),
85 MATCHING(".ogv"),
86 MATCHING(".rm"),
87 MATCHING(".rmj"),
88 MATCHING(".rmm"),
89 MATCHING(".rms"),
90 MATCHING(".rmx"),
91 MATCHING(".rmvb"),
92 MATCHING(".swf"),
93 MATCHING(".ts"),
94 MATCHING(".weba"),
95 MATCHING(".webm"),
96 MATCHING(".wmv")
97};
98
99Eina_Bool
100_emotion_object_extension_can_play_generic_get(const void *data EINA_UNUSED, const char *file)
101{
102 unsigned int length;
103 unsigned int i;
104
105 length = eina_stringshare_strlen(file) + 1;
106 if (length < 5) return EINA_FALSE;
107
108 for (i = 0; i < sizeof (matchs) / sizeof (struct ext_match_s); ++i)
109 {
110 if (matchs[i].length > length) continue;
111
112 if (!strcasecmp(matchs[i].extension,
113 file + length - matchs[i].length))
114 return EINA_TRUE;
115 }
116
117 return EINA_FALSE;
118}
119
120EAPI Eina_Bool
121emotion_object_extension_may_play_fast_get(const char *file)
122{
123 if (!file) return EINA_FALSE;
124 return _emotion_object_extension_can_play_generic_get(NULL, file);
125}
126
127EAPI Eina_Bool
128emotion_object_extension_may_play_get(const char *file)
129{
130 const char *tmp;
131 Eina_Bool result;
132
133 if (!file) return EINA_FALSE;
134 tmp = eina_stringshare_add(file);
135 result = emotion_object_extension_may_play_fast_get(tmp);
136 eina_stringshare_del(tmp);
137
138 return result;
139}
140
141typedef struct _Emotion_Webcams Emotion_Webcams;
142
143struct _Emotion_Webcams
144{
145 Eina_List *webcams;
146};
147
148struct _Emotion_Webcam
149{
150 EINA_REFCOUNT;
151
152 const char *syspath;
153 const char *device;
154 const char *name;
155
156 const char *custom;
157
158 const char *filename;
159};
160
161static int _emotion_webcams_count = 0;
162static Eet_Data_Descriptor *_webcam_edd;
163static Eet_Data_Descriptor *_webcams_edd;
164
165static Emotion_Webcams *_emotion_webcams = NULL;
166static Eet_File *_emotion_webcams_file = NULL;
167
168static Eet_Data_Descriptor *
169_emotion_webcams_data(void)
170{
171 Eet_Data_Descriptor_Class eddc;
172
173 EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Emotion_Webcam);
174 _webcam_edd = eet_data_descriptor_file_new(&eddc);
175 EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "device", device, EET_T_STRING);
176 EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "name", name, EET_T_STRING);
177 EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "custom", custom, EET_T_STRING);
178 EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "filename", filename, EET_T_STRING);
179
180 EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Emotion_Webcams);
181 _webcams_edd = eet_data_descriptor_file_new(&eddc);
182 EET_DATA_DESCRIPTOR_ADD_LIST(_webcams_edd, Emotion_Webcams, "webcams", webcams, _webcam_edd);
183
184 return _webcams_edd;
185}
186
187static void
188emotion_webcam_destroy(Emotion_Webcam *ew)
189{
190 if (!ew->custom)
191 {
192 eina_stringshare_del(ew->syspath);
193 eina_stringshare_del(ew->device);
194 eina_stringshare_del(ew->name);
195 }
196 free(ew);
197}
198
199#ifdef HAVE_EEZE
200static Eeze_Udev_Watch *eeze_watcher = NULL;
201
202static void
203_emotion_check_device(Emotion_Webcam *ew)
204{
205#ifdef HAVE_V4L2
206 Emotion_Webcam *check;
207 Eina_List *l;
208 struct v4l2_capability caps;
209 int fd;
210#endif
211
212 if (!ew) return ;
213#ifdef HAVE_V4L2
214 if (!ew->device) goto on_error;
215
216 fd = open(ew->filename, O_RDONLY);
217 if (fd < 0) goto on_error;
218
219 if (ioctl(fd, VIDIOC_QUERYCAP, &caps) == -1) goto on_error;
220
221 /* Likely not a webcam */
222 if (!caps.capabilities & V4L2_CAP_VIDEO_CAPTURE) goto on_error;
223 if (caps.capabilities & V4L2_CAP_TUNER
224 || caps.capabilities & V4L2_CAP_RADIO
225 || caps.capabilities & V4L2_CAP_MODULATOR)
226 goto on_error;
227
228 EINA_LIST_FOREACH(_emotion_webcams->webcams, l, check)
229 if (check->device == ew->device)
230 goto on_error;
231
232 _emotion_webcams->webcams = eina_list_append(_emotion_webcams->webcams, ew);
233
234 EINA_REFCOUNT_INIT(ew);
235
236 return ;
237
238 on_error:
239#endif
240 EINA_LOG_ERR("'%s' is not a webcam ['%s']", ew->name, strerror(errno));
241 eina_stringshare_del(ew->syspath);
242 eina_stringshare_del(ew->device);
243 eina_stringshare_del(ew->name);
244 free(ew);
245}
246
247static Emotion_Webcam *
248_emotion_webcam_new(const char *syspath)
249{
250 Emotion_Webcam *test;
251 const char *device;
252 char *local;
253
254 test = malloc(sizeof (Emotion_Webcam));
255 if (!test) return NULL;
256
257 test->custom = NULL;
258 test->syspath = eina_stringshare_ref(syspath);
259 test->name = eeze_udev_syspath_get_sysattr(syspath, "name");
260
261 device = eeze_udev_syspath_get_property(syspath, "DEVNAME");
262 local = alloca(eina_stringshare_strlen(device) + 8);
263 snprintf(local, eina_stringshare_strlen(device) + 8, "v4l2://%s", device);
264 test->device = eina_stringshare_add(local);
265 eina_stringshare_del(device);
266 test->filename = test->device + 7;
267
268 return test;
269}
270
271static void
272_emotion_enumerate_all_webcams(void)
273{
274 Eina_List *devices;
275 const char *syspath;
276
277 devices = eeze_udev_find_by_type(EEZE_UDEV_TYPE_V4L, NULL);
278
279 EINA_LIST_FREE(devices, syspath)
280 {
281 Emotion_Webcam *test;
282
283 test = _emotion_webcam_new(syspath);
284 if (test) _emotion_check_device(test);
285
286 eina_stringshare_del(syspath);
287 }
288}
289
290static void
291_emotion_eeze_events(const char *syspath,
292 Eeze_Udev_Event ev,
293 void *data EINA_UNUSED,
294 Eeze_Udev_Watch *watcher EINA_UNUSED)
295{
296 if (ev == EEZE_UDEV_EVENT_REMOVE)
297 {
298 Emotion_Webcam *check;
299 Eina_List *l;
300
301 EINA_LIST_FOREACH(_emotion_webcams->webcams, l, check)
302 if (check->syspath == syspath)
303 {
304 _emotion_webcams->webcams = eina_list_remove_list(_emotion_webcams->webcams, l);
305 EINA_REFCOUNT_UNREF(check)
306 emotion_webcam_destroy(check);
307 break ;
308 }
309 }
310 else if (ev == EEZE_UDEV_EVENT_ADD)
311 {
312 Emotion_Webcam *test;
313
314 test = _emotion_webcam_new(syspath);
315 if (test) _emotion_check_device(test);
316 }
317 ecore_event_add(EMOTION_WEBCAM_UPDATE, NULL, NULL, NULL);
318}
319
320#endif
321
322EAPI Eina_Bool
323emotion_init(void)
324{
325 char buffer[4096];
326
327 if (_emotion_webcams_count++) return EINA_TRUE;
328
329 ecore_init();
330
331 snprintf(buffer, 4096, "%s/emotion.cfg", PACKAGE_DATA_DIR);
332 _emotion_webcams_file = eet_open(buffer, EET_FILE_MODE_READ);
333 if (_emotion_webcams_file)
334 {
335 Eet_Data_Descriptor *edd;
336
337 edd = _emotion_webcams_data();
338
339 _emotion_webcams = eet_data_read(_emotion_webcams_file, edd, "config");
340
341 eet_data_descriptor_free(_webcams_edd); _webcams_edd = NULL;
342 eet_data_descriptor_free(_webcam_edd); _webcam_edd = NULL;
343 }
344
345 if (!_emotion_webcams)
346 {
347 _emotion_webcams = calloc(1, sizeof (Emotion_Webcams));
348 if (!_emotion_webcams) return EINA_FALSE;
349 }
350
351#ifdef HAVE_EEZE
352 EMOTION_WEBCAM_UPDATE = ecore_event_type_new();
353
354 eeze_init();
355
356 _emotion_enumerate_all_webcams();
357
358 eeze_watcher = eeze_udev_watch_add(EEZE_UDEV_TYPE_V4L,
359 (EEZE_UDEV_EVENT_ADD | EEZE_UDEV_EVENT_REMOVE),
360 _emotion_eeze_events, NULL);
361#endif
362
363 return EINA_TRUE;
364}
365
366EAPI Eina_Bool
367emotion_shutdown(void)
368{
369 Emotion_Webcam *ew;
370 double start;
371
372 if (_emotion_webcams_count <= 0)
373 {
374 EINA_LOG_ERR("Init count not greater than 0 in shutdown.");
375 return EINA_FALSE;
376 }
377 if (--_emotion_webcams_count) return EINA_TRUE;
378
379 EINA_LIST_FREE(_emotion_webcams->webcams, ew)
380 {
381 /* There is currently no way to refcount from the outside, this help, but could lead to some issue */
382 EINA_REFCOUNT_UNREF(ew)
383 emotion_webcam_destroy(ew);
384 }
385 free(_emotion_webcams);
386 _emotion_webcams = NULL;
387
388 if (_emotion_webcams_file)
389 {
390 /* As long as there is no one reference any pointer, you are safe */
391 eet_close(_emotion_webcams_file);
392 _emotion_webcams_file = NULL;
393 }
394
395#ifdef HAVE_EEZE
396 eeze_udev_watch_del(eeze_watcher);
397 eeze_watcher = NULL;
398
399 eeze_shutdown();
400#endif
401
402 start = ecore_time_get();
403 while (emotion_pending_objects && ecore_time_get() - start < 0.5)
404 ecore_main_loop_iterate();
405
406 if (emotion_pending_objects)
407 {
408 EINA_LOG_ERR("There is still %i Emotion pipeline running", emotion_pending_objects);
409 }
410
411 ecore_shutdown();
412
413 return EINA_TRUE;
414}
415
416EAPI const Eina_List *
417emotion_webcams_get(void)
418{
419 return _emotion_webcams->webcams;
420}
421
422EAPI const char *
423emotion_webcam_name_get(const Emotion_Webcam *ew)
424{
425 if (!ew) return NULL;
426
427 return ew->name;
428}
429
430EAPI const char *
431emotion_webcam_device_get(const Emotion_Webcam *ew)
432{
433 if (!ew) return NULL;
434
435 return ew->device;
436}
437
438EAPI const char *
439emotion_webcam_custom_get(const char *device)
440{
441 const Emotion_Webcam *ew;
442 const Eina_List *l;
443
444 if (_emotion_webcams)
445 {
446 EINA_LIST_FOREACH(_emotion_webcams->webcams, l, ew)
447 if (ew->device && strcmp(device, ew->device) == 0)
448 return ew->custom;
449 }
450
451 return NULL;
452}
453
454EAPI void
455_emotion_pending_object_ref(void)
456{
457 emotion_pending_objects++;
458}
459
460EAPI void
461_emotion_pending_object_unref(void)
462{
463 emotion_pending_objects--;
464}