forked from enlightenment/efl
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:
parent
4c64334b9d
commit
356d4f733c
|
@ -13,13 +13,10 @@
|
||||||
#define META_TRACK_COUNT 8
|
#define META_TRACK_COUNT 8
|
||||||
|
|
||||||
typedef enum _Emotion_Format Emotion_Format;
|
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 _Emotion_Module_Options Emotion_Module_Options;
|
||||||
typedef struct _Eina_Emotion_Plugins Eina_Emotion_Plugins;
|
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
|
enum _Emotion_Format
|
||||||
{
|
{
|
||||||
EMOTION_FORMAT_NONE,
|
EMOTION_FORMAT_NONE,
|
||||||
|
@ -31,20 +28,23 @@ enum _Emotion_Format
|
||||||
|
|
||||||
struct _Emotion_Module_Options
|
struct _Emotion_Module_Options
|
||||||
{
|
{
|
||||||
const char *player;
|
|
||||||
Eina_Bool no_video : 1;
|
Eina_Bool no_video : 1;
|
||||||
Eina_Bool no_audio : 1;
|
Eina_Bool no_audio : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Eina_Emotion_Plugins
|
struct _Emotion_Engine
|
||||||
{
|
{
|
||||||
Emotion_Module_Open open;
|
#define EMOTION_ENGINE_API_VERSION (1U)
|
||||||
Emotion_Module_Close close;
|
unsigned version;
|
||||||
};
|
|
||||||
|
|
||||||
struct _Emotion_Video_Module
|
#define EMOTION_ENGINE_PRIORITY_DEFAULT (50)
|
||||||
{
|
int priority; /* default priority, may be overwritten by user. Try to keep from 0-100. */
|
||||||
unsigned char (*file_open) (const char *file, Evas_Object *obj, void *video);
|
|
||||||
|
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 (*file_close) (void *ef);
|
||||||
void (*play) (void *ef, double pos);
|
void (*play) (void *ef, double pos);
|
||||||
void (*stop) (void *ef);
|
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 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_register(const Emotion_Engine *api);
|
||||||
EAPI Eina_Bool _emotion_module_unregister(const char *name);
|
EAPI Eina_Bool _emotion_module_unregister(const Emotion_Engine *api);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,9 +17,37 @@ Eina_Bool generic_module_init(void);
|
||||||
void generic_module_shutdown(void);
|
void generic_module_shutdown(void);
|
||||||
#endif
|
#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 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
|
static void
|
||||||
_emotion_modules_load(void)
|
_emotion_modules_load(void)
|
||||||
{
|
{
|
||||||
|
@ -80,9 +108,6 @@ emotion_modules_init(void)
|
||||||
{
|
{
|
||||||
int static_modules = 0;
|
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();
|
_emotion_modules_load();
|
||||||
|
|
||||||
/* Init static module */
|
/* Init static module */
|
||||||
|
@ -101,12 +126,20 @@ emotion_modules_init(void)
|
||||||
else if (_emotion_modules)
|
else if (_emotion_modules)
|
||||||
eina_module_list_load(_emotion_modules);
|
eina_module_list_load(_emotion_modules);
|
||||||
|
|
||||||
|
if (!_emotion_engine_registry)
|
||||||
|
ERR("Couldn't find any emotion engine.");
|
||||||
|
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
emotion_modules_shutdown(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
|
#ifdef EMOTION_STATIC_BUILD_XINE
|
||||||
xine_module_shutdown();
|
xine_module_shutdown();
|
||||||
#endif
|
#endif
|
||||||
|
@ -123,39 +156,74 @@ emotion_modules_shutdown(void)
|
||||||
eina_array_free(_emotion_modules);
|
eina_array_free(_emotion_modules);
|
||||||
_emotion_modules = NULL;
|
_emotion_modules = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
eina_hash_free(_emotion_backends);
|
|
||||||
_emotion_backends = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EAPI Eina_Bool
|
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(api, EINA_FALSE);
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(plugin, EINA_FALSE);
|
|
||||||
|
|
||||||
plugin->open = mod_open;
|
if (api->version != EMOTION_ENGINE_API_VERSION)
|
||||||
plugin->close = mod_close;
|
{
|
||||||
|
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);
|
EINA_SAFETY_ON_NULL_RETURN_VAL(api->name, EINA_FALSE);
|
||||||
return eina_hash_add(_emotion_backends, name, plugin);
|
|
||||||
|
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
|
EAPI Eina_Bool
|
||||||
_emotion_module_unregister(const char *name)
|
_emotion_module_unregister(const Emotion_Engine *api)
|
||||||
{
|
{
|
||||||
INF("unregister module=%s", name);
|
Eina_List *n;
|
||||||
return eina_hash_del_by_key(_emotion_backends, name);
|
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
|
struct _Emotion_Engine_Instance
|
||||||
{
|
{
|
||||||
Eina_Emotion_Plugins *plugin;
|
const Emotion_Engine *api;
|
||||||
Emotion_Video_Module *api;
|
|
||||||
Evas_Object *obj;
|
Evas_Object *obj;
|
||||||
char *name;
|
|
||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -192,66 +260,81 @@ struct _Emotion_Engine_Instance
|
||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
|
|
||||||
static const char *_backend_priority[] = {
|
static const Emotion_Engine *
|
||||||
"gstreamer",
|
_emotion_engine_registry_find(const char *name)
|
||||||
"xine",
|
{
|
||||||
"generic"
|
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 *
|
||||||
emotion_engine_instance_new(const char *name, Evas_Object *obj, Emotion_Module_Options *opts)
|
emotion_engine_instance_new(const char *name, Evas_Object *obj, Emotion_Module_Options *opts)
|
||||||
{
|
{
|
||||||
// TODO: rewrite
|
const Eina_List *n;
|
||||||
Eina_Emotion_Plugins *plugin;
|
const Emotion_Engine_Registry_Entry *re;
|
||||||
unsigned int i = 0;
|
const Emotion_Engine *engine;
|
||||||
Emotion_Video_Module *mod = NULL;
|
void *data;
|
||||||
void *data = NULL;
|
|
||||||
|
|
||||||
if (!_emotion_backends)
|
if ((!name) && getenv("EMOTION_ENGINE"))
|
||||||
{
|
|
||||||
ERR("No backend loaded");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!name && getenv("EMOTION_ENGINE"))
|
|
||||||
{
|
{
|
||||||
name = getenv("EMOTION_ENGINE");
|
name = getenv("EMOTION_ENGINE");
|
||||||
DBG("using EMOTION_ENGINE=%s", name);
|
DBG("using EMOTION_ENGINE=%s", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Always look for a working backend. */
|
if (name)
|
||||||
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 (i != 0 && i < (sizeof (_backend_priority) / sizeof (char*)))
|
engine = _emotion_engine_registry_find(name);
|
||||||
goto retry;
|
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");
|
ERR("Requested engine '%s' could not be used. Try fallback", name);
|
||||||
return NULL;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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));
|
engine = re->engine;
|
||||||
INF("opened %s, mod=%p, video=%p", name, mod, data);
|
DBG("Trying engine %s, priority=%d (%d)",
|
||||||
inst->plugin = plugin;
|
engine->name, re->priority, engine->priority);
|
||||||
inst->api = mod;
|
|
||||||
inst->obj = obj;
|
data = engine->add(engine, obj, opts);
|
||||||
inst->data = data;
|
if (data)
|
||||||
inst->name = strdup(name);
|
{
|
||||||
return inst;
|
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*)))
|
ERR("No engine worked");
|
||||||
goto retry;
|
|
||||||
|
|
||||||
ERR("Unable to load module: %s", name);
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,7 +342,7 @@ void
|
||||||
emotion_engine_instance_del(Emotion_Engine_Instance *inst)
|
emotion_engine_instance_del(Emotion_Engine_Instance *inst)
|
||||||
{
|
{
|
||||||
EINA_SAFETY_ON_NULL_RETURN(inst);
|
EINA_SAFETY_ON_NULL_RETURN(inst);
|
||||||
inst->plugin->close(inst->api, inst->data); // TODO: weird api
|
inst->api->del(inst->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
Eina_Bool
|
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 */
|
/* these are valid, no safety macros here */
|
||||||
if (!name) return EINA_FALSE;
|
if (!name) return EINA_FALSE;
|
||||||
if (!inst) return EINA_FALSE;
|
if (!inst) return EINA_FALSE;
|
||||||
return strcmp(name, inst->name) == 0;
|
return strcmp(name, inst->api->name) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
|
@ -278,11 +361,11 @@ emotion_engine_instance_data_get(const Emotion_Engine_Instance *inst)
|
||||||
return inst->data;
|
return inst->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char
|
Eina_Bool
|
||||||
emotion_engine_instance_file_open(Emotion_Engine_Instance *inst, const char *file)
|
emotion_engine_instance_file_open(Emotion_Engine_Instance *inst, const char *file)
|
||||||
{
|
{
|
||||||
EMOTION_ENGINE_INSTANCE_CHECK(inst, file_open, EINA_FALSE);
|
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
|
void
|
||||||
|
|
|
@ -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);
|
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);
|
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_file_close(Emotion_Engine_Instance *inst);
|
||||||
void emotion_engine_instance_play(Emotion_Engine_Instance *inst, double pos);
|
void emotion_engine_instance_play(Emotion_Engine_Instance *inst, double pos);
|
||||||
void emotion_engine_instance_stop(Emotion_Engine_Instance *inst);
|
void emotion_engine_instance_stop(Emotion_Engine_Instance *inst);
|
||||||
|
|
|
@ -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);
|
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
|
||||||
if ((!opt) || (!val)) return;
|
if ((!opt) || (!val)) return;
|
||||||
|
|
||||||
// TODO remove me
|
if (strcmp(opt, "video") == 0)
|
||||||
if (!strcmp(opt, "player"))
|
{
|
||||||
eina_stringshare_replace(&sd->module_options.player, val);
|
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
|
EAPI Eina_Bool
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
#include "emotion_generic.h"
|
#include "emotion_generic.h"
|
||||||
|
|
||||||
static Eina_Prefix *pfx = NULL;
|
static Eina_Prefix *pfx = NULL;
|
||||||
|
static Eina_List *_generic_players = NULL;
|
||||||
|
static int _emotion_init_count = 0;
|
||||||
|
|
||||||
static int _emotion_generic_log_domain = -1;
|
static int _emotion_generic_log_domain = -1;
|
||||||
#ifdef DBG
|
#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__)
|
#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 Eina_Bool _fork_and_exec(Emotion_Generic_Video *ev);
|
||||||
static void em_partial_shutdown(Emotion_Generic_Video *ev);
|
static void em_partial_shutdown(Emotion_Generic_Video *ev);
|
||||||
|
|
||||||
|
@ -71,65 +61,6 @@ _player_restart(void *data)
|
||||||
return EINA_FALSE;
|
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
|
static void
|
||||||
_player_send_cmd(Emotion_Generic_Video *ev, int cmd)
|
_player_send_cmd(Emotion_Generic_Video *ev, int cmd)
|
||||||
{
|
{
|
||||||
|
@ -966,7 +897,7 @@ _player_exec(Emotion_Generic_Video *ev)
|
||||||
return EINA_FALSE;
|
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(
|
ev->player.exe = ecore_exe_pipe_run(
|
||||||
buf,
|
buf,
|
||||||
|
@ -1027,18 +958,13 @@ _fork_and_exec(Emotion_Generic_Video *ev)
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char
|
static void *
|
||||||
em_init(Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt)
|
em_add(const Emotion_Engine *api, Evas_Object *obj, const Emotion_Module_Options *opt EINA_UNUSED)
|
||||||
{
|
{
|
||||||
Emotion_Generic_Video *ev;
|
Emotion_Generic_Video *ev;
|
||||||
const char *player;
|
|
||||||
|
|
||||||
if (!emotion_video) return 0;
|
ev = calloc(1, sizeof(*ev));
|
||||||
player = _get_player(opt ? opt->player : NULL);
|
EINA_SAFETY_ON_NULL_RETURN_VAL(ev, NULL);
|
||||||
if (!player) return 0;
|
|
||||||
|
|
||||||
ev = (Emotion_Generic_Video *)calloc(1, sizeof(*ev));
|
|
||||||
if (!ev) return 0;
|
|
||||||
|
|
||||||
ev->fd_read = -1;
|
ev->fd_read = -1;
|
||||||
ev->fd_write = -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->cmd.type = -1;
|
||||||
|
|
||||||
ev->obj = obj;
|
ev->obj = obj;
|
||||||
ev->cmdline = eina_stringshare_add(player);
|
ev->engine = (Emotion_Engine_Generic *)api;
|
||||||
*emotion_video = ev;
|
|
||||||
|
|
||||||
return _fork_and_exec(ev);
|
if (!_fork_and_exec(ev))
|
||||||
|
{
|
||||||
|
free(ev);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ev;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1092,23 +1023,18 @@ em_partial_shutdown(Emotion_Generic_Video *ev)
|
||||||
ev->player_restart = NULL;
|
ev->player_restart = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
em_shutdown(void *data)
|
em_del(void *data)
|
||||||
{
|
{
|
||||||
Emotion_Generic_Video *ev = data;
|
Emotion_Generic_Video *ev = data;
|
||||||
|
|
||||||
if (!ev) return 0;
|
|
||||||
|
|
||||||
eina_stringshare_del(ev->cmdline);
|
|
||||||
eina_stringshare_del(ev->shmname);
|
eina_stringshare_del(ev->shmname);
|
||||||
|
|
||||||
em_partial_shutdown(ev);
|
em_partial_shutdown(ev);
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char
|
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;
|
Emotion_Generic_Video *ev = data;
|
||||||
INF("file set: %s", file);
|
INF("file set: %s", file);
|
||||||
|
@ -1700,8 +1626,13 @@ em_meta_get(void *data, int meta)
|
||||||
return NULL;
|
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_open, /* file_open */
|
||||||
em_file_close, /* file_close */
|
em_file_close, /* file_close */
|
||||||
em_play, /* play */
|
em_play, /* play */
|
||||||
|
@ -1763,64 +1694,181 @@ static const Emotion_Video_Module em_module =
|
||||||
NULL /* priority_get */
|
NULL /* priority_get */
|
||||||
};
|
};
|
||||||
|
|
||||||
static Eina_Bool
|
static void
|
||||||
module_open(Evas_Object *obj, const Emotion_Video_Module **module, void **video, Emotion_Module_Options *opt)
|
_player_entry_add(const Eina_File_Direct_Info *info)
|
||||||
{
|
{
|
||||||
if (!module) {
|
Emotion_Engine_Generic *eg;
|
||||||
return EINA_FALSE;
|
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();
|
if ((*endptr == '-') || (*endptr == '_'))
|
||||||
eina_log_threads_enable();
|
endptr++;
|
||||||
_emotion_generic_log_domain = eina_log_domain_register
|
name = endptr;
|
||||||
("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 (*name == '\0')
|
||||||
|
{
|
||||||
|
ERR("Invalid generic player: %s", info->path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!em_init(obj, video, opt)) {
|
eg = malloc(sizeof(Emotion_Engine_Generic));
|
||||||
return EINA_FALSE;
|
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
|
Eina_Bool
|
||||||
generic_module_init(void)
|
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,
|
pfx = eina_prefix_new(NULL, emotion_init,
|
||||||
"EMOTION", "emotion", "checkme",
|
"EMOTION", "emotion", "checkme",
|
||||||
PACKAGE_BIN_DIR, PACKAGE_LIB_DIR,
|
PACKAGE_BIN_DIR, PACKAGE_LIB_DIR,
|
||||||
PACKAGE_DATA_DIR, PACKAGE_DATA_DIR);
|
PACKAGE_DATA_DIR, PACKAGE_DATA_DIR);
|
||||||
if (!pfx) return EINA_FALSE;
|
if (!pfx)
|
||||||
return _emotion_module_register("generic", module_open, module_close);
|
{
|
||||||
|
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
|
void
|
||||||
generic_module_shutdown(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);
|
eina_prefix_free(pfx);
|
||||||
pfx = NULL;
|
pfx = NULL;
|
||||||
|
|
||||||
_emotion_module_unregister("generic");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef EMOTION_STATIC_BUILD_GENERIC
|
#ifndef EMOTION_STATIC_BUILD_GENERIC
|
||||||
|
|
|
@ -58,10 +58,16 @@ struct _Emotion_Generic_Cmd_Buffer
|
||||||
} param;
|
} param;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct _Emotion_Engine_Generic
|
||||||
|
{
|
||||||
|
Emotion_Engine engine;
|
||||||
|
char *path;
|
||||||
|
} Emotion_Engine_Generic;
|
||||||
|
|
||||||
/* emotion/generic main structure */
|
/* emotion/generic main structure */
|
||||||
struct _Emotion_Generic_Video
|
struct _Emotion_Generic_Video
|
||||||
{
|
{
|
||||||
const char *cmdline;
|
const Emotion_Engine_Generic *engine;
|
||||||
const char *shmname;
|
const char *shmname;
|
||||||
|
|
||||||
Emotion_Generic_Player player;
|
Emotion_Generic_Player player;
|
||||||
|
|
|
@ -51,7 +51,7 @@ emotion_gstreamer_buffer_free(Emotion_Gstreamer_Buffer *send)
|
||||||
if (send->ev->in == send->ev->out
|
if (send->ev->in == send->ev->out
|
||||||
&& send->ev->threads == NULL
|
&& send->ev->threads == NULL
|
||||||
&& send->ev->delete_me)
|
&& send->ev->delete_me)
|
||||||
em_shutdown(send->ev);
|
send->ev->api->del(send->ev);
|
||||||
|
|
||||||
gst_buffer_unref(send->frame);
|
gst_buffer_unref(send->frame);
|
||||||
free(send);
|
free(send);
|
||||||
|
@ -83,7 +83,7 @@ emotion_gstreamer_message_free(Emotion_Gstreamer_Message *send)
|
||||||
if (send->ev->in == send->ev->out
|
if (send->ev->in == send->ev->out
|
||||||
&& send->ev->threads == NULL
|
&& send->ev->threads == NULL
|
||||||
&& send->ev->delete_me)
|
&& send->ev->delete_me)
|
||||||
em_shutdown(send->ev);
|
send->ev->api->del(send->ev);
|
||||||
|
|
||||||
gst_message_unref(send->msg);
|
gst_message_unref(send->msg);
|
||||||
free(send);
|
free(send);
|
||||||
|
|
|
@ -33,173 +33,12 @@ Eina_Bool debug_fps = EINA_FALSE;
|
||||||
Eina_Bool _ecore_x_available = EINA_FALSE;
|
Eina_Bool _ecore_x_available = EINA_FALSE;
|
||||||
|
|
||||||
static Ecore_Idler *restart_idler;
|
static Ecore_Idler *restart_idler;
|
||||||
|
static int _emotion_init_count = 0;
|
||||||
|
|
||||||
/* Callbacks to get the eos */
|
/* Callbacks to get the eos */
|
||||||
static void _for_each_tag (GstTagList const* list, gchar const* tag, void *data);
|
static void _for_each_tag (GstTagList const* list, gchar const* tag, void *data);
|
||||||
static void _free_metadata (Emotion_Gstreamer_Metadata *m);
|
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,
|
static GstBusSyncReply _eos_sync_fct(GstBus *bus,
|
||||||
GstMessage *message,
|
GstMessage *message,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
|
@ -208,68 +47,6 @@ static Eina_Bool _em_restart_stream(void *data);
|
||||||
|
|
||||||
/* Module interface */
|
/* 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 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
|
static void
|
||||||
em_cleanup(Emotion_Gstreamer_Video *ev)
|
em_cleanup(Emotion_Gstreamer_Video *ev)
|
||||||
{
|
{
|
||||||
|
@ -455,14 +194,10 @@ em_cleanup(Emotion_Gstreamer_Video *ev)
|
||||||
free(vstream);
|
free(vstream);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static void
|
||||||
em_shutdown(void *video)
|
em_del(void *video)
|
||||||
{
|
{
|
||||||
Emotion_Gstreamer_Video *ev;
|
Emotion_Gstreamer_Video *ev = video;
|
||||||
|
|
||||||
ev = (Emotion_Gstreamer_Video *)video;
|
|
||||||
if (!ev)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (ev->threads)
|
if (ev->threads)
|
||||||
{
|
{
|
||||||
|
@ -472,34 +207,28 @@ em_shutdown(void *video)
|
||||||
ecore_thread_cancel(t);
|
ecore_thread_cancel(t);
|
||||||
|
|
||||||
ev->delete_me = EINA_TRUE;
|
ev->delete_me = EINA_TRUE;
|
||||||
return EINA_FALSE;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ev->in != ev->out)
|
if (ev->in != ev->out)
|
||||||
{
|
{
|
||||||
ev->delete_me = EINA_TRUE;
|
ev->delete_me = EINA_TRUE;
|
||||||
return EINA_FALSE;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
em_cleanup(ev);
|
em_cleanup(ev);
|
||||||
|
|
||||||
free(ev);
|
free(ev);
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
static unsigned char
|
em_file_open(void *video,
|
||||||
em_file_open(const char *file,
|
const char *file)
|
||||||
Evas_Object *obj,
|
|
||||||
void *video)
|
|
||||||
{
|
{
|
||||||
Emotion_Gstreamer_Video *ev;
|
Emotion_Gstreamer_Video *ev = video;
|
||||||
Eina_Strbuf *sbuf = NULL;
|
Eina_Strbuf *sbuf = NULL;
|
||||||
const char *uri;
|
const char *uri;
|
||||||
|
|
||||||
ev = (Emotion_Gstreamer_Video *)video;
|
|
||||||
|
|
||||||
if (!file) return EINA_FALSE;
|
if (!file) return EINA_FALSE;
|
||||||
if (strstr(file, "://") == NULL)
|
if (strstr(file, "://") == NULL)
|
||||||
{
|
{
|
||||||
|
@ -529,7 +258,7 @@ em_file_open(const char *file,
|
||||||
|
|
||||||
uri = sbuf ? eina_strbuf_string_get(sbuf) : file;
|
uri = sbuf ? eina_strbuf_string_get(sbuf) : file;
|
||||||
DBG("setting file to '%s'", uri);
|
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 (sbuf) eina_strbuf_free(sbuf);
|
||||||
|
|
||||||
if (!ev->pipeline)
|
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);
|
gst_bus_set_sync_handler(ev->eos_bus, _eos_sync_fct, ev);
|
||||||
|
|
||||||
/* Evas Object */
|
|
||||||
ev->obj = obj;
|
|
||||||
|
|
||||||
ev->position = 0.0;
|
ev->position = 0.0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1334,54 +1060,17 @@ _ecore_event_x_destroy(void *data EINA_UNUSED, int type EINA_UNUSED, void *event
|
||||||
|
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static Eina_Bool
|
static void
|
||||||
module_open(Evas_Object *obj,
|
gstreamer_ecore_x_check(void)
|
||||||
const Emotion_Video_Module **module,
|
|
||||||
void **video,
|
|
||||||
Emotion_Module_Options *opt)
|
|
||||||
{
|
{
|
||||||
#ifdef HAVE_ECORE_X
|
|
||||||
Ecore_X_Window *roots;
|
Ecore_X_Window *roots;
|
||||||
int num;
|
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);
|
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. */
|
/* 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)
|
if (roots && num > 0)
|
||||||
{
|
{
|
||||||
Ecore_X_Window win, twin;
|
Ecore_X_Window win, twin;
|
||||||
|
@ -1425,39 +1114,138 @@ module_open(Evas_Object *obj,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(roots);
|
free(roots);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
*module = &em_module;
|
static void *
|
||||||
return EINA_TRUE;
|
em_add(const Emotion_Engine *api,
|
||||||
}
|
Evas_Object *obj,
|
||||||
|
const Emotion_Module_Options *opt EINA_UNUSED)
|
||||||
static void
|
|
||||||
module_close(Emotion_Video_Module *module EINA_UNUSED,
|
|
||||||
void *video)
|
|
||||||
{
|
{
|
||||||
em_shutdown(video);
|
Emotion_Gstreamer_Video *ev;
|
||||||
|
|
||||||
#ifdef HAVE_ECORE_X
|
ev = calloc(1, sizeof(Emotion_Gstreamer_Video));
|
||||||
if (_ecore_x_available)
|
EINA_SAFETY_ON_NULL_RETURN_VAL(ev, NULL);
|
||||||
{
|
|
||||||
ecore_x_shutdown();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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
|
Eina_Bool
|
||||||
gstreamer_module_init(void)
|
gstreamer_module_init(void)
|
||||||
{
|
{
|
||||||
GError *error;
|
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))
|
if (!gst_init_check(0, NULL, &error))
|
||||||
{
|
{
|
||||||
EINA_LOG_CRIT("Could not init GStreamer");
|
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,
|
if (gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
|
||||||
"emotion-sink",
|
"emotion-sink",
|
||||||
"video sink plugin for Emotion",
|
"video sink plugin for Emotion",
|
||||||
|
@ -1469,16 +1257,66 @@ gstreamer_module_init(void)
|
||||||
"http://www.enlightenment.org/") == FALSE)
|
"http://www.enlightenment.org/") == FALSE)
|
||||||
{
|
{
|
||||||
EINA_LOG_CRIT("Could not load static gstreamer video sink for Emotion.");
|
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
|
void
|
||||||
gstreamer_module_shutdown(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();
|
gst_deinit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef __EMOTION_GSTREAMER_H__
|
#ifndef __EMOTION_GSTREAMER_H__
|
||||||
#define __EMOTION_GSTREAMER_H__
|
#define __EMOTION_GSTREAMER_H__
|
||||||
|
|
||||||
|
#include "Emotion_Module.h"
|
||||||
|
|
||||||
typedef void (*Evas_Video_Convert_Cb)(unsigned char *evas_data,
|
typedef void (*Evas_Video_Convert_Cb)(unsigned char *evas_data,
|
||||||
const unsigned char *gst_data,
|
const unsigned char *gst_data,
|
||||||
unsigned int w,
|
unsigned int w,
|
||||||
|
@ -49,6 +51,8 @@ struct _Emotion_Gstreamer_Metadata
|
||||||
|
|
||||||
struct _Emotion_Gstreamer_Video
|
struct _Emotion_Gstreamer_Video
|
||||||
{
|
{
|
||||||
|
const Emotion_Engine *api;
|
||||||
|
|
||||||
/* Gstreamer elements */
|
/* Gstreamer elements */
|
||||||
GstElement *pipeline;
|
GstElement *pipeline;
|
||||||
GstElement *sink;
|
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 _emotion_gstreamer_video_pipeline_parse(Emotion_Gstreamer_Video *ev,
|
||||||
Eina_Bool force);
|
Eina_Bool force);
|
||||||
|
|
||||||
int em_shutdown(void *video);
|
|
||||||
|
|
||||||
typedef struct _ColorSpace_FourCC_Convertion ColorSpace_FourCC_Convertion;
|
typedef struct _ColorSpace_FourCC_Convertion ColorSpace_FourCC_Convertion;
|
||||||
typedef struct _ColorSpace_Format_Convertion ColorSpace_Format_Convertion;
|
typedef struct _ColorSpace_Format_Convertion ColorSpace_Format_Convertion;
|
||||||
|
|
||||||
|
|
|
@ -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 (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)
|
if (ev->in == ev->out && ev->delete_me)
|
||||||
em_shutdown(ev);
|
ev->api->del(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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 (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)
|
if (ev->in == ev->out && ev->delete_me)
|
||||||
em_shutdown(ev);
|
ev->api->del(ev);
|
||||||
else
|
else
|
||||||
_emotion_gstreamer_video_pipeline_parse(data, EINA_TRUE);
|
_emotion_gstreamer_video_pipeline_parse(data, EINA_TRUE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,63 +10,7 @@
|
||||||
#include "emotion_xine.h"
|
#include "emotion_xine.h"
|
||||||
|
|
||||||
int _emotion_xine_log_domain = -1;
|
int _emotion_xine_log_domain = -1;
|
||||||
|
static int _emotion_init_count = 0;
|
||||||
/* 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);
|
|
||||||
|
|
||||||
/* internal util calls */
|
/* internal util calls */
|
||||||
static void *_em_slave (void *par);
|
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[];
|
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
|
/* this is a slave controller thread for the xine module - libxine loves
|
||||||
* to deadlock, internally stall and otherwise have unpredictable behavior
|
* 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 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");
|
if (write(ev->fd_slave_write, buf, sizeof(buf)) < 0) perror("write");
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char
|
static void *
|
||||||
em_init(Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt)
|
em_add(const Emotion_Engine *api EINA_UNUSED,
|
||||||
|
Evas_Object *obj,
|
||||||
|
const Emotion_Module_Options *opt)
|
||||||
{
|
{
|
||||||
Emotion_Xine_Video *ev;
|
Emotion_Xine_Video *ev;
|
||||||
int fds[2];
|
int fds[2];
|
||||||
|
|
||||||
if (!emotion_video) return 0;
|
|
||||||
|
|
||||||
ev = calloc(1, sizeof(Emotion_Xine_Video));
|
ev = calloc(1, sizeof(Emotion_Xine_Video));
|
||||||
if (!ev) return 0;
|
EINA_SAFETY_ON_NULL_RETURN_VAL(ev, NULL);
|
||||||
ev->obj = obj;
|
ev->obj = obj;
|
||||||
|
|
||||||
if (pipe(fds) == 0)
|
if (pipe(fds) == 0)
|
||||||
{
|
{
|
||||||
ev->fd_read = 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);
|
_em_slave_event(ev, 1, NULL);
|
||||||
|
|
||||||
ev->buffer = 1.0;
|
ev->buffer = 1.0;
|
||||||
|
|
||||||
*emotion_video = ev;
|
return ev;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
em_shutdown(void *ef)
|
em_del(void *ef)
|
||||||
{
|
{
|
||||||
Emotion_Xine_Video *ev;
|
Emotion_Xine_Video *ev = ef;
|
||||||
|
|
||||||
ev = (Emotion_Xine_Video *)ef;
|
|
||||||
ev->closing = 1;
|
ev->closing = 1;
|
||||||
ev->delete_me = 1;
|
ev->delete_me = 1;
|
||||||
DBG("del fds %p", ev);
|
DBG("del fds %p", ev);
|
||||||
|
@ -450,22 +394,18 @@ em_shutdown(void *ef)
|
||||||
ecore_animator_del(ev->anim);
|
ecore_animator_del(ev->anim);
|
||||||
ev->anim = NULL;
|
ev->anim = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ev->closing = 1;
|
ev->closing = 1;
|
||||||
_em_slave_event(ev, 3, NULL);
|
_em_slave_event(ev, 3, NULL);
|
||||||
DBG("done %p", ev);
|
DBG("done %p", ev);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char
|
static Eina_Bool
|
||||||
em_file_open(const char *file, Evas_Object *obj EINA_UNUSED, void *ef)
|
em_file_open(void *ef, const char *file)
|
||||||
{
|
{
|
||||||
Emotion_Xine_Video *ev;
|
Emotion_Xine_Video *ev = ef;
|
||||||
|
|
||||||
ev = (Emotion_Xine_Video *)ef;
|
|
||||||
if (!ev) return 0;
|
|
||||||
_em_slave_event(ev, 2, strdup(file));
|
_em_slave_event(ev, 2, strdup(file));
|
||||||
return 1;
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1533,8 +1473,13 @@ _em_get_pos_len(Emotion_Xine_Video *ev)
|
||||||
pthread_mutex_unlock(&(ev->get_pos_len_mutex));
|
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_open, /* file_open */
|
||||||
em_file_close, /* file_close */
|
em_file_close, /* file_close */
|
||||||
em_play, /* play */
|
em_play, /* play */
|
||||||
|
@ -1596,48 +1541,56 @@ static const Emotion_Video_Module em_module =
|
||||||
NULL /* priority_get */
|
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
|
Eina_Bool
|
||||||
xine_module_init(void)
|
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
|
void
|
||||||
xine_module_shutdown(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
|
#ifndef EMOTION_STATIC_BUILD_XINE
|
||||||
|
|
Loading…
Reference in New Issue