Switch to unified view

a/src/ohplaylist.cxx b/src/ohplaylist.cxx
...
...
242
    m_metacache = nmeta;
242
    m_metacache = nmeta;
243
243
244
    return true;
244
    return true;
245
}
245
}
246
246
247
// (private)
248
int OHPlaylist::idFromOldId(int oldid)
249
{
250
    string uri;
251
    for (const auto& entry: m_mpdsavedstate.queue) {
252
        if (entry.mpdid == oldid) {
253
            uri = entry.uri;
254
            break;
255
        }
256
    }
257
    if (uri.empty()) {
258
        LOGERR("OHPlaylist::idFromOldId: " << oldid << " not found\n");
259
        return -1;
260
    }
261
    vector<UpSong> vdata;
262
    if (!m_dev->m_mpdcli->getQueueData(vdata)) {
263
        LOGERR("OHPlaylist::idFromUri: getQueueData failed\n");
264
        return -1;
265
    }
266
    for (const auto& entry: vdata) {
267
        if (!entry.uri.compare(uri)) {
268
            return entry.mpdid;
269
        }
270
    }
271
    LOGERR("OHPlaylist::idFromOldId: uri for " << oldid << " not found\n");
272
    return -1;
273
}
274
247
bool OHPlaylist::makestate(unordered_map<string, string> &st)
275
bool OHPlaylist::makestate(unordered_map<string, string> &st)
248
{
276
{
277
    if (m_active) {
249
    st.clear();
278
        st.clear();
250
279
251
    const MpdStatus &mpds = m_dev->getMpdStatusNoUpdate();
280
        const MpdStatus &mpds = m_dev->getMpdStatusNoUpdate();
252
281
253
    st["TransportState"] =  mpdstatusToTransportState(mpds.state);
282
        st["TransportState"] =  mpdstatusToTransportState(mpds.state);
254
    st["Repeat"] = SoapHelp::i2s(mpds.rept);
283
        st["Repeat"] = SoapHelp::i2s(mpds.rept);
255
    st["Shuffle"] = SoapHelp::i2s(mpds.random);
284
        st["Shuffle"] = SoapHelp::i2s(mpds.random);
256
    st["Id"] = mpds.songid == -1 ? "0" : SoapHelp::i2s(mpds.songid);
285
        st["Id"] = mpds.songid == -1 ? "0" : SoapHelp::i2s(mpds.songid);
257
    st["TracksMax"] = SoapHelp::i2s(tracksmax);
286
        st["TracksMax"] = SoapHelp::i2s(tracksmax);
258
    st["ProtocolInfo"] = Protocolinfo::the()->gettext();
287
        st["ProtocolInfo"] = Protocolinfo::the()->gettext();
259
    makeIdArray(st["IdArray"]);
288
        makeIdArray(st["IdArray"]);
289
    } else {
290
        st = m_upnpstate;
291
    }
260
292
261
    return true;
293
    return true;
262
}
294
}
263
295
264
void OHPlaylist::refreshState()
296
void OHPlaylist::refreshState()
...
...
274
        m_dev->loopWakeup();
306
        m_dev->loopWakeup();
275
}
307
}
276
308
277
void OHPlaylist::setActive(bool onoff)
309
void OHPlaylist::setActive(bool onoff)
278
{
310
{
279
    m_active = onoff;
311
    if (onoff) {
280
    if (m_active) {
281
        m_dev->m_mpdcli->clearQueue();
312
        m_dev->m_mpdcli->clearQueue();
282
        m_dev->m_mpdcli->restoreState(m_mpdsavedstate);
313
        m_dev->m_mpdcli->restoreState(m_mpdsavedstate);
283
        m_dev->m_mpdcli->consume(false);
314
        m_dev->m_mpdcli->consume(false);
284
        m_dev->m_mpdcli->single(false);
315
        m_dev->m_mpdcli->single(false);
285
        refreshState();
316
        refreshState();
286
        maybeWakeUp(true);
317
        maybeWakeUp(true);
318
        m_active = true;
287
    } else {
319
    } else {
320
        m_mpdqvers = -1;
321
        makestate(m_upnpstate);
288
        m_dev->m_mpdcli->saveState(m_mpdsavedstate);
322
        m_dev->m_mpdcli->saveState(m_mpdsavedstate);
289
        iStop();
323
        iStop();
324
        m_active = false;
290
    }
325
    }
291
}
326
}
292
327
293
int OHPlaylist::play(const SoapIncoming& sc, SoapOutgoing& data)
328
int OHPlaylist::play(const SoapIncoming& sc, SoapOutgoing& data)
294
{
329
{
...
...
323
    return iStop();
358
    return iStop();
324
}
359
}
325
360
326
int OHPlaylist::next(const SoapIncoming& sc, SoapOutgoing& data)
361
int OHPlaylist::next(const SoapIncoming& sc, SoapOutgoing& data)
327
{
362
{
363
    if (!m_active) {
364
        LOGERR("OHPlaylist::next: not active\n");
365
        return UPNP_E_INTERNAL_ERROR;
366
    }
328
    LOGDEB("OHPlaylist::next" << endl);
367
    LOGDEB("OHPlaylist::next" << endl);
329
    bool ok = m_dev->m_mpdcli->next();
368
    bool ok = m_dev->m_mpdcli->next();
330
    maybeWakeUp(ok);
369
    maybeWakeUp(ok);
331
    return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
370
    return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
332
}
371
}
333
372
334
int OHPlaylist::previous(const SoapIncoming& sc, SoapOutgoing& data)
373
int OHPlaylist::previous(const SoapIncoming& sc, SoapOutgoing& data)
335
{
374
{
375
    if (!m_active) {
376
        LOGERR("OHPlaylist::previous: not active\n");
377
        return UPNP_E_INTERNAL_ERROR;
378
    }
336
    LOGDEB("OHPlaylist::previous" << endl);
379
    LOGDEB("OHPlaylist::previous" << endl);
337
    bool ok = m_dev->m_mpdcli->previous();
380
    bool ok = m_dev->m_mpdcli->previous();
338
    maybeWakeUp(ok);
381
    maybeWakeUp(ok);
339
    return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
382
    return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
340
}
383
}
341
384
342
int OHPlaylist::setRepeat(const SoapIncoming& sc, SoapOutgoing& data)
385
int OHPlaylist::setRepeat(const SoapIncoming& sc, SoapOutgoing& data)
343
{
386
{
387
    if (!m_active) {
388
        LOGERR("OHPlaylist::setRepeat: not active\n");
389
        return UPNP_E_INTERNAL_ERROR;
390
    }
344
    LOGDEB("OHPlaylist::setRepeat" << endl);
391
    LOGDEB("OHPlaylist::setRepeat" << endl);
345
    bool onoff;
392
    bool onoff;
346
    bool ok = sc.get("Value", &onoff);
393
    bool ok = sc.get("Value", &onoff);
347
    if (ok) {
394
    if (ok) {
348
        ok = m_dev->m_mpdcli->repeat(onoff);
395
        ok = m_dev->m_mpdcli->repeat(onoff);
...
...
351
    return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
398
    return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
352
}
399
}
353
400
354
int OHPlaylist::repeat(const SoapIncoming& sc, SoapOutgoing& data)
401
int OHPlaylist::repeat(const SoapIncoming& sc, SoapOutgoing& data)
355
{
402
{
403
    if (!m_active) {
404
        LOGERR("OHPlaylist::repeat: not active\n");
405
        return UPNP_E_INTERNAL_ERROR;
406
    }
356
    LOGDEB("OHPlaylist::repeat" << endl);
407
    LOGDEB("OHPlaylist::repeat" << endl);
357
    const MpdStatus &mpds =  m_dev->getMpdStatusNoUpdate();
408
    const MpdStatus &mpds =  m_dev->getMpdStatusNoUpdate();
358
    data.addarg("Value", mpds.rept? "1" : "0");
409
    data.addarg("Value", mpds.rept? "1" : "0");
359
    return UPNP_E_SUCCESS;
410
    return UPNP_E_SUCCESS;
360
}
411
}
361
412
362
int OHPlaylist::setShuffle(const SoapIncoming& sc, SoapOutgoing& data)
413
int OHPlaylist::setShuffle(const SoapIncoming& sc, SoapOutgoing& data)
363
{
414
{
415
    if (!m_active) {
416
        LOGERR("OHPlaylist::setShuffle: not active\n");
417
        return UPNP_E_INTERNAL_ERROR;
418
    }
364
    LOGDEB("OHPlaylist::setShuffle" << endl);
419
    LOGDEB("OHPlaylist::setShuffle" << endl);
365
    bool onoff;
420
    bool onoff;
366
    bool ok = sc.get("Value", &onoff);
421
    bool ok = sc.get("Value", &onoff);
367
    if (ok) {
422
    if (ok) {
368
        // Note that mpd shuffle shuffles the playlist, which is different
423
        // Note that mpd shuffle shuffles the playlist, which is different
...
...
373
    return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
428
    return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
374
}
429
}
375
430
376
int OHPlaylist::shuffle(const SoapIncoming& sc, SoapOutgoing& data)
431
int OHPlaylist::shuffle(const SoapIncoming& sc, SoapOutgoing& data)
377
{
432
{
433
    if (!m_active) {
434
        LOGERR("OHPlaylist::shuffle: not active\n");
435
        return UPNP_E_INTERNAL_ERROR;
436
    }
378
    LOGDEB("OHPlaylist::shuffle" << endl);
437
    LOGDEB("OHPlaylist::shuffle" << endl);
379
    const MpdStatus &mpds =  m_dev->getMpdStatusNoUpdate();
438
    const MpdStatus &mpds =  m_dev->getMpdStatusNoUpdate();
380
    data.addarg("Value", mpds.random ? "1" : "0");
439
    data.addarg("Value", mpds.random ? "1" : "0");
381
    return UPNP_E_SUCCESS;
440
    return UPNP_E_SUCCESS;
382
}
441
}
383
442
384
int OHPlaylist::seekSecondAbsolute(const SoapIncoming& sc, SoapOutgoing& data)
443
int OHPlaylist::seekSecondAbsolute(const SoapIncoming& sc, SoapOutgoing& data)
385
{
444
{
445
    if (!m_active) {
446
        LOGERR("OHPlaylist::seekSecond: not active\n");
447
        return UPNP_E_INTERNAL_ERROR;
448
    }
386
    LOGDEB("OHPlaylist::seekSecondAbsolute" << endl);
449
    LOGDEB("OHPlaylist::seekSecondAbsolute" << endl);
387
    int seconds;
450
    int seconds;
388
    bool ok = sc.get("Value", &seconds);
451
    bool ok = sc.get("Value", &seconds);
389
    if (ok) {
452
    if (ok) {
390
        ok = m_dev->m_mpdcli->seek(seconds);
453
        ok = m_dev->m_mpdcli->seek(seconds);
...
...
393
    return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
456
    return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
394
}
457
}
395
458
396
int OHPlaylist::seekSecondRelative(const SoapIncoming& sc, SoapOutgoing& data)
459
int OHPlaylist::seekSecondRelative(const SoapIncoming& sc, SoapOutgoing& data)
397
{
460
{
461
    if (!m_active) {
462
        LOGERR("OHPlaylist::seekSecond: not active\n");
463
        return UPNP_E_INTERNAL_ERROR;
464
    }
398
    LOGDEB("OHPlaylist::seekSecondRelative" << endl);
465
    LOGDEB("OHPlaylist::seekSecondRelative" << endl);
399
    int seconds;
466
    int seconds;
400
    bool ok = sc.get("Value", &seconds);
467
    bool ok = sc.get("Value", &seconds);
401
    if (ok) {
468
    if (ok) {
402
        const MpdStatus &mpds =  m_dev->getMpdStatusNoUpdate();
469
        const MpdStatus &mpds =  m_dev->getMpdStatusNoUpdate();
...
...
433
}
500
}
434
501
435
// Skip to track specified by Id
502
// Skip to track specified by Id
436
int OHPlaylist::seekId(const SoapIncoming& sc, SoapOutgoing& data)
503
int OHPlaylist::seekId(const SoapIncoming& sc, SoapOutgoing& data)
437
{
504
{
505
    int id;
506
    if (!sc.get("Value", &id)) {
507
        LOGERR("OHPlaylist::seekId: no Id\n");
508
        return UPNP_E_INVALID_PARAM;
509
    }
438
    LOGDEB("OHPlaylist::seekId" << endl);
510
    LOGDEB("OHPlaylist::seekId" << endl);
439
    if (!m_active) {
511
    if (!m_active) {
440
        // If I'm not active, the ids in the playlist are those of
512
        // If I'm not active, the ids in the playlist are those of
441
        // another service (e.g. radio). If I activate myself and
513
        // another service (e.g. radio). After activating myself and
442
        // restore the playlist, the mpd ids are going to be different
514
        // restoring the playlist, the input id needs to be mapped.
443
        // from what the caller may have in store. This just can't
515
        m_dev->m_ohpr->iSetSourceIndexByName("Playlist");
444
        // work as long as we use mpd ids directly.
516
        id = idFromOldId(id);
445
        LOGERR("OHPlaylist::seekId: not active" << endl);
517
        if (id < 0) {
446
        return UPNP_E_INTERNAL_ERROR;
518
            return UPNP_E_INTERNAL_ERROR;
447
    }
519
        }
448
    int id;
520
    }
449
    bool ok = sc.get("Value", &id);
450
    if (ok) {
451
        ok = m_dev->m_mpdcli->playId(id);
521
    bool ok = m_dev->m_mpdcli->playId(id);
452
        maybeWakeUp(ok);
522
    maybeWakeUp(ok);
453
    }
454
    return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
523
    return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
455
}
524
}
456
525
457
// Skip to track with specified index 
526
// Skip to track with specified index 
458
int OHPlaylist::seekIndex(const SoapIncoming& sc, SoapOutgoing& data)
527
int OHPlaylist::seekIndex(const SoapIncoming& sc, SoapOutgoing& data)
...
...
474
}
543
}
475
544
476
// Return current Id
545
// Return current Id
477
int OHPlaylist::id(const SoapIncoming& sc, SoapOutgoing& data)
546
int OHPlaylist::id(const SoapIncoming& sc, SoapOutgoing& data)
478
{
547
{
479
    LOGDEB("OHPlaylist::id" << endl);
480
    if (!m_active) {
548
    if (!m_active) {
481
        LOGERR("OHPlaylist::id: not active" << endl);
549
        LOGERR("OHPlaylist::id: not active" << endl);
482
        return UPNP_E_INTERNAL_ERROR;
550
        return UPNP_E_INTERNAL_ERROR;
483
    }
551
    }
552
    LOGDEB("OHPlaylist::id" << endl);
484
553
485
    const MpdStatus &mpds = m_dev->getMpdStatusNoUpdate();
554
    const MpdStatus &mpds = m_dev->getMpdStatusNoUpdate();
486
    data.addarg("Value", mpds.songid == -1 ? "0" : SoapHelp::i2s(mpds.songid));
555
    data.addarg("Value", mpds.songid == -1 ? "0" : SoapHelp::i2s(mpds.songid));
487
    return UPNP_E_SUCCESS;
556
    return UPNP_E_SUCCESS;
488
}
557
}
...
...
499
568
500
// Report the uri and metadata for a given track id. 
569
// Report the uri and metadata for a given track id. 
501
// Returns a 800 fault code if the given id is not in the playlist. 
570
// Returns a 800 fault code if the given id is not in the playlist. 
502
int OHPlaylist::ohread(const SoapIncoming& sc, SoapOutgoing& data)
571
int OHPlaylist::ohread(const SoapIncoming& sc, SoapOutgoing& data)
503
{
572
{
504
    if (!m_active) {
505
        // See comment in seekId()
506
        LOGERR("OHPlaylist::read: not active" << endl);
507
        return UPNP_E_INTERNAL_ERROR;
508
    }
509
    int id;
573
    int id;
510
    bool ok = sc.get("Id", &id);
574
    bool ok = sc.get("Id", &id);
575
    if (!ok) {
576
        LOGERR("OHPlaylist::ohread: no Id in params\n");
577
        return UPNP_E_INVALID_PARAM;
578
    }
511
    LOGDEB("OHPlaylist::ohread id " << id << endl);
579
    LOGDEB("OHPlaylist::ohread id " << id << endl);
512
    UpSong song;
580
    UpSong song;
513
    if (ok) {
581
    string metadata;
582
    if (m_active) {
514
        ok = m_dev->m_mpdcli->statSong(song, id, true);
583
        if (!m_dev->m_mpdcli->statSong(song, id, true)) {
584
            LOGERR("OHPlaylist::ohread: statsong failed for " << id << endl);
585
            return UPNP_E_INTERNAL_ERROR;
515
    }
586
        }
516
    if (ok) {
517
        auto cached = m_metacache.find(song.uri);
587
        auto cached = m_metacache.find(song.uri);
518
        string metadata;
519
        if (cached != m_metacache.end()) {
588
        if (cached != m_metacache.end()) {
520
            metadata = cached->second;
589
            metadata = cached->second;
521
        } else {
590
        } else {
522
            metadata = didlmake(song);
591
            metadata = didlmake(song);
523
            m_metacache[song.uri] = metadata;
592
            m_metacache[song.uri] = metadata;
524
            m_cachedirty = true;
593
            m_cachedirty = true;
525
        }
594
        }
526
        data.addarg("Uri", song.uri);
595
    } else {
596
        LOGDEB("OHPlaylist::read: not active: using saved queue\n");
597
        for (const auto& entry : m_mpdsavedstate.queue) {
598
            if (entry.mpdid == id) {
599
                song = entry;
600
                metadata = didlmake(song);
601
            }
602
        }
603
        if (metadata.empty()) {
604
            LOGDEB("OHPlaylist: id " << id << " not found\n");
605
            return UPNP_E_INTERNAL_ERROR;
606
        }
607
    }
608
    data.addarg("Uri", SoapHelp::xmlQuote(song.uri));
527
        data.addarg("Metadata", metadata);
609
    data.addarg("Metadata", metadata);
528
    }
610
    return UPNP_E_SUCCESS;
529
    return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
530
}
611
}
531
612
532
// Given a space separated list of track Id's, report their associated
613
// Given a space separated list of track Id's, report their associated
533
// uri and metadata in the following xml form:
614
// uri and metadata in the following xml form:
534
//
615
//
...
...
541
//  </TrackList>
622
//  </TrackList>
542
//
623
//
543
// Any ids not in the playlist are ignored. 
624
// Any ids not in the playlist are ignored. 
544
int OHPlaylist::readList(const SoapIncoming& sc, SoapOutgoing& data)
625
int OHPlaylist::readList(const SoapIncoming& sc, SoapOutgoing& data)
545
{
626
{
546
    if (!m_active) {
547
        // See comment in seekId()
548
        LOGERR("OHPlaylist::readList: not active" << endl);
549
        return UPNP_E_INTERNAL_ERROR;
550
    }
551
    string sids;
627
    string sids;
552
    bool ok = sc.get("IdList", &sids);
628
    bool ok = sc.get("IdList", &sids);
553
    LOGDEB("OHPlaylist::readList: [" << sids << "]" << endl);
629
    LOGDEB("OHPlaylist::readList: [" << sids << "]" << endl);
554
    vector<string> ids;
630
    vector<string> ids;
555
    string out("<TrackList>");
631
    string out("<TrackList>");
...
...
560
            if (id == -1) {
636
            if (id == -1) {
561
                // Lumin does this??
637
                // Lumin does this??
562
                LOGDEB("OHPlaylist::readlist: request for id -1" << endl);
638
                LOGDEB("OHPlaylist::readlist: request for id -1" << endl);
563
                continue;
639
                continue;
564
            }
640
            }
641
            string metadata;
565
            UpSong song;
642
            UpSong song;
643
            if (m_active) {
566
            if (!m_dev->m_mpdcli->statSong(song, id, true)) {
644
                if (!m_dev->m_mpdcli->statSong(song, id, true)) {
567
                LOGDEB("OHPlaylist::readList:stat failed for " << id << endl);
645
                    LOGDEB("OHPlaylist::readList:stat failed for " << id <<endl);
568
                continue;
646
                    continue;
569
            }
647
                }
570
            auto mit = m_metacache.find(song.uri);
648
                auto mit = m_metacache.find(song.uri);
571
            string metadata;
572
            if (mit != m_metacache.end()) {
649
                if (mit != m_metacache.end()) {
573
                //LOGDEB("OHPlaylist::readList: meta for id " << id << " uri "
650
                    LOGDEB1("OHPlaylist::readList: meta for id " << id << " uri "
574
                // << song.uri << " found in cache " << endl);
651
                            << song.uri << " found in cache " << endl);
575
                metadata = SoapHelp::xmlQuote(mit->second);
652
                    metadata = SoapHelp::xmlQuote(mit->second);
653
                } else {
654
                    LOGDEB("OHPlaylist::readList: meta for id " << id << " uri "
655
                           << song.uri << " not found " << endl);
656
                    metadata = didlmake(song);
657
                    m_metacache[song.uri] = metadata;
658
                    m_cachedirty = true;
659
                    metadata = SoapHelp::xmlQuote(metadata);
660
                }
576
            } else {
661
            } else {
577
                //LOGDEB("OHPlaylist::readList: meta for id " << id << " uri "
662
                LOGDEB("OHPlaylist::readList: not active: using saved queue\n");
578
                // << song.uri << " not found " << endl);
663
                for (const auto& entry : m_mpdsavedstate.queue) {
664
                    if (entry.mpdid == id) {
665
                        song = entry;
579
                metadata = didlmake(song);
666
                        metadata = didlmake(song);
580
                m_metacache[song.uri] = metadata;
667
                    }
581
                m_cachedirty = true;
668
                }
582
                metadata = SoapHelp::xmlQuote(metadata);
669
                if (metadata.empty()) {
670
                    LOGDEB("OHPlaylist: id " << id << " not found\n");
671
                    continue;
672
                }
583
            }
673
            }
584
            out += "<Entry><Id>";
674
            out += "<Entry><Id>";
585
            out += SoapHelp::xmlQuote(it->c_str());
675
            out += SoapHelp::xmlQuote(it->c_str());
586
            out += "</Id><Uri>";
676
            out += "</Id><Uri>";
587
            out += SoapHelp::xmlQuote(song.uri);
677
            out += SoapHelp::xmlQuote(song.uri);
588
            out += "</Uri><Metadata>";
678
            out += "</Uri><Metadata>";
589
            out += metadata;
679
            out += metadata;
590
            out += "</Metadata></Entry>";
680
            out += "</Metadata></Entry>";
591
        }
681
        }
592
        out += "</TrackList>";
682
        out += "</TrackList>";
593
        //LOGDEB1("OHPlaylist::readList: out: [" << out << "]" << endl);
683
        LOGDEB1("OHPlaylist::readList: out: [" << out << "]" << endl);
594
        data.addarg("TrackList", out);
684
        data.addarg("TrackList", out);
595
    }
685
    }
596
    return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
686
    return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
597
}
687
}
598
688
...
...
640
        LOGERR("OHPlaylist::insert: bad uri: " << uri << endl);
730
        LOGERR("OHPlaylist::insert: bad uri: " << uri << endl);
641
        return UPNP_E_INVALID_PARAM;
731
        return UPNP_E_INVALID_PARAM;
642
    }
732
    }
643
        
733
        
644
    if (!m_active) {
734
    if (!m_active) {
645
        // See comment in seekId()
646
        // It's not clear if special-casing afterId == 0 is a good
647
        // idea because it makes the device appear even more
648
        // unpredictable. Otoh, it allows Bubble (basic, not DS) to
649
        // switch to playlist by just adding tracks.
650
        if (afterid == 0 && m_dev->m_ohpr) {
651
            m_dev->m_ohpr->iSetSourceIndexByName("Playlist");
735
        m_dev->m_ohpr->iSetSourceIndexByName("Playlist");
652
        } else {
736
        afterid = idFromOldId(afterid);
653
            LOGERR("OHPlaylist::insert: not active" << endl);
737
        if (afterid < 0) {
654
            return UPNP_E_INTERNAL_ERROR;
738
            return UPNP_E_INTERNAL_ERROR;
655
        }
739
        }
656
    }
740
    }
657
741
658
    LOGDEB("OHPlaylist::insert: afterid " << afterid << " Uri " <<
742
    LOGDEB("OHPlaylist::insert: afterid " << afterid << " Uri " <<
...
...
672
                           const string& metadata, int *newid, bool nocheck)
756
                           const string& metadata, int *newid, bool nocheck)
673
{
757
{
674
    LOGDEB1("OHPlaylist::insertUri: " << uri << endl);
758
    LOGDEB1("OHPlaylist::insertUri: " << uri << endl);
675
    if (!m_active) {
759
    if (!m_active) {
676
        LOGERR("OHPlaylist::insertUri: not active" << endl);
760
        LOGERR("OHPlaylist::insertUri: not active" << endl);
761
        m_dev->m_ohpr->iSetSourceIndexByName("Playlist");
677
        return false;
762
        return false;
678
    }
763
    }
679
764
680
    UpSong metaformpd;
765
    UpSong metaformpd;
681
    if (!m_dev->checkContentFormat(uri, metadata, &metaformpd, nocheck)) {
766
    if (!m_dev->checkContentFormat(uri, metadata, &metaformpd, nocheck)) {
...
...
696
    return false;
781
    return false;
697
}
782
}
698
783
699
int OHPlaylist::deleteId(const SoapIncoming& sc, SoapOutgoing& data)
784
int OHPlaylist::deleteId(const SoapIncoming& sc, SoapOutgoing& data)
700
{
785
{
786
    int id;
787
    if (!sc.get("Value", &id)) {
788
        LOGERR("OHPlaylist::deleteId: no Id param\n");
789
        return UPNP_E_INVALID_PARAM;
790
    }
701
    LOGDEB("OHPlaylist::deleteId" << endl);
791
    LOGDEB("OHPlaylist::deleteId" << endl);
702
    if (!m_active) {
792
    if (!m_active) {
703
        // See comment in seekId()
793
        m_dev->m_ohpr->iSetSourceIndexByName("Playlist");
704
        LOGERR("OHPlaylist::deleteId: not active" << endl);
794
        id = idFromOldId(id);
795
        if (id < 0) {
705
        return UPNP_E_INTERNAL_ERROR;
796
            return UPNP_E_INTERNAL_ERROR;
706
    }
797
        }
707
    int id;
798
    }
708
    bool ok = sc.get("Value", &id);
709
    if (ok) {
710
        const MpdStatus &mpds = m_dev->getMpdStatusNoUpdate();
799
    const MpdStatus &mpds = m_dev->getMpdStatusNoUpdate();
711
        if (mpds.songid == id) {
800
    if (mpds.songid == id) {
712
            // MPD skips to the next track if the current one is removed,
801
        // MPD skips to the next track if the current one is removed,
713
            // but I think it's better to stop in this case
802
        // but I think it's better to stop in this case
714
            m_dev->m_mpdcli->stop();
803
        m_dev->m_mpdcli->stop();
715
        }
804
    }
716
        ok = m_dev->m_mpdcli->deleteId(id);
805
    bool ok = m_dev->m_mpdcli->deleteId(id);
717
        m_mpdqvers = -1;
806
    m_mpdqvers = -1;
718
        maybeWakeUp(ok);
807
    maybeWakeUp(ok);
719
    }
720
    return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
808
    return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
721
}
809
}
722
810
723
int OHPlaylist::deleteAll(const SoapIncoming& sc, SoapOutgoing& data)
811
int OHPlaylist::deleteAll(const SoapIncoming& sc, SoapOutgoing& data)
724
{
812
{
...
...
737
    LOGDEB("OHPlaylist::tracksMax" << endl);
825
    LOGDEB("OHPlaylist::tracksMax" << endl);
738
    data.addarg("Value", SoapHelp::i2s(tracksmax));
826
    data.addarg("Value", SoapHelp::i2s(tracksmax));
739
    return UPNP_E_SUCCESS;
827
    return UPNP_E_SUCCESS;
740
}
828
}
741
829
830
831
bool OHPlaylist::iidArray(string& idarray, int *token)
832
{
833
    LOGDEB("OHPlaylist::idArray (internal)" << endl);
834
    unordered_map<string, string> st;
835
    makestate(st);
836
    idarray = st["IdArray"];
837
    if (token) {
838
        if (m_active) {
839
            const MpdStatus &mpds = m_dev->getMpdStatusNoUpdate();
840
            LOGDEB("OHPlaylist::idArray: qvers " << mpds.qvers << endl);
841
            *token = mpds.qvers;
842
        } else {
843
            *token = 0;
844
        }
845
    }
846
    return true;
847
}
848
849
742
// Returns current list of id as array of big endian 32bits integers,
850
// Returns current list of id as array of big endian 32bits integers,
743
// base-64-encoded. 
851
// base-64-encoded. 
744
int OHPlaylist::idArray(const SoapIncoming& sc, SoapOutgoing& data)
852
int OHPlaylist::idArray(const SoapIncoming& sc, SoapOutgoing& data)
745
{
853
{
746
    LOGDEB("OHPlaylist::idArray" << endl);
854
    LOGDEB("OHPlaylist::idArray" << endl);
747
    if (!m_active) {
748
        // See comment in seekId()
749
        LOGERR("OHPlaylist::idArray: not active" << endl);
750
        return UPNP_E_INTERNAL_ERROR;
751
    }
752
    string idarray;
855
    string idarray;
753
    int token;
856
    int token;
754
    if (iidArray(idarray, &token)) {
857
    if (iidArray(idarray, &token)) {
755
        data.addarg("Token", SoapHelp::i2s(token));
858
        data.addarg("Token", SoapHelp::i2s(token));
756
        data.addarg("Array", idarray);
859
        data.addarg("Array", idarray);
757
        return UPNP_E_SUCCESS;
860
        return UPNP_E_SUCCESS;
758
    }
861
    }
759
    return UPNP_E_INTERNAL_ERROR;
862
    return UPNP_E_INTERNAL_ERROR;
760
}
863
}
761
864
762
bool OHPlaylist::iidArray(string& idarray, int *token)
763
{
764
    LOGDEB("OHPlaylist::idArray (internal)" << endl);
765
    if (makeIdArray(idarray)) {
766
        const MpdStatus &mpds = m_dev->getMpdStatusNoUpdate();
767
        LOGDEB("OHPlaylist::idArray: qvers " << mpds.qvers << endl);
768
        if (token)
769
            *token = mpds.qvers;
770
        return true;
771
    }
772
    return false;
773
}
774
865
775
bool OHPlaylist::urlMap(unordered_map<int, string>& umap)
866
bool OHPlaylist::urlMap(unordered_map<int, string>& umap)
776
{
867
{
777
    //LOGDEB1("OHPlaylist::urlMap\n");
868
    LOGDEB1("OHPlaylist::urlMap\n");
778
    string sarray; 
869
    string sarray; 
779
    if (iidArray(sarray, 0)) {
870
    if (iidArray(sarray, 0)) {
780
        vector<int> ids;
871
        vector<int> ids;
781
        if (ohplIdArrayToVec(sarray, &ids)) {
872
        if (ohplIdArrayToVec(sarray, &ids)) {
782
            vector<UpSong> songs;
873
            vector<UpSong> songs;