#define META_TRACK_COUNT 8
typedef enum _Emotion_Format Emotion_Format;
-typedef struct _Emotion_Video_Module Emotion_Video_Module;
+typedef struct _Emotion_Engine Emotion_Engine;
typedef struct _Emotion_Module_Options Emotion_Module_Options;
typedef struct _Eina_Emotion_Plugins Eina_Emotion_Plugins;
-typedef Eina_Bool (*Emotion_Module_Open)(Evas_Object *, const Emotion_Video_Module **, void **, Emotion_Module_Options *);
-typedef void (*Emotion_Module_Close)(Emotion_Video_Module *module, void *);
-
enum _Emotion_Format
{
EMOTION_FORMAT_NONE,
struct _Emotion_Module_Options
{
- const char *player;
Eina_Bool no_video : 1;
Eina_Bool no_audio : 1;
};
-struct _Eina_Emotion_Plugins
+struct _Emotion_Engine
{
- Emotion_Module_Open open;
- Emotion_Module_Close close;
-};
+#define EMOTION_ENGINE_API_VERSION (1U)
+ unsigned version;
-struct _Emotion_Video_Module
-{
- unsigned char (*file_open) (const char *file, Evas_Object *obj, void *video);
+#define EMOTION_ENGINE_PRIORITY_DEFAULT (50)
+ int priority; /* default priority, may be overwritten by user. Try to keep from 0-100. */
+
+ const char *name;
+ void *(*add)(const Emotion_Engine *api, Evas_Object *obj, const Emotion_Module_Options *opts);
+ void (*del)(void *ef);
+
+ Eina_Bool (*file_open) (void *ef, const char *file);
void (*file_close) (void *ef);
void (*play) (void *ef, double pos);
void (*stop) (void *ef);
EAPI const char *emotion_webcam_custom_get(const char *device);
-EAPI Eina_Bool _emotion_module_register(const char *name, Emotion_Module_Open open, Emotion_Module_Close close);
-EAPI Eina_Bool _emotion_module_unregister(const char *name);
+EAPI Eina_Bool _emotion_module_register(const Emotion_Engine *api);
+EAPI Eina_Bool _emotion_module_unregister(const Emotion_Engine *api);
#endif
void generic_module_shutdown(void);
#endif
-static Eina_Hash *_emotion_backends = NULL;
+typedef struct _Emotion_Engine_Registry_Entry
+{
+ const Emotion_Engine *engine;
+ int priority;
+} Emotion_Engine_Registry_Entry;
+
+static Eina_List *_emotion_engine_registry = NULL;
static Eina_Array *_emotion_modules = NULL;
static void
+_emotion_engine_registry_entry_free(Emotion_Engine_Registry_Entry *re)
+{
+ free(re);
+}
+
+static int
+_emotion_engine_registry_entry_cmp(const void *pa, const void *pb)
+{
+ const Emotion_Engine_Registry_Entry *a = pa, *b = pb;
+ int r = a->priority - b->priority;
+
+ if (r == 0)
+ r = a->engine->priority - b->engine->priority;
+
+ if (r == 0)
+ /* guarantee some order to ease debug */
+ r = strcmp(a->engine->name, b->engine->name);
+
+ return r;
+}
+
+static void
_emotion_modules_load(void)
{
char buf[PATH_MAX];
{
int static_modules = 0;
- _emotion_backends = eina_hash_string_small_new(free);
- EINA_SAFETY_ON_NULL_RETURN_VAL(_emotion_backends, EINA_FALSE);
-
_emotion_modules_load();
/* Init static module */
else if (_emotion_modules)
eina_module_list_load(_emotion_modules);
+ if (!_emotion_engine_registry)
+ ERR("Couldn't find any emotion engine.");
+
return EINA_TRUE;
}
void
emotion_modules_shutdown(void)
{
+ Emotion_Engine_Registry_Entry *re;
+
+ EINA_LIST_FREE(_emotion_engine_registry, re)
+ _emotion_engine_registry_entry_free(re);
+
#ifdef EMOTION_STATIC_BUILD_XINE
xine_module_shutdown();
#endif
eina_array_free(_emotion_modules);
_emotion_modules = NULL;
}
-
- eina_hash_free(_emotion_backends);
- _emotion_backends = NULL;
}
EAPI Eina_Bool
-_emotion_module_register(const char *name, Emotion_Module_Open mod_open, Emotion_Module_Close mod_close)
+_emotion_module_register(const Emotion_Engine *api)
{
- Eina_Emotion_Plugins *plugin;
+ Emotion_Engine_Registry_Entry *re;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(api, EINA_FALSE);
+
+ if (api->version != EMOTION_ENGINE_API_VERSION)
+ {
+ ERR("Module '%p' uses api version=%u while %u was expected",
+ api, api->version, EMOTION_ENGINE_API_VERSION);
+ return EINA_FALSE;
+ }
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(api->name, EINA_FALSE);
+
+ INF("register name=%s, version=%u, priority=%d, api=%p",
+ api->name, api->version, api->priority, api);
+
+ re = calloc(1, sizeof(Emotion_Engine_Registry_Entry));
+ EINA_SAFETY_ON_NULL_RETURN_VAL(re, EINA_FALSE);
- plugin = malloc(sizeof (Eina_Emotion_Plugins));
- EINA_SAFETY_ON_NULL_RETURN_VAL(plugin, EINA_FALSE);
+ re->engine = api;
+ re->priority = api->priority; // TODO: use user-priority from file as weel.
- plugin->open = mod_open;
- plugin->close = mod_close;
+ _emotion_engine_registry = eina_list_sorted_insert
+ (_emotion_engine_registry, _emotion_engine_registry_entry_cmp, re);
- INF("register module=%s, open=%p, close=%p", name, mod_open, mod_close);
- return eina_hash_add(_emotion_backends, name, plugin);
+ return EINA_TRUE;
}
EAPI Eina_Bool
-_emotion_module_unregister(const char *name)
+_emotion_module_unregister(const Emotion_Engine *api)
{
- INF("unregister module=%s", name);
- return eina_hash_del_by_key(_emotion_backends, name);
+ Eina_List *n;
+ Emotion_Engine_Registry_Entry *re;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(api, EINA_FALSE);
+ if (api->version != EMOTION_ENGINE_API_VERSION)
+ {
+ ERR("Module '%p' uses api version=%u while %u was expected",
+ api, api->version, EMOTION_ENGINE_API_VERSION);
+ return EINA_FALSE;
+ }
+
+ INF("unregister name=%s, api=%p", api->name, api);
+
+ EINA_LIST_FOREACH(_emotion_engine_registry, n, re)
+ {
+ if (re->engine == api)
+ {
+ _emotion_engine_registry_entry_free(re);
+ _emotion_engine_registry = eina_list_remove_list
+ (_emotion_engine_registry, n);
+ return EINA_TRUE;
+ }
+ }
+
+ ERR("module not registered name=%s, api=%p", api->name, api);
+ return EINA_FALSE;
}
struct _Emotion_Engine_Instance
{
- Eina_Emotion_Plugins *plugin;
- Emotion_Video_Module *api;
+ const Emotion_Engine *api;
Evas_Object *obj;
- char *name;
void *data;
};
while (0)
-static const char *_backend_priority[] = {
- "gstreamer",
- "xine",
- "generic"
-};
+static const Emotion_Engine *
+_emotion_engine_registry_find(const char *name)
+{
+ const Eina_List *n;
+ const Emotion_Engine_Registry_Entry *re;
+ EINA_LIST_FOREACH(_emotion_engine_registry, n, re)
+ {
+ if (strcmp(re->engine->name, name) == 0)
+ return re->engine;
+ }
+ return NULL;
+}
+
+static Emotion_Engine_Instance *
+_emotion_engine_instance_new(const Emotion_Engine *engine, Evas_Object *obj, void *data)
+{
+ Emotion_Engine_Instance *inst = calloc(1, sizeof(Emotion_Engine_Instance));
+ EINA_SAFETY_ON_NULL_GOTO(inst, error);
+ inst->api = engine;
+ inst->obj = obj;
+ inst->data = data;
+ return inst;
+
+ error:
+ engine->del(data);
+ return NULL;
+}
Emotion_Engine_Instance *
emotion_engine_instance_new(const char *name, Evas_Object *obj, Emotion_Module_Options *opts)
{
- // TODO: rewrite
- Eina_Emotion_Plugins *plugin;
- unsigned int i = 0;
- Emotion_Video_Module *mod = NULL;
- void *data = NULL;
-
- if (!_emotion_backends)
- {
- ERR("No backend loaded");
- return NULL;
- }
+ const Eina_List *n;
+ const Emotion_Engine_Registry_Entry *re;
+ const Emotion_Engine *engine;
+ void *data;
- if (!name && getenv("EMOTION_ENGINE"))
+ if ((!name) && getenv("EMOTION_ENGINE"))
{
name = getenv("EMOTION_ENGINE");
DBG("using EMOTION_ENGINE=%s", name);
}
- /* FIXME: Always look for a working backend. */
- retry:
- if (!name || i > 0)
- name = _backend_priority[i++];
-
- plugin = eina_hash_find(_emotion_backends, name);
- DBG("try engine=%s, plugin=%p", name, plugin);
- if (!plugin)
+ if (name)
{
- if (i != 0 && i < (sizeof (_backend_priority) / sizeof (char*)))
- goto retry;
+ engine = _emotion_engine_registry_find(name);
+ if (!engine)
+ ERR("Couldn't find requested engine: %s. Try fallback", name);
+ else
+ {
+ data = engine->add(engine, obj, opts);
+ if (data)
+ {
+ INF("Using requested engine %s, data=%p", name, data);
+ return _emotion_engine_instance_new(engine, obj, data);
+ }
- ERR("No backend loaded");
- return NULL;
+ ERR("Requested engine '%s' could not be used. Try fallback", name);
+ }
}
- if (plugin->open(obj, (const Emotion_Video_Module **) &mod, &data, opts))
+ EINA_LIST_FOREACH(_emotion_engine_registry, n, re)
{
- Emotion_Engine_Instance *inst = calloc(1, sizeof(Emotion_Engine_Instance));
- INF("opened %s, mod=%p, video=%p", name, mod, data);
- inst->plugin = plugin;
- inst->api = mod;
- inst->obj = obj;
- inst->data = data;
- inst->name = strdup(name);
- return inst;
- }
+ engine = re->engine;
+ DBG("Trying engine %s, priority=%d (%d)",
+ engine->name, re->priority, engine->priority);
- if (i != 0 && i < (sizeof (_backend_priority) / sizeof (char*)))
- goto retry;
-
- ERR("Unable to load module: %s", name);
+ data = engine->add(engine, obj, opts);
+ if (data)
+ {
+ INF("Using fallback engine %s, data=%p", engine->name, data);
+ return _emotion_engine_instance_new(engine, obj, data);
+ }
+ }
+ ERR("No engine worked");
return NULL;
}
emotion_engine_instance_del(Emotion_Engine_Instance *inst)
{
EINA_SAFETY_ON_NULL_RETURN(inst);
- inst->plugin->close(inst->api, inst->data); // TODO: weird api
+ inst->api->del(inst->data);
}
Eina_Bool
/* these are valid, no safety macros here */
if (!name) return EINA_FALSE;
if (!inst) return EINA_FALSE;
- return strcmp(name, inst->name) == 0;
+ return strcmp(name, inst->api->name) == 0;
}
void *
return inst->data;
}
-unsigned char
+Eina_Bool
emotion_engine_instance_file_open(Emotion_Engine_Instance *inst, const char *file)
{
EMOTION_ENGINE_INSTANCE_CHECK(inst, file_open, EINA_FALSE);
- return inst->api->file_open(file, inst->obj, inst->data); // TODO: weird api
+ return inst->api->file_open(inst->data, file);
}
void
Eina_Bool emotion_engine_instance_name_equal(const Emotion_Engine_Instance *inst, const char *name);
void *emotion_engine_instance_data_get(const Emotion_Engine_Instance *inst);
-unsigned char emotion_engine_instance_file_open(Emotion_Engine_Instance *inst, const char *file);
+Eina_Bool emotion_engine_instance_file_open(Emotion_Engine_Instance *inst, const char *file);
void emotion_engine_instance_file_close(Emotion_Engine_Instance *inst);
void emotion_engine_instance_play(Emotion_Engine_Instance *inst, double pos);
void emotion_engine_instance_stop(Emotion_Engine_Instance *inst);
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
if ((!opt) || (!val)) return;
- // TODO remove me
- if (!strcmp(opt, "player"))
- eina_stringshare_replace(&sd->module_options.player, val);
+ if (strcmp(opt, "video") == 0)
+ {
+ if (strcmp(val, "off") == 0)
+ sd->module_options.no_video = EINA_TRUE;
+ else if (strcmp(val, "on") == 0)
+ sd->module_options.no_video = EINA_FALSE;
+ else
+ sd->module_options.no_video = !!atoi(val);
+
+ ERR("Deprecated. Use emotion_object_video_mute_set()");
+ }
+ else if (strcmp(opt, "audio") == 0)
+ {
+ if (strcmp(val, "off") == 0)
+ sd->module_options.no_audio = EINA_TRUE;
+ else if (strcmp(val, "on") == 0)
+ sd->module_options.no_audio = EINA_FALSE;
+ else
+ sd->module_options.no_audio = !!atoi(val);
+
+ ERR("Deprecated. Use emotion_object_audio_mute_set()");
+ }
+ else
+ ERR("Unsupported %s=%s", opt, val);
}
EAPI Eina_Bool
#include "emotion_generic.h"
static Eina_Prefix *pfx = NULL;
+static Eina_List *_generic_players = NULL;
+static int _emotion_init_count = 0;
static int _emotion_generic_log_domain = -1;
#ifdef DBG
#define CRITICAL(...) EINA_LOG_DOM_CRIT(_emotion_generic_log_domain, __VA_ARGS__)
-struct _default_players {
- const char *name;
- const char *cmdline;
-};
-
-static struct _default_players players[] = {
-#ifdef EMOTION_BUILD_GENERIC_VLC
- { "vlc", "em_generic_vlc" },
-#endif
- { NULL, NULL }
-};
-
static Eina_Bool _fork_and_exec(Emotion_Generic_Video *ev);
static void em_partial_shutdown(Emotion_Generic_Video *ev);
return EINA_FALSE;
}
-static const char *
-_get_player(const char *name)
-{
- const char *selected_name = NULL;
- const char *libdir = eina_prefix_lib_get(pfx);
- static char buf[PATH_MAX];
- int i;
-
- if (name)
- {
- for (i = 0; players[i].name; i++)
- {
- if (!strcmp(players[i].name, name))
- {
- selected_name = players[i].cmdline;
- break;
- }
- }
- }
-
- if ((!selected_name) && (name))
- selected_name = name;
-
- if (selected_name)
- {
- const char *cmd;
-
- if (selected_name[0] == '/') cmd = selected_name;
- else
- {
- snprintf(buf, sizeof(buf), "%s/emotion/utils/" MODULE_ARCH "/%s",
- libdir, selected_name);
- cmd = buf;
- }
-
- DBG("Try generic player '%s'", cmd);
- if (access(cmd, R_OK | X_OK) == 0)
- {
- INF("Using generic player '%s'", cmd);
- return cmd;
- }
- }
-
- for (i = 0; players[i].name; i++)
- {
- snprintf(buf, sizeof(buf), "%s/emotion/utils/" MODULE_ARCH "/%s",
- libdir, players[i].cmdline);
- DBG("Try generic player '%s'", buf);
- if (access(buf, R_OK | X_OK) == 0)
- {
- INF("Using fallback player '%s'", buf);
- return buf;
- }
- }
-
- ERR("no generic player found, given name='%s'", name ? name : "");
- return NULL;
-}
-
static void
_player_send_cmd(Emotion_Generic_Video *ev, int cmd)
{
return EINA_FALSE;
}
- snprintf(buf, sizeof(buf), "%s %d %d\n", ev->cmdline, pipe_out[0], pipe_in[1]);
+ snprintf(buf, sizeof(buf), "%s %d %d\n", ev->engine->path, pipe_out[0], pipe_in[1]);
ev->player.exe = ecore_exe_pipe_run(
buf,
return EINA_TRUE;
}
-static unsigned char
-em_init(Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt)
+static void *
+em_add(const Emotion_Engine *api, Evas_Object *obj, const Emotion_Module_Options *opt EINA_UNUSED)
{
Emotion_Generic_Video *ev;
- const char *player;
-
- if (!emotion_video) return 0;
- player = _get_player(opt ? opt->player : NULL);
- if (!player) return 0;
- ev = (Emotion_Generic_Video *)calloc(1, sizeof(*ev));
- if (!ev) return 0;
+ ev = calloc(1, sizeof(*ev));
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ev, NULL);
ev->fd_read = -1;
ev->fd_write = -1;
ev->cmd.type = -1;
ev->obj = obj;
- ev->cmdline = eina_stringshare_add(player);
- *emotion_video = ev;
+ ev->engine = (Emotion_Engine_Generic *)api;
+
+ if (!_fork_and_exec(ev))
+ {
+ free(ev);
+ return NULL;
+ }
- return _fork_and_exec(ev);
+ return ev;
}
static void
ev->player_restart = NULL;
}
-static int
-em_shutdown(void *data)
+static void
+em_del(void *data)
{
Emotion_Generic_Video *ev = data;
- if (!ev) return 0;
-
- eina_stringshare_del(ev->cmdline);
eina_stringshare_del(ev->shmname);
em_partial_shutdown(ev);
-
- return 1;
}
static unsigned char
-em_file_open(const char *file, Evas_Object *obj EINA_UNUSED, void *data)
+em_file_open(void *data, const char *file)
{
Emotion_Generic_Video *ev = data;
INF("file set: %s", file);
return NULL;
}
-static const Emotion_Video_Module em_module =
+static const Emotion_Engine em_template_engine =
{
+ EMOTION_ENGINE_API_VERSION,
+ EMOTION_ENGINE_PRIORITY_DEFAULT,
+ "generic",
+ em_add, /* add */
+ em_del, /* del */
em_file_open, /* file_open */
em_file_close, /* file_close */
em_play, /* play */
NULL /* priority_get */
};
-static Eina_Bool
-module_open(Evas_Object *obj, const Emotion_Video_Module **module, void **video, Emotion_Module_Options *opt)
+static void
+_player_entry_add(const Eina_File_Direct_Info *info)
{
- if (!module) {
- return EINA_FALSE;
- }
+ Emotion_Engine_Generic *eg;
+ const char *name;
+ char *endptr;
+ int priority;
- if (_emotion_generic_log_domain < 0)
+ name = info->path + info->name_start;
+
+ priority = strtol(name, &endptr, 10);
+ if (endptr == name)
+ priority = EMOTION_ENGINE_PRIORITY_DEFAULT;
+ else
{
- eina_threads_init();
- eina_log_threads_enable();
- _emotion_generic_log_domain = eina_log_domain_register
- ("emotion-generic", EINA_COLOR_LIGHTCYAN);
- if (_emotion_generic_log_domain < 0)
- {
- EINA_LOG_CRIT("Could not register log domain 'emotion-generic'");
- return EINA_FALSE;
- }
+ if ((*endptr == '-') || (*endptr == '_'))
+ endptr++;
+ name = endptr;
}
+ if (*name == '\0')
+ {
+ ERR("Invalid generic player: %s", info->path);
+ return;
+ }
- if (!em_init(obj, video, opt)) {
- return EINA_FALSE;
- }
+ eg = malloc(sizeof(Emotion_Engine_Generic));
+ EINA_SAFETY_ON_NULL_RETURN(eg);
- *module = &em_module;
+ /* inherit template */
+ memcpy(&(eg->engine), &em_template_engine, sizeof(em_template_engine));
- return EINA_TRUE;
+ eg->path = strdup(info->path);
+ EINA_SAFETY_ON_NULL_GOTO(eg->path, error_path);
+
+ eg->engine.name = strdup(name);
+ EINA_SAFETY_ON_NULL_GOTO(eg->engine.name, error_name);
+
+ eg->engine.priority = priority;
+
+ DBG("Add player name=%s, priority=%d, path=%s",
+ eg->engine.name, eg->engine.priority, eg->path);
+ _generic_players = eina_list_append(_generic_players, eg);
+
+ return;
+
+ error_name:
+ free(eg->path);
+ error_path:
+ free(eg);
}
-static void module_close(Emotion_Video_Module *module EINA_UNUSED, void *video)
+static void
+_player_entry_free(Emotion_Engine_Generic *eg)
{
- em_shutdown(video);
+ free(eg->path);
+ free((void *)eg->engine.name);
+ free(eg);
}
+static void _players_all_from(const char *path)
+{
+ const Eina_File_Direct_Info *info;
+ int count = 0;
+ Eina_Iterator *itr = eina_file_direct_ls(path);
+ if (!itr) goto end;;
+ EINA_ITERATOR_FOREACH(itr, info)
+ {
+ if (access(info->path, R_OK | X_OK) == 0)
+ {
+ _player_entry_add(info);
+ count++;
+ }
+ }
+ eina_iterator_free(itr);
+
+ end:
+ if (count == 0)
+ DBG("No generic players at %s", path);
+}
+
+static void
+_players_load(void)
+{
+ char buf[PATH_MAX];
+ const char *homedir = getenv("HOME");
+
+ if (homedir)
+ {
+ eina_str_join(buf, sizeof(buf), '/',
+ homedir,
+ ".emotion/generic_players/" MODULE_ARCH);
+ _players_all_from(buf);
+ }
+
+ eina_str_join(buf, sizeof(buf), '/',
+ eina_prefix_lib_get(pfx),
+ "emotion/generic_players/" MODULE_ARCH);
+ _players_all_from(buf);
+
+ if (!_generic_players)
+ ERR("no generic players available");
+ else
+ {
+ const Eina_List *n;
+ const Emotion_Engine_Generic *eg;
+ INF("Found %d generic players", eina_list_count(_generic_players));
+ EINA_LIST_FOREACH(_generic_players, n, eg)
+ _emotion_module_register(&(eg->engine));
+ }
+}
Eina_Bool
generic_module_init(void)
{
- if (pfx) return EINA_TRUE;
+ if (_emotion_init_count > 0)
+ {
+ _emotion_init_count++;
+ return EINA_TRUE;
+ }
+
+ _emotion_generic_log_domain = eina_log_domain_register
+ ("emotion-generic", EINA_COLOR_LIGHTCYAN);
+ if (_emotion_generic_log_domain < 0)
+ {
+ EINA_LOG_CRIT("Could not register log domain 'emotion-generic'");
+ return EINA_FALSE;
+ }
pfx = eina_prefix_new(NULL, emotion_init,
"EMOTION", "emotion", "checkme",
PACKAGE_BIN_DIR, PACKAGE_LIB_DIR,
PACKAGE_DATA_DIR, PACKAGE_DATA_DIR);
- if (!pfx) return EINA_FALSE;
- return _emotion_module_register("generic", module_open, module_close);
+ if (!pfx)
+ {
+ CRITICAL("Could not get prefix for emotion");
+ eina_log_domain_unregister(_emotion_generic_log_domain);
+ _emotion_generic_log_domain = -1;
+ return EINA_FALSE;
+ }
+
+ _players_load();
+
+ _emotion_init_count = 1;
+ return EINA_TRUE;
}
void
generic_module_shutdown(void)
{
- if (!pfx) return;
+ Emotion_Engine_Generic *eg;
+
+ if (_emotion_init_count > 1)
+ {
+ _emotion_init_count--;
+ return;
+ }
+ else if (_emotion_init_count == 0)
+ {
+ EINA_LOG_ERR("too many generic_module_shutdown()");
+ return;
+ }
+ _emotion_init_count = 0;
+
+ EINA_LIST_FREE(_generic_players, eg)
+ {
+ _emotion_module_unregister(&(eg->engine));
+ _player_entry_free(eg);
+ }
+
+ eina_log_domain_unregister(_emotion_generic_log_domain);
+ _emotion_generic_log_domain = -1;
eina_prefix_free(pfx);
pfx = NULL;
-
- _emotion_module_unregister("generic");
}
#ifndef EMOTION_STATIC_BUILD_GENERIC
} param;
};
+typedef struct _Emotion_Engine_Generic
+{
+ Emotion_Engine engine;
+ char *path;
+} Emotion_Engine_Generic;
+
/* emotion/generic main structure */
struct _Emotion_Generic_Video
{
- const char *cmdline;
+ const Emotion_Engine_Generic *engine;
const char *shmname;
Emotion_Generic_Player player;
if (send->ev->in == send->ev->out
&& send->ev->threads == NULL
&& send->ev->delete_me)
- em_shutdown(send->ev);
+ send->ev->api->del(send->ev);
gst_buffer_unref(send->frame);
free(send);
if (send->ev->in == send->ev->out
&& send->ev->threads == NULL
&& send->ev->delete_me)
- em_shutdown(send->ev);
+ send->ev->api->del(send->ev);
gst_message_unref(send->msg);
free(send);
Eina_Bool _ecore_x_available = EINA_FALSE;
static Ecore_Idler *restart_idler;
+static int _emotion_init_count = 0;
/* Callbacks to get the eos */
static void _for_each_tag (GstTagList const* list, gchar const* tag, void *data);
static void _free_metadata (Emotion_Gstreamer_Metadata *m);
-/* Interface */
-
-static unsigned char em_init (Evas_Object *obj,
- void **emotion_video,
- Emotion_Module_Options *opt);
-
-static unsigned char em_file_open (const char *file,
- Evas_Object *obj,
- void *video);
-
-static void em_file_close (void *video);
-
-static void em_play (void *video,
- double pos);
-
-static void em_stop (void *video);
-
-static void em_size_get (void *video,
- int *width,
- int *height);
-
-static void em_pos_set (void *video,
- double pos);
-
-
-static double em_len_get (void *video);
-
-static double em_buffer_size_get (void *video);
-
-static int em_fps_num_get (void *video);
-
-static int em_fps_den_get (void *video);
-
-static double em_fps_get (void *video);
-
-static double em_pos_get (void *video);
-
-static void em_vis_set (void *video,
- Emotion_Vis vis);
-
-static Emotion_Vis em_vis_get (void *video);
-
-static Eina_Bool em_vis_supported (void *video,
- Emotion_Vis vis);
-
-static double em_ratio_get (void *video);
-
-static int em_video_handled (void *video);
-
-static int em_audio_handled (void *video);
-
-static int em_seekable (void *video);
-
-static void em_frame_done (void *video);
-
-static Emotion_Format em_format_get (void *video);
-
-static void em_video_data_size_get (void *video,
- int *w,
- int *h);
-
-static int em_yuv_rows_get (void *video,
- int w,
- int h,
- unsigned char **yrows,
- unsigned char **urows,
- unsigned char **vrows);
-
-static int em_bgra_data_get (void *video,
- unsigned char **bgra_data);
-
-static void em_event_feed (void *video,
- int event);
-
-static void em_event_mouse_button_feed (void *video,
- int button,
- int x,
- int y);
-
-static void em_event_mouse_move_feed (void *video,
- int x,
- int y);
-
-static int em_video_channel_count (void *video);
-
-static void em_video_channel_set (void *video,
- int channel);
-
-static int em_video_channel_get (void *video);
-
-static void em_video_subtitle_file_set (void *video,
- const char *filepath);
-
-static const char *em_video_subtitle_file_get (void *video);
-
-static const char *em_video_channel_name_get (void *video,
- int channel);
-
-static void em_video_channel_mute_set (void *video,
- int mute);
-
-static int em_video_channel_mute_get (void *video);
-
-static int em_audio_channel_count (void *video);
-
-static void em_audio_channel_set (void *video,
- int channel);
-
-static int em_audio_channel_get (void *video);
-
-static const char *em_audio_channel_name_get (void *video,
- int channel);
-
-static void em_audio_channel_mute_set (void *video,
- int mute);
-
-static int em_audio_channel_mute_get (void *video);
-
-static void em_audio_channel_volume_set (void *video,
- double vol);
-
-static double em_audio_channel_volume_get (void *video);
-
-static int em_spu_channel_count (void *video);
-
-static void em_spu_channel_set (void *video,
- int channel);
-
-static int em_spu_channel_get (void *video);
-
-static const char *em_spu_channel_name_get (void *video,
- int channel);
-
-static void em_spu_channel_mute_set (void *video,
- int mute);
-
-static int em_spu_channel_mute_get (void *video);
-
-static int em_chapter_count (void *video);
-
-static void em_chapter_set (void *video,
- int chapter);
-
-static int em_chapter_get (void *video);
-
-static const char *em_chapter_name_get (void *video,
- int chapter);
-
-static void em_speed_set (void *video,
- double speed);
-
-static double em_speed_get (void *video);
-
-static int em_eject (void *video);
-
-static const char *em_meta_get (void *video,
- int meta);
-
-static void em_priority_set (void *video,
- Eina_Bool pri);
-static Eina_Bool em_priority_get (void *video);
-
static GstBusSyncReply _eos_sync_fct(GstBus *bus,
GstMessage *message,
gpointer data);
/* Module interface */
-static const Emotion_Video_Module em_module =
-{
- em_file_open, /* file_open */
- em_file_close, /* file_close */
- em_play, /* play */
- em_stop, /* stop */
- em_size_get, /* size_get */
- em_pos_set, /* pos_set */
- em_len_get, /* len_get */
- em_buffer_size_get, /* buffer_size_get */
- em_fps_num_get, /* fps_num_get */
- em_fps_den_get, /* fps_den_get */
- em_fps_get, /* fps_get */
- em_pos_get, /* pos_get */
- em_vis_set, /* vis_set */
- em_vis_get, /* vis_get */
- em_vis_supported, /* vis_supported */
- em_ratio_get, /* ratio_get */
- em_video_handled, /* video_handled */
- em_audio_handled, /* audio_handled */
- em_seekable, /* seekable */
- em_frame_done, /* frame_done */
- em_format_get, /* format_get */
- em_video_data_size_get, /* video_data_size_get */
- em_yuv_rows_get, /* yuv_rows_get */
- em_bgra_data_get, /* bgra_data_get */
- em_event_feed, /* event_feed */
- em_event_mouse_button_feed, /* event_mouse_button_feed */
- em_event_mouse_move_feed, /* event_mouse_move_feed */
- em_video_channel_count, /* video_channel_count */
- em_video_channel_set, /* video_channel_set */
- em_video_channel_get, /* video_channel_get */
- em_video_subtitle_file_set, /* video_subtitle_file_set */
- em_video_subtitle_file_get, /* video_subtitle_file_get */
- em_video_channel_name_get, /* video_channel_name_get */
- em_video_channel_mute_set, /* video_channel_mute_set */
- em_video_channel_mute_get, /* video_channel_mute_get */
- em_audio_channel_count, /* audio_channel_count */
- em_audio_channel_set, /* audio_channel_set */
- em_audio_channel_get, /* audio_channel_get */
- em_audio_channel_name_get, /* audio_channel_name_get */
- em_audio_channel_mute_set, /* audio_channel_mute_set */
- em_audio_channel_mute_get, /* audio_channel_mute_get */
- em_audio_channel_volume_set, /* audio_channel_volume_set */
- em_audio_channel_volume_get, /* audio_channel_volume_get */
- em_spu_channel_count, /* spu_channel_count */
- em_spu_channel_set, /* spu_channel_set */
- em_spu_channel_get, /* spu_channel_get */
- em_spu_channel_name_get, /* spu_channel_name_get */
- em_spu_channel_mute_set, /* spu_channel_mute_set */
- em_spu_channel_mute_get, /* spu_channel_mute_get */
- em_chapter_count, /* chapter_count */
- em_chapter_set, /* chapter_set */
- em_chapter_get, /* chapter_get */
- em_chapter_name_get, /* chapter_name_get */
- em_speed_set, /* speed_set */
- em_speed_get, /* speed_get */
- em_eject, /* eject */
- em_meta_get, /* meta_get */
- em_priority_set, /* priority_set */
- em_priority_get /* priority_get */
-};
static int priority_overide = 0;
}
}
-static unsigned char
-em_init(Evas_Object *obj,
- void **emotion_video,
- Emotion_Module_Options *opt EINA_UNUSED)
-{
- Emotion_Gstreamer_Video *ev;
- GError *error;
-
- if (!emotion_video)
- return 0;
-
- ev = calloc(1, sizeof(Emotion_Gstreamer_Video));
- if (!ev) return 0;
-
- ev->obj = obj;
-
- /* Initialization of gstreamer */
- if (!gst_init_check(NULL, NULL, &error))
- goto failure;
-
- /* Default values */
- ev->ratio = 1.0;
- ev->vis = EMOTION_VIS_NONE;
- ev->volume = 0.8;
- ev->play_started = 0;
- ev->delete_me = EINA_FALSE;
- ev->threads = NULL;
-
- *emotion_video = ev;
-
- return 1;
-
-failure:
- free(ev);
-
- return 0;
-}
-
static void
em_cleanup(Emotion_Gstreamer_Video *ev)
{
free(vstream);
}
-int
-em_shutdown(void *video)
+static void
+em_del(void *video)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
- if (!ev)
- return 0;
+ Emotion_Gstreamer_Video *ev = video;
if (ev->threads)
{
ecore_thread_cancel(t);
ev->delete_me = EINA_TRUE;
- return EINA_FALSE;
+ return;
}
if (ev->in != ev->out)
{
ev->delete_me = EINA_TRUE;
- return EINA_FALSE;
+ return;
}
em_cleanup(ev);
free(ev);
-
- return 1;
}
-
-static unsigned char
-em_file_open(const char *file,
- Evas_Object *obj,
- void *video)
+static Eina_Bool
+em_file_open(void *video,
+ const char *file)
{
- Emotion_Gstreamer_Video *ev;
+ Emotion_Gstreamer_Video *ev = video;
Eina_Strbuf *sbuf = NULL;
const char *uri;
- ev = (Emotion_Gstreamer_Video *)video;
-
if (!file) return EINA_FALSE;
if (strstr(file, "://") == NULL)
{
uri = sbuf ? eina_strbuf_string_get(sbuf) : file;
DBG("setting file to '%s'", uri);
- ev->pipeline = gstreamer_video_sink_new(ev, obj, uri);
+ ev->pipeline = gstreamer_video_sink_new(ev, ev->obj, uri);
if (sbuf) eina_strbuf_free(sbuf);
if (!ev->pipeline)
gst_bus_set_sync_handler(ev->eos_bus, _eos_sync_fct, ev);
- /* Evas Object */
- ev->obj = obj;
-
ev->position = 0.0;
return 1;
return EINA_TRUE;
}
-#endif
-static Eina_Bool
-module_open(Evas_Object *obj,
- const Emotion_Video_Module **module,
- void **video,
- Emotion_Module_Options *opt)
+static void
+gstreamer_ecore_x_check(void)
{
-#ifdef HAVE_ECORE_X
Ecore_X_Window *roots;
int num;
-#endif
-
- if (!module)
- return EINA_FALSE;
- if (_emotion_gstreamer_log_domain < 0)
- {
- eina_threads_init();
- eina_log_threads_enable();
- _emotion_gstreamer_log_domain = eina_log_domain_register
- ("emotion-gstreamer", EINA_COLOR_LIGHTCYAN);
- if (_emotion_gstreamer_log_domain < 0)
- {
- EINA_LOG_CRIT("Could not register log domain 'emotion-gstreamer'");
- return EINA_FALSE;
- }
- }
-
- if (!em_init(obj, video, opt))
- return EINA_FALSE;
-
-#ifdef HAVE_ECORE_X
ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY, _ecore_event_x_destroy, NULL);
-#endif
-
- if (getenv("EMOTION_FPS_DEBUG")) debug_fps = EINA_TRUE;
-
- eina_threads_init();
-
-#ifdef HAVE_ECORE_X
- if (ecore_x_init(NULL) > 0)
- {
- _ecore_x_available = EINA_TRUE;
- }
/* Check if the window manager is able to handle our special Xv window. */
- roots = _ecore_x_available ? ecore_x_window_root_list(&num) : NULL;
+ roots = ecore_x_window_root_list(&num);
if (roots && num > 0)
{
Ecore_X_Window win, twin;
}
}
free(roots);
-#endif
-
- *module = &em_module;
- return EINA_TRUE;
}
+#endif
-static void
-module_close(Emotion_Video_Module *module EINA_UNUSED,
- void *video)
+static void *
+em_add(const Emotion_Engine *api,
+ Evas_Object *obj,
+ const Emotion_Module_Options *opt EINA_UNUSED)
{
- em_shutdown(video);
+ Emotion_Gstreamer_Video *ev;
-#ifdef HAVE_ECORE_X
- if (_ecore_x_available)
- {
- ecore_x_shutdown();
- }
-#endif
+ ev = calloc(1, sizeof(Emotion_Gstreamer_Video));
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ev, NULL);
+
+ ev->api = api;
+ ev->obj = obj;
- eina_threads_shutdown();
+ /* Default values */
+ ev->ratio = 1.0;
+ ev->vis = EMOTION_VIS_NONE;
+ ev->volume = 0.8;
+ ev->play_started = 0;
+ ev->delete_me = EINA_FALSE;
+ ev->threads = NULL;
+
+ return ev;
}
+static const Emotion_Engine em_engine =
+{
+ EMOTION_ENGINE_API_VERSION,
+ EMOTION_ENGINE_PRIORITY_DEFAULT,
+ "gstreamer",
+ em_add, /* add */
+ em_del, /* del */
+ em_file_open, /* file_open */
+ em_file_close, /* file_close */
+ em_play, /* play */
+ em_stop, /* stop */
+ em_size_get, /* size_get */
+ em_pos_set, /* pos_set */
+ em_len_get, /* len_get */
+ em_buffer_size_get, /* buffer_size_get */
+ em_fps_num_get, /* fps_num_get */
+ em_fps_den_get, /* fps_den_get */
+ em_fps_get, /* fps_get */
+ em_pos_get, /* pos_get */
+ em_vis_set, /* vis_set */
+ em_vis_get, /* vis_get */
+ em_vis_supported, /* vis_supported */
+ em_ratio_get, /* ratio_get */
+ em_video_handled, /* video_handled */
+ em_audio_handled, /* audio_handled */
+ em_seekable, /* seekable */
+ em_frame_done, /* frame_done */
+ em_format_get, /* format_get */
+ em_video_data_size_get, /* video_data_size_get */
+ em_yuv_rows_get, /* yuv_rows_get */
+ em_bgra_data_get, /* bgra_data_get */
+ em_event_feed, /* event_feed */
+ em_event_mouse_button_feed, /* event_mouse_button_feed */
+ em_event_mouse_move_feed, /* event_mouse_move_feed */
+ em_video_channel_count, /* video_channel_count */
+ em_video_channel_set, /* video_channel_set */
+ em_video_channel_get, /* video_channel_get */
+ em_video_subtitle_file_set, /* video_subtitle_file_set */
+ em_video_subtitle_file_get, /* video_subtitle_file_get */
+ em_video_channel_name_get, /* video_channel_name_get */
+ em_video_channel_mute_set, /* video_channel_mute_set */
+ em_video_channel_mute_get, /* video_channel_mute_get */
+ em_audio_channel_count, /* audio_channel_count */
+ em_audio_channel_set, /* audio_channel_set */
+ em_audio_channel_get, /* audio_channel_get */
+ em_audio_channel_name_get, /* audio_channel_name_get */
+ em_audio_channel_mute_set, /* audio_channel_mute_set */
+ em_audio_channel_mute_get, /* audio_channel_mute_get */
+ em_audio_channel_volume_set, /* audio_channel_volume_set */
+ em_audio_channel_volume_get, /* audio_channel_volume_get */
+ em_spu_channel_count, /* spu_channel_count */
+ em_spu_channel_set, /* spu_channel_set */
+ em_spu_channel_get, /* spu_channel_get */
+ em_spu_channel_name_get, /* spu_channel_name_get */
+ em_spu_channel_mute_set, /* spu_channel_mute_set */
+ em_spu_channel_mute_get, /* spu_channel_mute_get */
+ em_chapter_count, /* chapter_count */
+ em_chapter_set, /* chapter_set */
+ em_chapter_get, /* chapter_get */
+ em_chapter_name_get, /* chapter_name_get */
+ em_speed_set, /* speed_set */
+ em_speed_get, /* speed_get */
+ em_eject, /* eject */
+ em_meta_get, /* meta_get */
+ em_priority_set, /* priority_set */
+ em_priority_get /* priority_get */
+};
+
Eina_Bool
gstreamer_module_init(void)
{
GError *error;
+ if (_emotion_init_count > 0)
+ {
+ _emotion_init_count++;
+ return EINA_TRUE;
+ }
+
+ if (getenv("EMOTION_FPS_DEBUG")) debug_fps = EINA_TRUE;
+
+ eina_threads_init();
+ eina_log_threads_enable();
+ _emotion_gstreamer_log_domain = eina_log_domain_register
+ ("emotion-gstreamer", EINA_COLOR_LIGHTCYAN);
+ if (_emotion_gstreamer_log_domain < 0)
+ {
+ EINA_LOG_CRIT("Could not register log domain 'emotion-gstreamer'");
+ return EINA_FALSE;
+ }
+
if (!gst_init_check(0, NULL, &error))
{
EINA_LOG_CRIT("Could not init GStreamer");
- return EINA_FALSE;
+ goto error_gst_init;
+ }
+
+#ifdef HAVE_ECORE_X
+ if (ecore_x_init(NULL) > 0)
+ {
+ _ecore_x_available = EINA_TRUE;
+ gstreamer_ecore_x_check();
}
+#endif
if (gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
"emotion-sink",
"http://www.enlightenment.org/") == FALSE)
{
EINA_LOG_CRIT("Could not load static gstreamer video sink for Emotion.");
- return EINA_FALSE;
+ goto error_gst_plugin;
+ }
+
+ if (!_emotion_module_register(&em_engine))
+ {
+ ERR("Could not register module %p", &em_engine);
+ goto error_register;
+ }
+
+ _emotion_init_count = 1;
+ return EINA_TRUE;
+
+ error_register:
+ error_gst_plugin:
+#ifdef HAVE_ECORE_X
+ if (_ecore_x_available)
+ {
+ ecore_x_shutdown();
+ _ecore_x_available = EINA_FALSE;
+ window_manager_video = EINA_FALSE;
}
+#endif
+
+ gst_deinit();
+
+ error_gst_init:
+ eina_log_domain_unregister(_emotion_gstreamer_log_domain);
+ _emotion_gstreamer_log_domain = -1;
- return _emotion_module_register("gstreamer", module_open, module_close);
+ return EINA_FALSE;
}
void
gstreamer_module_shutdown(void)
{
- _emotion_module_unregister("gstreamer");
+ if (_emotion_init_count > 1)
+ {
+ _emotion_init_count--;
+ return;
+ }
+ else if (_emotion_init_count == 0)
+ {
+ EINA_LOG_ERR("too many gstreamer_module_shutdown()");
+ return;
+ }
+ _emotion_init_count = 0;
+
+ _emotion_module_unregister(&em_engine);
+
+#ifdef HAVE_ECORE_X
+ if (_ecore_x_available)
+ {
+ ecore_x_shutdown();
+ _ecore_x_available = EINA_FALSE;
+ window_manager_video = EINA_FALSE;
+ }
+#endif
+
+ eina_log_domain_unregister(_emotion_gstreamer_log_domain);
+ _emotion_gstreamer_log_domain = -1;
gst_deinit();
}
#ifndef __EMOTION_GSTREAMER_H__
#define __EMOTION_GSTREAMER_H__
+#include "Emotion_Module.h"
+
typedef void (*Evas_Video_Convert_Cb)(unsigned char *evas_data,
const unsigned char *gst_data,
unsigned int w,
struct _Emotion_Gstreamer_Video
{
+ const Emotion_Engine *api;
+
/* Gstreamer elements */
GstElement *pipeline;
GstElement *sink;
Eina_Bool _emotion_gstreamer_video_pipeline_parse(Emotion_Gstreamer_Video *ev,
Eina_Bool force);
-int em_shutdown(void *video);
-
typedef struct _ColorSpace_FourCC_Convertion ColorSpace_FourCC_Convertion;
typedef struct _ColorSpace_Format_Convertion ColorSpace_Format_Convertion;
if (getenv("EMOTION_GSTREAMER_DOT")) GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(ev->pipeline), GST_DEBUG_GRAPH_SHOW_ALL, getenv("EMOTION_GSTREAMER_DOT"));
if (ev->in == ev->out && ev->delete_me)
- em_shutdown(ev);
+ ev->api->del(ev);
}
static void
if (getenv("EMOTION_GSTREAMER_DOT")) GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(ev->pipeline), GST_DEBUG_GRAPH_SHOW_ALL, getenv("EMOTION_GSTREAMER_DOT"));
if (ev->in == ev->out && ev->delete_me)
- em_shutdown(ev);
+ ev->api->del(ev);
else
_emotion_gstreamer_video_pipeline_parse(data, EINA_TRUE);
}
#include "emotion_xine.h"
int _emotion_xine_log_domain = -1;
-
-/* module api */
-static unsigned char em_init (Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt);
-static int em_shutdown (void *ef);
-static unsigned char em_file_open (const char *file, Evas_Object *obj, void *ef);
-static void em_file_close (void *ef);
-static void em_play (void *ef, double pos);
-static void em_stop (void *ef);
-static void em_size_get (void *ef, int *w, int *h);
-static void em_pos_set (void *ef, double pos);
-static double em_buffer_size_get (void *ef);
-static double em_len_get (void *ef);
-static int em_fps_num_get (void *ef);
-static int em_fps_den_get (void *ef);
-static double em_fps_get (void *ef);
-static double em_pos_get (void *ef);
-static void em_vis_set (void *ef, Emotion_Vis vis);
-static Emotion_Vis em_vis_get (void *ef);
-static Eina_Bool em_vis_supported (void *ef, Emotion_Vis vis);
-static double em_ratio_get (void *ef);
-static int em_seekable (void *ef);
-static void em_frame_done (void *ef);
-static Emotion_Format em_format_get (void *ef);
-static void em_video_data_size_get (void *ef, int *w, int *h);
-static int em_yuv_rows_get (void *ef, int w, int h, unsigned char **yrows, unsigned char **urows, unsigned char **vrows);
-static int em_bgra_data_get (void *ef, unsigned char **bgra_data);
-static void em_event_feed (void *ef, int event);
-static void em_event_mouse_button_feed (void *ef, int button, int x, int y);
-static void em_event_mouse_move_feed (void *ef, int x, int y);
-static int em_video_channel_count (void *ef);
-static void em_video_channel_set (void *ef, int channel);
-static int em_video_channel_get (void *ef);
-static const char *em_video_channel_name_get (void *ef, int channel);
-static void em_video_channel_mute_set (void *ef, int mute);
-static int em_video_channel_mute_get (void *ef);
-static int em_audio_channel_count (void *ef);
-static void em_audio_channel_set (void *ef, int channel);
-static int em_audio_channel_get (void *ef);
-static const char *em_audio_channel_name_get (void *ef, int channel);
-static void em_audio_channel_mute_set (void *ef, int mute);
-static int em_audio_channel_mute_get (void *ef);
-static void em_audio_channel_volume_set(void *ef, double vol);
-static double em_audio_channel_volume_get(void *ef);
-static int em_spu_channel_count (void *ef);
-static void em_spu_channel_set (void *ef, int channel);
-static int em_spu_channel_get (void *ef);
-static const char *em_spu_channel_name_get (void *ef, int channel);
-static void em_spu_channel_mute_set (void *ef, int mute);
-static int em_spu_channel_mute_get (void *ef);
-static int em_chapter_count (void *ef);
-static void em_chapter_set (void *ef, int chapter);
-static int em_chapter_get (void *ef);
-static const char *em_chapter_name_get (void *ef, int chapter);
-static void em_speed_set (void *ef, double speed);
-static double em_speed_get (void *ef);
-static int em_eject (void *ef);
-static const char *em_meta_get (void *ef, int meta);
+static int _emotion_init_count = 0;
/* internal util calls */
static void *_em_slave (void *par);
extern plugin_info_t emotion_xine_plugin_info[];
+static void em_frame_done(void *ef);
+
/* this is a slave controller thread for the xine module - libxine loves
* to deadlock, internally stall and otherwise have unpredictable behavior
* if we use the main process thread for many things - so a lot will be
if (write(ev->fd_slave_write, buf, sizeof(buf)) < 0) perror("write");
}
-static unsigned char
-em_init(Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt)
+static void *
+em_add(const Emotion_Engine *api EINA_UNUSED,
+ Evas_Object *obj,
+ const Emotion_Module_Options *opt)
{
Emotion_Xine_Video *ev;
int fds[2];
-
- if (!emotion_video) return 0;
-
+
ev = calloc(1, sizeof(Emotion_Xine_Video));
- if (!ev) return 0;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ev, NULL);
ev->obj = obj;
-
+
if (pipe(fds) == 0)
{
ev->fd_read = fds[0];
_em_slave_event(ev, 1, NULL);
ev->buffer = 1.0;
-
- *emotion_video = ev;
- return 1;
+
+ return ev;
}
-static int
-em_shutdown(void *ef)
+static void
+em_del(void *ef)
{
- Emotion_Xine_Video *ev;
-
- ev = (Emotion_Xine_Video *)ef;
+ Emotion_Xine_Video *ev = ef;
+
ev->closing = 1;
ev->delete_me = 1;
DBG("del fds %p", ev);
ecore_animator_del(ev->anim);
ev->anim = NULL;
}
-
+
ev->closing = 1;
_em_slave_event(ev, 3, NULL);
DBG("done %p", ev);
- return 1;
}
-static unsigned char
-em_file_open(const char *file, Evas_Object *obj EINA_UNUSED, void *ef)
+static Eina_Bool
+em_file_open(void *ef, const char *file)
{
- Emotion_Xine_Video *ev;
-
- ev = (Emotion_Xine_Video *)ef;
- if (!ev) return 0;
+ Emotion_Xine_Video *ev = ef;
_em_slave_event(ev, 2, strdup(file));
- return 1;
+ return EINA_TRUE;
}
static void
pthread_mutex_unlock(&(ev->get_pos_len_mutex));
}
-static const Emotion_Video_Module em_module =
+static const Emotion_Engine em_engine =
{
+ EMOTION_ENGINE_API_VERSION,
+ EMOTION_ENGINE_PRIORITY_DEFAULT,
+ "xine",
+ em_add, /* add */
+ em_del, /* del */
em_file_open, /* file_open */
em_file_close, /* file_close */
em_play, /* play */
NULL /* priority_get */
};
-static Eina_Bool
-module_open(Evas_Object *obj, const Emotion_Video_Module **module, void **video, Emotion_Module_Options *opt)
+Eina_Bool
+xine_module_init(void)
{
- if (!module)
- return EINA_FALSE;
+ if (_emotion_init_count > 0)
+ {
+ _emotion_init_count++;
+ return EINA_TRUE;
+ }
+ eina_threads_init();
+ eina_log_threads_enable();
+ _emotion_xine_log_domain = eina_log_domain_register
+ ("emotion-xine", EINA_COLOR_LIGHTCYAN);
if (_emotion_xine_log_domain < 0)
{
- eina_threads_init();
- eina_log_threads_enable();
- _emotion_xine_log_domain = eina_log_domain_register
- ("emotion-xine", EINA_COLOR_LIGHTCYAN);
- if (_emotion_xine_log_domain < 0)
- {
- EINA_LOG_CRIT("Could not register log domain 'emotion-xine'");
- return EINA_FALSE;
- }
+ EINA_LOG_CRIT("Could not register log domain 'emotion-xine'");
+ return EINA_FALSE;
}
- if (!em_init(obj, video, opt))
- return EINA_FALSE;
+ if (!_emotion_module_register(&em_engine))
+ {
+ CRITICAL("Could not register module %p", &em_engine);
+ eina_log_domain_unregister(_emotion_xine_log_domain);
+ _emotion_xine_log_domain = -1;
+ return EINA_FALSE;
+ }
- *module = &em_module;
+ _emotion_init_count = 1;
return EINA_TRUE;
}
-static void
-module_close(Emotion_Video_Module *module EINA_UNUSED, void *video)
-{
- em_shutdown(video);
-}
-
-Eina_Bool
-xine_module_init(void)
-{
- return _emotion_module_register("xine", module_open, module_close);
-}
-
void
xine_module_shutdown(void)
{
- _emotion_module_unregister("xine");
+ if (_emotion_init_count > 1)
+ {
+ _emotion_init_count--;
+ return;
+ }
+ else if (_emotion_init_count == 0)
+ {
+ EINA_LOG_ERR("too many xine_module_shutdown()");
+ return;
+ }
+ _emotion_init_count = 0;
+
+ _emotion_module_unregister(&em_engine);
+
+ eina_log_domain_unregister(_emotion_xine_log_domain);
+ _emotion_xine_log_domain = -1;
}
#ifndef EMOTION_STATIC_BUILD_XINE