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]
