From cd89c6e3bf1e6c4b786b6ee89bc5fa9a0e780d61 Mon Sep 17 00:00:00 2001 From: Ben Loftis Date: Mon, 24 Mar 2008 00:19:03 +0000 Subject: [PATCH] initial checkin of freesound integration git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@3168 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/SConscript | 12 + gtk2_ardour/sfdb_freesound_mootcher.cc | 489 +++++++++++++++++++++++++ gtk2_ardour/sfdb_freesound_mootcher.h | 79 ++++ gtk2_ardour/sfdb_ui.cc | 287 ++++++++++++--- gtk2_ardour/sfdb_ui.h | 24 +- 5 files changed, 843 insertions(+), 48 deletions(-) create mode 100644 gtk2_ardour/sfdb_freesound_mootcher.cc create mode 100644 gtk2_ardour/sfdb_freesound_mootcher.h diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript index e390845d9d..7991500fa5 100644 --- a/gtk2_ardour/SConscript +++ b/gtk2_ardour/SConscript @@ -79,6 +79,10 @@ if gtkardour['FFT_ANALYSIS']: gtkardour.Merge ([libraries['fftw3f']]) gtkardour.Append(CCFLAGS='-DFFT_ANALYSIS') +if gtkardour['FREESOUND']: + gtkardour.Merge ([libraries['curl']]) + gtkardour.Append(CCFLAGS='-DFREESOUND') + if gtkardour['RUBBERBAND']: gtkardour.Merge ([ libraries['rubberband'] ]) else: @@ -237,6 +241,10 @@ fft_graph.cc fft_result.cc """) +freesound_files=Split(""" +sfdb_freesound_mootcher.cc +""") + pixmap_files = glob.glob('pixmaps/*.xpm') icon_files = glob.glob ('icons/*.png') @@ -297,6 +305,9 @@ else: if env['FFT_ANALYSIS']: extra_sources += fft_analysis_files +if env['FREESOUND']: + extra_sources += freesound_files + intl_files += extra_sources gtkardour.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE") @@ -533,6 +544,7 @@ env.Alias ('tarball', env.Distribute (env['DISTTREE'], gtkosx_files + x11_files + fft_analysis_files + + freesound_files + glob.glob('po/*.po') + glob.glob('*.h'))) # generate a prototype full-featured ardour_ui.rc file diff --git a/gtk2_ardour/sfdb_freesound_mootcher.cc b/gtk2_ardour/sfdb_freesound_mootcher.cc new file mode 100644 index 0000000000..c9e04c14d5 --- /dev/null +++ b/gtk2_ardour/sfdb_freesound_mootcher.cc @@ -0,0 +1,489 @@ +/* sfdb_freesound_mootcher.cpp ********************************************************************** + + Adapted for Ardour by Ben Loftis, March 2008 + + Mootcher 23-8-2005 + + 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 + + ----------------------------------------------------------------- + + Includes: + curl.h (version 7.14.0) + Librarys: + libcurl.lib + + ----------------------------------------------------------------- + Licence GPL: + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +*************************************************************************************/ +#include "sfdb_freesound_mootcher.h" + +#include + +#include +#include + +#include + +#define TRUE 1 + +//------------------------------------------------------------------------ +Mootcher:: Mootcher(const char *saveLocation) + : curl( NULL ) + , connection( NULL ) +{ + changeWorkingDir(saveLocation); +}; +//------------------------------------------------------------------------ +Mootcher:: ~Mootcher() +{ + remove( "cookiejar.txt" ); +} +//------------------------------------------------------------------------ +const char* Mootcher::changeWorkingDir(const char *saveLocation) +{ + basePath = saveLocation; +#ifdef __WIN32__ + std::string replace = "/"; + int pos = (int)basePath.find("\\"); + while( pos != std::string::npos ){ + basePath.replace(pos, 1, replace); + pos = (int)basePath.find("\\"); + } +#endif + // + int pos2 = basePath.find_last_of("/"); + if(basePath.length() != (pos2+1)) basePath += "/"; + // add a check if the given directory exists + createResourceLocation(); + return basePath.c_str(); +} + +//------------------------------------------------------------------------ +void Mootcher::createResourceLocation() +{ + // create a snd directory + std::string sndLocation = basePath + "snd"; + mkdir(sndLocation.c_str(), 0x777); +} + +//------------------------------------------------------------------------ +size_t Mootcher::WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data) +{ + register int realsize = (int)(size * nmemb); + struct MemoryStruct *mem = (struct MemoryStruct *)data; + + // There might be a realloc() out there that doesn't like + // reallocing NULL pointers, so we take care of it here + if(mem->memory) mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1); + else mem->memory = (char *)malloc(mem->size + realsize + 1); + + if (mem->memory) { + memcpy(&(mem->memory[mem->size]), ptr, realsize); + mem->size += realsize; + mem->memory[mem->size] = 0; + } + return realsize; +} + + +//------------------------------------------------------------------------ +void Mootcher::toLog(std::string input) +{ +//printf("%s", input.c_str());// for debugging +} + + +//------------------------------------------------------------------------ +void Mootcher::setcUrlOptions() +{ + // basic init for curl + curl_global_init(CURL_GLOBAL_ALL); + // some servers don't like requests that are made without a user-agent field, so we provide one + curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0"); + // setup curl error buffer + CURLcode res = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer); + // always use the cookie with session id which is received at the login + curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "cookiejar.txt"); + // Allow redirection + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); +} + +//------------------------------------------------------------------------ +int Mootcher::doLogin(std::string login, std::string password) +{ + if(connection==1) + return 1; + + struct MemoryStruct xml_page; + xml_page.memory = NULL; + xml_page.size = NULL; + + // create the post message from the login and password + std::string postMessage; + postMessage += "username="; + postMessage += curl_escape(login.c_str(), 0); + postMessage += "&password="; + postMessage += curl_escape(password.c_str(), 0); + postMessage += "&login="; + postMessage += curl_escape("1", 0); + postMessage += "&redirect="; + postMessage += curl_escape("../tests/login.php", 0); + + // Do the setup for libcurl + curl = curl_easy_init(); + + if(curl) + { + setcUrlOptions(); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&xml_page); + // use POST for login variables + curl_easy_setopt(curl, CURLOPT_POST, TRUE); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postMessage.c_str()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1); + + // the url to get + std::string login_url = "http://freesound.iua.upf.edu/forum/login.php"; + curl_easy_setopt(curl, CURLOPT_URL, login_url.c_str() ); + + // perform online request + CURLcode res = curl_easy_perform(curl); + // if something goes wrong 'connection' is set to '0' + if(strcmp(curl_easy_strerror(res), "no error") == 0) connection = 1; + else connection = 0; + + if (connection == 1){ + std::string check_page = xml_page.memory; + int test = (int)check_page.find("login"); //logged + if( test != -1){ + sprintf(message, "Login: %s\n", xml_page.memory); + toLog(message); + } + else { + sprintf(message, "Login: Check username and password\n"); + toLog(message); + connection = 0; + } + } + + // free the memory + if(xml_page.memory){ + free( xml_page.memory ); + xml_page.memory = NULL; + xml_page.size = NULL; + } + + return connection; + } + else return 3; // will be returned if a curl related problem ocurrs +} +//------------------------------------------------------------------------ +std::string Mootcher::searchText(std::string word) +{ + struct MemoryStruct xml_page; + xml_page.memory = NULL; + xml_page.size = NULL; + + std::string result; + + if(connection != 0) + { + // create a url encoded post message + std::string postMessage; + char tempString[ 128 ]; + char *tempPointer = &tempString[0]; + + postMessage = "search="; + postMessage += curl_escape(word.c_str(), 0); + sprintf( tempPointer, "&searchDescriptions=1"); + postMessage += tempPointer; + sprintf( tempPointer, "&searchtags=1"); + postMessage += tempPointer; + + if(curl) + { + // basic init for curl + setcUrlOptions(); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&xml_page); + // setup the post message + curl_easy_setopt(curl, CURLOPT_POST, TRUE); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postMessage.c_str()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1); + + // the url to get + std::string search_url = "http://freesound.iua.upf.edu/searchTextXML.php"; + curl_easy_setopt(curl, CURLOPT_URL, search_url.c_str()); + + // perform the online search + CURLcode res = curl_easy_perform(curl); + if(strcmp(curl_easy_strerror(res), "no error") == 0) connection = 1; + else connection = 0; + + result = xml_page.memory; +//printf("%s/n", result.c_str()); + + // free the memory + if(xml_page.memory){ + free( xml_page.memory ); + xml_page.memory = NULL; + xml_page.size = NULL; + } + + } + } + + return result; +} + +//------------------------------------------------------------------------ +std::string Mootcher::changeExtension(std::string filename) +{ + std::string aiff = ".aiff"; + std::string aif = ".aif"; + std::string wav = ".wav"; + std::string mp3 = ".mp3"; + std::string ogg = ".ogg"; + std::string flac = ".flac"; + + std::string replace = ".xml"; + int pos = 0; + + pos = (int)filename.find(aiff); + if(pos != std::string::npos) filename.replace(pos, aiff.size(), replace); + pos = (int)filename.find(aif); + if(pos != std::string::npos) filename.replace(pos, aif.size(), replace); + pos = (int)filename.find(wav); + if(pos != std::string::npos) filename.replace(pos, wav.size(), replace); + pos = (int)filename.find(mp3); + if(pos != std::string::npos) filename.replace(pos, mp3.size(), replace); + pos = (int)filename.find(ogg); + if(pos != std::string::npos) filename.replace(pos, ogg.size(), replace); + pos = (int)filename.find(flac); + if(pos != std::string::npos) filename.replace(pos, flac.size(), replace); + + return filename; +} +//------------------------------------------------------------------------ +void Mootcher::GetXml(std::string ID, struct MemoryStruct &xml_page) +{ + + if(curl) { + setcUrlOptions(); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&xml_page); + + // URL to get + std::string getxml_url = "http://freesound.iua.upf.edu/samplesViewSingleXML.php?id="; + getxml_url += ID; + + curl_easy_setopt(curl, CURLOPT_URL, getxml_url.c_str() ); + + // get it! + CURLcode res = curl_easy_perform(curl); + if(strcmp(curl_easy_strerror(res), "no error") == 0) connection = 1; + else connection = 0; + } +} +//------------------------------------------------------------------------ +std::string Mootcher::getXmlFile(std::string ID, int &length) +{ + struct MemoryStruct xml_page; + xml_page.memory = NULL; + xml_page.size = NULL; + + std::string xmlFileName; + std::string audioFileName; + std::string filename; + + if(connection != 0) { + // download the xmlfile into xml_page + GetXml(ID, xml_page); + + // if sample ID does not exist on the freesound website + if(strcmp(xml_page.memory, "sample non existant") == 0){ + free( xml_page.memory ); + sprintf(message, "getXmlFile: sample with ID:%s does not exist!\n", ID.c_str() ); + toLog(message); + return filename; + } else { + XMLTree doc; + doc.read_buffer( xml_page.memory ); + XMLNode *freesound = doc.root(); + + // if the page is not a valid xml document with a 'freesound' root + if( freesound == NULL){ + sprintf(message, "getXmlFile: There is no valid root in the xml file"); + toLog(message); + } else { + XMLNode *sample = freesound->child("sample"); + XMLNode *name = NULL; + XMLNode *filesize = NULL; + if (sample) { + name = sample->child("originalFilename"); + filesize = sample->child("filesize"); + } + + // get the file name and size from xml file + if (sample && name && filesize) { + + audioFileName = name->child("text")->content(); + sprintf( message, "getXmlFile: %s needs to be downloaded\n", audioFileName.c_str() ); + toLog(message); + + length = atoi(filesize->child("text")->content().c_str()); + + // create new filename with the ID number + filename = basePath; + filename += "snd/"; + filename += sample->property("id")->value(); + filename += "-"; + filename += audioFileName; + // change the extention into .xml + xmlFileName = changeExtension( filename ); + + sprintf(message, "getXmlFile: saving XML: %s\n", xmlFileName.c_str() ); + toLog(message); + + // save the xml file to disk + doc.write(xmlFileName.c_str()); + + //store all the tags in the database + XMLNode *tags = sample->child("tags"); + if (tags) { + XMLNodeList children = tags->children(); + XMLNodeConstIterator niter; + vector strings; + for (niter = children.begin(); niter != children.end(); ++niter) { + XMLNode *node = *niter; + if( strcmp( node->name().c_str(), "tag") == 0 ) { + XMLNode *text = node->child("text"); + if (text) strings.push_back(text->content()); + } + } + ARDOUR::Library->set_tags (string("//")+filename, strings); + ARDOUR::Library->save_changes (); + } + } + + // clear the memory + if(xml_page.memory){ + free( xml_page.memory ); + xml_page.memory = NULL; + xml_page.size = 0; + } + return audioFileName; + } + } + } + else { + return audioFileName; + } + +} + +int audioFileWrite(void *buffer, size_t size, size_t nmemb, void *file) +{ + return (int)fwrite(buffer, size, nmemb, (FILE*) file); +}; + +//------------------------------------------------------------------------ +std::string Mootcher::getFile(std::string ID) +{ + CURLcode result_curl; + + std::string audioFileName; + + if(connection != 0) + { + int length; + std::string name = getXmlFile(ID, length); + if( name != "" ){ + + // create new filename with the ID number + audioFileName += basePath; + audioFileName += "snd/"; + audioFileName += ID; + audioFileName += "-"; + audioFileName += name; + + //check to see if audio file already exists + FILE *testFile = fopen(audioFileName.c_str(), "r"); + if (testFile) { //TODO: should also check length to see if file is complete + fseek (testFile , 0 , SEEK_END); + if (ftell (testFile) == length) { + sprintf(message, "%s already exists\n", audioFileName.c_str() ); + toLog(message); + fclose (testFile); + return audioFileName; + } else { + remove( audioFileName.c_str() ); //file was not correct length, delete it and try again + } + } + + + //now download the actual file + if (curl) { + + FILE* theFile; + theFile = fopen( audioFileName.c_str(), "wb" ); + + // create the download url, this url will also update the download statics on the site + std::string audioURL; + audioURL += "http://freesound.iua.upf.edu/samplesDownload.php?id="; + audioURL += ID; + + setcUrlOptions(); + curl_easy_setopt(curl, CURLOPT_URL, audioURL.c_str() ); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, audioFileWrite); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, theFile); + CURLcode res = curl_easy_perform(curl); + if(strcmp(curl_easy_strerror(res), "no error") == 0) connection = 1; + else connection = 0; + + fclose(theFile); + } + +/* + bar.dlnowMoo = 0; + bar.dltotalMoo = 0; + curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 0); // turn on the process bar thingy + curl_easy_setopt (curl, CURLOPT_PROGRESSFUNCTION, progress_callback); + curl_easy_setopt (curl, CURLOPT_PROGRESSDATA, &bar); +*/ + } + } + + return audioFileName; +} + +//--------- +int Mootcher::progress_callback(void *bar, double dltotal, double dlnow, double ultotal, double ulnow) +{ + struct dlprocess *lbar = (struct dlprocess *) bar; + lbar->dltotalMoo = dltotal; + lbar->dlnowMoo = dlnow; + return 0; +} diff --git a/gtk2_ardour/sfdb_freesound_mootcher.h b/gtk2_ardour/sfdb_freesound_mootcher.h new file mode 100644 index 0000000000..af5f4e0bab --- /dev/null +++ b/gtk2_ardour/sfdb_freesound_mootcher.h @@ -0,0 +1,79 @@ +/*sfdb_freesound_mootcher.h**************************************************************************** + + Adapted for Ardour by Ben Loftis, March 2008 + + 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 +#include +#include +#include +#include +#include +#include +#include +//#include + +#include "curl/curl.h" + + +// mootcher version +#define ___VERSION___ 1.3 + +//--- struct to store XML file +struct MemoryStruct { + char *memory; + size_t size; +}; + +//--- for download process viewing +struct dlprocess { + double dltotalMoo; + double dlnowMoo; +}; + +class Mootcher +{ +public: + Mootcher(const char *saveLocation); + ~Mootcher(); + + int doLogin(std::string login, std::string password); + std::string getFile(std::string ID); + std::string searchText(std::string word); + + + struct dlprocess bar; + +private: + + const char* changeWorkingDir(const char *saveLocation); + void createResourceLocation(); + + std::string getXmlFile(std::string ID, int &length); + void GetXml(std::string ID, struct MemoryStruct &xml_page); + std::string changeExtension(std::string filename); + + void toLog(std::string input); + + 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); + + CURL *curl; + char errorBuffer[CURL_ERROR_SIZE]; // storage for cUrl error message + + int connection; // is 0 if no connection + char message[128]; // storage for messages that are send to the logfile + + std::string basePath; + std::string xmlLocation; +}; diff --git a/gtk2_ardour/sfdb_ui.cc b/gtk2_ardour/sfdb_ui.cc index d40487e5f5..7b8babca58 100644 --- a/gtk2_ardour/sfdb_ui.cc +++ b/gtk2_ardour/sfdb_ui.cc @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include @@ -52,6 +54,10 @@ #include "utils.h" #include "gain_meter.h" +#ifdef FREESOUND +#include "sfdb_freesound_mootcher.h" +#endif + #include "i18n.h" using namespace ARDOUR; @@ -386,70 +392,138 @@ SoundFileBox::save_tags (const vector& tags) SoundFileBrowser::SoundFileBrowser (Gtk::Window& parent, string title, ARDOUR::Session* s, bool persistent) : ArdourDialog (parent, title, false, false), found_list (ListStore::create(found_list_columns)), + freesound_list (ListStore::create(freesound_list_columns)), chooser (FILE_CHOOSER_ACTION_OPEN), found_list_view (found_list), + freesound_list_view (freesound_list), preview (persistent), - found_search_btn (_("Search")) + found_search_btn (_("Search")), + freesound_search_btn (_("Start Downloading")) { + resetting_ourselves = false; + gm = 0; + if (ARDOUR::Profile->get_sae()) { chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops"); chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files"); } - VBox* vbox; - HBox* hbox; + //add the file chooser + { + chooser.set_border_width (12); + custom_filter.add_custom (FILE_FILTER_FILENAME, mem_fun(*this, &SoundFileBrowser::on_custom)); + custom_filter.set_name (_("Audio files")); - gm = 0; + matchall_filter.add_pattern ("*.*"); + matchall_filter.set_name (_("All files")); - set_session (s); - resetting_ourselves = false; + chooser.add_filter (custom_filter); + chooser.add_filter (matchall_filter); + chooser.set_select_multiple (true); + chooser.signal_update_preview().connect(mem_fun(*this, &SoundFileBrowser::update_preview)); + chooser.signal_file_activated().connect (mem_fun (*this, &SoundFileBrowser::chooser_file_activated)); + + if (!persistent_folder.empty()) { + chooser.set_current_folder (persistent_folder); + } + notebook.append_page (chooser, _("Browse Files")); + } - hpacker.set_spacing (6); - hpacker.pack_start (notebook, true, true); - hpacker.pack_start (preview, false, false); + //add tag search + { + VBox* vbox; + HBox* hbox; - get_vbox()->pack_start (hpacker, true, true); + hpacker.set_spacing (6); + hpacker.pack_start (notebook, true, true); + hpacker.pack_start (preview, false, false); - hbox = manage(new HBox); - hbox->pack_start (found_entry); - hbox->pack_start (found_search_btn); + get_vbox()->pack_start (hpacker, true, true); + + hbox = manage(new HBox); + hbox->pack_start (found_entry); + hbox->pack_start (found_search_btn); + + Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow); + scroll->add(found_list_view); + scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + + vbox = manage(new VBox); + vbox->pack_start (*hbox, PACK_SHRINK); + vbox->pack_start (*scroll); + + found_list_view.append_column(_("Paths"), found_list_columns.pathname); + + found_list_view.get_selection()->signal_changed().connect(mem_fun(*this, &SoundFileBrowser::found_list_view_selected)); + + found_list_view.signal_row_activated().connect (mem_fun (*this, &SoundFileBrowser::found_list_view_activated)); + + found_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked)); + found_entry.signal_activate().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked)); + + notebook.append_page (*vbox, _("Search Tags")); + } - vbox = manage(new VBox); - vbox->pack_start (*hbox, PACK_SHRINK); - vbox->pack_start (found_list_view); - found_list_view.append_column(_("Paths"), found_list_columns.pathname); - - chooser.set_border_width (12); + //add freesound search +#ifdef FREESOUND + { + VBox* vbox; + HBox* passbox; + Label* label; - notebook.append_page (chooser, _("Browse Files")); - notebook.append_page (*vbox, _("Search Tags")); + hpacker.set_spacing (6); + hpacker.pack_start (notebook, true, true); + hpacker.pack_start (preview, false, false); + + get_vbox()->pack_start (hpacker, true, true); + + passbox = manage(new HBox); + passbox->set_border_width (12); + passbox->set_spacing (6); + + label = manage (new Label); + label->set_text (_("User:")); + passbox->pack_start (*label, false, false); + passbox->pack_start (freesound_name_entry); + label = manage (new Label); + label->set_text (_("Password:")); + passbox->pack_start (*label, false, false); + passbox->pack_start (freesound_pass_entry); + label = manage (new Label); + label->set_text (_("Tags:")); + passbox->pack_start (*label, false, false); + passbox->pack_start (freesound_entry, false, false); + passbox->pack_start (freesound_search_btn, false, false); + + Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow); + scroll->add(freesound_list_view); + scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + + vbox = manage(new VBox); + vbox->pack_start (*passbox, PACK_SHRINK); + vbox->pack_start(*scroll); + + //vbox->pack_start (freesound_list_view); + + freesound_list_view.append_column(_("Paths"), freesound_list_columns.pathname); + + freesound_list_view.get_selection()->signal_changed().connect(mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected)); + + //freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE); + freesound_list_view.signal_row_activated().connect (mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated)); + + freesound_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::freesound_search_clicked)); + freesound_entry.signal_activate().connect(mem_fun(*this, &SoundFileBrowser::freesound_search_clicked)); + + notebook.append_page (*vbox, _("Search Freesound")); + } +#endif + notebook.set_size_request (500, -1); - found_list_view.get_selection()->set_mode (SELECTION_MULTIPLE); - found_list_view.signal_row_activated().connect (mem_fun (*this, &SoundFileBrowser::found_list_view_activated)); - - custom_filter.add_custom (FILE_FILTER_FILENAME, mem_fun(*this, &SoundFileBrowser::on_custom)); - custom_filter.set_name (_("Audio files")); - - matchall_filter.add_pattern ("*.*"); - matchall_filter.set_name (_("All files")); - - chooser.add_filter (custom_filter); - chooser.add_filter (matchall_filter); - chooser.set_select_multiple (true); - chooser.signal_update_preview().connect(mem_fun(*this, &SoundFileBrowser::update_preview)); - chooser.signal_file_activated().connect (mem_fun (*this, &SoundFileBrowser::chooser_file_activated)); - - if (!persistent_folder.empty()) { - chooser.set_current_folder (persistent_folder); - } - - found_list_view.get_selection()->signal_changed().connect(mem_fun(*this, &SoundFileBrowser::found_list_view_selected)); - - found_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked)); - found_entry.signal_activate().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked)); + set_session (s); add_button (Stock::CANCEL, RESPONSE_CANCEL); add_button (Stock::APPLY, RESPONSE_APPLY); @@ -489,6 +563,12 @@ SoundFileBrowser::found_list_view_activated (const TreeModel::Path& path, TreeVi preview.audition (); } +void +SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path& path, TreeViewColumn* col) +{ + preview.audition (); +} + void SoundFileBrowser::set_session (Session* s) { @@ -587,6 +667,29 @@ SoundFileBrowser::found_list_view_selected () } } +void +SoundFileBrowser::freesound_list_view_selected () +{ + if (!reset_options ()) { + set_response_sensitive (RESPONSE_OK, false); + } else { + ustring file; + + TreeView::Selection::ListHandle_Path rows = freesound_list_view.get_selection()->get_selected_rows (); + + if (!rows.empty()) { + TreeIter iter = freesound_list->get_iter(*rows.begin()); + file = (*iter)[freesound_list_columns.pathname]; + chooser.set_filename (file); + set_response_sensitive (RESPONSE_OK, true); + } else { + set_response_sensitive (RESPONSE_OK, false); + } + + preview.setup_labels (file); + } +} + void SoundFileBrowser::found_search_clicked () { @@ -611,6 +714,88 @@ SoundFileBrowser::found_search_clicked () } } +void* +freesound_search_thread_entry (void* arg) +{ + PBD::ThreadCreated (pthread_self(), X_("Freesound Search")); + + static_cast(arg)->freesound_search_thread (); + + return 0; +} + +bool searching = false; +bool canceling = false; + +void +SoundFileBrowser::freesound_search_clicked () +{ + if (canceling) //already canceling, button does nothing + return; + + if ( searching ) { + freesound_search_btn.set_label(_("Canceling..")); + canceling = true; + } else { + searching = true; + freesound_search_btn.set_label(_("Cancel")); + pthread_t freesound_thr; + pthread_create_and_store ("freesound_search", &freesound_thr, 0, freesound_search_thread_entry, this); + } +} + +void +SoundFileBrowser::freesound_search_thread() +{ +#ifdef FREESOUND + freesound_list->clear(); + + string path; + path = Glib::get_home_dir(); + path += "/Freesound/"; + Mootcher theMootcher(path.c_str()); + + string name_string = freesound_name_entry.get_text (); + string pass_string = freesound_pass_entry.get_text (); + string search_string = freesound_entry.get_text (); + + if ( theMootcher.doLogin( name_string, pass_string ) ) { + + string theString = theMootcher.searchText(search_string); + + XMLTree doc; + doc.read_buffer( theString ); + XMLNode *root = doc.root(); + + if (root==NULL) return; + + if ( strcmp(root->name().c_str(), "freesound") == 0) { + + XMLNode *node = 0; + XMLNodeList children = root->children(); + XMLNodeConstIterator niter; + for (niter = children.begin(); niter != children.end() && !canceling; ++niter) { + node = *niter; + if( strcmp( node->name().c_str(), "sample") == 0 ){ + XMLProperty *prop=node->property ("id"); + string filename = theMootcher.getFile( prop->value().c_str() ); + if ( filename != "" ) { + TreeModel::iterator new_row = freesound_list->append(); + TreeModel::Row row = *new_row; + string path = Glib::filename_from_uri (string ("file:") + filename); + row[freesound_list_columns.pathname] = path; + } + } + } + } + } + + searching = false; + canceling = false; + freesound_search_btn.set_label(_("Start Downloading")); +#endif +} + vector SoundFileBrowser::get_paths () { @@ -629,7 +814,7 @@ SoundFileBrowser::get_paths () } } - } else { + } else if (n==1){ typedef TreeView::Selection::ListHandle_Path ListPath; @@ -638,6 +823,17 @@ SoundFileBrowser::get_paths () TreeIter iter = found_list->get_iter(*i); ustring str = (*iter)[found_list_columns.pathname]; + results.push_back (str); + } + } else { + + typedef TreeView::Selection::ListHandle_Path ListPath; + + 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); + ustring str = (*iter)[freesound_list_columns.pathname]; + results.push_back (str); } } @@ -936,6 +1132,7 @@ SoundFileChooser::SoundFileChooser (Gtk::Window& parent, string title, ARDOUR::S { chooser.set_select_multiple (false); found_list_view.get_selection()->set_mode (SELECTION_SINGLE); + freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE); } void diff --git a/gtk2_ardour/sfdb_ui.h b/gtk2_ardour/sfdb_ui.h index 43f76a9ea2..0f164bcb11 100644 --- a/gtk2_ardour/sfdb_ui.h +++ b/gtk2_ardour/sfdb_ui.h @@ -117,6 +117,9 @@ class SoundFileBrowser : public ArdourDialog FoundTagColumns found_list_columns; Glib::RefPtr found_list; + FoundTagColumns freesound_list_columns; + Glib::RefPtr freesound_list; + public: SoundFileBrowser (Gtk::Window& parent, std::string title, ARDOUR::Session* _s, bool persistent); virtual ~SoundFileBrowser (); @@ -127,20 +130,30 @@ class SoundFileBrowser : public ArdourDialog void clear_selection (); Gtk::FileChooserWidget chooser; + + SoundFileBox preview; + + Gtk::Entry found_entry; + Gtk::Button found_search_btn; Gtk::TreeView found_list_view; + Gtk::Entry freesound_name_entry; + Gtk::Entry freesound_pass_entry; + Gtk::Entry freesound_entry; + Gtk::Button freesound_search_btn; + Gtk::TreeView freesound_list_view; + + void freesound_search_thread(); + protected: bool resetting_ourselves; Gtk::FileFilter custom_filter; Gtk::FileFilter matchall_filter; - SoundFileBox preview; Gtk::HBox hpacker; static Glib::ustring persistent_folder; - Gtk::Entry found_entry; - Gtk::Button found_search_btn; Gtk::Notebook notebook; GainMeter* gm; @@ -153,10 +166,15 @@ class SoundFileBrowser : public ArdourDialog sigc::connection metering_connection; void update_preview (); + void found_list_view_selected (); void found_list_view_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*); void found_search_clicked (); + void freesound_list_view_selected (); + void freesound_list_view_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*); + void freesound_search_clicked (); + void chooser_file_activated (); bool on_custom (const Gtk::FileFilter::Info& filter_info);