music_control: add metadata (title, artist and album) and the cover image to the...
authordavemds <dave@gurumeditation.it>
Mon, 28 Oct 2013 21:55:10 +0000 (22:55 +0100)
committerdavemds <dave@gurumeditation.it>
Mon, 28 Oct 2013 21:55:10 +0000 (22:55 +0100)
Reviewers: zmike, zehortigoza

Reviewed By: zehortigoza

CC: cedric
Differential Revision: https://phab.enlightenment.org/D272

data/themes/edc/music_control.edc
src/modules/music-control/e_mod_main.c
src/modules/music-control/private.h
src/modules/music-control/ui.c

index 6a0ef23..f0fa2a4 100644 (file)
@@ -49,62 +49,97 @@ group {
       image: "pause.png" COMP;
       image: "play.png" COMP;
    }
+   styles {
+      style { name: "music_control_metadata_style";
+         base: "font=Sans font_size=10 align=left text_class=tb_plain color=#ffff style=shadow,bottom shadow_color=#00000080";
+         tag: "title" "+ font_size=12 font=Sans:style=Bold text_class=tb_big";
+         tag: "tag" "+ font_size=8 color=#888f";
+         tag: "br" "\n";
+      }
+   }
    parts {
-      part {
-         name: "player_name";
-         type: TEXT;
-         description {
-            state: "default" 0;
-            text.size: 12;
-            text.text: "Music player";
-            text.font: "Sans";
+      part { name: "cover_bg";
+         type: IMAGE;
+         description {  state: "default" 0;
+            min: 90 90;
             rel1.relative: 0.0 0.0;
+            rel2.relative: 0.35 1.0;
+            image.normal: "music_control_icon.png";
+         }
+      }
+      part { name: "cover_swallow";
+         type: SWALLOW;
+         description {  state: "default" 0;
+            rel1.to: "cover_bg";
+            rel2.to: "cover_bg";
+         }
+      }
+      part { name: "player_name";
+         type: TEXT;
+         effect: GLOW;
+         description { state: "default" 0;
+            color: 51 153 255 255;
+            color2: 51 153 255 24;
+            color3: 51 153 255 18;
+            text {
+               size: 12;
+               text: "Music player";
+               font: "Sans:style=Bold";
+            }
+            rel1.to: "cover_bg";
+            rel1.relative: 1.0 0.0;
             rel2.relative: 1.0 0.0;
-            rel2.offset: 0 16;
+            rel2.offset: 0 12;
          }
       }
-      part {
+      part { name: "metadata";
+         type: TEXTBLOCK;
+         description { state: "default" 0;
+            text {
+               style: "music_control_metadata_style";
+               text: "Song Title";
+               align: 0.0 0.0;
+            }
+            rel1.to: "player_name";
+            rel1.relative: 0.0 1.0;
+            rel1.offset: 3 0;
+         }
+      }
+      part { name: "previous_btn";
          type: IMAGE;
-         name: "previous_btn";
-         description {
-            state: "default" 0;
+         description { state: "default" 0;
+            max: 32 32;
             aspect: 1.0 1.0;
             aspect_preference: BOTH;
-            rel1.to: "player_name";
-            rel1.relative: 0.0 1.0;
-            rel2.relative: 0.33 1.0;
+            align: 0.1 1.0;
+            rel1.relative: 0.35 0.0;
             image.normal: "previous.png";
          }
       }
-      part {
+      part { name: "play_btn";
          type: IMAGE;
-         name: "play_btn";
-         description {
-            state: "default" 0;
-               aspect: 1.0 1.0;
-               aspect_preference: BOTH;
-               rel1.to: "player_name";
-               rel1.relative: 0.33 1.0;
-               rel2.relative: 0.66 1.0;
-               image.normal: "pause.png";
+         description { state: "default" 0;
+            max: 32 32;
+            aspect: 1.0 1.0;
+            aspect_preference: BOTH;
+            align: 0.5 1.0;
+            rel1.relative: 0.35 0.0;
+            image.normal: "pause.png";
          }
-         description {
-             state: "play" 0.0;
-             inherit: "default" 0.0;
-             image.normal: "play.png";
+         description { state: "play" 0.0;
+            inherit: "default" 0.0;
+            image.normal: "play.png";
          }
       }
-      part {
+      part {  name: "next_btn";
          type: IMAGE;
-         name: "next_btn";
-         description {
-            state: "default" 0;
-               aspect: 1.0 1.0;
-               aspect_preference: BOTH;
-               rel1.to: "player_name";
-               rel1.relative: 0.66 1.0;
-               rel2.relative: 1.0 1.0;
-               image.normal: "next.png";
+         description { state: "default" 0;
+            max: 32 32;
+            aspect: 1.0 1.0;
+            aspect_preference: BOTH;
+            align: 0.9 1.0;
+            rel1.relative: 0.35 0.0;
+            image.normal: "next.png";
          }
       }
    }
index 3dbd279..2c921e2 100644 (file)
@@ -211,6 +211,60 @@ static const E_Gadcon_Client_Class _gc_class =
 EAPI E_Module_Api e_modapi = { E_MODULE_API_VERSION, _e_music_control_Name };
 
 static void
+parse_metadata(E_Music_Control_Module_Context *ctxt, Eina_Value *array)
+{
+   unsigned i;
+
+   E_FREE_FUNC(ctxt->meta_title, eina_stringshare_del);
+   E_FREE_FUNC(ctxt->meta_album, eina_stringshare_del);
+   E_FREE_FUNC(ctxt->meta_artist, eina_stringshare_del);
+   E_FREE_FUNC(ctxt->meta_cover, eina_stringshare_del);
+   // DBG("Metadata: %s", eina_value_to_string(array));
+
+   for (i = 0; i < eina_value_array_count(array); i++)
+     {
+        const char *key, *str_val;
+        Eina_Value st, subst;
+
+        eina_value_array_value_get(array, i, &st);
+        eina_value_struct_get(&st, "arg0", &key);
+        if (!strcmp(key, "xesam:title"))
+          {
+             eina_value_struct_value_get(&st, "arg1", &subst);
+             eina_value_struct_get(&subst, "arg0", &str_val);
+             ctxt->meta_title = eina_stringshare_add(str_val);
+             eina_value_flush(&subst);
+          }
+        else if (!strcmp(key, "xesam:album"))
+          {
+             eina_value_struct_value_get(&st, "arg1", &subst);
+             eina_value_struct_get(&subst, "arg0", &str_val);
+             ctxt->meta_album = eina_stringshare_add(str_val);
+             eina_value_flush(&subst);
+          }
+        else if (!strcmp(key, "xesam:artist"))
+          {
+             Eina_Value arr;
+             eina_value_struct_value_get(&st, "arg1", &subst);
+             eina_value_struct_value_get(&subst, "arg0", &arr);
+             eina_value_array_get(&arr, 0, &str_val);
+             ctxt->meta_artist = eina_stringshare_add(str_val);
+             eina_value_flush(&arr);
+             eina_value_flush(&subst);
+          }
+        else if (!strcmp(key, "mpris:artUrl"))
+          {
+             eina_value_struct_value_get(&st, "arg1", &subst);
+             eina_value_struct_get(&subst, "arg0", &str_val);
+             if (!strncmp(str_val, "file://", 7))
+               ctxt->meta_cover = eina_stringshare_add(str_val + 7);
+             eina_value_flush(&subst);
+          }
+        eina_value_flush(&st);
+     }
+}
+
+static void
 cb_playback_status_get(void *data, Eldbus_Pending *p, const char *propname, Eldbus_Proxy *proxy, Eldbus_Error_Info *error_info, const char *value)
 {
    E_Music_Control_Module_Context *ctxt = data;
@@ -229,6 +283,14 @@ cb_playback_status_get(void *data, Eldbus_Pending *p, const char *propname, Eldb
 }
 
 static void
+cb_metadata_get(void *data, Eldbus_Pending *p, const char *propname, Eldbus_Proxy *proxy, Eldbus_Error_Info *error_info, Eina_Value *value)
+{
+   E_Music_Control_Module_Context *ctxt = data;
+   parse_metadata(ctxt, value);
+   music_control_metadata_update_all(ctxt);
+}
+
+static void
 prop_changed(void *data, Eldbus_Proxy *proxy, void *event_info)
 {
    Eldbus_Proxy_Event_Property_Changed *event = event_info;
@@ -246,6 +308,11 @@ prop_changed(void *data, Eldbus_Proxy *proxy, void *event_info)
           ctxt->playing = EINA_FALSE;
         music_control_state_update_all(ctxt);
      }
+   else if (!strcmp(event->name, "Metadata"))
+     {
+        parse_metadata(ctxt, (Eina_Value*)event->value);
+        music_control_metadata_update_all(ctxt);
+     }
 }
 
 Eina_Bool
@@ -258,6 +325,7 @@ music_control_dbus_init(E_Music_Control_Module_Context *ctxt, const char *bus)
    ctxt->mrpis2 = mpris_media_player2_proxy_get(ctxt->conn, bus, NULL);
    ctxt->mpris2_player = media_player2_player_proxy_get(ctxt->conn, bus, NULL);
    media_player2_player_playback_status_propget(ctxt->mpris2_player, cb_playback_status_get, ctxt);
+   media_player2_player_metadata_propget(ctxt->mpris2_player, cb_metadata_get, ctxt);
    eldbus_proxy_event_callback_add(ctxt->mpris2_player, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
                                   prop_changed, ctxt);
    return EINA_TRUE;
@@ -306,6 +374,11 @@ e_modapi_shutdown(E_Module *m)
    EINA_SAFETY_ON_NULL_RETURN_VAL(music_control_mod, 0);
    ctxt = music_control_mod->data;
 
+   E_FREE_FUNC(ctxt->meta_title, eina_stringshare_del);
+   E_FREE_FUNC(ctxt->meta_album, eina_stringshare_del);
+   E_FREE_FUNC(ctxt->meta_artist, eina_stringshare_del);
+   E_FREE_FUNC(ctxt->meta_cover, eina_stringshare_del);
+
    free(ctxt->config);
    E_CONFIG_DD_FREE(ctxt->conf_edd);
 
index efae6c0..b674068 100644 (file)
@@ -18,6 +18,10 @@ typedef struct _E_Music_Control_Module_Context
    Eina_List *instances;
    Eldbus_Connection *conn;
    Eina_Bool playing:1;
+   Eina_Stringshare *meta_artist;
+   Eina_Stringshare *meta_album;
+   Eina_Stringshare *meta_title;
+   Eina_Stringshare *meta_cover;
    Eldbus_Proxy *mrpis2;
    Eldbus_Proxy *mpris2_player;
    E_Config_DD *conf_edd;
@@ -38,6 +42,7 @@ void music_control_mouse_down_cb(void *data, Evas *evas, Evas_Object *obj, void
 const char *music_control_edj_path_get(void);
 void music_control_popup_del(E_Music_Control_Instance *inst);
 void music_control_state_update_all(E_Music_Control_Module_Context *ctxt);
+void music_control_metadata_update_all(E_Music_Control_Module_Context *ctxt);
 Eina_Bool music_control_dbus_init(E_Music_Control_Module_Context *ctxt, const char *bus);
 Eina_Bool _desklock_cb(void *data, int type, void *ev);
 
index 06d89b9..c2b956f 100644 (file)
@@ -29,6 +29,46 @@ music_control_state_update_all(E_Music_Control_Module_Context *ctxt)
 }
 
 static void
+_metadata_update(E_Music_Control_Instance *inst)
+{
+   Eina_Strbuf *str;
+   Evas_Object *img;
+
+   if (!inst->popup) return;
+
+   str = eina_strbuf_new();
+
+   if (inst->ctxt->meta_title)
+     eina_strbuf_append_printf(str, "<title>%s</><br>", inst->ctxt->meta_title);
+   if (inst->ctxt->meta_artist)
+     eina_strbuf_append_printf(str, "<tag>by</> %s<br>", inst->ctxt->meta_artist);
+   if (inst->ctxt->meta_album)
+     eina_strbuf_append_printf(str, "<tag>from</> %s<br>", inst->ctxt->meta_album);
+   edje_object_part_text_set(inst->content_popup, "metadata", eina_strbuf_string_get(str));
+   eina_strbuf_free(str);
+
+   img = edje_object_part_swallow_get(inst->content_popup, "cover_swallow");
+   E_FREE_FUNC(img, evas_object_del);
+
+   if (inst->ctxt->meta_cover)
+     {
+        img = evas_object_image_filled_add(evas_object_evas_get(inst->content_popup));
+        evas_object_image_file_set(img, inst->ctxt->meta_cover, NULL);
+        edje_object_part_swallow(inst->content_popup, "cover_swallow", img);
+     }
+}
+
+void
+music_control_metadata_update_all(E_Music_Control_Module_Context *ctxt)
+{
+   E_Music_Control_Instance *inst;
+   Eina_List *list;
+
+   EINA_LIST_FOREACH(ctxt->instances, list, inst)
+     _metadata_update(inst);
+}
+
+static void
 _btn_clicked(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source)
 {
    E_Music_Control_Instance *inst = data;
@@ -79,6 +119,7 @@ _popup_new(E_Music_Control_Instance *inst)
 
    _player_name_update(inst);
    _play_state_update(inst, EINA_TRUE);
+   _metadata_update(inst);
    e_popup_autoclose(inst->popup->win, NULL, NULL, NULL);
    e_gadcon_popup_show(inst->popup);
    e_object_data_set(E_OBJECT(inst->popup), inst);
@@ -88,6 +129,11 @@ _popup_new(E_Music_Control_Instance *inst)
 void
 music_control_popup_del(E_Music_Control_Instance *inst)
 {
+   Evas_Object *cover;
+
+   cover = edje_object_part_swallow_get(inst->content_popup, "cover_swallow");
+   E_FREE_FUNC(cover, evas_object_del);
+
    E_FREE_FUNC(inst->popup, e_object_del);
 }