Switch to unified view

a/src/cdplugins/plgwithslave.cxx b/src/cdplugins/plgwithslave.cxx
...
...
245
// RTMP, apparently because of the use of a different API key. Look up
245
// RTMP, apparently because of the use of a different API key. Look up
246
// the git history if you need this again.
246
// the git history if you need this again.
247
// The Python code calls the service to translate the trackid to a temp
247
// The Python code calls the service to translate the trackid to a temp
248
// URL. We cache the result for a few seconds to avoid multiple calls
248
// URL. We cache the result for a few seconds to avoid multiple calls
249
// to tidal.
249
// to tidal.
250
string PlgWithSlave::get_media_url(const std::string& path)
250
string PlgWithSlave::get_media_url(const string& path)
251
{
251
{
252
    LOGDEB("PlgWithSlave::get_media_url: " << path << endl);
252
    LOGDEB("PlgWithSlave::get_media_url: " << path << endl);
253
    if (!m->maybeStartCmd()) {
253
    if (!m->maybeStartCmd()) {
254
    return string();
254
    return string();
255
    }
255
    }
...
...
276
    LOGDEB("PlgWithSlave: got media url [" << m->laststream.media_url << "]\n");
276
    LOGDEB("PlgWithSlave: got media url [" << m->laststream.media_url << "]\n");
277
    return m->laststream.media_url;
277
    return m->laststream.media_url;
278
}
278
}
279
279
280
280
281
PlgWithSlave::PlgWithSlave(const std::string& name, CDPluginServices *services)
281
PlgWithSlave::PlgWithSlave(const string& name, CDPluginServices *services)
282
    : CDPlugin(name, services)
282
    : CDPlugin(name, services)
283
{
283
{
284
    m = new Internal(this, services->getexecpath(this),
284
    m = new Internal(this, services->getexecpath(this),
285
                     services->getupnpaddr(this),
285
                     services->getupnpaddr(this),
286
                     services->getupnpport(this),
286
                     services->getupnpport(this),
...
...
291
{
291
{
292
    delete m;
292
    delete m;
293
}
293
}
294
294
295
static int resultToEntries(const string& encoded, int stidx, int cnt,
295
static int resultToEntries(const string& encoded, int stidx, int cnt,
296
               std::vector<UpSong>& entries)
296
               vector<UpSong>& entries)
297
{
297
{
298
    entries.clear();
298
    auto decoded = json::parse(encoded);
299
    auto decoded = json::parse(encoded);
299
    LOGDEB("PlgWithSlave::results: got " << decoded.size() << " entries\n");
300
    LOGDEB0("PlgWithSlave::results: got " << decoded.size() << " entries\n");
300
    LOGDEB1("PlgWithSlave::results: undecoded json: " << decoded.dump() << endl);
301
    LOGDEB1("PlgWithSlave::results: undecoded: " << decoded.dump() << endl);
301
302
302
    for (unsigned int i = stidx; i < decoded.size(); i++) {
303
    for (unsigned int i = stidx; i < decoded.size(); i++) {
303
    if (--cnt < 0) {
304
    if (--cnt < 0) {
304
        break;
305
        break;
305
    }
306
    }
...
...
329
        JSONTOUPS(genre, upnp:genre);
330
        JSONTOUPS(genre, upnp:genre);
330
        JSONTOUPS(tracknum, upnp:originalTrackNumber);
331
        JSONTOUPS(tracknum, upnp:originalTrackNumber);
331
        JSONTOUPS(artUri, upnp:albumArtURI);
332
        JSONTOUPS(artUri, upnp:albumArtURI);
332
        JSONTOUPS(duration_secs, duration);
333
        JSONTOUPS(duration_secs, duration);
333
    } else {
334
    } else {
334
        LOGERR("PlgWithSlave::browse: bad type in entry: " << it1.value() << endl);
335
        LOGERR("PlgWithSlave::browse: bad type in entry: " <<
336
                   it1.value() << endl);
335
        continue;
337
        continue;
336
    }
338
    }
337
    JSONTOUPS(id, id);
339
    JSONTOUPS(id, id);
338
    JSONTOUPS(parentid, pid);
340
    JSONTOUPS(parentid, pid);
339
    JSONTOUPS(title, tt);
341
    JSONTOUPS(title, tt);
...
...
342
    // We return the total match size, the count of actually returned
344
    // We return the total match size, the count of actually returned
343
    // entries can be obtained from the vector
345
    // entries can be obtained from the vector
344
    return decoded.size();
346
    return decoded.size();
345
}
347
}
346
348
349
// Better return a bogus informative entry than an outright error:
350
static int errorEntries(const string& pid, vector<UpSong>& entries)
351
{
352
    entries.clear();
353
    entries.push_back(
354
        UpSong::item(pid + "$bogus", pid,
355
                     "Service login or communication failure"));
356
    return 1;
357
}
358
347
int PlgWithSlave::browse(const std::string& objid, int stidx, int cnt,
359
int PlgWithSlave::browse(const string& objid, int stidx, int cnt,
348
          std::vector<UpSong>& entries,
360
          vector<UpSong>& entries,
349
          const std::vector<std::string>& sortcrits,
361
          const vector<string>& sortcrits,
350
          BrowseFlag flg)
362
          BrowseFlag flg)
351
{
363
{
352
    LOGDEB("PlgWithSlave::browse\n");
364
    LOGDEB("PlgWithSlave::browse\n");
353
    if (!m->maybeStartCmd()) {
365
    if (!m->maybeStartCmd()) {
354
  return -1;
366
  return errorEntries(objid, entries);
355
    }
367
    }
356
    string sbflg;
368
    string sbflg;
357
    switch (flg) {
369
    switch (flg) {
358
    case CDPlugin::BFMeta:
370
    case CDPlugin::BFMeta:
359
        sbflg = "meta";
371
        sbflg = "meta";
...
...
365
    }
377
    }
366
378
367
    unordered_map<string, string> res;
379
    unordered_map<string, string> res;
368
    if (!m->cmd.callproc("browse", {{"objid", objid}, {"flag", sbflg}}, res)) {
380
    if (!m->cmd.callproc("browse", {{"objid", objid}, {"flag", sbflg}}, res)) {
369
    LOGERR("PlgWithSlave::browse: slave failure\n");
381
    LOGERR("PlgWithSlave::browse: slave failure\n");
370
  return -1;
382
  return errorEntries(objid, entries);
371
    }
383
    }
372
384
373
    auto it = res.find("entries");
385
    auto it = res.find("entries");
374
    if (it == res.end()) {
386
    if (it == res.end()) {
375
    LOGERR("PlgWithSlave::browse: no entries returned\n");
387
    LOGERR("PlgWithSlave::browse: no entries returned\n");
376
  return -1;
388
        return errorEntries(objid, entries);
377
    }
389
    }
378
    return resultToEntries(it->second, stidx, cnt, entries);
390
    return resultToEntries(it->second, stidx, cnt, entries);
379
}
391
}
380
392
381
393
...
...
384
          vector<UpSong>& entries,
396
          vector<UpSong>& entries,
385
          const vector<string>& sortcrits)
397
          const vector<string>& sortcrits)
386
{
398
{
387
    LOGDEB("PlgWithSlave::search\n");
399
    LOGDEB("PlgWithSlave::search\n");
388
    if (!m->maybeStartCmd()) {
400
    if (!m->maybeStartCmd()) {
389
  return -1;
401
  return errorEntries(ctid, entries);
390
    }
402
    }
391
403
392
    // We only accept field xx value as search criteria
404
    // We only accept field xx value as search criteria
393
    vector<string> vs;
405
    vector<string> vs;
394
    stringToStrings(searchstr, vs);
406
    stringToStrings(searchstr, vs);
395
    if (vs.size() != 3) {
407
    if (vs.size() != 3) {
396
    LOGERR("PlgWithSlave::search: bad search string: [" << searchstr <<
408
    LOGERR("PlgWithSlave::search: bad search string: [" << searchstr <<
397
               "]\n");
409
               "]\n");
398
  return -1;
410
  return errorEntries(ctid, entries);
399
    }
411
    }
400
    const string& upnpproperty = vs[0];
412
    const string& upnpproperty = vs[0];
401
    string slavefield;
413
    string slavefield;
402
    if (!upnpproperty.compare("upnp:artist") ||
414
    if (!upnpproperty.compare("upnp:artist") ||
403
    !upnpproperty.compare("dc:author")) {
415
    !upnpproperty.compare("dc:author")) {
...
...
405
    } else if (!upnpproperty.compare("upnp:album")) {
417
    } else if (!upnpproperty.compare("upnp:album")) {
406
    slavefield = "album";
418
    slavefield = "album";
407
    } else if (!upnpproperty.compare("dc:title")) {
419
    } else if (!upnpproperty.compare("dc:title")) {
408
    slavefield = "track";
420
    slavefield = "track";
409
    } else {
421
    } else {
410
    LOGERR("PlgWithSlave::search: bad property: [" << upnpproperty << "]\n");
422
    LOGERR("PlgWithSlave::search: bad property: [" << upnpproperty << endl);
411
  return -1;
423
  return errorEntries(ctid, entries);
412
    }
424
    }
413
    
425
    
414
    unordered_map<string, string> res;
426
    unordered_map<string, string> res;
415
    if (!m->cmd.callproc("search", {
427
    if (!m->cmd.callproc("search", {
416
        {"objid", ctid},
428
        {"ctid", ctid},
417
        {"field", slavefield},
429
        {"field", slavefield},
418
        {"value", vs[2]} },  res)) {
430
        {"value", vs[2]} },  res)) {
419
    LOGERR("PlgWithSlave::search: slave failure\n");
431
    LOGERR("PlgWithSlave::search: slave failure\n");
420
  return -1;
432
  return errorEntries(ctid, entries);
421
    }
433
    }
422
434
423
    auto it = res.find("entries");
435
    auto it = res.find("entries");
424
    if (it == res.end()) {
436
    if (it == res.end()) {
425
    LOGERR("PlgWithSlave::search: no entries returned\n");
437
    LOGERR("PlgWithSlave::search: no entries returned\n");
426
  return -1;
438
  return errorEntries(ctid, entries);
427
    }
439
    }
428
    return resultToEntries(it->second, stidx, cnt, entries);
440
    return resultToEntries(it->second, stidx, cnt, entries);
429
}
441
}