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