|
a/src/avtransport.cxx |
|
b/src/avtransport.cxx |
|
... |
|
... |
31 |
#include "mpdcli.hxx"
|
31 |
#include "mpdcli.hxx"
|
32 |
#include "ohplaylist.hxx"
|
32 |
#include "ohplaylist.hxx"
|
33 |
#include "upmpd.hxx"
|
33 |
#include "upmpd.hxx"
|
34 |
#include "upmpdutils.hxx"
|
34 |
#include "upmpdutils.hxx"
|
35 |
#include "smallut.h"
|
35 |
#include "smallut.h"
|
|
|
36 |
#include "conftree.h"
|
36 |
|
37 |
|
37 |
// For testing upplay with a dumb renderer.
|
38 |
// For testing upplay with a dumb renderer.
|
38 |
// #define NO_SETNEXT
|
39 |
// #define NO_SETNEXT
|
39 |
|
40 |
|
40 |
using namespace std;
|
41 |
using namespace std;
|
41 |
using namespace std::placeholders;
|
42 |
using namespace std::placeholders;
|
42 |
|
43 |
|
43 |
static const string sIdTransport("urn:upnp-org:serviceId:AVTransport");
|
44 |
static const string sIdTransport("urn:upnp-org:serviceId:AVTransport");
|
44 |
static const string sTpTransport("urn:schemas-upnp-org:service:AVTransport:1");
|
45 |
static const string sTpTransport("urn:schemas-upnp-org:service:AVTransport:1");
|
|
|
46 |
|
|
|
47 |
static bool m_autoplay{false};
|
45 |
|
48 |
|
46 |
UpMpdAVTransport::UpMpdAVTransport(UpMpd *dev, bool noev)
|
49 |
UpMpdAVTransport::UpMpdAVTransport(UpMpd *dev, bool noev)
|
47 |
: UpnpService(sTpTransport, sIdTransport, "AVTransport.xml", dev, noev),
|
50 |
: UpnpService(sTpTransport, sIdTransport, "AVTransport.xml", dev, noev),
|
48 |
m_dev(dev), m_ohp(0)
|
51 |
m_dev(dev), m_ohp(0)
|
49 |
{
|
52 |
{
|
|
... |
|
... |
95 |
// dev->m_mpdcli->consume(true);
|
98 |
// dev->m_mpdcli->consume(true);
|
96 |
#ifdef NO_SETNEXT
|
99 |
#ifdef NO_SETNEXT
|
97 |
// If no setnext, we'd like to fake stopping at each track but this does not work because mpd goes into PAUSED PLAY at the end of track, not STOP.
|
100 |
// If no setnext, we'd like to fake stopping at each track but this does not work because mpd goes into PAUSED PLAY at the end of track, not STOP.
|
98 |
// m_dev->m_mpdcli->single(true);
|
101 |
// m_dev->m_mpdcli->single(true);
|
99 |
#endif
|
102 |
#endif
|
|
|
103 |
string scratch;
|
|
|
104 |
if (g_config->get("avtautoplay", scratch)) {
|
|
|
105 |
m_autoplay = stringToBool(scratch);
|
|
|
106 |
}
|
100 |
}
|
107 |
}
|
101 |
|
108 |
|
102 |
// AVTransport Errors
|
109 |
// AVTransport Errors
|
103 |
enum AVTErrorCode {
|
110 |
enum AVTErrorCode {
|
104 |
UPNP_AV_AVT_INVALID_TRANSITION = 701,
|
111 |
UPNP_AV_AVT_INVALID_TRANSITION = 701,
|
|
... |
|
... |
478 |
m_nextMetadata.clear();
|
485 |
m_nextMetadata.clear();
|
479 |
}
|
486 |
}
|
480 |
|
487 |
|
481 |
if (!setnext) {
|
488 |
if (!setnext) {
|
482 |
// Have to tell mpd which track to play, else it will keep on
|
489 |
// Have to tell mpd which track to play, else it will keep on
|
483 |
// the previous despite the insertion. The UPnP docs say
|
490 |
// the previous despite the insertion.
|
|
|
491 |
// The UPnP AVTransport definition document is very clear on
|
484 |
// that setAVTransportURI should not change the transport
|
492 |
// the fact that setAVTransportURI should not change the
|
485 |
// state (pause/stop stay pause/stop) but it seems that some clients
|
493 |
// transport state (pause/stop stay pause/stop)
|
486 |
// expect that the track will start playing.
|
494 |
// However some control points expect that the track will
|
487 |
// Needs to be revisited after seeing more clients. For now try to
|
495 |
// start playing without having to issue a Play command, which
|
488 |
// preserve state as per standard.
|
496 |
// is why the avtautoplay quirk was added for forcing Play after
|
|
|
497 |
// insert
|
489 |
// Audionet: issues a Play
|
498 |
// - Audionet: issues a Play
|
490 |
// BubbleUpnp: issues a Play
|
499 |
// - BubbleUpnp: issues a Play
|
491 |
// MediaHouse: no setnext, Play
|
500 |
// - MediaHouse: no setnext, Play
|
492 |
#if 1 || defined(upmpd_do_restore_play_state_after_add)
|
501 |
// - Raumfeld: needs autoplay
|
|
|
502 |
if (m_autoplay) {
|
|
|
503 |
m_dev->m_mpdcli->play(curpos);
|
|
|
504 |
} else {
|
493 |
switch (st) {
|
505 |
switch (st) {
|
494 |
case MpdStatus::MPDS_PLAY: m_dev->m_mpdcli->play(curpos); break;
|
506 |
case MpdStatus::MPDS_PLAY: m_dev->m_mpdcli->play(curpos); break;
|
495 |
case MpdStatus::MPDS_PAUSE: m_dev->m_mpdcli->pause(true); break;
|
507 |
case MpdStatus::MPDS_PAUSE: m_dev->m_mpdcli->pause(true); break;
|
496 |
case MpdStatus::MPDS_STOP: m_dev->m_mpdcli->stop(); break;
|
508 |
case MpdStatus::MPDS_STOP: m_dev->m_mpdcli->stop(); break;
|
497 |
default: break;
|
509 |
default: break;
|
498 |
}
|
510 |
}
|
499 |
#endif
|
511 |
}
|
500 |
// Clean up old song ids
|
512 |
// Clean up old song ids
|
501 |
if (!(m_dev->m_options & UpMpd::upmpdOwnQueue)) {
|
513 |
if (!(m_dev->m_options & UpMpd::upmpdOwnQueue)) {
|
502 |
for (auto id : m_songids) {
|
514 |
for (auto id : m_songids) {
|
503 |
// Can't just delete here. If the id does not exist, MPD
|
515 |
// Can't just delete here. If the id does not exist, MPD
|
504 |
// gets into an apparently permanent error state, where even
|
516 |
// gets into an apparently permanent error state, where even
|