Hello community,

here is the log from the commit of package upmpdcli for openSUSE:Factory 
checked in at 2020-12-09 22:22:20
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/upmpdcli (Old)
 and      /work/SRC/openSUSE:Factory/.upmpdcli.new.2328 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "upmpdcli"

Wed Dec  9 22:22:20 2020 rev:2 rq:854281 version:1.5.5

Changes:
--------
--- /work/SRC/openSUSE:Factory/upmpdcli/upmpdcli.changes        2020-11-30 
09:53:46.457774084 +0100
+++ /work/SRC/openSUSE:Factory/.upmpdcli.new.2328/upmpdcli.changes      
2020-12-09 22:22:21.659732559 +0100
@@ -1,0 +2,10 @@
+Wed Dec  9 13:56:21 UTC 2020 - Michael Pujos <[email protected]>
+
+- update to 1.5.5:
+  * Fix issue with removing tracks from the playlist (sometimes slow or 
freezed).
+  * Fix bad locking causing multiple execs of radio scripts.
+  * Setting lumincompat = 1 is not useful any more and crashes some Kazoo 
versions.
+    So you should keep the default value which is off.
+  * Improve metadata processing when playing radios with BubbleDS.
+
+-------------------------------------------------------------------
@@ -12 +21,0 @@
-

Old:
----
  upmpdcli-1.5.2.tar.gz

New:
----
  upmpdcli-1.5.5.tar.gz

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

Other differences:
------------------
++++++ upmpdcli.spec ++++++
--- /var/tmp/diff_new_pack.8FpjtO/_old  2020-12-09 22:22:22.163733071 +0100
+++ /var/tmp/diff_new_pack.8FpjtO/_new  2020-12-09 22:22:22.163733071 +0100
@@ -17,16 +17,16 @@
 
 
 Name:           upmpdcli
-Version:        1.5.2
+Version:        1.5.5
 Release:        0
 Summary:        UPnP Media Renderer front-end to MPD, the Music Player Daemon
 License:        GPL-2.0-or-later
 URL:            https://www.lesbonscomptes.com/updmpdcli
 Source0:        
https://www.lesbonscomptes.com/upmpdcli/downloads/upmpdcli-%{version}.tar.gz
 BuildRequires:  gcc-c++
-BuildRequires:  group(audio)
 BuildRequires:  pkgconfig
 BuildRequires:  systemd-rpm-macros
+BuildRequires:  group(audio)
 BuildRequires:  pkgconfig(jsoncpp)
 BuildRequires:  pkgconfig(libmicrohttpd)
 BuildRequires:  pkgconfig(libmpdclient)

++++++ upmpdcli-1.5.2.tar.gz -> upmpdcli-1.5.5.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/upmpdcli-1.5.2/configure new/upmpdcli-1.5.5/configure
--- old/upmpdcli-1.5.2/configure        2020-11-24 18:09:52.000000000 +0100
+++ new/upmpdcli-1.5.5/configure        2020-12-07 18:01:42.000000000 +0100
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for upmpdcli 1.5.2.
+# Generated by GNU Autoconf 2.69 for upmpdcli 1.5.5.
 #
 # Report bugs to <[email protected]>.
 #
@@ -580,8 +580,8 @@
 # Identity of this package.
 PACKAGE_NAME='upmpdcli'
 PACKAGE_TARNAME='upmpdcli'
-PACKAGE_VERSION='1.5.2'
-PACKAGE_STRING='upmpdcli 1.5.2'
+PACKAGE_VERSION='1.5.5'
+PACKAGE_STRING='upmpdcli 1.5.5'
 PACKAGE_BUGREPORT='[email protected]'
 PACKAGE_URL='http://www.lesbonscomptes.com/upmpdcli'
 
@@ -1331,7 +1331,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures upmpdcli 1.5.2 to adapt to many kinds of systems.
+\`configure' configures upmpdcli 1.5.5 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1398,7 +1398,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of upmpdcli 1.5.2:";;
+     short | recursive ) echo "Configuration of upmpdcli 1.5.5:";;
    esac
   cat <<\_ACEOF
 
@@ -1523,7 +1523,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-upmpdcli configure 1.5.2
+upmpdcli configure 1.5.5
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1826,7 +1826,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by upmpdcli $as_me 1.5.2, which was
+It was created by upmpdcli $as_me 1.5.5, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2696,7 +2696,7 @@
 
 # Define the identity of the package.
  PACKAGE='upmpdcli'
- VERSION='1.5.2'
+ VERSION='1.5.5'
 
 
 # Some tools Automake needs.
@@ -6136,7 +6136,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by upmpdcli $as_me 1.5.2, which was
+This file was extended by upmpdcli $as_me 1.5.5, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -6203,7 +6203,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; 
s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-upmpdcli config.status 1.5.2
+upmpdcli config.status 1.5.5
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/upmpdcli-1.5.2/configure.ac 
new/upmpdcli-1.5.5/configure.ac
--- old/upmpdcli-1.5.2/configure.ac     2020-11-24 18:09:38.000000000 +0100
+++ new/upmpdcli-1.5.5/configure.ac     2020-12-07 18:00:19.000000000 +0100
@@ -1,4 +1,4 @@
-AC_INIT([upmpdcli], [1.5.2], [[email protected]],
+AC_INIT([upmpdcli], [1.5.5], [[email protected]],
              [upmpdcli], [http://www.lesbonscomptes.com/upmpdcli])
 AC_PREREQ([2.53])
 AC_CONFIG_MACRO_DIRS([m4])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/upmpdcli-1.5.2/src/main.cxx 
new/upmpdcli-1.5.5/src/main.cxx
--- old/upmpdcli-1.5.2/src/main.cxx     2020-11-24 10:51:35.000000000 +0100
+++ new/upmpdcli-1.5.5/src/main.cxx     2020-12-01 10:39:38.000000000 +0100
@@ -404,7 +404,7 @@
         if (g_config->get("scsendermpdport", value))
             sendermpdport = atoi(value.c_str());
 
-        g_lumincompat = g_config->getBool("lumincompat", false);
+        g_lumincompat = g_config->getBool("lumincompat", g_lumincompat);
     } else {
         // g_configfilename is empty. Create an empty config anyway
         g_config = new ConfSimple(string(), 1, true);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/upmpdcli-1.5.2/src/mpdcli.cxx 
new/upmpdcli-1.5.5/src/mpdcli.cxx
--- old/upmpdcli-1.5.2/src/mpdcli.cxx   2020-11-13 10:45:39.000000000 +0100
+++ new/upmpdcli-1.5.5/src/mpdcli.cxx   2020-12-01 09:56:00.000000000 +0100
@@ -285,10 +285,12 @@
         LOGERR(who << " server error: " << 
                mpd_connection_get_server_error(m_conn) << endl);
     }
-
     if (error == MPD_ERROR_CLOSED)
         if (openconn())
             return true;
+
+    if (!mpd_connection_clear_error(m_conn))
+        openconn();
     return false;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/upmpdcli-1.5.2/src/ohcredentials.cxx 
new/upmpdcli-1.5.5/src/ohcredentials.cxx
--- old/upmpdcli-1.5.2/src/ohcredentials.cxx    2020-11-12 16:50:51.000000000 
+0100
+++ new/upmpdcli-1.5.5/src/ohcredentials.cxx    2020-11-30 15:16:34.000000000 
+0100
@@ -637,6 +637,7 @@
            in_Enabled << endl);
     if (m->setEnabled(in_Id, in_Enabled)) {
         m->seq++;
+        onEvent(nullptr);
         return UPNP_E_SUCCESS;
     } else {
         return 800;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/upmpdcli-1.5.2/src/ohinfo.cxx 
new/upmpdcli-1.5.5/src/ohinfo.cxx
--- old/upmpdcli-1.5.2/src/ohinfo.cxx   2020-11-24 11:13:36.000000000 +0100
+++ new/upmpdcli-1.5.5/src/ohinfo.cxx   2020-12-06 16:46:27.000000000 +0100
@@ -63,13 +63,13 @@
     bool is_song = (mpds.state == MpdStatus::MPDS_PLAY) || 
         (mpds.state == MpdStatus::MPDS_PAUSE);
 
-    if (is_song) {
-        uri = mpds.currentsong.rsrc.uri;
-        // If somebody (e.g. ohradio) took care to set the metatext, use it.
-        // Metatext is reset by OHProduct::setSourceIndex.
-        if (!m_metatext.empty()) {
-            metadata = m_metatext;
-        } else {
+    // If somebody (e.g. ohradio) took care to set the metadata, use it.
+    // Metadata is reset by OHProduct::setSourceIndex.
+    if (!m_metadata.empty()) {
+        metadata = m_metadata;
+    } else {
+        if (is_song) {
+            uri = mpds.currentsong.rsrc.uri;
             // Playlist or AVTransport playing, probably.
             // Prefer metadata from cache (copy from media server) to
             // whatever comes from mpd.
@@ -77,10 +77,10 @@
                 return;
             }
             metadata = didlmake(mpds.currentsong);
+        } else {
+            uri.clear();
+            metadata.clear();
         }
-    } else {
-        uri.clear();
-        metadata.clear();
     }
 }
 
@@ -102,22 +102,22 @@
     }
 }
 
+// For radios: Metadata is for the static channel name. Metatext is
+// for the current song. Both are didl.
 bool OHInfo::makestate(unordered_map<string, string> &st)
 {
     st.clear();
-
     st["TrackCount"] = SoapHelp::i2s(m_dev->getMpdStatus().trackcounter);
-    st["DetailsCount"] =
-        SoapHelp::i2s(m_dev->getMpdStatus().detailscounter);
+    st["DetailsCount"] = SoapHelp::i2s(m_dev->getMpdStatus().detailscounter);
     st["MetatextCount"] = SoapHelp::i2s(m_metatextcnt);
     string uri, metadata;
     urimetadata(uri, metadata);
     st["Uri"] = uri;
     st["Metadata"] = metadata;
+    st["Metatext"] = m_metatext;
     makedetails(st["Duration"], st["BitRate"], 
st["BitDepth"],st["SampleRate"]);
     st["Lossless"] = "0";
     st["CodecName"] = "";
-    st["Metatext"] = m_metatext.empty() ? metadata : m_metatext;
     return true;
 }
 
@@ -159,6 +159,7 @@
     return UPNP_E_SUCCESS;
 }
 
+// See note above about metatext/metadata, this is wrong.
 int OHInfo::metatext(const SoapIncoming& sc, SoapOutgoing& data)
 {
     LOGDEB("OHInfo::metatext" << endl);
@@ -166,12 +167,13 @@
     return UPNP_E_SUCCESS;
 }
 
-void OHInfo::setMetatext(const string& metatext)
+// Called from ohradio only at the moment. Should we call it from playlist?
+void OHInfo::setMetadata(const string& metadata, const string& metatext)
 {
-    //LOGDEB1("OHInfo::setMetatext: " << metatext << endl);
-    if (metatext.compare(m_metatext)) {
+    //LOGDEB1("OHInfo::setMetadata: " << metadata << endl);
+    m_metadata = metadata;
+    if (metatext != m_metatext) {
         m_metatext = metatext;
         m_metatextcnt++;
-        onEvent(nullptr);
     }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/upmpdcli-1.5.2/src/ohinfo.hxx 
new/upmpdcli-1.5.5/src/ohinfo.hxx
--- old/upmpdcli-1.5.2/src/ohinfo.hxx   2020-11-12 16:50:51.000000000 +0100
+++ new/upmpdcli-1.5.5/src/ohinfo.hxx   2020-12-03 19:31:51.000000000 +0100
@@ -37,8 +37,14 @@
     // cached data.
     OHInfo(UpMpd *dev, UpMpdOpenHome *udev, bool updstatus);
 
-    void setMetatext(const std::string& metatext);
-
+    // When set from a radio, metadata is the static channel name and
+    // metatext is the dynamic current title info. Both are
+    // didl-encoded
+    void setMetadata(const std::string& metadata, const std::string& metatext);
+    void resetMetadata() {
+        m_metatext = m_metadata = "";
+        m_metatextcnt++;
+    }
     void setOHPL(OHPlaylist *ohp) {
         m_ohpl = ohp;
     }
@@ -56,6 +62,7 @@
     void makedetails(std::string &duration, std::string& bitrate,
                      std::string& bitdepth, std::string& samplerate);
 
+    std::string m_metadata;
     std::string m_metatext;
     int m_metatextcnt{0};
     bool m_updstatus{false};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/upmpdcli-1.5.2/src/ohplaylist.cxx 
new/upmpdcli-1.5.5/src/ohplaylist.cxx
--- old/upmpdcli-1.5.2/src/ohplaylist.cxx       2020-11-24 14:34:58.000000000 
+0100
+++ new/upmpdcli-1.5.5/src/ohplaylist.cxx       2020-12-01 10:04:59.000000000 
+0100
@@ -305,13 +305,6 @@
     makestate(st);
 }
 
-void OHPlaylist::maybeWakeUp(bool ok)
-{
-    if (ok && m_dev) {
-        onEvent(nullptr);
-    }
-}
-
 void OHPlaylist::setActive(bool onoff)
 {
     if (onoff) {
@@ -321,7 +314,7 @@
             m_dev->getmpdcli()->consume(false);
         m_dev->getmpdcli()->single(false);
         refreshState();
-        maybeWakeUp(true);
+        onEvent(nullptr);
         m_active = true;
     } else {
         m_mpdqvers = -1;
@@ -343,7 +336,6 @@
         m_dev->getmpdcli()->consume(false);
     m_dev->getmpdcli()->single(false);
     ok = m_dev->getmpdcli()->play();
-    maybeWakeUp(ok);
     return ok ? UPNP_E_SUCCESS : UpnpService::UPNP_ACTION_FAILED;
 }
 
@@ -351,14 +343,12 @@
 {
     LOGDEB("OHPlaylist::pause" << endl);
     bool ok = m_dev->getmpdcli()->pause(true);
-    maybeWakeUp(ok);
     return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
 }
 
 int OHPlaylist::iStop()
 {
     bool ok = m_dev->getmpdcli()->stop();
-    maybeWakeUp(ok);
     return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
 }
 int OHPlaylist::stop(const SoapIncoming& sc, SoapOutgoing& data)
@@ -375,7 +365,6 @@
     }
     LOGDEB("OHPlaylist::next" << endl);
     bool ok = m_dev->getmpdcli()->next();
-    maybeWakeUp(ok);
     return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
 }
 
@@ -387,7 +376,6 @@
     }
     LOGDEB("OHPlaylist::previous" << endl);
     bool ok = m_dev->getmpdcli()->previous();
-    maybeWakeUp(ok);
     return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
 }
 
@@ -402,7 +390,6 @@
     bool ok = sc.get("Value", &onoff);
     if (ok) {
         ok = m_dev->getmpdcli()->repeat(onoff);
-        maybeWakeUp(ok);
     }
     return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
 }
@@ -432,7 +419,6 @@
         // Note that mpd shuffle shuffles the playlist, which is different
         // from playing at random
         ok = m_dev->getmpdcli()->random(onoff);
-        maybeWakeUp(ok);
     }
     return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
 }
@@ -460,7 +446,6 @@
     bool ok = sc.get("Value", &seconds);
     if (ok) {
         ok = m_dev->getmpdcli()->seek(seconds);
-        maybeWakeUp(ok);
     }
     return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
 }
@@ -484,7 +469,6 @@
         } else {
             ok = false;
         }
-        maybeWakeUp(ok);
     }
     return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
 }
@@ -531,7 +515,6 @@
         m_dev->getmpdcli()->consume(false);
     m_dev->getmpdcli()->single(false);
     bool ok = m_dev->getmpdcli()->playId(id);
-    maybeWakeUp(ok);
     return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
 }
 
@@ -552,7 +535,6 @@
             m_dev->getmpdcli()->consume(false);
         m_dev->getmpdcli()->single(false);
         ok = m_dev->getmpdcli()->play(pos);
-        maybeWakeUp(ok);
     }
     return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
 }
@@ -769,7 +751,6 @@
         data.addarg("NewId", SoapHelp::i2s(newid));
         LOGDEB("OHPlaylist::insert: new id: " << newid << endl);
     }
-    maybeWakeUp(ok);
     return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
 }
 
@@ -826,7 +807,6 @@
     }
     bool ok = m_dev->getmpdcli()->deleteId(id);
     m_mpdqvers = -1;
-    maybeWakeUp(ok);
     return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
 }
 
@@ -838,7 +818,6 @@
     }
     bool ok = m_dev->getmpdcli()->clearQueue();
     m_mpdqvers = -1;
-    maybeWakeUp(ok);
     return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/upmpdcli-1.5.2/src/ohplaylist.hxx 
new/upmpdcli-1.5.5/src/ohplaylist.hxx
--- old/upmpdcli-1.5.2/src/ohplaylist.hxx       2020-11-12 16:50:51.000000000 
+0100
+++ new/upmpdcli-1.5.5/src/ohplaylist.hxx       2020-12-01 10:05:05.000000000 
+0100
@@ -74,7 +74,6 @@
     // Private internal non-soap versions of some of the interface +
     // utility methods
     bool makeIdArray(std::string&);
-    void maybeWakeUp(bool ok);
     void refreshState();
     bool insertUri(int afterid, const std::string& uri, 
                    const std::string& metadata, int *newid, bool nocheck);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/upmpdcli-1.5.2/src/ohproduct.cxx 
new/upmpdcli-1.5.5/src/ohproduct.cxx
--- old/upmpdcli-1.5.2/src/ohproduct.cxx        2020-11-24 14:57:13.000000000 
+0100
+++ new/upmpdcli-1.5.5/src/ohproduct.cxx        2020-12-02 10:52:07.000000000 
+0100
@@ -297,7 +297,7 @@
         return UPNP_E_SUCCESS;
     }
 
-    m_udev->getohif()->setMetatext("");
+    m_udev->getohif()->resetMetadata();
 
     bool ok = true;
     string curtp = o_sources[m_sourceIndex].first;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/upmpdcli-1.5.2/src/ohradio.cxx 
new/upmpdcli-1.5.5/src/ohradio.cxx
--- old/upmpdcli-1.5.2/src/ohradio.cxx  2020-11-24 14:36:04.000000000 +0100
+++ new/upmpdcli-1.5.5/src/ohradio.cxx  2020-12-07 16:02:00.000000000 +0100
@@ -91,9 +91,15 @@
         }
         preferScript = stringToBool(ps);
     }
+
+    // The static title, URI and icon (from the radios configuration or
+    // setChannel) are always used in the ohradio interface. The
+    // dynamic currently playing title and metadata are only sent to
+    // OHInfo and obtainable from there.
     string title;
-    // Static playlist URI (from config)
     string uri;
+    string artUri;
+    
     // Script to retrieve current art
     vector<string> artScript; 
     // Script to retrieve all metadata
@@ -102,7 +108,6 @@
     // uri, which will normally be empty if the metascript is used for
     // audio).
     string currentAudioUri;
-    string artUri;
     // Keep values from script over mpd's (from icy)
     bool preferScript{true};
     // Time after which we should re-fire the metadata script
@@ -112,6 +117,10 @@
     string dynArtist;
 };
 
+
+// Our radio channels. The Id is an index is this. Channel 0 is
+// reserved for externally set Uri/Metadata from SetChannel. Our
+// preset channels (from the config) begin at 1
 static vector<RadioMeta> o_radios;
 
 OHRadio::OHRadio(UpMpd *dev, UpMpdOpenHome *udev)
@@ -128,7 +137,7 @@
         return;
     }
 
-    // Try to restore the current preset channel if this was memorized.
+    // Try to restore the channel if this was memorized.
     string refstr;
     if (g_state && g_state->get(cstr_sturlkey, refstr)) {
         for (unsigned int i = 0; i < o_radios.size(); i++) {
@@ -211,7 +220,7 @@
 
 bool OHRadio::readRadios()
 {
-    // Id 0 means no selection
+    // Id 0 means no selection /  externally set channel from setChannel()
     o_radios.push_back(RadioMeta("Unknown radio", "", "", "", "", ""));
     
     getRadiosFromConf(g_config);
@@ -335,6 +344,7 @@
 
 bool OHRadio::makestate(unordered_map<string, string>& st)
 {
+    LOGDEB1("OHRadio::makestate\n");
     st.clear();
 
     MpdStatus mpds = m_dev->getMpdStatus();
@@ -344,28 +354,36 @@
     makeIdArray(st["IdArray"]);
     st["ProtocolInfo"] = Protocolinfo::the()->gettext();
     st["TransportState"] =  mpdstatusToTransportState(mpds.state);
-    st["Uri"] = mpds.currentsong.rsrc.uri;
-
     st["Metadata"] =  "";
+    st["Uri"] = "";
 
     if (!m_active) {
         st["TransportState"] =  "Stopped";
-        st["Uri"] = "";
         return true;
     }
 
     if (m_id < 0 || m_id >= o_radios.size()) {
         // ??
-        LOGDEB("OHRadio::makestate: bad m_id " << m_id << endl);
+        LOGERR("OHRadio::makestate: bad m_id " << m_id << endl);
         return true;
     }
         
+    RadioMeta& radio = o_radios[m_id];
+
+    // In any case, Uri and Metadata are fixed and come from the channel.
+    // The dynamic data is sent to ohinfo.
+    st["Metadata"] = metaForId(m_id);
+    // We used to set this to mpds.currentsong.rsrc.uri. From
+    // re-reading the spec, using the radio uri seems more appropriate
+    st["Uri"] = radio.uri.empty() ? radio.currentAudioUri:radio.uri;
+
+    /////////////
+    // Compute dynamic metadata for ohinfo
+
     if (mpds.currentsong.album.empty()) {
-        mpds.currentsong.album = o_radios[m_id].title;
+        mpds.currentsong.album = radio.title;
     }
 
-    RadioMeta& radio = o_radios[m_id];
-
     // Some radios do not insert icy metadata in the stream, but rather
     // provide a script to retrieve it.
     bool nompddata = mpds.currentsong.title.empty() &&
@@ -376,7 +394,10 @@
         mpds.currentsong.title = radio.dynTitle;
         mpds.currentsong.artist = radio.dynArtist;
     }
-
+    if (mpds.currentsong.title.empty()) {
+        mpds.currentsong.title = radio.title;
+    }
+        
     // Some radios provide a url to the art for the current song. 
     // Execute script to retrieve it if the current title+artist changed
     if (radio.artScript.size()) {
@@ -396,22 +417,21 @@
     mpds.currentsong.artUri = radio.dynArtUri.empty() ? radio.artUri :
         radio.dynArtUri;
 
-    string meta = didlmake(mpds.currentsong);
-    st["Metadata"] =  meta;
-    m_udev->getohif()->setMetatext(meta);
-    return true;
-}
-
-void OHRadio::maybeWakeUp(bool ok)
-{
-    if (ok) {
-        onEvent(nullptr);
+    // Don't report the ever changing bitrate, this causes unnecessary
+    // events. CPs interested in bitrate changes can get them from the
+    // Info service Details state variable
+    if (st["TransportState"] != "Playing") {
+        m_udev->getohif()->setMetadata(st["Metadata"], "");
+    } else {
+        string metatext = didlmake(mpds.currentsong, true);
+        m_udev->getohif()->setMetadata(st["Metadata"], metatext);
     }
+    return true;
 }
 
 int OHRadio::setPlaying()
 {
-    if (m_id > o_radios.size()) {
+    if (m_id >= o_radios.size()) {
         LOGERR("OHRadio::setPlaying: called with bad id (" << m_id << ")\n");
         return UPNP_E_INTERNAL_ERROR;
     }
@@ -428,8 +448,8 @@
         // We count on the metascript to also return an audio URI,
         // which will be sent to MPD during makestate().
         radio.currentAudioUri.clear();
-        m_dev->getmpdcli()->clearQueue();
         m_playpending = true;
+        m_dev->getmpdcli()->clearQueue();
         return UPNP_E_SUCCESS;
     }
     
@@ -487,7 +507,7 @@
                 m_dev->getmpdcli()->restoreState(m_mpdsavedstate);
             }
         }
-        maybeWakeUp(true);
+        onEvent(nullptr);
     } else {
         m_dev->getmpdcli()->saveState(m_mpdsavedstate);
         m_dev->getmpdcli()->clearQueue();
@@ -498,7 +518,6 @@
 int OHRadio::iPlay()
 {
     int ret = setPlaying();
-    maybeWakeUp(ret == UPNP_E_SUCCESS);
     return ret;
 }
 
@@ -516,7 +535,6 @@
     LOGDEB("OHRadio::pause" << endl);
     bool ok = m_dev->getmpdcli()->pause(true);
     m_playpending = false;
-    maybeWakeUp(ok);
     return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
 }
 
@@ -524,7 +542,6 @@
 {
     bool ok = m_dev->getmpdcli()->stop();
     m_playpending = false;
-    maybeWakeUp(ok);
     return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
 }
 int OHRadio::stop(const SoapIncoming& sc, SoapOutgoing& data)
@@ -554,7 +571,6 @@
         uMetaToUpSong(metadata, &ups);
         o_radios[0].title = ups.album + " " + ups.title;
     }
-    maybeWakeUp(ok);
     return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
 }
 
@@ -581,7 +597,6 @@
         g_state->set(cstr_sturlkey, refstr);
     }
     
-    maybeWakeUp(true);
     return UPNP_E_SUCCESS;
 }
 
@@ -593,59 +608,28 @@
     return UPNP_E_SUCCESS;
 }
 
-static string radioDidlMake(const string& title, const string& uri,
-                            const string& artUri)
-{
-    string out("<DIDL-Lite xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n";
-               "xmlns:upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\"\n"
-               "xmlns=\"urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/\">\n"
-               "<item id=\"\" parentID=\"\" restricted=\"True\">\n"
-               "<dc:title>");
-    out += SoapHelp::xmlQuote(title);
-    out += "</dc:title>\n"
-        "<res protocolInfo=\"*:*:*:*\" bitrate=\"6000\">";
-    if (uri.empty()) {
-        // Kazoo absolutely does not want uri to be empty, else it
-        // does not display anything in the radio list (not even the
-        // entries with uris). So fill up with bogus value. This is
-        // not used anyway because setId/setPlaying use the value from
-        // the radio array or from the metascript
-        out += SoapHelp::xmlQuote("http://www.bogus.com/bogus.mp3";);
-    } else {
-        out += SoapHelp::xmlQuote(uri);
-    }
-    out += "</res>\n";
-    if (!artUri.empty()) {
-        out +=  "<upnp:albumArtURI>";
-        out += SoapHelp::xmlQuote(artUri);
-        out += "</upnp:albumArtURI>\n";
-    }
-    out +=  "<upnp:class>object.item.audioItem</upnp:class>\n"
-        "</item>\n"
-        "</DIDL-Lite>\n";
-    return out;
-}
-
 // This is called from read, and readlist. Don't send current metadata
 // (including dynamic art and song title) for the current channel,
 // else the radio logo AND name are replaced by the song's in channel
-// selection interfaces. Only send the song metadata with
-// OHRadio::Channel and Info:Metatext
+// selection interfaces. Only send the song metadata from the Info
+// service metatext variable
 string OHRadio::metaForId(unsigned int id)
 {
     LOGDEB1("OHRadio::metaForId: id " << id << " m_id " << m_id << endl);
-    string meta;
-    if (id >= 0 && id  < o_radios.size()) {
-        if (false && id == m_id) {
-            LOGDEB1("OHRadio::metaForId: using Metadata\n");
-            meta = m_state["Metadata"];
-        } else {
-            LOGDEB1("OHRadio::metaForId: using list data\n");
-            meta = radioDidlMake(o_radios[id].title, o_radios[id].uri, 
-                                 o_radios[id].artUri);
-        }
+    if (id  >= o_radios.size()) {
+        return string();
     }
-    return meta;
+    UpSong usong;
+    usong.title = o_radios[id].title;
+    // Kazoo absolutely does not want uri to be empty, else it
+    // does not display anything in the radio list (not even the
+    // entries with uris). So fill up with bogus value. This is
+    // not used anyway because setId/setPlaying use the value from
+    // the radio array or from the metascript
+    usong.rsrc.uri = o_radios[id].uri.empty() ?
+        "http://www.bogus.com/bogus.mp3"; : o_radios[id].uri;
+    usong.artUri = o_radios[id].artUri;
+    return didlmake(usong);
 }
 
 // Report the metadata for a given channel id.
@@ -679,7 +663,6 @@
 int OHRadio::readList(const SoapIncoming& sc, SoapOutgoing& data)
 {
     string sids;
-    UpSong song;
 
     bool ok = sc.get("IdList", &sids);
     LOGDEB("OHRadio::readList: [" << sids << "]" << endl);
@@ -688,15 +671,15 @@
     string out("<ChannelList>");
     if (ok) {
         stringToTokens(sids, ids);
-        for (auto it = ids.begin(); it != ids.end(); it++) {
-            int id = atoi(it->c_str());
+        for (auto strid : ids) {
+            int id = atoi(strid.c_str());
             if (id <= 0 || id >= int(o_radios.size())) {
                 LOGDEB("OHRadio::readlist: bad id " << id << endl);
                 continue;
             }
             string meta = metaForId(id);
             out += "<Entry><Id>";
-            out += *it;
+            out += strid;
             out += "</Id><Metadata>";
             out += SoapHelp::xmlQuote(meta);
             out += "</Metadata></Entry>";
@@ -729,7 +712,6 @@
     bool ok = sc.get("Value", &seconds);
     if (ok) {
         ok = m_dev->getmpdcli()->seek(seconds);
-        maybeWakeUp(ok);
     }
     return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
 }
@@ -749,7 +731,6 @@
         } else {
             ok = false;
         }
-        maybeWakeUp(ok);
     }
     return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/upmpdcli-1.5.2/src/ohradio.hxx 
new/upmpdcli-1.5.5/src/ohradio.hxx
--- old/upmpdcli-1.5.2/src/ohradio.hxx  2020-11-12 16:50:51.000000000 +0100
+++ new/upmpdcli-1.5.5/src/ohradio.hxx  2020-12-01 10:09:11.000000000 +0100
@@ -72,7 +72,6 @@
     bool readRadios();
     int setPlaying();
     bool makeIdArray(std::string&);
-    void maybeWakeUp(bool ok);
     void maybeExecMetaScript(RadioMeta& radio, MpdStatus &);
 
     bool m_active{false};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/upmpdcli-1.5.2/src/ohservice.hxx 
new/upmpdcli-1.5.5/src/ohservice.hxx
--- old/upmpdcli-1.5.2/src/ohservice.hxx        2020-11-24 14:59:24.000000000 
+0100
+++ new/upmpdcli-1.5.5/src/ohservice.hxx        2020-12-02 11:57:24.000000000 
+0100
@@ -52,8 +52,8 @@
 
     virtual bool getEventData(bool all, std::vector<std::string>& names, 
                               std::vector<std::string>& values) {
+        std::unique_lock<std::mutex> lock(m_statemutex);
         //LOGDEB("OHService::getEventData" << std::endl);
-        std::unique_lock<std::mutex> loc;
             
         std::unordered_map<std::string, std::string> state, changed;
         makestate(state);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/upmpdcli-1.5.2/src/upmpdcli.conf-dist 
new/upmpdcli-1.5.5/src/upmpdcli.conf-dist
--- old/upmpdcli-1.5.2/src/upmpdcli.conf-dist   2020-11-15 12:25:32.000000000 
+0100
+++ new/upmpdcli-1.5.5/src/upmpdcli.conf-dist   2020-12-01 11:01:20.000000000 
+0100
@@ -39,7 +39,7 @@
 #upnpav = 1
 # Enable OpenHome services (0/1).
 #openhome = 1
-# For upmpdcli version 1.3: enable Lumin compatibility mode (lose 
ohcredentials) (0/1).
+# Disable the OpenHome Credentials service.
 #lumincompat = 0
 # Save the streaming services login parameters to disk.
 #saveohcredentials = 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/upmpdcli-1.5.2/src/upmpdcli.conf-xml 
new/upmpdcli-1.5.5/src/upmpdcli.conf-xml
--- old/upmpdcli-1.5.2/src/upmpdcli.conf-xml    2020-11-15 12:25:11.000000000 
+0100
+++ new/upmpdcli-1.5.5/src/upmpdcli.conf-xml    2020-12-01 10:43:58.000000000 
+0100
@@ -80,13 +80,15 @@
 # off.</descr></var>
 #openhome = 1
 
-# <var name="lumincompat" type="bool" values="1"><brief>For upmpdcli
-# version 1.3: enable Lumin compatibility mode (lose ohcredentials)
-# (0/1).</brief><descr>For some unknown reason, Lumin 1.10 can't discover
-# upmpdcli when the OpenHome Credentials service is enabled. Setting this
-# allows upmpdcli to work with Lumin, at the cost of losing the use of the
-# Credentials service (normally used for logging in to Qobuz or Tidal inside
-# Kazoo).</descr></var>
+# <var name="lumincompat" type="bool" values="1">
+# <brief>Disable the OpenHome Credentials service.</brief>
+#
+# <descr>At some point, this was necessary to enable Lumin to see upmpdcli
+# instances: for some unknown reason, Lumin 1.10 did not discover
+# upmpdcli with Credentials enabled. Credentials does
+# not work at this point anyway (12/2020), but it is enabled anyway,
+# because some Kazoo versions crash if it is not enabled.</descr>
+# </var>
 #lumincompat = 0
 
 # <var name="saveohcredentials" type="bool"><brief>Save the streaming
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/upmpdcli-1.5.2/src/upmpdutils.cxx 
new/upmpdcli-1.5.5/src/upmpdutils.cxx
--- old/upmpdcli-1.5.2/src/upmpdutils.cxx       2020-11-12 16:50:51.000000000 
+0100
+++ new/upmpdcli-1.5.5/src/upmpdutils.cxx       2020-12-07 16:02:48.000000000 
+0100
@@ -169,7 +169,7 @@
     ss << ">" << SoapHelp::xmlQuote(res.uri) << "</res>";
 }
 
-string UpSong::didl() const
+string UpSong::didl(bool noresource) const
 {
     ostringstream ss;
     string typetag;
@@ -204,9 +204,11 @@
         UPNPXMLD(upnpClass, upnp:class, "object.item.audioItem.musicTrack");
         UPNPXML(album, upnp:album);
         UPNPXML(tracknum, upnp:originalTrackNumber);
-        didlPrintResource(ss, rsrc);
-        for (const auto& res : resources) {
-            didlPrintResource(ss, res);
+        if (!noresource) {
+            didlPrintResource(ss, rsrc);
+            for (const auto& res : resources) {
+                didlPrintResource(ss, res);
+            }
         }
     }
     UPNPXML(genre, upnp:genre);
@@ -241,9 +243,9 @@
     return headDIDL() + data + tailDIDL();
 }
 
-string didlmake(const UpSong& song)
+string didlmake(const UpSong& song, bool noresource)
 {
-    return wrapDIDL(song.didl());
+    return wrapDIDL(song.didl(noresource));
 }
 
 bool dirObjToUpSong(const UPnPDirObject& dobj, UpSong *ups)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/upmpdcli-1.5.2/src/upmpdutils.hxx 
new/upmpdcli-1.5.5/src/upmpdutils.hxx
--- old/upmpdcli-1.5.2/src/upmpdutils.hxx       2020-11-18 10:18:39.000000000 
+0100
+++ new/upmpdcli-1.5.5/src/upmpdutils.hxx       2020-12-07 15:58:54.000000000 
+0100
@@ -76,7 +76,7 @@
                            "] Tno [" + tracknum + "] Uri [" + rsrc.uri + "]");
     }
     // Format to DIDL fragment 
-    std::string didl() const;
+    std::string didl(bool nobitrate = false) const;
 
     static UpSong container(const std::string& id, const std::string& pid,
                             const std::string& title, bool sable = true,
@@ -115,7 +115,7 @@
     const std::string& k);
 
 // Format a didl fragment from MPD status data. Used by the renderer
-extern std::string didlmake(const UpSong& song);
+extern std::string didlmake(const UpSong& song, bool noresource = false);
 
 // Wrap DIDL entries in header / trailer
 extern const std::string& headDIDL();
_______________________________________________
openSUSE Commits mailing list -- [email protected]
To unsubscribe, email [email protected]
List Netiquette: https://en.opensuse.org/openSUSE:Mailing_list_netiquette
List Archives: 
https://lists.opensuse.org/archives/list/[email protected]

Reply via email to