efl/emotion: rework module infra, better integration with 'generic'.

Change the module infra and allow one to register using the
description structure itself, saves some work.

Replace module_open and module_close with add() and del(), that are
more descriptive.

Move stuff to init/shutdown where it was a better fit.

Since add() now receives the first parameter being the owning
structure we can create one structure per generic player and they will
merge transparently with other modules, then we can use a simple
algorithm that considers the plugin priority. ALL DYNAMIC!

Future work could be done to load the plugin priority specified by
user from configuration file. But this is not in my plans right now.



SVN revision: 82602
This commit is contained in:
Gustavo Sverzut Barbieri 2013-01-11 03:06:42 +00:00
parent 4c64334b9d
commit 356d4f733c
11 changed files with 625 additions and 674 deletions

View File

@ -13,13 +13,10 @@
#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,
@ -31,20 +28,23 @@ enum _Emotion_Format
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);
@ -129,7 +129,7 @@ EAPI void _emotion_pending_object_unref(void);
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

View File

@ -17,9 +17,37 @@ Eina_Bool generic_module_init(void);
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)
{
@ -80,9 +108,6 @@ emotion_modules_init(void)
{
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 */
@ -101,12 +126,20 @@ emotion_modules_init(void)
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
@ -123,39 +156,74 @@ emotion_modules_shutdown(void)
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;
plugin = malloc(sizeof (Eina_Emotion_Plugins));
EINA_SAFETY_ON_NULL_RETURN_VAL(plugin, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(api, EINA_FALSE);
plugin->open = mod_open;
plugin->close = mod_close;
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("register module=%s, open=%p, close=%p", name, mod_open, mod_close);
return eina_hash_add(_emotion_backends, name, plugin);
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);
re->engine = api;
re->priority = api->priority; // TODO: use user-priority from file as weel.
_emotion_engine_registry = eina_list_sorted_insert
(_emotion_engine_registry, _emotion_engine_registry_entry_cmp, re);
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;
};
@ -192,66 +260,81 @@ struct _Emotion_Engine_Instance
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;
const Eina_List *n;
const Emotion_Engine_Registry_Entry *re;
const Emotion_Engine *engine;
void *data;
if (!_emotion_backends)
{
ERR("No backend loaded");
return NULL;
}
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);
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);
}
}
if (i != 0 && i < (sizeof (_backend_priority) / sizeof (char*)))
goto retry;
ERR("Unable to load module: %s", name);
ERR("No engine worked");
return NULL;
}
@ -259,7 +342,7 @@ void
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
@ -268,7 +351,7 @@ emotion_engine_instance_name_equal(const Emotion_Engine_Instance *inst, const ch
/* 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 *
@ -278,11 +361,11 @@ emotion_engine_instance_data_get(const Emotion_Engine_Instance *inst)
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

View File

@ -30,7 +30,7 @@ void emotion_engine_instance_del(Emotion_Engine_Instance *in
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);

View File

@ -280,9 +280,30 @@ emotion_object_module_option_set(Evas_Object *obj, const char *opt, const char *
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

View File

@ -18,6 +18,8 @@
#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
@ -46,18 +48,6 @@ static int _emotion_generic_log_domain = -1;
#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);
@ -71,65 +61,6 @@ _player_restart(void *data)
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)
{
@ -966,7 +897,7 @@ _player_exec(Emotion_Generic_Video *ev)
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,
@ -1027,18 +958,13 @@ _fork_and_exec(Emotion_Generic_Video *ev)
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;
@ -1048,10 +974,15 @@ em_init(Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt)
ev->cmd.type = -1;
ev->obj = obj;
ev->cmdline = eina_stringshare_add(player);
*emotion_video = ev;
ev->engine = (Emotion_Engine_Generic *)api;
return _fork_and_exec(ev);
if (!_fork_and_exec(ev))
{
free(ev);
return NULL;
}
return ev;
}
static void
@ -1092,23 +1023,18 @@ em_partial_shutdown(Emotion_Generic_Video *ev)
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);
@ -1700,8 +1626,13 @@ em_meta_get(void *data, int meta)
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 */
@ -1763,64 +1694,181 @@ static const Emotion_Video_Module em_module =
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

View File

@ -58,10 +58,16 @@ struct _Emotion_Generic_Cmd_Buffer
} 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;

View File

@ -51,7 +51,7 @@ emotion_gstreamer_buffer_free(Emotion_Gstreamer_Buffer *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_buffer_unref(send->frame);
free(send);
@ -83,7 +83,7 @@ emotion_gstreamer_message_free(Emotion_Gstreamer_Message *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);

View File

@ -33,173 +33,12 @@ Eina_Bool debug_fps = EINA_FALSE;
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);
@ -208,68 +47,6 @@ static Eina_Bool _em_restart_stream(void *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;
@ -340,44 +117,6 @@ emotion_visualization_element_name_get(Emotion_Vis visualisation)
}
}
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)
{
@ -455,14 +194,10 @@ 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)
{
@ -472,34 +207,28 @@ em_shutdown(void *video)
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)
{
@ -529,7 +258,7 @@ em_file_open(const char *file,
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)
@ -544,9 +273,6 @@ em_file_open(const char *file,
gst_bus_set_sync_handler(ev->eos_bus, _eos_sync_fct, ev);
/* Evas Object */
ev->obj = obj;
ev->position = 0.0;
return 1;
@ -1334,54 +1060,17 @@ _ecore_event_x_destroy(void *data EINA_UNUSED, int type EINA_UNUSED, void *event
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;
@ -1425,39 +1114,138 @@ module_open(Evas_Object *obj,
}
}
free(roots);
}
#endif
*module = &em_module;
return EINA_TRUE;
}
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);
eina_threads_shutdown();
ev->api = api;
ev->obj = obj;
/* 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",
"video sink plugin for Emotion",
@ -1469,16 +1257,66 @@ gstreamer_module_init(void)
"http://www.enlightenment.org/") == FALSE)
{
EINA_LOG_CRIT("Could not load static gstreamer video sink for Emotion.");
return EINA_FALSE;
goto error_gst_plugin;
}
return _emotion_module_register("gstreamer", module_open, module_close);
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 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();
}

View File

@ -1,6 +1,8 @@
#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,
@ -49,6 +51,8 @@ struct _Emotion_Gstreamer_Metadata
struct _Emotion_Gstreamer_Video
{
const Emotion_Engine *api;
/* Gstreamer elements */
GstElement *pipeline;
GstElement *sink;
@ -260,8 +264,6 @@ void emotion_gstreamer_message_free(Emotion_Gstreamer_Message *send);
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;

View File

@ -848,7 +848,7 @@ _emotion_gstreamer_cancel(void *data, Ecore_Thread *thread)
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
@ -867,7 +867,7 @@ _emotion_gstreamer_end(void *data, Ecore_Thread *thread)
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);
}

View File

@ -10,63 +10,7 @@
#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);
@ -81,6 +25,8 @@ static void _em_get_pos_len (Emotion_Xine_Video *ev);
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
@ -369,18 +315,18 @@ _em_slave_event(void *data, int type, void *arg)
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];
@ -427,17 +373,15 @@ em_init(Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt)
_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);
@ -450,22 +394,18 @@ em_shutdown(void *ef)
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
@ -1533,8 +1473,13 @@ _em_get_pos_len(Emotion_Xine_Video *ev)
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 */
@ -1596,48 +1541,56 @@ static const Emotion_Video_Module em_module =
NULL /* priority_get */
};
static Eina_Bool
module_open(Evas_Object *obj, const Emotion_Video_Module **module, void **video, Emotion_Module_Options *opt)
{
if (!module)
return EINA_FALSE;
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;
}
}
if (!em_init(obj, video, opt))
return EINA_FALSE;
*module = &em_module;
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);
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_LOG_CRIT("Could not register log domain 'emotion-xine'");
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;
}
_emotion_init_count = 1;
return EINA_TRUE;
}
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