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