diff options
author | Cedric BAIL <cedric@osg.samsung.com> | 2016-06-01 11:32:15 -0700 |
---|---|---|
committer | Tom Hacohen <tom@stosb.com> | 2016-06-02 11:35:05 +0100 |
commit | 36f15d761a2d39fc81c38a9db7b13d1d571ef453 (patch) | |
tree | d2e5da2b9b7d7974c59a23ad866b49632c1809a9 | |
parent | e649307d92325862f1f5fdad5c8e94cfd0cd2f71 (diff) |
emotion: integrate generic legacy vlc support in the build system.
-rw-r--r-- | AUTHORS | 21 | ||||
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | legacy/emotion_generic_players/AUTHORS | 20 | ||||
-rw-r--r-- | m4/emotion_generic_players.m4 | 37 | ||||
-rw-r--r-- | src/Makefile_Emotion.am | 21 | ||||
-rw-r--r-- | src/generic/emotion/vlc/emotion_generic_vlc.c | 790 |
6 files changed, 873 insertions, 21 deletions
@@ -344,6 +344,27 @@ Leandro Dorileo <dorileo@profusion.mobi> | |||
344 | Michael Bouchaud (yoz) <yoz@efl.so> | 344 | Michael Bouchaud (yoz) <yoz@efl.so> |
345 | Aymeric Dumaz <aymeric.dumaz@gmail.com> | 345 | Aymeric Dumaz <aymeric.dumaz@gmail.com> |
346 | 346 | ||
347 | Emotion Generic VLC | ||
348 | --- | ||
349 | Cedric Bail <cedric.bail@free.fr> | ||
350 | Hugo Camboulive <hugo.camboulive@zodiacaerospace.com> | ||
351 | Leandro Dorileo <dorileo@profusion.mobi> | ||
352 | Pierre Le Magourou <pierre.lemagourou@openwide.fr> | ||
353 | Rafael Antognolli <antognolli@profusion.mobi> | ||
354 | Sohyun Kim <anna1014.kim@samsung.com> | ||
355 | Carsten Haitzler (Rasterman) <raster@rasterman.com> | ||
356 | Davide Andreoli <dave@gurumeditation.it> | ||
357 | Gustavo Sverzut Barbieri <barbieri@gmail.com> | ||
358 | Stefan Schmidt <s.schmidt@samsung.com> | ||
359 | Bruno Dilly <bdilly@profusion.mobi> | ||
360 | ChunEon Park <hermet@hermet.pe.kr> | ||
361 | Daniel Juyung Seo <juyung.seo@samsung.com> | ||
362 | Doug Newgard <scimmia22@outlook.com> | ||
363 | Jerome Pinot <ngc891@gmail.com> | ||
364 | Mike Blumenkrantz <zmike@samsung.com> | ||
365 | Sebastian Dransfeld <sd@tango.flipp.net> | ||
366 | Vincent Torri <vincent.torri@gmail.com> | ||
367 | |||
347 | Ethumb | 368 | Ethumb |
348 | ------ | 369 | ------ |
349 | Rafael Antognolli <antognolli@profusion.mobi> | 370 | Rafael Antognolli <antognolli@profusion.mobi> |
diff --git a/configure.ac b/configure.ac index 875968d833..1f70416ca5 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -4902,10 +4902,13 @@ fi | |||
4902 | 4902 | ||
4903 | ### Check availability | 4903 | ### Check availability |
4904 | 4904 | ||
4905 | ## Generic player | ||
4906 | EMOTION_GENERIC_PLAYER([GENERIC_VLC], [yes], [libvlc >= 2.0 eina >= 1.1.99 ecore >= 1.7.99]) | ||
4907 | EFL_ADD_FEATURE([EMOTION], [generic_vlc], [${with_generic_vlc}]) | ||
4908 | |||
4905 | EFL_LIB_END([Emotion]) | 4909 | EFL_LIB_END([Emotion]) |
4906 | #### End of Emotion | 4910 | #### End of Emotion |
4907 | 4911 | ||
4908 | |||
4909 | #### Ethumb | 4912 | #### Ethumb |
4910 | EFL_LIB_START([Ethumb]) | 4913 | EFL_LIB_START([Ethumb]) |
4911 | 4914 | ||
diff --git a/legacy/emotion_generic_players/AUTHORS b/legacy/emotion_generic_players/AUTHORS deleted file mode 100644 index e7965e98cb..0000000000 --- a/legacy/emotion_generic_players/AUTHORS +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | VLC | ||
2 | --- | ||
3 | Cedric Bail <cedric.bail@free.fr> | ||
4 | Hugo Camboulive <hugo.camboulive@zodiacaerospace.com> | ||
5 | Leandro Dorileo <dorileo@profusion.mobi> | ||
6 | Pierre Le Magourou <pierre.lemagourou@openwide.fr> | ||
7 | Rafael Antognolli <antognolli@profusion.mobi> | ||
8 | Sohyun Kim <anna1014.kim@samsung.com> | ||
9 | Carsten Haitzler (Rasterman) <raster@rasterman.com> | ||
10 | Davide Andreoli <dave@gurumeditation.it> | ||
11 | Gustavo Sverzut Barbieri <barbieri@gmail.com> | ||
12 | Stefan Schmidt <s.schmidt@samsung.com> | ||
13 | Bruno Dilly <bdilly@profusion.mobi> | ||
14 | ChunEon Park <hermet@hermet.pe.kr> | ||
15 | Daniel Juyung Seo <juyung.seo@samsung.com> | ||
16 | Doug Newgard <scimmia22@outlook.com> | ||
17 | Jerome Pinot <ngc891@gmail.com> | ||
18 | Mike Blumenkrantz <zmike@samsung.com> | ||
19 | Sebastian Dransfeld <sd@tango.flipp.net> | ||
20 | Vincent Torri <vincent.torri@gmail.com> | ||
diff --git a/m4/emotion_generic_players.m4 b/m4/emotion_generic_players.m4 new file mode 100644 index 0000000000..d852dbaa29 --- /dev/null +++ b/m4/emotion_generic_players.m4 | |||
@@ -0,0 +1,37 @@ | |||
1 | dnl EMOTION_GENERIC_PLAYER(NAME, DEFAULT_STATE, [PKG_CONFIG_DEPS]) | ||
2 | dnl Does the following: | ||
3 | dnl * AC_ARG_WITH(NAME) | ||
4 | dnl * define with_name to yes or no | ||
5 | dnl * PKG_CHECK_MODULES(NAME, PKG_CONFIG_DEPS) | ||
6 | dnl * AC_DEFINE([HAVE_NAME]) | ||
7 | dnl * AM_CONDITIONAL([HAVE_NAME]) | ||
8 | AC_DEFUN([EMOTION_GENERIC_PLAYER], | ||
9 | [dnl | ||
10 | m4_pushdef([DOWN], m4_translit([$1], [-A-Z], [_a-z]))dnl | ||
11 | m4_pushdef([UP], m4_translit([$1], [-a-z], [_A-Z]))dnl | ||
12 | |||
13 | AC_ARG_WITH([DOWN], | ||
14 | [AC_HELP_STRING([--with-]m4_defn([DOWN]), | ||
15 | [build generic player ]m4_defn([UP])[. @<:@default=$2@:>@])], | ||
16 | [], [with_]m4_defn([DOWN])[="$2"]) | ||
17 | |||
18 | if test "${with_[]m4_defn([DOWN])}" = "yes"; then | ||
19 | m4_ifval([$3], [dnl | ||
20 | PKG_CHECK_MODULES(m4_defn([UP]), [$3]) | ||
21 | ], [dnl | ||
22 | m4_defn([UP])_LIBS="${m4_defn([UP])_LIBS}" | ||
23 | m4_defn([UP])_CFLAGS="${m4_defn([UP])_CFLAGS}" | ||
24 | AC_SUBST(m4_defn([UP])[_LIBS]) | ||
25 | AC_SUBST(m4_defn([UP])[_CFLAGS]) | ||
26 | ]) | ||
27 | |||
28 | AC_SEARCH_LIBS([shm_open], [rt], [], [AC_MSG_ERROR([unable to find the shm_open() function])]) | ||
29 | if test "${ac_cv_search_shm_open}" != "none required"; then | ||
30 | m4_defn([UP])_LIBS="${m4_defn([UP])_LIBS} ${ac_cv_search_shm_open}" | ||
31 | fi | ||
32 | fi | ||
33 | AM_CONDITIONAL([HAVE_]m4_defn([UP]), [test "$with_[]m4_defn([DOWN])" = "yes"]) | ||
34 | |||
35 | m4_popdef([UP])dnl | ||
36 | m4_popdef([DOWN])dnl | ||
37 | ]) | ||
diff --git a/src/Makefile_Emotion.am b/src/Makefile_Emotion.am index 87285a8e0d..1175d2baf4 100644 --- a/src/Makefile_Emotion.am +++ b/src/Makefile_Emotion.am | |||
@@ -354,3 +354,24 @@ CLEANFILES += $(generated_emotion_js_bindings) | |||
354 | GENERATED_JS_BINDINGS += $(generated_emotion_js_bindings) | 354 | GENERATED_JS_BINDINGS += $(generated_emotion_js_bindings) |
355 | 355 | ||
356 | endif | 356 | endif |
357 | |||
358 | emotiongenericplayersdir = \ | ||
359 | $(libdir)/emotion/generic_players/$(MODULE_ARCH) | ||
360 | |||
361 | emotiongenericplayers_PROGRAMS = | ||
362 | |||
363 | if HAVE_GENERIC_VLC | ||
364 | |||
365 | emotiongenericplayers_PROGRAMS += generic/emotion/vlc/vlc | ||
366 | generic_emotion_vlc_vlc_SOURCES = generic/emotion/vlc/emotion_generic_vlc.c | ||
367 | generic_emotion_vlc_vlc_CPPFLAGS = \ | ||
368 | -I$(top_srcdir)/src/modules/emotion/generic \ | ||
369 | -DPACKAGE_BIN_DIR=\"$(bindir)\" \ | ||
370 | -DPACKAGE_LIB_DIR=\"$(libdir)\" \ | ||
371 | -DPACKAGE_DATA_DIR=\"$(datadir)/emotion\" \ | ||
372 | -DPACKAGE_BUILD_DIR=\"$(abs_top_builddir)\" \ | ||
373 | -DEMOTION_GENERIC_PLAYERS_DIR=\"$(libdir)/emotion/generic_players/$(MODULE_ARCH)\" \ | ||
374 | @GENERIC_VLC_CFLAGS@ | ||
375 | generic_emotion_vlc_vlc_LDADD = @GENERIC_VLC_LIBS@ | ||
376 | |||
377 | endif | ||
diff --git a/src/generic/emotion/vlc/emotion_generic_vlc.c b/src/generic/emotion/vlc/emotion_generic_vlc.c new file mode 100644 index 0000000000..456509e673 --- /dev/null +++ b/src/generic/emotion/vlc/emotion_generic_vlc.c | |||
@@ -0,0 +1,790 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif | ||
4 | |||
5 | #include <errno.h> | ||
6 | #include <limits.h> | ||
7 | #include <stdio.h> | ||
8 | #include <stdlib.h> | ||
9 | #include <unistd.h> | ||
10 | #include <string.h> | ||
11 | #include <sys/mman.h> | ||
12 | #include <sys/stat.h> | ||
13 | #include <fcntl.h> | ||
14 | #include <pthread.h> | ||
15 | #include <poll.h> | ||
16 | |||
17 | #include <signal.h> | ||
18 | |||
19 | #include <vlc/vlc.h> | ||
20 | |||
21 | #include <Emotion_Generic_Plugin.h> | ||
22 | #include <Eina.h> | ||
23 | #include <Ecore.h> | ||
24 | |||
25 | static int _em_vlc_log_dom = -1; | ||
26 | #define ERR(...) EINA_LOG_DOM_ERR(_em_vlc_log_dom, __VA_ARGS__) | ||
27 | #define DBG(...) EINA_LOG_DOM_DBG(_em_vlc_log_dom, __VA_ARGS__) | ||
28 | #define INF(...) EINA_LOG_DOM_INFO(_em_vlc_log_dom, __VA_ARGS__) | ||
29 | #define WRN(...) EINA_LOG_DOM_WARN(_em_vlc_log_dom, __VA_ARGS__) | ||
30 | #define CRIT(...) EINA_LOG_DOM_CRIT(_em_vlc_log_dom, __VA_ARGS__) | ||
31 | |||
32 | |||
33 | typedef struct _App App; | ||
34 | struct _App { | ||
35 | Emotion_Generic_Video_Shared *vs; | ||
36 | Emotion_Generic_Video_Frame vf; | ||
37 | |||
38 | libvlc_instance_t *libvlc; | ||
39 | libvlc_media_t *m; | ||
40 | libvlc_media_player_t *mp; | ||
41 | libvlc_event_manager_t *event_mgr; | ||
42 | |||
43 | Ecore_Pipe *fd_read; // read commands from emotion here | ||
44 | Ecore_Pipe *fd_write; // write commands for emotion here | ||
45 | Eina_Lock cmd_mutex;// lock used to send just one command at a time | ||
46 | int last_order; // current command received from emotion | ||
47 | |||
48 | char *filename; | ||
49 | char *subtitle_path; | ||
50 | char *shmname; | ||
51 | unsigned w, h; | ||
52 | int volume; | ||
53 | Eina_Bool audio_muted; | ||
54 | |||
55 | Eina_Bool opening; | ||
56 | Eina_Bool closing; | ||
57 | Eina_Bool playing; | ||
58 | Eina_Bool inited; | ||
59 | }; | ||
60 | |||
61 | static void _player_setup(App *app); | ||
62 | |||
63 | |||
64 | /* Utilities to send commands back to emotion */ | ||
65 | #define SEND_CMD_PARAM(app, i) \ | ||
66 | if ((app)->fd_write) \ | ||
67 | if (!ecore_pipe_write((app)->fd_write, &(i), sizeof((i)))) \ | ||
68 | ecore_main_loop_quit(); | ||
69 | |||
70 | static void | ||
71 | _send_cmd(App *app, int cmd) | ||
72 | { | ||
73 | if (!app->fd_write) | ||
74 | return; | ||
75 | |||
76 | eina_lock_take(&app->cmd_mutex); /* LOCK HERE */ | ||
77 | |||
78 | if (!ecore_pipe_write(app->fd_write, &cmd, sizeof(cmd))) | ||
79 | ecore_main_loop_quit(); | ||
80 | } | ||
81 | |||
82 | static void | ||
83 | _send_cmd_str(App *app, const char *str) | ||
84 | { | ||
85 | int len; | ||
86 | |||
87 | len = str ? strlen(str) + 1 : 0; | ||
88 | if (app->fd_write) | ||
89 | if (!ecore_pipe_write(app->fd_write, &len, sizeof(len))) | ||
90 | ecore_main_loop_quit(); | ||
91 | if (app->fd_write) | ||
92 | if (!ecore_pipe_write(app->fd_write, str, len)) | ||
93 | ecore_main_loop_quit(); | ||
94 | } | ||
95 | |||
96 | static void | ||
97 | _send_cmd_finish(App *app) | ||
98 | { | ||
99 | eina_lock_release(&app->cmd_mutex); /* UNLOCK HERE */ | ||
100 | } | ||
101 | |||
102 | /* Commands sent to the emotion pipe */ | ||
103 | static void | ||
104 | _send_file_closed(App *app) | ||
105 | { | ||
106 | _send_cmd(app, EM_RESULT_FILE_CLOSE); | ||
107 | _send_cmd_finish(app); | ||
108 | } | ||
109 | |||
110 | static void | ||
111 | _send_time_changed(App *app) | ||
112 | { | ||
113 | float new_time; | ||
114 | |||
115 | if (app->vs->frame_drop > 1) | ||
116 | return; | ||
117 | |||
118 | new_time = libvlc_media_player_get_time(app->mp); | ||
119 | new_time /= 1000; | ||
120 | _send_cmd(app, EM_RESULT_POSITION_CHANGED); | ||
121 | SEND_CMD_PARAM(app, new_time); | ||
122 | _send_cmd_finish(app); | ||
123 | } | ||
124 | |||
125 | static void | ||
126 | _send_resize(App *app, int width, int height) | ||
127 | { | ||
128 | _send_cmd(app, EM_RESULT_FRAME_SIZE); | ||
129 | SEND_CMD_PARAM(app, width); | ||
130 | SEND_CMD_PARAM(app, height); | ||
131 | _send_cmd_finish(app); | ||
132 | } | ||
133 | |||
134 | static void | ||
135 | _send_track_info(App *app, int cmd, int current, int count, libvlc_track_description_t *desc) | ||
136 | { | ||
137 | _send_cmd(app, cmd); | ||
138 | SEND_CMD_PARAM(app, current); | ||
139 | SEND_CMD_PARAM(app, count); | ||
140 | while (desc) | ||
141 | { | ||
142 | int tid = desc->i_id; | ||
143 | const char *name = desc->psz_name; | ||
144 | SEND_CMD_PARAM(app, tid); | ||
145 | _send_cmd_str(app, name); | ||
146 | desc = desc->p_next; | ||
147 | } | ||
148 | _send_cmd_finish(app); | ||
149 | } | ||
150 | |||
151 | static void | ||
152 | _send_all_track_info(App *app) | ||
153 | { | ||
154 | int track_count, current; | ||
155 | libvlc_track_description_t *desc; | ||
156 | |||
157 | current = libvlc_audio_get_track(app->mp); | ||
158 | track_count = libvlc_audio_get_track_count(app->mp); | ||
159 | desc = libvlc_audio_get_track_description(app->mp); | ||
160 | |||
161 | _send_track_info(app, EM_RESULT_AUDIO_TRACK_INFO, | ||
162 | current, track_count, desc); | ||
163 | |||
164 | current = libvlc_video_get_track(app->mp); | ||
165 | track_count = libvlc_video_get_track_count(app->mp); | ||
166 | desc = libvlc_video_get_track_description(app->mp); | ||
167 | |||
168 | _send_track_info(app, EM_RESULT_VIDEO_TRACK_INFO, | ||
169 | current, track_count, desc); | ||
170 | |||
171 | current = libvlc_video_get_spu(app->mp); | ||
172 | track_count = libvlc_video_get_spu_count(app->mp); | ||
173 | desc = libvlc_video_get_spu_description(app->mp); | ||
174 | |||
175 | _send_track_info(app, EM_RESULT_SPU_TRACK_INFO, | ||
176 | current, track_count, desc); | ||
177 | } | ||
178 | |||
179 | static void | ||
180 | _send_all_meta_info(App *app) | ||
181 | { | ||
182 | const char *meta; | ||
183 | |||
184 | _send_cmd(app, EM_RESULT_META_INFO); | ||
185 | |||
186 | /* | ||
187 | * Will send in this order: title, artist, album, year, | ||
188 | * genre, comments, disc id and track count. | ||
189 | */ | ||
190 | meta = libvlc_media_get_meta(app->m, libvlc_meta_Title); | ||
191 | _send_cmd_str(app, meta); | ||
192 | meta = libvlc_media_get_meta(app->m, libvlc_meta_Artist); | ||
193 | _send_cmd_str(app, meta); | ||
194 | meta = libvlc_media_get_meta(app->m, libvlc_meta_Album); | ||
195 | _send_cmd_str(app, meta); | ||
196 | meta = libvlc_media_get_meta(app->m, libvlc_meta_Date); | ||
197 | _send_cmd_str(app, meta); | ||
198 | meta = libvlc_media_get_meta(app->m, libvlc_meta_Genre); | ||
199 | _send_cmd_str(app, meta); | ||
200 | meta = NULL; // sending empty comments | ||
201 | _send_cmd_str(app, meta); | ||
202 | meta = NULL; // sending empty disc id | ||
203 | _send_cmd_str(app, meta); | ||
204 | meta = libvlc_media_get_meta(app->m, libvlc_meta_TrackNumber); | ||
205 | _send_cmd_str(app, meta); | ||
206 | |||
207 | _send_cmd_finish(app); | ||
208 | } | ||
209 | |||
210 | static void | ||
211 | _send_length_changed(App *app) | ||
212 | { | ||
213 | float length = libvlc_media_player_get_length(app->mp); | ||
214 | |||
215 | length /= 1000; | ||
216 | _send_cmd(app, EM_RESULT_LENGTH_CHANGED); | ||
217 | SEND_CMD_PARAM(app, length); | ||
218 | _send_cmd_finish(app); | ||
219 | } | ||
220 | |||
221 | static void | ||
222 | _send_seekable_changed(App *app, const struct libvlc_event_t *ev) | ||
223 | { | ||
224 | int seekable = ev->u.media_player_seekable_changed.new_seekable; | ||
225 | |||
226 | _send_cmd(app, EM_RESULT_SEEKABLE_CHANGED); | ||
227 | SEND_CMD_PARAM(app, seekable); | ||
228 | _send_cmd_finish(app); | ||
229 | } | ||
230 | |||
231 | static void | ||
232 | _send_playback_started(App *app) | ||
233 | { | ||
234 | _send_cmd(app, EM_RESULT_PLAYBACK_STARTED); | ||
235 | _send_cmd_finish(app); | ||
236 | } | ||
237 | |||
238 | static void | ||
239 | _send_playback_stopped(App *app) | ||
240 | { | ||
241 | _send_cmd(app, EM_RESULT_PLAYBACK_STOPPED); | ||
242 | _send_cmd_finish(app); | ||
243 | } | ||
244 | |||
245 | static void | ||
246 | _send_init(App *app) | ||
247 | { | ||
248 | _send_cmd(app, EM_RESULT_INIT); | ||
249 | _send_cmd_finish(app); | ||
250 | } | ||
251 | |||
252 | static void | ||
253 | _send_file_set(App *app) | ||
254 | { | ||
255 | _send_cmd(app, EM_RESULT_FILE_SET); | ||
256 | _send_cmd_finish(app); | ||
257 | } | ||
258 | |||
259 | static void | ||
260 | _send_file_set_done(App *app, int success) | ||
261 | { | ||
262 | _send_cmd(app, EM_RESULT_FILE_SET_DONE); | ||
263 | SEND_CMD_PARAM(app, success); | ||
264 | _send_cmd_finish(app); | ||
265 | } | ||
266 | |||
267 | |||
268 | /* VLC events and callbacks */ | ||
269 | static void | ||
270 | _event_cb(const struct libvlc_event_t *ev, void *data) | ||
271 | { | ||
272 | App *app = data; | ||
273 | |||
274 | ecore_thread_main_loop_begin(); | ||
275 | switch (ev->type) | ||
276 | { | ||
277 | case libvlc_MediaPlayerTimeChanged: | ||
278 | // DBG("libvlc_MediaPlayerTimeChanged"); | ||
279 | _send_time_changed(app); | ||
280 | break; | ||
281 | case libvlc_MediaPlayerLengthChanged: | ||
282 | DBG("libvlc_MediaPlayerLengthChanged"); | ||
283 | _send_length_changed(app); | ||
284 | break; | ||
285 | case libvlc_MediaPlayerSeekableChanged: | ||
286 | DBG("libvlc_MediaPlayerSeekableChanged"); | ||
287 | _send_seekable_changed(app, ev); | ||
288 | break; | ||
289 | case libvlc_MediaPlayerPlaying: | ||
290 | DBG("libvlc_MediaPlayerPlaying"); | ||
291 | libvlc_audio_set_volume(app->mp, app->volume); | ||
292 | libvlc_audio_set_mute(app->mp, app->audio_muted); | ||
293 | _send_playback_started(app); | ||
294 | break; | ||
295 | case libvlc_MediaPlayerStopped: | ||
296 | DBG("libvlc_MediaPlayerStopped"); | ||
297 | _send_playback_stopped(app); | ||
298 | if (app->closing) | ||
299 | { | ||
300 | free(app->filename); | ||
301 | app->filename = NULL; | ||
302 | free(app->subtitle_path); | ||
303 | app->subtitle_path = NULL; | ||
304 | libvlc_media_release(app->m); | ||
305 | app->m = NULL; | ||
306 | libvlc_media_player_release(app->mp); | ||
307 | app->mp = NULL; | ||
308 | emotion_generic_shm_free(app->vs); | ||
309 | app->playing = EINA_FALSE; | ||
310 | app->closing = EINA_FALSE; | ||
311 | _send_file_closed(app); | ||
312 | } | ||
313 | break; | ||
314 | case libvlc_MediaPlayerEndReached: | ||
315 | DBG("libvlc_MediaPlayerEndReached"); | ||
316 | app->playing = EINA_FALSE; | ||
317 | /* vlc had released the media_playere here, we create a new one */ | ||
318 | app->mp = libvlc_media_player_new_from_media(app->m); | ||
319 | _player_setup(app); | ||
320 | _send_playback_stopped(app); | ||
321 | break; | ||
322 | } | ||
323 | ecore_thread_main_loop_end(); | ||
324 | } | ||
325 | |||
326 | static void | ||
327 | _tmp_playing_event_cb(const struct libvlc_event_t *ev, void *data) | ||
328 | { | ||
329 | App *app = data; | ||
330 | |||
331 | if (ev->type != libvlc_MediaPlayerPlaying) | ||
332 | return; | ||
333 | |||
334 | /* pause and stop listening the temporary event */ | ||
335 | libvlc_event_detach(app->event_mgr,libvlc_MediaPlayerPlaying, | ||
336 | _tmp_playing_event_cb, app); | ||
337 | libvlc_media_player_set_pause(app->mp, 1); | ||
338 | |||
339 | /* sending size info */ | ||
340 | libvlc_video_get_size(app->mp, 0, &app->w, &app->h); | ||
341 | _send_resize(app, app->w, app->h); | ||
342 | |||
343 | /* sending total lenght */ | ||
344 | _send_length_changed(app); | ||
345 | |||
346 | /* sending audio track info */ | ||
347 | _send_all_track_info(app); | ||
348 | |||
349 | /* sending meta info */ | ||
350 | _send_all_meta_info(app); | ||
351 | |||
352 | /* ok, we are done! Now let emotion create the shmem for us */ | ||
353 | _send_file_set(app); | ||
354 | } | ||
355 | |||
356 | static void * | ||
357 | _lock(void *data, void **pixels) | ||
358 | { | ||
359 | App *app = data; | ||
360 | |||
361 | if (app->playing) | ||
362 | *pixels = app->vf.frames[app->vs->frame.player]; | ||
363 | else | ||
364 | *pixels = NULL; | ||
365 | |||
366 | return NULL; // picture identifier, not needed here | ||
367 | } | ||
368 | |||
369 | static void | ||
370 | _unlock(void *data EINA_UNUSED, void *id EINA_UNUSED, void *const *pixels EINA_UNUSED) | ||
371 | { | ||
372 | } | ||
373 | |||
374 | static void | ||
375 | _display(void *data, void *id EINA_UNUSED) | ||
376 | { | ||
377 | App *app = data; | ||
378 | |||
379 | if (!app->playing) | ||
380 | return; | ||
381 | |||
382 | eina_semaphore_lock(&app->vs->lock); | ||
383 | app->vs->frame.last = app->vs->frame.player; | ||
384 | app->vs->frame.player = app->vs->frame.next; | ||
385 | app->vs->frame.next = app->vs->frame.last; | ||
386 | if (!app->vs->frame_drop++) | ||
387 | { | ||
388 | _send_cmd(app, EM_RESULT_FRAME_NEW); | ||
389 | _send_cmd_finish(app); | ||
390 | } | ||
391 | eina_semaphore_release(&app->vs->lock, 1); | ||
392 | } | ||
393 | |||
394 | static void | ||
395 | _player_setup(App *app) | ||
396 | { | ||
397 | |||
398 | libvlc_video_set_format(app->mp, "RV32", app->w, app->h, app->w * 4); | ||
399 | libvlc_video_set_callbacks(app->mp, _lock, _unlock, _display, app); | ||
400 | |||
401 | app->event_mgr = libvlc_media_player_event_manager(app->mp); | ||
402 | libvlc_event_attach(app->event_mgr, libvlc_MediaPlayerPlaying, | ||
403 | _event_cb, app); | ||
404 | libvlc_event_attach(app->event_mgr, libvlc_MediaPlayerTimeChanged, | ||
405 | _event_cb, app); | ||
406 | libvlc_event_attach(app->event_mgr, libvlc_MediaPlayerLengthChanged, | ||
407 | _event_cb, app); | ||
408 | libvlc_event_attach(app->event_mgr, libvlc_MediaPlayerSeekableChanged, | ||
409 | _event_cb, app); | ||
410 | libvlc_event_attach(app->event_mgr, libvlc_MediaPlayerEndReached, | ||
411 | _event_cb, app); | ||
412 | libvlc_event_attach(app->event_mgr, libvlc_MediaPlayerStopped, | ||
413 | _event_cb, app); | ||
414 | } | ||
415 | |||
416 | /* Commands received from the emotion pipe */ | ||
417 | static void | ||
418 | _file_set(App *app) | ||
419 | { | ||
420 | DBG("Path: %s", app->filename); | ||
421 | app->m = libvlc_media_new_path(app->libvlc, app->filename); | ||
422 | if (!app->m) | ||
423 | { | ||
424 | ERR("could not open path: \"%s\"", app->filename); | ||
425 | return; | ||
426 | } | ||
427 | |||
428 | app->mp = libvlc_media_player_new_from_media(app->m); | ||
429 | if (!app->mp) | ||
430 | { | ||
431 | ERR("could not create new player from media."); | ||
432 | return; | ||
433 | } | ||
434 | |||
435 | app->opening = EINA_TRUE; | ||
436 | |||
437 | /* Here we start playing and connect a temporary callback to know when | ||
438 | * the file is parsed and ready to be played for real. | ||
439 | */ | ||
440 | app->event_mgr = libvlc_media_player_event_manager(app->mp); | ||
441 | libvlc_event_attach(app->event_mgr, libvlc_MediaPlayerPlaying, | ||
442 | _tmp_playing_event_cb, app); | ||
443 | |||
444 | libvlc_media_player_play(app->mp); | ||
445 | } | ||
446 | |||
447 | static void | ||
448 | _file_set_done(App *app) | ||
449 | { | ||
450 | int r; | ||
451 | |||
452 | DBG("Path: %s", app->filename); | ||
453 | app->opening = EINA_FALSE; | ||
454 | |||
455 | r = emotion_generic_shm_get(app->shmname, &app->vs, &app->vf); | ||
456 | if (!r) | ||
457 | { | ||
458 | free(app->filename); | ||
459 | libvlc_media_release(app->m); | ||
460 | libvlc_media_player_release(app->mp); | ||
461 | app->filename = NULL; | ||
462 | app->m = NULL; | ||
463 | app->mp = NULL; | ||
464 | } | ||
465 | else | ||
466 | { | ||
467 | _player_setup(app); | ||
468 | } | ||
469 | |||
470 | _send_file_set_done(app, r); | ||
471 | } | ||
472 | |||
473 | static void | ||
474 | _file_close(App *app) | ||
475 | { | ||
476 | DBG("closing file"); | ||
477 | |||
478 | if (!app->mp) | ||
479 | return; | ||
480 | |||
481 | app->closing = EINA_TRUE; | ||
482 | libvlc_media_player_stop(app->mp); | ||
483 | } | ||
484 | |||
485 | static void | ||
486 | _stop(App *app) | ||
487 | { | ||
488 | DBG("Stop"); | ||
489 | if (app->mp) | ||
490 | libvlc_media_player_set_pause(app->mp, 1); | ||
491 | } | ||
492 | |||
493 | static void | ||
494 | _play(App *app, float pos) | ||
495 | { | ||
496 | DBG("Play at %.3f", pos); | ||
497 | |||
498 | if (!app->mp) | ||
499 | return; | ||
500 | |||
501 | if (app->playing) | ||
502 | { | ||
503 | libvlc_media_player_set_pause(app->mp, 0); | ||
504 | } | ||
505 | else | ||
506 | { | ||
507 | libvlc_time_t new_time = pos * 1000; | ||
508 | libvlc_media_player_set_time(app->mp, new_time); | ||
509 | libvlc_media_player_play(app->mp); | ||
510 | |||
511 | if (app->subtitle_path) | ||
512 | libvlc_video_set_subtitle_file(app->mp, app->subtitle_path); | ||
513 | |||
514 | app->playing = EINA_TRUE; | ||
515 | } | ||
516 | } | ||
517 | |||
518 | static void | ||
519 | _position_set(App *app, float position) | ||
520 | { | ||
521 | libvlc_time_t new_time; | ||
522 | |||
523 | DBG("Position set %.3f", position); | ||
524 | if (!app->mp) | ||
525 | return; | ||
526 | |||
527 | new_time = position * 1000; | ||
528 | libvlc_media_player_set_time(app->mp, new_time); | ||
529 | |||
530 | if (libvlc_media_player_get_state(app->mp) == libvlc_Paused) | ||
531 | _send_time_changed(app); | ||
532 | } | ||
533 | |||
534 | static void | ||
535 | _speed_set(App *app, float rate) | ||
536 | { | ||
537 | DBG("Speed set %.3f", rate); | ||
538 | if (!app->mp) | ||
539 | return; | ||
540 | |||
541 | libvlc_media_player_set_rate(app->mp, rate); | ||
542 | } | ||
543 | |||
544 | static void | ||
545 | _mute_set(App *app, int mute) | ||
546 | { | ||
547 | DBG("Mute %d", mute); | ||
548 | if (!app->mp) | ||
549 | return; | ||
550 | |||
551 | app->audio_muted = mute; | ||
552 | libvlc_audio_set_mute(app->mp, mute); | ||
553 | } | ||
554 | |||
555 | static void | ||
556 | _volume_set(App *app, float volume) | ||
557 | { | ||
558 | DBG("Volume set %.2f", volume); | ||
559 | if (!app->mp) | ||
560 | return; | ||
561 | |||
562 | app->volume = volume * 100; | ||
563 | libvlc_audio_set_volume(app->mp, app->volume); | ||
564 | } | ||
565 | |||
566 | static void | ||
567 | _spu_track_set(App *app, int track) | ||
568 | { | ||
569 | DBG("SPU track %d", track); | ||
570 | libvlc_video_set_spu(app->mp, track); | ||
571 | } | ||
572 | |||
573 | static void | ||
574 | _audio_track_set(App *app, int track) | ||
575 | { | ||
576 | DBG("Audio track %d", track); | ||
577 | libvlc_audio_set_track(app->mp, track); | ||
578 | } | ||
579 | |||
580 | static void | ||
581 | _video_track_set(App *app, int track) | ||
582 | { | ||
583 | DBG("Video Track %d", track); | ||
584 | libvlc_video_set_track(app->mp, track); | ||
585 | } | ||
586 | |||
587 | static void | ||
588 | _remote_command(void *data, void *buffer, unsigned int nbyte) | ||
589 | { | ||
590 | App *app = data; | ||
591 | |||
592 | if (nbyte == 0) | ||
593 | { | ||
594 | ecore_main_loop_quit(); | ||
595 | return ; | ||
596 | } | ||
597 | |||
598 | if (app->last_order == EM_CMD_LAST) | ||
599 | { | ||
600 | if (nbyte != sizeof (int)) | ||
601 | { | ||
602 | ERR("didn't receive a valid command from emotion (%i) !", nbyte); | ||
603 | ecore_main_loop_quit(); | ||
604 | return ; | ||
605 | } | ||
606 | |||
607 | app->last_order = *((int*) buffer); | ||
608 | |||
609 | if (!app->inited && | ||
610 | app->last_order != EM_CMD_INIT) | ||
611 | { | ||
612 | ERR("wrong init command!"); | ||
613 | ecore_main_loop_quit(); | ||
614 | return ; | ||
615 | } | ||
616 | |||
617 | switch (app->last_order) | ||
618 | { | ||
619 | case EM_CMD_FILE_SET: | ||
620 | if (app->opening) | ||
621 | { | ||
622 | libvlc_media_release(app->m); | ||
623 | libvlc_media_player_release(app->mp); | ||
624 | free(app->filename); | ||
625 | app->opening = EINA_FALSE; | ||
626 | } | ||
627 | break; | ||
628 | case EM_CMD_FILE_SET_DONE: | ||
629 | _file_set_done(app); | ||
630 | app->last_order = EM_CMD_LAST; | ||
631 | break; | ||
632 | case EM_CMD_FILE_CLOSE: | ||
633 | _file_close(app); | ||
634 | app->last_order = EM_CMD_LAST; | ||
635 | break; | ||
636 | case EM_CMD_STOP: | ||
637 | _stop(app); | ||
638 | app->last_order = EM_CMD_LAST; | ||
639 | break; | ||
640 | } | ||
641 | } | ||
642 | else | ||
643 | { | ||
644 | switch (app->last_order) | ||
645 | { | ||
646 | case EM_CMD_INIT: | ||
647 | app->shmname = strdup(buffer); | ||
648 | app->inited = EINA_TRUE; | ||
649 | _send_init(app); | ||
650 | break; | ||
651 | case EM_CMD_FILE_SET: | ||
652 | app->filename = strdup(buffer); | ||
653 | _file_set(app); | ||
654 | break; | ||
655 | case EM_CMD_SUBTITLE_SET: | ||
656 | app->subtitle_path = strdup(buffer); | ||
657 | break; | ||
658 | case EM_CMD_PLAY: | ||
659 | _play(app, *(float*) buffer); | ||
660 | break; | ||
661 | case EM_CMD_POSITION_SET: | ||
662 | _position_set(app, *(float*) buffer); | ||
663 | break; | ||
664 | case EM_CMD_SPEED_SET: | ||
665 | _speed_set(app, *(float*) buffer); | ||
666 | break; | ||
667 | case EM_CMD_AUDIO_MUTE_SET: | ||
668 | _mute_set(app, *(int*) buffer); | ||
669 | break; | ||
670 | case EM_CMD_VOLUME_SET: | ||
671 | _volume_set(app, *(float*) buffer); | ||
672 | break; | ||
673 | case EM_CMD_SPU_TRACK_SET: | ||
674 | _spu_track_set(app, *(int*) buffer); | ||
675 | break; | ||
676 | case EM_CMD_AUDIO_TRACK_SET: | ||
677 | _audio_track_set(app, *(int*) buffer); | ||
678 | break; | ||
679 | case EM_CMD_VIDEO_TRACK_SET: | ||
680 | _video_track_set(app, *(int*) buffer); | ||
681 | break; | ||
682 | } | ||
683 | app->last_order = EM_CMD_LAST; | ||
684 | } | ||
685 | } | ||
686 | |||
687 | static void | ||
688 | _dummy(void *data EINA_UNUSED, void *buffer EINA_UNUSED, unsigned int nbyte EINA_UNUSED) | ||
689 | { | ||
690 | /* This function is useless for the pipe we use to send message back | ||
691 | to emotion, but still needed */ | ||
692 | } | ||
693 | |||
694 | /* Main */ | ||
695 | static Eina_Bool | ||
696 | exit_func(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev EINA_UNUSED) | ||
697 | { | ||
698 | DBG("Quit signal received !"); | ||
699 | ecore_main_loop_quit(); | ||
700 | return EINA_TRUE; | ||
701 | } | ||
702 | |||
703 | int | ||
704 | main(int argc, const char *argv[]) | ||
705 | { | ||
706 | App app; | ||
707 | Ecore_Event_Handler *hld; | ||
708 | int vlc_argc; | ||
709 | |||
710 | const char *vlc_argv[] = | ||
711 | { | ||
712 | "--quiet", | ||
713 | "--intf", "dummy", /* no interface */ | ||
714 | "--vout", "dummy", /* we don't want video (output) */ | ||
715 | "--no-video-title-show", /* nor the filename displayed */ | ||
716 | "--no-sub-autodetect-file", /* we don't want automatic subtitles */ | ||
717 | "--no-stats", /* no stats */ | ||
718 | "--no-inhibit", /* we don't want interfaces */ | ||
719 | "--no-disable-screensaver", /* we don't want interfaces */ | ||
720 | // XXX: causes newer vlcs to segv! | ||
721 | // "--codec", "avcodec", | ||
722 | // XXX: disable this just in case | ||
723 | // "--demux", "avformat" | ||
724 | }; | ||
725 | vlc_argc = sizeof(vlc_argv) / sizeof(*vlc_argv); | ||
726 | |||
727 | memset(&app, 0, sizeof(app)); | ||
728 | if (!eina_init()) | ||
729 | { | ||
730 | EINA_LOG_CRIT("Can't initialize generic vlc player, eina failed."); | ||
731 | return -1; | ||
732 | } | ||
733 | |||
734 | _em_vlc_log_dom = eina_log_domain_register("emotion_generic_vlc", | ||
735 | EINA_COLOR_CYAN); | ||
736 | if (_em_vlc_log_dom < 0) | ||
737 | { | ||
738 | EINA_LOG_CRIT("Unable to register emotion_generic_vlc log domain."); | ||
739 | goto error; | ||
740 | } | ||
741 | |||
742 | if (!eina_log_domain_level_check(_em_vlc_log_dom, EINA_LOG_LEVEL_WARN)) | ||
743 | eina_log_domain_level_set("emotion_generic_vlc", EINA_LOG_LEVEL_WARN); | ||
744 | |||
745 | if (argc < 3) | ||
746 | { | ||
747 | ERR("missing parameters."); | ||
748 | ERR("syntax:\n\t%s <fd read> <fd write>", argv[0]); | ||
749 | goto error; | ||
750 | } | ||
751 | |||
752 | ecore_init(); | ||
753 | |||
754 | eina_lock_new(&app.cmd_mutex); | ||
755 | |||
756 | app.fd_read = ecore_pipe_full_add(_remote_command, &app, | ||
757 | atoi(argv[1]), -1, EINA_FALSE, EINA_FALSE); | ||
758 | app.fd_write = ecore_pipe_full_add(_dummy, NULL, | ||
759 | -1, atoi(argv[2]), EINA_FALSE, EINA_FALSE); | ||
760 | |||
761 | hld = ecore_event_handler_add(ECORE_EVENT_SIGNAL_HUP, exit_func, NULL); | ||
762 | |||
763 | app.libvlc = libvlc_new(vlc_argc, vlc_argv); | ||
764 | app.mp = NULL; | ||
765 | app.filename = NULL; | ||
766 | app.subtitle_path = NULL; | ||
767 | app.w = 0; | ||
768 | app.h = 0; | ||
769 | app.opening = EINA_FALSE; | ||
770 | app.playing = EINA_FALSE; | ||
771 | app.inited = EINA_FALSE; | ||
772 | app.last_order = EM_CMD_LAST; | ||
773 | |||
774 | ecore_main_loop_begin(); | ||
775 | |||
776 | libvlc_release(app.libvlc); | ||
777 | ecore_pipe_del(app.fd_read); | ||
778 | ecore_pipe_del(app.fd_write); | ||
779 | ecore_event_handler_del(hld); | ||
780 | eina_lock_free(&app.cmd_mutex); | ||
781 | |||
782 | ecore_shutdown(); | ||
783 | eina_shutdown(); | ||
784 | return 0; | ||
785 | |||
786 | error: | ||
787 | eina_shutdown(); | ||
788 | return -1; | ||
789 | } | ||
790 | #undef SEND_CMD_PARAM | ||