Switch to side-by-side view

--- a/src/cdplugins/tidal.cxx
+++ b/src/cdplugins/tidal.cxx
@@ -41,7 +41,7 @@
 class Tidal::Internal {
 public:
     Internal(const vector<string>& pth, const string& hp, const string& pp)
-	: path(pth), httphp(hp), pathprefix(pp) { }
+	: path(pth), httphp(hp), pathprefix(pp), lasttime(0) { }
 
     bool maybeStartCmd(const string&);
     string get_media_url(const std::string& path);
@@ -55,11 +55,19 @@
 
     CmdTalk cmd;
     vector<string> path;
+    // Host and port part for the URIs we generate.
     string httphp;
+    // path prefix (this is used to redirect gets to us).
     string pathprefix;
     // mimetype is a constant for a given session, depend on quality
     // choice only. Initialized once
     string mimetype;
+
+    // Cached uri translation for the vdir: we do this in getinfo()
+    // and reuse in open()
+    string lastpath;
+    string lastmediaurl;
+    time_t lasttime;
 };
 
 bool Tidal::Internal::maybeStartCmd(const string& who)
@@ -86,21 +94,25 @@
     if (!maybeStartCmd("get_media_url")) {
 	return string();
     }
-
-    unordered_map<string, string> res;
-    if (!cmd.callproc("trackuri", {{"path", path}}, res)) {
-	LOGERR("Tidal::get_media_url: slave failure\n");
-	return string();
-    }
-
-    auto it = res.find("media_url");
-    if (it == res.end()) {
-	LOGERR("Tidal::get_media_url: no media url in result\n");
-	return string();
-    }
-    string& media_url = it->second;
-    LOGDEB("Tidal: got media url [" << media_url << "]\n");
-    return media_url;
+    if (lastpath.compare(path) || (time(0) - lasttime > 10)) {
+	unordered_map<string, string> res;
+	if (!cmd.callproc("trackuri", {{"path", path}}, res)) {
+	    LOGERR("Tidal::get_media_url: slave failure\n");
+	    return string();
+	}
+
+	auto it = res.find("media_url");
+	if (it == res.end()) {
+	    LOGERR("Tidal::get_media_url: no media url in result\n");
+	    return string();
+	}
+	lastmediaurl = it->second;
+	lastpath = path;
+	lasttime = time(0);
+    }
+
+    LOGDEB("Tidal: got media url [" << lastmediaurl << "]\n");
+    return lastmediaurl;
 }
 
 string Tidal::Internal::get_mimetype(const std::string& path)
@@ -126,15 +138,6 @@
     return mimetype;
 }
 
-int Tidal::Internal::getinfo(const std::string& path, VirtualDir::FileInfo *inf)
-{
-    LOGDEB("Tidal::getinfo: " << path << endl);
-    inf->file_length = -1;
-    inf->last_modified = 0;
-    inf->mime = get_mimetype(path);
-    return 0;
-}
-
 class StreamHandle {
 public:
     StreamHandle() : rtmp(nullptr), http_handle(nullptr) {
@@ -145,7 +148,9 @@
 	    RTMP_Free(rtmp);
 	}
 	if (http_handle) {
+            LOGDEB("StreamHandle:~: closing http handle\n");
 	    UpnpCloseHttpGet(http_handle);
+            LOGDEB("StreamHandle:~: close done\n");
 	}
     }
 	
@@ -153,6 +158,47 @@
     void *http_handle;
     int len;
 };
+
+
+int Tidal::Internal::getinfo(const std::string& path, VirtualDir::FileInfo *inf)
+{
+    LOGDEB("Tidal::getinfo: " << path << endl);
+    string media_url = get_media_url(path);
+    if (media_url.empty()) {
+	return -1;
+    }
+    inf->file_length = -1;
+    inf->last_modified = 0;
+    inf->mime = get_mimetype(path);
+    if (media_url.find("http") == 0) {
+	void *http_handle;
+	char *content_type;
+	int content_length;
+	int httpstatus;
+	int code = UpnpOpenHttpGet(media_url.c_str(), &http_handle,
+				     &content_type, &content_length,
+				     &httpstatus, 30);
+	LOGDEB("Tidal::getinfo: UpnpOpenHttpGet: ret " << code <<
+	       " mtype " << content_type << " length " << content_length <<
+	       " HTTP status " << httpstatus << endl);
+	if (code) {
+	    LOGERR("Tidal::getinfo: UpnpOpenHttpGet: ret " << code <<
+		   " mtype " << content_type << " length " << content_length <<
+		   " HTTP status " << httpstatus << endl);
+	} else {
+	    inf->file_length = content_length;
+	    LOGDEB("Tidal:getinfo: got file length "<< inf->file_length <<endl);
+	}
+        // Doc says to free this, but it causes malloc issues
+	//free(content_type);
+	StreamHandle hdl;
+	hdl.http_handle = http_handle;
+	// Let StreamHandle clean up
+    }
+    LOGDEB("Tidal::getinfo: returning\n");
+    return 0;
+}
+
 
 void *Tidal::Internal::open(const string& path)
 {
@@ -178,6 +224,8 @@
 		   " HTTP status " << httpstatus << endl);
 	    return nullptr;
 	}
+        // Doc says to free this, but it causes malloc issues
+	//free(content_type);
 	StreamHandle *hdl = new StreamHandle;
 	hdl->http_handle = http_handle;
 	hdl->len = content_length;
@@ -291,8 +339,8 @@
 			   std::vector<UpSong>& entries)
 {
     auto decoded = json::parse(encoded);
-    LOGDEB("Tidal::browse: got " << decoded.size() << " entries\n");
-    LOGDEB1("Tidal::browse: undecoded json: " << decoded.dump() << endl);
+    LOGDEB("Tidal::results: got " << decoded.size() << " entries\n");
+    LOGDEB1("Tidal::results: undecoded json: " << decoded.dump() << endl);
 
     for (unsigned int i = stidx; i < decoded.size(); i++) {
 	if (--cnt < 0) {