18 #include "emotion_private.h"
19 #include "emotion_generic.h"
21 static Eina_Prefix *pfx = NULL;
23 static int _emotion_generic_log_domain = -1;
24 #define DBG(...) EINA_LOG_DOM_DBG(_emotion_generic_log_domain, __VA_ARGS__)
25 #define INF(...) EINA_LOG_DOM_INFO(_emotion_generic_log_domain, __VA_ARGS__)
26 #define WRN(...) EINA_LOG_DOM_WARN(_emotion_generic_log_domain, __VA_ARGS__)
27 #define ERR(...) EINA_LOG_DOM_ERR(_emotion_generic_log_domain, __VA_ARGS__)
28 #define CRITICAL(...) EINA_LOG_DOM_CRIT(_emotion_generic_log_domain, __VA_ARGS__)
31 struct _default_players {
36 static struct _default_players players[] = {
37 #ifdef EMOTION_BUILD_GENERIC_VLC
38 { "vlc", "em_generic_vlc" },
43 static Eina_Bool _fork_and_exec(Emotion_Generic_Video *ev);
44 static void em_partial_shutdown(Emotion_Generic_Video *ev);
47 _player_restart(void *data)
49 Emotion_Generic_Video *ev = data;
52 ev->player_restart = NULL;
57 _get_player(const char *name)
59 const char *selected_name = NULL;
60 const char *libdir = eina_prefix_lib_get(pfx);
61 static char buf[PATH_MAX];
66 for (i = 0; players[i].name; i++)
68 if (!strcmp(players[i].name, name))
70 selected_name = players[i].cmdline;
76 if ((!selected_name) && (name))
83 if (selected_name[0] == '/') cmd = selected_name;
86 snprintf(buf, sizeof(buf), "%s/emotion/utils/%s",
87 libdir, selected_name);
91 DBG("Try generic player '%s'", cmd);
92 if (access(cmd, R_OK | X_OK) == 0)
94 INF("Using generic player '%s'", cmd);
99 for (i = 0; players[i].name; i++)
101 snprintf(buf, sizeof(buf), "%s/emotion/utils/%s",
102 libdir, players[i].cmdline);
103 DBG("Try generic player '%s'", buf);
104 if (access(buf, R_OK | X_OK) == 0)
106 INF("Using fallback player '%s'", buf);
111 ERR("no generic player found, given name='%s'", name ? name : "");
116 _player_send_cmd(Emotion_Generic_Video *ev, int cmd)
118 if (cmd >= EM_CMD_LAST)
120 ERR("invalid command to player.");
123 if (ev->fd_write == -1)
125 ERR("you should wait for emotion to be ready to take action.");
128 if (write(ev->fd_write, &cmd, sizeof(cmd)) < 0) perror("write");
132 _player_send_int(Emotion_Generic_Video *ev, int number)
134 if (ev->fd_write == -1)
136 ERR("you should wait for emotion to be ready to take action.");
139 if (write(ev->fd_write, &number, sizeof(number)) < 0) perror("write");
143 _player_send_float(Emotion_Generic_Video *ev, float number)
145 if (ev->fd_write == -1)
147 ERR("you should wait for emotion to be ready to take action.");
150 if (write(ev->fd_write, &number, sizeof(number)) < 0) perror("write");
154 _player_send_str(Emotion_Generic_Video *ev, const char *str, Eina_Bool stringshared)
159 len = eina_stringshare_strlen(str) + 1;
161 len = strlen(str) + 1;
162 if (write(ev->fd_write, &len, sizeof(len)) < 0) perror("write");
163 if (write(ev->fd_write, str, len) < 0) perror("write");
167 _create_shm_data(Emotion_Generic_Video *ev, const char *shmname)
172 Emotion_Generic_Video_Shared *vs;
174 shmfd = shm_open(shmname, O_CREAT | O_RDWR | O_TRUNC, 0777);
177 ERR("player: could not open shm: %s", shmname);
178 ERR("player: %s", strerror(errno));
181 size = 3 * (ev->w * ev->h * DEFAULTPITCH) + sizeof(*vs);
183 npages = (int)(size / getpagesize()) + 1;
184 size = npages * getpagesize();
186 if (ftruncate(shmfd, size))
188 ERR("error when allocating shared memory (size = %zd): "
189 "%s", size, strerror(errno));
193 vs = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, shmfd, 0);
194 if (vs == MAP_FAILED)
196 ERR("error when mapping shared memory");
203 vs->pitch = DEFAULTPITCH;
204 vs->frame.emotion = 0;
205 vs->frame.player = 1;
209 if (!eina_semaphore_new(&vs->lock, 1))
211 ERR("can not create semaphore");
214 ev->frame.frames[0] = (unsigned char *)vs + sizeof(*vs);
215 ev->frame.frames[1] = (unsigned char *)vs + sizeof(*vs) + vs->height * vs->width * vs->pitch;
216 ev->frame.frames[2] = (unsigned char *)vs + sizeof(*vs) + 2 * vs->height * vs->width * vs->pitch;
219 munmap(ev->shared, ev->shared->size);
226 _player_new_frame(Emotion_Generic_Video *ev)
230 _emotion_frame_new(ev->obj);
234 _file_open(Emotion_Generic_Video *ev)
236 INF("Opening file: %s", ev->filename);
239 if (!ev->ready || !ev->filename)
241 _player_send_cmd(ev, EM_CMD_FILE_SET);
242 _player_send_str(ev, ev->filename, EINA_TRUE);
246 _player_file_set_done(Emotion_Generic_Video *ev)
248 if (ev->file_changed)
251 ev->file_changed = EINA_FALSE;
255 if (!_create_shm_data(ev, ev->shmname))
257 ERR("could not create shared memory.");
260 _player_send_cmd(ev, EM_CMD_FILE_SET_DONE);
264 _player_ready(Emotion_Generic_Video *ev)
266 INF("received: player ready.");
268 ev->initializing = EINA_FALSE;
269 ev->ready = EINA_TRUE;
278 _player_cmd_param_read(Emotion_Generic_Video *ev, void *param, size_t size)
280 ssize_t done, todo, i;
282 /* When a parameter must be read, we cannot make sure it will be entirely
283 * available. Thus we store the bytes that could be read in a temp buffer,
284 * and when more data is read we try to complete the buffer and finally use
289 ev->cmd.tmp = malloc(size);
291 ev->cmd.total = size;
294 todo = ev->cmd.total - ev->cmd.i;
296 done = read(ev->fd_read, &ev->cmd.tmp[i], todo);
298 if (done < 0 && errno != EINTR && errno != EAGAIN)
305 ERR("problem when reading parameter from pipe.");
312 memcpy(param, ev->cmd.tmp, size);
325 _player_frame_resize(Emotion_Generic_Video *ev)
329 w = ev->cmd.param.size.width;
330 h = ev->cmd.param.size.height;
332 INF("received frame resize: %dx%d", w, h);
335 ev->ratio = (float)w / h;
340 _emotion_frame_resize(ev->obj, ev->w, ev->h, ev->ratio);
344 _player_length_changed(Emotion_Generic_Video *ev)
346 float length = ev->cmd.param.f_num;
348 INF("received length changed: %0.3f", length);
351 _emotion_video_pos_update(ev->obj, ev->pos, ev->len);
355 _player_position_changed(Emotion_Generic_Video *ev)
357 float position = ev->cmd.param.f_num;
359 INF("received position changed: %0.3f", position);
362 _emotion_video_pos_update(ev->obj, ev->pos, ev->len);
363 /* hmmm. no _emotion_progress_set() is for "buffering" progress.
367 float progress = ev->pos / ev->len;
369 snprintf(buf, sizeof(buf), "%0.1f%%", progress * 100);
371 _emotion_progress_set(ev->obj, buf, progress);
376 _player_seekable_changed(Emotion_Generic_Video *ev)
378 int seekable = ev->cmd.param.i_num;
380 INF("received seekable changed: %d", seekable);
382 seekable = !!seekable;
384 ev->seekable = seekable;
388 _audio_channels_free(Emotion_Generic_Video *ev)
391 for (i = 0; i < ev->audio_channels_count; i++)
392 eina_stringshare_del(ev->audio_channels[i].name);
393 free(ev->audio_channels);
394 ev->audio_channels = NULL;
395 ev->audio_channels_count = 0;
399 _video_channels_free(Emotion_Generic_Video *ev)
402 for (i = 0; i < ev->video_channels_count; i++)
403 eina_stringshare_del(ev->video_channels[i].name);
404 free(ev->video_channels);
405 ev->video_channels = NULL;
406 ev->video_channels_count = 0;
410 _spu_channels_free(Emotion_Generic_Video *ev)
413 for (i = 0; i < ev->spu_channels_count; i++)
414 eina_stringshare_del(ev->spu_channels[i].name);
415 free(ev->spu_channels);
416 ev->spu_channels = NULL;
417 ev->spu_channels_count = 0;
421 _player_tracks_info(Emotion_Generic_Video *ev, Emotion_Generic_Channel **channels, int *count, int *current)
423 Emotion_Generic_Channel *pchannels;
426 *count = ev->cmd.param.track.total;
427 *current = ev->cmd.param.track.current;
428 pchannels = ev->cmd.param.track.channels;
430 INF("number of tracks: %d (current = %d):", *count, *current);
431 for (i = 0; i < *count; i++)
433 INF("\tchannel %d: %s", pchannels[i].id, pchannels[i].name);
436 *channels = pchannels;
440 _player_audio_tracks_info(Emotion_Generic_Video *ev)
442 INF("Receiving audio channels:");
443 if (ev->audio_channels_count)
444 _audio_channels_free(ev);
446 _player_tracks_info(ev, &ev->audio_channels, &ev->audio_channels_count,
447 &ev->audio_channel_current);
451 _player_video_tracks_info(Emotion_Generic_Video *ev)
453 INF("Receiving video channels:");
454 if (ev->video_channels_count)
455 _video_channels_free(ev);
457 _player_tracks_info(ev, &ev->video_channels, &ev->video_channels_count,
458 &ev->video_channel_current);
462 _player_spu_tracks_info(Emotion_Generic_Video *ev)
464 INF("Receiving spu channels:");
465 if (ev->spu_channels_count)
466 _spu_channels_free(ev);
468 _player_tracks_info(ev, &ev->spu_channels, &ev->spu_channels_count,
469 &ev->spu_channel_current);
473 _player_meta_info_free(Emotion_Generic_Video *ev)
475 eina_stringshare_replace(&ev->meta.title, NULL);
476 eina_stringshare_replace(&ev->meta.artist, NULL);
477 eina_stringshare_replace(&ev->meta.album, NULL);
478 eina_stringshare_replace(&ev->meta.year, NULL);
479 eina_stringshare_replace(&ev->meta.genre, NULL);
480 eina_stringshare_replace(&ev->meta.comment, NULL);
481 eina_stringshare_replace(&ev->meta.disc_id, NULL);
482 eina_stringshare_replace(&ev->meta.count, NULL);
486 _player_meta_info_read(Emotion_Generic_Video *ev)
488 INF("Receiving meta info:");
489 _player_meta_info_free(ev);
490 ev->meta.title = ev->cmd.param.meta.title;
491 ev->meta.artist = ev->cmd.param.meta.artist;
492 ev->meta.album = ev->cmd.param.meta.album;
493 ev->meta.year = ev->cmd.param.meta.year;
494 ev->meta.genre = ev->cmd.param.meta.genre;
495 ev->meta.comment = ev->cmd.param.meta.comment;
496 ev->meta.disc_id = ev->cmd.param.meta.disc_id;
497 ev->meta.count = ev->cmd.param.meta.count;
498 INF("title: '%s'", ev->meta.title);
499 INF("artist: '%s'", ev->meta.artist);
500 INF("album: '%s'", ev->meta.album);
501 INF("year: '%s'", ev->meta.year);
502 INF("genre: '%s'", ev->meta.genre);
503 INF("comment: '%s'", ev->meta.comment);
504 INF("disc_id: '%s'", ev->meta.disc_id);
505 INF("count: '%s'", ev->meta.count);
509 _player_file_closed(Emotion_Generic_Video *ev)
511 INF("Closed previous file.");
512 eina_semaphore_free(&ev->shared->lock);
513 ev->closing = EINA_FALSE;
520 _player_open_done(Emotion_Generic_Video *ev)
524 success = ev->cmd.param.i_num;
525 shm_unlink(ev->shmname);
527 if (ev->file_changed)
530 ev->file_changed = EINA_FALSE;
534 ev->opening = EINA_FALSE;
537 ERR("Could not open file.");
541 ev->file_ready = EINA_TRUE;
543 _emotion_open_done(ev->obj);
547 _player_send_cmd(ev, EM_CMD_PLAY);
548 _player_send_float(ev, ev->pos);
551 _player_send_cmd(ev, EM_CMD_VOLUME_SET);
552 _player_send_float(ev, ev->volume);
554 _player_send_cmd(ev, EM_CMD_SPEED_SET);
555 _player_send_float(ev, ev->speed);
557 int mute = ev->audio_mute;
558 _player_send_cmd(ev, EM_CMD_AUDIO_MUTE_SET);
559 _player_send_int(ev, mute);
561 mute = ev->video_mute;
562 _player_send_cmd(ev, EM_CMD_VIDEO_MUTE_SET);
563 _player_send_int(ev, mute);
566 _player_send_cmd(ev, EM_CMD_SPU_MUTE_SET);
567 _player_send_int(ev, mute);
573 _player_cmd_process(Emotion_Generic_Video *ev)
575 switch (ev->cmd.type) {
579 case EM_RESULT_FRAME_NEW:
580 _player_new_frame(ev);
582 case EM_RESULT_FILE_SET:
583 _player_file_set_done(ev);
585 case EM_RESULT_FILE_SET_DONE:
586 _player_open_done(ev);
588 case EM_RESULT_FILE_CLOSE:
589 _player_file_closed(ev);
591 case EM_RESULT_PLAYBACK_STARTED:
592 _emotion_playback_started(ev->obj);
594 case EM_RESULT_PLAYBACK_STOPPED:
596 _emotion_playback_finished(ev->obj);
597 _emotion_decode_stop(ev->obj);
599 em_partial_shutdown(ev);
600 ev->player_restart = ecore_idler_add(_player_restart, ev);
602 case EM_RESULT_FRAME_SIZE:
603 _player_frame_resize(ev);
605 case EM_RESULT_LENGTH_CHANGED:
606 _player_length_changed(ev);
608 case EM_RESULT_POSITION_CHANGED:
609 _player_position_changed(ev);
611 case EM_RESULT_SEEKABLE_CHANGED:
612 _player_seekable_changed(ev);
614 case EM_RESULT_AUDIO_TRACK_INFO:
615 _player_audio_tracks_info(ev);
617 case EM_RESULT_VIDEO_TRACK_INFO:
618 _player_video_tracks_info(ev);
620 case EM_RESULT_SPU_TRACK_INFO:
621 _player_spu_tracks_info(ev);
623 case EM_RESULT_META_INFO:
624 _player_meta_info_read(ev);
627 WRN("received wrong command: %d", ev->cmd.type);
634 _player_cmd_single_int_process(Emotion_Generic_Video *ev)
636 if (!_player_cmd_param_read(ev, &ev->cmd.param.i_num, sizeof(ev->cmd.param.i_num)))
639 _player_cmd_process(ev);
643 _player_cmd_single_float_process(Emotion_Generic_Video *ev)
645 if (!_player_cmd_param_read(ev, &ev->cmd.param.f_num, sizeof(ev->cmd.param.f_num)))
648 _player_cmd_process(ev);
652 _player_cmd_double_int_process(Emotion_Generic_Video *ev)
656 if (ev->cmd.num_params == 0)
658 ev->cmd.num_params = 2;
659 ev->cmd.cur_param = 0;
660 ev->cmd.param.size.width = 0;
661 ev->cmd.param.size.height = 0;
664 if (!_player_cmd_param_read(ev, ¶m, sizeof(param)))
667 if (ev->cmd.cur_param == 0)
668 ev->cmd.param.size.width = param;
670 ev->cmd.param.size.height = param;
673 if (ev->cmd.cur_param == ev->cmd.num_params)
674 _player_cmd_process(ev);
678 _player_cmd_track_info(Emotion_Generic_Video *ev)
683 if (ev->cmd.num_params == 0)
685 ev->cmd.cur_param = 0;
686 ev->cmd.num_params = 2;
687 ev->cmd.param.track.channels = NULL;
691 while (ev->cmd.cur_param < 2)
693 if (!_player_cmd_param_read(ev, ¶m, sizeof(param)))
696 if (ev->cmd.cur_param == 0)
697 ev->cmd.param.track.current = param;
700 ev->cmd.param.track.total = param;
701 ev->cmd.num_params += param * 2;
702 ev->cmd.param.track.channels =
703 calloc(param, sizeof(*ev->cmd.param.track.channels));
708 if (ev->cmd.cur_param == ev->cmd.num_params)
710 _player_cmd_process(ev);
714 i = (ev->cmd.cur_param - 2) / 2;
715 if ((ev->cmd.cur_param % 2) == 0) // reading track id
717 if (!_player_cmd_param_read(ev, ¶m, sizeof(param)))
719 ev->cmd.param.track.channels[i].id = param;
722 else // reading track name
726 if (ev->cmd.s_len == -1)
728 if (!_player_cmd_param_read(ev, ¶m, sizeof(param)))
730 ev->cmd.s_len = param;
733 if (!_player_cmd_param_read(ev, buf, ev->cmd.s_len))
735 ev->cmd.param.track.channels[i].name =
736 eina_stringshare_add_length(buf, ev->cmd.s_len);
741 if (ev->cmd.cur_param == ev->cmd.num_params)
742 _player_cmd_process(ev);
746 _player_cmd_meta_info(Emotion_Generic_Video *ev)
752 if (ev->cmd.num_params == 0)
754 ev->cmd.cur_param = 0;
755 ev->cmd.num_params = 8;
756 ev->cmd.param.meta.title = NULL;
757 ev->cmd.param.meta.artist = NULL;
758 ev->cmd.param.meta.album = NULL;
759 ev->cmd.param.meta.year = NULL;
760 ev->cmd.param.meta.genre = NULL;
761 ev->cmd.param.meta.comment = NULL;
762 ev->cmd.param.meta.disc_id = NULL;
763 ev->cmd.param.meta.count = NULL;
767 if (ev->cmd.s_len == -1)
769 if (!_player_cmd_param_read(ev, ¶m, sizeof(param)))
771 ev->cmd.s_len = param;
774 if (!_player_cmd_param_read(ev, buf, ev->cmd.s_len))
777 info = eina_stringshare_add_length(buf, ev->cmd.s_len);
780 if (ev->cmd.cur_param == 0)
781 ev->cmd.param.meta.title = info;
782 else if (ev->cmd.cur_param == 1)
783 ev->cmd.param.meta.artist = info;
784 else if (ev->cmd.cur_param == 2)
785 ev->cmd.param.meta.album = info;
786 else if (ev->cmd.cur_param == 3)
787 ev->cmd.param.meta.year = info;
788 else if (ev->cmd.cur_param == 4)
789 ev->cmd.param.meta.genre = info;
790 else if (ev->cmd.cur_param == 5)
791 ev->cmd.param.meta.comment = info;
792 else if (ev->cmd.cur_param == 6)
793 ev->cmd.param.meta.disc_id = info;
794 else if (ev->cmd.cur_param == 7)
795 ev->cmd.param.meta.count = info;
799 if (ev->cmd.cur_param == 8)
800 _player_cmd_process(ev);
804 _player_cmd_read(Emotion_Generic_Video *ev)
806 if (ev->cmd.type < 0)
808 if (!_player_cmd_param_read(ev, &ev->cmd.type, sizeof(ev->cmd.type)))
810 ev->cmd.num_params = 0;
813 switch (ev->cmd.type) {
815 case EM_RESULT_FILE_SET:
816 case EM_RESULT_PLAYBACK_STARTED:
817 case EM_RESULT_PLAYBACK_STOPPED:
818 case EM_RESULT_FILE_CLOSE:
819 case EM_RESULT_FRAME_NEW:
820 _player_cmd_process(ev);
822 case EM_RESULT_FILE_SET_DONE:
823 case EM_RESULT_SEEKABLE_CHANGED:
824 _player_cmd_single_int_process(ev);
826 case EM_RESULT_LENGTH_CHANGED:
827 case EM_RESULT_POSITION_CHANGED:
828 _player_cmd_single_float_process(ev);
830 case EM_RESULT_FRAME_SIZE:
831 _player_cmd_double_int_process(ev);
833 case EM_RESULT_AUDIO_TRACK_INFO:
834 case EM_RESULT_VIDEO_TRACK_INFO:
835 case EM_RESULT_SPU_TRACK_INFO:
836 _player_cmd_track_info(ev);
838 case EM_RESULT_META_INFO:
839 _player_cmd_meta_info(ev);
843 WRN("received wrong command: %d", ev->cmd.type);
849 _player_cmd_handler_cb(void *data, Ecore_Fd_Handler *fd_handler)
851 Emotion_Generic_Video *ev = data;
853 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR))
855 ERR("an error occurred on fd_read %d.", ev->fd_read);
856 return ECORE_CALLBACK_CANCEL;
859 _player_cmd_read(ev);
861 return ECORE_CALLBACK_RENEW;
865 _player_data_cb(void *data, int type __UNUSED__, void *event)
867 Ecore_Exe_Event_Data *ev = event;
868 Emotion_Generic_Video *evideo = data;
871 if (ev->exe != evideo->player.exe)
873 INF("slave != ev->exe");
874 return ECORE_CALLBACK_PASS_ON;
877 for (i = 0; ev->lines[i].line; i++)
878 INF("received input from player: \"%s\"", ev->lines[i].line);
880 return ECORE_CALLBACK_DONE;
884 _player_add_cb(void *data, int type __UNUSED__, void *event)
886 Ecore_Exe_Event_Add *event_add = event;
887 Ecore_Exe *player = event_add->exe;
888 Emotion_Generic_Video *ev = data;
890 if (ev->player.exe != player)
892 INF("ev->player != player.");
893 return ECORE_CALLBACK_PASS_ON;
896 _player_send_cmd(ev, EM_CMD_INIT);
897 _player_send_str(ev, ev->shmname, EINA_TRUE);
899 return ECORE_CALLBACK_DONE;
903 _player_del_cb(void *data, int type __UNUSED__, void *event __UNUSED__)
905 Ecore_Exe_Event_Del *event_del = event;
906 Ecore_Exe *player = event_del->exe;
907 Emotion_Generic_Video *ev = data;
909 if (ev->player.exe != player)
911 INF("ev->player != player.");
912 return ECORE_CALLBACK_PASS_ON;
917 ev->player.exe = NULL;
918 ev->ready = EINA_FALSE;
919 ev->file_ready = EINA_FALSE;
920 ecore_main_fd_handler_del(ev->fd_handler);
925 _emotion_decode_stop(ev->obj);
927 return ECORE_CALLBACK_DONE;
931 _player_exec(Emotion_Generic_Video *ev)
937 if (pipe(pipe_out) == -1)
939 ERR("could not create pipe for communication emotion -> player: %s", strerror(errno));
943 if (pipe(pipe_in) == -1)
945 ERR("could not create pipe for communication player -> emotion: %s", strerror(errno));
951 snprintf(buf, sizeof(buf), "%s %d %d\n", ev->cmdline, pipe_out[0], pipe_in[1]);
953 ev->player.exe = ecore_exe_pipe_run(
955 ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_WRITE |
956 ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_NOT_LEADER,
959 INF("created pipe emotion -> player: %d -> %d", pipe_out[1], pipe_out[0]);
960 INF("created pipe player -> emotion: %d -> %d", pipe_in[1], pipe_in[0]);
972 ev->fd_read = pipe_in[0];
973 ev->fd_write = pipe_out[1];
975 ev->fd_handler = ecore_main_fd_handler_add(
976 ev->fd_read, ECORE_FD_READ | ECORE_FD_ERROR, _player_cmd_handler_cb, ev,
983 _fork_and_exec(Emotion_Generic_Video *ev)
988 gettimeofday(&tv, NULL);
989 snprintf(shmname, sizeof(shmname), "/em-generic-shm_%d_%d",
990 (int)tv.tv_sec, (int)tv.tv_usec);
992 ev->shmname = eina_stringshare_add(shmname);
994 ev->player_add = ecore_event_handler_add(
995 ECORE_EXE_EVENT_ADD, _player_add_cb, ev);
996 ev->player_del = ecore_event_handler_add(
997 ECORE_EXE_EVENT_DEL, _player_del_cb, ev);
998 ev->player_data = ecore_event_handler_add(
999 ECORE_EXE_EVENT_DATA, _player_data_cb, ev);
1001 if (!_player_exec(ev))
1003 ERR("could not start player.");
1007 ev->initializing = EINA_TRUE;
1012 static unsigned char
1013 em_init(Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt)
1015 Emotion_Generic_Video *ev;
1018 if (!emotion_video) return 0;
1019 player = _get_player(opt ? opt->player : NULL);
1020 if (!player) return 0;
1022 ev = (Emotion_Generic_Video *)calloc(1, sizeof(*ev));
1029 ev->audio_mute = EINA_FALSE;
1033 ev->cmdline = eina_stringshare_add(player);
1034 *emotion_video = ev;
1036 return _fork_and_exec(ev);
1040 em_partial_shutdown(Emotion_Generic_Video *ev)
1042 _emotion_image_reset(ev->obj);
1046 ecore_exe_terminate(ev->player.exe);
1047 ecore_exe_free(ev->player.exe);
1048 ev->player.exe = NULL;
1052 munmap(ev->shared, ev->shared->size);
1055 if (ev->fd_read >= 0)
1058 if (ev->fd_write >= 0)
1059 close(ev->fd_write);
1062 ecore_main_fd_handler_del(ev->fd_handler);
1063 ev->fd_handler = NULL;
1065 if (ev->player_add) ecore_event_handler_del(ev->player_add);
1066 ev->player_add = NULL;
1067 if (ev->player_data) ecore_event_handler_del(ev->player_data);
1068 ev->player_data = NULL;
1069 if (ev->player_del) ecore_event_handler_del(ev->player_del);
1070 ev->player_del = NULL;
1071 if (ev->player_restart) ecore_idler_del(ev->player_restart);
1072 ev->player_restart = NULL;
1076 em_shutdown(void *data)
1078 Emotion_Generic_Video *ev = data;
1082 eina_stringshare_del(ev->cmdline);
1083 eina_stringshare_del(ev->shmname);
1085 em_partial_shutdown(ev);
1090 static unsigned char
1091 em_file_open(const char *file, Evas_Object *obj __UNUSED__, void *data)
1093 Emotion_Generic_Video *ev = data;
1094 INF("file set: %s", file);
1097 eina_stringshare_replace(&ev->filename, file);
1105 if (ev->ready && ev->opening)
1107 INF("file changed while opening.");
1108 ev->file_changed = EINA_TRUE;
1112 ev->opening = EINA_TRUE;
1121 em_file_close(void *data)
1123 Emotion_Generic_Video *ev = data;
1125 if (!ev || !ev->filename) return;
1127 INF("file close: %s", ev->filename);
1129 eina_stringshare_replace(&ev->filename, NULL);
1131 ev->file_ready = EINA_FALSE;
1132 _audio_channels_free(ev);
1133 _video_channels_free(ev);
1134 _spu_channels_free(ev);
1135 _player_meta_info_free(ev);
1140 _player_send_cmd(ev, EM_CMD_FILE_CLOSE);
1141 ev->closing = EINA_TRUE;
1144 static Emotion_Format
1145 em_format_get(void *ef __UNUSED__)
1147 return EMOTION_FORMAT_BGRA;
1151 em_video_data_size_get(void *data, int *w, int *h)
1153 Emotion_Generic_Video *ev = data;
1161 em_play(void *data, double pos)
1163 Emotion_Generic_Video *ev = data;
1168 ev->play = EINA_TRUE;
1169 INF("play: %0.3f", pos);
1171 if (ev->initializing || ev->opening)
1176 _player_send_cmd(ev, EM_CMD_PLAY);
1177 _player_send_float(ev, ev->pos);
1181 if (!_player_exec(ev))
1182 ERR("could not start player.");
1188 Emotion_Generic_Video *ev = data;
1193 ev->play = EINA_FALSE;
1195 if (!ev->file_ready)
1198 _player_send_cmd(ev, EM_CMD_STOP);
1199 _emotion_decode_stop(ev->obj);
1203 em_size_get(void *data, int *w, int *h)
1205 Emotion_Generic_Video *ev = data;
1211 em_pos_set(void *data, double pos)
1213 Emotion_Generic_Video *ev = data;
1214 float position = pos;
1216 if (!ev->file_ready)
1219 _player_send_cmd(ev, EM_CMD_POSITION_SET);
1220 _player_send_float(ev, position);
1221 _emotion_seek_done(ev->obj);
1225 em_len_get(void *data)
1227 Emotion_Generic_Video *ev = data;
1232 em_buffer_size_get(void *data __UNUSED__)
1238 em_fps_num_get(void *data)
1240 Emotion_Generic_Video *ev = data;
1241 return (int)(ev->fps * 1000.0);
1245 em_fps_den_get(void *ef __UNUSED__)
1251 em_fps_get(void *data)
1253 Emotion_Generic_Video *ev = data;
1258 em_pos_get(void *data)
1260 Emotion_Generic_Video *ev = data;
1265 em_vis_set(void *ef __UNUSED__, Emotion_Vis vis __UNUSED__)
1270 em_vis_get(void *data)
1272 Emotion_Generic_Video *ev = data;
1277 em_vis_supported(void *ef __UNUSED__, Emotion_Vis vis __UNUSED__)
1283 em_ratio_get(void *data)
1285 Emotion_Generic_Video *ev = data;
1289 static int em_video_handled(void *ef __UNUSED__)
1291 fprintf(stderr, "video handled!\n");
1295 static int em_audio_handled(void *ef __UNUSED__)
1297 fprintf(stderr, "audio handled!\n");
1301 static int em_seekable(void *data)
1303 Emotion_Generic_Video *ev = data;
1304 return ev->seekable;
1307 static void em_frame_done(void *ef __UNUSED__)
1312 em_yuv_rows_get(void *data __UNUSED__, int w __UNUSED__, int h __UNUSED__, unsigned char **yrows __UNUSED__, unsigned char **urows __UNUSED__, unsigned char **vrows __UNUSED__)
1318 em_bgra_data_get(void *data, unsigned char **bgra_data)
1320 Emotion_Generic_Video *ev = data;
1322 if (!ev || !ev->file_ready)
1326 if (!eina_semaphore_lock(&ev->shared->lock))
1329 // send current frame to emotion
1330 if (ev->shared->frame.emotion != ev->shared->frame.last)
1332 ev->shared->frame.next = ev->shared->frame.emotion;
1333 ev->shared->frame.emotion = ev->shared->frame.last;
1335 *bgra_data = ev->frame.frames[ev->shared->frame.emotion];
1337 if (ev->shared->frame_drop > 1)
1338 WRN("dropped frames: %d", ev->shared->frame_drop - 1);
1339 ev->shared->frame_drop = 0;
1341 // unlock frame here
1342 eina_semaphore_release(&ev->shared->lock, 1);
1349 em_event_feed(void *ef __UNUSED__, int event __UNUSED__)
1354 em_event_mouse_button_feed(void *ef __UNUSED__, int button __UNUSED__, int x __UNUSED__, int y __UNUSED__)
1359 em_event_mouse_move_feed(void *ef __UNUSED__, int x __UNUSED__, int y __UNUSED__)
1364 em_video_channel_count(void *data)
1366 Emotion_Generic_Video *ev = data;
1367 return ev->video_channels_count;
1371 em_video_channel_set(void *data, int channel)
1373 Emotion_Generic_Video *ev = data;
1375 if (channel < 0 || channel >= ev->video_channels_count)
1377 WRN("video channel out of range.");
1381 _player_send_cmd(ev, EM_CMD_VIDEO_TRACK_SET);
1382 _player_send_int(ev, ev->video_channels[channel].id);
1383 ev->video_channel_current = channel;
1387 em_video_channel_get(void *data)
1389 Emotion_Generic_Video *ev = data;
1390 return ev->video_channel_current;
1394 em_video_channel_name_get(void *data, int channel)
1396 Emotion_Generic_Video *ev = data;
1398 if (channel < 0 || channel >= ev->video_channels_count)
1400 WRN("video channel out of range.");
1404 return ev->video_channels[channel].name;
1408 em_video_channel_mute_set(void *data, int mute)
1410 Emotion_Generic_Video *ev = data;
1412 ev->video_mute = !!mute;
1414 if (!ev || !ev->file_ready)
1417 _player_send_cmd(ev, EM_CMD_VIDEO_MUTE_SET);
1418 _player_send_int(ev, mute);
1422 em_video_channel_mute_get(void *data)
1424 Emotion_Generic_Video *ev = data;
1425 return ev->video_mute;
1429 em_audio_channel_count(void *data)
1431 Emotion_Generic_Video *ev = data;
1432 return ev->audio_channels_count;
1436 em_audio_channel_set(void *data, int channel)
1438 Emotion_Generic_Video *ev = data;
1440 if (channel < 0 || channel >= ev->audio_channels_count)
1442 WRN("audio channel out of range.");
1446 _player_send_cmd(ev, EM_CMD_AUDIO_TRACK_SET);
1447 _player_send_int(ev, ev->audio_channels[channel].id);
1448 ev->audio_channel_current = channel;
1452 em_audio_channel_get(void *data)
1454 Emotion_Generic_Video *ev = data;
1455 return ev->audio_channel_current;
1459 em_audio_channel_name_get(void *data, int channel)
1461 Emotion_Generic_Video *ev = data;
1463 if (channel < 0 || channel >= ev->audio_channels_count)
1465 WRN("audio channel out of range.");
1469 return ev->audio_channels[channel].name;
1473 em_audio_channel_mute_set(void *data, int mute)
1475 Emotion_Generic_Video *ev = data;
1477 ev->audio_mute = !!mute;
1479 if (!ev || !ev->file_ready)
1482 _player_send_cmd(ev, EM_CMD_AUDIO_MUTE_SET);
1483 _player_send_int(ev, mute);
1487 em_audio_channel_mute_get(void *data)
1489 Emotion_Generic_Video *ev = data;
1490 return ev->audio_mute;
1494 em_audio_channel_volume_set(void *data, double vol)
1496 Emotion_Generic_Video *ev = data;
1498 if (vol > 1.0) vol = 1.0;
1499 if (vol < 0.0) vol = 0.0;
1503 if (!ev || !ev->file_ready)
1506 _player_send_cmd(ev, EM_CMD_VOLUME_SET);
1507 _player_send_float(ev, ev->volume);
1511 em_audio_channel_volume_get(void *data)
1513 Emotion_Generic_Video *ev = data;
1518 em_spu_channel_count(void *data)
1520 Emotion_Generic_Video *ev = data;
1521 return ev->spu_channels_count;
1525 em_spu_channel_set(void *data, int channel)
1527 Emotion_Generic_Video *ev = data;
1529 if (channel < 0 || channel >= ev->spu_channels_count)
1531 WRN("spu channel out of range.");
1535 _player_send_cmd(ev, EM_CMD_SPU_TRACK_SET);
1536 _player_send_int(ev, ev->spu_channels[channel].id);
1537 ev->spu_channel_current = channel;
1541 em_spu_channel_get(void *data)
1543 Emotion_Generic_Video *ev = data;
1544 return ev->spu_channel_current;
1548 em_spu_channel_name_get(void *data, int channel)
1550 Emotion_Generic_Video *ev = data;
1552 if (channel < 0 || channel >= ev->spu_channels_count)
1554 WRN("spu channel out of range.");
1558 return ev->spu_channels[channel].name;
1562 em_spu_channel_mute_set(void *data, int mute)
1564 Emotion_Generic_Video *ev = data;
1566 ev->spu_mute = !!mute;
1568 if (!ev || !ev->file_ready)
1571 _player_send_cmd(ev, EM_CMD_SPU_MUTE_SET);
1572 _player_send_int(ev, mute);
1576 em_spu_channel_mute_get(void *data)
1578 Emotion_Generic_Video *ev = data;
1579 return ev->spu_mute;
1583 em_chapter_count(void *ef __UNUSED__)
1590 em_chapter_set(void *ef __UNUSED__, int chapter __UNUSED__)
1595 em_chapter_get(void *ef __UNUSED__)
1602 em_chapter_name_get(void *ef __UNUSED__, int chapter __UNUSED__)
1608 em_speed_set(void *data, double speed)
1610 Emotion_Generic_Video *ev = data;
1614 if (!ev || !ev->file_ready)
1617 _player_send_cmd(ev, EM_CMD_SPEED_SET);
1618 _player_send_float(ev, rate);
1622 em_speed_get(void *data)
1624 Emotion_Generic_Video *ev = data;
1625 return (double)ev->speed;
1629 em_eject(void *ef __UNUSED__)
1635 em_meta_get(void *data, int meta)
1637 Emotion_Generic_Video *ev = data;
1640 case EMOTION_META_INFO_TRACK_TITLE:
1641 return ev->meta.title;
1642 case EMOTION_META_INFO_TRACK_ARTIST:
1643 return ev->meta.artist;
1644 case EMOTION_META_INFO_TRACK_ALBUM:
1645 return ev->meta.album;
1646 case EMOTION_META_INFO_TRACK_YEAR:
1647 return ev->meta.year;
1648 case EMOTION_META_INFO_TRACK_GENRE:
1649 return ev->meta.genre;
1650 case EMOTION_META_INFO_TRACK_COMMENT:
1651 return ev->meta.comment;
1652 case EMOTION_META_INFO_TRACK_DISC_ID:
1653 return ev->meta.disc_id;
1654 case EMOTION_META_INFO_TRACK_COUNT:
1655 return ev->meta.count;
1661 static Emotion_Video_Module em_module =
1664 em_shutdown, /* shutdown */
1665 em_file_open, /* file_open */
1666 em_file_close, /* file_close */
1669 em_size_get, /* size_get */
1670 em_pos_set, /* pos_set */
1671 em_len_get, /* len_get */
1672 em_buffer_size_get, /* buffer_size_get */
1673 em_fps_num_get, /* fps_num_get */
1674 em_fps_den_get, /* fps_den_get */
1675 em_fps_get, /* fps_get */
1676 em_pos_get, /* pos_get */
1677 em_vis_set, /* vis_set */
1678 em_vis_get, /* vis_get */
1679 em_vis_supported, /* vis_supported */
1680 em_ratio_get, /* ratio_get */
1681 em_video_handled, /* video_handled */
1682 em_audio_handled, /* audio_handled */
1683 em_seekable, /* seekable */
1684 em_frame_done, /* frame_done */
1685 em_format_get, /* format_get */
1686 em_video_data_size_get, /* video_data_size_get */
1687 em_yuv_rows_get, /* yuv_rows_get */
1688 em_bgra_data_get, /* bgra_data_get */
1689 em_event_feed, /* event_feed */
1690 em_event_mouse_button_feed, /* event_mouse_button_feed */
1691 em_event_mouse_move_feed, /* event_mouse_move_feed */
1692 em_video_channel_count, /* video_channel_count */
1693 em_video_channel_set, /* video_channel_set */
1694 em_video_channel_get, /* video_channel_get */
1695 em_video_channel_name_get, /* video_channel_name_get */
1696 em_video_channel_mute_set, /* video_channel_mute_set */
1697 em_video_channel_mute_get, /* video_channel_mute_get */
1698 em_audio_channel_count, /* audio_channel_count */
1699 em_audio_channel_set, /* audio_channel_set */
1700 em_audio_channel_get, /* audio_channel_get */
1701 em_audio_channel_name_get, /* audio_channel_name_get */
1702 em_audio_channel_mute_set, /* audio_channel_mute_set */
1703 em_audio_channel_mute_get, /* audio_channel_mute_get */
1704 em_audio_channel_volume_set, /* audio_channel_volume_set */
1705 em_audio_channel_volume_get, /* audio_channel_volume_get */
1706 em_spu_channel_count, /* spu_channel_count */
1707 em_spu_channel_set, /* spu_channel_set */
1708 em_spu_channel_get, /* spu_channel_get */
1709 em_spu_channel_name_get, /* spu_channel_name_get */
1710 em_spu_channel_mute_set, /* spu_channel_mute_set */
1711 em_spu_channel_mute_get, /* spu_channel_mute_get */
1712 em_chapter_count, /* chapter_count */
1713 em_chapter_set, /* chapter_set */
1714 em_chapter_get, /* chapter_get */
1715 em_chapter_name_get, /* chapter_name_get */
1716 em_speed_set, /* speed_set */
1717 em_speed_get, /* speed_get */
1718 em_eject, /* eject */
1719 em_meta_get, /* meta_get */
1720 NULL, /* priority_set */
1721 NULL, /* priority_get */
1726 module_open(Evas_Object *obj, const Emotion_Video_Module **module, void **video, Emotion_Module_Options *opt)
1732 if (_emotion_generic_log_domain < 0)
1734 eina_threads_init();
1735 eina_log_threads_enable();
1736 _emotion_generic_log_domain = eina_log_domain_register
1737 ("emotion-generic", EINA_COLOR_LIGHTCYAN);
1738 if (_emotion_generic_log_domain < 0)
1740 EINA_LOG_CRIT("Could not register log domain 'emotion-generic'");
1746 if (!em_module.init(obj, video, opt)) {
1750 *module = &em_module;
1755 static void module_close(Emotion_Video_Module *module __UNUSED__, void *video)
1757 em_module.shutdown(video);
1762 generic_module_init(void)
1766 pfx = eina_prefix_new(NULL, emotion_object_add,
1767 "EMOTION", "emotion", NULL,
1772 if (!pfx) return EINA_FALSE;
1774 return _emotion_module_register("generic", module_open, module_close);
1778 generic_module_shutdown(void)
1782 eina_prefix_free(pfx);
1785 _emotion_module_unregister("generic");
1788 #ifndef EMOTION_STATIC_BUILD_GENERIC
1790 EINA_MODULE_INIT(generic_module_init);
1791 EINA_MODULE_SHUTDOWN(generic_module_shutdown);