14 #include "emotion_private.h"
15 #include "emotion_generic.h"
17 struct _default_players {
22 int _emotion_generic_log_domain = -1;
24 static struct _default_players players[] = {
25 { "vlc", "em_generic_vlc" },
30 _get_player(const char *name)
35 return players[0].cmdline;
37 for (i = 0; players[i].name; i++)
39 if (!strcmp(players[i].name, name))
40 return players[i].cmdline;
47 _player_send_cmd(Emotion_Generic_Video *ev, int cmd)
49 if (cmd >= EM_CMD_LAST)
51 ERR("invalid command to player.");
54 ecore_exe_send(ev->player.exe, &cmd, sizeof(cmd));
58 _player_send_int(Emotion_Generic_Video *ev, int number)
60 ecore_exe_send(ev->player.exe, &number, sizeof(number));
64 _player_send_float(Emotion_Generic_Video *ev, float number)
66 ecore_exe_send(ev->player.exe, &number, sizeof(number));
70 _player_send_str(Emotion_Generic_Video *ev, const char *str, Eina_Bool stringshared)
75 len = eina_stringshare_strlen(str) + 1;
77 len = strlen(str) + 1;
78 ecore_exe_send(ev->player.exe, &len, sizeof(len));
79 ecore_exe_send(ev->player.exe, str, len);
83 _create_shm_data(Emotion_Generic_Video *ev, const char *shmname)
88 Emotion_Generic_Video_Shared *vs;
90 shmfd = shm_open(shmname, O_CREAT | O_RDWR | O_TRUNC, 0777);
91 size = 3 * (ev->w * ev->h * DEFAULTPITCH) + sizeof(*vs);
93 npages = (int)(size / getpagesize()) + 1;
94 size = npages * getpagesize();
95 char *buf = malloc(size);
97 if (ftruncate(shmfd, size))
99 ERR("error when allocating shared memory (size = %zd): "
100 "%s", size, strerror(errno));
103 vs = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, shmfd, 0);
104 if (vs == MAP_FAILED)
106 ERR("error when mapping shared memory.\n");
110 memcmp(vs, buf, size);
115 vs->pitch = DEFAULTPITCH;
116 vs->frame.emotion = 0;
117 vs->frame.player = 1;
120 sem_init(&vs->lock, 1, 1);
121 ev->frame.frames[0] = (char *)vs + sizeof(*vs);
122 ev->frame.frames[1] = (char *)vs + sizeof(*vs) + vs->height * vs->width * vs->pitch;
123 ev->frame.frames[2] = (char *)vs + sizeof(*vs) + 2 * vs->height * vs->width * vs->pitch;
126 munmap(ev->shared, ev->shared->size);
133 _player_new_frame(Emotion_Generic_Video *ev)
136 _emotion_frame_new(ev->obj);
140 _player_file_set_done(Emotion_Generic_Video *ev)
142 if (!_create_shm_data(ev, ev->shmname))
144 ERR("could not create shared memory.");
147 _player_send_cmd(ev, EM_CMD_FILE_SET_DONE);
151 _file_open(Emotion_Generic_Video *ev)
153 INF("Opening file: %s", ev->filename);
154 ev->w = DEFAULTWIDTH;
155 ev->h = DEFAULTHEIGHT;
156 ev->ratio = (double)DEFAULTWIDTH / DEFAULTHEIGHT;
163 _player_send_cmd(ev, EM_CMD_FILE_SET);
164 _player_send_str(ev, ev->filename, EINA_TRUE);
168 _player_ready(Emotion_Generic_Video *ev)
170 INF("received: player ready.");
172 ev->initializing = EINA_FALSE;
173 ev->ready = EINA_TRUE;
181 #define RCV_CMD_PARAM(src, param) \
182 memcpy(&(param), (src), sizeof((param))); \
183 (src) = (char *)(src) + sizeof((param));
185 #define RCV_CMD_STR(src, buf, len) \
186 RCV_CMD_PARAM((src), (len)); \
187 memcpy((buf), (src), (len)); \
188 (src) = (char *)(src) + len;
191 _player_int_read(Emotion_Generic_Video *ev, void **data)
194 memcpy(&number, *data, sizeof(number));
195 *data = (char *)(*data) + sizeof(number);
201 _player_frame_resize(Emotion_Generic_Video *ev, void *line)
204 RCV_CMD_PARAM(line, w);
205 RCV_CMD_PARAM(line, h);
207 INF("received frame resize: %dx%d", w, h);
210 ev->ratio = (float)w / h;
215 _emotion_frame_resize(ev->obj, ev->w, ev->h, ev->ratio);
219 _player_length_changed(Emotion_Generic_Video *ev, void *line)
222 RCV_CMD_PARAM(line, length);
224 INF("received length changed: %0.3f", length);
227 _emotion_video_pos_update(ev->obj, ev->pos, ev->len);
231 _player_position_changed(Emotion_Generic_Video *ev, void *line)
234 RCV_CMD_PARAM(line, position);
236 INF("received position changed: %0.3f", position);
239 _emotion_video_pos_update(ev->obj, ev->pos, ev->len);
244 float progress = ev->pos / ev->len;
246 snprintf(buf, sizeof(buf), "%0.1f%%", progress * 100);
248 _emotion_progress_set(ev->obj, buf, progress);
252 _player_seekable_changed(Emotion_Generic_Video *ev, void *line)
255 RCV_CMD_PARAM(line, seekable);
257 INF("received seekable changed: %d", seekable);
259 seekable = !!seekable;
261 ev->seekable = seekable;
265 _player_volume(Emotion_Generic_Video *ev, void *line)
268 RCV_CMD_PARAM(line, vol);
270 INF("received volume: %0.3f", vol);
274 if (vol != oldvol && !ev->opening)
275 _emotion_audio_level_change(ev->obj);
279 _player_audio_mute(Emotion_Generic_Video *ev, void *line)
282 RCV_CMD_PARAM(line, mute);
284 INF("received audio mute: %d", mute);
286 ev->audio_mute = !!mute;
290 _audio_channels_free(Emotion_Generic_Video *ev)
293 for (i = 0; i < ev->audio_channels_count; i++)
294 eina_stringshare_del(ev->audio_channels[i].name);
295 free(ev->audio_channels);
296 ev->audio_channels_count = 0;
300 _player_audio_tracks_info(Emotion_Generic_Video *ev, void *line)
302 int track_current, tracks_count;
305 if (ev->audio_channels_count)
306 _audio_channels_free(ev);
308 RCV_CMD_PARAM(line, track_current);
309 RCV_CMD_PARAM(line, tracks_count);
310 INF("video with %d audio tracks (current = %d):", tracks_count, track_current);
311 ev->audio_channels = calloc(
312 tracks_count, sizeof(Emotion_Generic_Audio_Channel));
313 ev->audio_channels_count = tracks_count;
314 ev->audio_channel_current = track_current;
315 for (i = 0; i < tracks_count; i++)
319 RCV_CMD_PARAM(line, tid);
320 RCV_CMD_STR(line, buf, len);
321 ev->audio_channels[i].id = tid;
322 ev->audio_channels[i].name = eina_stringshare_add_length(buf, len);
323 INF("\t%d: %s", tid, buf);
328 _player_file_closed(Emotion_Generic_Video *ev)
330 INF("Closed previous file.");
331 sem_destroy(&ev->shared->lock);
333 ev->closing = EINA_FALSE;
340 _player_open_done(Emotion_Generic_Video *ev)
342 ev->opening = EINA_FALSE;
343 shm_unlink(ev->shmname);
344 _emotion_open_done(ev->obj);
348 _player_send_cmd(ev, EM_CMD_PLAY);
349 _player_send_float(ev, ev->pos);
356 _player_read_cmd(Emotion_Generic_Video *ev, void *line, int size)
359 RCV_CMD_PARAM(line, type);
365 case EM_RESULT_FRAME_NEW:
366 _player_new_frame(ev);
368 case EM_RESULT_FILE_SET:
369 _player_file_set_done(ev);
371 case EM_RESULT_FILE_SET_DONE:
372 _player_open_done(ev);
374 case EM_RESULT_FILE_CLOSE:
375 _player_file_closed(ev);
377 case EM_RESULT_PLAYBACK_STOPPED:
378 _emotion_playback_finished(ev->obj);
380 case EM_RESULT_FRAME_SIZE:
381 _player_frame_resize(ev, line);
383 case EM_RESULT_LENGTH_CHANGED:
384 _player_length_changed(ev, line);
386 case EM_RESULT_POSITION_CHANGED:
387 _player_position_changed(ev, line);
389 case EM_RESULT_SEEKABLE_CHANGED:
390 _player_seekable_changed(ev, line);
392 case EM_RESULT_AUDIO_TRACK_INFO:
393 _player_audio_tracks_info(ev, line);
396 WRN("received wrong command: %d", type);
403 _player_data_cb(void *data, int type __UNUSED__, void *event)
405 Ecore_Exe_Event_Data *ev = event;
406 Emotion_Generic_Video *evideo = data;
411 if (ev->exe != evideo->player.exe)
413 ERR("slave != ev->exe");
414 return ECORE_CALLBACK_DONE;
419 ERR("invalid command: missing bytes.");
420 return ECORE_CALLBACK_DONE;
423 for (i = 0; ev->lines[i].line; i++)
424 _player_read_cmd(evideo, ev->lines[i].line, ev->lines[i].size);
426 return ECORE_CALLBACK_DONE;
430 _player_add_cb(void *data, int type __UNUSED__, void *event)
432 Ecore_Exe_Event_Add *event_add = event;
433 Ecore_Exe *player = event_add->exe;
434 Emotion_Generic_Video *ev = data;
436 if (ev->player.exe != player)
438 ERR("ev->player != player.");
439 return ECORE_CALLBACK_DONE;
442 _player_send_cmd(ev, EM_CMD_INIT);
443 _player_send_str(ev, ev->shmname, EINA_TRUE);
445 return ECORE_CALLBACK_DONE;
449 _player_del_cb(void *data, int type __UNUSED__, void *event)
451 Ecore_Exe_Event_Del *event_del = event;
452 Ecore_Exe *player = event_del->exe;
453 Emotion_Generic_Video *ev = data;
456 ev->player.exe = NULL;
457 ev->ready = EINA_FALSE;
458 _emotion_decode_stop(ev->obj);
460 return ECORE_CALLBACK_DONE;
464 _fork_and_exec(Evas_Object *obj, Emotion_Generic_Video *ev)
469 gettimeofday(&tv, NULL);
470 snprintf(shmname, sizeof(shmname), "/em-generic-shm_%d_%d",
471 (int)tv.tv_sec, (int)tv.tv_usec);
473 ev->shmname = eina_stringshare_add(shmname);
475 ev->player_add = ecore_event_handler_add(
476 ECORE_EXE_EVENT_ADD, _player_add_cb, ev);
477 ev->player_del = ecore_event_handler_add(
478 ECORE_EXE_EVENT_DEL, _player_del_cb, ev);
479 ev->player_data = ecore_event_handler_add(
480 ECORE_EXE_EVENT_DATA, _player_data_cb, ev);
482 ev->player.exe = ecore_exe_pipe_run(
484 ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_WRITE |
485 ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_NOT_LEADER,
490 ERR("could not start player.");
494 ev->initializing = EINA_TRUE;
500 em_init(Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt)
502 Emotion_Generic_Video *ev;
504 if (!emotion_video) return 0;
506 ev = (Emotion_Generic_Video *)calloc(1, sizeof(*ev));
511 ev->audio_mute = EINA_FALSE;
514 ev->cmdline = eina_stringshare_add(_get_player(opt->player));
517 return _fork_and_exec(obj, ev);
521 em_shutdown(void *data)
523 Emotion_Generic_Video *ev = data;
529 ecore_exe_terminate(ev->player.exe);
530 ecore_exe_free(ev->player.exe);
531 ev->player.exe = NULL;
535 munmap(ev->shared, ev->shared->size);
537 _audio_channels_free(ev);
539 eina_stringshare_del(ev->cmdline);
540 eina_stringshare_del(ev->shmname);
542 ecore_event_handler_del(ev->player_add);
543 ecore_event_handler_del(ev->player_data);
544 ecore_event_handler_del(ev->player_del);
550 em_file_open(const char *file, Evas_Object *obj, void *data)
552 Emotion_Generic_Video *ev = data;
553 INF("file set: %s", file);
557 ev->opening = EINA_TRUE;
559 eina_stringshare_replace(&ev->filename, file);
568 em_file_close(void *data)
570 Emotion_Generic_Video *ev = data;
573 INF("file close: %s", ev->filename);
578 _player_send_cmd(ev, EM_CMD_FILE_CLOSE);
579 ev->closing = EINA_TRUE;
582 static Emotion_Format
583 em_format_get(void *ef)
585 return EMOTION_FORMAT_BGRA;
589 em_video_data_size_get(void *data, int *w, int *h)
591 Emotion_Generic_Video *ev = data;
599 em_play(void *data, double pos)
601 Emotion_Generic_Video *ev = data;
606 ev->play = EINA_TRUE;
607 INF("play: %0.3f", pos);
609 if (ev->initializing || ev->opening)
614 _player_send_cmd(ev, EM_CMD_PLAY);
615 _player_send_float(ev, ev->pos);
619 ev->player.exe = ecore_exe_pipe_run(
621 ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_WRITE |
622 ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_NOT_LEADER,
626 ERR("could not start player.");
632 Emotion_Generic_Video *ev = data;
637 ev->play = EINA_FALSE;
642 _player_send_cmd(ev, EM_CMD_STOP);
643 _emotion_decode_stop(ev->obj);
647 em_size_get(void *data, int *w, int *h)
649 Emotion_Generic_Video *ev = data;
655 em_pos_set(void *data, double pos)
657 Emotion_Generic_Video *ev = data;
658 float position = pos;
659 _player_send_cmd(ev, EM_CMD_POSITION_SET);
660 _player_send_float(ev, position);
661 _emotion_seek_done(ev->obj);
665 em_len_get(void *data)
667 Emotion_Generic_Video *ev = data;
672 em_fps_num_get(void *data)
674 Emotion_Generic_Video *ev = data;
675 return (int)(ev->fps * 1000.0);
679 em_fps_den_get(void *ef)
685 em_fps_get(void *data)
687 Emotion_Generic_Video *ev = data;
692 em_pos_get(void *data)
694 Emotion_Generic_Video *ev = data;
699 em_vis_set(void *ef, Emotion_Vis vis)
704 em_vis_get(void *data)
706 Emotion_Generic_Video *ev = data;
711 em_vis_supported(void *ef, Emotion_Vis vis)
717 em_ratio_get(void *data)
719 Emotion_Generic_Video *ev = data;
723 static int em_video_handled(void *ef)
725 fprintf(stderr, "video handled!\n");
729 static int em_audio_handled(void *ef)
731 fprintf(stderr, "audio handled!\n");
735 static int em_seekable(void *data)
737 Emotion_Generic_Video *ev = data;
741 static void em_frame_done(void *ef)
746 em_yuv_rows_get(void *data, int w, int h, unsigned char **yrows, unsigned char **urows, unsigned char **vrows)
748 Emotion_Generic_Video *ev;
749 volatile Emotion_Generic_Video_Shared *vs;
754 em_bgra_data_get(void *data, unsigned char **bgra_data)
756 Emotion_Generic_Video *ev = data;
758 if (!ev || ev->opening || ev->closing)
762 sem_wait(&ev->shared->lock);
764 // send current frame to emotion
765 if (ev->shared->frame.emotion != ev->shared->frame.last)
767 ev->shared->frame.next = ev->shared->frame.emotion;
768 ev->shared->frame.emotion = ev->shared->frame.last;
770 *bgra_data = ev->frame.frames[ev->shared->frame.emotion];
773 sem_post(&ev->shared->lock);
780 em_event_feed(void *ef, int event)
785 em_event_mouse_button_feed(void *ef, int button, int x, int y)
790 em_event_mouse_move_feed(void *ef, int x, int y)
795 em_video_channel_count(void *ef)
802 em_video_channel_set(void *ef, int channel)
807 em_video_channel_get(void *ef)
813 em_video_channel_name_get(void *ef, int channel)
819 em_video_channel_mute_set(void *ef, int mute)
824 em_video_channel_mute_get(void *data)
826 Emotion_Generic_Video *ev = data;
827 return ev->video_mute;
831 em_audio_channel_count(void *data)
833 Emotion_Generic_Video *ev = data;
834 return ev->audio_channels_count;
838 em_audio_channel_set(void *data, int channel)
840 Emotion_Generic_Video *ev = data;
843 for (i = 0; i < ev->audio_channels_count; i++)
845 if (ev->audio_channels[i].id == channel)
847 _player_send_cmd(ev, EM_CMD_AUDIO_TRACK_SET);
848 _player_send_int(ev, channel);
855 em_audio_channel_get(void *data)
857 Emotion_Generic_Video *ev = data;
858 return ev->audio_channel_current;
862 em_audio_channel_name_get(void *data, int channel)
864 Emotion_Generic_Video *ev = data;
867 for (i = 0; i < ev->audio_channels_count; i++)
869 if (ev->audio_channels[i].id == channel)
870 return ev->audio_channels[i].name;
877 em_audio_channel_mute_set(void *data, int mute)
879 Emotion_Generic_Video *ev = data;
880 _player_send_cmd(ev, EM_CMD_AUDIO_MUTE_SET);
881 _player_send_int(ev, mute);
882 ev->audio_mute = !!mute;
886 em_audio_channel_mute_get(void *data)
888 Emotion_Generic_Video *ev = data;
889 return ev->audio_mute;
893 em_audio_channel_volume_set(void *data, double vol)
895 Emotion_Generic_Video *ev = data;
898 if (vol > 1.0) vol = 1.0;
899 if (vol < 0.0) vol = 0.0;
902 _player_send_cmd(ev, EM_CMD_VOLUME_SET);
903 _player_send_float(ev, fvol);
909 em_audio_channel_volume_get(void *data)
911 Emotion_Generic_Video *ev = data;
916 em_spu_channel_count(void *ef)
922 em_spu_channel_set(void *ef, int channel)
927 em_spu_channel_get(void *ef)
934 em_spu_channel_name_get(void *ef, int channel)
940 em_spu_channel_mute_set(void *ef, int mute)
946 em_spu_channel_mute_get(void *ef)
952 em_chapter_count(void *ef)
959 em_chapter_set(void *ef, int chapter)
964 em_chapter_get(void *ef)
971 em_chapter_name_get(void *ef, int chapter)
977 em_speed_set(void *data, double speed)
979 Emotion_Generic_Video *ev = data;
982 _player_send_cmd(ev, EM_CMD_SPEED_SET);
983 _player_send_float(ev, rate);
989 em_speed_get(void *data)
991 Emotion_Generic_Video *ev = data;
992 return (double)ev->speed;
1002 em_meta_get(void *ef, int meta)
1004 char * meta_data = NULL;
1008 static Emotion_Video_Module em_module =
1011 em_shutdown, /* shutdown */
1012 em_file_open, /* file_open */
1013 em_file_close, /* file_close */
1016 em_size_get, /* size_get */
1017 em_pos_set, /* pos_set */
1018 em_len_get, /* len_get */
1019 em_fps_num_get, /* fps_num_get */
1020 em_fps_den_get, /* fps_den_get */
1021 em_fps_get, /* fps_get */
1022 em_pos_get, /* pos_get */
1023 em_vis_set, /* vis_set */
1024 em_vis_get, /* vis_get */
1025 em_vis_supported, /* vis_supported */
1026 em_ratio_get, /* ratio_get */
1027 em_video_handled, /* video_handled */
1028 em_audio_handled, /* audio_handled */
1029 em_seekable, /* seekable */
1030 em_frame_done, /* frame_done */
1031 em_format_get, /* format_get */
1032 em_video_data_size_get, /* video_data_size_get */
1033 em_yuv_rows_get, /* yuv_rows_get */
1034 em_bgra_data_get, /* bgra_data_get */
1035 em_event_feed, /* event_feed */
1036 em_event_mouse_button_feed, /* event_mouse_button_feed */
1037 em_event_mouse_move_feed, /* event_mouse_move_feed */
1038 em_video_channel_count, /* video_channel_count */
1039 em_video_channel_set, /* video_channel_set */
1040 em_video_channel_get, /* video_channel_get */
1041 em_video_channel_name_get, /* video_channel_name_get */
1042 em_video_channel_mute_set, /* video_channel_mute_set */
1043 em_video_channel_mute_get, /* video_channel_mute_get */
1044 em_audio_channel_count, /* audio_channel_count */
1045 em_audio_channel_set, /* audio_channel_set */
1046 em_audio_channel_get, /* audio_channel_get */
1047 em_audio_channel_name_get, /* audio_channel_name_get */
1048 em_audio_channel_mute_set, /* audio_channel_mute_set */
1049 em_audio_channel_mute_get, /* audio_channel_mute_get */
1050 em_audio_channel_volume_set, /* audio_channel_volume_set */
1051 em_audio_channel_volume_get, /* audio_channel_volume_get */
1052 em_spu_channel_count, /* spu_channel_count */
1053 em_spu_channel_set, /* spu_channel_set */
1054 em_spu_channel_get, /* spu_channel_get */
1055 em_spu_channel_name_get, /* spu_channel_name_get */
1056 em_spu_channel_mute_set, /* spu_channel_mute_set */
1057 em_spu_channel_mute_get, /* spu_channel_mute_get */
1058 em_chapter_count, /* chapter_count */
1059 em_chapter_set, /* chapter_set */
1060 em_chapter_get, /* chapter_get */
1061 em_chapter_name_get, /* chapter_name_get */
1062 em_speed_set, /* speed_set */
1063 em_speed_get, /* speed_get */
1064 em_eject, /* eject */
1065 em_meta_get, /* meta_get */
1070 module_open(Evas_Object *obj, const Emotion_Video_Module **module, void **video, Emotion_Module_Options *opt)
1076 if (_emotion_generic_log_domain < 0)
1078 eina_threads_init();
1079 eina_log_threads_enable();
1080 _emotion_generic_log_domain = eina_log_domain_register
1081 ("emotion-generic", EINA_COLOR_LIGHTCYAN);
1082 if (_emotion_generic_log_domain < 0)
1084 EINA_LOG_CRIT("Could not register log domain 'emotion-generic'");
1090 if (!em_module.init(obj, video, opt)) {
1094 *module = &em_module;
1099 static void module_close(Emotion_Video_Module *module, void *video)
1101 em_module.shutdown(video);
1106 generic_module_init(void)
1108 return _emotion_module_register("generic", module_open, module_close);
1112 generic_module_shutdown(void)
1114 _emotion_module_unregister("generic");
1117 #ifndef EMOTION_STATIC_BUILD_GENERIC
1119 EINA_MODULE_INIT(generic_module_init);
1120 EINA_MODULE_SHUTDOWN(generic_module_shutdown);