View Issue Details

IDProjectCategoryView StatusLast Update
0003884ardourbugspublic2015-09-18 15:14
Reportercolinf Assigned Topaul  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Target Version3.X 
Summary0003884: Freesound tab doesn't appear in 'Import' dialog
DescriptionI built A3 with Freesound, but there's no sign of the 'Freesound' tab in the 'Import' dialog.

In fact, I don't think FREESOUND is defined for compilation at all.
TagsNo tags attached.

Activities

paul

2011-03-25 20:04

administrator   ~0010413

FreeSound support is broken now that FreeSound has moved to their new API (which looks as if it might actually work, unlike the old one). FreeSound support will not return until someone volunteers to port the code over to their new API.

colinf

2011-11-06 23:52

updater   ~0011923

I've had a play with the new Freesound API this weekend, and I'm hopeful that making this work might actually be within my capabilities. Patch to follow soonish.

2011-11-08 18:52

 

freesound-new-api-10499.patch (37,904 bytes)   
Index: gtk2_ardour/wscript
===================================================================
--- gtk2_ardour/wscript	(revision 10499)
+++ gtk2_ardour/wscript	(working copy)
@@ -388,6 +388,7 @@
 
     if bld.is_defined('FREESOUND'):
         obj.source +=  [ 'sfdb_freesound_mootcher.cc' ]
+        obj.defines += [ 'FREESOUND' ]
 
     if bld.is_defined('VST_SUPPORT'):
         obj.source += [ 'vst_pluginui.cc' ]
Index: gtk2_ardour/sfdb_freesound_mootcher.cc
===================================================================
--- gtk2_ardour/sfdb_freesound_mootcher.cc	(revision 10499)
+++ gtk2_ardour/sfdb_freesound_mootcher.cc	(working copy)
@@ -1,6 +1,7 @@
 /* sfdb_freesound_mootcher.cpp **********************************************************************
 
 	Adapted for Ardour by Ben Loftis, March 2008
+	Updated to new Freesound API by Colin Fletcher, November 2011
 
 	Mootcher 23-8-2005
 
@@ -43,37 +44,39 @@
 
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <iostream>
 
 #include "ardour/audio_library.h"
 
-#define TRUE 1
+static const std::string base_url = "http://www.freesound.org/api";
+static const std::string api_key = "35abf53d8a694e65bae0adf3aa408fb3"; // test, starlingaudio.co.uk, c0l1n_fl3tch3r
 
+
 //------------------------------------------------------------------------
-Mootcher::	Mootcher(const char *saveLocation)
-	: curl( NULL )
-	, connection( 0 )
+Mootcher::Mootcher(const char *saveLocation)
+	: curl(curl_easy_init())
 {
 	changeWorkingDir(saveLocation);
 };
 //------------------------------------------------------------------------
-Mootcher::	~Mootcher()
+Mootcher:: ~Mootcher()
 {
-	remove( "cookiejar.txt" );
 }
+
 //------------------------------------------------------------------------
 const char* Mootcher::changeWorkingDir(const char *saveLocation)
 {
 	basePath = saveLocation;
 #ifdef __WIN32__
 	std::string replace = "/";
-	int pos = (int)basePath.find("\\");
+	size_t pos = basePath.find("\\");
 	while( pos != std::string::npos ){
 		basePath.replace(pos, 1, replace);
-		pos = (int)basePath.find("\\");
+		pos = basePath.find("\\");
 	}
 #endif
 	//
-	int pos2 = basePath.find_last_of("/");
+	size_t pos2 = basePath.find_last_of("/");
 	if(basePath.length() != (pos2+1)) basePath += "/";
 
 	// create Freesound directory and sound dir
@@ -86,15 +89,12 @@
 }
 
 //------------------------------------------------------------------------
-size_t		Mootcher::WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
+size_t Mootcher::WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
 {
 	register int realsize = (int)(size * nmemb);
 	struct MemoryStruct *mem = (struct MemoryStruct *)data;
 
-	// There might be a realloc() out there that doesn't like
-	// reallocing NULL pointers, so we take care of it here
-	if(mem->memory)	mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1);
-	else			mem->memory = (char *)malloc(mem->size + realsize + 1);
+	mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1);
 
 	if (mem->memory) {
 		memcpy(&(mem->memory[mem->size]), ptr, realsize);
@@ -106,332 +106,183 @@
 
 
 //------------------------------------------------------------------------
-void		Mootcher::toLog(std::string input)
-{
-printf("%s\n", input.c_str());// for debugging
-}
 
+std::string Mootcher::sortMethodString(enum sortMethod sort) {
 
+	switch (sort) {
+		case sort_duration_desc:	return "duration_desc";	
+		case sort_duration_asc: 	return "duration_asc";
+		case sort_created_desc:		return "created_desc";
+		case sort_created_asc:		return "created_asc";
+		case sort_downloads_desc:	return "downloads_desc";
+		case sort_downloads_asc:	return "downloads_asc";
+		case sort_rating_desc:		return "rating_desc";
+		case sort_rating_asc:		return "rating_asc";
+		default:			return "";	
+	}
+}
+
 //------------------------------------------------------------------------
-void		Mootcher::setcUrlOptions()
+void Mootcher::setcUrlOptions()
 {
 	// basic init for curl
 	curl_global_init(CURL_GLOBAL_ALL);
 	// some servers don't like requests that are made without a user-agent field, so we provide one
 	curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
 	// setup curl error buffer
-	CURLcode res = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
-	// always use the cookie with session id which is received at the login
-	curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "cookiejar.txt");
+	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
 	// Allow redirection
 	curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
+	
+	// Allow connections to time out (without using signals)
+	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+	curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10);
+
+
 }
 
-//------------------------------------------------------------------------
-int			Mootcher::doLogin(std::string login, std::string password)
+std::string Mootcher::doRequest(std::string uri, std::string params)
 {
-	if(connection==1)
-		return 1;
-
+	std::string result;
 	struct MemoryStruct xml_page;
 	xml_page.memory = NULL;
 	xml_page.size = 0;
 
-	// create the post message from the login and password
-	std::string postMessage;
-	postMessage += "username=";
-	postMessage += curl_escape(login.c_str(), 0);
-	postMessage += "&password=";
-	postMessage += curl_escape(password.c_str(), 0);
-	postMessage += "&login=";
-	postMessage += curl_escape("1", 0);
-	postMessage += "&redirect=";
-	postMessage += curl_escape("../tests/login.php", 0);
+	setcUrlOptions();
+	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
+	curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &xml_page);
 
-	// Do the setup for libcurl
-	curl = curl_easy_init();
+	// curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
+	// curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postMessage.c_str());
+	// curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1);
 
-	if(curl)
-	{
-		setcUrlOptions();
-		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
-		curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&xml_page);
-		// save the sessoin id that is given back by the server in a cookie
-		curl_easy_setopt(curl, CURLOPT_COOKIEJAR, "cookiejar.txt");
-		// use POST for login variables
-		curl_easy_setopt(curl, CURLOPT_POST, TRUE);
-		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postMessage.c_str());
-		curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1);
+	// the url to get
+	std::string url = base_url + uri + "?";
+	if (params != "") {
+		url += params + "&api_key=" + api_key + "&format=xml";
+	} else {
+		url += "api_key=" + api_key + "&format=xml";
+	}
+		
+	curl_easy_setopt(curl, CURLOPT_URL, url.c_str() );
+	std::cerr << "doRequest: " << url << std::endl;
+	
+	// perform online request
+	CURLcode res = curl_easy_perform(curl);
+	if( res != 0 ) {
+		std::cerr << "curl error " << res << " (" << curl_easy_strerror(res) << ")" << std::endl;
+		return "";
+	}
 
-		// the url to get
-		std::string login_url = "http://www.freesound.org/forum/login.php";
-		curl_easy_setopt(curl, CURLOPT_URL, login_url.c_str() );
+	result = xml_page.memory;
+	// free the memory
+	if(xml_page.memory){
+		free( xml_page.memory );
+		xml_page.memory = NULL;
+		xml_page.size = 0;
+	}
 
-		// perform online request
-		connection = 1;
-		CURLcode res = curl_easy_perform(curl);
-		if( res != 0 ) {
-			toLog("curl login error\n");
-			toLog(curl_easy_strerror(res));
-			connection = 0;
-		}
+	return result;
 
-		if (connection == 1){
-			std::string check_page = xml_page.memory;
-			int test = (int)check_page.find("login");   //logged
-			if(	strcmp(xml_page.memory, "login") == 0 )
-				toLog("Logged in.\n");
-			else {
-				toLog("Login failed: Check username and password.\n");
-				connection = 0;
-			}
-		}
+}
 
-		// free the memory
-		if(xml_page.memory){
-			free( xml_page.memory );
-			xml_page.memory = NULL;
-			xml_page.size = 0;
-		}
 
-		std::cerr << "Login was cool, connection = "  << connection << std::endl;
-		return connection;
-	}
-	else return 3; // will be returned if a curl related problem ocurrs
-}
-//------------------------------------------------------------------------
-std::string	Mootcher::searchText(std::string word)
+std::string Mootcher::searchText(std::string query, int page, std::string filter, enum sortMethod sort)
 {
-	struct MemoryStruct xml_page;
-	xml_page.memory = NULL;
-	xml_page.size = 0;
+	std::string params = "";
+	char buf[24];
 
-	std::string result;
-
-	if(connection != 0)
-	{
-		// create a url encoded post message
-		std::string postMessage;
-		char tempString[ 128 ];
-		char *tempPointer = &tempString[0];
-
-		postMessage = "search=";
-		postMessage += curl_escape(word.c_str(), 0);
-		sprintf( tempPointer, "&searchDescriptions=1");
-		postMessage += tempPointer;
-		sprintf( tempPointer, "&searchtags=1");
-		postMessage += tempPointer;
-
-		// Ref: http://www.freesound.org/forum/viewtopic.php?p=19081
-		// const ORDER_DEFAULT = 0;
-		// const ORDER_DOWNLOADS_DESC = 1;
-		// const ORDER_DOWNLOADS_ASC = 2;
-		// const ORDER_USERNAME_DESC = 3;
-		// const ORDER_USERNAME_ASC = 4;
-		// const ORDER_DATE_DESC = 5;
-		// const ORDER_DATE_ASC = 6;
-		// const ORDER_DURATION_DESC = 7;
-		// const ORDER_DURATION_ASC = 8;
-		// const ORDER_FILEFORMAT_DESC = 9;
-		// const ORDER_FILEFORMAT_ASC = 10;
-		sprintf( tempPointer, "&order=1");
-		postMessage += tempPointer;
-		sprintf( tempPointer, "&start=0");
-		postMessage += tempPointer;
-		sprintf( tempPointer, "&limit=10");
-		postMessage += tempPointer;
-		// The limit of 10 samples is arbitrary, but seems
-		// reasonable in light of the fact that all of the returned
-		// samples get downloaded, and downloads are s-l-o-w.
-
-		if(curl)
-		{
-			// basic init for curl
-			setcUrlOptions();
-			curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
-			curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&xml_page);
-			// setup the post message
-			curl_easy_setopt(curl, CURLOPT_POST, TRUE);
-			curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postMessage.c_str());
-			curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1);
-
-			// the url to get
-			std::string search_url = "http://www.freesound.org/searchTextXML.php";
-			curl_easy_setopt(curl, CURLOPT_URL, search_url.c_str());
-
-			// perform the online search
-			connection = 1;
-			CURLcode res = curl_easy_perform(curl);
-			if( res != 0 ) {
-				toLog("curl login error\n");
-				toLog(curl_easy_strerror(res));
-				connection = 0;
-			}
-
-			result = xml_page.memory;
-			toLog( result.c_str() );
-
-			// free the memory
-			if(xml_page.memory){
-				free( xml_page.memory );
-				xml_page.memory = NULL;
-				xml_page.size = 0;
-			}
-
-		}
+	if (page > 1) {
+		snprintf(buf, 23, "p=%d&", page);
+		params += buf;
 	}
+	
+	params += "q=" + query;	
 
-	return result;
+	if (filter != "")
+		params += "&f=" + filter;
+	
+	if (sort)
+		params += "&s=" + sortMethodString(sort);
+
+	return doRequest("/sounds/search", params);
 }
 
 //------------------------------------------------------------------------
-std::string Mootcher::changeExtension(std::string filename)
+
+std::string Mootcher::getSoundResourceFile(std::string ID)
 {
-	std::string aiff = ".aiff";
-	std::string aif = ".aif";
-	std::string wav = ".wav";
-	std::string mp3 = ".mp3";
-	std::string ogg = ".ogg";
-	std::string flac = ".flac";
 
-	std::string replace = ".xml";
-	int pos = 0;
+	std::string originalSoundURI;
+	std::string audioFileName;
+	std::string xmlFileName;
+	std::string xml;
 
- 	pos = (int)filename.find(aiff);
-	if(pos != std::string::npos) filename.replace(pos, aiff.size(), replace);
- 	pos = (int)filename.find(aif);
-	if(pos != std::string::npos) filename.replace(pos, aif.size(), replace);
- 	pos = (int)filename.find(wav);
-	if(pos != std::string::npos) filename.replace(pos, wav.size(), replace);
- 	pos = (int)filename.find(mp3);
-	if(pos != std::string::npos) filename.replace(pos, mp3.size(), replace);
- 	pos = (int)filename.find(ogg);
-	if(pos != std::string::npos) filename.replace(pos, ogg.size(), replace);
- 	pos = (int)filename.find(flac);
-	if(pos != std::string::npos) filename.replace(pos, flac.size(), replace);
 
-	return filename;
-}
-//------------------------------------------------------------------------
-void		Mootcher::GetXml(std::string ID, struct MemoryStruct &xml_page)
-{
+	std::cerr << "getSoundResourceFile(" << ID << ")" << std::endl;
 
-	if(curl) {
-		setcUrlOptions();
-		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
-		curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&xml_page);
+	// download the xmlfile into xml_page
+	xml = doRequest("/sounds/" + ID, "");
 
-		// URL to get
-		std::string getxml_url = "http://www.freesound.org/samplesViewSingleXML.php?id=";
-		getxml_url += ID;
+	XMLTree doc;
+	doc.read_buffer( xml.c_str() );
+	XMLNode *freesound = doc.root();
 
-		curl_easy_setopt(curl, CURLOPT_URL, getxml_url.c_str() );
+	// if the page is not a valid xml document with a 'freesound' root
+	if (freesound == NULL) {
+		std::cerr << "getSoundResourceFile: There is no valid root in the xml file" << std::endl;
+		return "";
+	}
 
-		// get it!
-		connection = 1;
-		CURLcode res = curl_easy_perform(curl);
-		if( res != 0 ) {
-			toLog("curl login error\n");
-			toLog(curl_easy_strerror(res));
-			connection = 0;
-		}
+	if (strcmp(doc.root()->name().c_str(), "response") != 0) {
+		std::cerr << "getSoundResourceFile: root =" << doc.root()->name() << ", != response" << std::endl;
+		return "";
 	}
-}
-//------------------------------------------------------------------------
-std::string	Mootcher::getXmlFile(std::string ID, int &length)
-{
-	struct MemoryStruct xml_page;
-	xml_page.memory = NULL;
-	xml_page.size = NULL;
 
-	std::string xmlFileName;
-	std::string audioFileName;
-	std::string filename;
+	XMLNode *name = freesound->child("original_filename");
+	XMLNode *filesize = freesound->child("filesize");
 
-	if(connection != 0) {
-		// download the xmlfile into xml_page
-		GetXml(ID, xml_page);
 
-		// if sample ID does not exist on the freesound website
-		if(strcmp(xml_page.memory, "sample non existant") == 0){
-			free( xml_page.memory );
-			sprintf(message, "getXmlFile: sample with ID:%s does not exist!\n", ID.c_str() );
-			toLog(message);
-			return filename;
-		} else {
-			XMLTree doc;
-			doc.read_buffer( xml_page.memory );
-			XMLNode *freesound = doc.root();
+	// get the file name and size from xml file
+	if (name && filesize) {
 
-			// if the page is not a valid xml document with a 'freesound' root
-			if( freesound == NULL){
-				sprintf(message, "getXmlFile: There is no valid root in the xml file");
-				toLog(message);
-			} else {
-				XMLNode *sample = freesound->child("sample");
-				XMLNode *name = NULL;
-				XMLNode *filesize = NULL;
-				if (sample) {
-					name = sample->child("originalFilename");
-					filesize = sample->child("filesize");
-				}
+		audioFileName = basePath + "snd/" + ID + "-" + name->child("text")->content();
 
-				// get the file name and size from xml file
-				if (sample && name && filesize) {
+		// create new filename with the ID number
+		xmlFileName = basePath;
+		xmlFileName += "snd/";
+		xmlFileName += freesound->child("id")->child("text")->content();
+		xmlFileName += "-";
+		xmlFileName += name->child("text")->content();
+		xmlFileName += ".xml";
 
-					audioFileName = name->child("text")->content();
-					sprintf( message, "getXmlFile: %s needs to be downloaded\n", audioFileName.c_str() );
-					toLog(message);
+		// std::cerr << "getSoundResourceFile: saving XML: " << xmlFileName << std::endl;
 
-					length = atoi(filesize->child("text")->content().c_str());
+		// save the xml file to disk
+		doc.write(xmlFileName.c_str());
 
-					// create new filename with the ID number
-					filename = basePath;
-					filename += "snd/";
-					filename += sample->property("id")->value();
-					filename += "-";
-					filename += audioFileName;
-					// change the extention into .xml
-					xmlFileName = changeExtension( filename );
-
-					sprintf(message, "getXmlFile: saving XML: %s\n", xmlFileName.c_str() );
-					toLog(message);
-
-					// save the xml file to disk
-					doc.write(xmlFileName.c_str());
-
-					//store all the tags in the database
-					XMLNode *tags = sample->child("tags");
-					if (tags) {
-						XMLNodeList children = tags->children();
-						XMLNodeConstIterator niter;
-						std::vector<std::string> strings;
-						for (niter = children.begin(); niter != children.end(); ++niter) {
-							XMLNode *node = *niter;
-							if( strcmp( node->name().c_str(), "tag") == 0 ) {
-								XMLNode *text = node->child("text");
-								if (text) strings.push_back(text->content());
-							}
-						}
-						ARDOUR::Library->set_tags (std::string("//")+filename, strings);
-						ARDOUR::Library->save_changes ();
+		//store all the tags in the database
+		XMLNode *tags = freesound->child("tags");
+		if (tags) {
+			XMLNodeList children = tags->children();
+			XMLNodeConstIterator niter;
+			std::vector<std::string> strings;
+			for (niter = children.begin(); niter != children.end(); ++niter) {
+				XMLNode *node = *niter;
+				if( strcmp( node->name().c_str(), "resource") == 0 ) {
+					XMLNode *text = node->child("text");
+					if (text) {
+						// std::cerr << "tag: " << text->content() << std::endl;
+						strings.push_back(text->content());
 					}
 				}
-
-				// clear the memory
-				if(xml_page.memory){
-					free( xml_page.memory );
-					xml_page.memory = NULL;
-					xml_page.size = 0;
-				}
-				return audioFileName;
 			}
+			ARDOUR::Library->set_tags (std::string("//")+audioFileName, strings);
+			ARDOUR::Library->save_changes ();
 		}
 	}
-	else {
-		return audioFileName;
-	}
 
+	return audioFileName;
 }
 
 int audioFileWrite(void *buffer, size_t size, size_t nmemb, void *file)
@@ -440,74 +291,63 @@
 };
 
 //------------------------------------------------------------------------
-std::string	Mootcher::getFile(std::string ID)
+std::string Mootcher::getAudioFile(std::string originalFileName, std::string ID, std::string audioURL, Gtk::ProgressBar *progress_bar)
 {
-	CURLcode result_curl;
 
-	std::string audioFileName;
+	std::string audioFileName = basePath + "snd/" + ID + "-" + originalFileName;
 
-	if(connection != 0)
-	{
-		int length;
-		std::string name = getXmlFile(ID, length);
-		if( name != "" ){
+	//check to see if audio file already exists
+	FILE *testFile = fopen(audioFileName.c_str(), "r");
+	if (testFile) {  
+		fseek (testFile , 0 , SEEK_END);
+		if (ftell (testFile) > 256) {
+			std::cerr << "audio file " << audioFileName << " already exists" << std::endl;
+			fclose (testFile);
+			return audioFileName;
+		}
+		
+		// else file was small, probably an error, delete it and try again
+		fclose(testFile);
+		remove( audioFileName.c_str() );  
+	}
 
-			// create new filename with the ID number
-			audioFileName += basePath;
-			audioFileName += "snd/";
-			audioFileName += ID;
-			audioFileName += "-";
-			audioFileName += name;
+	//now download the actual file
+	if (curl) {
 
-			//check to see if audio file already exists
-			FILE *testFile = fopen(audioFileName.c_str(), "r");
-			if (testFile) {  //TODO:  should also check length to see if file is complete
-				fseek (testFile , 0 , SEEK_END);
-				if (ftell (testFile) == length) {
-					sprintf(message, "%s already exists\n", audioFileName.c_str() );
-					toLog(message);
-					fclose (testFile);
-					return audioFileName;
-				} else {
-					remove( audioFileName.c_str() );  //file was not correct length, delete it and try again
-				}
-			}
+		FILE* theFile;
+		theFile = fopen( audioFileName.c_str(), "wb" );
 
+		if (theFile) {
+		
+			// create the download url
+			audioURL += "?api_key=" + api_key;
+		
+			setcUrlOptions();
+			curl_easy_setopt(curl, CURLOPT_URL, audioURL.c_str() );
+			curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, audioFileWrite);
+			curl_easy_setopt(curl, CURLOPT_WRITEDATA, theFile);
 
-			//now download the actual file
-			if (curl) {
+			std::cerr << "downloading " << audioFileName << " from " << audioURL << "..." << std::endl;
 
-				FILE* theFile;
-				theFile = fopen( audioFileName.c_str(), "wb" );
+			curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 0); // turn on the progress bar
+			curl_easy_setopt (curl, CURLOPT_PROGRESSFUNCTION, progress_callback);
+			curl_easy_setopt (curl, CURLOPT_PROGRESSDATA, progress_bar);
 
-				// create the download url, this url will also update the download statics on the site
-				std::string audioURL;
-				audioURL += "http://www.freesound.org/samplesDownload.php?id=";
-				audioURL += ID;
+			CURLcode res = curl_easy_perform(curl);
+			fclose(theFile);
 
-				setcUrlOptions();
-				curl_easy_setopt(curl, CURLOPT_URL, audioURL.c_str() );
-				curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, audioFileWrite);
-				curl_easy_setopt(curl, CURLOPT_WRITEDATA, theFile);
+			curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 1); // turn off the progress bar
+			progress_bar->set_fraction(0.0);
 
-				connection = 1;
-				CURLcode res = curl_easy_perform(curl);
-				if( res != 0 ) {
-					toLog("curl login error\n");
-					toLog(curl_easy_strerror(res));
-					connection = 0;
-				}
-
-				fclose(theFile);
+			if( res != 0 ) {
+				std::cerr <<  "curl error " << res << " (" << curl_easy_strerror(res) << ")" << std::endl;
+				remove( audioFileName.c_str() );  
+				return "";
+			} else {
+				std::cerr << "done!" << std::endl;
+				// now download the tags &c.
+				getSoundResourceFile(ID);
 			}
-
-/*
-			bar.dlnowMoo = 0;
-			bar.dltotalMoo = 0;
-			curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 0); // turn on the process bar thingy
-			curl_easy_setopt (curl, CURLOPT_PROGRESSFUNCTION, progress_callback);
-			curl_easy_setopt (curl, CURLOPT_PROGRESSDATA, &bar);
-*/
 		}
 	}
 
@@ -517,8 +357,17 @@
 //---------
 int Mootcher::progress_callback(void *bar, double dltotal, double dlnow, double ultotal, double ulnow)
 {
-	struct dlprocess *lbar = (struct dlprocess *) bar;
-	lbar->dltotalMoo = dltotal;
-	lbar->dlnowMoo = dlnow;
+
+	//XXX I hope it's OK to do GTK things in this callback. Otherwise
+	// I'll have to do stuff like in interthread_progress_window.
+	
+	Gtk::ProgressBar *progress_bar = (Gtk::ProgressBar *) bar;
+	progress_bar->set_fraction(dlnow/dltotal);
+	/* Make sure the progress widget gets updated */
+	while (Glib::MainContext::get_default()->iteration (false)) {
+		/* do nothing */
+	}
+	std::cerr << "progress: " << dlnow << " of " << dltotal << " \r";
 	return 0;
 }
+
Index: gtk2_ardour/sfdb_freesound_mootcher.h
===================================================================
--- gtk2_ardour/sfdb_freesound_mootcher.h	(revision 10499)
+++ gtk2_ardour/sfdb_freesound_mootcher.h	(working copy)
@@ -1,6 +1,7 @@
 /*sfdb_freesound_mootcher.h****************************************************************************
 
 	Adapted for Ardour by Ben Loftis, March 2008
+	Updated to new Freesound API by Colin Fletcher, November 2011
 
 	Mootcher Online Access to thefreesoundproject website
 	http://freesound.iua.upf.edu/
@@ -19,60 +20,55 @@
 #include <string>
 #include <sstream>
 #include <vector>
+#include <gtkmm/progressbar.h>
 //#include <ctime>
 
 #include "curl/curl.h"
 
-
-// mootcher version
-#define ___VERSION___ 1.3
-
 //--- struct to store XML file
 struct MemoryStruct {
 	char *memory;
 	size_t size;
 };
 
-//--- for download process viewing
-struct dlprocess {
-	double dltotalMoo;
-	double dlnowMoo;
+enum sortMethod {
+	sort_none,		// no sort
+	sort_duration_desc,	// Sort by the duration of the sounds, longest sounds first.
+	sort_duration_asc, 	// Same as above, but shortest sounds first.
+	sort_created_desc, 	// Sort by the date of when the sound was added. newest sounds first.
+	sort_created_asc, 	// Same as above, but oldest sounds first.
+	sort_downloads_desc, 	// Sort by the number of downloads, most downloaded sounds first.
+	sort_downloads_asc, 	// Same as above, but least downloaded sounds first.
+	sort_rating_desc, 	// Sort by the average rating given to the sounds, highest rated first.
+	sort_rating_asc 	// Same as above, but lowest rated sounds first.
 };
 
+
 class Mootcher
 {
 public:
 	Mootcher(const char *saveLocation);
 	~Mootcher();
 
-	int			doLogin(std::string login, std::string password);
-	std::string	getFile(std::string ID);
-	std::string	searchText(std::string word);
+	std::string	getAudioFile(std::string originalFileName, std::string ID, std::string audioURL, Gtk::ProgressBar *progress_bar);
+	std::string	searchText(std::string query, int page, std::string filter, enum sortMethod sort);
 
-
-	struct dlprocess bar;
-
 private:
 
 	const char*	changeWorkingDir(const char *saveLocation);
 
-	std::string	getXmlFile(std::string ID, int &length);
-	void		GetXml(std::string ID, struct MemoryStruct &xml_page);
-	std::string	changeExtension(std::string filename);
-
-	void		toLog(std::string input);
-
+	std::string	doRequest(std::string uri, std::string params);
 	void		setcUrlOptions();
 
-    static size_t		WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data);
-	static int			progress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
+	static size_t	WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data);
+	static int	progress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
+	std::string	sortMethodString(enum sortMethod sort);
+	std::string	getSoundResourceFile(std::string ID);
 
 	CURL *curl;
 	char errorBuffer[CURL_ERROR_SIZE];	// storage for cUrl error message
 
-	int connection;		// is 0 if no connection
-	char message[128];	// storage for messages that are send to the logfile
-
 	std::string basePath;
 	std::string xmlLocation;
 };
+
Index: gtk2_ardour/sfdb_ui.cc
===================================================================
--- gtk2_ardour/sfdb_ui.cc	(revision 10499)
+++ gtk2_ardour/sfdb_ui.cc	(working copy)
@@ -421,7 +421,7 @@
 	  preview (persistent),
 	  found_search_btn (_("Search")),
 	  found_list_view (found_list),
-	  freesound_search_btn (_("Start Downloading")),
+	  freesound_search_btn (_("Search")),
 	  freesound_list_view (freesound_list)
 {
 	resetting_ourselves = false;
@@ -516,33 +516,53 @@
 		passbox->set_spacing (6);
 
 		label = manage (new Label);
-		label->set_text (_("User:"));
+		label->set_text (_("Tags:"));
 		passbox->pack_start (*label, false, false);
-		passbox->pack_start (freesound_name_entry);
+		passbox->pack_start (freesound_entry, false, false);
+
 		label = manage (new Label);
-		label->set_text (_("Password:"));
+		label->set_text (_("Sort:"));
 		passbox->pack_start (*label, false, false);
-		passbox->pack_start (freesound_pass_entry);
+		passbox->pack_start (freesound_sort, false, false);
+		freesound_sort.clear_items();
+		
+		// Order of the following must correspond with enum sortMethod
+		// in sfdb_freesound_mootcher.h	
+		freesound_sort.append_text(_("None"));
+		freesound_sort.append_text(_("Longest"));
+		freesound_sort.append_text(_("Shortest"));
+		freesound_sort.append_text(_("Newest"));
+		freesound_sort.append_text(_("Oldest"));
+		freesound_sort.append_text(_("Most downloaded"));
+		freesound_sort.append_text(_("Least downloaded"));
+		freesound_sort.append_text(_("Highest rated"));
+		freesound_sort.append_text(_("Lowest rated"));
+		freesound_sort.set_active(0);
+
 		label = manage (new Label);
-		label->set_text (_("Tags:"));
+		label->set_text (_("Page:"));
 		passbox->pack_start (*label, false, false);
-		passbox->pack_start (freesound_entry, false, false);
+		passbox->pack_start (freesound_page, false, false);
+		freesound_page.set_range(1, 1000);
+		freesound_page.set_increments(1, 10);
+		
 		passbox->pack_start (freesound_search_btn, false, false);
-
+		passbox->pack_start (progress_bar);
+		
 		Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
 		scroll->add(freesound_list_view);
 		scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
 
 		vbox = manage(new VBox);
 		vbox->pack_start (*passbox, PACK_SHRINK);
-		vbox->pack_start(*scroll);
+		vbox->pack_start (*scroll);
 
-		//vbox->pack_start (freesound_list_view);
-
-		freesound_list_view.append_column(_("Paths"), freesound_list_columns.pathname);
+		freesound_list_view.append_column(_("ID")      , freesound_list_columns.id);
+		freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
+		freesound_list_view.append_column(_("URI")     , freesound_list_columns.uri);
 		freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
 
-		//freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
+		freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
 		freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
 		freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
 		freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
@@ -712,13 +732,33 @@
 	if (!reset_options ()) {
 		set_response_sensitive (RESPONSE_OK, false);
 	} else {
+
+		string path;
+		path = Glib::get_home_dir();
+		path += "/Freesound/";
+		Mootcher theMootcher(path.c_str()); // XXX should be a member of SoundFileBrowser
+
 		string file;
 
 		TreeView::Selection::ListHandle_Path rows = freesound_list_view.get_selection()->get_selected_rows ();
 
 		if (!rows.empty()) {
 			TreeIter iter = freesound_list->get_iter(*rows.begin());
-			file = (*iter)[freesound_list_columns.pathname];
+
+			string id  = (*iter)[freesound_list_columns.id];
+			string uri = (*iter)[freesound_list_columns.uri];
+			string ofn = (*iter)[freesound_list_columns.filename];
+
+			// download the sound file			
+			GdkCursor *prev_cursor;
+			prev_cursor = gdk_window_get_cursor (get_window()->gobj());
+			gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
+			gdk_flush();
+
+			file = theMootcher.getAudioFile(ofn, id, uri, &progress_bar);
+
+			gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
+
 			chooser.set_filename (file);
 			set_response_sensitive (RESPONSE_OK, true);
 		} else {
@@ -753,43 +793,16 @@
 	}
 }
 
-void*
-freesound_search_thread_entry (void* arg)
-{
-	SessionEvent::create_per_thread_pool ("freesound events", 64);
-
-	static_cast<SoundFileBrowser*>(arg)->freesound_search_thread ();
-
-	return 0;
-}
-
-bool searching = false;
-bool canceling = false;
-
 void
 SoundFileBrowser::freesound_search_clicked ()
 {
-	if (canceling)  //already canceling, button does nothing
-		return;
-
-	if ( searching ) {
-		freesound_search_btn.set_label(_("Cancelling.."));
-		canceling = true;
-	} else {
-		searching = true;
-		freesound_search_btn.set_label(_("Cancel"));
-		pthread_t freesound_thr;
-		pthread_create_and_store ("freesound_search", &freesound_thr, freesound_search_thread_entry, this);
-	}
+	freesound_search();
 }
 
+
 void
-SoundFileBrowser::freesound_search_thread()
+SoundFileBrowser::freesound_search()
 {
-#if 0
-
-	THIS IS ALL TOTALLY THREAD-ILLEGAL ... YOU CANNOT DO GTK STUFF IN THIS THREAD
-
 #ifdef FREESOUND
 	freesound_list->clear();
 
@@ -798,47 +811,80 @@
 	path += "/Freesound/";
 	Mootcher theMootcher(path.c_str());
 
-	string name_string = freesound_name_entry.get_text ();
-	string pass_string = freesound_pass_entry.get_text ();
 	string search_string = freesound_entry.get_text ();
+	enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
+	int page = freesound_page.get_value_as_int();
 
-	if ( theMootcher.doLogin( name_string, pass_string ) ) {
+	GdkCursor *prev_cursor;
+	prev_cursor = gdk_window_get_cursor (get_window()->gobj());
+	gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
+	gdk_flush();
 
-		string theString = theMootcher.searchText(search_string);
+	string theString = theMootcher.searchText(
+		search_string, 
+		page,
+		"", // filter, could do, e.g. "type:wav"
+		sort_method
+	);
 
-		XMLTree doc;
-		doc.read_buffer( theString );
-		XMLNode *root = doc.root();
+	gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
 
-		if (root==NULL) return;
+	XMLTree doc;
+	doc.read_buffer( theString );
+	XMLNode *root = doc.root();
 
-		if ( strcmp(root->name().c_str(), "freesound") == 0) {
+	if (!root) {
+		cerr << "no root XML node!" << endl;
+		return;
+	}
 
-			XMLNode *node = 0;
-			XMLNodeList children = root->children();
-			XMLNodeConstIterator niter;
-			for (niter = children.begin(); niter != children.end() && !canceling; ++niter) {
-				node = *niter;
-				if( strcmp( node->name().c_str(), "sample") == 0 ){
-					XMLProperty *prop=node->property ("id");
-					string filename = theMootcher.getFile( prop->value().c_str() );
-					if ( filename != "" ) {
-						TreeModel::iterator new_row = freesound_list->append();
-						TreeModel::Row row = *new_row;
-						string path = Glib::filename_from_uri (string ("file:") + filename);
-						row[freesound_list_columns.pathname] = path;
-					}
-				}
-			}
+	if ( strcmp(root->name().c_str(), "response") != 0) {
+		cerr << "root node name == " << root->name() << ", != \"response\"!" << endl;
+		return;
+	}
+
+	XMLNode *sounds_root = root->child("sounds");
+	
+	if (!sounds_root) {
+		cerr << "no child node \"sounds\" found!" << endl;
+		return;
+	}
+	
+	XMLNodeList sounds = sounds_root->children();
+	XMLNodeConstIterator niter;
+	XMLNode *node;
+	for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
+		node = *niter;
+		if( strcmp( node->name().c_str(), "resource") != 0 ){
+			cerr << "node->name()=" << node->name() << ",!= \"resource\"!" << endl;
+			continue; // return;
 		}
+
+		// node->dump(cerr, "node:");
+		
+		XMLNode *id_node  = node->child ("id");
+		XMLNode *uri_node = node->child ("serve");
+		XMLNode *ofn_node = node->child ("original_filename");
+
+		if (id_node && uri_node && ofn_node) {
+			
+			std::string  id =  id_node->child("text")->content();
+			std::string uri = uri_node->child("text")->content();
+			std::string ofn = ofn_node->child("text")->content();
+
+			std::string r;
+			// cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << endl;
+
+			TreeModel::iterator new_row = freesound_list->append();
+			TreeModel::Row row = *new_row;
+			
+			row[freesound_list_columns.id      ] = id;
+			row[freesound_list_columns.uri     ] = uri;
+			row[freesound_list_columns.filename] = ofn;
+
+		}
 	}
-
-	searching = false;
-	canceling = false;
-	freesound_search_btn.set_label(_("Start Downloading"));
 #endif
-#endif
-
 }
 
 vector<string>
@@ -874,12 +920,29 @@
 
 		typedef TreeView::Selection::ListHandle_Path ListPath;
 
+		string path;
+		path = Glib::get_home_dir();
+		path += "/Freesound/";
+		Mootcher theMootcher(path.c_str()); // XXX should be a member of SoundFileBrowser
+
+
 		ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
 		for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
 			TreeIter iter = freesound_list->get_iter(*i);
-			string str = (*iter)[freesound_list_columns.pathname];
+			string id  = (*iter)[freesound_list_columns.id];
+			string uri = (*iter)[freesound_list_columns.uri];
+			string ofn = (*iter)[freesound_list_columns.filename];
 
+			GdkCursor *prev_cursor;
+			prev_cursor = gdk_window_get_cursor (get_window()->gobj());
+			gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
+			gdk_flush();
+
+			string str = theMootcher.getAudioFile(ofn, id, uri, &progress_bar);
 			results.push_back (str);
+			
+			gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
+
 		}
 	}
 
Index: gtk2_ardour/sfdb_ui.h
===================================================================
--- gtk2_ardour/sfdb_ui.h	(revision 10499)
+++ gtk2_ardour/sfdb_ui.h	(working copy)
@@ -114,12 +114,24 @@
 		FoundTagColumns() { add(pathname); }
 	};
 
+	class FreesoundColumns : public Gtk::TreeModel::ColumnRecord
+	{
+	  public:
+		Gtk::TreeModelColumn<std::string> id;
+		Gtk::TreeModelColumn<std::string> uri;
+		Gtk::TreeModelColumn<std::string> filename;
+
+		FreesoundColumns() { add(id); add(filename); add(uri); }
+	};
+
 	FoundTagColumns found_list_columns;
 	Glib::RefPtr<Gtk::ListStore> found_list;
 
-	FoundTagColumns freesound_list_columns;
+	FreesoundColumns freesound_list_columns;
 	Glib::RefPtr<Gtk::ListStore> freesound_list;
 
+	Gtk::ProgressBar progress_bar;
+
   public:
 	SoundFileBrowser (Gtk::Window& parent, std::string title, ARDOUR::Session* _s, bool persistent);
 	virtual ~SoundFileBrowser ();
@@ -137,13 +149,14 @@
 	Gtk::Button found_search_btn;
 	Gtk::TreeView found_list_view;
 
-	Gtk::Entry freesound_name_entry;
-	Gtk::Entry freesound_pass_entry;
 	Gtk::Entry freesound_entry;
+	Gtk::ComboBoxText freesound_sort;
+	Gtk::SpinButton freesound_page;
+	
 	Gtk::Button freesound_search_btn;
 	Gtk::TreeView freesound_list_view;
 
-	void freesound_search_thread();
+	void freesound_search();
 
   protected:
 	bool resetting_ourselves;
freesound-new-api-10499.patch (37,904 bytes)   

colinf

2011-11-08 19:02

updater   ~0011954

Last edited: 2011-11-08 19:09

I've attached my current attempt at making this work, just so it's backed up somewhere in case my computer is struck by lightning or something.

There are still plenty of rough edges, and I haven't taken advantage of any of the nice stuff that the new Freesound API offers. However, I think it works more-or-less as well as the old Freesound support ever did.

bugs/wrinkles still remaining:
 - make the displayed data in the freesound tab more useful (we don't need to show the uri to users).
 - sort out oddities with the ProgressBar. It probably needs to be made properly thread-safe: I don't know what happens inside libcurl.
 - the progress bar is also rather arbitrarily placed in the window at the moment: it could probably be put somewhere more logical and/or nicer-looking.
 - sound file info sometimes doesn't get updated on the first click.
 - add a means of cancelling sound file downloads.
 - it uses an API key I registered myself (under an application name of 'test' and with my web site url): I guess someone will need to register a key (or keys) for Ardour. I'm happy to do this, but it might make more sense to do it through a freesound account accessible to one or more main developers.
 - loads of unnecessarily verbose debug output.
 - probably plenty more things wrong.

paul

2011-11-09 11:16

administrator   ~0011959

can i apply this? it contains your freesound credentials...

colinf

2011-11-09 12:42

updater   ~0011963

I suppose Ardour ought to have its own API key: do you have a Freesound account to create one, or should there be an Ardour account too?

paul

2011-11-09 12:46

administrator   ~0011964

i thought the idea was the user logged in themselves?

colinf

2011-11-09 15:16

updater   ~0011965

You may be right: the Freesound web site developer help just says "In order to use the Freesound API you need to be authenticated with an API key", but it's a bit ambiguous whether "use" means writing or running code that uses the API. I'll go & have another read & see if it's made any clearer anywhere else.

colinf

2011-11-10 13:50

updater   ~0011971

Looking at various messages in the Freesound google group, it seems that API keys are 'per-application', not 'per-user', so I guess that Ardour will need one. Shall I apply for one, or will you?

http://groups.google.com/group/freesound-api/browse_thread/thread/027bb502268cac56#
http://groups.google.com/group/freesound-api/browse_thread/thread/9c4280e7bb9df8e8#

paul

2011-11-10 14:01

administrator   ~0011972

colin - it would be great if you could take care of this. thanks.

2011-11-14 11:39

 

freesound-new-api-10577.patch (37,870 bytes)   
Index: gtk2_ardour/wscript
===================================================================
--- gtk2_ardour/wscript	(revision 10573)
+++ gtk2_ardour/wscript	(working copy)
@@ -389,6 +389,7 @@
 
     if bld.is_defined('FREESOUND'):
         obj.source +=  [ 'sfdb_freesound_mootcher.cc' ]
+        obj.defines += [ 'FREESOUND' ]
 
     if bld.is_defined('VST_SUPPORT'):
         obj.source += [ 'vst_pluginui.cc' ]
Index: gtk2_ardour/sfdb_freesound_mootcher.cc
===================================================================
--- gtk2_ardour/sfdb_freesound_mootcher.cc	(revision 10573)
+++ gtk2_ardour/sfdb_freesound_mootcher.cc	(working copy)
@@ -1,6 +1,7 @@
 /* sfdb_freesound_mootcher.cpp **********************************************************************
 
 	Adapted for Ardour by Ben Loftis, March 2008
+	Updated to new Freesound API by Colin Fletcher, November 2011
 
 	Mootcher 23-8-2005
 
@@ -43,37 +44,39 @@
 
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <iostream>
 
 #include "ardour/audio_library.h"
 
-#define TRUE 1
+static const std::string base_url = "http://www.freesound.org/api";
+static const std::string api_key = "9d77cb8d841b4bcfa960e1aae62224eb"; // ardour3
 
+
 //------------------------------------------------------------------------
-Mootcher::	Mootcher(const char *saveLocation)
-	: curl( NULL )
-	, connection( 0 )
+Mootcher::Mootcher(const char *saveLocation)
+	: curl(curl_easy_init())
 {
 	changeWorkingDir(saveLocation);
 };
 //------------------------------------------------------------------------
-Mootcher::	~Mootcher()
+Mootcher:: ~Mootcher()
 {
-	remove( "cookiejar.txt" );
 }
+
 //------------------------------------------------------------------------
 const char* Mootcher::changeWorkingDir(const char *saveLocation)
 {
 	basePath = saveLocation;
 #ifdef __WIN32__
 	std::string replace = "/";
-	int pos = (int)basePath.find("\\");
+	size_t pos = basePath.find("\\");
 	while( pos != std::string::npos ){
 		basePath.replace(pos, 1, replace);
-		pos = (int)basePath.find("\\");
+		pos = basePath.find("\\");
 	}
 #endif
 	//
-	int pos2 = basePath.find_last_of("/");
+	size_t pos2 = basePath.find_last_of("/");
 	if(basePath.length() != (pos2+1)) basePath += "/";
 
 	// create Freesound directory and sound dir
@@ -86,15 +89,12 @@
 }
 
 //------------------------------------------------------------------------
-size_t		Mootcher::WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
+size_t Mootcher::WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
 {
 	register int realsize = (int)(size * nmemb);
 	struct MemoryStruct *mem = (struct MemoryStruct *)data;
 
-	// There might be a realloc() out there that doesn't like
-	// reallocing NULL pointers, so we take care of it here
-	if(mem->memory)	mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1);
-	else			mem->memory = (char *)malloc(mem->size + realsize + 1);
+	mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1);
 
 	if (mem->memory) {
 		memcpy(&(mem->memory[mem->size]), ptr, realsize);
@@ -106,332 +106,183 @@
 
 
 //------------------------------------------------------------------------
-void		Mootcher::toLog(std::string input)
-{
-printf("%s\n", input.c_str());// for debugging
-}
 
+std::string Mootcher::sortMethodString(enum sortMethod sort) {
 
+	switch (sort) {
+		case sort_duration_desc:	return "duration_desc";	
+		case sort_duration_asc: 	return "duration_asc";
+		case sort_created_desc:		return "created_desc";
+		case sort_created_asc:		return "created_asc";
+		case sort_downloads_desc:	return "downloads_desc";
+		case sort_downloads_asc:	return "downloads_asc";
+		case sort_rating_desc:		return "rating_desc";
+		case sort_rating_asc:		return "rating_asc";
+		default:			return "";	
+	}
+}
+
 //------------------------------------------------------------------------
-void		Mootcher::setcUrlOptions()
+void Mootcher::setcUrlOptions()
 {
 	// basic init for curl
 	curl_global_init(CURL_GLOBAL_ALL);
 	// some servers don't like requests that are made without a user-agent field, so we provide one
 	curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
 	// setup curl error buffer
-	CURLcode res = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
-	// always use the cookie with session id which is received at the login
-	curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "cookiejar.txt");
+	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
 	// Allow redirection
 	curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
+	
+	// Allow connections to time out (without using signals)
+	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+	curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10);
+
+
 }
 
-//------------------------------------------------------------------------
-int			Mootcher::doLogin(std::string login, std::string password)
+std::string Mootcher::doRequest(std::string uri, std::string params)
 {
-	if(connection==1)
-		return 1;
-
+	std::string result;
 	struct MemoryStruct xml_page;
 	xml_page.memory = NULL;
 	xml_page.size = 0;
 
-	// create the post message from the login and password
-	std::string postMessage;
-	postMessage += "username=";
-	postMessage += curl_escape(login.c_str(), 0);
-	postMessage += "&password=";
-	postMessage += curl_escape(password.c_str(), 0);
-	postMessage += "&login=";
-	postMessage += curl_escape("1", 0);
-	postMessage += "&redirect=";
-	postMessage += curl_escape("../tests/login.php", 0);
+	setcUrlOptions();
+	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
+	curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &xml_page);
 
-	// Do the setup for libcurl
-	curl = curl_easy_init();
+	// curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
+	// curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postMessage.c_str());
+	// curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1);
 
-	if(curl)
-	{
-		setcUrlOptions();
-		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
-		curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&xml_page);
-		// save the sessoin id that is given back by the server in a cookie
-		curl_easy_setopt(curl, CURLOPT_COOKIEJAR, "cookiejar.txt");
-		// use POST for login variables
-		curl_easy_setopt(curl, CURLOPT_POST, TRUE);
-		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postMessage.c_str());
-		curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1);
+	// the url to get
+	std::string url = base_url + uri + "?";
+	if (params != "") {
+		url += params + "&api_key=" + api_key + "&format=xml";
+	} else {
+		url += "api_key=" + api_key + "&format=xml";
+	}
+		
+	curl_easy_setopt(curl, CURLOPT_URL, url.c_str() );
+	std::cerr << "doRequest: " << url << std::endl;
+	
+	// perform online request
+	CURLcode res = curl_easy_perform(curl);
+	if( res != 0 ) {
+		std::cerr << "curl error " << res << " (" << curl_easy_strerror(res) << ")" << std::endl;
+		return "";
+	}
 
-		// the url to get
-		std::string login_url = "http://www.freesound.org/forum/login.php";
-		curl_easy_setopt(curl, CURLOPT_URL, login_url.c_str() );
+	result = xml_page.memory;
+	// free the memory
+	if(xml_page.memory){
+		free( xml_page.memory );
+		xml_page.memory = NULL;
+		xml_page.size = 0;
+	}
 
-		// perform online request
-		connection = 1;
-		CURLcode res = curl_easy_perform(curl);
-		if( res != 0 ) {
-			toLog("curl login error\n");
-			toLog(curl_easy_strerror(res));
-			connection = 0;
-		}
+	return result;
 
-		if (connection == 1){
-			std::string check_page = xml_page.memory;
-			int test = (int)check_page.find("login");   //logged
-			if(	strcmp(xml_page.memory, "login") == 0 )
-				toLog("Logged in.\n");
-			else {
-				toLog("Login failed: Check username and password.\n");
-				connection = 0;
-			}
-		}
+}
 
-		// free the memory
-		if(xml_page.memory){
-			free( xml_page.memory );
-			xml_page.memory = NULL;
-			xml_page.size = 0;
-		}
 
-		std::cerr << "Login was cool, connection = "  << connection << std::endl;
-		return connection;
-	}
-	else return 3; // will be returned if a curl related problem ocurrs
-}
-//------------------------------------------------------------------------
-std::string	Mootcher::searchText(std::string word)
+std::string Mootcher::searchText(std::string query, int page, std::string filter, enum sortMethod sort)
 {
-	struct MemoryStruct xml_page;
-	xml_page.memory = NULL;
-	xml_page.size = 0;
+	std::string params = "";
+	char buf[24];
 
-	std::string result;
-
-	if(connection != 0)
-	{
-		// create a url encoded post message
-		std::string postMessage;
-		char tempString[ 128 ];
-		char *tempPointer = &tempString[0];
-
-		postMessage = "search=";
-		postMessage += curl_escape(word.c_str(), 0);
-		sprintf( tempPointer, "&searchDescriptions=1");
-		postMessage += tempPointer;
-		sprintf( tempPointer, "&searchtags=1");
-		postMessage += tempPointer;
-
-		// Ref: http://www.freesound.org/forum/viewtopic.php?p=19081
-		// const ORDER_DEFAULT = 0;
-		// const ORDER_DOWNLOADS_DESC = 1;
-		// const ORDER_DOWNLOADS_ASC = 2;
-		// const ORDER_USERNAME_DESC = 3;
-		// const ORDER_USERNAME_ASC = 4;
-		// const ORDER_DATE_DESC = 5;
-		// const ORDER_DATE_ASC = 6;
-		// const ORDER_DURATION_DESC = 7;
-		// const ORDER_DURATION_ASC = 8;
-		// const ORDER_FILEFORMAT_DESC = 9;
-		// const ORDER_FILEFORMAT_ASC = 10;
-		sprintf( tempPointer, "&order=1");
-		postMessage += tempPointer;
-		sprintf( tempPointer, "&start=0");
-		postMessage += tempPointer;
-		sprintf( tempPointer, "&limit=10");
-		postMessage += tempPointer;
-		// The limit of 10 samples is arbitrary, but seems
-		// reasonable in light of the fact that all of the returned
-		// samples get downloaded, and downloads are s-l-o-w.
-
-		if(curl)
-		{
-			// basic init for curl
-			setcUrlOptions();
-			curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
-			curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&xml_page);
-			// setup the post message
-			curl_easy_setopt(curl, CURLOPT_POST, TRUE);
-			curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postMessage.c_str());
-			curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1);
-
-			// the url to get
-			std::string search_url = "http://www.freesound.org/searchTextXML.php";
-			curl_easy_setopt(curl, CURLOPT_URL, search_url.c_str());
-
-			// perform the online search
-			connection = 1;
-			CURLcode res = curl_easy_perform(curl);
-			if( res != 0 ) {
-				toLog("curl login error\n");
-				toLog(curl_easy_strerror(res));
-				connection = 0;
-			}
-
-			result = xml_page.memory;
-			toLog( result.c_str() );
-
-			// free the memory
-			if(xml_page.memory){
-				free( xml_page.memory );
-				xml_page.memory = NULL;
-				xml_page.size = 0;
-			}
-
-		}
+	if (page > 1) {
+		snprintf(buf, 23, "p=%d&", page);
+		params += buf;
 	}
+	
+	params += "q=" + query;	
 
-	return result;
+	if (filter != "")
+		params += "&f=" + filter;
+	
+	if (sort)
+		params += "&s=" + sortMethodString(sort);
+
+	return doRequest("/sounds/search", params);
 }
 
 //------------------------------------------------------------------------
-std::string Mootcher::changeExtension(std::string filename)
+
+std::string Mootcher::getSoundResourceFile(std::string ID)
 {
-	std::string aiff = ".aiff";
-	std::string aif = ".aif";
-	std::string wav = ".wav";
-	std::string mp3 = ".mp3";
-	std::string ogg = ".ogg";
-	std::string flac = ".flac";
 
-	std::string replace = ".xml";
-	int pos = 0;
+	std::string originalSoundURI;
+	std::string audioFileName;
+	std::string xmlFileName;
+	std::string xml;
 
- 	pos = (int)filename.find(aiff);
-	if(pos != std::string::npos) filename.replace(pos, aiff.size(), replace);
- 	pos = (int)filename.find(aif);
-	if(pos != std::string::npos) filename.replace(pos, aif.size(), replace);
- 	pos = (int)filename.find(wav);
-	if(pos != std::string::npos) filename.replace(pos, wav.size(), replace);
- 	pos = (int)filename.find(mp3);
-	if(pos != std::string::npos) filename.replace(pos, mp3.size(), replace);
- 	pos = (int)filename.find(ogg);
-	if(pos != std::string::npos) filename.replace(pos, ogg.size(), replace);
- 	pos = (int)filename.find(flac);
-	if(pos != std::string::npos) filename.replace(pos, flac.size(), replace);
 
-	return filename;
-}
-//------------------------------------------------------------------------
-void		Mootcher::GetXml(std::string ID, struct MemoryStruct &xml_page)
-{
+	std::cerr << "getSoundResourceFile(" << ID << ")" << std::endl;
 
-	if(curl) {
-		setcUrlOptions();
-		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
-		curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&xml_page);
+	// download the xmlfile into xml_page
+	xml = doRequest("/sounds/" + ID, "");
 
-		// URL to get
-		std::string getxml_url = "http://www.freesound.org/samplesViewSingleXML.php?id=";
-		getxml_url += ID;
+	XMLTree doc;
+	doc.read_buffer( xml.c_str() );
+	XMLNode *freesound = doc.root();
 
-		curl_easy_setopt(curl, CURLOPT_URL, getxml_url.c_str() );
+	// if the page is not a valid xml document with a 'freesound' root
+	if (freesound == NULL) {
+		std::cerr << "getSoundResourceFile: There is no valid root in the xml file" << std::endl;
+		return "";
+	}
 
-		// get it!
-		connection = 1;
-		CURLcode res = curl_easy_perform(curl);
-		if( res != 0 ) {
-			toLog("curl login error\n");
-			toLog(curl_easy_strerror(res));
-			connection = 0;
-		}
+	if (strcmp(doc.root()->name().c_str(), "response") != 0) {
+		std::cerr << "getSoundResourceFile: root =" << doc.root()->name() << ", != response" << std::endl;
+		return "";
 	}
-}
-//------------------------------------------------------------------------
-std::string	Mootcher::getXmlFile(std::string ID, int &length)
-{
-	struct MemoryStruct xml_page;
-	xml_page.memory = NULL;
-	xml_page.size = NULL;
 
-	std::string xmlFileName;
-	std::string audioFileName;
-	std::string filename;
+	XMLNode *name = freesound->child("original_filename");
+	XMLNode *filesize = freesound->child("filesize");
 
-	if(connection != 0) {
-		// download the xmlfile into xml_page
-		GetXml(ID, xml_page);
 
-		// if sample ID does not exist on the freesound website
-		if(strcmp(xml_page.memory, "sample non existant") == 0){
-			free( xml_page.memory );
-			sprintf(message, "getXmlFile: sample with ID:%s does not exist!\n", ID.c_str() );
-			toLog(message);
-			return filename;
-		} else {
-			XMLTree doc;
-			doc.read_buffer( xml_page.memory );
-			XMLNode *freesound = doc.root();
+	// get the file name and size from xml file
+	if (name && filesize) {
 
-			// if the page is not a valid xml document with a 'freesound' root
-			if( freesound == NULL){
-				sprintf(message, "getXmlFile: There is no valid root in the xml file");
-				toLog(message);
-			} else {
-				XMLNode *sample = freesound->child("sample");
-				XMLNode *name = NULL;
-				XMLNode *filesize = NULL;
-				if (sample) {
-					name = sample->child("originalFilename");
-					filesize = sample->child("filesize");
-				}
+		audioFileName = basePath + "snd/" + ID + "-" + name->child("text")->content();
 
-				// get the file name and size from xml file
-				if (sample && name && filesize) {
+		// create new filename with the ID number
+		xmlFileName = basePath;
+		xmlFileName += "snd/";
+		xmlFileName += freesound->child("id")->child("text")->content();
+		xmlFileName += "-";
+		xmlFileName += name->child("text")->content();
+		xmlFileName += ".xml";
 
-					audioFileName = name->child("text")->content();
-					sprintf( message, "getXmlFile: %s needs to be downloaded\n", audioFileName.c_str() );
-					toLog(message);
+		// std::cerr << "getSoundResourceFile: saving XML: " << xmlFileName << std::endl;
 
-					length = atoi(filesize->child("text")->content().c_str());
+		// save the xml file to disk
+		doc.write(xmlFileName.c_str());
 
-					// create new filename with the ID number
-					filename = basePath;
-					filename += "snd/";
-					filename += sample->property("id")->value();
-					filename += "-";
-					filename += audioFileName;
-					// change the extention into .xml
-					xmlFileName = changeExtension( filename );
-
-					sprintf(message, "getXmlFile: saving XML: %s\n", xmlFileName.c_str() );
-					toLog(message);
-
-					// save the xml file to disk
-					doc.write(xmlFileName.c_str());
-
-					//store all the tags in the database
-					XMLNode *tags = sample->child("tags");
-					if (tags) {
-						XMLNodeList children = tags->children();
-						XMLNodeConstIterator niter;
-						std::vector<std::string> strings;
-						for (niter = children.begin(); niter != children.end(); ++niter) {
-							XMLNode *node = *niter;
-							if( strcmp( node->name().c_str(), "tag") == 0 ) {
-								XMLNode *text = node->child("text");
-								if (text) strings.push_back(text->content());
-							}
-						}
-						ARDOUR::Library->set_tags (std::string("//")+filename, strings);
-						ARDOUR::Library->save_changes ();
+		//store all the tags in the database
+		XMLNode *tags = freesound->child("tags");
+		if (tags) {
+			XMLNodeList children = tags->children();
+			XMLNodeConstIterator niter;
+			std::vector<std::string> strings;
+			for (niter = children.begin(); niter != children.end(); ++niter) {
+				XMLNode *node = *niter;
+				if( strcmp( node->name().c_str(), "resource") == 0 ) {
+					XMLNode *text = node->child("text");
+					if (text) {
+						// std::cerr << "tag: " << text->content() << std::endl;
+						strings.push_back(text->content());
 					}
 				}
-
-				// clear the memory
-				if(xml_page.memory){
-					free( xml_page.memory );
-					xml_page.memory = NULL;
-					xml_page.size = 0;
-				}
-				return audioFileName;
 			}
+			ARDOUR::Library->set_tags (std::string("//")+audioFileName, strings);
+			ARDOUR::Library->save_changes ();
 		}
 	}
-	else {
-		return audioFileName;
-	}
 
+	return audioFileName;
 }
 
 int audioFileWrite(void *buffer, size_t size, size_t nmemb, void *file)
@@ -440,74 +291,63 @@
 };
 
 //------------------------------------------------------------------------
-std::string	Mootcher::getFile(std::string ID)
+std::string Mootcher::getAudioFile(std::string originalFileName, std::string ID, std::string audioURL, Gtk::ProgressBar *progress_bar)
 {
-	CURLcode result_curl;
 
-	std::string audioFileName;
+	std::string audioFileName = basePath + "snd/" + ID + "-" + originalFileName;
 
-	if(connection != 0)
-	{
-		int length;
-		std::string name = getXmlFile(ID, length);
-		if( name != "" ){
+	//check to see if audio file already exists
+	FILE *testFile = fopen(audioFileName.c_str(), "r");
+	if (testFile) {  
+		fseek (testFile , 0 , SEEK_END);
+		if (ftell (testFile) > 256) {
+			std::cerr << "audio file " << audioFileName << " already exists" << std::endl;
+			fclose (testFile);
+			return audioFileName;
+		}
+		
+		// else file was small, probably an error, delete it and try again
+		fclose(testFile);
+		remove( audioFileName.c_str() );  
+	}
 
-			// create new filename with the ID number
-			audioFileName += basePath;
-			audioFileName += "snd/";
-			audioFileName += ID;
-			audioFileName += "-";
-			audioFileName += name;
+	//now download the actual file
+	if (curl) {
 
-			//check to see if audio file already exists
-			FILE *testFile = fopen(audioFileName.c_str(), "r");
-			if (testFile) {  //TODO:  should also check length to see if file is complete
-				fseek (testFile , 0 , SEEK_END);
-				if (ftell (testFile) == length) {
-					sprintf(message, "%s already exists\n", audioFileName.c_str() );
-					toLog(message);
-					fclose (testFile);
-					return audioFileName;
-				} else {
-					remove( audioFileName.c_str() );  //file was not correct length, delete it and try again
-				}
-			}
+		FILE* theFile;
+		theFile = fopen( audioFileName.c_str(), "wb" );
 
+		if (theFile) {
+		
+			// create the download url
+			audioURL += "?api_key=" + api_key;
+		
+			setcUrlOptions();
+			curl_easy_setopt(curl, CURLOPT_URL, audioURL.c_str() );
+			curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, audioFileWrite);
+			curl_easy_setopt(curl, CURLOPT_WRITEDATA, theFile);
 
-			//now download the actual file
-			if (curl) {
+			std::cerr << "downloading " << audioFileName << " from " << audioURL << "..." << std::endl;
 
-				FILE* theFile;
-				theFile = fopen( audioFileName.c_str(), "wb" );
+			curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 0); // turn on the progress bar
+			curl_easy_setopt (curl, CURLOPT_PROGRESSFUNCTION, progress_callback);
+			curl_easy_setopt (curl, CURLOPT_PROGRESSDATA, progress_bar);
 
-				// create the download url, this url will also update the download statics on the site
-				std::string audioURL;
-				audioURL += "http://www.freesound.org/samplesDownload.php?id=";
-				audioURL += ID;
+			CURLcode res = curl_easy_perform(curl);
+			fclose(theFile);
 
-				setcUrlOptions();
-				curl_easy_setopt(curl, CURLOPT_URL, audioURL.c_str() );
-				curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, audioFileWrite);
-				curl_easy_setopt(curl, CURLOPT_WRITEDATA, theFile);
+			curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 1); // turn off the progress bar
+			progress_bar->set_fraction(0.0);
 
-				connection = 1;
-				CURLcode res = curl_easy_perform(curl);
-				if( res != 0 ) {
-					toLog("curl login error\n");
-					toLog(curl_easy_strerror(res));
-					connection = 0;
-				}
-
-				fclose(theFile);
+			if( res != 0 ) {
+				std::cerr <<  "curl error " << res << " (" << curl_easy_strerror(res) << ")" << std::endl;
+				remove( audioFileName.c_str() );  
+				return "";
+			} else {
+				std::cerr << "done!" << std::endl;
+				// now download the tags &c.
+				getSoundResourceFile(ID);
 			}
-
-/*
-			bar.dlnowMoo = 0;
-			bar.dltotalMoo = 0;
-			curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 0); // turn on the process bar thingy
-			curl_easy_setopt (curl, CURLOPT_PROGRESSFUNCTION, progress_callback);
-			curl_easy_setopt (curl, CURLOPT_PROGRESSDATA, &bar);
-*/
 		}
 	}
 
@@ -517,8 +357,17 @@
 //---------
 int Mootcher::progress_callback(void *bar, double dltotal, double dlnow, double ultotal, double ulnow)
 {
-	struct dlprocess *lbar = (struct dlprocess *) bar;
-	lbar->dltotalMoo = dltotal;
-	lbar->dlnowMoo = dlnow;
+
+	//XXX I hope it's OK to do GTK things in this callback. Otherwise
+	// I'll have to do stuff like in interthread_progress_window.
+	
+	Gtk::ProgressBar *progress_bar = (Gtk::ProgressBar *) bar;
+	progress_bar->set_fraction(dlnow/dltotal);
+	/* Make sure the progress widget gets updated */
+	while (Glib::MainContext::get_default()->iteration (false)) {
+		/* do nothing */
+	}
+	std::cerr << "progress: " << dlnow << " of " << dltotal << " \r";
 	return 0;
 }
+
Index: gtk2_ardour/sfdb_freesound_mootcher.h
===================================================================
--- gtk2_ardour/sfdb_freesound_mootcher.h	(revision 10573)
+++ gtk2_ardour/sfdb_freesound_mootcher.h	(working copy)
@@ -1,6 +1,7 @@
 /*sfdb_freesound_mootcher.h****************************************************************************
 
 	Adapted for Ardour by Ben Loftis, March 2008
+	Updated to new Freesound API by Colin Fletcher, November 2011
 
 	Mootcher Online Access to thefreesoundproject website
 	http://freesound.iua.upf.edu/
@@ -19,60 +20,55 @@
 #include <string>
 #include <sstream>
 #include <vector>
+#include <gtkmm/progressbar.h>
 //#include <ctime>
 
 #include "curl/curl.h"
 
-
-// mootcher version
-#define ___VERSION___ 1.3
-
 //--- struct to store XML file
 struct MemoryStruct {
 	char *memory;
 	size_t size;
 };
 
-//--- for download process viewing
-struct dlprocess {
-	double dltotalMoo;
-	double dlnowMoo;
+enum sortMethod {
+	sort_none,		// no sort
+	sort_duration_desc,	// Sort by the duration of the sounds, longest sounds first.
+	sort_duration_asc, 	// Same as above, but shortest sounds first.
+	sort_created_desc, 	// Sort by the date of when the sound was added. newest sounds first.
+	sort_created_asc, 	// Same as above, but oldest sounds first.
+	sort_downloads_desc, 	// Sort by the number of downloads, most downloaded sounds first.
+	sort_downloads_asc, 	// Same as above, but least downloaded sounds first.
+	sort_rating_desc, 	// Sort by the average rating given to the sounds, highest rated first.
+	sort_rating_asc 	// Same as above, but lowest rated sounds first.
 };
 
+
 class Mootcher
 {
 public:
 	Mootcher(const char *saveLocation);
 	~Mootcher();
 
-	int			doLogin(std::string login, std::string password);
-	std::string	getFile(std::string ID);
-	std::string	searchText(std::string word);
+	std::string	getAudioFile(std::string originalFileName, std::string ID, std::string audioURL, Gtk::ProgressBar *progress_bar);
+	std::string	searchText(std::string query, int page, std::string filter, enum sortMethod sort);
 
-
-	struct dlprocess bar;
-
 private:
 
 	const char*	changeWorkingDir(const char *saveLocation);
 
-	std::string	getXmlFile(std::string ID, int &length);
-	void		GetXml(std::string ID, struct MemoryStruct &xml_page);
-	std::string	changeExtension(std::string filename);
-
-	void		toLog(std::string input);
-
+	std::string	doRequest(std::string uri, std::string params);
 	void		setcUrlOptions();
 
-    static size_t		WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data);
-	static int			progress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
+	static size_t	WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data);
+	static int	progress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
+	std::string	sortMethodString(enum sortMethod sort);
+	std::string	getSoundResourceFile(std::string ID);
 
 	CURL *curl;
 	char errorBuffer[CURL_ERROR_SIZE];	// storage for cUrl error message
 
-	int connection;		// is 0 if no connection
-	char message[128];	// storage for messages that are send to the logfile
-
 	std::string basePath;
 	std::string xmlLocation;
 };
+
Index: gtk2_ardour/sfdb_ui.cc
===================================================================
--- gtk2_ardour/sfdb_ui.cc	(revision 10573)
+++ gtk2_ardour/sfdb_ui.cc	(working copy)
@@ -421,7 +421,7 @@
 	  preview (persistent),
 	  found_search_btn (_("Search")),
 	  found_list_view (found_list),
-	  freesound_search_btn (_("Start Downloading")),
+	  freesound_search_btn (_("Search")),
 	  freesound_list_view (freesound_list)
 {
 	resetting_ourselves = false;
@@ -516,33 +516,53 @@
 		passbox->set_spacing (6);
 
 		label = manage (new Label);
-		label->set_text (_("User:"));
+		label->set_text (_("Tags:"));
 		passbox->pack_start (*label, false, false);
-		passbox->pack_start (freesound_name_entry);
+		passbox->pack_start (freesound_entry, false, false);
+
 		label = manage (new Label);
-		label->set_text (_("Password:"));
+		label->set_text (_("Sort:"));
 		passbox->pack_start (*label, false, false);
-		passbox->pack_start (freesound_pass_entry);
+		passbox->pack_start (freesound_sort, false, false);
+		freesound_sort.clear_items();
+		
+		// Order of the following must correspond with enum sortMethod
+		// in sfdb_freesound_mootcher.h	
+		freesound_sort.append_text(_("None"));
+		freesound_sort.append_text(_("Longest"));
+		freesound_sort.append_text(_("Shortest"));
+		freesound_sort.append_text(_("Newest"));
+		freesound_sort.append_text(_("Oldest"));
+		freesound_sort.append_text(_("Most downloaded"));
+		freesound_sort.append_text(_("Least downloaded"));
+		freesound_sort.append_text(_("Highest rated"));
+		freesound_sort.append_text(_("Lowest rated"));
+		freesound_sort.set_active(0);
+
 		label = manage (new Label);
-		label->set_text (_("Tags:"));
+		label->set_text (_("Page:"));
 		passbox->pack_start (*label, false, false);
-		passbox->pack_start (freesound_entry, false, false);
+		passbox->pack_start (freesound_page, false, false);
+		freesound_page.set_range(1, 1000);
+		freesound_page.set_increments(1, 10);
+		
 		passbox->pack_start (freesound_search_btn, false, false);
-
+		passbox->pack_start (progress_bar);
+		
 		Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
 		scroll->add(freesound_list_view);
 		scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
 
 		vbox = manage(new VBox);
 		vbox->pack_start (*passbox, PACK_SHRINK);
-		vbox->pack_start(*scroll);
+		vbox->pack_start (*scroll);
 
-		//vbox->pack_start (freesound_list_view);
-
-		freesound_list_view.append_column(_("Paths"), freesound_list_columns.pathname);
+		freesound_list_view.append_column(_("ID")      , freesound_list_columns.id);
+		freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
+		freesound_list_view.append_column(_("URI")     , freesound_list_columns.uri);
 		freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
 
-		//freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
+		freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
 		freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
 		freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
 		freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
@@ -712,13 +732,33 @@
 	if (!reset_options ()) {
 		set_response_sensitive (RESPONSE_OK, false);
 	} else {
+
+		string path;
+		path = Glib::get_home_dir();
+		path += "/Freesound/";
+		Mootcher theMootcher(path.c_str()); // XXX should be a member of SoundFileBrowser
+
 		string file;
 
 		TreeView::Selection::ListHandle_Path rows = freesound_list_view.get_selection()->get_selected_rows ();
 
 		if (!rows.empty()) {
 			TreeIter iter = freesound_list->get_iter(*rows.begin());
-			file = (*iter)[freesound_list_columns.pathname];
+
+			string id  = (*iter)[freesound_list_columns.id];
+			string uri = (*iter)[freesound_list_columns.uri];
+			string ofn = (*iter)[freesound_list_columns.filename];
+
+			// download the sound file			
+			GdkCursor *prev_cursor;
+			prev_cursor = gdk_window_get_cursor (get_window()->gobj());
+			gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
+			gdk_flush();
+
+			file = theMootcher.getAudioFile(ofn, id, uri, &progress_bar);
+
+			gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
+
 			chooser.set_filename (file);
 			set_response_sensitive (RESPONSE_OK, true);
 		} else {
@@ -753,43 +793,16 @@
 	}
 }
 
-void*
-freesound_search_thread_entry (void* arg)
-{
-	SessionEvent::create_per_thread_pool ("freesound events", 64);
-
-	static_cast<SoundFileBrowser*>(arg)->freesound_search_thread ();
-
-	return 0;
-}
-
-bool searching = false;
-bool canceling = false;
-
 void
 SoundFileBrowser::freesound_search_clicked ()
 {
-	if (canceling)  //already canceling, button does nothing
-		return;
-
-	if ( searching ) {
-		freesound_search_btn.set_label(_("Cancelling.."));
-		canceling = true;
-	} else {
-		searching = true;
-		freesound_search_btn.set_label(_("Cancel"));
-		pthread_t freesound_thr;
-		pthread_create_and_store ("freesound_search", &freesound_thr, freesound_search_thread_entry, this);
-	}
+	freesound_search();
 }
 
+
 void
-SoundFileBrowser::freesound_search_thread()
+SoundFileBrowser::freesound_search()
 {
-#if 0
-
-	THIS IS ALL TOTALLY THREAD-ILLEGAL ... YOU CANNOT DO GTK STUFF IN THIS THREAD
-
 #ifdef FREESOUND
 	freesound_list->clear();
 
@@ -798,47 +811,80 @@
 	path += "/Freesound/";
 	Mootcher theMootcher(path.c_str());
 
-	string name_string = freesound_name_entry.get_text ();
-	string pass_string = freesound_pass_entry.get_text ();
 	string search_string = freesound_entry.get_text ();
+	enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
+	int page = freesound_page.get_value_as_int();
 
-	if ( theMootcher.doLogin( name_string, pass_string ) ) {
+	GdkCursor *prev_cursor;
+	prev_cursor = gdk_window_get_cursor (get_window()->gobj());
+	gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
+	gdk_flush();
 
-		string theString = theMootcher.searchText(search_string);
+	string theString = theMootcher.searchText(
+		search_string, 
+		page,
+		"", // filter, could do, e.g. "type:wav"
+		sort_method
+	);
 
-		XMLTree doc;
-		doc.read_buffer( theString );
-		XMLNode *root = doc.root();
+	gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
 
-		if (root==NULL) return;
+	XMLTree doc;
+	doc.read_buffer( theString );
+	XMLNode *root = doc.root();
 
-		if ( strcmp(root->name().c_str(), "freesound") == 0) {
+	if (!root) {
+		cerr << "no root XML node!" << endl;
+		return;
+	}
 
-			XMLNode *node = 0;
-			XMLNodeList children = root->children();
-			XMLNodeConstIterator niter;
-			for (niter = children.begin(); niter != children.end() && !canceling; ++niter) {
-				node = *niter;
-				if( strcmp( node->name().c_str(), "sample") == 0 ){
-					XMLProperty *prop=node->property ("id");
-					string filename = theMootcher.getFile( prop->value().c_str() );
-					if ( filename != "" ) {
-						TreeModel::iterator new_row = freesound_list->append();
-						TreeModel::Row row = *new_row;
-						string path = Glib::filename_from_uri (string ("file:") + filename);
-						row[freesound_list_columns.pathname] = path;
-					}
-				}
-			}
+	if ( strcmp(root->name().c_str(), "response") != 0) {
+		cerr << "root node name == " << root->name() << ", != \"response\"!" << endl;
+		return;
+	}
+
+	XMLNode *sounds_root = root->child("sounds");
+	
+	if (!sounds_root) {
+		cerr << "no child node \"sounds\" found!" << endl;
+		return;
+	}
+	
+	XMLNodeList sounds = sounds_root->children();
+	XMLNodeConstIterator niter;
+	XMLNode *node;
+	for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
+		node = *niter;
+		if( strcmp( node->name().c_str(), "resource") != 0 ){
+			cerr << "node->name()=" << node->name() << ",!= \"resource\"!" << endl;
+			continue; // return;
 		}
+
+		// node->dump(cerr, "node:");
+		
+		XMLNode *id_node  = node->child ("id");
+		XMLNode *uri_node = node->child ("serve");
+		XMLNode *ofn_node = node->child ("original_filename");
+
+		if (id_node && uri_node && ofn_node) {
+			
+			std::string  id =  id_node->child("text")->content();
+			std::string uri = uri_node->child("text")->content();
+			std::string ofn = ofn_node->child("text")->content();
+
+			std::string r;
+			// cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << endl;
+
+			TreeModel::iterator new_row = freesound_list->append();
+			TreeModel::Row row = *new_row;
+			
+			row[freesound_list_columns.id      ] = id;
+			row[freesound_list_columns.uri     ] = uri;
+			row[freesound_list_columns.filename] = ofn;
+
+		}
 	}
-
-	searching = false;
-	canceling = false;
-	freesound_search_btn.set_label(_("Start Downloading"));
 #endif
-#endif
-
 }
 
 vector<string>
@@ -874,12 +920,29 @@
 
 		typedef TreeView::Selection::ListHandle_Path ListPath;
 
+		string path;
+		path = Glib::get_home_dir();
+		path += "/Freesound/";
+		Mootcher theMootcher(path.c_str()); // XXX should be a member of SoundFileBrowser
+
+
 		ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
 		for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
 			TreeIter iter = freesound_list->get_iter(*i);
-			string str = (*iter)[freesound_list_columns.pathname];
+			string id  = (*iter)[freesound_list_columns.id];
+			string uri = (*iter)[freesound_list_columns.uri];
+			string ofn = (*iter)[freesound_list_columns.filename];
 
+			GdkCursor *prev_cursor;
+			prev_cursor = gdk_window_get_cursor (get_window()->gobj());
+			gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
+			gdk_flush();
+
+			string str = theMootcher.getAudioFile(ofn, id, uri, &progress_bar);
 			results.push_back (str);
+			
+			gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
+
 		}
 	}
 
Index: gtk2_ardour/sfdb_ui.h
===================================================================
--- gtk2_ardour/sfdb_ui.h	(revision 10573)
+++ gtk2_ardour/sfdb_ui.h	(working copy)
@@ -114,12 +114,24 @@
 		FoundTagColumns() { add(pathname); }
 	};
 
+	class FreesoundColumns : public Gtk::TreeModel::ColumnRecord
+	{
+	  public:
+		Gtk::TreeModelColumn<std::string> id;
+		Gtk::TreeModelColumn<std::string> uri;
+		Gtk::TreeModelColumn<std::string> filename;
+
+		FreesoundColumns() { add(id); add(filename); add(uri); }
+	};
+
 	FoundTagColumns found_list_columns;
 	Glib::RefPtr<Gtk::ListStore> found_list;
 
-	FoundTagColumns freesound_list_columns;
+	FreesoundColumns freesound_list_columns;
 	Glib::RefPtr<Gtk::ListStore> freesound_list;
 
+	Gtk::ProgressBar progress_bar;
+
   public:
 	SoundFileBrowser (Gtk::Window& parent, std::string title, ARDOUR::Session* _s, bool persistent);
 	virtual ~SoundFileBrowser ();
@@ -137,13 +149,14 @@
 	Gtk::Button found_search_btn;
 	Gtk::TreeView found_list_view;
 
-	Gtk::Entry freesound_name_entry;
-	Gtk::Entry freesound_pass_entry;
 	Gtk::Entry freesound_entry;
+	Gtk::ComboBoxText freesound_sort;
+	Gtk::SpinButton freesound_page;
+	
 	Gtk::Button freesound_search_btn;
 	Gtk::TreeView freesound_list_view;
 
-	void freesound_search_thread();
+	void freesound_search();
 
   protected:
 	bool resetting_ourselves;
freesound-new-api-10577.patch (37,870 bytes)   

colinf

2011-11-14 11:44

updater   ~0011991

New version of patch uploaded, the same as the previous except that the API key is now one I've created for Ardour 3. In fact, I registered ardour3 as a Freesound user and created the API key from that account: I hope that was a sensible thing to do.

I hope I'll have a few moments this week to polish some of the other rough edges, but I'm very happy if you want to apply this version in the meanwhile.

paul

2011-11-14 22:08

administrator   ~0012019

committed in rev 10596

2011-12-08 22:23

 

freesound-2011-12-08.patch (7,862 bytes)   
Index: gtk2_ardour/sfdb_freesound_mootcher.cc
===================================================================
--- gtk2_ardour/sfdb_freesound_mootcher.cc	(revision 10941)
+++ gtk2_ardour/sfdb_freesound_mootcher.cc	(working copy)
@@ -136,7 +136,7 @@
 	
 	// Allow connections to time out (without using signals)
 	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
-	curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10);
+	curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);
 
 
 }
@@ -291,7 +291,7 @@
 };
 
 //------------------------------------------------------------------------
-std::string Mootcher::getAudioFile(std::string originalFileName, std::string ID, std::string audioURL, Gtk::ProgressBar *progress_bar)
+std::string Mootcher::getAudioFile(std::string originalFileName, std::string ID, std::string audioURL, SoundFileBrowser *caller)
 {
 
 	std::string audioFileName = basePath + "snd/" + ID + "-" + originalFileName;
@@ -328,17 +328,20 @@
 			curl_easy_setopt(curl, CURLOPT_WRITEDATA, theFile);
 
 			std::cerr << "downloading " << audioFileName << " from " << audioURL << "..." << std::endl;
+			/* hack to get rid of the barber-pole stripes */
+			caller->progress_bar.hide();
+			caller->progress_bar.show();
 
 			curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 0); // turn on the progress bar
 			curl_easy_setopt (curl, CURLOPT_PROGRESSFUNCTION, progress_callback);
-			curl_easy_setopt (curl, CURLOPT_PROGRESSDATA, progress_bar);
+			curl_easy_setopt (curl, CURLOPT_PROGRESSDATA, caller);
 
 			CURLcode res = curl_easy_perform(curl);
 			fclose(theFile);
 
 			curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 1); // turn off the progress bar
-			progress_bar->set_fraction(0.0);
-
+			caller->progress_bar.set_fraction(0.0);
+			
 			if( res != 0 ) {
 				std::cerr <<  "curl error " << res << " (" << curl_easy_strerror(res) << ")" << std::endl;
 				remove( audioFileName.c_str() );  
@@ -355,14 +358,18 @@
 }
 
 //---------
-int Mootcher::progress_callback(void *bar, double dltotal, double dlnow, double ultotal, double ulnow)
+int Mootcher::progress_callback(void *caller, double dltotal, double dlnow, double ultotal, double ulnow)
 {
 
+SoundFileBrowser *sfb = (SoundFileBrowser *) caller;
 	//XXX I hope it's OK to do GTK things in this callback. Otherwise
 	// I'll have to do stuff like in interthread_progress_window.
+	if (sfb->freesound_stop) {
+		return -1;
+	}
 	
-	Gtk::ProgressBar *progress_bar = (Gtk::ProgressBar *) bar;
-	progress_bar->set_fraction(dlnow/dltotal);
+	
+	sfb->progress_bar.set_fraction(dlnow/dltotal);
 	/* Make sure the progress widget gets updated */
 	while (Glib::MainContext::get_default()->iteration (false)) {
 		/* do nothing */
Index: gtk2_ardour/sfdb_freesound_mootcher.h
===================================================================
--- gtk2_ardour/sfdb_freesound_mootcher.h	(revision 10941)
+++ gtk2_ardour/sfdb_freesound_mootcher.h	(working copy)
@@ -23,6 +23,8 @@
 #include <gtkmm/progressbar.h>
 //#include <ctime>
 
+#include "sfdb_ui.h"
+
 #include "curl/curl.h"
 
 //--- struct to store XML file
@@ -50,7 +52,7 @@
 	Mootcher(const char *saveLocation);
 	~Mootcher();
 
-	std::string	getAudioFile(std::string originalFileName, std::string ID, std::string audioURL, Gtk::ProgressBar *progress_bar);
+	std::string	getAudioFile(std::string originalFileName, std::string ID, std::string audioURL, SoundFileBrowser *caller);
 	std::string	searchText(std::string query, int page, std::string filter, enum sortMethod sort);
 
 private:
Index: gtk2_ardour/sfdb_ui.cc
===================================================================
--- gtk2_ardour/sfdb_ui.cc	(revision 10941)
+++ gtk2_ardour/sfdb_ui.cc	(working copy)
@@ -548,6 +548,8 @@
 		
 		passbox->pack_start (freesound_search_btn, false, false);
 		passbox->pack_start (progress_bar);
+		passbox->pack_end   (freesound_stop_btn, false, false);
+		freesound_stop_btn.set_label(_("Stop"));
 		
 		Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
 		scroll->add(freesound_list_view);
@@ -559,13 +561,14 @@
 
 		freesound_list_view.append_column(_("ID")      , freesound_list_columns.id);
 		freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
-		freesound_list_view.append_column(_("URI")     , freesound_list_columns.uri);
+		// freesound_list_view.append_column(_("URI")     , freesound_list_columns.uri);
 		freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
 
 		freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
 		freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
 		freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
 		freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
+		freesound_stop_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_stop_clicked));
 		notebook.append_page (*vbox, _("Search Freesound"));
 	}
 #endif
@@ -756,12 +759,15 @@
 			gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
 			gdk_flush();
 
-			file = theMootcher.getAudioFile(ofn, id, uri, &progress_bar);
+			freesound_stop = false;
+			file = theMootcher.getAudioFile(ofn, id, uri, this);
 
 			gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
 
-			chooser.set_filename (file);
-			set_response_sensitive (RESPONSE_OK, true);
+			if (file != "") {
+				chooser.set_filename (file);
+				set_response_sensitive (RESPONSE_OK, true);
+			}
 		} else {
 			set_response_sensitive (RESPONSE_OK, false);
 		}
@@ -801,7 +807,13 @@
 	freesound_search();
 }
 
+void
+SoundFileBrowser::freesound_stop_clicked ()
+{
+	freesound_stop = true;
+}
 
+
 void
 SoundFileBrowser::freesound_search()
 {
@@ -940,8 +952,11 @@
 			gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
 			gdk_flush();
 
-			string str = theMootcher.getAudioFile(ofn, id, uri, &progress_bar);
-			results.push_back (str);
+			freesound_stop = false;
+			string str = theMootcher.getAudioFile(ofn, id, uri, this);
+			if (str != "") {
+				results.push_back (str);
+			}
 			
 			gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
 
Index: gtk2_ardour/sfdb_ui.h
===================================================================
--- gtk2_ardour/sfdb_ui.h	(revision 10941)
+++ gtk2_ardour/sfdb_ui.h	(working copy)
@@ -26,6 +26,7 @@
 
 #include <sigc++/signal.h>
 
+#include <gtkmm/stock.h>
 #include <gtkmm/box.h>
 #include <gtkmm/button.h>
 #include <gtkmm/checkbutton.h>
@@ -36,7 +37,12 @@
 #include <gtkmm/frame.h>
 #include <gtkmm/label.h>
 #include <gtkmm/textview.h>
+#include <gtkmm/table.h>
+#include <gtkmm/liststore.h>
+#include <gtkmm/spinbutton.h>
+#include <gtkmm/notebook.h>
 
+
 #include "ardour/audiofilesource.h"
 #include "ardour/session_handle.h"
 
@@ -130,7 +136,7 @@
 	FreesoundColumns freesound_list_columns;
 	Glib::RefPtr<Gtk::ListStore> freesound_list;
 
-	Gtk::ProgressBar progress_bar;
+	Gtk::Button freesound_stop_btn;
 
   public:
 	SoundFileBrowser (Gtk::Window& parent, std::string title, ARDOUR::Session* _s, bool persistent);
@@ -155,7 +161,10 @@
 	
 	Gtk::Button freesound_search_btn;
 	Gtk::TreeView freesound_list_view;
+	Gtk::ProgressBar progress_bar;
 
+	bool freesound_stop;
+
 	void freesound_search();
 
   protected:
@@ -189,7 +198,8 @@
 	void freesound_list_view_selected ();
 	void freesound_list_view_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*);
 	void freesound_search_clicked ();
-
+	void freesound_stop_clicked ();
+	
 	void chooser_file_activated ();
 
 	bool on_audio_filter (const Gtk::FileFilter::Info& filter_info);
freesound-2011-12-08.patch (7,862 bytes)   

colinf

2011-12-08 22:33

updater   ~0012328

Attached a patch (freesound-2011-12-08.patch) to address a (very) few of the outstanding annoyances with this. The patch:
 * adds a 'Stop' button.
 * ups the curl timeout to 30 seconds so it now works via my GPRS phone.
 * clears the progress bar barbershop pole pattern after a sound file download (in a very hackish way: sorry).
 * removes the display of the URI in the listbox: only the ID and the file name are displayed now. Maybe some other information could be added, e.g. length, sample rate, &c., if anyone thinks this might be useful.

paul

2012-01-18 18:43

administrator   ~0012567

2011-12-08 patched committed in rev 11265

paul

2012-01-20 11:19

administrator   ~0012590

I'm going to close this bug for now because of the title. I'm sure there are some more issues to be addressed with freesound support, but lets open new bugs for them.

colinf

2015-09-18 15:14

updater   ~0017262

Closing old issues reported by me: these have long since been fixed.

Issue History

Date Modified Username Field Change
2011-03-25 18:28 colinf New Issue
2011-03-25 18:35 cth103 cost => 0.00
2011-03-25 18:35 cth103 Target Version => 3.0-beta1
2011-03-25 20:04 paul Note Added: 0010413
2011-03-25 20:04 paul Status new => confirmed
2011-04-18 23:22 cth103 Target Version 3.0-beta1 => 3.X
2011-11-06 23:52 colinf Note Added: 0011923
2011-11-08 18:52 colinf File Added: freesound-new-api-10499.patch
2011-11-08 19:02 colinf Note Added: 0011954
2011-11-08 19:07 colinf Note Edited: 0011954
2011-11-08 19:09 colinf Note Edited: 0011954
2011-11-09 11:16 paul Note Added: 0011959
2011-11-09 11:16 paul Status confirmed => assigned
2011-11-09 11:16 paul Assigned To => paul
2011-11-09 12:42 colinf Note Added: 0011963
2011-11-09 12:46 paul Note Added: 0011964
2011-11-09 15:16 colinf Note Added: 0011965
2011-11-10 13:50 colinf Note Added: 0011971
2011-11-10 14:01 paul Note Added: 0011972
2011-11-14 11:39 colinf File Added: freesound-new-api-10577.patch
2011-11-14 11:44 colinf Note Added: 0011991
2011-11-14 22:08 paul Note Added: 0012019
2011-12-08 22:23 colinf File Added: freesound-2011-12-08.patch
2011-12-08 22:33 colinf Note Added: 0012328
2012-01-18 18:43 paul Note Added: 0012567
2012-01-20 11:19 paul Note Added: 0012590
2012-01-20 11:19 paul Status assigned => resolved
2012-01-20 11:19 paul Resolution open => fixed
2015-09-18 15:14 colinf Note Added: 0017262
2015-09-18 15:14 colinf Status resolved => closed