--- a/src/mediaserver/cdplugins/plgwithslave.cxx
+++ b/src/mediaserver/cdplugins/plgwithslave.cxx
@@ -66,7 +66,7 @@
public:
Internal(PlgWithSlave *_plg, const string& exe, const string& hst,
int prt, const string& pp)
- : plg(_plg), exepath(exe), upnphost(hst), upnpport(prt), pathprefix(pp),
+ : plg(_plg), exepath(exe), upnphost(hst), upnpport(prt), pathprefix(pp),
laststream(this) {
}
@@ -118,7 +118,7 @@
// and then dispatch the request.
PlgWithSlave::Internal *plgi = (PlgWithSlave::Internal*)cls;
PlgWithSlave *realplg =
- dynamic_cast<PlgWithSlave*>(plgi->plg->m_services->getpluginforpath(url));
+ dynamic_cast<PlgWithSlave*>(plgi->plg->m_services->getpluginforpath(url));
if (nullptr == realplg) {
LOGERR("answer_to_connection: no plugin for path [" << url << endl);
return MHD_NO;
@@ -245,22 +245,22 @@
{
LOGDEB0("PlgWithSlave::get_media_url: " << path << endl);
if (!m->maybeStartCmd()) {
- return string();
+ return string();
}
time_t now = time(0);
if (m->laststream.path.compare(path) ||
(now - m->laststream.opentime > 10)) {
- unordered_map<string, string> res;
- if (!m->cmd.callproc("trackuri", {{"path", path}}, res)) {
- LOGERR("PlgWithSlave::get_media_url: slave failure\n");
- return string();
- }
-
- auto it = res.find("media_url");
- if (it == res.end()) {
- LOGERR("PlgWithSlave::get_media_url: no media url in result\n");
- return string();
- }
+ unordered_map<string, string> res;
+ if (!m->cmd.callproc("trackuri", {{"path", path}}, res)) {
+ LOGERR("PlgWithSlave::get_media_url: slave failure\n");
+ return string();
+ }
+
+ auto it = res.find("media_url");
+ if (it == res.end()) {
+ LOGERR("PlgWithSlave::get_media_url: no media url in result\n");
+ return string();
+ }
m->laststream.clear();
m->laststream.path = path;
m->laststream.media_url = it->second;
@@ -287,7 +287,7 @@
}
static int resultToEntries(const string& encoded, int stidx, int cnt,
- vector<UpSong>& entries)
+ vector<UpSong>& entries)
{
Json::Value decoded;
istringstream input(encoded);
@@ -298,25 +298,31 @@
for (unsigned int i = stidx; i < decoded.size(); i++) {
#define JSONTOUPS(fld, nm) {song.fld = decoded[i].get(#nm, "").asString();}
- if (dolimit && --cnt < 0) {
- break;
- }
- UpSong song;
- // tp is container ("ct") or item ("it")
+ if (dolimit && --cnt < 0) {
+ break;
+ }
+ UpSong song;
+ JSONTOUPS(id, id);
+ JSONTOUPS(parentid, pid);
+ JSONTOUPS(title, tt);
+ JSONTOUPS(artUri, upnp:albumArtURI);
+ JSONTOUPS(artist, upnp:artist);
+ JSONTOUPS(upnpClass, upnp:class);
+ // tp is container ("ct") or item ("it")
string stp = decoded[i].get("tp", "").asString();
- if (!stp.compare("ct")) {
- song.iscontainer = true;
+ if (!stp.compare("ct")) {
+ song.iscontainer = true;
string ss = decoded[i].get("searchable", "").asString();
if (!ss.empty()) {
song.searchable = stringToBool(ss);
}
- } else if (!stp.compare("it")) {
- song.iscontainer = false;
- JSONTOUPS(uri, uri);
- JSONTOUPS(artist, dc:creator);
- JSONTOUPS(genre, upnp:genre);
+ } else if (!stp.compare("it")) {
+ song.iscontainer = false;
+ JSONTOUPS(uri, uri);
+ JSONTOUPS(artist, dc:creator);
+ JSONTOUPS(genre, upnp:genre);
JSONTOUPS(album, upnp:album);
- JSONTOUPS(tracknum, upnp:originalTrackNumber);
+ JSONTOUPS(tracknum, upnp:originalTrackNumber);
JSONTOUPS(mime, res:mime);
string srate = decoded[i].get("res:samplefreq", "").asString();
if (!srate.empty()) {
@@ -326,18 +332,13 @@
if (!sdur.empty()) {
song.duration_secs = atoi(sdur.c_str());
}
- } else {
- LOGERR("PlgWithSlave::result: bad type in entry: " << stp << endl);
- continue;
- }
- JSONTOUPS(id, id);
- JSONTOUPS(parentid, pid);
- JSONTOUPS(title, tt);
- JSONTOUPS(artUri, upnp:albumArtURI);
- JSONTOUPS(artist, upnp:artist);
- JSONTOUPS(upnpClass, upnp:class);
+ } else {
+ LOGERR("PlgWithSlave::result: bad type in entry: " << stp <<
+ "(title: " << song.title << ")\n");
+ continue;
+ }
LOGDEB1("PlgWitSlave::result: pushing: " << song.dump() << endl);
- entries.push_back(song);
+ entries.push_back(song);
}
// We return the total match size, the count of actually returned
// entries can be obtained from the vector
@@ -463,7 +464,7 @@
LOGDEB1("PlgWithSlave::browse\n");
entries.clear();
if (!m->maybeStartCmd()) {
- return errorEntries(objid, entries);
+ return errorEntries(objid, entries);
}
string sbflg;
switch (flg) {
@@ -489,13 +490,13 @@
unordered_map<string, string> res;
if (!m->cmd.callproc("browse", {{"objid", objid}, {"flag", sbflg}}, res)) {
- LOGERR("PlgWithSlave::browse: slave failure\n");
- return errorEntries(objid, entries);
+ LOGERR("PlgWithSlave::browse: slave failure\n");
+ return errorEntries(objid, entries);
}
auto it = res.find("entries");
if (it == res.end()) {
- LOGERR("PlgWithSlave::browse: no entries returned\n");
+ LOGERR("PlgWithSlave::browse: no entries returned\n");
return errorEntries(objid, entries);
}
@@ -523,9 +524,14 @@
LOGDEB("PlgWithSlave::search: [" << searchstr << "]\n");
entries.clear();
if (!m->maybeStartCmd()) {
- return errorEntries(ctid, entries);
- }
-
+ return errorEntries(ctid, entries);
+ }
+
+ // Computing a pre-cooked query. For simple-minded plugins.
+ // Note that none of the qobuz/gmusic/tidal plugins actually use
+ // the slavefield part (defining in what field the term should
+ // match).
+ //
// Ok, so the upnp query language is quite powerful, but us, not
// so much. We get rid of parenthesis and then try to find the
// first searchExp on a field we can handle, pretend the operator
@@ -543,9 +549,9 @@
// The sequence can now be either [field, op, value], or
// [field, op, value, and/or, field, op, value,...]
if ((vs.size() + 1) % 4 != 0) {
- LOGERR("PlgWithSlave::search: bad search string: [" << searchstr <<
+ LOGERR("PlgWithSlave::search: bad search string: [" << searchstr <<
"]\n");
- return errorEntries(ctid, entries);
+ return errorEntries(ctid, entries);
}
string slavefield;
string value;
@@ -571,7 +577,7 @@
}
classfilter = what;
} else if (!upnpproperty.compare("upnp:artist") ||
- !upnpproperty.compare("dc:author")) {
+ !upnpproperty.compare("dc:author")) {
slavefield = "artist";
value = vs[i+2];
break;
@@ -585,14 +591,10 @@
break;
}
}
- if (slavefield.empty()) {
- LOGERR("PlgWithSlave: unsupported search: [" << searchstr << "]\n");
- return errorEntries(ctid, entries);
- }
// In cache ?
ContentCacheEntry *cep;
- string cachekey(m_name + ":" + objkind + ":" + slavefield + ":" + value);
+ string cachekey(m_name + ":" + ctid + ":" + searchstr);
if ((cep = o_scache.get(cachekey)) != nullptr) {
int total = cep->toResult(classfilter, stidx, cnt, entries);
delete cep;
@@ -602,19 +604,19 @@
// Run query
unordered_map<string, string> res;
if (!m->cmd.callproc("search", {
- {"objid", ctid},
- {"objkind", objkind},
+ {"objid", ctid},
+ {"objkind", objkind},
{"origsearch", searchstr},
{"field", slavefield},
- {"value", value} }, res)) {
- LOGERR("PlgWithSlave::search: slave failure\n");
- return errorEntries(ctid, entries);
+ {"value", value} }, res)) {
+ LOGERR("PlgWithSlave::search: slave failure\n");
+ return errorEntries(ctid, entries);
}
auto it = res.find("entries");
if (it == res.end()) {
- LOGERR("PlgWithSlave::search: no entries returned\n");
- return errorEntries(ctid, entries);
+ LOGERR("PlgWithSlave::search: no entries returned\n");
+ return errorEntries(ctid, entries);
}
// Convert the whole set and store in cache
ContentCacheEntry e;