Merge branch 'master' into cairocanvas
[ardour.git] / gtk2_ardour / sfdb_ui.cc
index a508048fc2c8e34e7b0cd6d0f8f3a12953be7520..84065c69b1b4d8b1192a5a99960baef1da8a7f5e 100644 (file)
 #include <sstream>
 
 #include <unistd.h>
+#include <limits.h>
 #include <sys/stat.h>
-#include <sys/param.h>
 
 #include <gtkmm/box.h>
 #include <gtkmm/stock.h>
+
+#include <glib/gstdio.h>
 #include <glibmm/fileutils.h>
 
 #include "pbd/convert.h"
@@ -64,9 +66,7 @@
 #include "main_clock.h"
 #include "public_editor.h"
 
-#ifdef FREESOUND
 #include "sfdb_freesound_mootcher.h"
-#endif
 
 #include "i18n.h"
 
@@ -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)
@@ -121,7 +122,9 @@ SoundFileBox::SoundFileBox (bool persistent)
          length_clock ("sfboxLengthClock", !persistent, "", false, false, true, false),
          timecode_clock ("sfboxTimecodeClock", !persistent, "", false, false, false, false),
          main_box (false, 6),
-         autoplay_btn (_("Auto-play"))
+         autoplay_btn (_("Auto-play")),
+         seek_slider(0,1000,1),
+         _seeking(false)
 
 {
        set_name (X_("SoundFileBox"));
@@ -199,9 +202,18 @@ SoundFileBox::SoundFileBox (bool persistent)
        bottom_box.pack_start(stop_btn, true, true);
        bottom_box.pack_start(autoplay_btn, false, false);
 
+       seek_slider.set_draw_value(false);
+
+       seek_slider.add_events(Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
+       seek_slider.signal_button_press_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_press), false);
+       seek_slider.signal_button_release_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_release), false);
+       main_box.pack_start (seek_slider, false, false);
+
        play_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::audition));
        stop_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::stop_audition));
 
+       stop_btn.set_sensitive (false);
+
        channels_value.set_alignment (0.0f, 0.5f);
        samplerate_value.set_alignment (0.0f, 0.5f);
 }
@@ -217,9 +229,45 @@ SoundFileBox::set_session(Session* s)
        if (!_session) {
                play_btn.set_sensitive (false);
                stop_btn.set_sensitive (false);
+               auditioner_connections.drop_connections();
+       } else {
+               auditioner_connections.drop_connections();
+               _session->AuditionActive.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_active, this, _1), gui_context());
+               _session->the_auditioner()->AuditionProgress.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_progress, this, _1, _2), gui_context());
+       }
+}
+
+void
+SoundFileBox::audition_active(bool active) {
+       stop_btn.set_sensitive (active);
+       seek_slider.set_sensitive (active);
+       if (!active) {
+               seek_slider.set_value(0);
+       }
+}
+
+void
+SoundFileBox::audition_progress(ARDOUR::framecnt_t pos, ARDOUR::framecnt_t len) {
+       if (!_seeking) {
+               seek_slider.set_value( 1000.0 * pos / len);
+               seek_slider.set_sensitive (true);
        }
 }
 
+bool
+SoundFileBox::seek_button_press(GdkEventButton*) {
+       _seeking = true;
+       return false; // pass on to slider
+}
+
+bool
+SoundFileBox::seek_button_release(GdkEventButton*) {
+       _seeking = false;
+       _session->the_auditioner()->seek_to_percent(seek_slider.get_value() / 10.0);
+       seek_slider.set_sensitive (false);
+       return false; // pass on to slider
+}
+
 bool
 SoundFileBox::setup_labels (const string& filename)
 {
@@ -340,9 +388,10 @@ SoundFileBox::audition ()
        for (int n = 0; n < sf_info.channels; ++n) {
                try {
                        afs = boost::dynamic_pointer_cast<AudioFileSource> (
-                                       SourceFactory::createReadable (DataType::AUDIO, *_session,
-                                                       path, n, Source::Flag (0), false));
-
+                               SourceFactory::createExternal (DataType::AUDIO, *_session,
+                                                              path, n,
+                                                              Source::Flag (0), false));
+                       
                        srclist.push_back(afs);
 
                } catch (failed_constructor& err) {
@@ -512,16 +561,10 @@ 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
-
        //add freesound search
 
-       mootcher = new Mootcher();
-       
        HBox* passbox;
        Label* label;
        
@@ -553,8 +596,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_end   (freesound_stop_btn, false, false);
-       freesound_stop_btn.set_label(_("Stop"));
+       passbox->pack_start (freesound_more_btn, false, false);
+       freesound_more_btn.set_label(_("More"));
+       freesound_more_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);
@@ -563,9 +611,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);
@@ -574,21 +621,23 @@ 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_stop_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_stop_clicked));
+       freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
+       freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
        notebook.append_page (*vbox, _("Search Freesound"));
-#endif
 
        notebook.set_size_request (500, -1);
        notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
@@ -707,6 +756,7 @@ SoundFileBrowser::add_gain_meter ()
        boost::shared_ptr<Route> r = _session->the_auditioner ();
 
        gm->set_controls (r, r->shared_peak_meter(), r->amp());
+       gm->set_fader_name (X_("GainFader"));
 
        meter_packer.set_border_width (12);
        meter_packer.pack_start (*gm, false, true);
@@ -782,7 +832,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());
@@ -797,53 +847,6 @@ SoundFileBrowser::found_list_view_selected ()
        }
 }
 
-void
-SoundFileBrowser::freesound_list_view_selected ()
-{
-       freesound_download_cancel = false;
-
-#ifdef FREESOUND
-       if (!reset_options ()) {
-               set_action_sensitive (false);
-       } else {
-
-               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(_("found %1 matche(s)"), matches));
-
-               preview.setup_labels (file);
-       }
-#endif
-}
-
 void
 SoundFileBrowser::found_search_clicked ()
 {
@@ -868,28 +871,137 @@ 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 ()
 {
-       freesound_search_cancel = false;
+       freesound_page = 1;
+       freesound_list->clear();
+       matches = 0;
        freesound_search();
 }
 
 void
-SoundFileBrowser::freesound_stop_clicked ()
+SoundFileBrowser::freesound_more_clicked ()
 {
-       freesound_download_cancel = true;
-       freesound_search_cancel = true;
+       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_similar_clicked ()
+{
+       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
-       freesound_list->clear();
-       freesound_list_view.get_column(1)->set_sizing(TREE_VIEW_COLUMN_GROW_ONLY);
-       matches = 0;
+       Mootcher mootcher;
 
        string search_string = freesound_entry.get_text ();
        enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
@@ -897,179 +1009,160 @@ 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();
 
-       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);
+       handle_freesound_results(theString);
+}
 
-               if (!root) {
-                       error << "no root XML node!" << endmsg;
-                       break;
-               }
+void
+SoundFileBrowser::handle_freesound_results(std::string theString) {
+       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);
+       }
+
+       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);
+                       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);
+                       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';
+                       }
 
-       freesound_progress_bar.set_fraction(0.0);
-       switch (matches) {
-               case 0:
-                       freesound_progress_bar.set_text(_("Search returned no results."));
-                       break;
-               case 1:
-                       freesound_progress_bar.set_text(_("Found one match."));
-                       break;
-               default:
-                       freesound_progress_bar.set_text(string_compose(_("Found %1 matche(s)"), matches));
+                       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_list_view.get_column(1)->set_sizing(TREE_VIEW_COLUMN_AUTOSIZE);
-#endif
 }
 
 vector<string>
@@ -1090,9 +1183,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) {
@@ -1102,30 +1193,13 @@ SoundFileBrowser::get_paths ()
                        results.push_back (str);
                }
        } else {
-#ifdef FREESOUND
-               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);
-                       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
        }
 
        return results;
@@ -1335,8 +1409,9 @@ SoundFileOmega::reset_options ()
                src_combo.set_sensitive (false);
        }
 
-       /* We must copy MIDI files or those from Freesound */
-       bool const must_copy = have_a_midi_file || notebook.get_current_page() == 2;
+       /* We must copy MIDI files or those from Freesound
+        * or any file if we are under nsm control */
+       bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
        
        if (Config->get_only_copy_imported_files()) {
 
@@ -1431,6 +1506,9 @@ SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool&
 bool
 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
 {
+#ifdef PLATFORM_WINDOWS
+       return false;
+#else
        std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
        bool ret = false;
 
@@ -1442,7 +1520,7 @@ SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths
 
        for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
 
-               char tmpc[MAXPATHLEN+1];
+               char tmpc[PATH_MAX+1];
 
                snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
 
@@ -1452,7 +1530,7 @@ SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths
                        goto out;
                }
 
-               unlink (tmpc);
+               ::g_unlink (tmpc);
        }
 
        ret = true;
@@ -1460,6 +1538,7 @@ SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths
   out:
        rmdir (tmpdir.c_str());
        return ret;
+#endif
 }
 
 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
@@ -1699,7 +1778,7 @@ SoundFileOmega::get_position() const
 SrcQuality
 SoundFileOmega::get_src_quality() const
 {
-       string str = where_combo.get_active_text();
+       string str = src_combo.get_active_text();
 
        if (str == _("Best")) {
                return SrcBest;