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" },
44 _get_player(const char *name)
46 const char *selected_name = NULL;
47 const char *libdir = eina_prefix_lib_get(pfx);
48 static char buf[PATH_MAX];
53 for (i = 0; players[i].name; i++)
55 if (!strcmp(players[i].name, name))
57 selected_name = players[i].cmdline;
63 if ((!selected_name) && (name))
70 if (selected_name[0] == '/') cmd = selected_name;
73 snprintf(buf, sizeof(buf), "%s/emotion/utils/%s",
74 libdir, selected_name);
78 DBG("Try generic player '%s'", cmd);
79 if (access(cmd, R_OK | X_OK) == 0)
81 INF("Using generic player '%s'", cmd);
86 for (i = 0; players[i].name; i++)
88 snprintf(buf, sizeof(buf), "%s/emotion/utils/%s",
89 libdir, players[i].cmdline);
90 DBG("Try generic player '%s'", buf);
91 if (access(buf, R_OK | X_OK) == 0)
93 INF("Using fallback player '%s'", buf);
98 ERR("no generic player found, given name='%s'", name ? name : "");
103 _player_send_cmd(Emotion_Generic_Video *ev, int cmd)
105 if (cmd >= EM_CMD_LAST)
107 ERR("invalid command to player.");
110 if (write(ev->fd_write, &cmd, sizeof(cmd)) < 0) perror("write");
114 _player_send_int(Emotion_Generic_Video *ev, int number)
116 if (write(ev->fd_write, &number, sizeof(number)) < 0) perror("write");
120 _player_send_float(Emotion_Generic_Video *ev, float number)
122 if (write(ev->fd_write, &number, sizeof(number)) < 0) perror("write");
126 _player_send_str(Emotion_Generic_Video *ev, const char *str, Eina_Bool stringshared)
131 len = eina_stringshare_strlen(str) + 1;
133 len = strlen(str) + 1;
134 if (write(ev->fd_write, &len, sizeof(len)) < 0) perror("write");
135 if (write(ev->fd_write, str, len) < 0) perror("write");
139 _create_shm_data(Emotion_Generic_Video *ev, const char *shmname)
144 Emotion_Generic_Video_Shared *vs;
146 shmfd = shm_open(shmname, O_CREAT | O_RDWR | O_TRUNC, 0777);
149 ERR("player: could not open shm: %s", shmname);
150 ERR("player: %s", strerror(errno));
153 size = 3 * (ev->w * ev->h * DEFAULTPITCH) + sizeof(*vs);
155 npages = (int)(size / getpagesize()) + 1;
156 size = npages * getpagesize();
158 if (ftruncate(shmfd, size))
160 ERR("error when allocating shared memory (size = %zd): "
161 "%s", size, strerror(errno));
165 vs = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, shmfd, 0);
166 if (vs == MAP_FAILED)
168 ERR("error when mapping shared memory");
175 vs->pitch = DEFAULTPITCH;
176 vs->frame.emotion = 0;
177 vs->frame.player = 1;
181 if (!eina_semaphore_new(&vs->lock, 1))
183 ERR("can not create semaphore");
186 ev->frame.frames[0] = (unsigned char *)vs + sizeof(*vs);
187 ev->frame.frames[1] = (unsigned char *)vs + sizeof(*vs) + vs->height * vs->width * vs->pitch;
188 ev->frame.frames[2] = (unsigned char *)vs + sizeof(*vs) + 2 * vs->height * vs->width * vs->pitch;
191 munmap(ev->shared, ev->shared->size);
198 _player_new_frame(Emotion_Generic_Video *ev)
202 _emotion_frame_new(ev->obj);
206 _file_open(Emotion_Generic_Video *ev)
208 INF("Opening file: %s", ev->filename);
211 if (!ev->ready || !ev->filename)
213 _player_send_cmd(ev, EM_CMD_FILE_SET);
214 _player_send_str(ev, ev->filename, EINA_TRUE);
218 _player_file_set_done(Emotion_Generic_Video *ev)
220 if (ev->file_changed)
223 ev->file_changed = EINA_FALSE;
227 if (!_create_shm_data(ev, ev->shmname))
229 ERR("could not create shared memory.");
232 _player_send_cmd(ev, EM_CMD_FILE_SET_DONE);
236 _player_ready(Emotion_Generic_Video *ev)
238 INF("received: player ready.");
240 ev->initializing = EINA_FALSE;
241 ev->ready = EINA_TRUE;
250 _player_cmd_param_read(Emotion_Generic_Video *ev, void *param, size_t size)
252 ssize_t done, todo, i;
254 /* When a parameter must be read, we cannot make sure it will be entirely
255 * available. Thus we store the bytes that could be read in a temp buffer,
256 * and when more data is read we try to complete the buffer and finally use
261 ev->cmd.tmp = malloc(size);
263 ev->cmd.total = size;
266 todo = ev->cmd.total - ev->cmd.i;
268 done = read(ev->fd_read, &ev->cmd.tmp[i], todo);
270 if (done < 0 && errno != EINTR && errno != EAGAIN)
277 ERR("problem when reading parameter from pipe.");
284 memcpy(param, ev->cmd.tmp, size);
297 _player_frame_resize(Emotion_Generic_Video *ev)
301 w = ev->cmd.param.size.width;
302 h = ev->cmd.param.size.height;
304 INF("received frame resize: %dx%d", w, h);
307 ev->ratio = (float)w / h;
312 _emotion_frame_resize(ev->obj, ev->w, ev->h, ev->ratio);
316 _player_length_changed(Emotion_Generic_Video *ev)
318 float length = ev->cmd.param.f_num;
320 INF("received length changed: %0.3f", length);
323 _emotion_video_pos_update(ev->obj, ev->pos, ev->len);
327 _player_position_changed(Emotion_Generic_Video *ev)
329 float position = ev->cmd.param.f_num;
331 INF("received position changed: %0.3f", position);
334 _emotion_video_pos_update(ev->obj, ev->pos, ev->len);
335 /* hmmm. no _emotion_progress_set() is for "buffering" progress.
339 float progress = ev->pos / ev->len;
341 snprintf(buf, sizeof(buf), "%0.1f%%", progress * 100);
343 _emotion_progress_set(ev->obj, buf, progress);
348 _player_seekable_changed(Emotion_Generic_Video *ev)
350 int seekable = ev->cmd.param.i_num;
352 INF("received seekable changed: %d", seekable);
354 seekable = !!seekable;
356 ev->seekable = seekable;
360 _audio_channels_free(Emotion_Generic_Video *ev)
363 for (i = 0; i < ev->audio_channels_count; i++)
364 eina_stringshare_del(ev->audio_channels[i].name);
365 free(ev->audio_channels);
366 ev->audio_channels_count = 0;
370 _video_channels_free(Emotion_Generic_Video *ev)
373 for (i = 0; i < ev->video_channels_count; i++)
374 eina_stringshare_del(ev->video_channels[i].name);
375 free(ev->video_channels);
376 ev->video_channels_count = 0;
380 _spu_channels_free(Emotion_Generic_Video *ev)
383 for (i = 0; i < ev->spu_channels_count; i++)
384 eina_stringshare_del(ev->spu_channels[i].name);
385 free(ev->spu_channels);
386 ev->spu_channels_count = 0;
390 _player_tracks_info(Emotion_Generic_Video *ev, Emotion_Generic_Channel **channels, int *count, int *current)
392 Emotion_Generic_Channel *pchannels;
395 *count = ev->cmd.param.track.total;
396 *current = ev->cmd.param.track.current;
397 pchannels = ev->cmd.param.track.channels;
399 INF("number of tracks: %d (current = %d):", *count, *current);
400 for (i = 0; i < *count; i++)
402 INF("\tchannel %d: %s", pchannels[i].id, pchannels[i].name);
405 *channels = pchannels;
409 _player_audio_tracks_info(Emotion_Generic_Video *ev)
411 INF("Receiving audio channels:");
412 if (ev->audio_channels_count)
413 _audio_channels_free(ev);
415 _player_tracks_info(ev, &ev->audio_channels, &ev->audio_channels_count,
416 &ev->audio_channel_current);
420 _player_video_tracks_info(Emotion_Generic_Video *ev)
422 INF("Receiving video channels:");
423 if (ev->video_channels_count)
424 _video_channels_free(ev);
426 _player_tracks_info(ev, &ev->video_channels, &ev->video_channels_count,
427 &ev->video_channel_current);
431 _player_spu_tracks_info(Emotion_Generic_Video *ev)
433 INF("Receiving spu channels:");
434 if (ev->spu_channels_count)
435 _spu_channels_free(ev);
437 _player_tracks_info(ev, &ev->spu_channels, &ev->spu_channels_count,
438 &ev->spu_channel_current);
442 _player_meta_info_free(Emotion_Generic_Video *ev)
444 eina_stringshare_replace(&ev->meta.title, NULL);
445 eina_stringshare_replace(&ev->meta.artist, NULL);
446 eina_stringshare_replace(&ev->meta.album, NULL);
447 eina_stringshare_replace(&ev->meta.year, NULL);
448 eina_stringshare_replace(&ev->meta.genre, NULL);
449 eina_stringshare_replace(&ev->meta.comment, NULL);
450 eina_stringshare_replace(&ev->meta.disc_id, NULL);
451 eina_stringshare_replace(&ev->meta.count, NULL);
455 _player_meta_info_read(Emotion_Generic_Video *ev)
457 INF("Receiving meta info:");
458 _player_meta_info_free(ev);
459 ev->meta.title = ev->cmd.param.meta.title;
460 ev->meta.artist = ev->cmd.param.meta.artist;
461 ev->meta.album = ev->cmd.param.meta.album;
462 ev->meta.year = ev->cmd.param.meta.year;
463 ev->meta.genre = ev->cmd.param.meta.genre;
464 ev->meta.comment = ev->cmd.param.meta.comment;
465 ev->meta.disc_id = ev->cmd.param.meta.disc_id;
466 ev->meta.count = ev->cmd.param.meta.count;
467 INF("title: '%s'", ev->meta.title);
468 INF("artist: '%s'", ev->meta.artist);
469 INF("album: '%s'", ev->meta.album);
470 INF("year: '%s'", ev->meta.year);
471 INF("genre: '%s'", ev->meta.genre);
472 INF("comment: '%s'", ev->meta.comment);
473 INF("disc_id: '%s'", ev->meta.disc_id);
474 INF("count: '%s'", ev->meta.count);
478 _player_file_closed(Emotion_Generic_Video *ev)
480 INF("Closed previous file.");
481 eina_semaphore_free(&ev->shared->lock);
482 ev->closing = EINA_FALSE;
489 _player_open_done(Emotion_Generic_Video *ev)
493 success = ev->cmd.param.i_num;
494 shm_unlink(ev->shmname);
496 if (ev->file_changed)
499 ev->file_changed = EINA_FALSE;
503 ev->opening = EINA_FALSE;
506 ERR("Could not open file.");
510 ev->file_ready = EINA_TRUE;
512 _emotion_open_done(ev->obj);
516 _player_send_cmd(ev, EM_CMD_PLAY);
517 _player_send_float(ev, ev->pos);
520 _player_send_cmd(ev, EM_CMD_VOLUME_SET);
521 _player_send_float(ev, ev->volume);
523 _player_send_cmd(ev, EM_CMD_SPEED_SET);
524 _player_send_float(ev, ev->speed);
526 int mute = ev->audio_mute;
527 _player_send_cmd(ev, EM_CMD_AUDIO_MUTE_SET);
528 _player_send_int(ev, mute);
530 mute = ev->video_mute;
531 _player_send_cmd(ev, EM_CMD_VIDEO_MUTE_SET);
532 _player_send_int(ev, mute);
535 _player_send_cmd(ev, EM_CMD_SPU_MUTE_SET);
536 _player_send_int(ev, mute);
542 _player_cmd_process(Emotion_Generic_Video *ev)
544 switch (ev->cmd.type) {
548 case EM_RESULT_FRAME_NEW:
549 _player_new_frame(ev);
551 case EM_RESULT_FILE_SET:
552 _player_file_set_done(ev);
554 case EM_RESULT_FILE_SET_DONE:
555 _player_open_done(ev);
557 case EM_RESULT_FILE_CLOSE:
558 _player_file_closed(ev);
560 case EM_RESULT_PLAYBACK_STOPPED:
561 _emotion_playback_finished(ev->obj);
563 case EM_RESULT_FRAME_SIZE:
564 _player_frame_resize(ev);
566 case EM_RESULT_LENGTH_CHANGED:
567 _player_length_changed(ev);
569 case EM_RESULT_POSITION_CHANGED:
570 _player_position_changed(ev);
572 case EM_RESULT_SEEKABLE_CHANGED:
573 _player_seekable_changed(ev);
575 case EM_RESULT_AUDIO_TRACK_INFO:
576 _player_audio_tracks_info(ev);
578 case EM_RESULT_VIDEO_TRACK_INFO:
579 _player_video_tracks_info(ev);
581 case EM_RESULT_SPU_TRACK_INFO:
582 _player_spu_tracks_info(ev);
584 case EM_RESULT_META_INFO:
585 _player_meta_info_read(ev);
588 WRN("received wrong command: %d", ev->cmd.type);
595 _player_cmd_single_int_process(Emotion_Generic_Video *ev)
597 if (!_player_cmd_param_read(ev, &ev->cmd.param.i_num, sizeof(ev->cmd.param.i_num)))
600 _player_cmd_process(ev);
604 _player_cmd_single_float_process(Emotion_Generic_Video *ev)
606 if (!_player_cmd_param_read(ev, &ev->cmd.param.f_num, sizeof(ev->cmd.param.f_num)))
609 _player_cmd_process(ev);
613 _player_cmd_double_int_process(Emotion_Generic_Video *ev)
617 if (ev->cmd.num_params == 0)
619 ev->cmd.num_params = 2;
620 ev->cmd.cur_param = 0;
621 ev->cmd.param.size.width = 0;
622 ev->cmd.param.size.height = 0;
625 if (!_player_cmd_param_read(ev, ¶m, sizeof(param)))
628 if (ev->cmd.cur_param == 0)
629 ev->cmd.param.size.width = param;
631 ev->cmd.param.size.height = param;
634 if (ev->cmd.cur_param == ev->cmd.num_params)
635 _player_cmd_process(ev);
639 _player_cmd_track_info(Emotion_Generic_Video *ev)
644 if (ev->cmd.num_params == 0)
646 ev->cmd.cur_param = 0;
647 ev->cmd.num_params = 2;
648 ev->cmd.param.track.channels = NULL;
652 while (ev->cmd.cur_param < 2)
654 if (!_player_cmd_param_read(ev, ¶m, sizeof(param)))
657 if (ev->cmd.cur_param == 0)
658 ev->cmd.param.track.current = param;
661 ev->cmd.param.track.total = param;
662 ev->cmd.num_params += param * 2;
663 ev->cmd.param.track.channels =
664 calloc(param, sizeof(*ev->cmd.param.track.channels));
669 if (ev->cmd.cur_param == ev->cmd.num_params)
671 _player_cmd_process(ev);
675 i = (ev->cmd.cur_param - 2) / 2;
676 if ((ev->cmd.cur_param % 2) == 0) // reading track id
678 if (!_player_cmd_param_read(ev, ¶m, sizeof(param)))
680 ev->cmd.param.track.channels[i].id = param;
683 else // reading track name
687 if (ev->cmd.s_len == -1)
689 if (!_player_cmd_param_read(ev, ¶m, sizeof(param)))
691 ev->cmd.s_len = param;
694 if (!_player_cmd_param_read(ev, buf, ev->cmd.s_len))
696 ev->cmd.param.track.channels[i].name =
697 eina_stringshare_add_length(buf, ev->cmd.s_len);
702 if (ev->cmd.cur_param == ev->cmd.num_params)
703 _player_cmd_process(ev);
707 _player_cmd_meta_info(Emotion_Generic_Video *ev)
713 if (ev->cmd.num_params == 0)
715 ev->cmd.cur_param = 0;
716 ev->cmd.num_params = 8;
717 ev->cmd.param.meta.title = NULL;
718 ev->cmd.param.meta.artist = NULL;
719 ev->cmd.param.meta.album = NULL;
720 ev->cmd.param.meta.year = NULL;
721 ev->cmd.param.meta.genre = NULL;
722 ev->cmd.param.meta.comment = NULL;
723 ev->cmd.param.meta.disc_id = NULL;
724 ev->cmd.param.meta.count = NULL;
728 if (ev->cmd.s_len == -1)
730 if (!_player_cmd_param_read(ev, ¶m, sizeof(param)))
732 ev->cmd.s_len = param;
735 if (!_player_cmd_param_read(ev, buf, ev->cmd.s_len))
738 info = eina_stringshare_add_length(buf, ev->cmd.s_len);
741 if (ev->cmd.cur_param == 0)
742 ev->cmd.param.meta.title = info;
743 else if (ev->cmd.cur_param == 1)
744 ev->cmd.param.meta.artist = info;
745 else if (ev->cmd.cur_param == 2)
746 ev->cmd.param.meta.album = info;
747 else if (ev->cmd.cur_param == 3)
748 ev->cmd.param.meta.year = info;
749 else if (ev->cmd.cur_param == 4)
750 ev->cmd.param.meta.genre = info;
751 else if (ev->cmd.cur_param == 5)
752 ev->cmd.param.meta.comment = info;
753 else if (ev->cmd.cur_param == 6)
754 ev->cmd.param.meta.disc_id = info;
755 else if (ev->cmd.cur_param == 7)
756 ev->cmd.param.meta.count = info;
760 if (ev->cmd.cur_param == 8)
761 _player_cmd_process(ev);
765 _player_cmd_read(Emotion_Generic_Video *ev)
767 if (ev->cmd.type < 0)
769 if (!_player_cmd_param_read(ev, &ev->cmd.type, sizeof(ev->cmd.type)))
771 ev->cmd.num_params = 0;
774 switch (ev->cmd.type) {
776 case EM_RESULT_FILE_SET:
777 case EM_RESULT_PLAYBACK_STOPPED:
778 case EM_RESULT_FILE_CLOSE:
779 case EM_RESULT_FRAME_NEW:
780 _player_cmd_process(ev);
782 case EM_RESULT_FILE_SET_DONE:
783 case EM_RESULT_SEEKABLE_CHANGED:
784 _player_cmd_single_int_process(ev);
786 case EM_RESULT_LENGTH_CHANGED:
787 case EM_RESULT_POSITION_CHANGED:
788 _player_cmd_single_float_process(ev);
790 case EM_RESULT_FRAME_SIZE:
791 _player_cmd_double_int_process(ev);
793 case EM_RESULT_AUDIO_TRACK_INFO:
794 case EM_RESULT_VIDEO_TRACK_INFO:
795 case EM_RESULT_SPU_TRACK_INFO:
796 _player_cmd_track_info(ev);
798 case EM_RESULT_META_INFO:
799 _player_cmd_meta_info(ev);
803 WRN("received wrong command: %d", ev->cmd.type);
809 _player_cmd_handler_cb(void *data, Ecore_Fd_Handler *fd_handler)
811 Emotion_Generic_Video *ev = data;
813 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR))
815 ERR("an error occurred on fd_read %d.", ev->fd_read);
816 return ECORE_CALLBACK_CANCEL;
819 _player_cmd_read(ev);
821 return ECORE_CALLBACK_RENEW;
825 _player_data_cb(void *data, int type __UNUSED__, void *event)
827 Ecore_Exe_Event_Data *ev = event;
828 Emotion_Generic_Video *evideo = data;
831 if (ev->exe != evideo->player.exe)
833 ERR("slave != ev->exe");
834 return ECORE_CALLBACK_DONE;
837 for (i = 0; ev->lines[i].line; i++)
838 INF("received input from player: \"%s\"", ev->lines[i].line);
840 return ECORE_CALLBACK_DONE;
844 _player_add_cb(void *data, int type __UNUSED__, void *event)
846 Ecore_Exe_Event_Add *event_add = event;
847 Ecore_Exe *player = event_add->exe;
848 Emotion_Generic_Video *ev = data;
850 if (ev->player.exe != player)
852 ERR("ev->player != player.");
853 return ECORE_CALLBACK_DONE;
856 _player_send_cmd(ev, EM_CMD_INIT);
857 _player_send_str(ev, ev->shmname, EINA_TRUE);
859 return ECORE_CALLBACK_DONE;
863 _player_del_cb(void *data, int type __UNUSED__, void *event __UNUSED__)
865 Emotion_Generic_Video *ev = data;
868 ev->player.exe = NULL;
869 ev->ready = EINA_FALSE;
870 ev->file_ready = EINA_FALSE;
871 ecore_main_fd_handler_del(ev->fd_handler);
876 _emotion_decode_stop(ev->obj);
878 return ECORE_CALLBACK_DONE;
882 _player_exec(Emotion_Generic_Video *ev)
888 if (pipe(pipe_out) == -1)
890 ERR("could not create pipe for communication emotion -> player: %s", strerror(errno));
894 if (pipe(pipe_in) == -1)
896 ERR("could not create pipe for communication player -> emotion: %s", strerror(errno));
902 snprintf(buf, sizeof(buf), "%s %d %d\n", ev->cmdline, pipe_out[0], pipe_in[1]);
904 ev->player.exe = ecore_exe_pipe_run(
906 ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_WRITE |
907 ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_NOT_LEADER,
910 INF("created pipe emotion -> player: %d -> %d", pipe_out[1], pipe_out[0]);
911 INF("created pipe player -> emotion: %d -> %d", pipe_in[1], pipe_in[0]);
923 ev->fd_read = pipe_in[0];
924 ev->fd_write = pipe_out[1];
926 ev->fd_handler = ecore_main_fd_handler_add(
927 ev->fd_read, ECORE_FD_READ | ECORE_FD_ERROR, _player_cmd_handler_cb, ev,
934 _fork_and_exec(Evas_Object *obj __UNUSED__, Emotion_Generic_Video *ev)
939 gettimeofday(&tv, NULL);
940 snprintf(shmname, sizeof(shmname), "/em-generic-shm_%d_%d",
941 (int)tv.tv_sec, (int)tv.tv_usec);
943 ev->shmname = eina_stringshare_add(shmname);
945 ev->player_add = ecore_event_handler_add(
946 ECORE_EXE_EVENT_ADD, _player_add_cb, ev);
947 ev->player_del = ecore_event_handler_add(
948 ECORE_EXE_EVENT_DEL, _player_del_cb, ev);
949 ev->player_data = ecore_event_handler_add(
950 ECORE_EXE_EVENT_DATA, _player_data_cb, ev);
953 if (!_player_exec(ev))
955 ERR("could not start player.");
959 ev->initializing = EINA_TRUE;
965 em_init(Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt)
967 Emotion_Generic_Video *ev;
970 if (!emotion_video) return 0;
971 player = _get_player(opt ? opt->player : NULL);
972 if (!player) return 0;
974 ev = (Emotion_Generic_Video *)calloc(1, sizeof(*ev));
981 ev->audio_mute = EINA_FALSE;
985 ev->cmdline = eina_stringshare_add(player);
988 return _fork_and_exec(obj, ev);
992 em_shutdown(void *data)
994 Emotion_Generic_Video *ev = data;
1000 ecore_exe_terminate(ev->player.exe);
1001 ecore_exe_free(ev->player.exe);
1002 ev->player.exe = NULL;
1006 munmap(ev->shared, ev->shared->size);
1008 if (ev->fd_read >= 0)
1010 if (ev->fd_write >= 0)
1011 close(ev->fd_write);
1013 ecore_main_fd_handler_del(ev->fd_handler);
1015 eina_stringshare_del(ev->cmdline);
1016 eina_stringshare_del(ev->shmname);
1018 ecore_event_handler_del(ev->player_add);
1019 ecore_event_handler_del(ev->player_data);
1020 ecore_event_handler_del(ev->player_del);
1025 static unsigned char
1026 em_file_open(const char *file, Evas_Object *obj __UNUSED__, void *data)
1028 Emotion_Generic_Video *ev = data;
1029 INF("file set: %s", file);
1032 eina_stringshare_replace(&ev->filename, file);
1040 if (ev->ready && ev->opening)
1042 INF("file changed while opening.");
1043 ev->file_changed = EINA_TRUE;
1047 ev->opening = EINA_TRUE;
1056 em_file_close(void *data)
1058 Emotion_Generic_Video *ev = data;
1060 if (!ev || !ev->filename) return;
1062 INF("file close: %s", ev->filename);
1064 eina_stringshare_replace(&ev->filename, NULL);
1066 ev->file_ready = EINA_FALSE;
1067 _audio_channels_free(ev);
1068 _video_channels_free(ev);
1069 _spu_channels_free(ev);
1070 _player_meta_info_free(ev);
1075 _player_send_cmd(ev, EM_CMD_FILE_CLOSE);
1076 ev->closing = EINA_TRUE;
1079 static Emotion_Format
1080 em_format_get(void *ef __UNUSED__)
1082 return EMOTION_FORMAT_BGRA;
1086 em_video_data_size_get(void *data, int *w, int *h)
1088 Emotion_Generic_Video *ev = data;
1096 em_play(void *data, double pos)
1098 Emotion_Generic_Video *ev = data;
1103 ev->play = EINA_TRUE;
1104 INF("play: %0.3f", pos);
1106 if (ev->initializing || ev->opening)
1111 _player_send_cmd(ev, EM_CMD_PLAY);
1112 _player_send_float(ev, ev->pos);
1116 if (!_player_exec(ev))
1117 ERR("could not start player.");
1123 Emotion_Generic_Video *ev = data;
1128 ev->play = EINA_FALSE;
1130 if (!ev->file_ready)
1133 _player_send_cmd(ev, EM_CMD_STOP);
1134 _emotion_decode_stop(ev->obj);
1138 em_size_get(void *data, int *w, int *h)
1140 Emotion_Generic_Video *ev = data;
1146 em_pos_set(void *data, double pos)
1148 Emotion_Generic_Video *ev = data;
1149 float position = pos;
1151 if (!ev->file_ready)
1154 _player_send_cmd(ev, EM_CMD_POSITION_SET);
1155 _player_send_float(ev, position);
1156 _emotion_seek_done(ev->obj);
1160 em_len_get(void *data)
1162 Emotion_Generic_Video *ev = data;
1167 em_buffer_size_get(void *data __UNUSED__)
1173 em_fps_num_get(void *data)
1175 Emotion_Generic_Video *ev = data;
1176 return (int)(ev->fps * 1000.0);
1180 em_fps_den_get(void *ef __UNUSED__)
1186 em_fps_get(void *data)
1188 Emotion_Generic_Video *ev = data;
1193 em_pos_get(void *data)
1195 Emotion_Generic_Video *ev = data;
1200 em_vis_set(void *ef __UNUSED__, Emotion_Vis vis __UNUSED__)
1205 em_vis_get(void *data)
1207 Emotion_Generic_Video *ev = data;
1212 em_vis_supported(void *ef __UNUSED__, Emotion_Vis vis __UNUSED__)
1218 em_ratio_get(void *data)
1220 Emotion_Generic_Video *ev = data;
1224 static int em_video_handled(void *ef __UNUSED__)
1226 fprintf(stderr, "video handled!\n");
1230 static int em_audio_handled(void *ef __UNUSED__)
1232 fprintf(stderr, "audio handled!\n");
1236 static int em_seekable(void *data)
1238 Emotion_Generic_Video *ev = data;
1239 return ev->seekable;
1242 static void em_frame_done(void *ef __UNUSED__)
1247 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__)
1253 em_bgra_data_get(void *data, unsigned char **bgra_data)
1255 Emotion_Generic_Video *ev = data;
1257 if (!ev || !ev->file_ready)
1261 if (!eina_semaphore_lock(&ev->shared->lock))
1264 // send current frame to emotion
1265 if (ev->shared->frame.emotion != ev->shared->frame.last)
1267 ev->shared->frame.next = ev->shared->frame.emotion;
1268 ev->shared->frame.emotion = ev->shared->frame.last;
1270 *bgra_data = ev->frame.frames[ev->shared->frame.emotion];
1272 if (ev->shared->frame_drop > 1)
1273 WRN("dropped frames: %d", ev->shared->frame_drop - 1);
1274 ev->shared->frame_drop = 0;
1276 // unlock frame here
1277 eina_semaphore_release(&ev->shared->lock, 1);
1284 em_event_feed(void *ef __UNUSED__, int event __UNUSED__)
1289 em_event_mouse_button_feed(void *ef __UNUSED__, int button __UNUSED__, int x __UNUSED__, int y __UNUSED__)
1294 em_event_mouse_move_feed(void *ef __UNUSED__, int x __UNUSED__, int y __UNUSED__)
1299 em_video_channel_count(void *data)
1301 Emotion_Generic_Video *ev = data;
1302 return ev->video_channels_count;
1306 em_video_channel_set(void *data, int channel)
1308 Emotion_Generic_Video *ev = data;
1310 if (channel < 0 || channel >= ev->video_channels_count)
1312 WRN("video channel out of range.");
1316 _player_send_cmd(ev, EM_CMD_VIDEO_TRACK_SET);
1317 _player_send_int(ev, ev->video_channels[channel].id);
1318 ev->video_channel_current = channel;
1322 em_video_channel_get(void *data)
1324 Emotion_Generic_Video *ev = data;
1325 return ev->video_channel_current;
1329 em_video_channel_name_get(void *data, int channel)
1331 Emotion_Generic_Video *ev = data;
1333 if (channel < 0 || channel >= ev->video_channels_count)
1335 WRN("video channel out of range.");
1339 return ev->video_channels[channel].name;
1343 em_video_channel_mute_set(void *data, int mute)
1345 Emotion_Generic_Video *ev = data;
1347 ev->video_mute = !!mute;
1349 if (!ev || !ev->file_ready)
1352 _player_send_cmd(ev, EM_CMD_VIDEO_MUTE_SET);
1353 _player_send_int(ev, mute);
1357 em_video_channel_mute_get(void *data)
1359 Emotion_Generic_Video *ev = data;
1360 return ev->video_mute;
1364 em_audio_channel_count(void *data)
1366 Emotion_Generic_Video *ev = data;
1367 return ev->audio_channels_count;
1371 em_audio_channel_set(void *data, int channel)
1373 Emotion_Generic_Video *ev = data;
1375 if (channel < 0 || channel >= ev->audio_channels_count)
1377 WRN("audio channel out of range.");
1381 _player_send_cmd(ev, EM_CMD_AUDIO_TRACK_SET);
1382 _player_send_int(ev, ev->audio_channels[channel].id);
1383 ev->audio_channel_current = channel;
1387 em_audio_channel_get(void *data)
1389 Emotion_Generic_Video *ev = data;
1390 return ev->audio_channel_current;
1394 em_audio_channel_name_get(void *data, int channel)
1396 Emotion_Generic_Video *ev = data;
1398 if (channel < 0 || channel >= ev->audio_channels_count)
1400 WRN("audio channel out of range.");
1404 return ev->audio_channels[channel].name;
1408 em_audio_channel_mute_set(void *data, int mute)
1410 Emotion_Generic_Video *ev = data;
1412 ev->audio_mute = !!mute;
1414 if (!ev || !ev->file_ready)
1417 _player_send_cmd(ev, EM_CMD_AUDIO_MUTE_SET);
1418 _player_send_int(ev, mute);
1422 em_audio_channel_mute_get(void *data)
1424 Emotion_Generic_Video *ev = data;
1425 return ev->audio_mute;
1429 em_audio_channel_volume_set(void *data, double vol)
1431 Emotion_Generic_Video *ev = data;
1433 if (vol > 1.0) vol = 1.0;
1434 if (vol < 0.0) vol = 0.0;
1438 if (!ev || !ev->file_ready)
1441 _player_send_cmd(ev, EM_CMD_VOLUME_SET);
1442 _player_send_float(ev, ev->volume);
1446 em_audio_channel_volume_get(void *data)
1448 Emotion_Generic_Video *ev = data;
1453 em_spu_channel_count(void *data)
1455 Emotion_Generic_Video *ev = data;
1456 return ev->spu_channels_count;
1460 em_spu_channel_set(void *data, int channel)
1462 Emotion_Generic_Video *ev = data;
1464 if (channel < 0 || channel >= ev->spu_channels_count)
1466 WRN("spu channel out of range.");
1470 _player_send_cmd(ev, EM_CMD_SPU_TRACK_SET);
1471 _player_send_int(ev, ev->spu_channels[channel].id);
1472 ev->spu_channel_current = channel;
1476 em_spu_channel_get(void *data)
1478 Emotion_Generic_Video *ev = data;
1479 return ev->spu_channel_current;
1483 em_spu_channel_name_get(void *data, int channel)
1485 Emotion_Generic_Video *ev = data;
1487 if (channel < 0 || channel >= ev->spu_channels_count)
1489 WRN("spu channel out of range.");
1493 return ev->spu_channels[channel].name;
1497 em_spu_channel_mute_set(void *data, int mute)
1499 Emotion_Generic_Video *ev = data;
1501 ev->spu_mute = !!mute;
1503 if (!ev || !ev->file_ready)
1506 _player_send_cmd(ev, EM_CMD_SPU_MUTE_SET);
1507 _player_send_int(ev, mute);
1511 em_spu_channel_mute_get(void *data)
1513 Emotion_Generic_Video *ev = data;
1514 return ev->spu_mute;
1518 em_chapter_count(void *ef __UNUSED__)
1525 em_chapter_set(void *ef __UNUSED__, int chapter __UNUSED__)
1530 em_chapter_get(void *ef __UNUSED__)
1537 em_chapter_name_get(void *ef __UNUSED__, int chapter __UNUSED__)
1543 em_speed_set(void *data, double speed)
1545 Emotion_Generic_Video *ev = data;
1549 if (!ev || !ev->file_ready)
1552 _player_send_cmd(ev, EM_CMD_SPEED_SET);
1553 _player_send_float(ev, rate);
1557 em_speed_get(void *data)
1559 Emotion_Generic_Video *ev = data;
1560 return (double)ev->speed;
1564 em_eject(void *ef __UNUSED__)
1570 em_meta_get(void *data, int meta)
1572 Emotion_Generic_Video *ev = data;
1575 case EMOTION_META_INFO_TRACK_TITLE:
1576 return ev->meta.title;
1577 case EMOTION_META_INFO_TRACK_ARTIST:
1578 return ev->meta.artist;
1579 case EMOTION_META_INFO_TRACK_ALBUM:
1580 return ev->meta.album;
1581 case EMOTION_META_INFO_TRACK_YEAR:
1582 return ev->meta.year;
1583 case EMOTION_META_INFO_TRACK_GENRE:
1584 return ev->meta.genre;
1585 case EMOTION_META_INFO_TRACK_COMMENT:
1586 return ev->meta.comment;
1587 case EMOTION_META_INFO_TRACK_DISC_ID:
1588 return ev->meta.disc_id;
1589 case EMOTION_META_INFO_TRACK_COUNT:
1590 return ev->meta.count;
1596 static Emotion_Video_Module em_module =
1599 em_shutdown, /* shutdown */
1600 em_file_open, /* file_open */
1601 em_file_close, /* file_close */
1604 em_size_get, /* size_get */
1605 em_pos_set, /* pos_set */
1606 em_len_get, /* len_get */
1607 em_buffer_size_get, /* buffer_size_get */
1608 em_fps_num_get, /* fps_num_get */
1609 em_fps_den_get, /* fps_den_get */
1610 em_fps_get, /* fps_get */
1611 em_pos_get, /* pos_get */
1612 em_vis_set, /* vis_set */
1613 em_vis_get, /* vis_get */
1614 em_vis_supported, /* vis_supported */
1615 em_ratio_get, /* ratio_get */
1616 em_video_handled, /* video_handled */
1617 em_audio_handled, /* audio_handled */
1618 em_seekable, /* seekable */
1619 em_frame_done, /* frame_done */
1620 em_format_get, /* format_get */
1621 em_video_data_size_get, /* video_data_size_get */
1622 em_yuv_rows_get, /* yuv_rows_get */
1623 em_bgra_data_get, /* bgra_data_get */
1624 em_event_feed, /* event_feed */
1625 em_event_mouse_button_feed, /* event_mouse_button_feed */
1626 em_event_mouse_move_feed, /* event_mouse_move_feed */
1627 em_video_channel_count, /* video_channel_count */
1628 em_video_channel_set, /* video_channel_set */
1629 em_video_channel_get, /* video_channel_get */
1630 em_video_channel_name_get, /* video_channel_name_get */
1631 em_video_channel_mute_set, /* video_channel_mute_set */
1632 em_video_channel_mute_get, /* video_channel_mute_get */
1633 em_audio_channel_count, /* audio_channel_count */
1634 em_audio_channel_set, /* audio_channel_set */
1635 em_audio_channel_get, /* audio_channel_get */
1636 em_audio_channel_name_get, /* audio_channel_name_get */
1637 em_audio_channel_mute_set, /* audio_channel_mute_set */
1638 em_audio_channel_mute_get, /* audio_channel_mute_get */
1639 em_audio_channel_volume_set, /* audio_channel_volume_set */
1640 em_audio_channel_volume_get, /* audio_channel_volume_get */
1641 em_spu_channel_count, /* spu_channel_count */
1642 em_spu_channel_set, /* spu_channel_set */
1643 em_spu_channel_get, /* spu_channel_get */
1644 em_spu_channel_name_get, /* spu_channel_name_get */
1645 em_spu_channel_mute_set, /* spu_channel_mute_set */
1646 em_spu_channel_mute_get, /* spu_channel_mute_get */
1647 em_chapter_count, /* chapter_count */
1648 em_chapter_set, /* chapter_set */
1649 em_chapter_get, /* chapter_get */
1650 em_chapter_name_get, /* chapter_name_get */
1651 em_speed_set, /* speed_set */
1652 em_speed_get, /* speed_get */
1653 em_eject, /* eject */
1654 em_meta_get, /* meta_get */
1655 NULL, /* priority_set */
1656 NULL, /* priority_get */
1661 module_open(Evas_Object *obj, const Emotion_Video_Module **module, void **video, Emotion_Module_Options *opt)
1667 if (_emotion_generic_log_domain < 0)
1669 eina_threads_init();
1670 eina_log_threads_enable();
1671 _emotion_generic_log_domain = eina_log_domain_register
1672 ("emotion-generic", EINA_COLOR_LIGHTCYAN);
1673 if (_emotion_generic_log_domain < 0)
1675 EINA_LOG_CRIT("Could not register log domain 'emotion-generic'");
1681 if (!em_module.init(obj, video, opt)) {
1685 *module = &em_module;
1690 static void module_close(Emotion_Video_Module *module __UNUSED__, void *video)
1692 em_module.shutdown(video);
1697 generic_module_init(void)
1701 pfx = eina_prefix_new(NULL, emotion_object_add,
1702 "EMOTION", "emotion", NULL,
1707 if (!pfx) return EINA_FALSE;
1709 return _emotion_module_register("generic", module_open, module_close);
1713 generic_module_shutdown(void)
1717 eina_prefix_free(pfx);
1720 _emotion_module_unregister("generic");
1723 #ifndef EMOTION_STATIC_BUILD_GENERIC
1725 EINA_MODULE_INIT(generic_module_init);
1726 EINA_MODULE_SHUTDOWN(generic_module_shutdown);