Switch to side-by-side view

--- a/src/avtransport.cxx
+++ b/src/avtransport.cxx
@@ -89,10 +89,12 @@
                             bind(&UpMpdAVTransport::seqcontrol, 
                                  this, _1, _2, 1));
 
+    // This would make our life easier, but it's incompatible if
+    // ohplaylist is also in use, so refrain.
 //    dev->m_mpdcli->consume(true);
 #ifdef NO_SETNEXT
-    // If no setnext, fake stopping at each track
-    m_dev->m_mpdcli->single(true);
+    // 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.
+//    m_dev->m_mpdcli->single(true);
 #endif
 }
 
@@ -361,11 +363,11 @@
 }
 
 // http://192.168.4.4:8200/MediaItems/246.mp3
-int UpMpdAVTransport::setAVTransportURI(const SoapIncoming& sc, SoapOutgoing& data, 
-                                        bool setnext)
-{
+int UpMpdAVTransport::setAVTransportURI(const SoapIncoming& sc,
+                                        SoapOutgoing& data, bool setnext)
+{
+#ifdef NO_SETNEXT
     // pretend not to support setnext:
-#ifdef NO_SETNEXT
     if (setnext) {
         LOGERR("SetNextAVTransportURI: faking error\n");
         return UPNP_E_INVALID_PARAM;
@@ -394,8 +396,7 @@
         return UPNP_E_INVALID_PARAM;
     }
 
-    bool is_song = (st == MpdStatus::MPDS_PLAY) ||
-	(st == MpdStatus::MPDS_PAUSE);
+    bool is_song = (st == MpdStatus::MPDS_PLAY) || (st == MpdStatus::MPDS_PAUSE);
     UPMPD_UNUSED(is_song);
     int curpos = mpds.songpos;
     LOGDEB1("UpMpdAVTransport::set" << (setnext?"Next":"") << 
@@ -412,6 +413,17 @@
         curpos = -1;
     }
 
+    // If setAVTransport is called, the Control Point wants to control
+    // the playing, so we reset any special mpd playlist
+    // mode. Especially, repeat would prevent us from ever seeing the
+    // end of the track. Note that always setting repeat to false is
+    // one of the ways which we are incompatible with simultaneous
+    // mpc or ohplaylist use (there are many others of course).
+    m_dev->m_mpdcli->repeat(false);
+    m_dev->m_mpdcli->random(false);
+    // See comment about single in init
+    m_dev->m_mpdcli->single(false);
+    
     // curpos == -1 means that the playlist was cleared or we just started. A
     // play will use position 0, so it's actually equivalent to curpos == 0
     if (curpos == -1) {
@@ -474,13 +486,12 @@
 #endif
         // Clean up old song ids
         if (!(m_dev->m_options & UpMpd::upmpdOwnQueue)) {
-            for (set<int>::iterator it = m_songids.begin();
-                 it != m_songids.end(); it++) {
+            for (auto id : m_songids) {
                 // Can't just delete here. If the id does not exist, MPD 
                 // gets into an apparently permanent error state, where even 
                 // get_status does not work
-                if (m_dev->m_mpdcli->statId(*it)) {
-                    m_dev->m_mpdcli->deleteId(*it);
+                if (m_dev->m_mpdcli->statId(id)) {
+                    m_dev->m_mpdcli->deleteId(id);
                 }
             }
             m_songids.clear();
@@ -682,7 +693,15 @@
     m_dev->loopWakeup();
     return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
 }
-	
+
+/*
+ * For the AVTransport service, this only makes sense if we're playing a
+ * multi-track media, else we're only dealing with a single track (and
+ * possibly the next), and none of the repeat/shuffle modes make
+ * sense. If ownqueue is 0, it might still make sense for us to
+ * control the mpd play mode though, but any special mode will be reset if
+ * set(Next)AVTransport is called.
+*/
 int UpMpdAVTransport::setPlayMode(const SoapIncoming& sc, SoapOutgoing& data)
 {
     string playmode;
@@ -690,6 +709,14 @@
         return UPNP_E_INVALID_PARAM;
     }
     LOGDEB("UpMpdAVTransport::setPlayMode: " << playmode << endl);
+
+    if ((m_dev->m_options & UpMpd::upmpdOwnQueue)) {
+        // If we own the queue then none of this makes sense, we're
+        // only keeping 1 or 2 entries on the queue and controlling
+        // everything.
+        LOGDEB("AVTRansport::setPlayMode: ownqueue is set, doing nothing\n");
+        return 0;
+    }
 
     bool ok;
     if (!playmode.compare("NORMAL")) {
@@ -717,7 +744,8 @@
     return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
 }
 
-int UpMpdAVTransport::getTransportSettings(const SoapIncoming& sc, SoapOutgoing& data)
+int UpMpdAVTransport::getTransportSettings(const SoapIncoming& sc,
+                                           SoapOutgoing& data)
 {
     const MpdStatus &mpds = m_dev->getMpdStatus();
     string playmode = mpdsToPlaymode(mpds);