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