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