Set tooltips on generic UI controls for LV2 plugin controls with documentation (rdfs...
[ardour.git] / gtk2_ardour / sfdb_freesound_mootcher.cc
index 6833bae7684c44320878837fae3958b9bd0b770d..7e13c4f68b285818ec90b23ae13e95898d1654d6 100644 (file)
 #include "sfdb_freesound_mootcher.h"\r
 \r
 #include "pbd/xml++.h"\r
+#include "pbd/filesystem.h"\r
 \r
 #include <sys/stat.h>\r
 #include <sys/types.h>\r
 #include <iostream>\r
 \r
+#include <glib.h>\r
+#include <glib/gstdio.h>\r
+\r
+#include "i18n.h"\r
+\r
 #include "ardour/audio_library.h"\r
 \r
 static const std::string base_url = "http://www.freesound.org/api";\r
@@ -53,18 +59,21 @@ static const std::string api_key = "9d77cb8d841b4bcfa960e1aae62224eb"; // ardour
 \r
 \r
 //------------------------------------------------------------------------\r
-Mootcher::Mootcher(const char *saveLocation)\r
+Mootcher::Mootcher()\r
        : curl(curl_easy_init())\r
 {\r
-       changeWorkingDir(saveLocation);\r
+       std::string path;\r
+       path = Glib::get_home_dir() + "/Freesound/";\r
+       changeWorkingDir ( path.c_str() );\r
 };\r
 //------------------------------------------------------------------------\r
 Mootcher:: ~Mootcher()\r
 {\r
+       curl_easy_cleanup(curl);\r
 }\r
 \r
 //------------------------------------------------------------------------\r
-const char* Mootcher::changeWorkingDir(const char *saveLocation)\r
+void Mootcher::changeWorkingDir(const char *saveLocation)\r
 {\r
        basePath = saveLocation;\r
 #ifdef __WIN32__\r
@@ -78,15 +87,17 @@ const char* Mootcher::changeWorkingDir(const char *saveLocation)
        //\r
        size_t pos2 = basePath.find_last_of("/");\r
        if(basePath.length() != (pos2+1)) basePath += "/";\r
+}\r
 \r
-       // create Freesound directory and sound dir\r
-       std::string sndLocation = basePath;\r
-       mkdir(sndLocation.c_str(), 0777);\r
-       sndLocation += "snd";\r
-       mkdir(sndLocation.c_str(), 0777);\r
-\r
-       return basePath.c_str();\r
+void Mootcher::ensureWorkingDir ()\r
+{\r
+       PBD::sys::path p = basePath;\r
+       p /= "snd";\r
+       if (!PBD::sys::is_directory (p)) {\r
+               PBD::sys::create_directories (p);\r
+       }\r
 }\r
+       \r
 \r
 //------------------------------------------------------------------------\r
 size_t Mootcher::WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)\r
@@ -108,6 +119,8 @@ size_t Mootcher::WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void
 //------------------------------------------------------------------------\r
 \r
 std::string Mootcher::sortMethodString(enum sortMethod sort) {\r
+// given a sort type, returns the string value to be passed to the API to\r
+// sort the results in the requested way.\r
 \r
        switch (sort) {\r
                case sort_duration_desc:        return "duration_desc"; \r
@@ -136,7 +149,7 @@ void Mootcher::setcUrlOptions()
        \r
        // Allow connections to time out (without using signals)\r
        curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);\r
-       curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10);\r
+       curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);\r
 \r
 \r
 }\r
@@ -174,16 +187,16 @@ std::string Mootcher::doRequest(std::string uri, std::string params)
                return "";\r
        }\r
 \r
-       result = xml_page.memory;\r
        // free the memory\r
-       if(xml_page.memory){\r
-               free( xml_page.memory );\r
-               xml_page.memory = NULL;\r
-               xml_page.size = 0;\r
+       if (xml_page.memory) {\r
+               result = xml_page.memory;\r
        }\r
+       \r
+       free (xml_page.memory);\r
+       xml_page.memory = NULL;\r
+       xml_page.size = 0;\r
 \r
        return result;\r
-\r
 }\r
 \r
 \r
@@ -205,6 +218,8 @@ std::string Mootcher::searchText(std::string query, int page, std::string filter
        if (sort)\r
                params += "&s=" + sortMethodString(sort);\r
 \r
+       params += "&fields=id,original_filename,duration,serve";        \r
+\r
        return doRequest("/sounds/search", params);\r
 }\r
 \r
@@ -215,7 +230,6 @@ std::string Mootcher::getSoundResourceFile(std::string ID)
 \r
        std::string originalSoundURI;\r
        std::string audioFileName;\r
-       std::string xmlFileName;\r
        std::string xml;\r
 \r
 \r
@@ -240,27 +254,12 @@ std::string Mootcher::getSoundResourceFile(std::string ID)
        }\r
 \r
        XMLNode *name = freesound->child("original_filename");\r
-       XMLNode *filesize = freesound->child("filesize");\r
-\r
 \r
        // get the file name and size from xml file\r
-       if (name && filesize) {\r
+       if (name) {\r
 \r
                audioFileName = basePath + "snd/" + ID + "-" + name->child("text")->content();\r
 \r
-               // create new filename with the ID number\r
-               xmlFileName = basePath;\r
-               xmlFileName += "snd/";\r
-               xmlFileName += freesound->child("id")->child("text")->content();\r
-               xmlFileName += "-";\r
-               xmlFileName += name->child("text")->content();\r
-               xmlFileName += ".xml";\r
-\r
-               // std::cerr << "getSoundResourceFile: saving XML: " << xmlFileName << std::endl;\r
-\r
-               // save the xml file to disk\r
-               doc.write(xmlFileName.c_str());\r
-\r
                //store all the tags in the database\r
                XMLNode *tags = freesound->child("tags");\r
                if (tags) {\r
@@ -291,13 +290,13 @@ int audioFileWrite(void *buffer, size_t size, size_t nmemb, void *file)
 };\r
 \r
 //------------------------------------------------------------------------\r
-std::string Mootcher::getAudioFile(std::string originalFileName, std::string ID, std::string audioURL, Gtk::ProgressBar *progress_bar)\r
+std::string Mootcher::getAudioFile(std::string originalFileName, std::string ID, std::string audioURL, SoundFileBrowser *caller)\r
 {\r
-\r
+       ensureWorkingDir();\r
        std::string audioFileName = basePath + "snd/" + ID + "-" + originalFileName;\r
 \r
-       //check to see if audio file already exists\r
-       FILE *testFile = fopen(audioFileName.c_str(), "r");\r
+       // check to see if audio file already exists\r
+       FILE *testFile = g_fopen(audioFileName.c_str(), "r");\r
        if (testFile) {  \r
                fseek (testFile , 0 , SEEK_END);\r
                if (ftell (testFile) > 256) {\r
@@ -311,58 +310,77 @@ std::string Mootcher::getAudioFile(std::string originalFileName, std::string ID,
                remove( audioFileName.c_str() );  \r
        }\r
 \r
+       if (!curl) {\r
+               return "";\r
+       }\r
+\r
+       //if already canceling a previous download, bail out here  ( this can happen b/c getAudioFile gets called by various UI update funcs )\r
+       if ( caller->freesound_download_cancel ) {\r
+               return "";\r
+       }\r
+       \r
        //now download the actual file\r
-       if (curl) {\r
+       FILE* theFile;\r
+       theFile = g_fopen( audioFileName.c_str(), "wb" );\r
 \r
-               FILE* theFile;\r
-               theFile = fopen( audioFileName.c_str(), "wb" );\r
+       if (!theFile) {\r
+               return "";\r
+       }\r
+       \r
+       // create the download url\r
+       audioURL += "?api_key=" + api_key;\r
 \r
-               if (theFile) {\r
-               \r
-                       // create the download url\r
-                       audioURL += "?api_key=" + api_key;\r
-               \r
-                       setcUrlOptions();\r
-                       curl_easy_setopt(curl, CURLOPT_URL, audioURL.c_str() );\r
-                       curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, audioFileWrite);\r
-                       curl_easy_setopt(curl, CURLOPT_WRITEDATA, theFile);\r
-\r
-                       std::cerr << "downloading " << audioFileName << " from " << audioURL << "..." << std::endl;\r
-\r
-                       curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 0); // turn on the progress bar\r
-                       curl_easy_setopt (curl, CURLOPT_PROGRESSFUNCTION, progress_callback);\r
-                       curl_easy_setopt (curl, CURLOPT_PROGRESSDATA, progress_bar);\r
-\r
-                       CURLcode res = curl_easy_perform(curl);\r
-                       fclose(theFile);\r
-\r
-                       curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 1); // turn off the progress bar\r
-                       progress_bar->set_fraction(0.0);\r
-\r
-                       if( res != 0 ) {\r
-                               std::cerr <<  "curl error " << res << " (" << curl_easy_strerror(res) << ")" << std::endl;\r
-                               remove( audioFileName.c_str() );  \r
-                               return "";\r
-                       } else {\r
-                               std::cerr << "done!" << std::endl;\r
-                               // now download the tags &c.\r
-                               getSoundResourceFile(ID);\r
-                       }\r
-               }\r
+       setcUrlOptions();\r
+       curl_easy_setopt(curl, CURLOPT_URL, audioURL.c_str() );\r
+       curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, audioFileWrite);\r
+       curl_easy_setopt(curl, CURLOPT_WRITEDATA, theFile);\r
+\r
+       std::cerr << "downloading " << audioFileName << " from " << audioURL << "..." << std::endl;\r
+       /* hack to get rid of the barber-pole stripes */\r
+       caller->freesound_progress_bar.hide();\r
+       caller->freesound_progress_bar.show();\r
+\r
+       std::string prog;\r
+       prog = string_compose (_("%1: [Stop]->"), originalFileName);\r
+       caller->freesound_progress_bar.set_text(prog);\r
+\r
+       curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 0); // turn on the progress bar\r
+       curl_easy_setopt (curl, CURLOPT_PROGRESSFUNCTION, progress_callback);\r
+       curl_easy_setopt (curl, CURLOPT_PROGRESSDATA, caller);\r
+\r
+       CURLcode res = curl_easy_perform(curl);\r
+       fclose(theFile);\r
+\r
+       curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 1); // turn off the progress bar\r
+       caller->freesound_progress_bar.set_fraction(0.0);\r
+       caller->freesound_progress_bar.set_text("");\r
+       \r
+       if( res != 0 ) {\r
+               std::cerr <<  "curl error " << res << " (" << curl_easy_strerror(res) << ")" << std::endl;\r
+               remove( audioFileName.c_str() );  \r
+               return "";\r
+       } else {\r
+               std::cerr << "done!" << std::endl;\r
+               // now download the tags &c.\r
+               getSoundResourceFile(ID);\r
        }\r
 \r
        return audioFileName;\r
 }\r
 \r
 //---------\r
-int Mootcher::progress_callback(void *bar, double dltotal, double dlnow, double ultotal, double ulnow)\r
+int Mootcher::progress_callback(void *caller, double dltotal, double dlnow, double ultotal, double ulnow)\r
 {\r
 \r
+SoundFileBrowser *sfb = (SoundFileBrowser *) caller;\r
        //XXX I hope it's OK to do GTK things in this callback. Otherwise\r
        // I'll have to do stuff like in interthread_progress_window.\r
+       if (sfb->freesound_download_cancel) {\r
+               return -1;\r
+       }\r
+       \r
        \r
-       Gtk::ProgressBar *progress_bar = (Gtk::ProgressBar *) bar;\r
-       progress_bar->set_fraction(dlnow/dltotal);\r
+       sfb->freesound_progress_bar.set_fraction(dlnow/dltotal);\r
        /* Make sure the progress widget gets updated */\r
        while (Glib::MainContext::get_default()->iteration (false)) {\r
                /* do nothing */\r