Add API allowing plugin preset load to affect automation
[ardour.git] / gtk2_ardour / sfdb_ui.cc
1 /*
2     Copyright (C) 2005-2006 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifdef WAF_BUILD
21 #include "gtk2ardour-config.h"
22 #endif
23
24 #include "pbd/i18n.h"
25
26 #include <map>
27 #include <cerrno>
28 #include <sstream>
29
30 #include <unistd.h>
31 #include <limits.h>
32
33 #include <gtkmm/box.h>
34 #include <gtkmm/stock.h>
35
36 #include "pbd/gstdio_compat.h"
37 #include <glibmm/fileutils.h>
38
39 #include "pbd/convert.h"
40 #include "pbd/tokenizer.h"
41 #include "pbd/enumwriter.h"
42 #include "pbd/pthread_utils.h"
43 #include "pbd/xml++.h"
44
45 #include <gtkmm2ext/utils.h>
46
47 #include "evoral/SMF.hpp"
48
49 #include "ardour/audio_library.h"
50 #include "ardour/auditioner.h"
51 #include "ardour/audioregion.h"
52 #include "ardour/audiofilesource.h"
53 #include "ardour/midi_region.h"
54 #include "ardour/smf_source.h"
55 #include "ardour/region_factory.h"
56 #include "ardour/source_factory.h"
57 #include "ardour/session.h"
58 #include "ardour/session_directory.h"
59 #include "ardour/srcfilesource.h"
60 #include "ardour/profile.h"
61
62 #include "ardour_ui.h"
63 #include "editing.h"
64 #include "gui_thread.h"
65 #include "prompter.h"
66 #include "sfdb_ui.h"
67 #include "editing.h"
68 #include "gain_meter.h"
69 #include "main_clock.h"
70 #include "public_editor.h"
71 #include "timers.h"
72 #include "ui_config.h"
73
74 #include "sfdb_freesound_mootcher.h"
75
76 using namespace ARDOUR;
77 using namespace PBD;
78 using namespace std;
79 using namespace Gtk;
80 using namespace Gtkmm2ext;
81 using namespace Editing;
82
83 using std::string;
84
85 string SoundFileBrowser::persistent_folder;
86 typedef TreeView::Selection::ListHandle_Path ListPath;
87
88 static MidiTrackNameSource
89 string2miditracknamesource (string const & str)
90 {
91         if (str == _("by track number")) {
92                 return SMFTrackNumber;
93         } else if (str == _("by track name")) {
94                 return SMFTrackName;
95         } else if (str == _("by instrument name")) {
96                 return SMFInstrumentName;
97         }
98
99         warning << string_compose (_("programming error: unknown midi track name source string %1"), str) << endmsg;
100
101         return SMFTrackNumber;
102 }
103
104 static ImportMode
105 string2importmode (string const & str)
106 {
107         if (str == _("as new tracks")) {
108                 return ImportAsTrack;
109         } else if (str == _("to selected tracks")) {
110                 return ImportToTrack;
111         } else if (str == _("to region list")) {
112                 return ImportAsRegion;
113         } else if (str == _("as new tape tracks")) {
114                 return ImportAsTapeTrack;
115         }
116
117         warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
118
119         return ImportAsTrack;
120 }
121
122 static string
123 importmode2string (ImportMode mode)
124 {
125         switch (mode) {
126         case ImportAsTrack:
127                 return _("as new tracks");
128         case ImportToTrack:
129                 return _("to selected tracks");
130         case ImportAsRegion:
131                 return _("to region list");
132         case ImportAsTapeTrack:
133                 return _("as new tape tracks");
134         }
135         abort(); /*NOTREACHED*/
136         return _("as new tracks");
137 }
138
139 SoundFileBox::SoundFileBox (bool /*persistent*/)
140         : table (7, 2),
141           length_clock ("sfboxLengthClock", true, "", false, false, true, false),
142           timecode_clock ("sfboxTimecodeClock", true, "", false, false, false, false),
143           main_box (false, 6),
144           autoplay_btn (_("Auto-play")),
145           seek_slider(0,1000,1),
146           _seeking(false)
147
148 {
149         set_name (X_("SoundFileBox"));
150         set_size_request (300, -1);
151
152         preview_label.set_markup (_("<b>Sound File Information</b>"));
153
154         border_frame.set_label_widget (preview_label);
155         border_frame.add (main_box);
156
157         pack_start (border_frame, true, true);
158         set_border_width (6);
159
160         main_box.set_border_width (6);
161
162         length.set_text (_("Length:"));
163         length.set_alignment (1, 0.5);
164         timecode.set_text (_("Timestamp:"));
165         timecode.set_alignment (1, 0.5);
166         format.set_text (_("Format:"));
167         format.set_alignment (1, 0.5);
168         channels.set_text (_("Channels:"));
169         channels.set_alignment (1, 0.5);
170         samplerate.set_text (_("Sample rate:"));
171         samplerate.set_alignment (1, 0.5);
172         tempomap.set_text (_("Tempo Map:"));
173         tempomap.set_alignment (1, 0.5);
174
175         preview_label.set_max_width_chars (50);
176         preview_label.set_ellipsize (Pango::ELLIPSIZE_END);
177
178         format_text.set_max_width_chars (20);
179         format_text.set_ellipsize (Pango::ELLIPSIZE_END);
180         format_text.set_alignment (0, 1);
181
182         table.set_col_spacings (6);
183         table.set_homogeneous (false);
184         table.set_row_spacings (6);
185
186         table.attach (channels, 0, 1, 0, 1, FILL, FILL);
187         table.attach (samplerate, 0, 1, 1, 2, FILL, FILL);
188         table.attach (format, 0, 1, 2, 4, FILL, FILL);
189         table.attach (length, 0, 1, 4, 5, FILL, FILL);
190         table.attach (timecode, 0, 1, 5, 6, FILL, FILL);
191         table.attach (tempomap, 0, 1, 6, 7, FILL, FILL);
192
193         table.attach (channels_value, 1, 2, 0, 1, FILL, FILL);
194         table.attach (samplerate_value, 1, 2, 1, 2, FILL, FILL);
195         table.attach (format_text, 1, 2, 2, 4, FILL, FILL);
196         table.attach (length_clock, 1, 2, 4, 5, FILL, FILL);
197         table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL);
198         table.attach (tempomap_value, 1, 2, 6, 7, FILL, FILL);
199
200         length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock->mode());
201         timecode_clock.set_mode (AudioClock::Timecode);
202
203         main_box.pack_start (table, false, false);
204
205         tags_entry.set_editable (true);
206         tags_entry.set_wrap_mode(Gtk::WRAP_WORD);
207         tags_entry.signal_focus_out_event().connect (sigc::mem_fun (*this, &SoundFileBox::tags_entry_left));
208
209         Label* label = manage (new Label (_("Tags:")));
210         label->set_alignment (0.0f, 0.5f);
211         main_box.pack_start (*label, false, false);
212         main_box.pack_start (tags_entry, true, true);
213
214         main_box.pack_start (bottom_box, false, false);
215
216         play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
217 //      play_btn.set_label (_("Play"));
218
219         stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
220 //      stop_btn.set_label (_("Stop"));
221
222         bottom_box.set_homogeneous (false);
223         bottom_box.set_spacing (6);
224         bottom_box.pack_start(play_btn, true, true);
225         bottom_box.pack_start(stop_btn, true, true);
226         bottom_box.pack_start(autoplay_btn, false, false);
227
228         seek_slider.set_draw_value(false);
229
230         seek_slider.add_events(Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
231         seek_slider.signal_button_press_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_press), false);
232         seek_slider.signal_button_release_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_release), false);
233         main_box.pack_start (seek_slider, false, false);
234
235         play_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::audition));
236         stop_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::stop_audition));
237
238         stop_btn.set_sensitive (false);
239
240         channels_value.set_alignment (0.0f, 0.5f);
241         samplerate_value.set_alignment (0.0f, 0.5f);
242 }
243
244 void
245 SoundFileBox::set_session(Session* s)
246 {
247         SessionHandlePtr::set_session (s);
248
249         length_clock.set_session (s);
250         timecode_clock.set_session (s);
251
252         if (!_session) {
253                 play_btn.set_sensitive (false);
254                 stop_btn.set_sensitive (false);
255                 auditioner_connections.drop_connections();
256         } else {
257                 auditioner_connections.drop_connections();
258                 _session->AuditionActive.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_active, this, _1), gui_context());
259                 _session->the_auditioner()->AuditionProgress.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_progress, this, _1, _2), gui_context());
260         }
261 }
262
263 void
264 SoundFileBox::audition_active(bool active) {
265         stop_btn.set_sensitive (active);
266         seek_slider.set_sensitive (active);
267         if (!active) {
268                 seek_slider.set_value(0);
269         }
270 }
271
272 void
273 SoundFileBox::audition_progress(ARDOUR::framecnt_t pos, ARDOUR::framecnt_t len) {
274         if (!_seeking) {
275                 seek_slider.set_value( 1000.0 * pos / len);
276                 seek_slider.set_sensitive (true);
277         }
278 }
279
280 bool
281 SoundFileBox::seek_button_press(GdkEventButton*) {
282         _seeking = true;
283         return false; // pass on to slider
284 }
285
286 bool
287 SoundFileBox::seek_button_release(GdkEventButton*) {
288         _seeking = false;
289         _session->the_auditioner()->seek_to_percent(seek_slider.get_value() / 10.0);
290         seek_slider.set_sensitive (false);
291         return false; // pass on to slider
292 }
293
294 bool
295 SoundFileBox::setup_labels (const string& filename)
296 {
297         if (!path.empty()) {
298                 // save existing tags
299                 tags_changed ();
300         }
301
302         path = filename;
303
304         string error_msg;
305
306         if (SMFSource::valid_midi_file (path)) {
307
308                 boost::shared_ptr<SMFSource> ms;
309                 try {
310                         ms = boost::dynamic_pointer_cast<SMFSource> (
311                                 SourceFactory::createExternal (DataType::MIDI, *_session,
312                                                                path, 0, Source::Flag (0), false));
313                 } catch (const std::exception& e) {
314                         error << string_compose(_("Could not read file: %1 (%2)."),
315                                                 path, e.what()) << endmsg;
316                 }
317
318                 preview_label.set_markup (_("<b>Midi File Information</b>"));
319
320                 format_text.set_text ("MIDI");
321                 samplerate_value.set_text ("-");
322                 tags_entry.get_buffer()->set_text ("");
323                 timecode_clock.set (0);
324                 tags_entry.set_sensitive (false);
325
326                 if (ms) {
327                         if (ms->is_type0()) {
328                                 channels_value.set_text (to_string(ms->channels().size(), std::dec));
329                         } else {
330                                 if (ms->num_tracks() > 1) {
331                                         channels_value.set_text (to_string(ms->num_tracks(), std::dec) + _("(Tracks)"));
332                                 } else {
333                                         channels_value.set_text (to_string(ms->num_tracks(), std::dec));
334                                 }
335                         }
336                         length_clock.set (ms->length(ms->timeline_position()));
337                         switch (ms->num_tempos()) {
338                         case 0:
339                                 tempomap_value.set_text (_("No tempo data"));
340                                 break;
341                         case 1: {
342                                 Evoral::SMF::Tempo* t = ms->nth_tempo (0);
343                                 assert (t);
344                                 tempomap_value.set_text (string_compose (_("%1/%2 \u2669 = %3"),
345                                                                          t->numerator,
346                                                                          t->denominator,
347                                                                          t->tempo ()));
348                                 break;
349                         }
350                         default:
351                                 tempomap_value.set_text (string_compose (_("map with %1 sections"),
352                                                                          ms->num_tempos()));
353                                 break;
354                         }
355                 } else {
356                         channels_value.set_text ("");
357                         length_clock.set (0);
358                         tempomap_value.set_text (_("No tempo data"));
359                 }
360
361                 if (_session && ms) {
362                         play_btn.set_sensitive (true);
363                 } else {
364                         play_btn.set_sensitive (false);
365                 }
366
367                 return true;
368         }
369
370         if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
371
372                 preview_label.set_markup (_("<b>Sound File Information</b>"));
373                 format_text.set_text ("");
374                 channels_value.set_text ("");
375                 samplerate_value.set_text ("");
376                 tags_entry.get_buffer()->set_text ("");
377
378                 length_clock.set (0);
379                 timecode_clock.set (0);
380
381                 tags_entry.set_sensitive (false);
382                 play_btn.set_sensitive (false);
383
384                 return false;
385         }
386
387         preview_label.set_markup (string_compose ("<b>%1</b>", Glib::Markup::escape_text (Glib::path_get_basename (filename))));
388         std::string n = sf_info.format_name;
389         if (n.substr (0, 8) == X_("Format: ")) {
390                 n = n.substr (8);
391         }
392         format_text.set_text (n);
393         channels_value.set_text (to_string (sf_info.channels, std::dec));
394
395         if (_session && sf_info.samplerate != _session->frame_rate()) {
396                 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
397                 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
398                 samplerate_value.set_name ("NewSessionSR1Label");
399                 samplerate.set_name ("NewSessionSR1Label");
400         } else {
401                 samplerate.set_text (_("Sample rate:"));
402                 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
403                 samplerate_value.set_name ("NewSessionSR2Label");
404                 samplerate.set_name ("NewSessionSR2Label");
405         }
406
407         framecnt_t const nfr = _session ? _session->nominal_frame_rate() : 25;
408         double src_coef = (double) nfr / sf_info.samplerate;
409
410         length_clock.set (sf_info.length * src_coef + 0.5, true);
411         timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
412
413         // this is a hack that is fixed in trunk, i think (august 26th, 2007)
414
415         vector<string> tags = Library->get_tags (string ("//") + filename);
416
417         stringstream tag_string;
418         for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
419                 if (i != tags.begin()) {
420                         tag_string << ", ";
421                 }
422                 tag_string << *i;
423         }
424         tags_entry.get_buffer()->set_text (tag_string.str());
425
426         tags_entry.set_sensitive (true);
427         if (_session) {
428                 play_btn.set_sensitive (true);
429         }
430
431         return true;
432 }
433
434 bool
435 SoundFileBox::autoplay() const
436 {
437         return autoplay_btn.get_active();
438 }
439
440 bool
441 SoundFileBox::audition_oneshot()
442 {
443         audition ();
444         return false;
445 }
446
447 void
448 SoundFileBox::audition ()
449 {
450         if (!_session) {
451                 return;
452         }
453
454         _session->cancel_audition();
455
456         if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
457                 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
458                 return;
459         }
460
461         boost::shared_ptr<Region> r;
462
463         if (SMFSource::valid_midi_file (path)) {
464
465                 boost::shared_ptr<SMFSource> ms =
466                         boost::dynamic_pointer_cast<SMFSource> (
467                                         SourceFactory::createExternal (DataType::MIDI, *_session,
468                                                                                          path, 0, Source::Flag (0), false));
469
470                 string rname = region_name_from_path (ms->path(), false);
471
472                 PropertyList plist;
473
474                 plist.add (ARDOUR::Properties::start, 0);
475                 plist.add (ARDOUR::Properties::length, ms->length(ms->timeline_position()));
476                 plist.add (ARDOUR::Properties::name, rname);
477                 plist.add (ARDOUR::Properties::layer, 0);
478
479                 r = boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (boost::dynamic_pointer_cast<Source>(ms), plist, false));
480                 assert(r);
481
482         } else {
483
484                 SourceList srclist;
485                 boost::shared_ptr<AudioFileSource> afs;
486                 bool old_sbp = AudioSource::get_build_peakfiles ();
487
488                 /* don't even think of building peakfiles for these files */
489
490                 AudioSource::set_build_peakfiles (false);
491
492                 for (int n = 0; n < sf_info.channels; ++n) {
493                         try {
494                                 afs = boost::dynamic_pointer_cast<AudioFileSource> (
495                                         SourceFactory::createExternal (DataType::AUDIO, *_session,
496                                                                                          path, n,
497                                                                                          Source::Flag (ARDOUR::AudioFileSource::NoPeakFile), false));
498                                 if (afs->sample_rate() != _session->nominal_frame_rate()) {
499                                         boost::shared_ptr<SrcFileSource> sfs (new SrcFileSource(*_session, afs, _src_quality));
500                                         srclist.push_back(sfs);
501                                 } else {
502                                         srclist.push_back(afs);
503                                 }
504
505                         } catch (failed_constructor& err) {
506                                 error << _("Could not access soundfile: ") << path << endmsg;
507                                 AudioSource::set_build_peakfiles (old_sbp);
508                                 return;
509                         }
510                 }
511
512                 AudioSource::set_build_peakfiles (old_sbp);
513
514                 if (srclist.empty()) {
515                         return;
516                 }
517
518                 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
519                 string rname = region_name_from_path (afs->path(), false);
520
521                 PropertyList plist;
522
523                 plist.add (ARDOUR::Properties::start, 0);
524                 plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->timeline_position()));
525                 plist.add (ARDOUR::Properties::name, rname);
526                 plist.add (ARDOUR::Properties::layer, 0);
527
528                 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false));
529         }
530
531         frameoffset_t audition_position = 0;
532         switch(_import_position) {
533                 case ImportAtTimestamp:
534                         audition_position = 0;
535                         break;
536                 case ImportAtPlayhead:
537                         audition_position = _session->transport_frame();
538                         break;
539                 case ImportAtStart:
540                         audition_position = _session->current_start_frame();
541                         break;
542                 case ImportAtEditPoint:
543                         audition_position = PublicEditor::instance().get_preferred_edit_position ();
544                         break;
545         }
546         r->set_position(audition_position);
547
548         _session->audition_region(r);
549 }
550
551 void
552 SoundFileBox::stop_audition ()
553 {
554         if (_session) {
555                 _session->cancel_audition();
556         }
557 }
558
559 bool
560 SoundFileBox::tags_entry_left (GdkEventFocus *)
561 {
562         tags_changed ();
563         return false;
564 }
565
566 void
567 SoundFileBox::tags_changed ()
568 {
569         string tag_string = tags_entry.get_buffer()->get_text ();
570
571         if (tag_string.empty()) {
572                 return;
573         }
574
575         vector<string> tags;
576
577         if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
578                 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
579                 return;
580         }
581
582         save_tags (tags);
583 }
584
585 void
586 SoundFileBox::save_tags (const vector<string>& tags)
587 {
588         Library->set_tags (string ("//") + path, tags);
589         Library->save_changes ();
590 }
591
592 SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persistent)
593         : ArdourWindow (title)
594         , found_list (ListStore::create(found_list_columns))
595         , freesound_list (ListStore::create(freesound_list_columns))
596         , chooser (FILE_CHOOSER_ACTION_OPEN)
597         , preview (persistent)
598         , found_search_btn (_("Search"))
599         , found_list_view (found_list)
600         , freesound_search_btn (_("Search"))
601         , freesound_list_view (freesound_list)
602         , resetting_ourselves (false)
603         , matches (0)
604         , _status (0)
605         , _done (false)
606         , import_button (_("Import"))
607         , close_button (Stock::CLOSE)
608         , gm (0)
609 {
610
611 #ifdef __APPLE__
612         try {
613                 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
614                 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
615                 chooser.add_shortcut_folder_uri("file:///Library/Audio/Apple Loops");
616                 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
617         }
618         catch (Glib::Error & e) {
619                 std::cerr << "sfdb.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
620         }
621 #endif
622         Gtkmm2ext::add_volume_shortcuts (chooser);
623
624         //add the file chooser
625
626         chooser.set_border_width (12);
627
628         audio_and_midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun (*this, &SoundFileBrowser::on_audio_and_midi_filter));
629         audio_and_midi_filter.set_name (_("Audio and MIDI files"));
630
631         audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
632         audio_filter.set_name (_("Audio files"));
633
634         midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
635         midi_filter.set_name (_("MIDI files"));
636
637         matchall_filter.add_pattern ("*.*");
638         matchall_filter.set_name (_("All files"));
639
640         chooser.add_filter (audio_and_midi_filter);
641         chooser.add_filter (audio_filter);
642         chooser.add_filter (midi_filter);
643         chooser.add_filter (matchall_filter);
644         chooser.set_select_multiple (true);
645         chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
646         chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
647
648 #ifdef __APPLE__
649         /* some broken redraw behaviour - this is a bandaid */
650         chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
651 #endif
652
653         if (!persistent_folder.empty()) {
654                 chooser.set_current_folder (persistent_folder);
655         }
656
657         notebook.append_page (chooser, _("Browse Files"));
658
659         hpacker.set_spacing (6);
660         hpacker.pack_start (notebook, true, true);
661         hpacker.pack_start (preview, false, false);
662
663         vpacker.set_spacing (6);
664         vpacker.pack_start (hpacker, true, true);
665
666         add (vpacker);
667
668         //add tag search
669
670         VBox* vbox;
671         HBox* hbox;
672
673
674         hbox = manage(new HBox);
675         hbox->pack_start (found_entry);
676         hbox->pack_start (found_search_btn);
677
678         Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
679         scroll->add(found_list_view);
680         scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
681
682         vbox = manage(new VBox);
683         vbox->pack_start (*hbox, PACK_SHRINK);
684         vbox->pack_start (*scroll);
685
686         found_list_view.append_column(_("Paths"), found_list_columns.pathname);
687
688         found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
689
690         found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
691
692         found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
693         found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
694
695         notebook.append_page (*vbox, _("Search Tags"));
696
697         //add freesound search
698 #ifdef FREESOUND_GOT_FIXED
699
700         HBox* passbox;
701         Label* label;
702
703         passbox = manage(new HBox);
704         passbox->set_spacing (6);
705
706         label = manage (new Label);
707         label->set_text (_("Tags:"));
708         passbox->pack_start (*label, false, false);
709         passbox->pack_start (freesound_entry, true, true);
710
711         label = manage (new Label);
712         label->set_text (_("Sort:"));
713         passbox->pack_start (*label, false, false);
714         passbox->pack_start (freesound_sort, false, false);
715         freesound_sort.clear_items();
716
717         // Order of the following must correspond with enum sortMethod
718         // in sfdb_freesound_mootcher.h
719         freesound_sort.append_text(_("None"));
720         freesound_sort.append_text(_("Longest"));
721         freesound_sort.append_text(_("Shortest"));
722         freesound_sort.append_text(_("Newest"));
723         freesound_sort.append_text(_("Oldest"));
724         freesound_sort.append_text(_("Most downloaded"));
725         freesound_sort.append_text(_("Least downloaded"));
726         freesound_sort.append_text(_("Highest rated"));
727         freesound_sort.append_text(_("Lowest rated"));
728         freesound_sort.set_active(0);
729
730         passbox->pack_start (freesound_search_btn, false, false);
731         passbox->pack_start (freesound_more_btn, false, false);
732         freesound_more_btn.set_label(_("More"));
733         freesound_more_btn.set_sensitive(false);
734
735         passbox->pack_start (freesound_similar_btn, false, false);
736         freesound_similar_btn.set_label(_("Similar"));
737         freesound_similar_btn.set_sensitive(false);
738
739         scroll = manage(new ScrolledWindow);
740         scroll->add(freesound_list_view);
741         scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
742
743         vbox = manage(new VBox);
744         vbox->set_spacing (3);
745         vbox->pack_start (*passbox, PACK_SHRINK);
746         vbox->pack_start (*scroll);
747
748         freesound_list_view.append_column(_("ID")      , freesound_list_columns.id);
749         freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
750         // freesound_list_view.append_column(_("URI")     , freesound_list_columns.uri);
751         freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
752         freesound_list_view.append_column(_("Size"), freesound_list_columns.filesize);
753         freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
754         freesound_list_view.append_column(_("License"), freesound_list_columns.license);
755         freesound_list_view.get_column(0)->set_alignment(0.5);
756         freesound_list_view.get_column(1)->set_expand(true); // filename
757         freesound_list_view.get_column(1)->set_resizable(true); // filename
758         freesound_list_view.get_column(2)->set_alignment(0.5);
759         freesound_list_view.get_column(3)->set_alignment(0.5);
760         freesound_list_view.get_column(4)->set_alignment(0.5);
761         freesound_list_view.get_column(5)->set_alignment(0.5);
762
763         freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
764         freesound_list_view.set_tooltip_column(1);
765
766         freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
767         freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
768         freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
769         freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
770         freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
771         freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
772         notebook.append_page (*vbox, _("Search Freesound"));
773 #endif
774
775         notebook.set_size_request (500, -1);
776         notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
777
778         set_session (s);
779
780         Gtk::HButtonBox* button_box = manage (new HButtonBox);
781
782         button_box->set_layout (BUTTONBOX_END);
783         button_box->pack_start (close_button, false, false);
784         close_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_CLOSE));
785
786         button_box->pack_start (import_button, false, false);
787         import_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_OK));
788
789         Gtkmm2ext::UI::instance()->set_tip (import_button, _("Press to import selected files"));
790         Gtkmm2ext::UI::instance()->set_tip (close_button, _("Press to close this window without importing any files"));
791
792         vpacker.pack_end (*button_box, false, false);
793
794         set_wmclass (X_("import"), PROGRAM_NAME);
795 }
796
797 SoundFileBrowser::~SoundFileBrowser ()
798 {
799         persistent_folder = chooser.get_current_folder();
800 }
801
802 int
803 SoundFileBrowser::run ()
804 {
805         set_modal (true);
806         show_all ();
807         present ();
808
809         _done = false;
810
811         while (!_done) {
812                 gtk_main_iteration ();
813         }
814
815         return _status;
816 }
817
818 void
819 SoundFileBrowser::set_action_sensitive (bool yn)
820 {
821         import_button.set_sensitive (yn);
822 }
823
824 void
825 SoundFileBrowser::do_something (int action)
826 {
827         _done = true;
828         _status = action;
829 }
830
831 void
832 SoundFileBrowser::on_show ()
833 {
834         ArdourWindow::on_show ();
835         start_metering ();
836 }
837
838 void
839 SoundFileBrowser::clear_selection ()
840 {
841         chooser.unselect_all ();
842         found_list_view.get_selection()->unselect_all ();
843 }
844
845 void
846 SoundFileBrowser::chooser_file_activated ()
847 {
848         preview.audition ();
849 }
850
851 void
852 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
853 {
854         preview.audition ();
855 }
856
857 void
858 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
859 {
860         preview.audition ();
861 }
862
863 void
864 SoundFileBrowser::set_session (Session* s)
865 {
866         ArdourWindow::set_session (s);
867         preview.set_session (s);
868
869         if (_session) {
870                 add_gain_meter ();
871         } else {
872                 remove_gain_meter ();
873         }
874 }
875
876 void
877 SoundFileBrowser::add_gain_meter ()
878 {
879         delete gm;
880
881         gm = new GainMeter (_session, 250);
882
883         boost::shared_ptr<Route> r = _session->the_auditioner ();
884
885         gm->set_controls (r, r->shared_peak_meter(), r->amp(), r->gain_control());
886         gm->set_fader_name (X_("GainFader"));
887
888         meter_packer.set_border_width (12);
889         meter_packer.pack_start (*gm, false, true);
890         hpacker.pack_end (meter_packer, false, false);
891         meter_packer.show_all ();
892         start_metering ();
893 }
894
895 void
896 SoundFileBrowser::remove_gain_meter ()
897 {
898         if (gm) {
899                 meter_packer.remove (*gm);
900                 hpacker.remove (meter_packer);
901                 delete gm;
902                 gm = 0;
903         }
904 }
905
906 void
907 SoundFileBrowser::start_metering ()
908 {
909         metering_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
910 }
911
912 void
913 SoundFileBrowser::stop_metering ()
914 {
915         metering_connection.disconnect();
916 }
917
918 void
919 SoundFileBrowser::meter ()
920 {
921         if (is_mapped () && _session && gm) {
922                 gm->update_meters ();
923         }
924 }
925
926 bool
927 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
928 {
929         return AudioFileSource::safe_audio_file_extension (filter_info.filename);
930 }
931
932 bool
933 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
934 {
935         return SMFSource::safe_midi_file_extension (filter_info.filename);
936 }
937
938 bool
939 SoundFileBrowser::on_audio_and_midi_filter (const FileFilter::Info& filter_info)
940 {
941         return on_audio_filter (filter_info) || on_midi_filter (filter_info);
942 }
943
944 void
945 SoundFileBrowser::update_preview ()
946 {
947         if (preview.setup_labels (chooser.get_preview_filename())) {
948                 if (preview.autoplay()) {
949                         Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
950                 }
951         }
952 }
953
954 void
955 SoundFileBrowser::found_list_view_selected ()
956 {
957         if (!reset_options ()) {
958                 set_action_sensitive (false);
959         } else {
960                 string file;
961
962                 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
963
964                 if (!rows.empty()) {
965                         TreeIter iter = found_list->get_iter(*rows.begin());
966                         file = (*iter)[found_list_columns.pathname];
967                         chooser.set_filename (file);
968                         set_action_sensitive (true);
969                 } else {
970                         set_action_sensitive (false);
971                 }
972
973                 preview.setup_labels (file);
974         }
975 }
976
977 void
978 SoundFileBrowser::found_search_clicked ()
979 {
980         string tag_string = found_entry.get_text ();
981
982         vector<string> tags;
983
984         if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
985                 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
986                 return;
987         }
988
989         vector<string> results;
990         Library->search_members_and (results, tags);
991
992         found_list->clear();
993         for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
994                 TreeModel::iterator new_row = found_list->append();
995                 TreeModel::Row row = *new_row;
996                 string path = Glib::filename_from_uri (string ("file:") + *i);
997                 row[found_list_columns.pathname] = path;
998         }
999 }
1000
1001
1002 std::string
1003 SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
1004 {
1005
1006         Mootcher *mootcher = new Mootcher;
1007         std::string file;
1008
1009         string id  = (*iter)[freesound_list_columns.id];
1010         string uri = (*iter)[freesound_list_columns.uri];
1011         string ofn = (*iter)[freesound_list_columns.filename];
1012
1013         if (mootcher->checkAudioFile(ofn, id)) {
1014                 // file already exists, no need to download it again
1015                 file = mootcher->audioFileName;
1016                 delete mootcher;
1017                 (*iter)[freesound_list_columns.started] = false;
1018                 return file;
1019         }
1020         if (!(*iter)[freesound_list_columns.started]) {
1021                 // start downloading the sound file
1022                 (*iter)[freesound_list_columns.started] = true;
1023                 mootcher->fetchAudioFile(ofn, id, uri, this);
1024         }
1025         return "";
1026 }
1027
1028 void
1029 SoundFileBrowser::freesound_list_view_selected ()
1030 {
1031
1032         if (!reset_options ()) {
1033                 set_action_sensitive (false);
1034         } else {
1035                 std::string file;
1036                 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1037                 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1038                         file = freesound_get_audio_file (freesound_list->get_iter(*i));
1039                 }
1040
1041                 switch (rows.size()) {
1042                         case 0:
1043                                 // nothing selected
1044                                 freesound_similar_btn.set_sensitive(false);
1045                                 set_action_sensitive (false);
1046                                 break;
1047                         case 1:
1048                                 // exactly one item selected
1049                                 if (file != "") {
1050                                         // file exists on disk already
1051                                         chooser.set_filename (file);
1052                                         preview.setup_labels (file);
1053                                         set_action_sensitive (true);
1054                                 }
1055                                 freesound_similar_btn.set_sensitive(true);
1056                                 break;
1057                         default:
1058                                 // multiple items selected
1059                                 preview.setup_labels ("");
1060                                 freesound_similar_btn.set_sensitive(false);
1061                                 break;
1062                 }
1063
1064         }
1065 }
1066
1067 void
1068 SoundFileBrowser::refresh_display(std::string ID, std::string file)
1069 {
1070         // called when the mootcher has finished downloading a file
1071         ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1072         if (rows.size() == 1) {
1073                 // there's a single item selected in the freesound list
1074                 //XXX make a function to be used to construct the actual file name both here and in the mootcher
1075                 Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
1076                 std::string selected_ID = (*row)[freesound_list_columns.id];
1077                 if (ID == selected_ID) {
1078                         // the selected item in the freesound list is the item that has just finished downloading
1079                         chooser.set_filename(file);
1080                         preview.setup_labels (file);
1081                         set_action_sensitive (true);
1082                 }
1083         }
1084 }
1085
1086 void
1087 SoundFileBrowser::freesound_search_clicked ()
1088 {
1089         freesound_page = 1;
1090         freesound_list->clear();
1091         matches = 0;
1092         freesound_search();
1093 }
1094
1095 void
1096 SoundFileBrowser::freesound_more_clicked ()
1097 {
1098         char row_path[21];
1099         freesound_page++;
1100         freesound_search();
1101         snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
1102         freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
1103 }
1104
1105 void
1106 SoundFileBrowser::freesound_similar_clicked ()
1107 {
1108         ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1109         if (rows.size() == 1) {
1110                 Mootcher mootcher;
1111                 string id;
1112                 Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
1113                 id = (*iter)[freesound_list_columns.id];
1114                 freesound_list->clear();
1115
1116                 GdkCursor *prev_cursor;
1117                 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1118                 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1119                 gdk_flush();
1120
1121                 std::string theString = mootcher.searchSimilar(id);
1122
1123                 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1124                 handle_freesound_results(theString);
1125         }
1126 }
1127
1128 void
1129 SoundFileBrowser::freesound_search()
1130 {
1131         Mootcher mootcher;
1132
1133         string search_string = freesound_entry.get_text ();
1134         enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
1135
1136         GdkCursor *prev_cursor;
1137         prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1138         gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1139         gdk_flush();
1140
1141         std::string theString = mootcher.searchText(
1142                         search_string,
1143                         freesound_page,
1144 #ifdef __APPLE__
1145                         "", // OSX eats anything incl mp3
1146 #else
1147                         "type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
1148 #endif
1149                         sort_method
1150                         );
1151
1152         gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1153         handle_freesound_results(theString);
1154 }
1155
1156 void
1157 SoundFileBrowser::handle_freesound_results(std::string theString) {
1158         XMLTree doc;
1159         doc.read_buffer( theString );
1160         XMLNode *root = doc.root();
1161
1162         if (!root) {
1163                 error << "no root XML node!" << endmsg;
1164                 return;
1165         }
1166
1167         if ( strcmp(root->name().c_str(), "response") != 0) {
1168                 error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
1169                 return;
1170         }
1171
1172         // find out how many pages are available to search
1173         int freesound_n_pages = 1;
1174         XMLNode *res = root->child("num_pages");
1175         if (res) {
1176                 string result = res->child("text")->content();
1177                 freesound_n_pages = atoi(result);
1178         }
1179
1180         int more_pages = freesound_n_pages - freesound_page;
1181
1182         if (more_pages > 0) {
1183                 freesound_more_btn.set_sensitive(true);
1184                 freesound_more_btn.set_tooltip_text(string_compose(P_(
1185                                                 "%1 more page of 100 results available",
1186                                                 "%1 more pages of 100 results available",
1187                                                 more_pages), more_pages));
1188         } else {
1189                 freesound_more_btn.set_sensitive(false);
1190                 freesound_more_btn.set_tooltip_text(_("No more results available"));
1191         }
1192
1193         XMLNode *sounds_root = root->child("sounds");
1194         if (!sounds_root) {
1195                 error << "no child node \"sounds\" found!" << endmsg;
1196                 return;
1197         }
1198
1199         XMLNodeList sounds = sounds_root->children();
1200         if (sounds.size() == 0) {
1201                 /* nothing found */
1202                 return;
1203         }
1204
1205         XMLNodeConstIterator niter;
1206         XMLNode *node;
1207         for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
1208                 node = *niter;
1209                 if( strcmp( node->name().c_str(), "resource") != 0 ) {
1210                         error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
1211                         break;
1212                 }
1213
1214                 // node->dump(cerr, "node:");
1215
1216
1217                 XMLNode *id_node  = node->child ("id");
1218                 XMLNode *uri_node = node->child ("serve");
1219                 XMLNode *ofn_node = node->child ("original_filename");
1220                 XMLNode *dur_node = node->child ("duration");
1221                 XMLNode *siz_node = node->child ("filesize");
1222                 XMLNode *srt_node = node->child ("samplerate");
1223                 XMLNode *lic_node = node->child ("license");
1224
1225                 if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
1226
1227                         std::string  id =  id_node->child("text")->content();
1228                         std::string uri = uri_node->child("text")->content();
1229                         std::string ofn = ofn_node->child("text")->content();
1230                         std::string dur = dur_node->child("text")->content();
1231                         std::string siz = siz_node->child("text")->content();
1232                         std::string srt = srt_node->child("text")->content();
1233                         std::string lic = lic_node->child("text")->content();
1234
1235                         std::string r;
1236                         // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
1237
1238                         double duration_seconds = atof(dur);
1239                         double h, m, s;
1240                         char duration_hhmmss[16];
1241                         if (duration_seconds >= 99 * 60 * 60) {
1242                                 strcpy(duration_hhmmss, ">99h");
1243                         } else {
1244                                 s = modf(duration_seconds/60, &m) * 60;
1245                                 m = modf(m/60, &h) * 60;
1246                                 sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
1247                                                 h, m, s
1248                                        );
1249                         }
1250
1251                         double size_bytes = atof(siz);
1252                         char bsize[32];
1253                         if (size_bytes < 1000) {
1254                                 sprintf(bsize, "%.0f %s", size_bytes, _("B"));
1255                         } else if (size_bytes < 1000000 ) {
1256                                 sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
1257                         } else if (size_bytes < 10000000) {
1258                                 sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
1259                         } else if (size_bytes < 1000000000) {
1260                                 sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
1261                         } else {
1262                                 sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
1263                         }
1264
1265                         /* see http://www.freesound.org/help/faq/#licenses */
1266                         char shortlicense[64];
1267                         if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
1268                                 sprintf(shortlicense, "CC-BY-NC");
1269                         } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
1270                                 sprintf(shortlicense, "CC-BY");
1271                         } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
1272                                 sprintf(shortlicense, "sampling+");
1273                         } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
1274                                 sprintf(shortlicense, "PD");
1275                         } else {
1276                                 snprintf(shortlicense, 64, "%s", lic.c_str());
1277                                 shortlicense[63]= '\0';
1278                         }
1279
1280                         TreeModel::iterator new_row = freesound_list->append();
1281                         TreeModel::Row row = *new_row;
1282
1283                         row[freesound_list_columns.id      ] = id;
1284                         row[freesound_list_columns.uri     ] = uri;
1285                         row[freesound_list_columns.filename] = ofn;
1286                         row[freesound_list_columns.duration] = duration_hhmmss;
1287                         row[freesound_list_columns.filesize] = bsize;
1288                         row[freesound_list_columns.smplrate] = srt;
1289                         row[freesound_list_columns.license ] = shortlicense;
1290                         matches++;
1291                 }
1292         }
1293 }
1294
1295 vector<string>
1296 SoundFileBrowser::get_paths ()
1297 {
1298         vector<string> results;
1299
1300         int n = notebook.get_current_page ();
1301
1302         if (n == 0) {
1303                 vector<string> filenames = chooser.get_filenames();
1304                 vector<string>::iterator i;
1305
1306                 for (i = filenames.begin(); i != filenames.end(); ++i) {
1307                         GStatBuf buf;
1308                         if ((!g_stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
1309                                 results.push_back (*i);
1310                         }
1311                 }
1312
1313         } else if (n == 1) {
1314
1315                 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1316                 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1317                         TreeIter iter = found_list->get_iter(*i);
1318                         string str = (*iter)[found_list_columns.pathname];
1319
1320                         results.push_back (str);
1321                 }
1322         } else {
1323                 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1324                 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1325                         string str = freesound_get_audio_file (freesound_list->get_iter(*i));
1326                         if (str != "") {
1327                                 results.push_back (str);
1328                         }
1329                 }
1330         }
1331
1332         return results;
1333 }
1334
1335 void
1336 SoundFileOmega::reset_options_noret ()
1337 {
1338         if (!resetting_ourselves) {
1339                 (void) reset_options ();
1340         }
1341 }
1342
1343 bool
1344 SoundFileOmega::reset_options ()
1345 {
1346         if (_import_active) {
1347                 _reset_post_import = true;
1348                 return true;
1349         }
1350
1351         vector<string> paths = get_paths ();
1352
1353         if (paths.empty()) {
1354
1355                 channel_combo.set_sensitive (false);
1356                 action_combo.set_sensitive (false);
1357                 where_combo.set_sensitive (false);
1358                 copy_files_btn.set_active (true);
1359                 copy_files_btn.set_sensitive (false);
1360
1361                 return false;
1362
1363         } else {
1364
1365                 channel_combo.set_sensitive (true);
1366                 action_combo.set_sensitive (true);
1367                 where_combo.set_sensitive (true);
1368
1369                 /* if we get through this function successfully, this may be
1370                    reset at the end, once we know if we can use hard links
1371                    to do embedding (or if we are importing a MIDI file).
1372                 */
1373
1374                 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1375                         copy_files_btn.set_sensitive (false);
1376                 } else {
1377                         copy_files_btn.set_sensitive (false);
1378                 }
1379         }
1380
1381         bool same_size;
1382         bool src_needed;
1383         bool selection_includes_multichannel;
1384         bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1385         ImportMode mode;
1386
1387         /* See if we are thinking about importing any MIDI files */
1388         vector<string>::iterator i = paths.begin ();
1389         while (i != paths.end() && SMFSource::valid_midi_file (*i) == false) {
1390                 ++i;
1391         }
1392         bool const have_a_midi_file = (i != paths.end ());
1393
1394         if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1395                 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1396                 return false;
1397         }
1398
1399         if (have_a_midi_file) {
1400                 smf_tempo_btn.show ();
1401         } else {
1402                 smf_tempo_btn.hide ();
1403         }
1404
1405         string existing_choice;
1406         vector<string> action_strings;
1407
1408         resetting_ourselves = true;
1409
1410         if (chooser.get_filter() == &audio_filter) {
1411
1412                 /* AUDIO */
1413
1414                 if (selected_audio_track_cnt > 0) {
1415                         if (channel_combo.get_active_text().length()) {
1416                                 ImportDisposition id = get_channel_disposition();
1417
1418                                 switch (id) {
1419                                 case Editing::ImportDistinctFiles:
1420                                         if (selected_audio_track_cnt == paths.size()) {
1421                                                 action_strings.push_back (importmode2string (ImportToTrack));
1422                                         }
1423                                         break;
1424
1425                                 case Editing::ImportDistinctChannels:
1426                                         /* XXX it would be nice to allow channel-per-selected track
1427                                            but its too hard we don't want to deal with all the
1428                                            different per-file + per-track channel configurations.
1429                                         */
1430                                         break;
1431
1432                                 default:
1433                                         action_strings.push_back (importmode2string (ImportToTrack));
1434                                         break;
1435                                 }
1436                         }
1437                 }
1438
1439         }  else {
1440
1441                 /* MIDI ONLY */
1442
1443                 if (selected_midi_track_cnt > 0) {
1444                         action_strings.push_back (importmode2string (ImportToTrack));
1445                 }
1446         }
1447
1448         action_strings.push_back (importmode2string (ImportAsTrack));
1449         action_strings.push_back (importmode2string (ImportAsRegion));
1450         if (!Profile->get_mixbus()) {
1451                 action_strings.push_back (importmode2string (ImportAsTapeTrack));
1452         }
1453
1454         existing_choice = action_combo.get_active_text();
1455
1456         set_popdown_strings (action_combo, action_strings);
1457
1458         /* preserve any existing choice, if possible */
1459
1460
1461         if (existing_choice.length()) {
1462                 vector<string>::iterator x;
1463                 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1464                         if (*x == existing_choice) {
1465                                 action_combo.set_active_text (existing_choice);
1466                                 break;
1467                         }
1468                 }
1469                 if (x == action_strings.end()) {
1470                         action_combo.set_active_text (action_strings.front());
1471                 }
1472         } else {
1473                 action_combo.set_active_text (action_strings.front());
1474         }
1475
1476         resetting_ourselves = false;
1477
1478         if ((mode = get_mode()) == ImportAsRegion) {
1479                 where_combo.set_sensitive (false);
1480         } else {
1481                 where_combo.set_sensitive (true);
1482         }
1483
1484         vector<string> channel_strings;
1485
1486         if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1487
1488                 if (selection_includes_multichannel) {
1489                         channel_strings.push_back (_("one track per channel"));
1490                 }
1491
1492                 channel_strings.push_back (_("one track per file"));
1493
1494                 if (paths.size() > 1) {
1495                         /* tape tracks are a single region per track, so we cannot
1496                            sequence multiple files.
1497                         */
1498                         if (mode != ImportAsTapeTrack) {
1499                                 channel_strings.push_back (_("sequence files"));
1500                         }
1501                         if (same_size) {
1502                                 channel_strings.push_back (_("all files in one track"));
1503                                 channel_strings.push_back (_("merge files"));
1504                         }
1505
1506                 }
1507
1508         } else {
1509                 channel_strings.push_back (_("one region per file"));
1510
1511                 if (selection_includes_multichannel) {
1512                         channel_strings.push_back (_("one region per channel"));
1513                 }
1514
1515                 if (paths.size() > 1) {
1516                         if (same_size) {
1517                                 channel_strings.push_back (_("all files in one region"));
1518                         }
1519                 }
1520         }
1521
1522         resetting_ourselves = true;
1523
1524         existing_choice = channel_combo.get_active_text();
1525
1526         set_popdown_strings (channel_combo, channel_strings);
1527
1528         /* preserve any existing choice, if possible */
1529
1530         if (existing_choice.length()) {
1531                 vector<string>::iterator x;
1532                 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1533                         if (*x == existing_choice) {
1534                                 channel_combo.set_active_text (existing_choice);
1535                                 break;
1536                         }
1537                 }
1538                 if (x == channel_strings.end()) {
1539                         channel_combo.set_active_text (channel_strings.front());
1540                 }
1541         } else {
1542                 channel_combo.set_active_text (channel_strings.front());
1543         }
1544
1545         resetting_ourselves = false;
1546
1547         if (src_needed) {
1548                 src_combo.set_sensitive (true);
1549         } else {
1550                 src_combo.set_sensitive (false);
1551         }
1552
1553         /* We must copy MIDI files or those from Freesound
1554          * or any file if we are under nsm control */
1555         bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
1556
1557         if (UIConfiguration::instance().get_only_copy_imported_files()) {
1558
1559                 if (selection_can_be_embedded_with_links && !must_copy) {
1560                         copy_files_btn.set_sensitive (true);
1561                 } else {
1562                         if (must_copy) {
1563                                 copy_files_btn.set_active (true);
1564                         }
1565                         copy_files_btn.set_sensitive (false);
1566                 }
1567
1568         }  else {
1569
1570                 if (must_copy) {
1571                         copy_files_btn.set_active (true);
1572                 }
1573                 copy_files_btn.set_sensitive (!must_copy);
1574         }
1575
1576         return true;
1577 }
1578
1579
1580 bool
1581 SoundFileOmega::bad_file_message()
1582 {
1583         MessageDialog msg (*this,
1584                            string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1585                            true,
1586                            Gtk::MESSAGE_INFO,
1587                            Gtk::BUTTONS_OK);
1588         msg.run ();
1589         resetting_ourselves = true;
1590         chooser.unselect_uri (chooser.get_preview_uri());
1591         resetting_ourselves = false;
1592
1593         return false;
1594 }
1595
1596 bool
1597 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1598 {
1599         SoundFileInfo info;
1600         framepos_t sz = 0;
1601         bool err = false;
1602         string errmsg;
1603
1604         same_size = true;
1605         src_needed = false;
1606         multichannel = false;
1607
1608         for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1609
1610                 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1611                         if (info.channels > 1) {
1612                                 multichannel = true;
1613                         }
1614                         if (sz == 0) {
1615                                 sz = info.length;
1616                         } else {
1617                                 if (sz != info.length) {
1618                                         same_size = false;
1619                                 }
1620                         }
1621
1622                         if (info.samplerate != _session->frame_rate()) {
1623                                 src_needed = true;
1624                         }
1625
1626                 } else if (SMFSource::valid_midi_file (*i)) {
1627
1628                         Evoral::SMF reader;
1629
1630                         if (reader.open (*i)) {
1631                                 err = true;
1632                         } else {
1633                                 if (reader.is_type0 ()) {
1634                                         if (reader.channels().size() > 1) {
1635                                                 /* for type-0 files, we can split
1636                                                  * "one track per channel"
1637                                                  */
1638                                                 multichannel = true;
1639                                         }
1640                                 } else {
1641                                         if (reader.num_tracks() > 1) {
1642                                                 multichannel = true;
1643                                         }
1644                                 }
1645                         }
1646
1647                 } else {
1648                         err = true;
1649                 }
1650         }
1651
1652         return err;
1653 }
1654
1655
1656 bool
1657 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1658 {
1659 #ifdef PLATFORM_WINDOWS
1660         return false;
1661 #else
1662         std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
1663         bool ret = false;
1664
1665         if (g_mkdir (tmpdir.c_str(), 0744)) {
1666                 if (errno != EEXIST) {
1667                         return false;
1668                 }
1669         }
1670
1671         for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1672
1673                 char tmpc[PATH_MAX+1];
1674
1675                 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1676
1677                 /* can we link ? */
1678
1679                 if (link ((*i).c_str(), tmpc)) {
1680                         goto out;
1681                 }
1682
1683                 ::g_unlink (tmpc);
1684         }
1685
1686         ret = true;
1687
1688   out:
1689         g_rmdir (tmpdir.c_str());
1690         return ret;
1691 #endif
1692 }
1693
1694 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
1695         : SoundFileBrowser (title, s, false)
1696 {
1697         chooser.set_select_multiple (false);
1698         found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1699         freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1700 }
1701
1702 void
1703 SoundFileChooser::on_hide ()
1704 {
1705         ArdourWindow::on_hide();
1706         stop_metering ();
1707
1708         if (_session) {
1709                 _session->cancel_audition();
1710         }
1711 }
1712
1713 string
1714 SoundFileChooser::get_filename ()
1715 {
1716         vector<string> paths;
1717
1718         paths = get_paths ();
1719
1720         if (paths.empty()) {
1721                 return string ();
1722         }
1723
1724         if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1725                 return string();
1726         }
1727
1728         return paths.front();
1729 }
1730
1731 SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s,
1732                                 uint32_t selected_audio_tracks,
1733                                 uint32_t selected_midi_tracks,
1734                                 bool persistent,
1735                                 Editing::ImportMode mode_hint)
1736         : SoundFileBrowser (title, s, persistent)
1737         , copy_files_btn ( _("Copy files to session"))
1738         , smf_tempo_btn (_("Use MIDI Tempo Map (if defined)"))
1739         , selected_audio_track_cnt (selected_audio_tracks)
1740         , selected_midi_track_cnt (selected_midi_tracks)
1741         , _import_active (false)
1742         , _reset_post_import (false)
1743 {
1744         vector<string> str;
1745
1746         set_size_request (-1, 550);
1747
1748         block_two.set_border_width (12);
1749         block_three.set_border_width (12);
1750         block_four.set_border_width (12);
1751
1752         str.clear ();
1753         str.push_back (_("file timestamp"));
1754         str.push_back (_("edit point"));
1755         str.push_back (_("playhead"));
1756         str.push_back (_("session start"));
1757         set_popdown_strings (where_combo, str);
1758         where_combo.set_active_text (str.back());
1759         where_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::where_combo_changed));
1760
1761         Label* l = manage (new Label);
1762         l->set_markup (_("<b>Add files ...</b>"));
1763         options.attach (*l, 0, 1, 0, 1, FILL, SHRINK, 8, 0);
1764         options.attach (action_combo, 0, 1, 1, 2, FILL, SHRINK, 8, 0);
1765
1766         l = manage (new Label);
1767         l->set_markup (_("<b>Insert at</b>"));
1768         options.attach (*l, 0, 1, 3, 4, FILL, SHRINK, 8, 0);
1769         options.attach (where_combo, 0, 1, 4, 5, FILL, SHRINK, 8, 0);
1770
1771         l = manage (new Label);
1772         l->set_markup (_("<b>Mapping</b>"));
1773         options.attach (*l, 1, 2, 0, 1, FILL, SHRINK, 8, 0);
1774         options.attach (channel_combo, 1, 2, 1, 2, FILL, SHRINK, 8, 0);
1775
1776         l = manage (new Label);
1777         l->set_markup (_("<b>Conversion quality</b>"));
1778         options.attach (*l, 1, 2, 3, 4, FILL, SHRINK, 8, 0);
1779         options.attach (src_combo, 1, 2, 4, 5, FILL, SHRINK, 8, 0);
1780
1781         l = manage (new Label);
1782         l->set_markup (_("<b>MIDI Track Names</b>"));
1783         options.attach (*l, 2, 3, 0, 1, FILL, SHRINK, 8, 0);
1784         options.attach (midi_track_name_combo, 2, 3, 1, 2, FILL, SHRINK, 8, 0);
1785
1786         options.attach (smf_tempo_btn, 2, 3, 3, 4, FILL, SHRINK, 8, 0);
1787
1788         l = manage (new Label);
1789         l->set_markup (_("<b>Instrument</b>"));
1790         options.attach (*l, 3, 4, 0, 1, FILL, SHRINK, 8, 0);
1791         options.attach (instrument_combo, 3, 4, 1, 2, FILL, SHRINK, 8, 0);
1792
1793         Alignment *hspace = manage (new Alignment ());
1794         hspace->set_size_request (2, 2);
1795         options.attach (*hspace, 0, 3, 2, 3, FILL, SHRINK, 0, 8);
1796
1797         Alignment *vspace = manage (new Alignment ());
1798         vspace->set_size_request (2, 2);
1799         options.attach (*vspace, 2, 3, 0, 3, EXPAND, SHRINK, 0, 0);
1800
1801         str.clear ();
1802         str.push_back (_("by track number"));
1803         str.push_back (_("by track name"));
1804         str.push_back (_("by instrument name"));
1805         set_popdown_strings (midi_track_name_combo, str);
1806         midi_track_name_combo.set_active_text (str.front());
1807
1808         str.clear ();
1809         str.push_back (_("one track per file"));
1810         set_popdown_strings (channel_combo, str);
1811         channel_combo.set_active_text (str.front());
1812         channel_combo.set_sensitive (false);
1813
1814         str.clear ();
1815         str.push_back (_("Best"));
1816         str.push_back (_("Good"));
1817         str.push_back (_("Quick"));
1818         str.push_back (_("Fast"));
1819         str.push_back (_("Fastest"));
1820
1821         set_popdown_strings (src_combo, str);
1822         src_combo.set_active_text (str.front());
1823         src_combo.set_sensitive (false);
1824         src_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::src_combo_changed));
1825
1826         action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1827         channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1828
1829         copy_files_btn.set_active (true);
1830
1831         Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1832
1833         if (copy_label) {
1834                 copy_label->set_size_request (175, -1);
1835                 copy_label->set_line_wrap (true);
1836         }
1837
1838         block_four.pack_start (copy_files_btn, false, false);
1839         options.attach (block_four, 3, 4, 4, 5, FILL, SHRINK, 8, 0);
1840
1841         vpacker.pack_start (options, false, true);
1842
1843         /* setup disposition map */
1844
1845         disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1846         disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1847         disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1848         disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1849
1850         disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1851         disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1852         disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1853         disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1854
1855         chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1856
1857         /* set size requests for a couple of combos to allow them to display the longest text
1858            they will ever be asked to display.  This prevents them being resized when the user
1859            selects a file to import, which in turn prevents the size of the dialog from jumping
1860            around. */
1861
1862         str.clear ();
1863         str.push_back (_("one track per file"));
1864         str.push_back (_("one track per channel"));
1865         str.push_back (_("sequence files"));
1866         str.push_back (_("all files in one region"));
1867         set_popdown_strings (channel_combo, str);
1868
1869         str.clear ();
1870         str.push_back (importmode2string (ImportAsTrack));
1871         str.push_back (importmode2string (ImportToTrack));
1872         str.push_back (importmode2string (ImportAsRegion));
1873         str.push_back (importmode2string (ImportAsTapeTrack));
1874         set_popdown_strings (action_combo, str);
1875         action_combo.set_active_text (importmode2string(mode_hint));
1876
1877         reset (selected_audio_tracks, selected_midi_tracks);
1878 }
1879
1880 void
1881 SoundFileOmega::set_mode (ImportMode mode)
1882 {
1883         action_combo.set_active_text (importmode2string (mode));
1884 }
1885
1886 ImportMode
1887 SoundFileOmega::get_mode () const
1888 {
1889         return string2importmode (action_combo.get_active_text());
1890 }
1891
1892 void
1893 SoundFileOmega::on_hide ()
1894 {
1895         ArdourWindow::on_hide();
1896         if (_session) {
1897                 _session->cancel_audition();
1898         }
1899 }
1900
1901 ImportPosition
1902 SoundFileOmega::get_position() const
1903 {
1904         string str = where_combo.get_active_text();
1905
1906         if (str == _("file timestamp")) {
1907                 return ImportAtTimestamp;
1908         } else if (str == _("edit point")) {
1909                 return ImportAtEditPoint;
1910         } else if (str == _("playhead")) {
1911                 return ImportAtPlayhead;
1912         } else {
1913                 return ImportAtStart;
1914         }
1915 }
1916
1917 SrcQuality
1918 SoundFileOmega::get_src_quality() const
1919 {
1920         string str = src_combo.get_active_text();
1921
1922         if (str == _("Best")) {
1923                 return SrcBest;
1924         } else if (str == _("Good")) {
1925                 return SrcGood;
1926         } else if (str == _("Quick")) {
1927                 return SrcQuick;
1928         } else if (str == _("Fast")) {
1929                 return SrcFast;
1930         } else {
1931                 return SrcFastest;
1932         }
1933 }
1934
1935 void
1936 SoundFileOmega::src_combo_changed()
1937 {
1938         preview.set_src_quality(get_src_quality());
1939 }
1940
1941 void
1942 SoundFileOmega::where_combo_changed()
1943 {
1944         preview.set_import_position(get_position());
1945 }
1946
1947 MidiTrackNameSource
1948 SoundFileOmega::get_midi_track_name_source () const
1949 {
1950         return string2miditracknamesource (midi_track_name_combo.get_active_text());
1951 }
1952
1953 bool
1954 SoundFileOmega::get_use_smf_tempo_map () const
1955 {
1956         return smf_tempo_btn.get_active ();
1957 }
1958
1959 ImportDisposition
1960 SoundFileOmega::get_channel_disposition () const
1961 {
1962         /* we use a map here because the channel combo can contain different strings
1963            depending on the state of the other combos. the map contains all possible strings
1964            and the ImportDisposition enum that corresponds to it.
1965         */
1966
1967         string str = channel_combo.get_active_text();
1968         DispositionMap::const_iterator x = disposition_map.find (str);
1969
1970         if (x == disposition_map.end()) {
1971                 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1972                 abort(); /*NOTREACHED*/
1973         }
1974
1975         return x->second;
1976 }
1977
1978 void
1979 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
1980 {
1981         selected_audio_track_cnt = selected_audio_tracks;
1982         selected_midi_track_cnt = selected_midi_tracks;
1983
1984         if (selected_audio_track_cnt == 0 && selected_midi_track_cnt > 0) {
1985                 chooser.set_filter (midi_filter);
1986         } else if (selected_midi_track_cnt == 0 && selected_audio_track_cnt > 0) {
1987                 chooser.set_filter (audio_filter);
1988         } else {
1989                 chooser.set_filter (audio_and_midi_filter);
1990         }
1991
1992         reset_options ();
1993 }
1994
1995 void
1996 SoundFileOmega::file_selection_changed ()
1997 {
1998         if (resetting_ourselves) {
1999                 return;
2000         }
2001
2002         if (!reset_options ()) {
2003                 set_action_sensitive (false);
2004         } else {
2005                 if (chooser.get_filenames().size() > 0) {
2006                         set_action_sensitive (true);
2007                 } else {
2008                         set_action_sensitive (false);
2009                 }
2010         }
2011 }
2012
2013 void
2014 SoundFileOmega::do_something (int action)
2015 {
2016         SoundFileBrowser::do_something (action);
2017
2018         if (action == RESPONSE_CLOSE) {
2019                 hide ();
2020                 return;
2021         }
2022
2023         /* lets do it */
2024
2025         vector<string> paths = get_paths ();
2026         ImportPosition pos = get_position ();
2027         ImportMode mode = get_mode ();
2028         ImportDisposition chns = get_channel_disposition ();
2029         PluginInfoPtr instrument = instrument_combo.selected_instrument();
2030         framepos_t where;
2031         MidiTrackNameSource mts = get_midi_track_name_source ();
2032         MidiTempoMapDisposition mtd = (get_use_smf_tempo_map () ? SMFTempoUse : SMFTempoIgnore);
2033
2034         switch (pos) {
2035         case ImportAtEditPoint:
2036                 where = PublicEditor::instance().get_preferred_edit_position ();
2037                 break;
2038         case ImportAtTimestamp:
2039                 where = -1;
2040                 break;
2041         case ImportAtPlayhead:
2042                 where = _session->transport_frame();
2043                 break;
2044         case ImportAtStart:
2045                 where = _session->current_start_frame();
2046                 break;
2047         }
2048
2049         SrcQuality quality = get_src_quality();
2050
2051         _import_active = true;
2052
2053         if (copy_files_btn.get_active()) {
2054                 PublicEditor::instance().do_import (paths, chns, mode, quality, mts, mtd, where, instrument);
2055         } else {
2056                 PublicEditor::instance().do_embed (paths, chns, mode, where, instrument);
2057         }
2058
2059         _import_active = false;
2060
2061         if (_reset_post_import) {
2062                 _reset_post_import = false;
2063                 reset_options ();
2064         }
2065 }