2011-12-30 03:46:29 -08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2012-03-25 11:43:21 -07:00
|
|
|
#ifdef STDC_HEADERS
|
|
|
|
# include <stdlib.h>
|
|
|
|
# include <stddef.h>
|
|
|
|
#else
|
|
|
|
# ifdef HAVE_STDLIB_H
|
|
|
|
# include <stdlib.h>
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
2011-12-30 03:46:29 -08:00
|
|
|
#include <stdio.h>
|
2011-07-17 14:58:40 -07:00
|
|
|
|
2013-01-09 19:43:32 -08:00
|
|
|
#ifdef HAVE_EEZE
|
2011-12-30 03:46:29 -08:00
|
|
|
# include <sys/types.h>
|
|
|
|
# include <sys/stat.h>
|
|
|
|
# include <fcntl.h>
|
2011-08-09 02:15:56 -07:00
|
|
|
# ifdef HAVE_V4L2
|
2013-01-09 19:43:32 -08:00
|
|
|
# include <sys/ioctl.h>
|
2011-08-09 02:15:56 -07:00
|
|
|
# include <linux/videodev2.h>
|
|
|
|
# endif
|
2011-07-17 14:58:40 -07:00
|
|
|
# include <Eeze.h>
|
|
|
|
#endif
|
|
|
|
|
2012-12-02 14:21:47 -08:00
|
|
|
#include <Ecore.h>
|
2011-11-09 08:27:49 -08:00
|
|
|
#include <Eet.h>
|
|
|
|
|
2011-12-30 03:46:29 -08:00
|
|
|
#include "Emotion.h"
|
|
|
|
#include "emotion_private.h"
|
|
|
|
|
2012-03-16 21:17:29 -07:00
|
|
|
static Emotion_Version _version = { VMAJ, VMIN, VMIC, VREV };
|
2012-07-02 18:58:13 -07:00
|
|
|
static int emotion_pending_objects = 0;
|
2012-03-16 21:17:29 -07:00
|
|
|
EAPI Emotion_Version *emotion_version = &_version;
|
|
|
|
|
2011-07-17 14:58:40 -07:00
|
|
|
EAPI int EMOTION_WEBCAM_UPDATE = 0;
|
|
|
|
|
|
|
|
struct ext_match_s
|
|
|
|
{
|
|
|
|
unsigned int length;
|
|
|
|
const char *extension;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define MATCHING(Ext) \
|
|
|
|
{ sizeof (Ext), Ext }
|
|
|
|
|
|
|
|
static const struct ext_match_s matchs[] =
|
|
|
|
{ /* map extensions to know if it's a emotion playable content for good first-guess tries */
|
|
|
|
MATCHING(".264"),
|
|
|
|
MATCHING(".3g2"),
|
|
|
|
MATCHING(".3gp"),
|
|
|
|
MATCHING(".3gp2"),
|
|
|
|
MATCHING(".3gpp"),
|
|
|
|
MATCHING(".3gpp2"),
|
|
|
|
MATCHING(".3p2"),
|
|
|
|
MATCHING(".asf"),
|
|
|
|
MATCHING(".avi"),
|
|
|
|
MATCHING(".bdm"),
|
|
|
|
MATCHING(".bdmv"),
|
|
|
|
MATCHING(".clpi"),
|
|
|
|
MATCHING(".clp"),
|
|
|
|
MATCHING(".fla"),
|
|
|
|
MATCHING(".flv"),
|
|
|
|
MATCHING(".m1v"),
|
|
|
|
MATCHING(".m2v"),
|
|
|
|
MATCHING(".m2t"),
|
|
|
|
MATCHING(".m4v"),
|
|
|
|
MATCHING(".mkv"),
|
|
|
|
MATCHING(".mov"),
|
|
|
|
MATCHING(".mp2"),
|
|
|
|
MATCHING(".mp2ts"),
|
|
|
|
MATCHING(".mp4"),
|
|
|
|
MATCHING(".mpe"),
|
|
|
|
MATCHING(".mpeg"),
|
|
|
|
MATCHING(".mpg"),
|
|
|
|
MATCHING(".mpl"),
|
|
|
|
MATCHING(".mpls"),
|
|
|
|
MATCHING(".mts"),
|
|
|
|
MATCHING(".mxf"),
|
|
|
|
MATCHING(".nut"),
|
|
|
|
MATCHING(".nuv"),
|
|
|
|
MATCHING(".ogg"),
|
|
|
|
MATCHING(".ogm"),
|
|
|
|
MATCHING(".ogv"),
|
|
|
|
MATCHING(".rm"),
|
|
|
|
MATCHING(".rmj"),
|
|
|
|
MATCHING(".rmm"),
|
|
|
|
MATCHING(".rms"),
|
|
|
|
MATCHING(".rmx"),
|
|
|
|
MATCHING(".rmvb"),
|
|
|
|
MATCHING(".swf"),
|
|
|
|
MATCHING(".ts"),
|
|
|
|
MATCHING(".weba"),
|
|
|
|
MATCHING(".webm"),
|
|
|
|
MATCHING(".wmv")
|
|
|
|
};
|
|
|
|
|
|
|
|
Eina_Bool
|
2013-01-09 19:43:32 -08:00
|
|
|
_emotion_object_extension_can_play_generic_get(const void *data EINA_UNUSED, const char *file)
|
2011-07-17 14:58:40 -07:00
|
|
|
{
|
|
|
|
unsigned int length;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
length = eina_stringshare_strlen(file) + 1;
|
|
|
|
if (length < 5) return EINA_FALSE;
|
|
|
|
|
|
|
|
for (i = 0; i < sizeof (matchs) / sizeof (struct ext_match_s); ++i)
|
|
|
|
{
|
|
|
|
if (matchs[i].length > length) continue;
|
|
|
|
|
|
|
|
if (!strcasecmp(matchs[i].extension,
|
|
|
|
file + length - matchs[i].length))
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
|
|
|
emotion_object_extension_may_play_fast_get(const char *file)
|
|
|
|
{
|
|
|
|
if (!file) return EINA_FALSE;
|
|
|
|
return _emotion_object_extension_can_play_generic_get(NULL, file);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
|
|
|
emotion_object_extension_may_play_get(const char *file)
|
|
|
|
{
|
|
|
|
const char *tmp;
|
|
|
|
Eina_Bool result;
|
|
|
|
|
|
|
|
if (!file) return EINA_FALSE;
|
|
|
|
tmp = eina_stringshare_add(file);
|
|
|
|
result = emotion_object_extension_may_play_fast_get(tmp);
|
|
|
|
eina_stringshare_del(tmp);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2011-11-09 08:27:49 -08:00
|
|
|
typedef struct _Emotion_Webcams Emotion_Webcams;
|
|
|
|
|
|
|
|
struct _Emotion_Webcams
|
|
|
|
{
|
|
|
|
Eina_List *webcams;
|
|
|
|
};
|
|
|
|
|
2011-07-17 14:58:40 -07:00
|
|
|
struct _Emotion_Webcam
|
|
|
|
{
|
|
|
|
EINA_REFCOUNT;
|
|
|
|
|
|
|
|
const char *syspath;
|
|
|
|
const char *device;
|
|
|
|
const char *name;
|
2011-08-03 07:23:51 -07:00
|
|
|
|
2011-11-09 08:27:49 -08:00
|
|
|
const char *custom;
|
|
|
|
|
2011-08-03 07:23:51 -07:00
|
|
|
const char *filename;
|
2011-07-17 14:58:40 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
static int _emotion_webcams_count = 0;
|
2011-11-09 08:27:49 -08:00
|
|
|
static Eet_Data_Descriptor *_webcam_edd;
|
|
|
|
static Eet_Data_Descriptor *_webcams_edd;
|
|
|
|
|
|
|
|
static Emotion_Webcams *_emotion_webcams = NULL;
|
|
|
|
static Eet_File *_emotion_webcams_file = NULL;
|
|
|
|
|
|
|
|
static Eet_Data_Descriptor *
|
|
|
|
_emotion_webcams_data(void)
|
|
|
|
{
|
|
|
|
Eet_Data_Descriptor_Class eddc;
|
|
|
|
|
|
|
|
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Emotion_Webcam);
|
|
|
|
_webcam_edd = eet_data_descriptor_file_new(&eddc);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "device", device, EET_T_STRING);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "name", name, EET_T_STRING);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "custom", custom, EET_T_STRING);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "filename", filename, EET_T_STRING);
|
|
|
|
|
|
|
|
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Emotion_Webcams);
|
|
|
|
_webcams_edd = eet_data_descriptor_file_new(&eddc);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_LIST(_webcams_edd, Emotion_Webcams, "webcams", webcams, _webcam_edd);
|
|
|
|
|
|
|
|
return _webcams_edd;
|
|
|
|
}
|
|
|
|
|
2011-07-17 14:58:40 -07:00
|
|
|
static void
|
|
|
|
emotion_webcam_destroy(Emotion_Webcam *ew)
|
|
|
|
{
|
2011-11-09 08:27:49 -08:00
|
|
|
if (!ew->custom)
|
|
|
|
{
|
|
|
|
eina_stringshare_del(ew->syspath);
|
|
|
|
eina_stringshare_del(ew->device);
|
|
|
|
eina_stringshare_del(ew->name);
|
|
|
|
}
|
2011-07-17 14:58:40 -07:00
|
|
|
free(ew);
|
|
|
|
}
|
|
|
|
|
2013-01-09 19:43:32 -08:00
|
|
|
#ifdef HAVE_EEZE
|
2012-12-02 14:21:47 -08:00
|
|
|
static Eeze_Udev_Watch *eeze_watcher = NULL;
|
|
|
|
|
2011-07-17 14:58:40 -07:00
|
|
|
static void
|
|
|
|
_emotion_check_device(Emotion_Webcam *ew)
|
|
|
|
{
|
2011-08-09 02:15:56 -07:00
|
|
|
#ifdef HAVE_V4L2
|
2011-07-17 14:58:40 -07:00
|
|
|
Emotion_Webcam *check;
|
|
|
|
Eina_List *l;
|
|
|
|
struct v4l2_capability caps;
|
|
|
|
int fd;
|
2011-08-09 02:15:56 -07:00
|
|
|
#endif
|
2011-07-17 14:58:40 -07:00
|
|
|
|
|
|
|
if (!ew) return ;
|
2011-08-09 02:15:56 -07:00
|
|
|
#ifdef HAVE_V4L2
|
2011-07-17 14:58:40 -07:00
|
|
|
if (!ew->device) goto on_error;
|
|
|
|
|
2011-08-03 07:23:51 -07:00
|
|
|
fd = open(ew->filename, O_RDONLY);
|
|
|
|
if (fd < 0) goto on_error;
|
2011-07-17 14:58:40 -07:00
|
|
|
|
|
|
|
if (ioctl(fd, VIDIOC_QUERYCAP, &caps) == -1) goto on_error;
|
|
|
|
|
|
|
|
/* Likely not a webcam */
|
|
|
|
if (!caps.capabilities & V4L2_CAP_VIDEO_CAPTURE) goto on_error;
|
|
|
|
if (caps.capabilities & V4L2_CAP_TUNER
|
|
|
|
|| caps.capabilities & V4L2_CAP_RADIO
|
|
|
|
|| caps.capabilities & V4L2_CAP_MODULATOR)
|
|
|
|
goto on_error;
|
|
|
|
|
2011-11-09 08:27:49 -08:00
|
|
|
EINA_LIST_FOREACH(_emotion_webcams->webcams, l, check)
|
2011-07-17 14:58:40 -07:00
|
|
|
if (check->device == ew->device)
|
|
|
|
goto on_error;
|
|
|
|
|
2011-11-09 08:27:49 -08:00
|
|
|
_emotion_webcams->webcams = eina_list_append(_emotion_webcams->webcams, ew);
|
2011-07-17 14:58:40 -07:00
|
|
|
|
|
|
|
EINA_REFCOUNT_INIT(ew);
|
|
|
|
|
|
|
|
return ;
|
|
|
|
|
|
|
|
on_error:
|
2011-08-09 02:15:56 -07:00
|
|
|
#endif
|
2013-01-03 12:27:17 -08:00
|
|
|
EINA_LOG_ERR("'%s' is not a webcam ['%s']", ew->name, strerror(errno));
|
2011-07-17 14:58:40 -07:00
|
|
|
eina_stringshare_del(ew->syspath);
|
|
|
|
eina_stringshare_del(ew->device);
|
|
|
|
eina_stringshare_del(ew->name);
|
|
|
|
free(ew);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Emotion_Webcam *
|
|
|
|
_emotion_webcam_new(const char *syspath)
|
|
|
|
{
|
|
|
|
Emotion_Webcam *test;
|
2011-07-19 15:34:54 -07:00
|
|
|
const char *device;
|
|
|
|
char *local;
|
2011-07-17 14:58:40 -07:00
|
|
|
|
|
|
|
test = malloc(sizeof (Emotion_Webcam));
|
|
|
|
if (!test) return NULL;
|
|
|
|
|
2011-11-09 08:27:49 -08:00
|
|
|
test->custom = NULL;
|
2011-07-17 14:58:40 -07:00
|
|
|
test->syspath = eina_stringshare_ref(syspath);
|
|
|
|
test->name = eeze_udev_syspath_get_sysattr(syspath, "name");
|
|
|
|
|
2011-07-19 15:34:54 -07:00
|
|
|
device = eeze_udev_syspath_get_property(syspath, "DEVNAME");
|
|
|
|
local = alloca(eina_stringshare_strlen(device) + 8);
|
|
|
|
snprintf(local, eina_stringshare_strlen(device) + 8, "v4l2://%s", device);
|
|
|
|
test->device = eina_stringshare_add(local);
|
|
|
|
eina_stringshare_del(device);
|
2011-08-03 07:23:51 -07:00
|
|
|
test->filename = test->device + 7;
|
2011-07-19 15:34:54 -07:00
|
|
|
|
2011-07-17 14:58:40 -07:00
|
|
|
return test;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_emotion_enumerate_all_webcams(void)
|
|
|
|
{
|
|
|
|
Eina_List *devices;
|
|
|
|
const char *syspath;
|
|
|
|
|
|
|
|
devices = eeze_udev_find_by_type(EEZE_UDEV_TYPE_V4L, NULL);
|
|
|
|
|
|
|
|
EINA_LIST_FREE(devices, syspath)
|
|
|
|
{
|
|
|
|
Emotion_Webcam *test;
|
|
|
|
|
|
|
|
test = _emotion_webcam_new(syspath);
|
|
|
|
if (test) _emotion_check_device(test);
|
|
|
|
|
|
|
|
eina_stringshare_del(syspath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_emotion_eeze_events(const char *syspath,
|
|
|
|
Eeze_Udev_Event ev,
|
2013-01-09 19:43:32 -08:00
|
|
|
void *data EINA_UNUSED,
|
|
|
|
Eeze_Udev_Watch *watcher EINA_UNUSED)
|
2011-07-17 14:58:40 -07:00
|
|
|
{
|
|
|
|
if (ev == EEZE_UDEV_EVENT_REMOVE)
|
|
|
|
{
|
|
|
|
Emotion_Webcam *check;
|
|
|
|
Eina_List *l;
|
|
|
|
|
2011-11-09 08:27:49 -08:00
|
|
|
EINA_LIST_FOREACH(_emotion_webcams->webcams, l, check)
|
2011-07-17 14:58:40 -07:00
|
|
|
if (check->syspath == syspath)
|
|
|
|
{
|
2011-11-09 08:27:49 -08:00
|
|
|
_emotion_webcams->webcams = eina_list_remove_list(_emotion_webcams->webcams, l);
|
2011-07-17 14:58:40 -07:00
|
|
|
EINA_REFCOUNT_UNREF(check)
|
|
|
|
emotion_webcam_destroy(check);
|
|
|
|
break ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (ev == EEZE_UDEV_EVENT_ADD)
|
|
|
|
{
|
|
|
|
Emotion_Webcam *test;
|
|
|
|
|
|
|
|
test = _emotion_webcam_new(syspath);
|
|
|
|
if (test) _emotion_check_device(test);
|
|
|
|
}
|
|
|
|
ecore_event_add(EMOTION_WEBCAM_UPDATE, NULL, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
|
|
|
emotion_init(void)
|
|
|
|
{
|
2011-11-09 08:27:49 -08:00
|
|
|
char buffer[4096];
|
|
|
|
|
2011-07-17 14:58:40 -07:00
|
|
|
if (_emotion_webcams_count++) return EINA_TRUE;
|
|
|
|
|
2012-07-02 18:58:13 -07:00
|
|
|
ecore_init();
|
|
|
|
|
2011-11-09 08:27:49 -08:00
|
|
|
snprintf(buffer, 4096, "%s/emotion.cfg", PACKAGE_DATA_DIR);
|
|
|
|
_emotion_webcams_file = eet_open(buffer, EET_FILE_MODE_READ);
|
|
|
|
if (_emotion_webcams_file)
|
|
|
|
{
|
|
|
|
Eet_Data_Descriptor *edd;
|
|
|
|
|
|
|
|
edd = _emotion_webcams_data();
|
|
|
|
|
|
|
|
_emotion_webcams = eet_data_read(_emotion_webcams_file, edd, "config");
|
|
|
|
|
|
|
|
eet_data_descriptor_free(_webcams_edd); _webcams_edd = NULL;
|
|
|
|
eet_data_descriptor_free(_webcam_edd); _webcam_edd = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!_emotion_webcams)
|
|
|
|
{
|
|
|
|
_emotion_webcams = calloc(1, sizeof (Emotion_Webcams));
|
|
|
|
if (!_emotion_webcams) return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
2013-01-09 19:43:32 -08:00
|
|
|
#ifdef HAVE_EEZE
|
2011-07-17 14:58:40 -07:00
|
|
|
EMOTION_WEBCAM_UPDATE = ecore_event_type_new();
|
|
|
|
|
|
|
|
eeze_init();
|
|
|
|
|
|
|
|
_emotion_enumerate_all_webcams();
|
|
|
|
|
|
|
|
eeze_watcher = eeze_udev_watch_add(EEZE_UDEV_TYPE_V4L,
|
|
|
|
(EEZE_UDEV_EVENT_ADD | EEZE_UDEV_EVENT_REMOVE),
|
|
|
|
_emotion_eeze_events, NULL);
|
2011-11-09 08:27:49 -08:00
|
|
|
#endif
|
2011-07-17 14:58:40 -07:00
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
|
|
|
emotion_shutdown(void)
|
|
|
|
{
|
2011-11-09 08:27:49 -08:00
|
|
|
Emotion_Webcam *ew;
|
2012-07-02 18:58:13 -07:00
|
|
|
double start;
|
2011-11-09 08:27:49 -08:00
|
|
|
|
2012-05-30 03:08:41 -07:00
|
|
|
if (_emotion_webcams_count <= 0)
|
|
|
|
{
|
|
|
|
EINA_LOG_ERR("Init count not greater than 0 in shutdown.");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
2011-07-17 14:58:40 -07:00
|
|
|
if (--_emotion_webcams_count) return EINA_TRUE;
|
|
|
|
|
2011-11-09 08:27:49 -08:00
|
|
|
EINA_LIST_FREE(_emotion_webcams->webcams, ew)
|
|
|
|
{
|
|
|
|
/* There is currently no way to refcount from the outside, this help, but could lead to some issue */
|
|
|
|
EINA_REFCOUNT_UNREF(ew)
|
|
|
|
emotion_webcam_destroy(ew);
|
|
|
|
}
|
|
|
|
free(_emotion_webcams);
|
|
|
|
_emotion_webcams = NULL;
|
|
|
|
|
|
|
|
if (_emotion_webcams_file)
|
|
|
|
{
|
|
|
|
/* As long as there is no one reference any pointer, you are safe */
|
|
|
|
eet_close(_emotion_webcams_file);
|
|
|
|
_emotion_webcams_file = NULL;
|
|
|
|
}
|
|
|
|
|
2013-01-09 19:43:32 -08:00
|
|
|
#ifdef HAVE_EEZE
|
2011-07-17 14:58:40 -07:00
|
|
|
eeze_udev_watch_del(eeze_watcher);
|
|
|
|
eeze_watcher = NULL;
|
|
|
|
|
|
|
|
eeze_shutdown();
|
2011-11-09 08:27:49 -08:00
|
|
|
#endif
|
2011-07-17 14:58:40 -07:00
|
|
|
|
2012-07-02 18:58:13 -07:00
|
|
|
start = ecore_time_get();
|
|
|
|
while (emotion_pending_objects && ecore_time_get() - start < 0.5)
|
|
|
|
ecore_main_loop_iterate();
|
|
|
|
|
|
|
|
if (emotion_pending_objects)
|
|
|
|
{
|
|
|
|
EINA_LOG_ERR("There is still %i Emotion pipeline running", emotion_pending_objects);
|
|
|
|
}
|
|
|
|
|
|
|
|
ecore_shutdown();
|
|
|
|
|
2011-07-17 14:58:40 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI const Eina_List *
|
|
|
|
emotion_webcams_get(void)
|
|
|
|
{
|
2011-11-09 08:27:49 -08:00
|
|
|
return _emotion_webcams->webcams;
|
2011-07-17 14:58:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI const char *
|
2011-08-03 07:23:51 -07:00
|
|
|
emotion_webcam_name_get(const Emotion_Webcam *ew)
|
2011-07-17 14:58:40 -07:00
|
|
|
{
|
|
|
|
if (!ew) return NULL;
|
|
|
|
|
|
|
|
return ew->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI const char *
|
2011-08-03 07:23:51 -07:00
|
|
|
emotion_webcam_device_get(const Emotion_Webcam *ew)
|
2011-07-17 14:58:40 -07:00
|
|
|
{
|
|
|
|
if (!ew) return NULL;
|
|
|
|
|
|
|
|
return ew->device;
|
2011-11-09 08:27:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI const char *
|
|
|
|
emotion_webcam_custom_get(const char *device)
|
|
|
|
{
|
|
|
|
const Emotion_Webcam *ew;
|
|
|
|
const Eina_List *l;
|
|
|
|
|
2011-11-13 13:52:13 -08:00
|
|
|
if (_emotion_webcams)
|
|
|
|
{
|
|
|
|
EINA_LIST_FOREACH(_emotion_webcams->webcams, l, ew)
|
|
|
|
if (ew->device && strcmp(device, ew->device) == 0)
|
|
|
|
return ew->custom;
|
|
|
|
}
|
2011-11-09 08:27:49 -08:00
|
|
|
|
2011-07-17 14:58:40 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
2012-07-02 18:58:13 -07:00
|
|
|
|
|
|
|
EAPI void
|
|
|
|
_emotion_pending_object_ref(void)
|
|
|
|
{
|
|
|
|
emotion_pending_objects++;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
_emotion_pending_object_unref(void)
|
|
|
|
{
|
|
|
|
emotion_pending_objects--;
|
|
|
|
}
|