implement metadata for mpris so evene thumbs work for non-thumbed files

this allows us to port to artfiles always too... this way
music-control displays the albumart. music-control is a bit broken in
that it doesnt keep aspect ratio etc. of these. need to fix that over
there.... but... it's coming together.
This commit is contained in:
Carsten Haitzler 2017-11-28 14:32:59 +09:00
parent 34ab03ac29
commit 8d07759869
5 changed files with 261 additions and 29 deletions

View File

@ -45,7 +45,6 @@ https://specifications.freedesktop.org/mpris-spec/latest/Player_Interface.html
*
* Not implemented:
* Tracklist objects
* Metadata
* SetPosition (requires Tracklist objects)
*
* In rage generally and here:
@ -677,14 +676,140 @@ SETTER(shuffle)
return eldbus_message_method_return_new(msg);
}
/*
GETTER(metadata)
{
// XXX: return metadata
eldbus_message_iter_arguments_append(iter, "a{sv}", NULL);
Inf *inf = evas_object_data_get(mainwin, "inf");
Eldbus_Message_Iter *array = NULL, *entry = NULL, *var, *var2;
uint64_t len = 0;
char *buf = NULL;
const char *s;
// XXX: TODO:
// mpris:trackid
eldbus_message_iter_arguments_append(iter, "a{sv}", &array);
s = video_file_get(inf->vid);
if (s)
{
if (s[0] == '/')
{
buf = alloca(strlen(s) + sizeof("file://") + 1);
sprintf(buf, "file://%s", s);
}
else if (strstr(s, "://"))
{
buf = alloca(strlen(s) + 1);
strcpy(buf, s);
}
else
{
char cwd[PATH_MAX];
if (getcwd(cwd, sizeof(cwd) - 1))
{
cwd[sizeof(cwd) - 1] = 0;
buf = alloca(strlen(cwd) + 1 + strlen(s) + sizeof("file://") + 1);
sprintf(buf, "file://%s/%s", cwd, s);
}
}
}
if (buf)
{
eldbus_message_iter_arguments_append(array, "{sv}", &entry);
eldbus_message_iter_basic_append(entry, 's', "xesam:url");
var = eldbus_message_iter_container_new(entry, 'v', "s");
eldbus_message_iter_basic_append(var, 's', buf);
eldbus_message_iter_container_close(entry, var);
eldbus_message_iter_container_close(array, entry);
}
s = video_artfile_get(inf->vid);
if (s)
{
buf = alloca(strlen(s) + sizeof("file://") + 1);
sprintf(buf, "file://%s", s);
eldbus_message_iter_arguments_append(array, "{sv}", &entry);
eldbus_message_iter_basic_append(entry, 's', "mpris:artUrl");
var = eldbus_message_iter_container_new(entry, 'v', "s");
eldbus_message_iter_basic_append(var, 's', buf);
eldbus_message_iter_container_close(entry, var);
eldbus_message_iter_container_close(array, entry);
}
s = video_title_get(inf->vid);
if (!s) s = video_meta_title_get(inf->vid);
if (s)
{
eldbus_message_iter_arguments_append(array, "{sv}", &entry);
eldbus_message_iter_basic_append(entry, 's', "xesam:title");
var = eldbus_message_iter_container_new(entry, 'v', "s");
eldbus_message_iter_basic_append(var, 's', buf);
eldbus_message_iter_container_close(entry, var);
eldbus_message_iter_container_close(array, entry);
}
s = video_meta_album_get(inf->vid);
if (s)
{
eldbus_message_iter_arguments_append(array, "{sv}", &entry);
eldbus_message_iter_basic_append(entry, 's', "xesam:album");
var = eldbus_message_iter_container_new(entry, 'v', "s");
eldbus_message_iter_basic_append(var, 's', buf);
eldbus_message_iter_container_close(entry, var);
eldbus_message_iter_container_close(array, entry);
}
s = video_meta_artist_get(inf->vid);
if (s)
{
eldbus_message_iter_arguments_append(array, "{sv}", &entry);
eldbus_message_iter_basic_append(entry, 's', "xesam:artist");
var = eldbus_message_iter_container_new(entry, 'v', "as");
eldbus_message_iter_arguments_append(var, "as", &var2);
eldbus_message_iter_basic_append(var2, 's', s);
eldbus_message_iter_container_close(var, var2);
eldbus_message_iter_container_close(entry, var);
eldbus_message_iter_container_close(array, entry);
}
s = video_meta_comment_get(inf->vid);
if (s)
{
eldbus_message_iter_arguments_append(array, "{sv}", &entry);
eldbus_message_iter_basic_append(entry, 's', "xesam:comment");
var = eldbus_message_iter_container_new(entry, 'v', "as");
eldbus_message_iter_arguments_append(var, "as", &var2);
eldbus_message_iter_basic_append(var2, 's', s);
eldbus_message_iter_container_close(var, var2);
eldbus_message_iter_container_close(entry, var);
eldbus_message_iter_container_close(array, entry);
}
s = video_meta_genre_get(inf->vid);
if (s)
{
eldbus_message_iter_arguments_append(array, "{sv}", &entry);
eldbus_message_iter_basic_append(entry, 's', "xesam:genre");
var = eldbus_message_iter_container_new(entry, 'v', "as");
eldbus_message_iter_arguments_append(var, "as", &var2);
eldbus_message_iter_basic_append(var2, 's', s);
eldbus_message_iter_container_close(var, var2);
eldbus_message_iter_container_close(entry, var);
eldbus_message_iter_container_close(array, entry);
}
len = video_length_get(inf->vid) * 1000000.0;
eldbus_message_iter_arguments_append(array, "{sv}", &entry);
eldbus_message_iter_basic_append(entry, 's', "mpris:length");
var = eldbus_message_iter_container_new(entry, 'v', "x");
eldbus_message_iter_basic_append(var, 'x', len);
eldbus_message_iter_container_close(entry, var);
eldbus_message_iter_container_close(array, entry);
eldbus_message_iter_container_close(iter, array);
return EINA_TRUE;
}
*/
GETTER(volume)
{
@ -782,7 +907,7 @@ static const Eldbus_Property properties_player[] =
PROP_RW("LoopStatus", "s", loop_status),
PROP_RW("Rate", "d", rate),
PROP_RW("Shuffle", "b", shuffle),
// PROP_RO("Metadata", "a{sv}", metadata),
PROP_RO("Metadata", "a{sv}", metadata),
PROP_RW("Volume", "d", volume),
PROP_RO("Position", "x", position),
PROP_RO("MinimumRate", "d", minimum_rate),
@ -949,6 +1074,13 @@ mpris_position_change(double pos)
eldbus_service_property_changed(iface_player, "Position");
}
void
mpris_metadata_change(void)
{
if (!iface_player) return;
eldbus_service_property_changed(iface_player, "Metadata");
}
void
mpris_init(Evas_Object *win)
{

View File

@ -3,5 +3,6 @@ void mpris_volume_change(void);
void mpris_loop_status_change(void);
void mpris_playback_status_change(void);
void mpris_position_change(double pos);
void mpris_metadata_change(void);
void mpris_init(Evas_Object *win);
void mpris_shutdown(void);

View File

@ -9,6 +9,7 @@ static Evas_Object *vidimage = NULL;
static Eet_File *ef = NULL;
static Ecore_Timer *vid_timeout = NULL;
static Eina_Bool is_audio = EINA_FALSE;
static Eina_Bool is_video = EINA_FALSE;
static Eina_Bool is_movie = EINA_FALSE;
static int iw, ih, incr = 0;
static Eina_Bool poster = 0;
@ -78,6 +79,7 @@ _cb_loaded(void *data, Evas_Object *obj, void *info EINA_UNUSED)
(len >= (60.0 * 60.0)) &&
(len <= (5.0 * 60.0 * 60.0)))
is_movie = EINA_TRUE;
if (poster == 2) is_video = EINA_TRUE;
}
if (is_movie)
@ -86,6 +88,12 @@ _cb_loaded(void *data, Evas_Object *obj, void *info EINA_UNUSED)
_cb_fetched, (void *)file);
return;
}
else if (is_video)
{
albumart_find(file, NULL, NULL, title, NULL,
_cb_fetched, (void *)file);
return;
}
else
{
char buf_base[PATH_MAX];

View File

@ -3,6 +3,7 @@
#include "rage_config.h"
#include "config.h"
#include "albumart.h"
#include "mpris.h"
typedef struct _Video Video;
@ -13,6 +14,10 @@ struct _Video
Ecore_Timer *smooth_timer;
Ecore_Job *restart_job;
const char *file;
const char *realfile;
const char *artfile;
Ecore_Exe *exe;
Ecore_Event_Handler *exe_handler;
int w, h;
int iw, ih, piw, pih, tw, th;
int resizes;
@ -33,6 +38,27 @@ static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_NULL;
static void _ob_resize(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
static Eina_Bool
_cb_thumb_exe(void *data, int type EINA_UNUSED, void *event)
{
Ecore_Exe_Event_Del *ev = event;
Video *sd = evas_object_smart_data_get(data);
char *path;
if (!sd) return EINA_TRUE;
if (ev->exe == sd->exe)
{
sd->exe = NULL;
if (ev->exit_code == 0)
{
path = albumart_file_get(sd->realfile);
eina_stringshare_replace(&(sd->artfile), path);
mpris_metadata_change();
}
}
return EINA_TRUE;
}
static void
_art_check(Evas_Object *obj)
{
@ -50,28 +76,9 @@ _art_check(Evas_Object *obj)
}
if (sd->doart)
{
char *thumb = NULL, *realfile = NULL;
char *thumb = NULL;
evas_object_show(sd->o_img);
if (!strncasecmp(sd->file, "file:/", 6))
{
Efreet_Uri *uri = efreet_uri_decode(sd->file);
if (uri)
{
realfile = ecore_file_realpath(uri->path);
efreet_uri_free(uri);
}
}
else if ((!strncasecmp(sd->file, "http:/", 6)) ||
(!strncasecmp(sd->file, "https:/", 7)))
realfile = strdup(sd->file);
else
realfile = ecore_file_realpath(sd->file);
if (realfile)
{
thumb = albumart_file_get(realfile);
free(realfile);
}
thumb = albumart_file_get(sd->realfile);
if (thumb)
{
Evas_Coord ox, oy, ow, oh;
@ -83,6 +90,8 @@ _art_check(Evas_Object *obj)
evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
_ob_resize(obj, ox, oy, ow, oh);
}
eina_stringshare_replace(&(sd->artfile), thumb);
mpris_metadata_change();
free(thumb);
}
}
@ -90,6 +99,39 @@ _art_check(Evas_Object *obj)
{
evas_object_hide(sd->o_img);
}
if (!sd->artfile)
{
char buf[PATH_MAX];
const char *libdir;
char *s;
ecore_exe_run_priority_set(10);
s = ecore_file_escape_name(sd->realfile);
if (s)
{
libdir = elm_app_lib_dir_get();
if (libdir)
{
if (!sd->exe_handler)
sd->exe_handler = ecore_event_handler_add
(ECORE_EXE_EVENT_DEL, _cb_thumb_exe, obj);
snprintf(buf, sizeof(buf),
"%s/rage/utils/rage_thumb %s 10000 %i",
libdir, s, 2);
if (sd->exe)
{
ecore_exe_kill(sd->exe);
ecore_exe_free(sd->exe);
sd->exe = NULL;
}
sd->exe = ecore_exe_pipe_run(buf,
ECORE_EXE_TERM_WITH_PARENT |
ECORE_EXE_NOT_LEADER,
obj);
}
free(s);
}
}
}
static void
@ -153,11 +195,13 @@ _cb_vid_stop(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
{
sd->restart_job = ecore_job_add(_cb_restart, data);
evas_object_smart_callback_call(data, "loop", NULL);
mpris_metadata_change();
}
else
{
sd->restart_job = NULL;
evas_object_smart_callback_call(data, "stop", NULL);
mpris_metadata_change();
}
}
@ -184,6 +228,7 @@ _cb_open_done(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
if (!sd) return;
evas_object_smart_callback_call(data, "opened", NULL);
_art_check(data);
mpris_metadata_change();
}
static void
@ -200,6 +245,7 @@ _cb_length_change(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNU
Video *sd = evas_object_smart_data_get(data);
if (!sd) return;
evas_object_smart_callback_call(data, "length", NULL);
mpris_metadata_change();
}
static void
@ -208,6 +254,7 @@ _cb_title_change(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUS
Video *sd = evas_object_smart_data_get(data);
if (!sd) return;
evas_object_smart_callback_call(data, "title", NULL);
mpris_metadata_change();
}
static void
@ -216,6 +263,7 @@ _cb_audio_change(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUS
Video *sd = evas_object_smart_data_get(data);
if (!sd) return;
evas_object_smart_callback_call(data, "audio", NULL);
mpris_metadata_change();
}
static void
@ -224,6 +272,7 @@ _cb_channels_change(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_U
Video *sd = evas_object_smart_data_get(data);
if (!sd) return;
evas_object_smart_callback_call(data, "channels", NULL);
mpris_metadata_change();
}
static void
@ -232,6 +281,7 @@ _cb_play_start(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED
Video *sd = evas_object_smart_data_get(data);
if (!sd) return;
evas_object_smart_callback_call(data, "play_start", NULL);
mpris_metadata_change();
}
static void
@ -240,6 +290,7 @@ _cb_play_finish(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSE
Video *sd = evas_object_smart_data_get(data);
if (!sd) return;
evas_object_smart_callback_call(data, "play_finish", NULL);
mpris_metadata_change();
}
static void
@ -355,6 +406,8 @@ _smart_del(Evas_Object *obj)
Video *sd = evas_object_smart_data_get(obj);
if (!sd) return;
if (sd->file) eina_stringshare_del(sd->file);
if (sd->realfile) eina_stringshare_del(sd->realfile);
if (sd->artfile) eina_stringshare_del(sd->artfile);
if (sd->clip) evas_object_del(sd->clip);
if (sd->o_vid) evas_object_del(sd->o_vid);
if (sd->o_img) evas_object_del(sd->o_img);
@ -362,6 +415,17 @@ _smart_del(Evas_Object *obj)
if (sd->smooth_timer) sd->smooth_timer = ecore_timer_del(sd->smooth_timer);
if (sd->restart_job) ecore_job_del(sd->restart_job);
if (sd->exe)
{
ecore_exe_kill(sd->exe);
ecore_exe_free(sd->exe);
sd->exe = NULL;
}
if (sd->exe_handler)
{
ecore_event_handler_del(sd->exe_handler);
sd->exe_handler = NULL;
}
_parent_sc.del(obj);
emotion_shutdown();
@ -563,12 +627,30 @@ video_add(Evas_Object *parent)
void
video_file_set(Evas_Object *obj, const char *file)
{
char *realfile = NULL;
Video *sd = evas_object_smart_data_get(obj);
if (!sd) return;
evas_object_hide(sd->o_img);
evas_object_hide(sd->o_vid);
evas_object_hide(sd->clip);
eina_stringshare_replace(&(sd->file), file);
if (!strncasecmp(sd->file, "file:/", 6))
{
Efreet_Uri *uri = efreet_uri_decode(sd->file);
if (uri)
{
realfile = ecore_file_realpath(uri->path);
efreet_uri_free(uri);
}
}
else if ((!strncasecmp(sd->file, "http:/", 6)) ||
(!strncasecmp(sd->file, "https:/", 7)))
realfile = strdup(sd->file);
else
realfile = ecore_file_realpath(sd->file);
eina_stringshare_replace(&(sd->realfile), realfile);
free(realfile);
eina_stringshare_replace(&(sd->artfile), NULL);
emotion_object_file_set(sd->o_vid, sd->file);
video_position_set(obj, 0.0);
if ((sd->file) && (sd->doart))
@ -1082,6 +1164,14 @@ video_file_autosub_set(Evas_Object *obj, const char *file, const char *sub)
video_file_set(obj, file);
}
const char *
video_artfile_get(Evas_Object *obj)
{
Video *sd = evas_object_smart_data_get(obj);
if (!sd) return NULL;
return sd->artfile;
}
// emotion_object_seekable_get
// emotion_object_play_speed_set
// emotion_object_play_speed_get

View File

@ -57,4 +57,5 @@ const char *video_meta_genre_get(Evas_Object *obj);
const char *video_meta_comment_get(Evas_Object *obj);
void video_file_autosub_set(Evas_Object *obj, const char *file, const char *sub);
Evas_Object *video_meta_artwork_get(Evas_Object *obj, const char *path, int type);
const char *video_artfile_get(Evas_Object *obj);
#endif