Switch to side-by-side view

--- a/src/ohsndrcv.cxx
+++ b/src/ohsndrcv.cxx
@@ -46,11 +46,11 @@
         if (dev && origmpd) {
             dev->m_mpdcli = origmpd;
             origmpd = 0;
-            if (dev->m_ohpl) {
-                dev->m_ohpl->resetQVers();
-            }
             if (dev->m_ohrcv) {
                 dev->m_ohrcv->iStop();
+            }
+            if (dev->m_ohpl) {
+                dev->m_ohpl->refreshState();
             }
         }
         delete mpd;
@@ -60,6 +60,8 @@
     MPDCli *mpd;
     MPDCli *origmpd;
     ExecCmd *cmd;
+    string uri;
+    string meta;
 };
 
 
@@ -74,6 +76,39 @@
         delete m;
 }
 
+static bool copyMpd(MPDCli *src, MPDCli *dest, int seekms)
+{
+    if (!src || !dest) {
+        LOGERR("copyMpd: src or dest is null\n");
+        return false;
+    }
+
+    // Playing state. If playing is stopped at this point elapsedms is
+    // lost which is why we get it as a parameter
+    MpdStatus mpds = src->getStatus();
+    if (seekms < 0) {
+        seekms = mpds.songelapsedms;
+    }
+    // Playlist from source mpd
+    vector<UpSong> playlist;
+    if (!src->getQueueData(playlist)) {
+        LOGERR("copyMpd: can't retrieve current playlist\n");
+        return false;
+    }
+    // Copy the playlist to dest
+    dest->clearQueue();
+    for (unsigned int i = 0; i < playlist.size(); i++) {
+        if (dest->insert(playlist[i].uri, i, playlist[i]) < 0) {
+            LOGERR("copyMpdt: mpd->insert failed\n");
+            return false;
+        }
+    }
+    dest->play(mpds.songpos);
+    dest->setVolume(mpds.volume);
+    dest->seek(seekms/1000);
+    return true;
+}
+
 bool SenderReceiver::start(int seekms)
 {
     LOGDEB("SenderReceiver::start. seekms " << seekms << endl);
@@ -83,78 +118,60 @@
         return false;
     }
     
-    // Playing state. Playing is stopped at this point (source switch), so
-    // we get the elapsedms (would be 0) as input param.
-    MpdStatus mpds = m->dev->getMpdStatusNoUpdate();
-
-    // Retrieve the current playlist from the normal MPD
-    vector<UpSong> playlist;
-    if (!m->dev->m_mpdcli || !m->dev->m_mpdcli->getQueueData(playlist)) {
-        LOGERR("SenderReceiver::start: can't retrieve current playlist\n");
-        return false;
-    }
-
     // Stop MPD Play (normally already done)
     m->dev->m_mpdcli->stop();
 
-    // Start fifo MPD and Sender
-    m->cmd = new ExecCmd();
-    vector<string> args;
-    args.push_back("-p");
-    args.push_back(SoapHelp::i2s(mpdport));
-    m->cmd->startExec(makesendercmd, args, false, true);
+    if (!m->cmd) {
+        // First time: Start fifo MPD and Sender
+        m->cmd = new ExecCmd();
+        vector<string> args;
+        args.push_back("-p");
+        args.push_back(SoapHelp::i2s(mpdport));
+        args.push_back("-f");
+        args.push_back(m->dev->m_friendlyname);
+        m->cmd->startExec(makesendercmd, args, false, true);
 
-    string output;
-    if (!m->cmd->getline(output)) {
-        LOGERR("SenderReceiver::start: makesender command failed\n");
-        m->clear();
-        return false;
-    }
-    LOGDEB("SenderReceiver::start got [" << output << "] from script\n");
+        string output;
+        if (!m->cmd->getline(output)) {
+            LOGERR("SenderReceiver::start: makesender command failed\n");
+            m->clear();
+            return false;
+        }
+        LOGDEB("SenderReceiver::start got [" << output << "] from script\n");
 
-    // Output is like [Ok mpdport URI base64-encoded-uri METADATA b64-meta]
-    vector<string> toks;
-    stringToTokens(output, toks);
-    if (toks.size() != 6 || toks[0].compare("Ok")) {
-        LOGERR("SenderReceiver::start: bad output from script: " << output
-               << endl);
-        m->clear();
-        return false;
-    }
-    string uri = base64_decode(toks[3]);
-    string meta = base64_decode(toks[5]);
-    
-    // Connect to the new MPD, and copy the playlist
-    m->mpd = new MPDCli("localhost", mpdport);
-    if (!m->mpd || !m->mpd->ok()) {
-        LOGERR("SenderReceiver::start: can't connect to new MPD\n");
-        m->clear();
-        return false;
-    }
-    for (unsigned int i = 0; i < playlist.size(); i++) {
-        if (m->mpd->insert(playlist[i].uri, i, playlist[i]) < 0) {
-            LOGERR("SenderReceiver::start: mpd->insert failed\n");
+        // Output is like [Ok mpdport URI base64-encoded-uri METADATA b64-meta]
+        vector<string> toks;
+        stringToTokens(output, toks);
+        if (toks.size() != 6 || toks[0].compare("Ok")) {
+            LOGERR("SenderReceiver::start: bad output from script: " << output
+                   << endl);
+            m->clear();
+            return false;
+        }
+        m->uri = base64_decode(toks[3]);
+        m->meta = base64_decode(toks[5]);
+
+        // Connect to the new MPD
+        m->mpd = new MPDCli("localhost", mpdport);
+        if (!m->mpd || !m->mpd->ok()) {
+            LOGERR("SenderReceiver::start: can't connect to new MPD\n");
             m->clear();
             return false;
         }
     }
     
     // Start our receiver
-    if (!m->dev->m_ohrcv->iSetSender(uri, meta) ||
+    if (!m->dev->m_ohrcv->iSetSender(m->uri, m->meta) ||
         !m->dev->m_ohrcv->iPlay()) {
         m->clear();
         return false;
     }
 
-    // Replace the original mpd and play
+    // Copy mpd state 
+    copyMpd(m->dev->m_mpdcli, m->mpd, seekms);
     m->origmpd = m->dev->m_mpdcli;
     m->dev->m_mpdcli = m->mpd;
-    LOGDEB("SenderReceiver::starting new mpd. songelapsedms: " <<
-           mpds.songelapsedms << endl);
-    m->mpd->setVolume(mpds.volume);
-    m->mpd->play(mpds.songpos);
-    m->mpd->seek(seekms/1000);
-    m->mpd->setVolume(mpds.volume);
+
     return true;
 }
 
@@ -162,6 +179,17 @@
 {
     LOGDEB("SenderReceiver::stop()\n");
     // Do we want to transfer the playlist back ? Probably we do.
-    m->clear();
+    if (!m->dev || !m->origmpd || !m->mpd || !m->dev->m_ohpl ||
+        !m->dev->m_ohrcv) {
+        LOGERR("SenderReceiver::stop: bad state: dev/origmpd/mpd null\n");
+        return false;
+    }
+    copyMpd(m->mpd, m->origmpd, -1);
+    m->mpd->stop();
+    m->dev->m_mpdcli = m->origmpd;
+    m->origmpd = 0;
+    m->dev->m_ohrcv->iStop();
+    m->dev->m_ohpl->refreshState();
+
     return true;
 }