Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package deadbeef-plugin-mpris2 for openSUSE:Factory checked in at 2021-06-07 22:45:09 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/deadbeef-plugin-mpris2 (Old) and /work/SRC/openSUSE:Factory/.deadbeef-plugin-mpris2.new.32437 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "deadbeef-plugin-mpris2" Mon Jun 7 22:45:09 2021 rev:4 rq:898194 version:1.14 Changes: -------- --- /work/SRC/openSUSE:Factory/deadbeef-plugin-mpris2/deadbeef-plugin-mpris2.changes 2020-01-17 16:08:22.756524974 +0100 +++ /work/SRC/openSUSE:Factory/.deadbeef-plugin-mpris2.new.32437/deadbeef-plugin-mpris2.changes 2021-06-07 22:45:34.760695763 +0200 @@ -1,0 +2,9 @@ +Mon Jun 7 16:09:16 UTC 2021 - Ferdinand Thiessen <r...@fthiessen.de> + +- Update to version 1.14 + * Use Deadbeef title formating to produce metadata more + robust/accurate + * Add "Previous or restart current track" behavior to "Previous" + action + +------------------------------------------------------------------- Old: ---- deadbeef-mpris2-plugin-1.13.tar.xz New: ---- deadbeef-mpris2-plugin-1.14.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ deadbeef-plugin-mpris2.spec ++++++ --- /var/tmp/diff_new_pack.sNFsH1/_old 2021-06-07 22:45:35.152696425 +0200 +++ /var/tmp/diff_new_pack.sNFsH1/_new 2021-06-07 22:45:35.152696425 +0200 @@ -1,7 +1,7 @@ # # spec file for package deadbeef-plugin-mpris2 # -# Copyright (c) 2020 SUSE LLC +# Copyright (c) 2021 SUSE LLC # Copyright (c) 2020 Hillwood Yang <hillw...@opensuse.org> # # All modifications and additions to the file contributed by third parties @@ -19,13 +19,13 @@ %define _name deadbeef-mpris2-plugin Name: deadbeef-plugin-mpris2 -Version: 1.13 +Version: 1.14 Release: 0 Summary: MPRISv2 plugin for the DeaDBeeF music player License: GPL-3.0-or-later Group: Productivity/Multimedia/Sound/Players URL: https://github.com/Serranya/deadbeef-mpris2-plugin -Source: https://github.com/Serranya/%{_name}/releases/download/v%{version}/%{_name}-%{version}.tar.xz +Source: %{url}/releases/download/v%{version}/%{_name}-%{version}.tar.xz BuildRequires: autoconf >= 2.69 BuildRequires: automake BuildRequires: deadbeef-devel >= 0.6.2 @@ -35,7 +35,7 @@ BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(gthread-2.0) Requires: deadbeef >= 0.6.2 -Obsoletes: %{_name} <= %{version} +Obsoletes: %{_name} < %{version} Provides: %{_name} = %{version} Provides: deadbeef-MPRIS-plugin = %{version} Obsoletes: deadbeef-MPRIS-plugin < %{version} @@ -57,7 +57,6 @@ find %{buildroot} -type f -name "*.la" -delete -print %files -%defattr(-,root,root) %doc README %license LICENSE %{_libdir}/deadbeef/ ++++++ deadbeef-mpris2-plugin-1.13.tar.xz -> deadbeef-mpris2-plugin-1.14.tar.xz ++++++ ++++ 14282 lines of diff (skipped) ++++ retrying with extended exclude list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/deadbeef-1.13/README new/deadbeef-1.14/README --- old/deadbeef-1.13/README 2019-06-07 15:06:50.000000000 +0200 +++ new/deadbeef-1.14/README 2021-03-22 11:07:21.000000000 +0100 @@ -27,9 +27,9 @@ - make install ==== For Users ==== -- Grab the tarball from https://github.com/Serranya/deadbeef-mpris2-plugin/releases/download/v1.12/deadbeef-mpris2-plugin-1.12.tar.xz -- tar -xf deadbeef-mpris2-plugin-1.12.tar.xz -- cd deadbeef-mpris-plugin-1.12 +- Grab the tarball from https://github.com/Serranya/deadbeef-mpris2-plugin/releases/download/v1.14/deadbeef-mpris2-plugin-1.14.tar.xz +- tar -xf deadbeef-mpris2-plugin-1.14.tar.xz +- cd deadbeef-mpris-plugin-1.14 - ./configure - make install diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/deadbeef-1.13/build-aux/ar-lib new/deadbeef-1.14/build-aux/ar-lib --- old/deadbeef-1.13/build-aux/ar-lib 2019-06-07 15:10:19.000000000 +0200 +++ new/deadbeef-1.14/build-aux/ar-lib 2021-03-22 10:55:26.000000000 +0100 @@ -2,9 +2,9 @@ # Wrapper for Microsoft lib.exe me=ar-lib -scriptversion=2012-03-01.08; # UTC +scriptversion=2019-07-04.01; # UTC -# Copyright (C) 2010-2018 Free Software Foundation, Inc. +# Copyright (C) 2010-2020 Free Software Foundation, Inc. # Written by Peter Rosin <p...@lysator.liu.se>. # # This program is free software; you can redistribute it and/or modify @@ -53,7 +53,7 @@ MINGW*) file_conv=mingw ;; - CYGWIN*) + CYGWIN* | MSYS*) file_conv=cygwin ;; *) @@ -65,7 +65,7 @@ mingw) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; - cygwin) + cygwin | msys) file=`cygpath -m "$file" || echo "$file"` ;; wine) @@ -224,10 +224,11 @@ esac done else - $AR -NOLOGO -LIST "$archive" | sed -e 's/\\/\\\\/g' | while read member - do - $AR -NOLOGO -EXTRACT:"$member" "$archive" || exit $? - done + $AR -NOLOGO -LIST "$archive" | tr -d '\r' | sed -e 's/\\/\\\\/g' \ + | while read member + do + $AR -NOLOGO -EXTRACT:"$member" "$archive" || exit $? + done fi elif test -n "$quick$replace"; then diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/deadbeef-1.13/build-aux/compile new/deadbeef-1.14/build-aux/compile --- old/deadbeef-1.13/build-aux/compile 2019-06-07 15:10:19.000000000 +0200 +++ new/deadbeef-1.14/build-aux/compile 2021-03-22 10:55:26.000000000 +0100 @@ -3,7 +3,7 @@ scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1999-2018 Free Software Foundation, Inc. +# Copyright (C) 1999-2020 Free Software Foundation, Inc. # Written by Tom Tromey <tro...@cygnus.com>. # # This program is free software; you can redistribute it and/or modify @@ -53,7 +53,7 @@ MINGW*) file_conv=mingw ;; - CYGWIN*) + CYGWIN* | MSYS*) file_conv=cygwin ;; *) @@ -67,7 +67,7 @@ mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; - cygwin/*) + cygwin/* | msys/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/deadbeef-1.13/build-aux/missing new/deadbeef-1.14/build-aux/missing --- old/deadbeef-1.13/build-aux/missing 2019-06-07 15:10:19.000000000 +0200 +++ new/deadbeef-1.14/build-aux/missing 2021-03-22 10:55:26.000000000 +0100 @@ -3,7 +3,7 @@ scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1996-2018 Free Software Foundation, Inc. +# Copyright (C) 1996-2020 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard <pin...@iro.umontreal.ca>, 1996. # This program is free software; you can redistribute it and/or modify diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/deadbeef-1.13/configure.ac new/deadbeef-1.14/configure.ac --- old/deadbeef-1.13/configure.ac 2019-06-07 15:06:50.000000000 +0200 +++ new/deadbeef-1.14/configure.ac 2021-03-22 11:04:37.000000000 +0100 @@ -1,7 +1,7 @@ dnl Process this file with autoconf to produce a configure script. m4_define([plugin_version_major], [1]) -m4_define([plugin_version_minor], [13]) +m4_define([plugin_version_minor], [14]) m4_define([plugin_version], [plugin_version_major.plugin_version_minor]) AC_PREREQ([2.69]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/deadbeef-1.13/m4/libtool.m4 new/deadbeef-1.14/m4/libtool.m4 --- old/deadbeef-1.13/m4/libtool.m4 2019-06-07 15:10:15.000000000 +0200 +++ new/deadbeef-1.14/m4/libtool.m4 2021-03-22 10:55:22.000000000 +0100 @@ -728,7 +728,6 @@ cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/deadbeef-1.13/m4/ltversion.m4 new/deadbeef-1.14/m4/ltversion.m4 --- old/deadbeef-1.13/m4/ltversion.m4 2019-06-07 15:10:15.000000000 +0200 +++ new/deadbeef-1.14/m4/ltversion.m4 2021-03-22 10:55:22.000000000 +0100 @@ -12,11 +12,11 @@ # serial 4221 ltversion.m4 # This file is part of GNU Libtool -m4_define([LT_PACKAGE_VERSION], [2.4.6.42-b88ce]) +m4_define([LT_PACKAGE_VERSION], [2.4.6.42-b88ce-dirty]) m4_define([LT_PACKAGE_REVISION], [2.4.6.42]) AC_DEFUN([LTVERSION_VERSION], -[macro_version='2.4.6.42-b88ce' +[macro_version='2.4.6.42-b88ce-dirty' macro_revision='2.4.6.42' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/deadbeef-1.13/src/mpris.c new/deadbeef-1.14/src/mpris.c --- old/deadbeef-1.13/src/mpris.c 2019-06-07 15:06:50.000000000 +0200 +++ new/deadbeef-1.14/src/mpris.c 2021-03-22 10:55:02.000000000 +0100 @@ -12,6 +12,7 @@ static int onStart() { oldLoopStatus = mprisData.deadbeef->conf_get_int("playback.loop", 0); oldShuffleStatus = mprisData.deadbeef->conf_get_int("playback.order", PLAYBACK_ORDER_LINEAR); + mprisData.previousAction = mprisData.deadbeef->conf_get_int(SETTING_PREVIOUS_ACTION, PREVIOUS_ACTION_PREV_OR_RESTART); #if (GLIB_MAJOR_VERSION <= 2 && GLIB_MINOR_VERSION < 32) mprisThread = g_thread_create(startServer, (void *)&mprisData, TRUE, NULL); @@ -34,6 +35,9 @@ } static int onConnect() { + mprisData.artwork = NULL; + mprisData.prevOrRestart = NULL; + DB_artwork_plugin_t *artworkPlugin = (DB_artwork_plugin_t *)mprisData.deadbeef->plug_get_for_id ("artwork"); if (artworkPlugin != NULL) { @@ -43,6 +47,28 @@ debug("artwork plugin not detected... album art support disabled"); } + DB_plugin_t *hotkeysPlugin = mprisData.deadbeef->plug_get_for_id ("hotkeys"); + + if (hotkeysPlugin != NULL) { + debug("hotkeys plugin detected..."); + + DB_plugin_action_t *dbaction; + + for (dbaction = hotkeysPlugin->get_actions (NULL); dbaction; dbaction = dbaction->next) { + if (strcmp(dbaction->name, "prev_or_restart") == 0) { + debug("prev_or_restart command detected... previous or restart support enabled"); + mprisData.prevOrRestart = dbaction; + break; + } + } + + if (mprisData.prevOrRestart == NULL) { + debug("prev_or_restart command not detected... previous or restart support disabled"); + } + } else { + debug("hotkeys plugin not detected... previous or restart support disabled"); + } + return 0; } @@ -103,6 +129,8 @@ debug("ShuffleStatus changed %d", newShuffleStatus); emitShuffleStatusChanged(oldShuffleStatus = newShuffleStatus); } + + mprisData.previousAction = mprisData.deadbeef->conf_get_int(SETTING_PREVIOUS_ACTION, PREVIOUS_ACTION_PREV_OR_RESTART); } break; default: @@ -112,6 +140,13 @@ return 0; } +#define STR(x) #x +#define XSTR(x) STR(x) + +static const char settings_dlg[] = + "property \"\\\"Previous\\\" action behavior\" select[2] " SETTING_PREVIOUS_ACTION " " XSTR(PREVIOUS_ACTION_PREV_OR_RESTART) " \"Previous\" \"Previous or restart current track\";"; + + DB_misc_t plugin = { .plugin.api_vmajor = DB_API_VERSION_MAJOR,\ .plugin.api_vminor = DB_API_VERSION_MINOR, @@ -143,7 +178,7 @@ .plugin.stop = onStop, .plugin.connect = onConnect, .plugin.disconnect = NULL, - .plugin.configdialog = NULL, + .plugin.configdialog = settings_dlg, .plugin.message = handleEvent, }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/deadbeef-1.13/src/mprisServer.c new/deadbeef-1.14/src/mprisServer.c --- old/deadbeef-1.13/src/mprisServer.c 2019-06-07 15:06:50.000000000 +0200 +++ new/deadbeef-1.14/src/mprisServer.c 2021-03-22 10:55:02.000000000 +0100 @@ -4,6 +4,7 @@ #include <stdlib.h> #include <unistd.h> #include <sys/stat.h> +#include <assert.h> #include <glib.h> #include <gio/gio.h> @@ -17,6 +18,15 @@ #define PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties" #define CURRENT_TRACK -1 +typedef GVariant* (*ProduceVariantCb)(const char *valueStr); + +struct MetaFormatRecord { + const char *fieldName; + const char *valueFormat; + const ProduceVariantCb produceVariantCb; + char *bytecode; +}; + static const char xmlForNode[] = "<node name='/org/mpris/MediaPlayer2'>" " <interface name='org.mpris.MediaPlayer2'>" @@ -75,6 +85,85 @@ static GDBusConnection *globalConnection = NULL; static GMainLoop *loop; +static gboolean bytecodeCompiled; + +static GVariant* produceScalarString(const char *valueStr) { + return g_variant_new_string(valueStr); +} + +static GVariant* produceSingleStringArray(const char *valueStr) { + GVariantBuilder arrayBuilder; + g_variant_builder_init(&arrayBuilder, G_VARIANT_TYPE("as")); + + g_variant_builder_add(&arrayBuilder, "s", valueStr); + + return g_variant_builder_end(&arrayBuilder); +} + +static GVariant* produceScalarInt(const char *valueStr) { + gint32 value = atoi(valueStr); + + if (value <= 0) { + return NULL; + } + + return g_variant_new_int32(value); +} + +static char* chompCr(char *str) { + size_t len = strlen(str); + + if (len > 0 && str[len - 1] == '\r') { + str[len - 1] = '\0'; + } + + return str; +} + +static GVariant* produceArrayOfTokens(const char *valueStr) { + char **tokens = g_strsplit(valueStr, "\n", -1); + + GVariantBuilder arrayBuilder; + g_variant_builder_init(&arrayBuilder, G_VARIANT_TYPE("as")); + + for (char **token = tokens; *token; token++) { + g_variant_builder_add(&arrayBuilder, "s", chompCr(*token)); + } + + g_strfreev(tokens); + + return g_variant_builder_end(&arrayBuilder); +} + +static struct MetaFormatRecord metaFormatRecords[] = { + { "xesam:title", "%title%", produceScalarString }, + { "xesam:album", "%album%", produceScalarString }, + { "xesam:artist", "$if(%artist%,%artist%,Unknown Artist)", produceSingleStringArray }, + { "xesam:albumArtist", "%album artist%", produceSingleStringArray }, + { "xesam:trackNumber", "%track number%", produceScalarInt }, + { "xesam:genre", "%genre%", produceArrayOfTokens }, + { "xesam:contentCreated", "%date%", produceScalarString }, //TODO format date + { "xesam:asText", "$meta(unsynced lyrics)", produceScalarString }, + { "xesam:comment", "$meta(comment)", produceSingleStringArray }, + { "xesam:url", "$if($strcmp($left(%_path_raw%,1),/),file://)%_path_raw%", produceScalarString }, + { NULL } +}; + +static void compileTfBytecode(DB_functions_t *deadbeef) { + debug("Compiling tf bytecode"); + for (struct MetaFormatRecord *record = metaFormatRecords; record->fieldName; record++) { + record->bytecode = deadbeef->tf_compile(record->valueFormat); + assert(record->bytecode); + } +} + +static void freeTfBytecode(DB_functions_t *deadbeef) { + debug("Freeing tf bytecode"); + for (struct MetaFormatRecord *record = metaFormatRecords; record->fieldName; record++) { + deadbeef->tf_free(record->bytecode); + } +} + static void coverartCallback(const char *fname, const char *artist, const char *album, void *userData) { if (fname != NULL) { // cover was not ready debug("Async loaded cover for %s", album); @@ -106,19 +195,8 @@ int buf_size = sizeof(buf); int64_t duration = deadbeef->pl_get_item_duration(track) * 1000000; const char *album = deadbeef->pl_find_meta(track, "album"); - const char *albumArtist = deadbeef->pl_find_meta(track, "albumartist"); - if (albumArtist == NULL) - albumArtist = deadbeef->pl_find_meta(track, "album artist"); - if (albumArtist == NULL) - albumArtist = deadbeef->pl_find_meta(track, "band"); const char *artist = deadbeef->pl_find_meta(track, "artist"); - const char *lyrics = deadbeef->pl_find_meta(track, "lyrics"); - const char *comment = deadbeef->pl_find_meta(track, "comment"); - const char *date = deadbeef->pl_find_meta_raw(track, "year"); - const char *title = deadbeef->pl_find_meta(track, "title"); - const char *trackNumber = deadbeef->pl_find_meta(track, "track"); const char *uri = deadbeef->pl_find_meta(track, ":URI"); - const char *genres = deadbeef->pl_find_meta(track, "genre"); deadbeef->pl_lock(); @@ -131,27 +209,6 @@ g_variant_builder_add(builder, "{sv}", "mpris:length", g_variant_new("x", duration)); } - debug("get Metadata album: %s", album); - if (album != NULL) { - g_variant_builder_add(builder, "{sv}", "xesam:album", g_variant_new("s", album)); - } - - debug("get Metadata albumArtist: %s", albumArtist); - if (albumArtist != NULL) { - GVariantBuilder *albumArtistBuilder = g_variant_builder_new(G_VARIANT_TYPE("as")); - g_variant_builder_add(albumArtistBuilder, "s", albumArtist); - g_variant_builder_add(builder, "{sv}", "xesam:albumArtist", g_variant_builder_end(albumArtistBuilder)); - g_variant_builder_unref(albumArtistBuilder); - } - - debug("get Metadata artist: %s", artist); - if (artist != NULL) { - GVariantBuilder *artistBuilder = g_variant_builder_new(G_VARIANT_TYPE("as")); - g_variant_builder_add(artistBuilder, "s", artist); - g_variant_builder_add(builder, "{sv}", "xesam:artist", g_variant_builder_end(artistBuilder)); - g_variant_builder_unref(artistBuilder); - } - if (mprisData->artwork != NULL) { char *artworkPath = NULL; char *albumArtUri = NULL; @@ -183,64 +240,48 @@ } } - debug("get Metadata lyrics: %s", lyrics); - if (lyrics != NULL) { - g_variant_builder_add(builder, "{sv}", "xesam:asText", g_variant_new("s", lyrics)); - } - - debug("get Metadata comment: %s", comment); - if (comment != NULL) { - GVariantBuilder *commentBuilder = g_variant_builder_new(G_VARIANT_TYPE("as")); - g_variant_builder_add(commentBuilder, "s", comment); - g_variant_builder_add(builder, "{sv}", "xesam:comment", g_variant_builder_end(commentBuilder)); - g_variant_builder_unref(commentBuilder); - } - - if (date == NULL) - date = deadbeef->pl_find_meta(track, "date"); - debug("get Metadata contentCreated: %s", date); //TODO format date - if (date != NULL) { - g_variant_builder_add(builder, "{sv}", "xesam:contentCreated", g_variant_new("s", date)); - } - - debug("get Metdata genres: %s", genres); - if (genres != NULL) { - char *genresCpy = malloc(strlen(genres) + 1); - strcpy(genresCpy, genres); - GVariantBuilder *genreBuilder = g_variant_builder_new(G_VARIANT_TYPE("as")); - - char *genre = strtok(genresCpy, "\n"); - - while (genre != NULL) { - debug("genre is %s with length %d", genre, strlen(genre)); - g_variant_builder_add(genreBuilder, "s", genre); - genre = strtok(NULL, "\n"); + // init on first access + if (!bytecodeCompiled) { + compileTfBytecode(deadbeef); + bytecodeCompiled = TRUE; + } + + for (struct MetaFormatRecord *record = metaFormatRecords; record->fieldName; record++) { + assert(record->valueFormat); + assert(record->produceVariantCb); + assert(record->bytecode); + + ddb_tf_context_t ctx = { + sizeof(ddb_tf_context_t), + DDB_TF_CONTEXT_NO_DYNAMIC | DDB_TF_CONTEXT_MULTILINE, + track, + NULL, + 0, + 0, + PL_MAIN, + 0 + }; + + if (deadbeef->tf_eval(&ctx, record->bytecode, buf, buf_size) < 0) { + error("failed to produce string for field %s", record->fieldName); + continue; } - g_variant_builder_add(builder, "{sv}", "xesam:genre", g_variant_builder_end(genreBuilder)); - g_variant_builder_unref(genreBuilder); - free(genresCpy); - } + if (g_str_equal(buf, "")) { + debug("resulting string is empty, skipping %s field", record->fieldName); + continue; + } - debug("get Metadata title: %s", title); - if (title != NULL) { - g_variant_builder_add(builder, "{sv}", "xesam:title", g_variant_new("s", title)); - } + debug("got string '%s' for field %s", buf, record->fieldName); - debug("get Metadata trackNumber: %s", trackNumber); - if (trackNumber != NULL) { - int trackNumberAsInt = atoi(trackNumber); - if (trackNumberAsInt > 0) { - g_variant_builder_add(builder, "{sv}", "xesam:trackNumber", g_variant_new("i", trackNumberAsInt)); + GVariant *variant = record->produceVariantCb(buf); + if (!variant) { + debug("can't convert string '%s' to proper variant, skipping %s field", buf, record->fieldName); + continue; } - } - char *fullUri = malloc(strlen(uri) + 7 + 1); // strlen(uri) + strlen("file://") + \0 - strcpy(fullUri, "file://"); - strcpy(fullUri + 7, uri); - debug("get Metadata URI: %s", fullUri); - g_variant_builder_add(builder, "{sv}", "xesam:url", g_variant_new("s", fullUri)); - free(fullUri); + g_variant_builder_add(builder, "{sv}", record->fieldName, variant); + } deadbeef->pl_unlock(); deadbeef->pl_item_unref(track); @@ -383,14 +424,20 @@ GDBusMethodInvocation *invocation, void *userData) { debug("Method call on Player interface. sender: %s, methodName %s", sender, methodName); debug("Parameter signature is %s", g_variant_get_type_string (parameters)); - DB_functions_t *deadbeef = ((struct MprisData *)userData)->deadbeef; + struct MprisData *mprisData = (struct MprisData *)userData; + DB_functions_t *deadbeef = mprisData->deadbeef; if (strcmp(methodName, "Next") == 0) { g_dbus_method_invocation_return_value(invocation, NULL); deadbeef->sendmessage(DB_EV_NEXT, 0, 0, 0); } else if (strcmp(methodName, "Previous") == 0) { g_dbus_method_invocation_return_value(invocation, NULL); - deadbeef->sendmessage(DB_EV_PREV, 0, 0, 0); + + if (mprisData->previousAction == PREVIOUS_ACTION_PREV_OR_RESTART && mprisData->prevOrRestart && mprisData->prevOrRestart->callback2 != NULL) { + mprisData->prevOrRestart->callback2(mprisData->prevOrRestart, DDB_ACTION_CTX_MAIN); + } else { + deadbeef->sendmessage(DB_EV_PREV, 0, 0, 0); + } } else if (strcmp(methodName, "Pause") == 0) { g_dbus_method_invocation_return_value(invocation, NULL); deadbeef->sendmessage(DB_EV_PAUSE, 0, 0, 0); @@ -799,6 +846,8 @@ g_dbus_node_info_unref(mprisData->gdbusNodeInfo); g_main_loop_unref(loop); + freeTfBytecode(mprisData->deadbeef); + return 0; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/deadbeef-1.13/src/mprisServer.h new/deadbeef-1.14/src/mprisServer.h --- old/deadbeef-1.13/src/mprisServer.h 2019-06-07 15:06:50.000000000 +0200 +++ new/deadbeef-1.14/src/mprisServer.h 2021-03-22 10:55:02.000000000 +0100 @@ -4,15 +4,21 @@ #include <gio/gio.h> #include <gio/gdesktopappinfo.h> -#define DDB_API_LEVEL 7 +#define DDB_API_LEVEL 9 #define DDB_WARN_DEPRECATED 1 #include <deadbeef/deadbeef.h> #include "artwork.h" +#define SETTING_PREVIOUS_ACTION "mpris2.previous_action" +#define PREVIOUS_ACTION_PREVIOUS 0 +#define PREVIOUS_ACTION_PREV_OR_RESTART 1 + struct MprisData { DB_functions_t *deadbeef; DB_artwork_plugin_t *artwork; + DB_plugin_action_t *prevOrRestart; GDBusNodeInfo *gdbusNodeInfo; + int previousAction; }; void* startServer(void*);