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