#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
+
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
+#include <errno.h>
+
#include <Eina.h>
#include <Evas.h>
+#include <Ecore.h>
#include "Emotion.h"
#include "emotion_private.h"
ERR("invalid command to player.");
return;
}
- write(ev->fd_write, &cmd, sizeof(cmd));
+ if (write(ev->fd_write, &cmd, sizeof(cmd)) < 0) perror("write");
}
static void
_player_send_int(Emotion_Generic_Video *ev, int number)
{
- write(ev->fd_write, &number, sizeof(number));
+ if (write(ev->fd_write, &number, sizeof(number)) < 0) perror("write");
}
static void
_player_send_float(Emotion_Generic_Video *ev, float number)
{
- write(ev->fd_write, &number, sizeof(number));
+ if (write(ev->fd_write, &number, sizeof(number)) < 0) perror("write");
}
static void
len = eina_stringshare_strlen(str) + 1;
else
len = strlen(str) + 1;
- write(ev->fd_write, &len, sizeof(len));
- write(ev->fd_write, str, len);
+ if (write(ev->fd_write, &len, sizeof(len)) < 0) perror("write");
+ if (write(ev->fd_write, str, len) < 0) perror("write");
}
static Eina_Bool
vs = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, shmfd, 0);
if (vs == MAP_FAILED)
{
- ERR("error when mapping shared memory.\n");
+ ERR("error when mapping shared memory");
return EINA_FALSE;
}
vs->frame.player = 1;
vs->frame.last = 2;
vs->frame.next = 2;
- sem_init(&vs->lock, 1, 1);
+ vs->frame_drop = 0;
+ if (!eina_semaphore_new(&vs->lock, 1))
+ {
+ ERR("can not create semaphore");
+ return EINA_FALSE;
+ }
ev->frame.frames[0] = (unsigned char *)vs + sizeof(*vs);
ev->frame.frames[1] = (unsigned char *)vs + sizeof(*vs) + vs->height * vs->width * vs->pitch;
ev->frame.frames[2] = (unsigned char *)vs + sizeof(*vs) + 2 * vs->height * vs->width * vs->pitch;
static void
_player_new_frame(Emotion_Generic_Video *ev)
{
- if (!ev->drop++)
- _emotion_frame_new(ev->obj);
+ if (!ev->file_ready)
+ return;
+ _emotion_frame_new(ev->obj);
}
static void
_file_open(Emotion_Generic_Video *ev)
{
INF("Opening file: %s", ev->filename);
- ev->w = DEFAULTWIDTH;
- ev->h = DEFAULTHEIGHT;
- ev->ratio = (double)DEFAULTWIDTH / DEFAULTHEIGHT;
- ev->speed = 1.0;
- ev->len = 0;
ev->drop = 0;
- if (!ev->ready)
+ if (!ev->ready || !ev->filename)
return;
_player_send_cmd(ev, EM_CMD_FILE_SET);
_player_send_str(ev, ev->filename, EINA_TRUE);
_file_open(ev);
}
-static int
-_em_read_safe(int fd, void *buf, ssize_t size)
+static Eina_Bool
+_player_cmd_param_read(Emotion_Generic_Video *ev, void *param, size_t size)
{
- ssize_t todo;
- char *p;
+ ssize_t done, todo, i;
- todo = size;
- p = buf;
-
- while (todo > 0)
+ /* When a parameter must be read, we cannot make sure it will be entirely
+ * available. Thus we store the bytes that could be read in a temp buffer,
+ * and when more data is read we try to complete the buffer and finally use
+ * the read value.
+ */
+ if (!ev->cmd.tmp)
{
- ssize_t r;
-
- r = read(fd, p, todo);
- if (r > 0)
- {
- todo -= r;
- p += r;
- }
- else if (r == 0)
- return 0;
- else
- {
- if (errno == EINTR || errno == EAGAIN)
- continue;
- else
- {
- ERR("could not read from fd %d: %s", fd, strerror(errno));
- return 0;
- }
- }
+ ev->cmd.tmp = malloc(size);
+ ev->cmd.i = 0;
+ ev->cmd.total = size;
}
- return 1;
-}
+ todo = ev->cmd.total - ev->cmd.i;
+ i = ev->cmd.i;
+ done = read(ev->fd_read, &ev->cmd.tmp[i], todo);
-static Eina_Bool
-_player_int_read(Emotion_Generic_Video *ev, int *i)
-{
- int n;
- n = _em_read_safe(ev->fd_read, i, sizeof(*i));
- if (n <= 0)
+ if (done < 0 && errno != EINTR && errno != EAGAIN)
{
- ERR("could not read int from fd_read %d\n", ev->fd_read);
+ if (ev->cmd.tmp)
+ {
+ free(ev->cmd.tmp);
+ ev->cmd.tmp = NULL;
+ }
+ ERR("problem when reading parameter from pipe.");
+ ev->cmd.type = -1;
return EINA_FALSE;
}
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_player_float_read(Emotion_Generic_Video *ev, float *f)
-{
- int n;
- n = _em_read_safe(ev->fd_read, f, sizeof(*f));
- if (n <= 0)
+ if (done == todo)
{
- ERR("could not read float from fd_read %d\n", ev->fd_read);
- return EINA_FALSE;
+ memcpy(param, ev->cmd.tmp, size);
+ free(ev->cmd.tmp);
+ ev->cmd.tmp = NULL;
+ return EINA_TRUE;
}
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_player_str_read(Emotion_Generic_Video *ev, char *str, int *len)
-{
- int n;
-
- if (!_player_int_read(ev, len))
- return EINA_FALSE;
+ if (done > 0)
+ ev->cmd.i += done;
- n = _em_read_safe(ev->fd_read, str, *len);
- if (n <= 0)
- {
- ERR("could not read string from fd_read %d\n", ev->fd_read);
- return EINA_FALSE;
- }
-
- return EINA_TRUE;
+ return EINA_FALSE;
}
static void
_player_frame_resize(Emotion_Generic_Video *ev)
{
int w, h;
- _player_int_read(ev, &w);
- _player_int_read(ev, &h);
+
+ w = ev->cmd.param.size.width;
+ h = ev->cmd.param.size.height;
INF("received frame resize: %dx%d", w, h);
ev->w = w;
static void
_player_length_changed(Emotion_Generic_Video *ev)
{
- float length;
- _player_float_read(ev, &length);
+ float length = ev->cmd.param.f_num;
INF("received length changed: %0.3f", length);
static void
_player_position_changed(Emotion_Generic_Video *ev)
{
- float position;
- _player_float_read(ev, &position);
+ float position = ev->cmd.param.f_num;
INF("received position changed: %0.3f", position);
ev->pos = position;
_emotion_video_pos_update(ev->obj, ev->pos, ev->len);
-
+/* hmmm. no _emotion_progress_set() is for "buffering" progress.
if (ev->len == 0)
return;
snprintf(buf, sizeof(buf), "%0.1f%%", progress * 100);
_emotion_progress_set(ev->obj, buf, progress);
+ */
}
static void
_player_seekable_changed(Emotion_Generic_Video *ev)
{
- int seekable;
- _player_int_read(ev, &seekable);
+ int seekable = ev->cmd.param.i_num;
INF("received seekable changed: %d", seekable);
}
static void
-_player_volume(Emotion_Generic_Video *ev)
+_audio_channels_free(Emotion_Generic_Video *ev)
{
- float vol, oldvol;
- _player_float_read(ev, &vol);
-
- INF("received volume: %0.3f", vol);
-
- oldvol = ev->volume;
- ev->volume = vol;
- if (vol != oldvol && !ev->opening)
- _emotion_audio_level_change(ev->obj);
+ int i;
+ for (i = 0; i < ev->audio_channels_count; i++)
+ eina_stringshare_del(ev->audio_channels[i].name);
+ free(ev->audio_channels);
+ ev->audio_channels_count = 0;
}
static void
-_player_audio_mute(Emotion_Generic_Video *ev)
+_video_channels_free(Emotion_Generic_Video *ev)
{
- int mute;
- _player_int_read(ev, &mute);
-
- INF("received audio mute: %d", mute);
-
- ev->audio_mute = !!mute;
+ int i;
+ for (i = 0; i < ev->video_channels_count; i++)
+ eina_stringshare_del(ev->video_channels[i].name);
+ free(ev->video_channels);
+ ev->video_channels_count = 0;
}
static void
-_audio_channels_free(Emotion_Generic_Video *ev)
+_spu_channels_free(Emotion_Generic_Video *ev)
{
int i;
- for (i = 0; i < ev->audio_channels_count; i++)
- eina_stringshare_del(ev->audio_channels[i].name);
- free(ev->audio_channels);
- ev->audio_channels_count = 0;
+ for (i = 0; i < ev->spu_channels_count; i++)
+ eina_stringshare_del(ev->spu_channels[i].name);
+ free(ev->spu_channels);
+ ev->spu_channels_count = 0;
}
static void
-_player_audio_tracks_info(Emotion_Generic_Video *ev)
+_player_tracks_info(Emotion_Generic_Video *ev, Emotion_Generic_Channel **channels, int *count, int *current)
{
- int track_current, tracks_count;
+ Emotion_Generic_Channel *pchannels;
int i;
- if (ev->audio_channels_count)
- _audio_channels_free(ev);
+ *count = ev->cmd.param.track.total;
+ *current = ev->cmd.param.track.current;
+ pchannels = ev->cmd.param.track.channels;
- _player_int_read(ev, &track_current);
- _player_int_read(ev, &tracks_count);
- INF("video with %d audio tracks (current = %d):", tracks_count, track_current);
- ev->audio_channels = calloc(
- tracks_count, sizeof(Emotion_Generic_Audio_Channel));
- ev->audio_channels_count = tracks_count;
- ev->audio_channel_current = track_current;
- for (i = 0; i < tracks_count; i++)
+ INF("number of tracks: %d (current = %d):", *count, *current);
+ for (i = 0; i < *count; i++)
{
- int tid, len;
- char buf[PATH_MAX];
- _player_int_read(ev, &tid);
- _player_str_read(ev, buf, &len);
- ev->audio_channels[i].id = tid;
- ev->audio_channels[i].name = eina_stringshare_add_length(buf, len);
- INF("\t%d: %s", tid, buf);
+ INF("\tchannel %d: %s", pchannels[i].id, pchannels[i].name);
}
+
+ *channels = pchannels;
+}
+
+static void
+_player_audio_tracks_info(Emotion_Generic_Video *ev)
+{
+ INF("Receiving audio channels:");
+ if (ev->audio_channels_count)
+ _audio_channels_free(ev);
+
+ _player_tracks_info(ev, &ev->audio_channels, &ev->audio_channels_count,
+ &ev->audio_channel_current);
+}
+
+static void
+_player_video_tracks_info(Emotion_Generic_Video *ev)
+{
+ INF("Receiving video channels:");
+ if (ev->video_channels_count)
+ _video_channels_free(ev);
+
+ _player_tracks_info(ev, &ev->video_channels, &ev->video_channels_count,
+ &ev->video_channel_current);
+}
+
+static void
+_player_spu_tracks_info(Emotion_Generic_Video *ev)
+{
+ INF("Receiving spu channels:");
+ if (ev->spu_channels_count)
+ _spu_channels_free(ev);
+
+ _player_tracks_info(ev, &ev->spu_channels, &ev->spu_channels_count,
+ &ev->spu_channel_current);
+}
+
+static void
+_player_meta_info_free(Emotion_Generic_Video *ev)
+{
+ eina_stringshare_replace(&ev->meta.title, NULL);
+ eina_stringshare_replace(&ev->meta.artist, NULL);
+ eina_stringshare_replace(&ev->meta.album, NULL);
+ eina_stringshare_replace(&ev->meta.year, NULL);
+ eina_stringshare_replace(&ev->meta.genre, NULL);
+ eina_stringshare_replace(&ev->meta.comment, NULL);
+ eina_stringshare_replace(&ev->meta.disc_id, NULL);
+ eina_stringshare_replace(&ev->meta.count, NULL);
+}
+
+static void
+_player_meta_info_read(Emotion_Generic_Video *ev)
+{
+ INF("Receiving meta info:");
+ _player_meta_info_free(ev);
+ ev->meta.title = ev->cmd.param.meta.title;
+ ev->meta.artist = ev->cmd.param.meta.artist;
+ ev->meta.album = ev->cmd.param.meta.album;
+ ev->meta.year = ev->cmd.param.meta.year;
+ ev->meta.genre = ev->cmd.param.meta.genre;
+ ev->meta.comment = ev->cmd.param.meta.comment;
+ ev->meta.disc_id = ev->cmd.param.meta.disc_id;
+ ev->meta.count = ev->cmd.param.meta.count;
+ INF("title: '%s'", ev->meta.title);
+ INF("artist: '%s'", ev->meta.artist);
+ INF("album: '%s'", ev->meta.album);
+ INF("year: '%s'", ev->meta.year);
+ INF("genre: '%s'", ev->meta.genre);
+ INF("comment: '%s'", ev->meta.comment);
+ INF("disc_id: '%s'", ev->meta.disc_id);
+ INF("count: '%s'", ev->meta.count);
}
static void
_player_file_closed(Emotion_Generic_Video *ev)
{
INF("Closed previous file.");
- sem_destroy(&ev->shared->lock);
-
+ eina_semaphore_free(&ev->shared->lock);
ev->closing = EINA_FALSE;
if (ev->opening)
{
int success;
- _player_int_read(ev, &success);
+ success = ev->cmd.param.i_num;
shm_unlink(ev->shmname);
if (ev->file_changed)
return;
}
+ ev->file_ready = EINA_TRUE;
+
_emotion_open_done(ev->obj);
if (ev->play)
_player_send_float(ev, ev->pos);
}
+ _player_send_cmd(ev, EM_CMD_VOLUME_SET);
+ _player_send_float(ev, ev->volume);
+
+ _player_send_cmd(ev, EM_CMD_SPEED_SET);
+ _player_send_float(ev, ev->speed);
+
+ int mute = ev->audio_mute;
+ _player_send_cmd(ev, EM_CMD_AUDIO_MUTE_SET);
+ _player_send_int(ev, mute);
+
+ mute = ev->video_mute;
+ _player_send_cmd(ev, EM_CMD_VIDEO_MUTE_SET);
+ _player_send_int(ev, mute);
+
+ mute = ev->spu_mute;
+ _player_send_cmd(ev, EM_CMD_SPU_MUTE_SET);
+ _player_send_int(ev, mute);
+
INF("Open done");
}
static void
-_player_read_cmd(Emotion_Generic_Video *ev)
+_player_cmd_process(Emotion_Generic_Video *ev)
{
- int type;
-
- if (!_player_int_read(ev, &type))
- {
- ERR("could not read command\n");
- return;
- }
-
- switch (type) {
+ switch (ev->cmd.type) {
case EM_RESULT_INIT:
_player_ready(ev);
break;
case EM_RESULT_AUDIO_TRACK_INFO:
_player_audio_tracks_info(ev);
break;
+ case EM_RESULT_VIDEO_TRACK_INFO:
+ _player_video_tracks_info(ev);
+ break;
+ case EM_RESULT_SPU_TRACK_INFO:
+ _player_spu_tracks_info(ev);
+ break;
+ case EM_RESULT_META_INFO:
+ _player_meta_info_read(ev);
+ break;
+ default:
+ WRN("received wrong command: %d", ev->cmd.type);
+ }
+
+ ev->cmd.type = -1;
+}
+
+static void
+_player_cmd_single_int_process(Emotion_Generic_Video *ev)
+{
+ if (!_player_cmd_param_read(ev, &ev->cmd.param.i_num, sizeof(ev->cmd.param.i_num)))
+ return;
+
+ _player_cmd_process(ev);
+}
+
+static void
+_player_cmd_single_float_process(Emotion_Generic_Video *ev)
+{
+ if (!_player_cmd_param_read(ev, &ev->cmd.param.f_num, sizeof(ev->cmd.param.f_num)))
+ return;
+
+ _player_cmd_process(ev);
+}
+
+static void
+_player_cmd_double_int_process(Emotion_Generic_Video *ev)
+{
+ int param;
+
+ if (ev->cmd.num_params == 0)
+ {
+ ev->cmd.num_params = 2;
+ ev->cmd.cur_param = 0;
+ ev->cmd.param.size.width = 0;
+ ev->cmd.param.size.height = 0;
+ }
+
+ if (!_player_cmd_param_read(ev, ¶m, sizeof(param)))
+ return;
+
+ if (ev->cmd.cur_param == 0)
+ ev->cmd.param.size.width = param;
+ else
+ ev->cmd.param.size.height = param;
+
+ ev->cmd.cur_param++;
+ if (ev->cmd.cur_param == ev->cmd.num_params)
+ _player_cmd_process(ev);
+}
+
+static void
+_player_cmd_track_info(Emotion_Generic_Video *ev)
+{
+ int param;
+ int i;
+
+ if (ev->cmd.num_params == 0)
+ {
+ ev->cmd.cur_param = 0;
+ ev->cmd.num_params = 2;
+ ev->cmd.param.track.channels = NULL;
+ ev->cmd.s_len = -1;
+ }
+
+ while (ev->cmd.cur_param < 2)
+ {
+ if (!_player_cmd_param_read(ev, ¶m, sizeof(param)))
+ return;
+
+ if (ev->cmd.cur_param == 0)
+ ev->cmd.param.track.current = param;
+ else
+ {
+ ev->cmd.param.track.total = param;
+ ev->cmd.num_params += param * 2;
+ ev->cmd.param.track.channels =
+ calloc(param, sizeof(*ev->cmd.param.track.channels));
+ }
+ ev->cmd.cur_param++;
+ }
+
+ if (ev->cmd.cur_param == ev->cmd.num_params)
+ {
+ _player_cmd_process(ev);
+ return;
+ }
+
+ i = (ev->cmd.cur_param - 2) / 2;
+ if ((ev->cmd.cur_param % 2) == 0) // reading track id
+ {
+ if (!_player_cmd_param_read(ev, ¶m, sizeof(param)))
+ return;
+ ev->cmd.param.track.channels[i].id = param;
+ ev->cmd.cur_param++;
+ }
+ else // reading track name
+ {
+ char buf[PATH_MAX];
+
+ if (ev->cmd.s_len == -1)
+ {
+ if (!_player_cmd_param_read(ev, ¶m, sizeof(param)))
+ return;
+ ev->cmd.s_len = param;
+ }
+
+ if (!_player_cmd_param_read(ev, buf, ev->cmd.s_len))
+ return;
+ ev->cmd.param.track.channels[i].name =
+ eina_stringshare_add_length(buf, ev->cmd.s_len);
+ ev->cmd.cur_param++;
+ ev->cmd.s_len = -1;
+ }
+
+ if (ev->cmd.cur_param == ev->cmd.num_params)
+ _player_cmd_process(ev);
+}
+
+static void
+_player_cmd_meta_info(Emotion_Generic_Video *ev)
+{
+ int param;
+ const char *info;
+ char buf[PATH_MAX];
+
+ if (ev->cmd.num_params == 0)
+ {
+ ev->cmd.cur_param = 0;
+ ev->cmd.num_params = 8;
+ ev->cmd.param.meta.title = NULL;
+ ev->cmd.param.meta.artist = NULL;
+ ev->cmd.param.meta.album = NULL;
+ ev->cmd.param.meta.year = NULL;
+ ev->cmd.param.meta.genre = NULL;
+ ev->cmd.param.meta.comment = NULL;
+ ev->cmd.param.meta.disc_id = NULL;
+ ev->cmd.param.meta.count = NULL;
+ ev->cmd.s_len = -1;
+ }
+
+ if (ev->cmd.s_len == -1)
+ {
+ if (!_player_cmd_param_read(ev, ¶m, sizeof(param)))
+ return;
+ ev->cmd.s_len = param;
+ }
+
+ if (!_player_cmd_param_read(ev, buf, ev->cmd.s_len))
+ return;
+
+ info = eina_stringshare_add_length(buf, ev->cmd.s_len);
+ ev->cmd.s_len = -1;
+
+ if (ev->cmd.cur_param == 0)
+ ev->cmd.param.meta.title = info;
+ else if (ev->cmd.cur_param == 1)
+ ev->cmd.param.meta.artist = info;
+ else if (ev->cmd.cur_param == 2)
+ ev->cmd.param.meta.album = info;
+ else if (ev->cmd.cur_param == 3)
+ ev->cmd.param.meta.year = info;
+ else if (ev->cmd.cur_param == 4)
+ ev->cmd.param.meta.genre = info;
+ else if (ev->cmd.cur_param == 5)
+ ev->cmd.param.meta.comment = info;
+ else if (ev->cmd.cur_param == 6)
+ ev->cmd.param.meta.disc_id = info;
+ else if (ev->cmd.cur_param == 7)
+ ev->cmd.param.meta.count = info;
+
+ ev->cmd.cur_param++;
+
+ if (ev->cmd.cur_param == 8)
+ _player_cmd_process(ev);
+}
+
+static void
+_player_cmd_read(Emotion_Generic_Video *ev)
+{
+ if (ev->cmd.type < 0)
+ {
+ if (!_player_cmd_param_read(ev, &ev->cmd.type, sizeof(ev->cmd.type)))
+ return;
+ ev->cmd.num_params = 0;
+ }
+
+ switch (ev->cmd.type) {
+ case EM_RESULT_INIT:
+ case EM_RESULT_FILE_SET:
+ case EM_RESULT_PLAYBACK_STOPPED:
+ case EM_RESULT_FILE_CLOSE:
+ case EM_RESULT_FRAME_NEW:
+ _player_cmd_process(ev);
+ break;
+ case EM_RESULT_FILE_SET_DONE:
+ case EM_RESULT_SEEKABLE_CHANGED:
+ _player_cmd_single_int_process(ev);
+ break;
+ case EM_RESULT_LENGTH_CHANGED:
+ case EM_RESULT_POSITION_CHANGED:
+ _player_cmd_single_float_process(ev);
+ break;
+ case EM_RESULT_FRAME_SIZE:
+ _player_cmd_double_int_process(ev);
+ break;
+ case EM_RESULT_AUDIO_TRACK_INFO:
+ case EM_RESULT_VIDEO_TRACK_INFO:
+ case EM_RESULT_SPU_TRACK_INFO:
+ _player_cmd_track_info(ev);
+ break;
+ case EM_RESULT_META_INFO:
+ _player_cmd_meta_info(ev);
+ break;
+
default:
- WRN("received wrong command: %d", type);
- };
+ WRN("received wrong command: %d", ev->cmd.type);
+ ev->cmd.type = -1;
+ }
}
static Eina_Bool
return ECORE_CALLBACK_CANCEL;
}
- _player_read_cmd(ev);
+ _player_cmd_read(ev);
return ECORE_CALLBACK_RENEW;
}
return ECORE_CALLBACK_DONE;
}
- if (ev->size < 4)
- {
- ERR("invalid command: missing bytes.");
- return ECORE_CALLBACK_DONE;
- }
-
for (i = 0; ev->lines[i].line; i++)
INF("received input from player: \"%s\"", ev->lines[i].line);
ev->player.exe = NULL;
ev->ready = EINA_FALSE;
+ ev->file_ready = EINA_FALSE;
ecore_main_fd_handler_del(ev->fd_handler);
close(ev->fd_read);
close(ev->fd_write);
ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_NOT_LEADER,
ev);
- INF("created pipe emotion -> player: %d -> %d\n", pipe_out[1], pipe_out[0]);
- INF("created pipe player -> emotion: %d -> %d\n", pipe_in[1], pipe_in[0]);
+ INF("created pipe emotion -> player: %d -> %d", pipe_out[1], pipe_out[0]);
+ INF("created pipe player -> emotion: %d -> %d", pipe_in[1], pipe_in[0]);
close(pipe_in[1]);
close(pipe_out[0]);
}
static Eina_Bool
-_fork_and_exec(Evas_Object *obj, Emotion_Generic_Video *ev)
+_fork_and_exec(Evas_Object *obj __UNUSED__, Emotion_Generic_Video *ev)
{
char shmname[256];
struct timeval tv;
ev->speed = 1.0;
ev->volume = 0.5;
ev->audio_mute = EINA_FALSE;
+ ev->cmd.type = -1;
ev->obj = obj;
ev->cmdline = eina_stringshare_add(player);
if (ev->fd_handler)
ecore_main_fd_handler_del(ev->fd_handler);
- _audio_channels_free(ev);
-
eina_stringshare_del(ev->cmdline);
eina_stringshare_del(ev->shmname);
eina_stringshare_replace(&ev->filename, file);
ev->pos = 0;
+ ev->w = 0;
+ ev->h = 0;
+ ev->ratio = 1;
+ ev->len = 0;
if (ev->ready && ev->opening)
{
{
Emotion_Generic_Video *ev = data;
- if (!ev) return;
+ if (!ev || !ev->filename) return;
+
INF("file close: %s", ev->filename);
- if (!ev->filename)
- return;
+ eina_stringshare_replace(&ev->filename, NULL);
+
+ ev->file_ready = EINA_FALSE;
+ _audio_channels_free(ev);
+ _video_channels_free(ev);
+ _spu_channels_free(ev);
+ _player_meta_info_free(ev);
if (ev->opening)
return;
ev->play = EINA_FALSE;
- if (!ev->ready)
+ if (!ev->file_ready)
return;
_player_send_cmd(ev, EM_CMD_STOP);
em_size_get(void *data, int *w, int *h)
{
Emotion_Generic_Video *ev = data;
- if(w) *w = ev->w;
- if(h) *h = ev->h;
+ if (w) *w = ev->w;
+ if (h) *h = ev->h;
}
static void
{
Emotion_Generic_Video *ev = data;
float position = pos;
+
+ if (!ev->file_ready)
+ return;
+
_player_send_cmd(ev, EM_CMD_POSITION_SET);
_player_send_float(ev, position);
_emotion_seek_done(ev->obj);
return ev->len;
}
+static double
+em_buffer_size_get(void *data __UNUSED__)
+{
+ return 1.0;
+}
+
static int
em_fps_num_get(void *data)
{
{
Emotion_Generic_Video *ev = data;
- if (!ev || ev->opening || ev->closing)
+ if (!ev || !ev->file_ready)
return 0;
// lock frame here
- sem_wait(&ev->shared->lock);
+ if (!eina_semaphore_lock(&ev->shared->lock))
+ return 0;
// send current frame to emotion
if (ev->shared->frame.emotion != ev->shared->frame.last)
}
*bgra_data = ev->frame.frames[ev->shared->frame.emotion];
+ if (ev->shared->frame_drop > 1)
+ WRN("dropped frames: %d", ev->shared->frame_drop - 1);
+ ev->shared->frame_drop = 0;
+
// unlock frame here
- sem_post(&ev->shared->lock);
+ eina_semaphore_release(&ev->shared->lock, 1);
ev->drop = 0;
return 1;
}
static int
-em_video_channel_count(void *ef __UNUSED__)
+em_video_channel_count(void *data)
{
- int ret = 0;
- return ret;
+ Emotion_Generic_Video *ev = data;
+ return ev->video_channels_count;
}
static void
-em_video_channel_set(void *ef __UNUSED__, int channel __UNUSED__)
+em_video_channel_set(void *data, int channel)
{
+ Emotion_Generic_Video *ev = data;
+
+ if (channel < 0 || channel >= ev->video_channels_count)
+ {
+ WRN("video channel out of range.");
+ return;
+ }
+
+ _player_send_cmd(ev, EM_CMD_VIDEO_TRACK_SET);
+ _player_send_int(ev, ev->video_channels[channel].id);
+ ev->video_channel_current = channel;
}
static int
-em_video_channel_get(void *ef __UNUSED__)
+em_video_channel_get(void *data)
{
- return 1;
+ Emotion_Generic_Video *ev = data;
+ return ev->video_channel_current;
}
static const char *
-em_video_channel_name_get(void *ef __UNUSED__, int channel __UNUSED__)
+em_video_channel_name_get(void *data, int channel)
{
- return NULL;
+ Emotion_Generic_Video *ev = data;
+
+ if (channel < 0 || channel >= ev->video_channels_count)
+ {
+ WRN("video channel out of range.");
+ return NULL;
+ }
+
+ return ev->video_channels[channel].name;
}
static void
-em_video_channel_mute_set(void *ef __UNUSED__, int mute __UNUSED__)
+em_video_channel_mute_set(void *data, int mute)
{
+ Emotion_Generic_Video *ev = data;
+
+ ev->video_mute = !!mute;
+
+ if (!ev || !ev->file_ready)
+ return;
+
+ _player_send_cmd(ev, EM_CMD_VIDEO_MUTE_SET);
+ _player_send_int(ev, mute);
}
static int
em_audio_channel_set(void *data, int channel)
{
Emotion_Generic_Video *ev = data;
- int i;
- for (i = 0; i < ev->audio_channels_count; i++)
+ if (channel < 0 || channel >= ev->audio_channels_count)
{
- if (ev->audio_channels[i].id == channel)
- {
- _player_send_cmd(ev, EM_CMD_AUDIO_TRACK_SET);
- _player_send_int(ev, channel);
- break;
- }
+ WRN("audio channel out of range.");
+ return;
}
+
+ _player_send_cmd(ev, EM_CMD_AUDIO_TRACK_SET);
+ _player_send_int(ev, ev->audio_channels[channel].id);
+ ev->audio_channel_current = channel;
}
static int
em_audio_channel_name_get(void *data, int channel)
{
Emotion_Generic_Video *ev = data;
- int i;
- for (i = 0; i < ev->audio_channels_count; i++)
+ if (channel < 0 || channel >= ev->audio_channels_count)
{
- if (ev->audio_channels[i].id == channel)
- return ev->audio_channels[i].name;
+ WRN("audio channel out of range.");
+ return NULL;
}
- return NULL;
+ return ev->audio_channels[channel].name;
}
static void
em_audio_channel_mute_set(void *data, int mute)
{
Emotion_Generic_Video *ev = data;
+
+ ev->audio_mute = !!mute;
+
+ if (!ev || !ev->file_ready)
+ return;
+
_player_send_cmd(ev, EM_CMD_AUDIO_MUTE_SET);
_player_send_int(ev, mute);
- ev->audio_mute = !!mute;
}
static int
em_audio_channel_volume_set(void *data, double vol)
{
Emotion_Generic_Video *ev = data;
- float fvol;
if (vol > 1.0) vol = 1.0;
if (vol < 0.0) vol = 0.0;
- fvol = vol;
- _player_send_cmd(ev, EM_CMD_VOLUME_SET);
- _player_send_float(ev, fvol);
-
ev->volume = vol;
+
+ if (!ev || !ev->file_ready)
+ return;
+
+ _player_send_cmd(ev, EM_CMD_VOLUME_SET);
+ _player_send_float(ev, ev->volume);
}
static double
}
static int
-em_spu_channel_count(void *ef __UNUSED__)
+em_spu_channel_count(void *data)
{
- return 0;
+ Emotion_Generic_Video *ev = data;
+ return ev->spu_channels_count;
}
static void
-em_spu_channel_set(void *ef __UNUSED__, int channel __UNUSED__)
+em_spu_channel_set(void *data, int channel)
{
+ Emotion_Generic_Video *ev = data;
+
+ if (channel < 0 || channel >= ev->spu_channels_count)
+ {
+ WRN("spu channel out of range.");
+ return;
+ }
+
+ _player_send_cmd(ev, EM_CMD_SPU_TRACK_SET);
+ _player_send_int(ev, ev->spu_channels[channel].id);
+ ev->spu_channel_current = channel;
}
static int
-em_spu_channel_get(void *ef __UNUSED__)
+em_spu_channel_get(void *data)
{
- int num = 0;
- return num;
+ Emotion_Generic_Video *ev = data;
+ return ev->spu_channel_current;
}
static const char *
-em_spu_channel_name_get(void *ef __UNUSED__, int channel __UNUSED__)
+em_spu_channel_name_get(void *data, int channel)
{
- return NULL;
+ Emotion_Generic_Video *ev = data;
+
+ if (channel < 0 || channel >= ev->spu_channels_count)
+ {
+ WRN("spu channel out of range.");
+ return NULL;
+ }
+
+ return ev->spu_channels[channel].name;
}
static void
-em_spu_channel_mute_set(void *ef __UNUSED__, int mute __UNUSED__)
+em_spu_channel_mute_set(void *data, int mute)
{
- return;
+ Emotion_Generic_Video *ev = data;
+
+ ev->spu_mute = !!mute;
+
+ if (!ev || !ev->file_ready)
+ return;
+
+ _player_send_cmd(ev, EM_CMD_SPU_MUTE_SET);
+ _player_send_int(ev, mute);
}
static int
-em_spu_channel_mute_get(void *ef __UNUSED__)
+em_spu_channel_mute_get(void *data)
{
- return 0;
+ Emotion_Generic_Video *ev = data;
+ return ev->spu_mute;
}
static int
{
Emotion_Generic_Video *ev = data;
float rate = speed;
+ ev->speed = rate;
+
+ if (!ev || !ev->file_ready)
+ return;
_player_send_cmd(ev, EM_CMD_SPEED_SET);
_player_send_float(ev, rate);
-
- ev->speed = rate;
}
static double
}
static const char *
-em_meta_get(void *ef __UNUSED__, int meta __UNUSED__)
+em_meta_get(void *data, int meta)
{
- char * meta_data = NULL;
- return meta_data;
+ Emotion_Generic_Video *ev = data;
+
+ switch (meta) {
+ case EMOTION_META_INFO_TRACK_TITLE:
+ return ev->meta.title;
+ case EMOTION_META_INFO_TRACK_ARTIST:
+ return ev->meta.artist;
+ case EMOTION_META_INFO_TRACK_ALBUM:
+ return ev->meta.album;
+ case EMOTION_META_INFO_TRACK_YEAR:
+ return ev->meta.year;
+ case EMOTION_META_INFO_TRACK_GENRE:
+ return ev->meta.genre;
+ case EMOTION_META_INFO_TRACK_COMMENT:
+ return ev->meta.comment;
+ case EMOTION_META_INFO_TRACK_DISC_ID:
+ return ev->meta.disc_id;
+ case EMOTION_META_INFO_TRACK_COUNT:
+ return ev->meta.count;
+ }
+
+ return NULL;
}
static Emotion_Video_Module em_module =
em_size_get, /* size_get */
em_pos_set, /* pos_set */
em_len_get, /* len_get */
+ em_buffer_size_get, /* buffer_size_get */
em_fps_num_get, /* fps_num_get */
em_fps_den_get, /* fps_den_get */
em_fps_get, /* fps_get */
em_speed_get, /* speed_get */
em_eject, /* eject */
em_meta_get, /* meta_get */
+ NULL, /* priority_set */
+ NULL, /* priority_get */
NULL /* handle */
};