fix meter(s) when mixer-strip is switched to AuxSend
[ardour.git] / gtk2_ardour / sfdb_freesound_mootcher.cc
index e8b44ff4a790a9401471811eacf2640f812dce27..e1501460cadd682e0c762c58d1cc78b0b29c7a72 100644 (file)
@@ -54,6 +54,8 @@
 \r
 #include "ardour/audio_library.h"\r
 #include "ardour/rc_configuration.h"\r
+#include "pbd/pthread_utils.h"\r
+#include "gui_thread.h"\r
 \r
 using namespace PBD;\r
 \r
@@ -89,7 +91,7 @@ void Mootcher::ensureWorkingDir ()
                }\r
        }\r
        basePath = p;\r
-#ifdef __WIN32__\r
+#ifdef PLATFORM_WINDOWS\r
        std::string replace = "/";\r
        size_t pos = basePath.find("\\");\r
        while( pos != std::string::npos ){\r
@@ -119,7 +121,8 @@ size_t Mootcher::WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void
 \r
 //------------------------------------------------------------------------\r
 \r
-std::string Mootcher::sortMethodString(enum sortMethod sort) {\r
+std::string Mootcher::sortMethodString(enum sortMethod sort)\r
+{\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
@@ -200,6 +203,18 @@ std::string Mootcher::doRequest(std::string uri, std::string params)
 }\r
 \r
 \r
+std::string Mootcher::searchSimilar(std::string id)\r
+{\r
+       std::string params = "";\r
+\r
+       params += "&fields=id,original_filename,duration,filesize,samplerate,license,serve";\r
+       params += "&num_results=100";\r
+\r
+       return doRequest("/sounds/" + id + "/similar", params);\r
+}\r
+\r
+//------------------------------------------------------------------------\r
+\r
 std::string Mootcher::searchText(std::string query, int page, std::string filter, enum sortMethod sort)\r
 {\r
        std::string params = "";\r
@@ -294,9 +309,60 @@ 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, SoundFileBrowser *caller)\r
+\r
+void *\r
+Mootcher::threadFunc() {\r
+CURLcode res;\r
+\r
+       res = curl_easy_perform (curl);\r
+       fclose (theFile);\r
+       curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 1); // turn off the progress bar\r
+       \r
+       if (res != CURLE_OK) {\r
+               /* it's not an error if the user pressed the stop button */\r
+               if (res != CURLE_ABORTED_BY_CALLBACK) {\r
+                       error <<  string_compose (_("curl error %1 (%2)"), res, curl_easy_strerror(res)) << endmsg;\r
+               }\r
+               remove ( (audioFileName+".part").c_str() );  \r
+       } else {\r
+               rename ( (audioFileName+".part").c_str(), audioFileName.c_str() );\r
+               // now download the tags &c.\r
+               getSoundResourceFile(ID);\r
+       }\r
+\r
+       return (void *) res;\r
+}\r
\r
+void\r
+Mootcher::doneWithMootcher()\r
+{\r
+\r
+       // update the sound info pane if the selection in the list box is still us \r
+       sfb->refresh_display(ID, audioFileName);\r
+\r
+       delete this; // this should be OK to do as long as Progress and Finished signals are always received in the order in which they are emitted\r
+}\r
+\r
+static void *\r
+freesound_download_thread_func(void *arg) \r
+{ \r
+       Mootcher *thisMootcher = (Mootcher *) arg;\r
+       void *res;\r
+\r
+       // std::cerr << "freesound_download_thread_func(" << arg << ")" << std::endl;\r
+       res = thisMootcher->threadFunc();\r
+\r
+       thisMootcher->Finished(); /* EMIT SIGNAL */\r
+       return res;\r
+}\r
+\r
+\r
+//------------------------------------------------------------------------\r
+\r
+bool Mootcher::checkAudioFile(std::string originalFileName, std::string theID)\r
 {\r
        ensureWorkingDir();\r
+       ID = theID;\r
        audioFileName = Glib::build_filename (basePath, ID + "-" + originalFileName);\r
 \r
        // check to see if audio file already exists\r
@@ -305,29 +371,31 @@ std::string Mootcher::getAudioFile(std::string originalFileName, std::string ID,
                fseek (testFile , 0 , SEEK_END);\r
                if (ftell (testFile) > 256) {\r
                        fclose (testFile);\r
-                       return audioFileName;\r
+                       return true;\r
                }\r
                \r
-               // else file was small, probably an error, delete it and try again\r
+               // else file was small, probably an error, delete it \r
                fclose(testFile);\r
                remove( audioFileName.c_str() );  \r
        }\r
+       return false;\r
+}\r
 \r
-       if (!curl) {\r
-               return "";\r
-       }\r
 \r
-       // if already cancelling 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
+bool Mootcher::fetchAudioFile(std::string originalFileName, std::string theID, std::string audioURL, SoundFileBrowser *caller)\r
+{\r
+       ensureWorkingDir();\r
+       ID = theID;\r
+       audioFileName = Glib::build_filename (basePath, ID + "-" + originalFileName);\r
+\r
+       if (!curl) {\r
+               return false;\r
        }\r
-       \r
        // now download the actual file\r
-       FILE* theFile;\r
-       theFile = g_fopen( audioFileName.c_str(), "wb" );\r
+       theFile = g_fopen( (audioFileName + ".part").c_str(), "wb" );\r
 \r
        if (!theFile) {\r
-               return "";\r
+               return false;\r
        }\r
        \r
        // create the download url\r
@@ -338,57 +406,59 @@ std::string Mootcher::getAudioFile(std::string originalFileName, std::string ID,
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, audioFileWrite);\r
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, theFile);\r
 \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"), originalFileName);\r
-       caller->freesound_progress_bar.set_text(prog);\r
+       progress_bar.set_text(prog);\r
+\r
+       Gtk::VBox *freesound_vbox = dynamic_cast<Gtk::VBox *> (caller->notebook.get_nth_page(2));\r
+       freesound_vbox->pack_start(progress_hbox, Gtk::PACK_SHRINK);\r
+       progress_hbox.show();\r
+       cancel_download = false;\r
+       sfb = caller;\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
+       curl_easy_setopt (curl, CURLOPT_PROGRESSDATA, this);\r
 \r
-       CURLcode res = curl_easy_perform(curl);\r
-       fclose(theFile);\r
+       Progress.connect(*this, invalidator (*this), boost::bind(&Mootcher::updateProgress, this, _1, _2), gui_context());\r
+       Finished.connect(*this, invalidator (*this), boost::bind(&Mootcher::doneWithMootcher, this), gui_context());\r
+       pthread_t freesound_download_thread;\r
+       pthread_create_and_store("freesound_import", &freesound_download_thread, freesound_download_thread_func, this);\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
-               /* it's not an error if the user pressed the stop button */\r
-               if (res != CURLE_ABORTED_BY_CALLBACK) {\r
-                       error <<  string_compose (_("curl error %1 (%2)"), res, curl_easy_strerror(res)) << endmsg;\r
+       return true;\r
+}\r
+\r
+//---------\r
+\r
+void \r
+Mootcher::updateProgress(double dlnow, double dltotal) \r
+{\r
+       if (dltotal > 0) {\r
+               double fraction = dlnow / dltotal;\r
+               // std::cerr << "progress idle: " << progress->bar->get_text() << ". " << progress->dlnow << " / " << progress->dltotal << " = " << fraction << std::endl;\r
+               if (fraction > 1.0) {\r
+                       fraction = 1.0;\r
+               } else if (fraction < 0.0) {\r
+                       fraction = 0.0;\r
                }\r
-               remove( audioFileName.c_str() );  \r
-               return "";\r
-       } else {\r
-               // now download the tags &c.\r
-               getSoundResourceFile(ID);\r
+               progress_bar.set_fraction(fraction);\r
        }\r
-\r
-       return audioFileName;\r
 }\r
 \r
-//---------\r
-int Mootcher::progress_callback(void *caller, double dltotal, double dlnow, double /*ultotal*/, double /*ulnow*/)\r
+int \r
+Mootcher::progress_callback(void *caller, double dltotal, double dlnow, double /*ultotal*/, double /*ulnow*/)\r
 {\r
+       // It may seem curious to pass a pointer to an instance of an object to a static\r
+       // member function, but we can't use a normal member function as a curl progress callback,\r
+       // and we want access to some private members of Mootcher.\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
+       Mootcher *thisMootcher = (Mootcher *) caller;\r
        \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
+       if (thisMootcher->cancel_download) {\r
+               return -1;\r
        }\r
+\r
+       thisMootcher->Progress(dlnow, dltotal); /* EMIT SIGNAL */\r
        return 0;\r
 }\r
 \r