Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package mpv-mpris for openSUSE:Factory 
checked in at 2023-09-20 13:26:53
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/mpv-mpris (Old)
 and      /work/SRC/openSUSE:Factory/.mpv-mpris.new.16627 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "mpv-mpris"

Wed Sep 20 13:26:53 2023 rev:6 rq:1111981 version:1.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/mpv-mpris/mpv-mpris.changes      2023-04-04 
21:26:21.867217593 +0200
+++ /work/SRC/openSUSE:Factory/.mpv-mpris.new.16627/mpv-mpris.changes   
2023-09-20 13:28:38.205457047 +0200
@@ -1,0 +2,9 @@
+Sun Sep 17 01:36:42 UTC 2023 - Muhammad Akbar Yanuar Mantari <mantari...@pm.me>
+
+- Update to 1.1
+  * Fix idle -> playing state transition 
+    gh#hoyon/mpv-mpris#90
+  * add support for embedded cover art
+    gh#hoyon/mpv-mpris#94
+  
+-------------------------------------------------------------------

Old:
----
  mpv-mpris-1.0.tar.gz

New:
----
  mpv-mpris-1.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ mpv-mpris.spec ++++++
--- /var/tmp/diff_new_pack.IX6oju/_old  2023-09-20 13:28:39.349498033 +0200
+++ /var/tmp/diff_new_pack.IX6oju/_new  2023-09-20 13:28:39.349498033 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           mpv-mpris
-Version:        1.0
+Version:        1.1
 Release:        0
 Summary:        MPRIS plugin for mpv
 License:        MIT

++++++ mpv-mpris-1.0.tar.gz -> mpv-mpris-1.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mpv-mpris-1.0/.github/workflows/build.yml 
new/mpv-mpris-1.1/.github/workflows/build.yml
--- old/mpv-mpris-1.0/.github/workflows/build.yml       2023-03-30 
20:21:58.000000000 +0200
+++ new/mpv-mpris-1.1/.github/workflows/build.yml       2023-08-30 
19:19:38.000000000 +0200
@@ -12,7 +12,7 @@
       - name: Install dependencies
         run: |
           sudo apt update
-          sudo apt install libmpv-dev libglib2.0-dev
+          sudo apt install libmpv-dev libglib2.0-dev libavformat-dev
 
       - name: Checkout
         uses: actions/checkout@v3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mpv-mpris-1.0/Makefile new/mpv-mpris-1.1/Makefile
--- old/mpv-mpris-1.0/Makefile  2023-03-30 20:21:58.000000000 +0200
+++ new/mpv-mpris-1.1/Makefile  2023-08-30 19:19:38.000000000 +0200
@@ -7,8 +7,8 @@
 RM := rm
 
 # Base flags, environment CFLAGS / LDFLAGS can be appended.
-BASE_CFLAGS = -std=c99 -Wall -Wextra -O2 -pedantic $(shell $(PKG_CONFIG) 
--cflags gio-2.0 gio-unix-2.0 glib-2.0 mpv)
-BASE_LDFLAGS = $(shell $(PKG_CONFIG) --libs gio-2.0 gio-unix-2.0 glib-2.0)
+BASE_CFLAGS = -std=c99 -Wall -Wextra -O2 -pedantic $(shell $(PKG_CONFIG) 
--cflags gio-2.0 gio-unix-2.0 glib-2.0 mpv libavformat)
+BASE_LDFLAGS = $(shell $(PKG_CONFIG) --libs gio-2.0 gio-unix-2.0 glib-2.0 
libavformat)
 
 SCRIPTS_DIR := $(HOME)/.config/mpv/scripts
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mpv-mpris-1.0/README.md new/mpv-mpris-1.1/README.md
--- old/mpv-mpris-1.0/README.md 2023-03-30 20:21:58.000000000 +0200
+++ new/mpv-mpris-1.1/README.md 2023-08-30 19:19:38.000000000 +0200
@@ -44,6 +44,7 @@
  - mpv development files
  - glib development files
  - gio development files
+ - libavformat development files
 
 Building should be as simple as running `make` in the source code directory.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mpv-mpris-1.0/mpris.c new/mpv-mpris-1.1/mpris.c
--- old/mpv-mpris-1.0/mpris.c   2023-03-30 20:21:58.000000000 +0200
+++ new/mpv-mpris-1.1/mpris.c   2023-08-30 19:19:38.000000000 +0200
@@ -1,9 +1,12 @@
 #include <gio/gio.h>
 #include <glib-unix.h>
 #include <mpv/client.h>
+#include <libavformat/avformat.h>
 #include <inttypes.h>
 #include <string.h>
 
+
+
 static const char *introspection_xml =
     "<node>\n"
     "  <interface name=\"org.mpris.MediaPlayer2\">\n"
@@ -80,6 +83,8 @@
     GHashTable *changed_properties;
     GVariant *metadata;
     gboolean seek_expected;
+    gboolean idle;
+    gboolean paused;
 } UserData;
 
 static const char *STATUS_PLAYING = "Playing";
@@ -230,18 +235,16 @@
 
 static const int art_files_count = sizeof(art_files) / sizeof(art_files[0]);
 
-static void try_put_local_art(mpv_handle *mpv, GVariantDict *dict, char *path)
+static gchar* try_get_local_art(mpv_handle *mpv, char *path)
 {
-    gchar *dirname = g_path_get_dirname(path);
+    gchar *dirname = g_path_get_dirname(path), *out = NULL;
     gboolean found = FALSE;
 
     for (int i = 0; i < art_files_count; i++) {
         gchar *filename = g_build_filename(dirname, art_files[i], NULL);
 
         if (g_file_test(filename, G_FILE_TEST_EXISTS)) {
-            gchar *uri = path_to_uri(mpv, filename);
-            g_variant_dict_insert(dict, "mpris:artUrl", "s", uri);
-            g_free(uri);
+            out = path_to_uri(mpv, filename);
             found = TRUE;
         }
 
@@ -253,6 +256,7 @@
     }
 
     g_free(dirname);
+    return out;
 }
 
 static const char *youtube_url_pattern =
@@ -260,8 +264,9 @@
 
 static GRegex *youtube_url_regex;
 
-static void try_put_youtube_thumbnail(GVariantDict *dict, char *path)
+static gchar* try_get_youtube_thumbnail(char *path)
 {
+    gchar *out = NULL;
     if (!youtube_url_regex) {
         youtube_url_regex = g_regex_new(youtube_url_pattern, 0, 0, NULL);
     }
@@ -271,16 +276,56 @@
 
     if (matched) {
         gchar *video_id = g_match_info_fetch_named(match_info, "id");
-        gchar *thumbnail_url = g_strconcat("https://i1.ytimg.com/vi/";,
+        out = g_strconcat("https://i1.ytimg.com/vi/";,
                                            video_id, "/hqdefault.jpg", NULL);
-        g_variant_dict_insert(dict, "mpris:artUrl", "s", thumbnail_url);
         g_free(video_id);
-        g_free(thumbnail_url);
     }
 
     g_match_info_free(match_info);
+    return out;
+}
+
+static gchar* extract_embedded_art(AVFormatContext *context) {
+    if (avformat_find_stream_info(context, NULL) < 0) {
+        g_printerr("failed to find stream info");
+        return NULL;
+    }
+
+    AVPacket *packet = NULL;
+    for (unsigned int i = 0; i < context->nb_streams; i++) {
+        if (context->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC) {
+            packet = &context->streams[i]->attached_pic;
+        }
+    }
+    if (!packet) {
+        return NULL;
+    }
+
+    gchar *data = g_base64_encode(packet->data, packet->size);
+    gchar *img = g_strconcat("data:image/jpeg;base64,", data, NULL);
+
+    g_free(data);
+    return img;
 }
 
+static gchar* try_get_embedded_art(char *path)
+{
+    gchar *out = NULL;
+    AVFormatContext *context = NULL;
+    if (!avformat_open_input(&context, path, NULL, NULL)) {
+        out = extract_embedded_art(context);
+        avformat_close_input(&context);
+    }
+
+    return out;
+}
+
+// cached last file path, owned by mpv
+static char *cached_path = NULL;
+
+// cached last artwork url, owned by glib
+static gchar *cached_art_url = NULL;
+
 static void add_metadata_art(mpv_handle *mpv, GVariantDict *dict)
 {
     char *path = mpv_get_property_string(mpv, "path");
@@ -289,13 +334,27 @@
         return;
     }
 
-    if (g_str_has_prefix(path, "http")) {
-        try_put_youtube_thumbnail(dict, path);
+    // mpv may call create_metadata multiple times, so cache to save CPU
+    if (!cached_path || strcmp(path, cached_path)) {
+        mpv_free(cached_path);
+        g_free(cached_art_url);
+        cached_path = path;
+
+        if (g_str_has_prefix(path, "http")) {
+            cached_art_url = try_get_youtube_thumbnail(path);
+        } else {
+            cached_art_url = try_get_embedded_art(path);
+            if (!cached_art_url) {
+                cached_art_url = try_get_local_art(mpv, path);
+            }
+        }
     } else {
-        try_put_local_art(mpv, dict, path);
+        mpv_free(path);
     }
 
-    mpv_free(path);
+    if (cached_art_url) {
+        g_variant_dict_insert(dict, "mpris:artUrl", "s", cached_art_url);
+    }
 }
 
 static void add_metadata_content_created(mpv_handle *mpv, GVariantDict *dict)
@@ -795,6 +854,18 @@
     }
 }
 
+static GVariant * set_playback_status(UserData *ud)
+{
+    if (ud->idle) {
+        ud->status = STATUS_STOPPED;
+    } else if (ud->paused) {
+        ud->status = STATUS_PAUSED;
+    } else {
+        ud->status = STATUS_PLAYING;
+    }
+    return g_variant_new_string(ud->status);
+}
+
 static void set_stopped_status(UserData *ud)
 {
   const char *prop_name = "PlaybackStatus";
@@ -858,14 +929,14 @@
     const char *prop_name = NULL;
     GVariant *prop_value = NULL;
     if (g_strcmp0(name, "pause") == 0) {
-        int *paused = data;
-        if (*paused) {
-            ud->status = STATUS_PAUSED;
-        } else {
-            ud->status = STATUS_PLAYING;
-        }
+        ud->paused = *(int*)data;
         prop_name = "PlaybackStatus";
-        prop_value = g_variant_new_string(ud->status);
+        prop_value = set_playback_status(ud);
+
+    } else if (g_strcmp0(name, "idle-active") == 0) {
+        ud->idle = *(int*)data;
+        prop_name = "PlaybackStatus";
+        prop_value = set_playback_status(ud);
 
     } else if (g_strcmp0(name, "media-title") == 0 ||
                g_strcmp0(name, "duration") == 0) {
@@ -926,6 +997,7 @@
         gboolean *status = data;
         prop_name = "Fullscreen";
         prop_value = g_variant_new_boolean(*status);
+
     }
 
     if (prop_name) {
@@ -956,9 +1028,6 @@
             set_stopped_status(ud);
             g_main_loop_quit(ud->loop);
             break;
-        case MPV_EVENT_IDLE:
-            set_stopped_status(ud);
-            break;
         case MPV_EVENT_PROPERTY_CHANGE: {
             mpv_event_property *prop_event = (mpv_event_property*)event->data;
             handle_property_change(prop_event->name, prop_event->data, ud);
@@ -1016,6 +1085,8 @@
     ud.loop_status = LOOP_NONE;
     ud.changed_properties = g_hash_table_new(g_str_hash, g_str_equal);
     ud.seek_expected = FALSE;
+    ud.idle = FALSE;
+    ud.paused = FALSE;
 
     g_main_context_push_thread_default(ctx);
     ud.bus_id = g_bus_own_name(G_BUS_TYPE_SESSION,
@@ -1029,6 +1100,7 @@
 
     // Receive event for property changes
     mpv_observe_property(mpv, 0, "pause", MPV_FORMAT_FLAG);
+    mpv_observe_property(mpv, 0, "idle-active", MPV_FORMAT_FLAG);
     mpv_observe_property(mpv, 0, "media-title", MPV_FORMAT_STRING);
     mpv_observe_property(mpv, 0, "speed", MPV_FORMAT_DOUBLE);
     mpv_observe_property(mpv, 0, "volume", MPV_FORMAT_DOUBLE);

Reply via email to