Emotion: introce emotion_object_video_subtitle_file_set() call
authorLeandro Dorileo <dorileo@profusion.mobi>
Wed, 2 Jan 2013 21:03:30 +0000 (21:03 +0000)
committerLeandro Dorileo <dorileo@profusion.mobi>
Wed, 2 Jan 2013 21:03:30 +0000 (21:03 +0000)
For setting an arbitrary subtitle file, this patch introduces the
emotion_object_video_subtitle_file_set() and its counterpart
emotion_object_video_subtitle_file_get().

The tag @sice were added as 1.7.2 since we're preparing a backport to
stable tree.

SVN revision: 82019

14 files changed:
legacy/emotion/.gitignore
legacy/emotion/AUTHORS
legacy/emotion/ChangeLog
legacy/emotion/NEWS
legacy/emotion/src/examples/Makefile.am
legacy/emotion/src/examples/emotion_generic_subtitle_example.c [new file with mode: 0644]
legacy/emotion/src/generic_players/vlc/emotion_generic_vlc.c
legacy/emotion/src/lib/Emotion.h
legacy/emotion/src/lib/emotion_private.h
legacy/emotion/src/lib/emotion_smart.c
legacy/emotion/src/modules/generic/Emotion_Generic_Plugin.h
legacy/emotion/src/modules/generic/emotion_generic.c
legacy/emotion/src/modules/generic/emotion_generic.h
legacy/emotion/src/modules/gstreamer/emotion_gstreamer.c

index a38523e..70e8e3c 100644 (file)
@@ -49,8 +49,14 @@ src/edje_external/Makefile.in
 src/edje_external/module.la
 src/edje_external/module_la-emotion.lo
 src/examples/.deps/
+src/examples/.libs/
 src/examples/Makefile
 src/examples/Makefile.in
+src/examples/emotion_basic_example
+src/examples/emotion_border_example
+src/examples/emotion_generic_example
+src/examples/emotion_generic_subtitle_example
+src/examples/emotion_signals_example
 src/generic_players/Makefile
 src/generic_players/Makefile.in
 src/generic_players/vlc/.deps/
index c2579a8..0cfd8c6 100644 (file)
@@ -8,3 +8,4 @@ Jérôme Pinot <ngc891@gmail.com>
 Pierre Le Magourou <pierre.lemagourou@openwide.fr>
 Hugo Camboulive <hugo.camboulive@zodiacaerospace.com>
 Sohyun Kim <anna1014.kim@samsung.com>
+Leandro Dorileo <dorileo@profusion.mobi>
\ No newline at end of file
index 36a608d..3298ea3 100644 (file)
@@ -58,3 +58,7 @@
 2012-10-11  Sohyun Kim
 
        * Fix to call correct render function based on the format.
+
+2013-01-02  Leandro Dorileo (dorileo)
+
+       * Add subtitle file API.
index d3715bd..112b405 100644 (file)
@@ -1,4 +1,10 @@
-Emotion 1.7.1
+Emotion 1.7.2
+
+Changes since Emotion 1.7.1:
+-------------------------
+
+Additions:
+       - Add video subtitle file API.
 
 Changes since Emotion 1.7.0:
 -------------------------
index 7476f08..5e39adc 100644 (file)
@@ -17,6 +17,7 @@ LDADD = \
 SRCS = \
        emotion_basic_example.c \
        emotion_generic_example.c \
+       emotion_generic_subtitle_example.c \
        emotion_border_example.c \
        emotion_signals_example.c
 
@@ -33,6 +34,7 @@ if EFL_BUILD_EXAMPLES
 examples_PROGRAMS += \
        emotion_basic_example \
        emotion_generic_example \
+       emotion_generic_subtitle_example \
        emotion_border_example \
        emotion_signals_example
 endif
diff --git a/legacy/emotion/src/examples/emotion_generic_subtitle_example.c b/legacy/emotion/src/examples/emotion_generic_subtitle_example.c
new file mode 100644 (file)
index 0000000..448b505
--- /dev/null
@@ -0,0 +1,97 @@
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <stdio.h>
+
+#define WIDTH  (320)
+#define HEIGHT (240)
+
+static void
+_playback_started_cb(void *data, Evas_Object *o, void *event_info)
+{
+    printf("Emotion object started playback.\n");
+}
+
+static void
+_on_delete(Ecore_Evas *ee)
+{
+  ecore_main_loop_quit();
+}
+
+int
+main(int argc, const char *argv[])
+{
+   Ecore_Evas *ee;
+   Evas *e;
+   Evas_Object *bg, *em;
+   const char *filename = NULL;
+   const char *subtitle_filename = NULL;
+
+   if (argc < 2)
+     {
+       printf("At least one argument is necessary. Usage:\n");
+       printf("\t%s <filename> <subtitle filename>\n", argv[0]);
+        return -1;
+     }
+
+   filename = argv[1];
+
+   if (argc > 2)
+     subtitle_filename = argv[2];
+
+   if (!ecore_evas_init())
+     return EXIT_FAILURE;
+
+   /* this will give you a window with an Evas canvas under the first
+    * engine available */
+   ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL);
+   if (!ee)
+     goto error;
+
+   ecore_evas_callback_delete_request_set(ee, _on_delete);
+
+   ecore_evas_show(ee);
+
+   /* the canvas pointer, de facto */
+   e = ecore_evas_get(ee);
+
+   /* adding a background to this example */
+   bg = evas_object_rectangle_add(e);
+   evas_object_name_set(bg, "our dear rectangle");
+   evas_object_color_set(bg, 255, 255, 255, 255); /* white bg */
+   evas_object_move(bg, 0, 0); /* at canvas' origin */
+   evas_object_resize(bg, WIDTH, HEIGHT); /* covers full canvas */
+   evas_object_show(bg);
+
+   /* Creating the emotion object */
+   em = emotion_object_add(e);
+   emotion_object_init(em, "generic");
+
+   if (subtitle_filename)
+     emotion_object_video_subtitle_file_set(em, subtitle_filename);
+
+   evas_object_smart_callback_add(
+       em, "playback_started", _playback_started_cb, NULL);
+
+   emotion_object_file_set(em, filename);
+
+   evas_object_move(em, 0, 0);
+   evas_object_resize(em, WIDTH, HEIGHT);
+   evas_object_show(em);
+
+   emotion_object_play_set(em, EINA_TRUE);
+
+   ecore_main_loop_begin();
+
+   ecore_evas_free(ee);
+   ecore_evas_shutdown();
+   return 0;
+
+error:
+   fprintf(stderr, "you got to have at least one evas engine built and linked"
+                   " up to ecore-evas for this example to run properly.\n");
+
+   ecore_evas_shutdown();
+   return -1;
+}
index 836eda3..d153416 100644 (file)
@@ -37,6 +37,7 @@ struct _App {
      libvlc_event_manager_t *event_mgr;
      libvlc_event_manager_t *mevent_mgr;
      char *filename;
+     char *subtitle_path;
      char *shmname;
      void *tmpbuffer;
      int w, h;
@@ -313,6 +314,10 @@ _play(struct _App *app)
        libvlc_time_t new_time = pos * 1000;
        libvlc_media_player_set_time(app->mp, new_time);
         libvlc_media_player_play(app->mp);
+
+        if (app->subtitle_path)
+          libvlc_video_set_subtitle_file(app->mp, app->subtitle_path);
+
        app->playing = 1;
      }
 }
@@ -378,6 +383,12 @@ _event_cb(const struct libvlc_event_t *ev, void *data)
 }
 
 static void
+_subtitle_set(struct _App *app)
+{
+   _em_str_read(app->em_read, &app->subtitle_path);
+}
+
+static void
 _file_set(struct _App *app)
 {
    if (app->opening)
@@ -585,6 +596,9 @@ _process_emotion_commands(struct _App *app)
       case EM_CMD_FILE_SET_DONE:
         _file_set_done(app);
         break;
+      case EM_CMD_SUBTITLE_SET:
+         _subtitle_set(app);
+         break;
       case EM_CMD_FILE_CLOSE:
         _file_close(app);
         break;
@@ -805,6 +819,7 @@ main(int argc, const char *argv[])
    app.libvlc = libvlc_new(vlc_argc, vlc_argv);
    app.mp = NULL;
    app.filename = NULL;
+   app.subtitle_path = NULL;
    app.w = 0;
    app.h = 0;
    app.size_sent = 0;
index 361e4e5..186144e 100644 (file)
@@ -980,6 +980,38 @@ EAPI void         emotion_object_video_mute_set        (Evas_Object *obj, Eina_B
 EAPI Eina_Bool    emotion_object_video_mute_get        (const Evas_Object *obj);
 
 /**
+ * @brief Set the video's subtitle file path.
+ *
+ * @param obj  The object which we are setting a subtitle file path.
+ * @param filepath The subtitle file path.
+ *
+ * This function sets a video's subtitle file path(i.e an .srt file) for
+ * supported subtitle formats consult the backend's documentation.
+ *
+ * @see emotion_object_video_subtitle_file_get().
+ *
+ * @ingroup Emotion_Video
+ * @since 1.7.2
+ */
+EAPI void         emotion_object_video_subtitle_file_set (Evas_Object *obj, const char *filepath);
+
+/**
+ * @brief Get the video's subtitle file path.
+ *
+ * @param obj The object which we are retrieving the subtitle file path from.
+ * @return The video's subtitle file path previously set, NULL otherwise.
+ *
+ * This function returns the video's subtitle file path, if not previously set
+ * or in error NULL is returned.
+ *
+ * @see emotion_object_video_subtitle_file_set().
+ *
+ * @ingroup Emotion_Video
+ * @since 1.7.2
+ */
+EAPI const char   *emotion_object_video_subtitle_file_get (const Evas_Object *obj);
+
+/**
  * @brief Get the number of available video channel
  *
  * @param obj The object which we are retrieving the channel count from
index cf24c75..73a1b7d 100644 (file)
@@ -74,6 +74,8 @@ struct _Emotion_Video_Module
    int            (*video_channel_count) (void *ef);
    void           (*video_channel_set) (void *ef, int channel);
    int            (*video_channel_get) (void *ef);
+   void           (*video_subtitle_file_set) (void *ef, const char *filepath);
+   const char *   (*video_subtitle_file_get) (void *ef);
    const char *   (*video_channel_name_get) (void *ef, int channel);
    void           (*video_channel_mute_set) (void *ef, int mute);
    int            (*video_channel_mute_get) (void *ef);
index 48eafda..8a80f83 100644 (file)
@@ -999,6 +999,29 @@ emotion_object_video_mute_get(const Evas_Object *obj)
    return sd->module->video_channel_mute_get(sd->video_data);
 }
 
+EAPI void
+emotion_object_video_subtitle_file_set(Evas_Object *obj, const char *filepath)
+{
+   Smart_Data *sd;
+
+   E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
+   DBG("subtitle=%s", filepath);
+   if (!sd->module) return;
+   if (!sd->video_data) return;
+   sd->module->video_subtitle_file_set(sd->video_data, filepath);
+}
+
+EAPI const char *
+emotion_object_video_subtitle_file_get(const Evas_Object *obj)
+{
+   Smart_Data *sd;
+
+   E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
+   if (!sd->module) return EINA_FALSE;
+   if (!sd->video_data) return EINA_FALSE;
+   return sd->module->video_subtitle_file_get(sd->video_data);
+}
+
 EAPI int
 emotion_object_video_channel_count(const Evas_Object *obj)
 {
index 17bd7e9..f00ea6e 100644 (file)
@@ -35,6 +35,7 @@ enum _Emotion_Generic_Cmd
    EM_CMD_AUDIO_TRACK_SET, // param: track id (int)
    EM_CMD_VIDEO_TRACK_SET, // param: track id (int)
    EM_CMD_SPU_TRACK_SET, // param: track id (int)
+   EM_CMD_SUBTITLE_SET, // param: subtitle filename (string)
    EM_CMD_LAST
 };
 
index e0ff6d9..648be6d 100644 (file)
@@ -1129,6 +1129,7 @@ em_file_close(void *data)
    INF("file close: %s", ev->filename);
 
    eina_stringshare_replace(&ev->filename, NULL);
+   eina_stringshare_replace(&ev->subtitle_path, NULL);
 
    ev->file_ready = EINA_FALSE;
    _audio_channels_free(ev);
@@ -1175,8 +1176,15 @@ em_play(void *data, double pos)
 
    if (ev->ready)
      {
+        if (ev->subtitle_path)
+          {
+             _player_send_cmd(ev, EM_CMD_SUBTITLE_SET);
+             _player_send_str(ev, ev->subtitle_path, EINA_TRUE);
+          }
+
        _player_send_cmd(ev, EM_CMD_PLAY);
        _player_send_float(ev, ev->pos);
+
        return;
      }
 
@@ -1392,6 +1400,20 @@ em_video_channel_get(void *data)
    return ev->video_channel_current;
 }
 
+static void
+em_video_subtitle_file_set(void *data, const char *filepath)
+{
+   Emotion_Generic_Video *ev = data;
+   eina_stringshare_replace(&ev->subtitle_path, filepath);
+}
+
+static const char *
+em_video_subtitle_file_get(void *data)
+{
+   Emotion_Generic_Video *ev = data;
+   return ev->subtitle_path;
+}
+
 static const char *
 em_video_channel_name_get(void *data, int channel)
 {
@@ -1694,6 +1716,8 @@ static Emotion_Video_Module em_module =
    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 */
index ed3bdb0..864abb3 100644 (file)
@@ -106,6 +106,7 @@ struct _Emotion_Generic_Video
    int                      spu_channel_current;
    Emotion_Generic_Channel  *spu_channels;
    Emotion_Generic_Meta             meta;
+  const char                 *subtitle_path;
 };
 
 #endif
index 8ec71fb..395d931 100644 (file)
@@ -132,6 +132,11 @@ static void           em_video_channel_set        (void             *video,
 
 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);
 
@@ -241,6 +246,8 @@ static Emotion_Video_Module em_module =
    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 */
@@ -1028,6 +1035,20 @@ em_video_channel_get(void *video)
    return ev->video_stream_nbr;
 }
 
+static void
+em_video_subtitle_file_set(void *video __UNUSED__,
+                           const char *filepath __UNUSED__)
+{
+   DBG("video_subtitle_file_set not implemented for gstreamer yet.");
+}
+
+static const char *
+em_video_subtitle_file_get(void *video __UNUSED__)
+{
+   DBG("video_subtitle_file_get not implemented for gstreamer yet.");
+   return NULL;
+}
+
 static const char *
 em_video_channel_name_get(void *video __UNUSED__,
                           int   channel __UNUSED__)