|
a/src/mediaserver/cdplugins/plgwithslave.cxx |
|
b/src/mediaserver/cdplugins/plgwithslave.cxx |
|
... |
|
... |
90 |
// microhttpd daemon handle. There is only one of these, and one port, we find
|
90 |
// microhttpd daemon handle. There is only one of these, and one port, we find
|
91 |
// the right plugin by looking at the url path.
|
91 |
// the right plugin by looking at the url path.
|
92 |
static struct MHD_Daemon *mhd;
|
92 |
static struct MHD_Daemon *mhd;
|
93 |
|
93 |
|
94 |
// Microhttpd connection handler. We re-build the complete url + query
|
94 |
// Microhttpd connection handler. We re-build the complete url + query
|
95 |
// string (&trackid=value), use this to retrieve a Tidal URL, and
|
95 |
// string (&trackid=value), use this to retrieve a service URL
|
96 |
// redirect to it (HTTP). A previous version handled rtmp streams, and
|
96 |
// (tidal/qobuz...), and redirect to it (HTTP). A previous version
|
97 |
// had to read them. Look up the history if you need the code again
|
97 |
// handled rtmp streams, and had to read them. Look up the history if
|
98 |
// (the apparition of RTMP streams was apparently linked to the use of
|
98 |
// you need the code again (the apparition of RTMP streams was
|
99 |
// a different API key).
|
99 |
// apparently linked to the use of a different API key).
|
100 |
static int answer_to_connection(void *cls, struct MHD_Connection *connection,
|
100 |
static int answer_to_connection(void *cls, struct MHD_Connection *connection,
|
101 |
const char *url,
|
101 |
const char *url,
|
102 |
const char *method, const char *version,
|
102 |
const char *method, const char *version,
|
103 |
const char *upload_data,
|
103 |
const char *upload_data,
|
104 |
size_t *upload_data_size, void **con_cls)
|
104 |
size_t *upload_data_size, void **con_cls)
|
|
... |
|
... |
481 |
int PlgWithSlave::search(const string& ctid, int stidx, int cnt,
|
481 |
int PlgWithSlave::search(const string& ctid, int stidx, int cnt,
|
482 |
const string& searchstr,
|
482 |
const string& searchstr,
|
483 |
vector<UpSong>& entries,
|
483 |
vector<UpSong>& entries,
|
484 |
const vector<string>& sortcrits)
|
484 |
const vector<string>& sortcrits)
|
485 |
{
|
485 |
{
|
486 |
LOGDEB1("PlgWithSlave::search\n");
|
486 |
LOGDEB("PlgWithSlave::search: [" << searchstr << "]\n");
|
487 |
entries.clear();
|
487 |
entries.clear();
|
488 |
if (!m->maybeStartCmd()) {
|
488 |
if (!m->maybeStartCmd()) {
|
489 |
return errorEntries(ctid, entries);
|
489 |
return errorEntries(ctid, entries);
|
490 |
}
|
490 |
}
|
491 |
|
491 |
|
|
... |
|
... |
511 |
return errorEntries(ctid, entries);
|
511 |
return errorEntries(ctid, entries);
|
512 |
}
|
512 |
}
|
513 |
string slavefield;
|
513 |
string slavefield;
|
514 |
string value;
|
514 |
string value;
|
515 |
string classfilter;
|
515 |
string classfilter;
|
|
|
516 |
string objkind;
|
516 |
for (unsigned int i = 0; i < vs.size()-2; i += 4) {
|
517 |
for (unsigned int i = 0; i < vs.size()-2; i += 4) {
|
517 |
const string& upnpproperty = vs[i];
|
518 |
const string& upnpproperty = vs[i];
|
518 |
LOGDEB("PlgWithSlave::search:clause: " << vs[i] << " " << vs[i+1] <<
|
519 |
LOGDEB("PlgWithSlave::search:clause: " << vs[i] << " " << vs[i+1] <<
|
519 |
" " << vs[i+2] << endl);
|
520 |
" " << vs[i+2] << endl);
|
|
|
521 |
if (!upnpproperty.compare("upnp:class")) {
|
|
|
522 |
// This defines -what- we are looking for (track/album/artist)
|
|
|
523 |
const string& what(vs[i+2]);
|
|
|
524 |
if (beginswith(what, "object.item")) {
|
|
|
525 |
objkind = "track";
|
|
|
526 |
} else if (beginswith(what, "object.container.person")) {
|
|
|
527 |
objkind = "artist";
|
|
|
528 |
} else if (beginswith(what, "object.container.musicAlbum") ||
|
|
|
529 |
beginswith(what, "object.container.album")) {
|
|
|
530 |
objkind = "album";
|
|
|
531 |
} else if (beginswith(what, "object.container.playlistContainer")
|
|
|
532 |
|| beginswith(what, "object.container.playlist")) {
|
|
|
533 |
objkind = "playlist";
|
|
|
534 |
}
|
520 |
if (!upnpproperty.compare("upnp:artist") ||
|
535 |
} else if (!upnpproperty.compare("upnp:artist") ||
|
521 |
!upnpproperty.compare("dc:author")) {
|
536 |
!upnpproperty.compare("dc:author")) {
|
522 |
slavefield = "artist";
|
537 |
slavefield = "artist";
|
523 |
value = vs[i+2];
|
538 |
value = vs[i+2];
|
524 |
break;
|
539 |
break;
|
525 |
} else if (!upnpproperty.compare("upnp:album")) {
|
540 |
} else if (!upnpproperty.compare("upnp:album")) {
|
|
... |
|
... |
539 |
return errorEntries(ctid, entries);
|
554 |
return errorEntries(ctid, entries);
|
540 |
}
|
555 |
}
|
541 |
|
556 |
|
542 |
// In cache ?
|
557 |
// In cache ?
|
543 |
SearchCacheEntry *cep;
|
558 |
SearchCacheEntry *cep;
|
544 |
string cachekey(m_name + ":" + slavefield + ":" + value);
|
559 |
string cachekey(m_name + ":" + objkind + ":" + slavefield + ":" + value);
|
545 |
if ((cep = o_scache.get(cachekey)) != nullptr) {
|
560 |
if ((cep = o_scache.get(cachekey)) != nullptr) {
|
546 |
int total = resultFromCacheEntry(classfilter, stidx,cnt, *cep, entries);
|
561 |
int total = resultFromCacheEntry(classfilter, stidx,cnt, *cep, entries);
|
547 |
delete cep;
|
562 |
delete cep;
|
548 |
return total;
|
563 |
return total;
|
549 |
}
|
564 |
}
|
550 |
|
565 |
|
551 |
// Run query
|
566 |
// Run query
|
552 |
unordered_map<string, string> res;
|
567 |
unordered_map<string, string> res;
|
553 |
if (!m->cmd.callproc("search", {
|
568 |
if (!m->cmd.callproc("search", {
|
554 |
{"objid", ctid},
|
569 |
{"objid", ctid},
|
|
|
570 |
{"objkind", objkind},
|
555 |
{"field", slavefield},
|
571 |
{"field", slavefield},
|
556 |
{"value", value} }, res)) {
|
572 |
{"value", value} }, res)) {
|
557 |
LOGERR("PlgWithSlave::search: slave failure\n");
|
573 |
LOGERR("PlgWithSlave::search: slave failure\n");
|
558 |
return errorEntries(ctid, entries);
|
574 |
return errorEntries(ctid, entries);
|
559 |
}
|
575 |
}
|