Switch to side-by-side view

--- a/src/mediaserver/cdplugins/spotify/spotiproxy.cpp
+++ b/src/mediaserver/cdplugins/spotify/spotiproxy.cpp
@@ -585,8 +585,6 @@
     }
     
     // Write callback receiving data from Spotify.
-    //
-    // !! Hard-coded 2 channels of 16 bits samples. May have to change !!
     int framesink(const void *frames, int num_frames, int chans, int rate) {
         LOGDEB1("SpotiFefch::framesink. dryrun " << _dryrun << " num_frames " <<
                 num_frames<< " channels " << chans << " rate " << rate << endl);
@@ -614,9 +612,9 @@
                 // In the case where 200 mS is < actual diff, the long
                 // transfer will be truncated to content-length by mhd
                 // anyway, only the header will be wrong in this case.
-                int totalms = spp->durationMs() + 300;
+                _durationms = spp->durationMs() + 300;
                 _contentlen = 44 +
-                    ((totalms - _initseekmsecs) / 10) *
+                    ((_durationms - _initseekmsecs) / 10) *
                     (rate/100) * 2 * chans;
                 LOGDEB0("framesink: contentlen: " << _contentlen << endl);
                 _dryruncv.notify_all();
@@ -626,7 +624,8 @@
             }
             if (!_dryrun) {
                 char buf[100];
-                LOGDEB1("Sending wav header\n");
+                LOGDEB("Sending wav header. content-length " << _contentlen <<
+                       "\n");
                 int cnt = makewavheader(
                     buf, 100, rate, 16, chans, _contentlen - 44);
                 _totalsent += cnt;
@@ -649,7 +648,7 @@
             // a different way). No good solution here. Avoiding curl
             // (and wav header) errors is probably better all in all).
             size_t resid = _contentlen - _totalsent;
-            if (resid > 0 && resid < 500000) {
+            if (resid > 0 && resid < 5000000) {
                 LOGDEB("SpotiFetch: padding track with " << resid <<
                        " bytes (" << (resid*10)/(2*chans*rate/100) << " mS)\n");
                 char *buf = (char *)malloc(resid);
@@ -665,6 +664,12 @@
         }
 
         int bytes = num_frames * chans * 2;
+        if (_totalsent + bytes > _contentlen) {
+            bytes = _contentlen - _totalsent;
+            if (bytes <= 0) {
+                return num_frames;
+            }
+        }
         _totalsent += bytes;
         p->databufToQ(frames, bytes);
         return num_frames;
@@ -686,7 +691,7 @@
 
     bool waitForHeadersInternal(int maxSecs, bool isfordry) {
         unique_lock<mutex> lock(_mutex);
-        LOGDEB0("waitForHeaders: rate " << _samplerate << " isfordry " <<
+        LOGDEB("waitForHeaders: rate " << _samplerate << " isfordry " <<
                isfordry << " dryrun " << _dryrun << "\n");
         while (_samplerate == 0 || (!isfordry && _dryrun)) {
             LOGDEB1("waitForHeaders: waiting for sample rate. rate " <<
@@ -698,13 +703,14 @@
                 _cv.wait(lock);
             }
         }
-        LOGDEB0("SpotiFetch::waitForHeaders: isfordry " << isfordry <<
+        LOGDEB("SpotiFetch::waitForHeaders: isfordry " << isfordry <<
                " dryrun " << _dryrun<<" returning "<< spp->isPlaying() << endl);
         return spp->isPlaying();
     }
     void resetStreamFields() {
         _dryrun = false;
         _streamneedinit = true;
+        _durationms = 0;
         _initseekmsecs = 0;
         _samplerate = 0;
         _channels = 0;
@@ -720,6 +726,7 @@
     int _initseekmsecs{0};
     int _samplerate{0};
     int _channels{0};
+    int _durationms{0};
     uint64_t _contentlen{0};
     uint64_t _totalsent{0};
 
@@ -731,8 +738,9 @@
 bool SpotiFetch::reset()
 {
     LOGDEB("SpotiFetch::reset\n");
+    m->spp->stop();
     m->spp->waitForEndOfPlay();
-    m->spp->stop();
+
     m->resetStreamFields();
     return true;
 }
@@ -761,13 +769,18 @@
         if (m->_samplerate == 0 || m->_channels == 0) {
             LOGERR("SpotiFetch::start: rate or chans 0 after dryrun\n");
             return false;
+        } else {
+            LOGDEB("SpotiFetch::start: after dryrun rate " << m->_samplerate <<
+                   " chans " << m->_channels << endl);
         }
         v = (10 * offset) / (m->_channels * 2 * (m->_samplerate/100));
-        if (v > uint64_t(m->spp->durationMs())) {
-            v = MAX(0, m->spp->durationMs() - 10);
-        }
-    }
-    LOGDEB("SpotiFetch::start: seek secs: " << v/1000 << endl);
+        LOGDEB("SpotiFetch::start: computed seek ms: " << v << " duration " <<
+               m->_durationms << endl);
+        if (v > uint64_t(m->_durationms)) {
+            v = m->_durationms;
+        }
+    }
+    LOGDEB("SpotiFetch::start: seek msecs: " << v << endl);
     m->_initseekmsecs = v;
     
     m->_dryrun = false;
@@ -791,7 +804,7 @@
         return true;
     } else if (!stringlowercmp("content-length", nm)) {
         ulltodecstr(m->_contentlen, val);
-        LOGDEB0("SpotiFetch::headerValue: content-length: " << val << "\n");
+        LOGDEB("SpotiFetch::headerValue: content-length: " << val << "\n");
         return true;
     }
     return false;
@@ -800,6 +813,12 @@
 bool SpotiFetch::fetchDone(FetchStatus *code, int *http_code)
 {
     bool ret= !m->spp->isPlaying();
+    if (ret && code) {
+        *code = m->spp->getReason().empty() ? FETCH_OK : FETCH_FATAL;
+    }
+    if (http_code) {
+        *http_code = 0;
+    }
     LOGDEB0("SpotiFetch::fetchDone: returning " << ret << endl);
     return ret;
 }