efl/emotion: rework module infra, better integration with 'generic'.
authorGustavo Sverzut Barbieri <barbieri@gmail.com>
Fri, 11 Jan 2013 03:06:42 +0000 (03:06 +0000)
committerGustavo Sverzut Barbieri <barbieri@gmail.com>
Fri, 11 Jan 2013 03:06:42 +0000 (03:06 +0000)
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

src/lib/emotion/Emotion_Module.h
src/lib/emotion/emotion_modules.c
src/lib/emotion/emotion_private.h
src/lib/emotion/emotion_smart.c
src/modules/emotion/generic/emotion_generic.c
src/modules/emotion/generic/emotion_generic.h
src/modules/emotion/gstreamer/emotion_alloc.c
src/modules/emotion/gstreamer/emotion_gstreamer.c
src/modules/emotion/gstreamer/emotion_gstreamer.h
src/modules/emotion/gstreamer/emotion_sink.c
src/modules/emotion/xine/emotion_xine.c

index 56c9872..0ece2c1 100644 (file)
 #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
index 3e8a18a..95ac2b3 100644 (file)
@@ -17,10 +17,38 @@ 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)
 {
    char buf[PATH_MAX];
@@ -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;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(api, EINA_FALSE);
+
+   if (api->version != EMOTION_ENGINE_API_VERSION)
+     {
+        ERR("Module '%p' uses api version=%u while %u was expected",
+            api, api->version, EMOTION_ENGINE_API_VERSION);
+        return EINA_FALSE;
+     }
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(api->name, EINA_FALSE);
+
+   INF("register name=%s, version=%u, priority=%d, api=%p",
+       api->name, api->version, api->priority, api);
+
+   re = calloc(1, sizeof(Emotion_Engine_Registry_Entry));
+   EINA_SAFETY_ON_NULL_RETURN_VAL(re, EINA_FALSE);
 
-   plugin = malloc(sizeof (Eina_Emotion_Plugins));
-   EINA_SAFETY_ON_NULL_RETURN_VAL(plugin, EINA_FALSE);
+   re->engine = api;
+   re->priority = api->priority; // TODO: use user-priority from file as weel.
 
-   plugin->open = mod_open;
-   plugin->close = mod_close;
+   _emotion_engine_registry = eina_list_sorted_insert
+     (_emotion_engine_registry, _emotion_engine_registry_entry_cmp, re);
 
-   INF("register module=%s, open=%p, close=%p", name, mod_open, mod_close);
-   return eina_hash_add(_emotion_backends, name, plugin);
+   return EINA_TRUE;
 }
 
 EAPI Eina_Bool
-_emotion_module_unregister(const char *name)
+_emotion_module_unregister(const Emotion_Engine *api)
 {
-   INF("unregister module=%s", name);
-   return eina_hash_del_by_key(_emotion_backends, name);
+   Eina_List *n;
+   Emotion_Engine_Registry_Entry *re;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(api, EINA_FALSE);
+   if (api->version != EMOTION_ENGINE_API_VERSION)
+     {
+        ERR("Module '%p' uses api version=%u while %u was expected",
+            api, api->version, EMOTION_ENGINE_API_VERSION);
+        return EINA_FALSE;
+     }
+
+   INF("unregister name=%s, api=%p", api->name, api);
+
+   EINA_LIST_FOREACH(_emotion_engine_registry, n, re)
+     {
+        if (re->engine == api)
+          {
+             _emotion_engine_registry_entry_free(re);
+             _emotion_engine_registry = eina_list_remove_list
+               (_emotion_engine_registry, n);
+             return EINA_TRUE;
+          }
+     }
+
+   ERR("module not registered name=%s, api=%p", api->name, api);
+   return EINA_FALSE;
 }
 
 struct _Emotion_Engine_Instance
 {
-   Eina_Emotion_Plugins *plugin;
-   Emotion_Video_Module *api;
+   const Emotion_Engine *api;
    Evas_Object *obj;
-   char *name;
    void *data;
 };
 
@@ -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;
-
-   if (!_emotion_backends)
-     {
-        ERR("No backend loaded");
-        return NULL;
-     }
+   const Eina_List *n;
+   const Emotion_Engine_Registry_Entry *re;
+   const Emotion_Engine *engine;
+   void *data;
 
-   if (!name && getenv("EMOTION_ENGINE"))
+   if ((!name) && getenv("EMOTION_ENGINE"))
      {
         name = getenv("EMOTION_ENGINE");
         DBG("using EMOTION_ENGINE=%s", name);
      }
 
-   /* FIXME: Always look for a working backend. */
- retry:
-   if (!name || i > 0)
-     name = _backend_priority[i++];
-
-   plugin = eina_hash_find(_emotion_backends, name);
-   DBG("try engine=%s, plugin=%p", name, plugin);
-   if (!plugin)
+   if (name)
      {
-        if (i != 0 && i < (sizeof (_backend_priority) / sizeof (char*)))
-          goto retry;
+        engine = _emotion_engine_registry_find(name);
+        if (!engine)
+          ERR("Couldn't find requested engine: %s. Try fallback", name);
+        else
+          {
+             data = engine->add(engine, obj, opts);
+             if (data)
+               {
+                  INF("Using requested engine %s, data=%p", name, data);
+                  return _emotion_engine_instance_new(engine, obj, data);
+               }
 
-        ERR("No backend loaded");
-        return NULL;
+             ERR("Requested engine '%s' could not be used. Try fallback", name);
+          }
      }
 
-   if (plugin->open(obj, (const Emotion_Video_Module **) &mod, &data, opts))
+   EINA_LIST_FOREACH(_emotion_engine_registry, n, re)
      {
-        Emotion_Engine_Instance *inst = calloc(1, sizeof(Emotion_Engine_Instance));
-        INF("opened %s, mod=%p, video=%p", name, mod, data);
-        inst->plugin = plugin;
-        inst->api = mod;
-        inst->obj = obj;
-        inst->data = data;
-        inst->name = strdup(name);
-        return inst;
-     }
+        engine = re->engine;
+        DBG("Trying engine %s, priority=%d (%d)",
+            engine->name, re->priority, engine->priority);
 
-   if (i != 0 && i < (sizeof (_backend_priority) / sizeof (char*)))
-     goto retry;
-
-   ERR("Unable to load module: %s", name);
+        data = engine->add(engine, obj, opts);
+        if (data)
+          {
+             INF("Using fallback engine %s, data=%p", engine->name, data);
+             return _emotion_engine_instance_new(engine, obj, data);
+          }
+     }
 
+   ERR("No engine worked");
    return NULL;
 }
 
@@ -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
index 597e3fb..93419f6 100644 (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);
index a91ff3f..5cfa0e5 100644 (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
index 58a4f01..b30faa6 100644 (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;
+
+   if (!_fork_and_exec(ev))
+     {
+        free(ev);
+        return NULL;
+     }
 
-   return _fork_and_exec(ev);
+   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
index 864abb3..1536a0e 100644 (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;
index b7eecd4..c4aae04 100644 (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);
index 31f319e..e48d8f0 100644 (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,38 +1114,137 @@ module_open(Evas_Object           *obj,
           }
      }
    free(roots);
-#endif
-
-   *module = &em_module;
-   return EINA_TRUE;
 }
+#endif
 
-static void
-module_close(Emotion_Video_Module *module EINA_UNUSED,
-             void                 *video)
+static void *
+em_add(const Emotion_Engine *api,
+       Evas_Object *obj,
+       const Emotion_Module_Options *opt EINA_UNUSED)
 {
-   em_shutdown(video);
+   Emotion_Gstreamer_Video *ev;
 
-#ifdef HAVE_ECORE_X
-   if (_ecore_x_available)
-     {
-        ecore_x_shutdown();
-     }
-#endif
+   ev = calloc(1, sizeof(Emotion_Gstreamer_Video));
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev, NULL);
+
+   ev->api = api;
+   ev->obj = obj;
 
-   eina_threads_shutdown();
+   /* Default values */
+   ev->ratio = 1.0;
+   ev->vis = EMOTION_VIS_NONE;
+   ev->volume = 0.8;
+   ev->play_started = 0;
+   ev->delete_me = EINA_FALSE;
+   ev->threads = NULL;
+
+   return ev;
 }
 
+static const Emotion_Engine em_engine =
+{
+   EMOTION_ENGINE_API_VERSION,
+   EMOTION_ENGINE_PRIORITY_DEFAULT,
+   "gstreamer",
+   em_add, /* add */
+   em_del, /* del */
+   em_file_open, /* file_open */
+   em_file_close, /* file_close */
+   em_play, /* play */
+   em_stop, /* stop */
+   em_size_get, /* size_get */
+   em_pos_set, /* pos_set */
+   em_len_get, /* len_get */
+   em_buffer_size_get, /* buffer_size_get */
+   em_fps_num_get, /* fps_num_get */
+   em_fps_den_get, /* fps_den_get */
+   em_fps_get, /* fps_get */
+   em_pos_get, /* pos_get */
+   em_vis_set, /* vis_set */
+   em_vis_get, /* vis_get */
+   em_vis_supported, /* vis_supported */
+   em_ratio_get, /* ratio_get */
+   em_video_handled, /* video_handled */
+   em_audio_handled, /* audio_handled */
+   em_seekable, /* seekable */
+   em_frame_done, /* frame_done */
+   em_format_get, /* format_get */
+   em_video_data_size_get, /* video_data_size_get */
+   em_yuv_rows_get, /* yuv_rows_get */
+   em_bgra_data_get, /* bgra_data_get */
+   em_event_feed, /* event_feed */
+   em_event_mouse_button_feed, /* event_mouse_button_feed */
+   em_event_mouse_move_feed, /* event_mouse_move_feed */
+   em_video_channel_count, /* video_channel_count */
+   em_video_channel_set, /* video_channel_set */
+   em_video_channel_get, /* video_channel_get */
+   em_video_subtitle_file_set, /* video_subtitle_file_set */
+   em_video_subtitle_file_get, /* video_subtitle_file_get */
+   em_video_channel_name_get, /* video_channel_name_get */
+   em_video_channel_mute_set, /* video_channel_mute_set */
+   em_video_channel_mute_get, /* video_channel_mute_get */
+   em_audio_channel_count, /* audio_channel_count */
+   em_audio_channel_set, /* audio_channel_set */
+   em_audio_channel_get, /* audio_channel_get */
+   em_audio_channel_name_get, /* audio_channel_name_get */
+   em_audio_channel_mute_set, /* audio_channel_mute_set */
+   em_audio_channel_mute_get, /* audio_channel_mute_get */
+   em_audio_channel_volume_set, /* audio_channel_volume_set */
+   em_audio_channel_volume_get, /* audio_channel_volume_get */
+   em_spu_channel_count, /* spu_channel_count */
+   em_spu_channel_set, /* spu_channel_set */
+   em_spu_channel_get, /* spu_channel_get */
+   em_spu_channel_name_get, /* spu_channel_name_get */
+   em_spu_channel_mute_set, /* spu_channel_mute_set */
+   em_spu_channel_mute_get, /* spu_channel_mute_get */
+   em_chapter_count, /* chapter_count */
+   em_chapter_set, /* chapter_set */
+   em_chapter_get, /* chapter_get */
+   em_chapter_name_get, /* chapter_name_get */
+   em_speed_set, /* speed_set */
+   em_speed_get, /* speed_get */
+   em_eject, /* eject */
+   em_meta_get, /* meta_get */
+   em_priority_set, /* priority_set */
+   em_priority_get /* priority_get */
+};
+
 Eina_Bool
 gstreamer_module_init(void)
 {
    GError *error;
 
+   if (_emotion_init_count > 0)
+     {
+        _emotion_init_count++;
+        return EINA_TRUE;
+     }
+
+   if (getenv("EMOTION_FPS_DEBUG")) debug_fps = EINA_TRUE;
+
+   eina_threads_init();
+   eina_log_threads_enable();
+   _emotion_gstreamer_log_domain = eina_log_domain_register
+     ("emotion-gstreamer", EINA_COLOR_LIGHTCYAN);
+   if (_emotion_gstreamer_log_domain < 0)
+     {
+        EINA_LOG_CRIT("Could not register log domain 'emotion-gstreamer'");
+        return EINA_FALSE;
+     }
+
    if (!gst_init_check(0, NULL, &error))
      {
         EINA_LOG_CRIT("Could not init GStreamer");
-        return EINA_FALSE;
+        goto error_gst_init;
+     }
+
+#ifdef HAVE_ECORE_X
+   if (ecore_x_init(NULL) > 0)
+     {
+        _ecore_x_available = EINA_TRUE;
+        gstreamer_ecore_x_check();
      }
+#endif
 
    if (gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
                                   "emotion-sink",
@@ -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;
+     }
+
+   if (!_emotion_module_register(&em_engine))
+     {
+        ERR("Could not register module %p", &em_engine);
+        goto error_register;
+     }
+
+   _emotion_init_count = 1;
+   return EINA_TRUE;
+
+ error_register:
+ error_gst_plugin:
+#ifdef HAVE_ECORE_X
+   if (_ecore_x_available)
+     {
+        ecore_x_shutdown();
+        _ecore_x_available = EINA_FALSE;
+        window_manager_video = EINA_FALSE;
      }
+#endif
+
+   gst_deinit();
+
+ error_gst_init:
+   eina_log_domain_unregister(_emotion_gstreamer_log_domain);
+   _emotion_gstreamer_log_domain = -1;
 
-   return _emotion_module_register("gstreamer", module_open, module_close);
+   return EINA_FALSE;
 }
 
 void
 gstreamer_module_shutdown(void)
 {
-   _emotion_module_unregister("gstreamer");
+   if (_emotion_init_count > 1)
+     {
+        _emotion_init_count--;
+        return;
+     }
+   else if (_emotion_init_count == 0)
+     {
+        EINA_LOG_ERR("too many gstreamer_module_shutdown()");
+        return;
+     }
+   _emotion_init_count = 0;
+
+   _emotion_module_unregister(&em_engine);
+
+#ifdef HAVE_ECORE_X
+   if (_ecore_x_available)
+     {
+        ecore_x_shutdown();
+        _ecore_x_available = EINA_FALSE;
+        window_manager_video = EINA_FALSE;
+     }
+#endif
+
+   eina_log_domain_unregister(_emotion_gstreamer_log_domain);
+   _emotion_gstreamer_log_domain = -1;
 
    gst_deinit();
 }
index 18f6b6c..f7f6223 100644 (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;
 
index 755d48a..2e776d2 100644 (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);
 }
index b09db03..a3389bc 100644 (file)
 #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)
+Eina_Bool
+xine_module_init(void)
 {
-   if (!module)
-      return EINA_FALSE;
+   if (_emotion_init_count > 0)
+     {
+        _emotion_init_count++;
+        return EINA_TRUE;
+     }
 
+   eina_threads_init();
+   eina_log_threads_enable();
+   _emotion_xine_log_domain = eina_log_domain_register
+     ("emotion-xine", EINA_COLOR_LIGHTCYAN);
    if (_emotion_xine_log_domain < 0)
      {
-        eina_threads_init();
-        eina_log_threads_enable();
-        _emotion_xine_log_domain = eina_log_domain_register
-          ("emotion-xine", EINA_COLOR_LIGHTCYAN);
-        if (_emotion_xine_log_domain < 0)
-          {
-             EINA_LOG_CRIT("Could not register log domain 'emotion-xine'");
-             return EINA_FALSE;
-          }
+        EINA_LOG_CRIT("Could not register log domain 'emotion-xine'");
+        return EINA_FALSE;
      }
 
-   if (!em_init(obj, video, opt))
-      return EINA_FALSE;
+   if (!_emotion_module_register(&em_engine))
+     {
+        CRITICAL("Could not register module %p", &em_engine);
+        eina_log_domain_unregister(_emotion_xine_log_domain);
+        _emotion_xine_log_domain = -1;
+        return EINA_FALSE;
+     }
 
-   *module = &em_module;
+   _emotion_init_count = 1;
    return EINA_TRUE;
 }
 
-static void
-module_close(Emotion_Video_Module *module EINA_UNUSED, void *video)
-{
-   em_shutdown(video);
-}
-
-Eina_Bool
-xine_module_init(void)
-{
-   return _emotion_module_register("xine", module_open, module_close);
-}
-
 void
 xine_module_shutdown(void)
 {
-   _emotion_module_unregister("xine");
+   if (_emotion_init_count > 1)
+     {
+        _emotion_init_count--;
+        return;
+     }
+   else if (_emotion_init_count == 0)
+     {
+        EINA_LOG_ERR("too many xine_module_shutdown()");
+        return;
+     }
+   _emotion_init_count = 0;
+
+   _emotion_module_unregister(&em_engine);
+
+   eina_log_domain_unregister(_emotion_xine_log_domain);
+   _emotion_xine_log_domain = -1;
 }
 
 #ifndef EMOTION_STATIC_BUILD_XINE