View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0005383 | ardour | other | public | 2013-03-14 14:04 | 2020-04-19 20:16 |
| Reporter | colinf | Assigned To | colinf | ||
| Priority | normal | Severity | minor | Reproducibility | N/A |
| Status | closed | Resolution | fixed | ||
| Summary | 0005383: Request from freesound.org regarding API usage | ||||
| Description | I just received a message from Frederic at Freesound about Ardour's usage of their API - I used my email address when I registered the account that Ardour uses. He suggests a few ways in which Ardour could make better use of the API: I think we may be hammering their servers a bit. I've copied the message in "Additional Information" below. | ||||
| Additional Information | Here's the message I received: From: frederic.font To: ardour3 Date: March 14th, 2013 Subject: Ardour api usage Hello, I'm the main responsible for the development of the Freesound API and I have some suggestions about how Ardour3 uses the Freesound API in the import functionality. Well, first of all it is very nice that you integrated it in ardour! I just want to suggest some improvements that can make the requests faster. 1) When you do a search request you can add a parameter called "fields" to specify which information should be returned from every sound (http://www.freesound.org/docs/api/resources.html#sound-search-resource). Given that in your interface you only show filename, duration, samplerate and format (I might be missing some), you could restrict the request so it only returns these fields and there is less data to be transmitted. I guess that you also need the serve url to download the sounds so you also need that. 2) When you start searching you keep on requesting for all pages until users press "stop" or leave the window. Well, we don't like that behaviour because probably a lot of data is transmitted which is unnecessary. For that reason we would suggest to only retrieve a few pages and then stop unless user specifies she wants more sounds. If you limit the fields returned in every request as I suggested in "1)", you can also try to raise a bit the number of sounds per page (check the docs, its another parameter) so with less requests you get more sounds (the maximum is 100). 3) You could consider including our similarity search functionality which, given an example sound from freesound, returns more similar sounds based on content similarity (low-level features). That is all for the moment! frederic | ||||
| Tags | No tags attached. | ||||
|
|
As far as I can see, (1) above is already implemented in commit 164db566. |
|
|
I have changes to fix (2) in a local git branch now, too. Hopefully I can push them somewhere that the rest of the world can see... |
|
2013-03-16 15:23
|
freesound-tweaks-5853.diff (23,596 bytes)
commit 03bd2c5556c7d64b2a706642f29d05ba97432958
Author: Colin Fletcher <colin.m.fletcher@googlemail.com>
Date: Fri Mar 15 19:59:19 2013 +0000
Freesound fixes for #5853, and a few other small improvements
Add a 'More' button to load the next page of results without clearing the already-found list.
Don't allow cancellation of searches, and don't update progress bar around searches, since we only get one page at a time now.
Show number of pages of results remaining to download in the tooltip of the 'More' button.
Use a new Mootcher object for each request, to avoid bad things happening when clicking in the Freesound search results list while a search or file download is already in progress.
Make the 'Stop' button insensitive except when it will actually stop the download of a sound file.
Only retrieve one page worth of data per search, rather than looping to get all pages.
Don't show an error in the log window if the user cancelled download.
Request 100 items per page, rather than the default 30.
Fix DOS line endings.
diff --git a/gtk2_ardour/sfdb_freesound_mootcher.cc b/gtk2_ardour/sfdb_freesound_mootcher.cc
index ed1e2ab..e46fb12 100644
--- a/gtk2_ardour/sfdb_freesound_mootcher.cc
+++ b/gtk2_ardour/sfdb_freesound_mootcher.cc
@@ -226,6 +226,7 @@ std::string Mootcher::searchText(std::string query, int page, std::string filter
params += "&s=" + sortMethodString(sort);
params += "&fields=id,original_filename,duration,filesize,samplerate,license,serve";
+ params += "&sounds_per_page=100";
return doRequest("/sounds/search", params);
}
@@ -318,12 +319,12 @@ std::string Mootcher::getAudioFile(std::string originalFileName, std::string ID,
return "";
}
- //if already canceling a previous download, bail out here ( this can happen b/c getAudioFile gets called by various UI update funcs )
+ // if already cancelling a previous download, bail out here ( this can happen b/c getAudioFile gets called by various UI update funcs )
if ( caller->freesound_download_cancel ) {
return "";
}
- //now download the actual file
+ // now download the actual file
FILE* theFile;
theFile = g_fopen( audioFileName.c_str(), "wb" );
@@ -359,7 +360,10 @@ std::string Mootcher::getAudioFile(std::string originalFileName, std::string ID,
caller->freesound_progress_bar.set_text("");
if( res != 0 ) {
- error << string_compose (_("curl error %1 (%2)"), res, curl_easy_strerror(res)) << endmsg;
+ /* it's not an error if the user pressed the stop button */
+ if (res != CURLE_ABORTED_BY_CALLBACK) {
+ error << string_compose (_("curl error %1 (%2)"), res, curl_easy_strerror(res)) << endmsg;
+ }
remove( audioFileName.c_str() );
return "";
} else {
diff --git a/gtk2_ardour/sfdb_freesound_mootcher.h b/gtk2_ardour/sfdb_freesound_mootcher.h
index 40b67b9..7e39ba4 100644
--- a/gtk2_ardour/sfdb_freesound_mootcher.h
+++ b/gtk2_ardour/sfdb_freesound_mootcher.h
@@ -17,80 +17,80 @@
*/
-/*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/
-
- GPL 2005 Jorn Lemon
- mail for questions/remarks: mootcher@twistedlemon.nl
- or go to the freesound website forum
-
-*****************************************************************************/
-
-#include <string>
-#include <fstream>
-#include <iostream>
-#include <stdio.h>
-#include <cstring>
-#include <string>
-#include <sstream>
-#include <vector>
-#include <gtkmm/progressbar.h>
-//#include <ctime>
-
-#include "sfdb_ui.h"
-
-#include "curl/curl.h"
-
-//--- struct to store XML file
-struct MemoryStruct {
- char *memory;
- size_t size;
-};
-
-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();
- ~Mootcher();
-
- 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:
-
- void changeWorkingDir(const char *saveLocation);
- void ensureWorkingDir();
-
- 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);
- std::string sortMethodString(enum sortMethod sort);
- std::string getSoundResourceFile(std::string ID);
-
- CURL *curl;
- char errorBuffer[CURL_ERROR_SIZE]; // storage for cUrl error message
-
- std::string basePath;
- std::string xmlLocation;
-};
-
+/*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/
+
+ GPL 2005 Jorn Lemon
+ mail for questions/remarks: mootcher@twistedlemon.nl
+ or go to the freesound website forum
+
+*****************************************************************************/
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <stdio.h>
+#include <cstring>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <gtkmm/progressbar.h>
+//#include <ctime>
+
+#include "sfdb_ui.h"
+
+#include "curl/curl.h"
+
+//--- struct to store XML file
+struct MemoryStruct {
+ char *memory;
+ size_t size;
+};
+
+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();
+ ~Mootcher();
+
+ 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:
+
+ void changeWorkingDir(const char *saveLocation);
+ void ensureWorkingDir();
+
+ 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);
+ std::string sortMethodString(enum sortMethod sort);
+ std::string getSoundResourceFile(std::string ID);
+
+ CURL *curl;
+ char errorBuffer[CURL_ERROR_SIZE]; // storage for cUrl error message
+
+ std::string basePath;
+ std::string xmlLocation;
+};
+
diff --git a/gtk2_ardour/sfdb_ui.cc b/gtk2_ardour/sfdb_ui.cc
index 1566d08..20c2875 100644
--- a/gtk2_ardour/sfdb_ui.cc
+++ b/gtk2_ardour/sfdb_ui.cc
@@ -520,8 +520,6 @@ SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persi
//add freesound search
- mootcher = new Mootcher();
-
HBox* passbox;
Label* label;
@@ -553,8 +551,13 @@ SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persi
freesound_sort.set_active(0);
passbox->pack_start (freesound_search_btn, false, false);
+ passbox->pack_start (freesound_more_btn, false, false);
+ freesound_more_btn.set_label(_("More"));
+ freesound_more_btn.set_sensitive(false);
+
passbox->pack_end (freesound_stop_btn, false, false);
freesound_stop_btn.set_label(_("Stop"));
+ freesound_stop_btn.set_sensitive(false);
scroll = manage(new ScrolledWindow);
scroll->add(freesound_list_view);
@@ -586,6 +589,7 @@ SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persi
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_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
freesound_stop_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_stop_clicked));
notebook.append_page (*vbox, _("Search Freesound"));
#endif
@@ -802,12 +806,13 @@ void
SoundFileBrowser::freesound_list_view_selected ()
{
freesound_download_cancel = false;
+ freesound_stop_btn.set_sensitive(true);
#ifdef FREESOUND
if (!reset_options ()) {
set_action_sensitive (false);
} else {
-
+ Mootcher mootcher;
string file;
TreeView::Selection::ListHandle_Path rows = freesound_list_view.get_selection()->get_selected_rows ();
@@ -825,7 +830,7 @@ SoundFileBrowser::freesound_list_view_selected ()
gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
gdk_flush();
- file = mootcher->getAudioFile(ofn, id, uri, this);
+ file = mootcher.getAudioFile(ofn, id, uri, this);
gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
@@ -843,6 +848,7 @@ SoundFileBrowser::freesound_list_view_selected ()
preview.setup_labels (file);
}
#endif
+ freesound_stop_btn.set_sensitive(false);
}
void
@@ -872,15 +878,26 @@ SoundFileBrowser::found_search_clicked ()
void
SoundFileBrowser::freesound_search_clicked ()
{
- freesound_search_cancel = false;
+ freesound_page = 1;
+ freesound_list->clear();
+ matches = 0;
+ freesound_search();
+}
+
+void
+SoundFileBrowser::freesound_more_clicked ()
+{
+ char row_path[21];
+ freesound_page++;
freesound_search();
+ snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
+ freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
}
void
SoundFileBrowser::freesound_stop_clicked ()
{
freesound_download_cancel = true;
- freesound_search_cancel = true;
}
@@ -888,9 +905,8 @@ void
SoundFileBrowser::freesound_search()
{
#ifdef FREESOUND
- freesound_list->clear();
+ Mootcher mootcher;
freesound_list_view.get_column(1)->set_sizing(TREE_VIEW_COLUMN_GROW_ONLY);
- matches = 0;
string search_string = freesound_entry.get_text ();
enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
@@ -901,164 +917,155 @@ SoundFileBrowser::freesound_search()
freesound_progress_bar.set_fraction(0.0);
gdk_flush();
- int freesound_n_pages = 1;
- for (int page = 1; page <= 99 && page <= freesound_n_pages; page++ ) {
-
- std::string prog;
- if (freesound_n_pages > 1) {
- freesound_progress_bar.set_fraction(page/(float)freesound_n_pages);
- prog = string_compose (_("Searching Page %1 of %2, click Stop to cancel"), page, freesound_n_pages);
- } else {
- prog = _("Searching, click Stop to cancel");
- }
- freesound_progress_bar.set_text(prog);
- while (Glib::MainContext::get_default()->iteration (false)) {
- /* do nothing */
- }
-
- std::string theString = mootcher->searchText(
+ std::string theString = mootcher.searchText(
search_string,
- page,
+ freesound_page,
#ifdef GTKOSX
"", // OSX eats anything incl mp3
#else
"type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
#endif
sort_method
- );
+ );
- XMLTree doc;
- doc.read_buffer( theString );
- XMLNode *root = doc.root();
+ gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
- if (!root) {
- error << "no root XML node!" << endmsg;
- break;
- }
+ XMLTree doc;
+ doc.read_buffer( theString );
+ XMLNode *root = doc.root();
- if ( strcmp(root->name().c_str(), "response") != 0) {
- error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
- break;
- }
+ if (!root) {
+ error << "no root XML node!" << endmsg;
+ return;
+ }
- //find out how many pages are available to search
- XMLNode *res = root->child("num_pages");
- if (res) {
- string result = res->child("text")->content();
- freesound_n_pages = atoi(result.c_str());
- }
+ if ( strcmp(root->name().c_str(), "response") != 0) {
+ error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
+ return;
+ }
- XMLNode *sounds_root = root->child("sounds");
-
- if (!sounds_root) {
- error << "no child node \"sounds\" found!" << endmsg;
- break;
- }
-
- XMLNodeList sounds = sounds_root->children();
- if (sounds.size() == 0) {
- /* nothing found */
+ // find out how many pages are available to search
+ int freesound_n_pages = 1;
+ XMLNode *res = root->child("num_pages");
+ if (res) {
+ string result = res->child("text")->content();
+ freesound_n_pages = atoi(result.c_str());
+ }
+
+ int more_pages = freesound_n_pages - freesound_page;
+
+ if (more_pages > 0) {
+ freesound_more_btn.set_sensitive(true);
+ freesound_more_btn.set_tooltip_text(string_compose(P_(
+ "%1 more page of 100 results available",
+ "%1 more pages of 100 results available",
+ more_pages), more_pages));
+ } else {
+ freesound_more_btn.set_sensitive(false);
+ freesound_more_btn.set_tooltip_text(_("No more results available"));
+ }
+
+ XMLNode *sounds_root = root->child("sounds");
+ if (!sounds_root) {
+ error << "no child node \"sounds\" found!" << endmsg;
+ return;
+ }
+
+ XMLNodeList sounds = sounds_root->children();
+ if (sounds.size() == 0) {
+ /* nothing found */
+ return;
+ }
+
+ XMLNodeConstIterator niter;
+ XMLNode *node;
+ for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
+ node = *niter;
+ if( strcmp( node->name().c_str(), "resource") != 0 ) {
+ error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
break;
}
- XMLNodeConstIterator niter;
- XMLNode *node;
- for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
- node = *niter;
- if( strcmp( node->name().c_str(), "resource") != 0 ){
- error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
- freesound_search_cancel = true;
- break;
- }
+ // node->dump(cerr, "node:");
- // node->dump(cerr, "node:");
-
- XMLNode *id_node = node->child ("id");
- XMLNode *uri_node = node->child ("serve");
- XMLNode *ofn_node = node->child ("original_filename");
- XMLNode *dur_node = node->child ("duration");
- XMLNode *siz_node = node->child ("filesize");
- XMLNode *srt_node = node->child ("samplerate");
- XMLNode *lic_node = node->child ("license");
-
- if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_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 dur = dur_node->child("text")->content();
- std::string siz = siz_node->child("text")->content();
- std::string srt = srt_node->child("text")->content();
- std::string lic = lic_node->child("text")->content();
-
- std::string r;
- // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
-
- double duration_seconds = atof(dur.c_str());
- double h, m, s;
- char duration_hhmmss[16];
- if (duration_seconds >= 99 * 60 * 60) {
- strcpy(duration_hhmmss, ">99h");
- } else {
- s = modf(duration_seconds/60, &m) * 60;
- m = modf(m/60, &h) * 60;
- sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
- h, m, s
- );
- }
- double size_bytes = atof(siz.c_str());
- char bsize[32];
- if (size_bytes < 1000) {
- sprintf(bsize, "%.0f %s", size_bytes, _("B"));
- } else if (size_bytes < 1000000 ) {
- sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
- } else if (size_bytes < 10000000) {
- sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
- } else if (size_bytes < 1000000000) {
- sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
- } else {
- sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
- }
+ XMLNode *id_node = node->child ("id");
+ XMLNode *uri_node = node->child ("serve");
+ XMLNode *ofn_node = node->child ("original_filename");
+ XMLNode *dur_node = node->child ("duration");
+ XMLNode *siz_node = node->child ("filesize");
+ XMLNode *srt_node = node->child ("samplerate");
+ XMLNode *lic_node = node->child ("license");
- /* see http://www.freesound.org/help/faq/#licenses */
- char shortlicense[64];
- if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
- sprintf(shortlicense, "CC-BY-NC");
- } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
- sprintf(shortlicense, "CC-BY");
- } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
- sprintf(shortlicense, "sampling+");
- } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
- sprintf(shortlicense, "PD");
- } else {
- snprintf(shortlicense, 64, "%s", lic.c_str());
- shortlicense[63]= '\0';
- }
+ if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
- 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;
- row[freesound_list_columns.duration] = duration_hhmmss;
- row[freesound_list_columns.filesize] = bsize;
- row[freesound_list_columns.smplrate] = srt;
- row[freesound_list_columns.license ] = shortlicense;
- matches++;
+ 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 dur = dur_node->child("text")->content();
+ std::string siz = siz_node->child("text")->content();
+ std::string srt = srt_node->child("text")->content();
+ std::string lic = lic_node->child("text")->content();
+
+ std::string r;
+ // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
+ double duration_seconds = atof(dur.c_str());
+ double h, m, s;
+ char duration_hhmmss[16];
+ if (duration_seconds >= 99 * 60 * 60) {
+ strcpy(duration_hhmmss, ">99h");
+ } else {
+ s = modf(duration_seconds/60, &m) * 60;
+ m = modf(m/60, &h) * 60;
+ sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
+ h, m, s
+ );
}
- }
-
- if (freesound_search_cancel)
- break;
- } //page "for" loop
+ double size_bytes = atof(siz.c_str());
+ char bsize[32];
+ if (size_bytes < 1000) {
+ sprintf(bsize, "%.0f %s", size_bytes, _("B"));
+ } else if (size_bytes < 1000000 ) {
+ sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
+ } else if (size_bytes < 10000000) {
+ sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
+ } else if (size_bytes < 1000000000) {
+ sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
+ } else {
+ sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
+ }
- gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
+ /* see http://www.freesound.org/help/faq/#licenses */
+ char shortlicense[64];
+ if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
+ sprintf(shortlicense, "CC-BY-NC");
+ } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
+ sprintf(shortlicense, "CC-BY");
+ } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
+ sprintf(shortlicense, "sampling+");
+ } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
+ sprintf(shortlicense, "PD");
+ } else {
+ snprintf(shortlicense, 64, "%s", lic.c_str());
+ shortlicense[63]= '\0';
+ }
+
+ 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;
+ row[freesound_list_columns.duration] = duration_hhmmss;
+ row[freesound_list_columns.filesize] = bsize;
+ row[freesound_list_columns.smplrate] = srt;
+ row[freesound_list_columns.license ] = shortlicense;
+ matches++;
+ }
+ }
- freesound_progress_bar.set_fraction(0.0);
if (matches == 0) {
freesound_progress_bar.set_text(_("Search returned no results."));
} else {
@@ -1100,6 +1107,7 @@ SoundFileBrowser::get_paths ()
} else {
#ifdef FREESOUND
typedef TreeView::Selection::ListHandle_Path ListPath;
+ Mootcher mootcher;
ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
@@ -1113,7 +1121,7 @@ SoundFileBrowser::get_paths ()
gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
gdk_flush();
- string str = mootcher->getAudioFile(ofn, id, uri, this);
+ string str = mootcher.getAudioFile(ofn, id, uri, this);
if (str != "") {
results.push_back (str);
}
diff --git a/gtk2_ardour/sfdb_ui.h b/gtk2_ardour/sfdb_ui.h
index 6992bc5..bed800a 100644
--- a/gtk2_ardour/sfdb_ui.h
+++ b/gtk2_ardour/sfdb_ui.h
@@ -149,6 +149,7 @@ class SoundFileBrowser : public ArdourWindow
FreesoundColumns freesound_list_columns;
Glib::RefPtr<Gtk::ListStore> freesound_list;
+ Gtk::Button freesound_more_btn;
Gtk::Button freesound_stop_btn;
public:
@@ -173,21 +174,15 @@ class SoundFileBrowser : public ArdourWindow
Gtk::Entry freesound_entry;
Gtk::ComboBoxText freesound_sort;
- Gtk::SpinButton freesound_page;
-
+
Gtk::Button freesound_search_btn;
Gtk::TreeView freesound_list_view;
Gtk::ProgressBar freesound_progress_bar;
- bool freesound_search_cancel;
bool freesound_download_cancel;
void freesound_search();
-#ifdef FREESOUND
- Mootcher *mootcher;
-#endif
-
protected:
bool resetting_ourselves;
int matches;
@@ -228,7 +223,9 @@ class SoundFileBrowser : public ArdourWindow
void freesound_list_view_selected ();
void freesound_list_view_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*);
void freesound_search_clicked ();
+ void freesound_more_clicked ();
void freesound_stop_clicked ();
+ int freesound_page;
void chooser_file_activated ();
|
|
|
I can't work out what I need to do to make 'git push' work right now, so here's the patch for safekeeping. |
|
|
Changes to fix Frederic's point (2) above in commit 2233e910. I might have a poke at implementing 'similarity search' when I have a few more spare moments. |
|
|
After finding a few spare moments here & there, I now have a patch series with a small bunch of tweaks and improvements to Freesound import. I'll post it here in a moment before blindly committing it, in case I've done anything really bad that someone else might spot. It adds: * multi-threaded download - each sound file is downloaded in its own thread, with a separate progress indicator and cancel button for each sound downloading. * a 'Similar' button to use the Freesound similarity search, as suggested by Frederic above. * the location of downloaded sound files is set via a a Config variable, rather than being hard-coded to "~/Freesound/snd". |
|
2013-06-14 17:38
|
freesound-tweaks-20130614.patch (26,729 bytes)
diff --git a/gtk2_ardour/sfdb_freesound_mootcher.cc b/gtk2_ardour/sfdb_freesound_mootcher.cc
index e46fb12..b2601d8 100644
--- a/gtk2_ardour/sfdb_freesound_mootcher.cc
+++ b/gtk2_ardour/sfdb_freesound_mootcher.cc
@@ -53,6 +53,8 @@
#include "i18n.h"
#include "ardour/audio_library.h"
+#include "ardour/rc_configuration.h"
+#include "pbd/pthread_utils.h"
using namespace PBD;
@@ -63,9 +65,12 @@ static const std::string api_key = "9d77cb8d841b4bcfa960e1aae62224eb"; // ardour
Mootcher::Mootcher()
: curl(curl_easy_init())
{
- std::string path;
- path = Glib::get_home_dir() + "/Freesound/";
- changeWorkingDir ( path.c_str() );
+ cancel_download_btn.set_label (_("Cancel"));
+ progress_hbox.pack_start (progress_bar, true, true);
+ progress_hbox.pack_end (cancel_download_btn, false, false);
+ progress_bar.show();
+ cancel_download_btn.show();
+ cancel_download_btn.signal_clicked().connect(sigc::mem_fun (*this, &Mootcher::cancelDownload));
};
//------------------------------------------------------------------------
Mootcher:: ~Mootcher()
@@ -77,14 +82,6 @@ Mootcher:: ~Mootcher()
void Mootcher::changeWorkingDir(const char *saveLocation)
{
basePath = saveLocation;
-#ifdef __WIN32__
- std::string replace = "/";
- size_t pos = basePath.find("\\");
- while( pos != std::string::npos ){
- basePath.replace(pos, 1, replace);
- pos = basePath.find("\\");
- }
-#endif
//
size_t pos2 = basePath.find_last_of("/");
if(basePath.length() != (pos2+1)) basePath += "/";
@@ -92,13 +89,22 @@ void Mootcher::changeWorkingDir(const char *saveLocation)
void Mootcher::ensureWorkingDir ()
{
- std::string p = Glib::build_filename (basePath, "snd");
+ std::string p = ARDOUR::Config->get_freesound_download_dir();
if (!Glib::file_test (p, Glib::FILE_TEST_IS_DIR)) {
if (g_mkdir_with_parents (p.c_str(), 0775) != 0) {
PBD::error << "Unable to create Mootcher working dir" << endmsg;
}
}
+ basePath = p;
+#ifdef __WIN32__
+ std::string replace = "/";
+ size_t pos = basePath.find("\\");
+ while( pos != std::string::npos ){
+ basePath.replace(pos, 1, replace);
+ pos = basePath.find("\\");
+ }
+#endif
}
@@ -121,7 +127,8 @@ size_t Mootcher::WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void
//------------------------------------------------------------------------
-std::string Mootcher::sortMethodString(enum sortMethod sort) {
+std::string Mootcher::sortMethodString(enum sortMethod sort)
+{
// given a sort type, returns the string value to be passed to the API to
// sort the results in the requested way.
@@ -202,6 +209,18 @@ std::string Mootcher::doRequest(std::string uri, std::string params)
}
+std::string Mootcher::searchSimilar(std::string id)
+{
+ std::string params = "";
+
+ params += "&fields=id,original_filename,duration,filesize,samplerate,license,serve";
+ params += "&num_results=100";
+
+ return doRequest("/sounds/" + id + "/similar", params);
+}
+
+//------------------------------------------------------------------------
+
std::string Mootcher::searchText(std::string query, int page, std::string filter, enum sortMethod sort)
{
std::string params = "";
@@ -264,7 +283,7 @@ std::string Mootcher::getSoundResourceFile(std::string ID)
// get the file name and size from xml file
if (name) {
- audioFileName = basePath + "snd/" + ID + "-" + name->child("text")->content();
+ audioFileName = Glib::build_filename (basePath, ID + "-" + name->child("text")->content());
//store all the tags in the database
XMLNode *tags = freesound->child("tags");
@@ -296,10 +315,63 @@ int audioFileWrite(void *buffer, size_t size, size_t nmemb, void *file)
};
//------------------------------------------------------------------------
-std::string Mootcher::getAudioFile(std::string originalFileName, std::string ID, std::string audioURL, SoundFileBrowser *caller)
+
+void *
+Mootcher::threadFunc() {
+CURLcode res;
+
+ res = curl_easy_perform (curl);
+ fclose (theFile);
+ curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 1); // turn off the progress bar
+
+ if (res != CURLE_OK) {
+ /* it's not an error if the user pressed the stop button */
+ if (res != CURLE_ABORTED_BY_CALLBACK) {
+ error << string_compose (_("curl error %1 (%2)"), res, curl_easy_strerror(res)) << endmsg;
+ }
+ remove ( (audioFileName+".part").c_str() );
+ } else {
+ rename ( (audioFileName+".part").c_str(), audioFileName.c_str() );
+ // now download the tags &c.
+ getSoundResourceFile(ID);
+ }
+
+ return (void *) res;
+}
+
+static int
+donewithMootcher(void *arg)
+{
+ Mootcher *thisMootcher = (Mootcher *) arg;
+
+ // update the sound info pane if the selection in the list box is still us
+ thisMootcher->sfb->refresh_display(thisMootcher->ID, thisMootcher->audioFileName);
+
+ delete(thisMootcher);
+ return 0;
+}
+
+static void *
+freesound_download_thread_func(void *arg)
+{
+ Mootcher *thisMootcher = (Mootcher *) arg;
+ void *res;
+
+ // std::cerr << "freesound_download_thread_func(" << arg << ")" << std::endl;
+ res = thisMootcher->threadFunc();
+ g_idle_add(donewithMootcher, thisMootcher);
+
+ return res;
+}
+
+
+//------------------------------------------------------------------------
+
+bool Mootcher::checkAudioFile(std::string originalFileName, std::string theID)
{
ensureWorkingDir();
- std::string audioFileName = basePath + "snd/" + ID + "-" + originalFileName;
+ ID = theID;
+ audioFileName = Glib::build_filename (basePath, ID + "-" + originalFileName);
// check to see if audio file already exists
FILE *testFile = g_fopen(audioFileName.c_str(), "r");
@@ -307,29 +379,31 @@ std::string Mootcher::getAudioFile(std::string originalFileName, std::string ID,
fseek (testFile , 0 , SEEK_END);
if (ftell (testFile) > 256) {
fclose (testFile);
- return audioFileName;
+ return true;
}
- // else file was small, probably an error, delete it and try again
+ // else file was small, probably an error, delete it
fclose(testFile);
remove( audioFileName.c_str() );
}
+ return false;
+}
- if (!curl) {
- return "";
- }
- // if already cancelling a previous download, bail out here ( this can happen b/c getAudioFile gets called by various UI update funcs )
- if ( caller->freesound_download_cancel ) {
- return "";
+bool Mootcher::fetchAudioFile(std::string originalFileName, std::string theID, std::string audioURL, SoundFileBrowser *caller)
+{
+ ensureWorkingDir();
+ ID = theID;
+ audioFileName = Glib::build_filename (basePath, ID + "-" + originalFileName);
+
+ if (!curl) {
+ return false;
}
-
// now download the actual file
- FILE* theFile;
- theFile = g_fopen( audioFileName.c_str(), "wb" );
+ theFile = g_fopen( (audioFileName + ".part").c_str(), "wb" );
if (!theFile) {
- return "";
+ return false;
}
// create the download url
@@ -340,57 +414,71 @@ std::string Mootcher::getAudioFile(std::string originalFileName, std::string ID,
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, audioFileWrite);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, theFile);
- /* hack to get rid of the barber-pole stripes */
- caller->freesound_progress_bar.hide();
- caller->freesound_progress_bar.show();
-
std::string prog;
prog = string_compose (_("%1"), originalFileName);
- caller->freesound_progress_bar.set_text(prog);
+ progress_bar.set_text(prog);
+
+ Gtk::VBox *freesound_vbox = dynamic_cast<Gtk::VBox *> (caller->notebook.get_nth_page(2));
+ freesound_vbox->pack_start(progress_hbox, Gtk::PACK_SHRINK);
+ progress_hbox.show();
+ cancel_download = false;
+ sfb = caller;
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, caller);
+ curl_easy_setopt (curl, CURLOPT_PROGRESSDATA, this);
- CURLcode res = curl_easy_perform(curl);
- fclose(theFile);
+ pthread_t freesound_download_thread;
+ pthread_create_and_store("freesound_import", &freesound_download_thread, freesound_download_thread_func, this);
- curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 1); // turn off the progress bar
- caller->freesound_progress_bar.set_fraction(0.0);
- caller->freesound_progress_bar.set_text("");
-
- if( res != 0 ) {
- /* it's not an error if the user pressed the stop button */
- if (res != CURLE_ABORTED_BY_CALLBACK) {
- error << string_compose (_("curl error %1 (%2)"), res, curl_easy_strerror(res)) << endmsg;
+ return true;
+}
+
+//---------
+struct progressInfo {
+ Gtk::ProgressBar *bar;
+ double dltotal;
+ double dlnow;
+};
+
+static int
+updateProgress(void *arg)
+{
+ struct progressInfo *progress = (struct progressInfo *) arg;
+ if (progress->dltotal > 0) {
+ double fraction = progress->dlnow / progress->dltotal;
+ // std::cerr << "progress idle: " << progress->bar->get_text() << ". " << progress->dlnow << " / " << progress->dltotal << " = " << fraction << std::endl;
+ if (fraction > 1.0) {
+ fraction = 1.0;
+ } else if (fraction < 0.0) {
+ fraction = 0.0;
}
- remove( audioFileName.c_str() );
- return "";
- } else {
- // now download the tags &c.
- getSoundResourceFile(ID);
+ progress->bar->set_fraction(fraction);
}
- return audioFileName;
+ delete progress;
+ return 0;
}
-//---------
-int Mootcher::progress_callback(void *caller, double dltotal, double dlnow, double /*ultotal*/, double /*ulnow*/)
+int
+Mootcher::progress_callback(void *caller, double dltotal, double dlnow, double /*ultotal*/, double /*ulnow*/)
{
+ // It may seem curious to pass a pointer to an instance of an object to a static
+ // member function, but we can't use a normal member function as a curl progress callback,
+ // and we want access to some private members of Mootcher.
-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_download_cancel) {
- return -1;
- }
-
+ Mootcher *thisMootcher = (Mootcher *) caller;
- sfb->freesound_progress_bar.set_fraction(dlnow/dltotal);
- /* Make sure the progress widget gets updated */
- while (Glib::MainContext::get_default()->iteration (false)) {
- /* do nothing */
+ if (thisMootcher->cancel_download) {
+ return -1;
}
+
+ struct progressInfo *progress = new struct progressInfo;
+ progress->bar = &thisMootcher->progress_bar;
+ progress->dltotal = dltotal;
+ progress->dlnow = dlnow;
+
+ g_idle_add(updateProgress, progress);
return 0;
}
diff --git a/gtk2_ardour/sfdb_freesound_mootcher.h b/gtk2_ardour/sfdb_freesound_mootcher.h
index 7e39ba4..ee65020 100644
--- a/gtk2_ardour/sfdb_freesound_mootcher.h
+++ b/gtk2_ardour/sfdb_freesound_mootcher.h
@@ -71,12 +71,17 @@ public:
Mootcher();
~Mootcher();
- std::string getAudioFile(std::string originalFileName, std::string ID, std::string audioURL, SoundFileBrowser *caller);
+ bool checkAudioFile(std::string originalFileName, std::string ID);
+ bool fetchAudioFile(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);
+ std::string searchSimilar(std::string id);
+ void * threadFunc();
+ SoundFileBrowser *sfb;
+ std::string audioFileName;
+ std::string ID;
private:
- void changeWorkingDir(const char *saveLocation);
void ensureWorkingDir();
std::string doRequest(std::string uri, std::string params);
@@ -90,6 +95,18 @@ private:
CURL *curl;
char errorBuffer[CURL_ERROR_SIZE]; // storage for cUrl error message
+ FILE* theFile;
+
+ Gtk::HBox progress_hbox;
+ Gtk::ProgressBar progress_bar;
+ Gtk::Button cancel_download_btn;
+
+ bool cancel_download;
+ void cancelDownload() {
+ cancel_download = true;
+ progress_hbox.hide();
+ }
+
std::string basePath;
std::string xmlLocation;
};
diff --git a/gtk2_ardour/sfdb_ui.cc b/gtk2_ardour/sfdb_ui.cc
index 85b4f7d..e8db9d4 100644
--- a/gtk2_ardour/sfdb_ui.cc
+++ b/gtk2_ardour/sfdb_ui.cc
@@ -80,6 +80,7 @@ using namespace Editing;
using std::string;
string SoundFileBrowser::persistent_folder;
+typedef TreeView::Selection::ListHandle_Path ListPath;
static ImportMode
string2importmode (string str)
@@ -512,8 +513,6 @@ SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persi
found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
- freesound_stop_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_stop_clicked));
-
notebook.append_page (*vbox, _("Search Tags"));
#ifdef FREESOUND
@@ -555,9 +554,9 @@ SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persi
freesound_more_btn.set_label(_("More"));
freesound_more_btn.set_sensitive(false);
- passbox->pack_end (freesound_stop_btn, false, false);
- freesound_stop_btn.set_label(_("Stop"));
- freesound_stop_btn.set_sensitive(false);
+ passbox->pack_start (freesound_similar_btn, false, false);
+ freesound_similar_btn.set_label(_("Similar"));
+ freesound_similar_btn.set_sensitive(false);
scroll = manage(new ScrolledWindow);
scroll->add(freesound_list_view);
@@ -566,9 +565,8 @@ SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persi
vbox = manage(new VBox);
vbox->set_spacing (3);
vbox->pack_start (*passbox, PACK_SHRINK);
- vbox->pack_start (freesound_progress_bar, PACK_SHRINK);
vbox->pack_start (*scroll);
-
+
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);
@@ -577,20 +575,22 @@ SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persi
freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
freesound_list_view.append_column(_("License"), freesound_list_columns.license);
freesound_list_view.get_column(0)->set_alignment(0.5);
- freesound_list_view.get_column(1)->set_expand(true);
+ freesound_list_view.get_column(1)->set_expand(true); // filename
+ freesound_list_view.get_column(1)->set_resizable(true); // filename
freesound_list_view.get_column(2)->set_alignment(0.5);
freesound_list_view.get_column(3)->set_alignment(0.5);
freesound_list_view.get_column(4)->set_alignment(0.5);
freesound_list_view.get_column(5)->set_alignment(0.5);
freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
+ freesound_list_view.set_tooltip_column(1);
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_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
- freesound_stop_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_stop_clicked));
+ freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
notebook.append_page (*vbox, _("Search Freesound"));
#endif
@@ -787,7 +787,7 @@ SoundFileBrowser::found_list_view_selected ()
} else {
string file;
- TreeView::Selection::ListHandle_Path rows = found_list_view.get_selection()->get_selected_rows ();
+ ListPath rows = found_list_view.get_selection()->get_selected_rows ();
if (!rows.empty()) {
TreeIter iter = found_list->get_iter(*rows.begin());
@@ -803,55 +803,6 @@ SoundFileBrowser::found_list_view_selected ()
}
void
-SoundFileBrowser::freesound_list_view_selected ()
-{
- freesound_download_cancel = false;
- freesound_stop_btn.set_sensitive(true);
-
-#ifdef FREESOUND
- if (!reset_options ()) {
- set_action_sensitive (false);
- } else {
- Mootcher mootcher;
- 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());
-
- 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 = mootcher.getAudioFile(ofn, id, uri, this);
-
- gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
-
- if (file != "") {
- chooser.set_filename (file);
- set_action_sensitive (true);
- }
- } else {
- set_action_sensitive (false);
- }
-
- freesound_progress_bar.set_text(
- string_compose(P_("found %1 match", "found %1 matches", matches), matches));
-
- preview.setup_labels (file);
- }
-#endif
- freesound_stop_btn.set_sensitive(false);
-}
-
-void
SoundFileBrowser::found_search_clicked ()
{
string tag_string = found_entry.get_text ();
@@ -875,6 +826,91 @@ SoundFileBrowser::found_search_clicked ()
}
}
+
+std::string
+SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
+{
+
+ Mootcher *mootcher = new Mootcher;
+ std::string file;
+
+ string id = (*iter)[freesound_list_columns.id];
+ string uri = (*iter)[freesound_list_columns.uri];
+ string ofn = (*iter)[freesound_list_columns.filename];
+
+ if (mootcher->checkAudioFile(ofn, id)) {
+ // file already exists, no need to download it again
+ file = mootcher->audioFileName;
+ delete mootcher;
+ (*iter)[freesound_list_columns.started] = false;
+ return file;
+ }
+ if (!(*iter)[freesound_list_columns.started]) {
+ // start downloading the sound file
+ (*iter)[freesound_list_columns.started] = true;
+ mootcher->fetchAudioFile(ofn, id, uri, this);
+ }
+ return "";
+}
+
+void
+SoundFileBrowser::freesound_list_view_selected ()
+{
+
+ if (!reset_options ()) {
+ set_action_sensitive (false);
+ } else {
+ std::string file;
+ ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
+ for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
+ file = freesound_get_audio_file (freesound_list->get_iter(*i));
+ }
+
+ switch (rows.size()) {
+ case 0:
+ // nothing selected
+ freesound_similar_btn.set_sensitive(false);
+ set_action_sensitive (false);
+ break;
+ case 1:
+ // exactly one item selected
+ if (file != "") {
+ // file exists on disk already
+ chooser.set_filename (file);
+ preview.setup_labels (file);
+ set_action_sensitive (true);
+ }
+ freesound_similar_btn.set_sensitive(true);
+ break;
+ default:
+ // multiple items selected
+ preview.setup_labels ("");
+ freesound_similar_btn.set_sensitive(false);
+ break;
+ }
+
+ }
+}
+
+void
+SoundFileBrowser::refresh_display(std::string ID, std::string file)
+{
+ // called when the mootcher has finished downloading a file
+ ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
+ if (rows.size() == 1) {
+ // there's a single item selected in the freesound list
+ //XXX make a function to be used to construct the actual file name both here and in the mootcher
+ Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
+ std::string selected_ID = (*row)[freesound_list_columns.id];
+ if (ID == selected_ID) {
+ // the selected item in the freesound list is the item that has just finished downloading
+ chooser.set_filename(file);
+ preview.setup_labels (file);
+ set_action_sensitive (true);
+ }
+ }
+}
+
void
SoundFileBrowser::freesound_search_clicked ()
{
@@ -895,18 +931,32 @@ SoundFileBrowser::freesound_more_clicked ()
}
void
-SoundFileBrowser::freesound_stop_clicked ()
+SoundFileBrowser::freesound_similar_clicked ()
{
- freesound_download_cancel = true;
+ ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
+ if (rows.size() == 1) {
+ Mootcher mootcher;
+ string id;
+ Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
+ id = (*iter)[freesound_list_columns.id];
+ freesound_list->clear();
+
+ 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();
+
+ std::string theString = mootcher.searchSimilar(id);
+
+ gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
+ handle_freesound_results(theString);
+ }
}
-
void
SoundFileBrowser::freesound_search()
{
-#ifdef FREESOUND
Mootcher mootcher;
- freesound_list_view.get_column(1)->set_sizing(TREE_VIEW_COLUMN_GROW_ONLY);
string search_string = freesound_entry.get_text ();
enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
@@ -914,7 +964,6 @@ SoundFileBrowser::freesound_search()
GdkCursor *prev_cursor;
prev_cursor = gdk_window_get_cursor (get_window()->gobj());
gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
- freesound_progress_bar.set_fraction(0.0);
gdk_flush();
std::string theString = mootcher.searchText(
@@ -929,7 +978,11 @@ SoundFileBrowser::freesound_search()
);
gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
+ handle_freesound_results(theString);
+}
+void
+SoundFileBrowser::handle_freesound_results(std::string theString) {
XMLTree doc;
doc.read_buffer( theString );
XMLNode *root = doc.root();
@@ -1065,14 +1118,6 @@ SoundFileBrowser::freesound_search()
matches++;
}
}
-
- if (matches == 0) {
- freesound_progress_bar.set_text(_("Search returned no results."));
- } else {
- freesound_progress_bar.set_text(string_compose(P_("Found %1 match", "Found %1 matches", matches), matches));
- }
- freesound_list_view.get_column(1)->set_sizing(TREE_VIEW_COLUMN_AUTOSIZE);
-#endif
}
vector<string>
@@ -1093,9 +1138,7 @@ SoundFileBrowser::get_paths ()
}
}
- } else if (n==1){
-
- typedef TreeView::Selection::ListHandle_Path ListPath;
+ } else if (n == 1) {
ListPath rows = found_list_view.get_selection()->get_selected_rows ();
for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
@@ -1106,28 +1149,12 @@ SoundFileBrowser::get_paths ()
}
} else {
#ifdef FREESOUND
- typedef TreeView::Selection::ListHandle_Path ListPath;
- Mootcher mootcher;
-
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 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 = mootcher.getAudioFile(ofn, id, uri, this);
+ string str = freesound_get_audio_file (freesound_list->get_iter(*i));
if (str != "") {
results.push_back (str);
}
-
- gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
-
}
#endif
}
diff --git a/gtk2_ardour/sfdb_ui.h b/gtk2_ardour/sfdb_ui.h
index bed800a..5d8decd 100644
--- a/gtk2_ardour/sfdb_ui.h
+++ b/gtk2_ardour/sfdb_ui.h
@@ -131,6 +131,7 @@ class SoundFileBrowser : public ArdourWindow
Gtk::TreeModelColumn<std::string> filesize;
Gtk::TreeModelColumn<std::string> smplrate;
Gtk::TreeModelColumn<std::string> license;
+ Gtk::TreeModelColumn<bool> started;
FreesoundColumns() {
add(id);
@@ -140,6 +141,7 @@ class SoundFileBrowser : public ArdourWindow
add(filesize);
add(smplrate);
add(license);
+ add(started);
}
};
@@ -150,8 +152,9 @@ class SoundFileBrowser : public ArdourWindow
Glib::RefPtr<Gtk::ListStore> freesound_list;
Gtk::Button freesound_more_btn;
- Gtk::Button freesound_stop_btn;
+ Gtk::Button freesound_similar_btn;
+ void handle_freesound_results(std::string theString);
public:
SoundFileBrowser (std::string title, ARDOUR::Session* _s, bool persistent);
virtual ~SoundFileBrowser ();
@@ -177,11 +180,10 @@ class SoundFileBrowser : public ArdourWindow
Gtk::Button freesound_search_btn;
Gtk::TreeView freesound_list_view;
- Gtk::ProgressBar freesound_progress_bar;
-
- bool freesound_download_cancel;
+ Gtk::Notebook notebook;
void freesound_search();
+ void refresh_display(std::string ID, std::string file);
protected:
bool resetting_ourselves;
@@ -203,7 +205,6 @@ class SoundFileBrowser : public ArdourWindow
static std::string persistent_folder;
- Gtk::Notebook notebook;
GainMeter* gm;
Gtk::VBox meter_packer;
@@ -224,10 +225,11 @@ class SoundFileBrowser : public ArdourWindow
void freesound_list_view_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*);
void freesound_search_clicked ();
void freesound_more_clicked ();
- void freesound_stop_clicked ();
+ void freesound_similar_clicked ();
int freesound_page;
void chooser_file_activated ();
+ std::string freesound_get_audio_file(Gtk::TreeIter iter);
bool on_audio_filter (const Gtk::FileFilter::Info& filter_info);
bool on_midi_filter (const Gtk::FileFilter::Info& filter_info);
diff --git a/libs/ardour/ardour/rc_configuration_vars.h b/libs/ardour/ardour/rc_configuration_vars.h
index f19f8fe..d8440f2 100644
--- a/libs/ardour/ardour/rc_configuration_vars.h
+++ b/libs/ardour/ardour/rc_configuration_vars.h
@@ -192,6 +192,7 @@ CONFIG_VARIABLE (bool, sound_midi_notes, "sound-midi-notes", false)
CONFIG_VARIABLE (bool, use_plugin_own_gui, "use-plugin-own-gui", true)
CONFIG_VARIABLE (uint32_t, max_recent_sessions, "max-recent-sessions", 10)
CONFIG_VARIABLE (double, automation_thinning_factor, "automation-thinning-factor", 20.0)
+CONFIG_VARIABLE (std::string, freesound_download_dir, "freesound-download-dir", Glib::get_home_dir() + "/Freesound/snd")
/* denormal management */
|
|
2013-06-14 17:56
|
freesound-tweaks-20130614-2.patch (26,740 bytes)
diff --git a/gtk2_ardour/sfdb_freesound_mootcher.cc b/gtk2_ardour/sfdb_freesound_mootcher.cc
index e46fb12..38d53aa 100644
--- a/gtk2_ardour/sfdb_freesound_mootcher.cc
+++ b/gtk2_ardour/sfdb_freesound_mootcher.cc
@@ -53,6 +53,8 @@
#include "i18n.h"
#include "ardour/audio_library.h"
+#include "ardour/rc_configuration.h"
+#include "pbd/pthread_utils.h"
using namespace PBD;
@@ -63,9 +65,12 @@ static const std::string api_key = "9d77cb8d841b4bcfa960e1aae62224eb"; // ardour
Mootcher::Mootcher()
: curl(curl_easy_init())
{
- std::string path;
- path = Glib::get_home_dir() + "/Freesound/";
- changeWorkingDir ( path.c_str() );
+ cancel_download_btn.set_label (_("Cancel"));
+ progress_hbox.pack_start (progress_bar, true, true);
+ progress_hbox.pack_end (cancel_download_btn, false, false);
+ progress_bar.show();
+ cancel_download_btn.show();
+ cancel_download_btn.signal_clicked().connect(sigc::mem_fun (*this, &Mootcher::cancelDownload));
};
//------------------------------------------------------------------------
Mootcher:: ~Mootcher()
@@ -74,31 +79,25 @@ Mootcher:: ~Mootcher()
}
//------------------------------------------------------------------------
-void Mootcher::changeWorkingDir(const char *saveLocation)
-{
- basePath = saveLocation;
-#ifdef __WIN32__
- std::string replace = "/";
- size_t pos = basePath.find("\\");
- while( pos != std::string::npos ){
- basePath.replace(pos, 1, replace);
- pos = basePath.find("\\");
- }
-#endif
- //
- size_t pos2 = basePath.find_last_of("/");
- if(basePath.length() != (pos2+1)) basePath += "/";
-}
void Mootcher::ensureWorkingDir ()
{
- std::string p = Glib::build_filename (basePath, "snd");
+ std::string p = ARDOUR::Config->get_freesound_download_dir();
if (!Glib::file_test (p, Glib::FILE_TEST_IS_DIR)) {
if (g_mkdir_with_parents (p.c_str(), 0775) != 0) {
PBD::error << "Unable to create Mootcher working dir" << endmsg;
}
}
+ basePath = p;
+#ifdef __WIN32__
+ std::string replace = "/";
+ size_t pos = basePath.find("\\");
+ while( pos != std::string::npos ){
+ basePath.replace(pos, 1, replace);
+ pos = basePath.find("\\");
+ }
+#endif
}
@@ -121,7 +120,8 @@ size_t Mootcher::WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void
//------------------------------------------------------------------------
-std::string Mootcher::sortMethodString(enum sortMethod sort) {
+std::string Mootcher::sortMethodString(enum sortMethod sort)
+{
// given a sort type, returns the string value to be passed to the API to
// sort the results in the requested way.
@@ -202,6 +202,18 @@ std::string Mootcher::doRequest(std::string uri, std::string params)
}
+std::string Mootcher::searchSimilar(std::string id)
+{
+ std::string params = "";
+
+ params += "&fields=id,original_filename,duration,filesize,samplerate,license,serve";
+ params += "&num_results=100";
+
+ return doRequest("/sounds/" + id + "/similar", params);
+}
+
+//------------------------------------------------------------------------
+
std::string Mootcher::searchText(std::string query, int page, std::string filter, enum sortMethod sort)
{
std::string params = "";
@@ -264,7 +276,7 @@ std::string Mootcher::getSoundResourceFile(std::string ID)
// get the file name and size from xml file
if (name) {
- audioFileName = basePath + "snd/" + ID + "-" + name->child("text")->content();
+ audioFileName = Glib::build_filename (basePath, ID + "-" + name->child("text")->content());
//store all the tags in the database
XMLNode *tags = freesound->child("tags");
@@ -296,10 +308,63 @@ int audioFileWrite(void *buffer, size_t size, size_t nmemb, void *file)
};
//------------------------------------------------------------------------
-std::string Mootcher::getAudioFile(std::string originalFileName, std::string ID, std::string audioURL, SoundFileBrowser *caller)
+
+void *
+Mootcher::threadFunc() {
+CURLcode res;
+
+ res = curl_easy_perform (curl);
+ fclose (theFile);
+ curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 1); // turn off the progress bar
+
+ if (res != CURLE_OK) {
+ /* it's not an error if the user pressed the stop button */
+ if (res != CURLE_ABORTED_BY_CALLBACK) {
+ error << string_compose (_("curl error %1 (%2)"), res, curl_easy_strerror(res)) << endmsg;
+ }
+ remove ( (audioFileName+".part").c_str() );
+ } else {
+ rename ( (audioFileName+".part").c_str(), audioFileName.c_str() );
+ // now download the tags &c.
+ getSoundResourceFile(ID);
+ }
+
+ return (void *) res;
+}
+
+static int
+donewithMootcher(void *arg)
+{
+ Mootcher *thisMootcher = (Mootcher *) arg;
+
+ // update the sound info pane if the selection in the list box is still us
+ thisMootcher->sfb->refresh_display(thisMootcher->ID, thisMootcher->audioFileName);
+
+ delete(thisMootcher);
+ return 0;
+}
+
+static void *
+freesound_download_thread_func(void *arg)
+{
+ Mootcher *thisMootcher = (Mootcher *) arg;
+ void *res;
+
+ // std::cerr << "freesound_download_thread_func(" << arg << ")" << std::endl;
+ res = thisMootcher->threadFunc();
+ g_idle_add(donewithMootcher, thisMootcher);
+
+ return res;
+}
+
+
+//------------------------------------------------------------------------
+
+bool Mootcher::checkAudioFile(std::string originalFileName, std::string theID)
{
ensureWorkingDir();
- std::string audioFileName = basePath + "snd/" + ID + "-" + originalFileName;
+ ID = theID;
+ audioFileName = Glib::build_filename (basePath, ID + "-" + originalFileName);
// check to see if audio file already exists
FILE *testFile = g_fopen(audioFileName.c_str(), "r");
@@ -307,29 +372,31 @@ std::string Mootcher::getAudioFile(std::string originalFileName, std::string ID,
fseek (testFile , 0 , SEEK_END);
if (ftell (testFile) > 256) {
fclose (testFile);
- return audioFileName;
+ return true;
}
- // else file was small, probably an error, delete it and try again
+ // else file was small, probably an error, delete it
fclose(testFile);
remove( audioFileName.c_str() );
}
+ return false;
+}
- if (!curl) {
- return "";
- }
- // if already cancelling a previous download, bail out here ( this can happen b/c getAudioFile gets called by various UI update funcs )
- if ( caller->freesound_download_cancel ) {
- return "";
+bool Mootcher::fetchAudioFile(std::string originalFileName, std::string theID, std::string audioURL, SoundFileBrowser *caller)
+{
+ ensureWorkingDir();
+ ID = theID;
+ audioFileName = Glib::build_filename (basePath, ID + "-" + originalFileName);
+
+ if (!curl) {
+ return false;
}
-
// now download the actual file
- FILE* theFile;
- theFile = g_fopen( audioFileName.c_str(), "wb" );
+ theFile = g_fopen( (audioFileName + ".part").c_str(), "wb" );
if (!theFile) {
- return "";
+ return false;
}
// create the download url
@@ -340,57 +407,71 @@ std::string Mootcher::getAudioFile(std::string originalFileName, std::string ID,
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, audioFileWrite);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, theFile);
- /* hack to get rid of the barber-pole stripes */
- caller->freesound_progress_bar.hide();
- caller->freesound_progress_bar.show();
-
std::string prog;
prog = string_compose (_("%1"), originalFileName);
- caller->freesound_progress_bar.set_text(prog);
+ progress_bar.set_text(prog);
+
+ Gtk::VBox *freesound_vbox = dynamic_cast<Gtk::VBox *> (caller->notebook.get_nth_page(2));
+ freesound_vbox->pack_start(progress_hbox, Gtk::PACK_SHRINK);
+ progress_hbox.show();
+ cancel_download = false;
+ sfb = caller;
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, caller);
+ curl_easy_setopt (curl, CURLOPT_PROGRESSDATA, this);
- CURLcode res = curl_easy_perform(curl);
- fclose(theFile);
+ pthread_t freesound_download_thread;
+ pthread_create_and_store("freesound_import", &freesound_download_thread, freesound_download_thread_func, this);
- curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 1); // turn off the progress bar
- caller->freesound_progress_bar.set_fraction(0.0);
- caller->freesound_progress_bar.set_text("");
-
- if( res != 0 ) {
- /* it's not an error if the user pressed the stop button */
- if (res != CURLE_ABORTED_BY_CALLBACK) {
- error << string_compose (_("curl error %1 (%2)"), res, curl_easy_strerror(res)) << endmsg;
+ return true;
+}
+
+//---------
+struct progressInfo {
+ Gtk::ProgressBar *bar;
+ double dltotal;
+ double dlnow;
+};
+
+static int
+updateProgress(void *arg)
+{
+ struct progressInfo *progress = (struct progressInfo *) arg;
+ if (progress->dltotal > 0) {
+ double fraction = progress->dlnow / progress->dltotal;
+ // std::cerr << "progress idle: " << progress->bar->get_text() << ". " << progress->dlnow << " / " << progress->dltotal << " = " << fraction << std::endl;
+ if (fraction > 1.0) {
+ fraction = 1.0;
+ } else if (fraction < 0.0) {
+ fraction = 0.0;
}
- remove( audioFileName.c_str() );
- return "";
- } else {
- // now download the tags &c.
- getSoundResourceFile(ID);
+ progress->bar->set_fraction(fraction);
}
- return audioFileName;
+ delete progress;
+ return 0;
}
-//---------
-int Mootcher::progress_callback(void *caller, double dltotal, double dlnow, double /*ultotal*/, double /*ulnow*/)
+int
+Mootcher::progress_callback(void *caller, double dltotal, double dlnow, double /*ultotal*/, double /*ulnow*/)
{
+ // It may seem curious to pass a pointer to an instance of an object to a static
+ // member function, but we can't use a normal member function as a curl progress callback,
+ // and we want access to some private members of Mootcher.
-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_download_cancel) {
- return -1;
- }
-
+ Mootcher *thisMootcher = (Mootcher *) caller;
- sfb->freesound_progress_bar.set_fraction(dlnow/dltotal);
- /* Make sure the progress widget gets updated */
- while (Glib::MainContext::get_default()->iteration (false)) {
- /* do nothing */
+ if (thisMootcher->cancel_download) {
+ return -1;
}
+
+ struct progressInfo *progress = new struct progressInfo;
+ progress->bar = &thisMootcher->progress_bar;
+ progress->dltotal = dltotal;
+ progress->dlnow = dlnow;
+
+ g_idle_add(updateProgress, progress);
return 0;
}
diff --git a/gtk2_ardour/sfdb_freesound_mootcher.h b/gtk2_ardour/sfdb_freesound_mootcher.h
index 7e39ba4..ee65020 100644
--- a/gtk2_ardour/sfdb_freesound_mootcher.h
+++ b/gtk2_ardour/sfdb_freesound_mootcher.h
@@ -71,12 +71,17 @@ public:
Mootcher();
~Mootcher();
- std::string getAudioFile(std::string originalFileName, std::string ID, std::string audioURL, SoundFileBrowser *caller);
+ bool checkAudioFile(std::string originalFileName, std::string ID);
+ bool fetchAudioFile(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);
+ std::string searchSimilar(std::string id);
+ void * threadFunc();
+ SoundFileBrowser *sfb;
+ std::string audioFileName;
+ std::string ID;
private:
- void changeWorkingDir(const char *saveLocation);
void ensureWorkingDir();
std::string doRequest(std::string uri, std::string params);
@@ -90,6 +95,18 @@ private:
CURL *curl;
char errorBuffer[CURL_ERROR_SIZE]; // storage for cUrl error message
+ FILE* theFile;
+
+ Gtk::HBox progress_hbox;
+ Gtk::ProgressBar progress_bar;
+ Gtk::Button cancel_download_btn;
+
+ bool cancel_download;
+ void cancelDownload() {
+ cancel_download = true;
+ progress_hbox.hide();
+ }
+
std::string basePath;
std::string xmlLocation;
};
diff --git a/gtk2_ardour/sfdb_ui.cc b/gtk2_ardour/sfdb_ui.cc
index 85b4f7d..e8db9d4 100644
--- a/gtk2_ardour/sfdb_ui.cc
+++ b/gtk2_ardour/sfdb_ui.cc
@@ -80,6 +80,7 @@ using namespace Editing;
using std::string;
string SoundFileBrowser::persistent_folder;
+typedef TreeView::Selection::ListHandle_Path ListPath;
static ImportMode
string2importmode (string str)
@@ -512,8 +513,6 @@ SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persi
found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
- freesound_stop_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_stop_clicked));
-
notebook.append_page (*vbox, _("Search Tags"));
#ifdef FREESOUND
@@ -555,9 +554,9 @@ SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persi
freesound_more_btn.set_label(_("More"));
freesound_more_btn.set_sensitive(false);
- passbox->pack_end (freesound_stop_btn, false, false);
- freesound_stop_btn.set_label(_("Stop"));
- freesound_stop_btn.set_sensitive(false);
+ passbox->pack_start (freesound_similar_btn, false, false);
+ freesound_similar_btn.set_label(_("Similar"));
+ freesound_similar_btn.set_sensitive(false);
scroll = manage(new ScrolledWindow);
scroll->add(freesound_list_view);
@@ -566,9 +565,8 @@ SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persi
vbox = manage(new VBox);
vbox->set_spacing (3);
vbox->pack_start (*passbox, PACK_SHRINK);
- vbox->pack_start (freesound_progress_bar, PACK_SHRINK);
vbox->pack_start (*scroll);
-
+
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);
@@ -577,20 +575,22 @@ SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persi
freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
freesound_list_view.append_column(_("License"), freesound_list_columns.license);
freesound_list_view.get_column(0)->set_alignment(0.5);
- freesound_list_view.get_column(1)->set_expand(true);
+ freesound_list_view.get_column(1)->set_expand(true); // filename
+ freesound_list_view.get_column(1)->set_resizable(true); // filename
freesound_list_view.get_column(2)->set_alignment(0.5);
freesound_list_view.get_column(3)->set_alignment(0.5);
freesound_list_view.get_column(4)->set_alignment(0.5);
freesound_list_view.get_column(5)->set_alignment(0.5);
freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
+ freesound_list_view.set_tooltip_column(1);
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_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
- freesound_stop_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_stop_clicked));
+ freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
notebook.append_page (*vbox, _("Search Freesound"));
#endif
@@ -787,7 +787,7 @@ SoundFileBrowser::found_list_view_selected ()
} else {
string file;
- TreeView::Selection::ListHandle_Path rows = found_list_view.get_selection()->get_selected_rows ();
+ ListPath rows = found_list_view.get_selection()->get_selected_rows ();
if (!rows.empty()) {
TreeIter iter = found_list->get_iter(*rows.begin());
@@ -803,55 +803,6 @@ SoundFileBrowser::found_list_view_selected ()
}
void
-SoundFileBrowser::freesound_list_view_selected ()
-{
- freesound_download_cancel = false;
- freesound_stop_btn.set_sensitive(true);
-
-#ifdef FREESOUND
- if (!reset_options ()) {
- set_action_sensitive (false);
- } else {
- Mootcher mootcher;
- 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());
-
- 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 = mootcher.getAudioFile(ofn, id, uri, this);
-
- gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
-
- if (file != "") {
- chooser.set_filename (file);
- set_action_sensitive (true);
- }
- } else {
- set_action_sensitive (false);
- }
-
- freesound_progress_bar.set_text(
- string_compose(P_("found %1 match", "found %1 matches", matches), matches));
-
- preview.setup_labels (file);
- }
-#endif
- freesound_stop_btn.set_sensitive(false);
-}
-
-void
SoundFileBrowser::found_search_clicked ()
{
string tag_string = found_entry.get_text ();
@@ -875,6 +826,91 @@ SoundFileBrowser::found_search_clicked ()
}
}
+
+std::string
+SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
+{
+
+ Mootcher *mootcher = new Mootcher;
+ std::string file;
+
+ string id = (*iter)[freesound_list_columns.id];
+ string uri = (*iter)[freesound_list_columns.uri];
+ string ofn = (*iter)[freesound_list_columns.filename];
+
+ if (mootcher->checkAudioFile(ofn, id)) {
+ // file already exists, no need to download it again
+ file = mootcher->audioFileName;
+ delete mootcher;
+ (*iter)[freesound_list_columns.started] = false;
+ return file;
+ }
+ if (!(*iter)[freesound_list_columns.started]) {
+ // start downloading the sound file
+ (*iter)[freesound_list_columns.started] = true;
+ mootcher->fetchAudioFile(ofn, id, uri, this);
+ }
+ return "";
+}
+
+void
+SoundFileBrowser::freesound_list_view_selected ()
+{
+
+ if (!reset_options ()) {
+ set_action_sensitive (false);
+ } else {
+ std::string file;
+ ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
+ for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
+ file = freesound_get_audio_file (freesound_list->get_iter(*i));
+ }
+
+ switch (rows.size()) {
+ case 0:
+ // nothing selected
+ freesound_similar_btn.set_sensitive(false);
+ set_action_sensitive (false);
+ break;
+ case 1:
+ // exactly one item selected
+ if (file != "") {
+ // file exists on disk already
+ chooser.set_filename (file);
+ preview.setup_labels (file);
+ set_action_sensitive (true);
+ }
+ freesound_similar_btn.set_sensitive(true);
+ break;
+ default:
+ // multiple items selected
+ preview.setup_labels ("");
+ freesound_similar_btn.set_sensitive(false);
+ break;
+ }
+
+ }
+}
+
+void
+SoundFileBrowser::refresh_display(std::string ID, std::string file)
+{
+ // called when the mootcher has finished downloading a file
+ ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
+ if (rows.size() == 1) {
+ // there's a single item selected in the freesound list
+ //XXX make a function to be used to construct the actual file name both here and in the mootcher
+ Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
+ std::string selected_ID = (*row)[freesound_list_columns.id];
+ if (ID == selected_ID) {
+ // the selected item in the freesound list is the item that has just finished downloading
+ chooser.set_filename(file);
+ preview.setup_labels (file);
+ set_action_sensitive (true);
+ }
+ }
+}
+
void
SoundFileBrowser::freesound_search_clicked ()
{
@@ -895,18 +931,32 @@ SoundFileBrowser::freesound_more_clicked ()
}
void
-SoundFileBrowser::freesound_stop_clicked ()
+SoundFileBrowser::freesound_similar_clicked ()
{
- freesound_download_cancel = true;
+ ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
+ if (rows.size() == 1) {
+ Mootcher mootcher;
+ string id;
+ Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
+ id = (*iter)[freesound_list_columns.id];
+ freesound_list->clear();
+
+ 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();
+
+ std::string theString = mootcher.searchSimilar(id);
+
+ gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
+ handle_freesound_results(theString);
+ }
}
-
void
SoundFileBrowser::freesound_search()
{
-#ifdef FREESOUND
Mootcher mootcher;
- freesound_list_view.get_column(1)->set_sizing(TREE_VIEW_COLUMN_GROW_ONLY);
string search_string = freesound_entry.get_text ();
enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
@@ -914,7 +964,6 @@ SoundFileBrowser::freesound_search()
GdkCursor *prev_cursor;
prev_cursor = gdk_window_get_cursor (get_window()->gobj());
gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
- freesound_progress_bar.set_fraction(0.0);
gdk_flush();
std::string theString = mootcher.searchText(
@@ -929,7 +978,11 @@ SoundFileBrowser::freesound_search()
);
gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
+ handle_freesound_results(theString);
+}
+void
+SoundFileBrowser::handle_freesound_results(std::string theString) {
XMLTree doc;
doc.read_buffer( theString );
XMLNode *root = doc.root();
@@ -1065,14 +1118,6 @@ SoundFileBrowser::freesound_search()
matches++;
}
}
-
- if (matches == 0) {
- freesound_progress_bar.set_text(_("Search returned no results."));
- } else {
- freesound_progress_bar.set_text(string_compose(P_("Found %1 match", "Found %1 matches", matches), matches));
- }
- freesound_list_view.get_column(1)->set_sizing(TREE_VIEW_COLUMN_AUTOSIZE);
-#endif
}
vector<string>
@@ -1093,9 +1138,7 @@ SoundFileBrowser::get_paths ()
}
}
- } else if (n==1){
-
- typedef TreeView::Selection::ListHandle_Path ListPath;
+ } else if (n == 1) {
ListPath rows = found_list_view.get_selection()->get_selected_rows ();
for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
@@ -1106,28 +1149,12 @@ SoundFileBrowser::get_paths ()
}
} else {
#ifdef FREESOUND
- typedef TreeView::Selection::ListHandle_Path ListPath;
- Mootcher mootcher;
-
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 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 = mootcher.getAudioFile(ofn, id, uri, this);
+ string str = freesound_get_audio_file (freesound_list->get_iter(*i));
if (str != "") {
results.push_back (str);
}
-
- gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
-
}
#endif
}
diff --git a/gtk2_ardour/sfdb_ui.h b/gtk2_ardour/sfdb_ui.h
index bed800a..5d8decd 100644
--- a/gtk2_ardour/sfdb_ui.h
+++ b/gtk2_ardour/sfdb_ui.h
@@ -131,6 +131,7 @@ class SoundFileBrowser : public ArdourWindow
Gtk::TreeModelColumn<std::string> filesize;
Gtk::TreeModelColumn<std::string> smplrate;
Gtk::TreeModelColumn<std::string> license;
+ Gtk::TreeModelColumn<bool> started;
FreesoundColumns() {
add(id);
@@ -140,6 +141,7 @@ class SoundFileBrowser : public ArdourWindow
add(filesize);
add(smplrate);
add(license);
+ add(started);
}
};
@@ -150,8 +152,9 @@ class SoundFileBrowser : public ArdourWindow
Glib::RefPtr<Gtk::ListStore> freesound_list;
Gtk::Button freesound_more_btn;
- Gtk::Button freesound_stop_btn;
+ Gtk::Button freesound_similar_btn;
+ void handle_freesound_results(std::string theString);
public:
SoundFileBrowser (std::string title, ARDOUR::Session* _s, bool persistent);
virtual ~SoundFileBrowser ();
@@ -177,11 +180,10 @@ class SoundFileBrowser : public ArdourWindow
Gtk::Button freesound_search_btn;
Gtk::TreeView freesound_list_view;
- Gtk::ProgressBar freesound_progress_bar;
-
- bool freesound_download_cancel;
+ Gtk::Notebook notebook;
void freesound_search();
+ void refresh_display(std::string ID, std::string file);
protected:
bool resetting_ourselves;
@@ -203,7 +205,6 @@ class SoundFileBrowser : public ArdourWindow
static std::string persistent_folder;
- Gtk::Notebook notebook;
GainMeter* gm;
Gtk::VBox meter_packer;
@@ -224,10 +225,11 @@ class SoundFileBrowser : public ArdourWindow
void freesound_list_view_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*);
void freesound_search_clicked ();
void freesound_more_clicked ();
- void freesound_stop_clicked ();
+ void freesound_similar_clicked ();
int freesound_page;
void chooser_file_activated ();
+ std::string freesound_get_audio_file(Gtk::TreeIter iter);
bool on_audio_filter (const Gtk::FileFilter::Info& filter_info);
bool on_midi_filter (const Gtk::FileFilter::Info& filter_info);
diff --git a/libs/ardour/ardour/rc_configuration_vars.h b/libs/ardour/ardour/rc_configuration_vars.h
index f19f8fe..d8440f2 100644
--- a/libs/ardour/ardour/rc_configuration_vars.h
+++ b/libs/ardour/ardour/rc_configuration_vars.h
@@ -192,6 +192,7 @@ CONFIG_VARIABLE (bool, sound_midi_notes, "sound-midi-notes", false)
CONFIG_VARIABLE (bool, use_plugin_own_gui, "use-plugin-own-gui", true)
CONFIG_VARIABLE (uint32_t, max_recent_sessions, "max-recent-sessions", 10)
CONFIG_VARIABLE (double, automation_thinning_factor, "automation-thinning-factor", 20.0)
+CONFIG_VARIABLE (std::string, freesound_download_dir, "freesound-download-dir", Glib::get_home_dir() + "/Freesound/snd")
/* denormal management */
|
|
|
Argh... forgot to save files before running git diff the first time: second attempt should actually compile... |
|
|
Colin, Why don't you just push the branch to git? You don't need to push to master at first.. |
|
|
Err, yes, good question... Mostly because I'm not sufficiently comfortable yet with git to feel confident enough to do stuff directly on git.ardour.org: messing around in my own clone of the repository is one thing, but messing around with the mothership is quite a bit more scary. Also, Paul said once before that, at least for smallish stuff (which this almost certainly qualifies as), pushing direct to master was the right thing to do, so reporting here was basically a statement of intent before I went ahead. Anyway, assuming that pushing to a branch really would be a sensible course: now I've got commits locally on top of master, how would I push those to a remote branch on git.ardour.org? |
|
|
i don't believe that this work requires a branch. there are insufficient testers for this to be productively done in a branch. |
|
|
Paul, I suggested the branch. Mainly for code-readability of multiple incremental patches. Having the patches in git is IMHO much better than attachments here. Why not master? Same answer as to the question "why post patches to mantis and not just apply it". Anyway, temporary topic-development branches - even for small things - are not a bad thing and they're cheap in git. |
|
|
Paul: I didn't want to push a half-baked patch directly onto master, but I did want to put it somewhere where anyone with more knowledge than I and a few minutes to spare could have a look, for which purpose a branch seemed to work pretty well. |
|
|
branches are cheap, yes. but then they don't get tested in the same way as stuff that lands in master. i suppose that the choice really comes down the likely lifetime of the development branch. if it is just a way to collect together a few days of related work OR if it is a long lived alternate (e.g. the cairocanvas branch), then branching makes sense i suppose. |
|
|
'Similar' search button (and a few other improvements besides) added in commit 9a9f4276. |
|
|
Issue has been closed automatically, by Trigger Close Plugin. Feel free to re-open with additional information if you think the issue is not resolved. |
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2013-03-14 14:04 | colinf | New Issue | |
| 2013-03-15 14:39 | colinf | Note Added: 0014720 | |
| 2013-03-15 14:41 | colinf | Note Added: 0014721 | |
| 2013-03-16 15:23 | colinf | File Added: freesound-tweaks-5853.diff | |
| 2013-03-16 15:24 | colinf | Note Added: 0014728 | |
| 2013-04-05 12:43 | colinf | Note Added: 0014811 | |
| 2013-06-14 17:35 | colinf | Note Added: 0014994 | |
| 2013-06-14 17:38 | colinf | File Added: freesound-tweaks-20130614.patch | |
| 2013-06-14 17:56 | colinf | File Added: freesound-tweaks-20130614-2.patch | |
| 2013-06-14 17:57 | colinf | Note Added: 0014995 | |
| 2013-06-15 13:50 | x42 | Note Added: 0014998 | |
| 2013-06-15 18:43 | colinf | Note Added: 0015000 | |
| 2013-06-17 02:57 | paul | Note Added: 0015006 | |
| 2013-06-17 07:44 | x42 | Note Added: 0015009 | |
| 2013-06-17 11:42 | colinf | Note Added: 0015011 | |
| 2013-06-17 12:24 | paul | Note Added: 0015012 | |
| 2013-06-27 17:06 | colinf | Note Added: 0015058 | |
| 2013-06-27 17:06 | colinf | Status | new => resolved |
| 2013-06-27 17:06 | colinf | Resolution | open => fixed |
| 2013-06-27 17:06 | colinf | Assigned To | => colinf |
| 2020-04-19 20:16 | system | Note Added: 0023203 | |
| 2020-04-19 20:16 | system | Status | resolved => closed |