various tweaks to Freesound UI and code. keep a single mootcher to speed up operatio...
[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 <map>
25 #include <cerrno>
26 #include <sstream>
27
28 #include <unistd.h>
29 #include <sys/stat.h>
30 #include <sys/param.h>
31
32 #include <gtkmm/box.h>
33 #include <gtkmm/stock.h>
34 #include <glibmm/fileutils.h>
35
36 #include "pbd/convert.h"
37 #include "pbd/tokenizer.h"
38 #include "pbd/enumwriter.h"
39 #include "pbd/pthread_utils.h"
40 #include "pbd/xml++.h"
41
42 #include <gtkmm2ext/utils.h>
43
44 #include "evoral/SMF.hpp"
45
46 #include "ardour/amp.h"
47 #include "ardour/audio_library.h"
48 #include "ardour/auditioner.h"
49 #include "ardour/audioregion.h"
50 #include "ardour/audiofilesource.h"
51 #include "ardour/smf_source.h"
52 #include "ardour/region_factory.h"
53 #include "ardour/source_factory.h"
54 #include "ardour/session.h"
55 #include "ardour/session_directory.h"
56 #include "ardour/profile.h"
57
58 #include "ardour_ui.h"
59 #include "editing.h"
60 #include "gui_thread.h"
61 #include "prompter.h"
62 #include "sfdb_ui.h"
63 #include "editing.h"
64 #include "utils.h"
65 #include "gain_meter.h"
66
67 #ifdef FREESOUND
68 #include "sfdb_freesound_mootcher.h"
69 #endif
70
71 #include "i18n.h"
72
73 using namespace ARDOUR;
74 using namespace PBD;
75 using namespace std;
76 using namespace Gtk;
77 using namespace Gtkmm2ext;
78 using namespace Editing;
79
80 using std::string;
81
82 string SoundFileBrowser::persistent_folder;
83
84 static ImportMode
85 string2importmode (string str)
86 {
87         if (str == _("as new tracks")) {
88                 return ImportAsTrack;
89         } else if (str == _("to selected tracks")) {
90                 return ImportToTrack;
91         } else if (str == _("to region list")) {
92                 return ImportAsRegion;
93         } else if (str == _("as new tape tracks")) {
94                 return ImportAsTapeTrack;
95         }
96
97         warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
98
99         return ImportAsTrack;
100 }
101
102 static string
103 importmode2string (ImportMode mode)
104 {
105         switch (mode) {
106         case ImportAsTrack:
107                 return _("as new tracks");
108         case ImportToTrack:
109                 return _("to selected tracks");
110         case ImportAsRegion:
111                 return _("to region list");
112         case ImportAsTapeTrack:
113                 return _("as new tape tracks");
114         }
115         /*NOTREACHED*/
116         return _("as new tracks");
117 }
118
119 SoundFileBox::SoundFileBox (bool persistent)
120         : table (6, 2),
121           length_clock ("sfboxLengthClock", !persistent, "", false, false, true, false),
122           timecode_clock ("sfboxTimecodeClock", !persistent, "", false, false, false, false),
123           main_box (false, 6),
124           autoplay_btn (_("Auto-play"))
125
126 {
127         set_name (X_("SoundFileBox"));
128         set_size_request (300, -1);
129
130         preview_label.set_markup (_("<b>Sound File Information</b>"));
131
132         border_frame.set_label_widget (preview_label);
133         border_frame.add (main_box);
134
135         pack_start (border_frame, true, true);
136         set_border_width (6);
137
138         main_box.set_border_width (6);
139
140         length.set_text (_("Length:"));
141         length.set_alignment (1, 0.5);
142         timecode.set_text (_("Timestamp:"));
143         timecode.set_alignment (1, 0.5);
144         format.set_text (_("Format:"));
145         format.set_alignment (1, 0.5);
146         channels.set_text (_("Channels:"));
147         channels.set_alignment (1, 0.5);
148         samplerate.set_text (_("Sample rate:"));
149         samplerate.set_alignment (1, 0.5);
150
151         preview_label.set_max_width_chars (50);
152         preview_label.set_ellipsize (Pango::ELLIPSIZE_END);
153
154         format_text.set_max_width_chars (20);
155         format_text.set_ellipsize (Pango::ELLIPSIZE_END);
156         format_text.set_alignment (0, 1);
157
158         table.set_col_spacings (6);
159         table.set_homogeneous (false);
160         table.set_row_spacings (6);
161
162         table.attach (channels, 0, 1, 0, 1, FILL, FILL);
163         table.attach (samplerate, 0, 1, 1, 2, FILL, FILL);
164         table.attach (format, 0, 1, 2, 4, FILL, FILL);
165         table.attach (length, 0, 1, 4, 5, FILL, FILL);
166         table.attach (timecode, 0, 1, 5, 6, FILL, FILL);
167
168         table.attach (channels_value, 1, 2, 0, 1, FILL, FILL);
169         table.attach (samplerate_value, 1, 2, 1, 2, FILL, FILL);
170         table.attach (format_text, 1, 2, 2, 4, FILL, FILL);
171         table.attach (length_clock, 1, 2, 4, 5, FILL, FILL);
172         table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL);
173
174         length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock->mode());
175         timecode_clock.set_mode (AudioClock::Timecode);
176
177         main_box.pack_start (table, false, false);
178
179         tags_entry.set_editable (true);
180         tags_entry.set_wrap_mode(Gtk::WRAP_WORD);
181         tags_entry.signal_focus_out_event().connect (sigc::mem_fun (*this, &SoundFileBox::tags_entry_left));
182
183         Label* label = manage (new Label (_("Tags:")));
184         label->set_alignment (0.0f, 0.5f);
185         main_box.pack_start (*label, false, false);
186         main_box.pack_start (tags_entry, true, true);
187
188         main_box.pack_start (bottom_box, false, false);
189
190         play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
191 //      play_btn.set_label (_("Play"));
192
193         stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
194 //      stop_btn.set_label (_("Stop"));
195
196         bottom_box.set_homogeneous (false);
197         bottom_box.set_spacing (6);
198         bottom_box.pack_start(play_btn, true, true);
199         bottom_box.pack_start(stop_btn, true, true);
200         bottom_box.pack_start(autoplay_btn, false, false);
201
202         play_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::audition));
203         stop_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::stop_audition));
204
205         channels_value.set_alignment (0.0f, 0.5f);
206         samplerate_value.set_alignment (0.0f, 0.5f);
207 }
208
209 void
210 SoundFileBox::set_session(Session* s)
211 {
212         SessionHandlePtr::set_session (s);
213
214         length_clock.set_session (s);
215         timecode_clock.set_session (s);
216
217         if (!_session) {
218                 play_btn.set_sensitive (false);
219                 stop_btn.set_sensitive (false);
220         }
221 }
222
223 bool
224 SoundFileBox::setup_labels (const string& filename)
225 {
226         if (!path.empty()) {
227                 // save existing tags
228                 tags_changed ();
229         }
230
231         path = filename;
232
233         string error_msg;
234
235         if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
236
237                 preview_label.set_markup (_("<b>Sound File Information</b>"));
238                 format_text.set_text ("");
239                 channels_value.set_text ("");
240                 samplerate_value.set_text ("");
241                 tags_entry.get_buffer()->set_text ("");
242
243                 length_clock.set (0);
244                 timecode_clock.set (0);
245
246                 tags_entry.set_sensitive (false);
247                 play_btn.set_sensitive (false);
248
249                 return false;
250         }
251
252         preview_label.set_markup (string_compose ("<b>%1</b>", Glib::path_get_basename (filename)));
253         std::string n = sf_info.format_name;
254         if (n.substr (0, 8) == X_("Format: ")) {
255                 n = n.substr (8);
256         }
257         format_text.set_text (n);
258         channels_value.set_text (to_string (sf_info.channels, std::dec));
259
260         if (_session && sf_info.samplerate != _session->frame_rate()) {
261                 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
262                 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
263                 samplerate_value.set_name ("NewSessionSR1Label");
264                 samplerate.set_name ("NewSessionSR1Label");
265         } else {
266                 samplerate.set_text (_("Sample rate:"));
267                 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
268                 samplerate_value.set_name ("NewSessionSR2Label");
269                 samplerate.set_name ("NewSessionSR2Label");
270         }
271
272         framecnt_t const nfr = _session ? _session->nominal_frame_rate() : 25;
273         double src_coef = (double) nfr / sf_info.samplerate;
274
275         length_clock.set (sf_info.length * src_coef + 0.5, true);
276         timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
277
278         // this is a hack that is fixed in trunk, i think (august 26th, 2007)
279
280         vector<string> tags = Library->get_tags (string ("//") + filename);
281
282         stringstream tag_string;
283         for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
284                 if (i != tags.begin()) {
285                         tag_string << ", ";
286                 }
287                 tag_string << *i;
288         }
289         tags_entry.get_buffer()->set_text (tag_string.str());
290
291         tags_entry.set_sensitive (true);
292         if (_session) {
293                 play_btn.set_sensitive (true);
294         }
295
296         return true;
297 }
298
299 bool
300 SoundFileBox::autoplay() const
301 {
302         return autoplay_btn.get_active();
303 }
304
305 bool
306 SoundFileBox::audition_oneshot()
307 {
308         audition ();
309         return false;
310 }
311
312 void
313 SoundFileBox::audition ()
314 {
315         if (!_session) {
316                 return;
317         }
318
319         if (SMFSource::safe_midi_file_extension (path)) {
320                 error << _("Auditioning of MIDI files is not yet supported") << endmsg;
321                 return;
322         }
323
324         _session->cancel_audition();
325
326         if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
327                 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
328                 return;
329         }
330
331         boost::shared_ptr<Region> r;
332         SourceList srclist;
333         boost::shared_ptr<AudioFileSource> afs;
334         bool old_sbp = AudioSource::get_build_peakfiles ();
335
336         /* don't even think of building peakfiles for these files */
337
338         AudioSource::set_build_peakfiles (false);
339
340         for (int n = 0; n < sf_info.channels; ++n) {
341                 try {
342                         afs = boost::dynamic_pointer_cast<AudioFileSource> (
343                                         SourceFactory::createReadable (DataType::AUDIO, *_session,
344                                                         path, n, Source::Flag (0), false));
345
346                         srclist.push_back(afs);
347
348                 } catch (failed_constructor& err) {
349                         error << _("Could not access soundfile: ") << path << endmsg;
350                         AudioSource::set_build_peakfiles (old_sbp);
351                         return;
352                 }
353         }
354
355         AudioSource::set_build_peakfiles (old_sbp);
356
357         if (srclist.empty()) {
358                 return;
359         }
360
361         afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
362         string rname = region_name_from_path (afs->path(), false);
363
364         PropertyList plist;
365
366         plist.add (ARDOUR::Properties::start, 0);
367         plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->timeline_position()));
368         plist.add (ARDOUR::Properties::name, rname);
369         plist.add (ARDOUR::Properties::layer, 0);
370
371         r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false));
372
373         _session->audition_region(r);
374 }
375
376 void
377 SoundFileBox::stop_audition ()
378 {
379         if (_session) {
380                 _session->cancel_audition();
381         }
382 }
383
384 bool
385 SoundFileBox::tags_entry_left (GdkEventFocus *)
386 {
387         tags_changed ();
388         return false;
389 }
390
391 void
392 SoundFileBox::tags_changed ()
393 {
394         string tag_string = tags_entry.get_buffer()->get_text ();
395
396         if (tag_string.empty()) {
397                 return;
398         }
399
400         vector<string> tags;
401
402         if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
403                 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
404                 return;
405         }
406
407         save_tags (tags);
408 }
409
410 void
411 SoundFileBox::save_tags (const vector<string>& tags)
412 {
413         Library->set_tags (string ("//") + path, tags);
414         Library->save_changes ();
415 }
416
417 SoundFileBrowser::SoundFileBrowser (Gtk::Window& parent, string title, ARDOUR::Session* s, bool persistent)
418         : ArdourDialog (parent, title, false, false),
419           found_list (ListStore::create(found_list_columns)),
420           freesound_list (ListStore::create(freesound_list_columns)),
421           chooser (FILE_CHOOSER_ACTION_OPEN),
422           preview (persistent),
423           found_search_btn (_("Search")),
424           found_list_view (found_list),
425           freesound_search_btn (_("Search")),
426           freesound_list_view (freesound_list)
427 {
428         resetting_ourselves = false;
429         gm = 0;
430
431         resetting_ourselves = false;
432         gm = 0;
433
434 #ifdef GTKOSX
435         chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
436         chooser.add_shortcut_folder_uri("file:///Library/Audio/Apple Loops");
437         chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
438
439         chooser.add_shortcut_folder_uri("file:///Volumes");
440 #endif
441
442 #ifdef FREESOUND
443         mootcher = new Mootcher();
444 #endif
445
446         //add the file chooser
447         {
448                 chooser.set_border_width (12);
449
450                 audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
451                 audio_filter.set_name (_("Audio files"));
452
453                 midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
454                 midi_filter.set_name (_("MIDI files"));
455
456                 matchall_filter.add_pattern ("*.*");
457                 matchall_filter.set_name (_("All files"));
458
459                 chooser.add_filter (audio_filter);
460                 chooser.add_filter (midi_filter);
461                 chooser.add_filter (matchall_filter);
462                 chooser.set_select_multiple (true);
463                 chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
464                 chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
465 #ifdef GTKOSX
466                 /* some broken redraw behaviour - this is a bandaid */
467                 chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
468 #endif
469
470                 if (!persistent_folder.empty()) {
471                         chooser.set_current_folder (persistent_folder);
472                 }
473                 notebook.append_page (chooser, _("Browse Files"));
474         }
475
476         hpacker.set_spacing (6);
477         hpacker.pack_start (notebook, true, true);
478         hpacker.pack_start (preview, false, false);
479
480         get_vbox()->pack_start (hpacker, true, true);
481
482         //add tag search
483         {
484                 VBox* vbox;
485                 HBox* hbox;
486
487
488                 hbox = manage(new HBox);
489                 hbox->pack_start (found_entry);
490                 hbox->pack_start (found_search_btn);
491
492                 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
493                 scroll->add(found_list_view);
494                 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
495
496                 vbox = manage(new VBox);
497                 vbox->pack_start (*hbox, PACK_SHRINK);
498                 vbox->pack_start (*scroll);
499
500                 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
501
502                 found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
503
504                 found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
505
506                 found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
507                 found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
508
509                 freesound_stop_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_stop_clicked));
510
511                 notebook.append_page (*vbox, _("Search Tags"));
512         }
513
514         //add freesound search
515 #ifdef FREESOUND
516         {
517                 VBox* vbox;
518                 HBox* passbox;
519                 Label* label;
520
521                 passbox = manage(new HBox);
522                 passbox->set_border_width (12);
523                 passbox->set_spacing (6);
524
525                 label = manage (new Label);
526                 label->set_text (_("Tags:"));
527                 passbox->pack_start (*label, false, false);
528                 passbox->pack_start (freesound_entry, false, false);
529
530                 label = manage (new Label);
531                 label->set_text (_("Sort:"));
532                 passbox->pack_start (*label, false, false);
533                 passbox->pack_start (freesound_sort, false, false);
534                 freesound_sort.clear_items();
535                 
536                 // Order of the following must correspond with enum sortMethod
537                 // in sfdb_freesound_mootcher.h 
538                 freesound_sort.append_text(_("None"));
539                 freesound_sort.append_text(_("Longest"));
540                 freesound_sort.append_text(_("Shortest"));
541                 freesound_sort.append_text(_("Newest"));
542                 freesound_sort.append_text(_("Oldest"));
543                 freesound_sort.append_text(_("Most downloaded"));
544                 freesound_sort.append_text(_("Least downloaded"));
545                 freesound_sort.append_text(_("Highest rated"));
546                 freesound_sort.append_text(_("Lowest rated"));
547                 freesound_sort.set_active(0);
548
549                 passbox->pack_start (freesound_search_btn, false, false);
550                 passbox->pack_start (freesound_progress_bar);
551                 passbox->pack_end   (freesound_stop_btn, false, false);
552                 freesound_stop_btn.set_label(_("Stop"));
553                 
554                 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
555                 scroll->add(freesound_list_view);
556                 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
557
558                 vbox = manage(new VBox);
559                 vbox->pack_start (*passbox, PACK_SHRINK);
560                 vbox->pack_start (*scroll);
561
562                 freesound_list_view.append_column(_("ID")      , freesound_list_columns.id);
563                 freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
564                 // freesound_list_view.append_column(_("URI")     , freesound_list_columns.uri);
565                 freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
566                 freesound_list_view.get_column(1)->set_expand(true);
567
568                 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
569
570                 freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
571                 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
572                 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
573                 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
574                 freesound_stop_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_stop_clicked));
575                 notebook.append_page (*vbox, _("Search Freesound"));
576         }
577
578 #endif
579
580
581         notebook.set_size_request (500, -1);
582
583         set_session (s);
584
585         add_button (Stock::CANCEL, RESPONSE_CANCEL);
586         add_button (Stock::APPLY, RESPONSE_APPLY);
587         add_button (Stock::OK, RESPONSE_OK);
588
589 }
590
591 SoundFileBrowser::~SoundFileBrowser ()
592 {
593         persistent_folder = chooser.get_current_folder();
594 }
595
596
597 void
598 SoundFileBrowser::on_show ()
599 {
600         ArdourDialog::on_show ();
601         start_metering ();
602 }
603
604 void
605 SoundFileBrowser::clear_selection ()
606 {
607         chooser.unselect_all ();
608         found_list_view.get_selection()->unselect_all ();
609 }
610
611 void
612 SoundFileBrowser::chooser_file_activated ()
613 {
614         preview.audition ();
615 }
616
617 void
618 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
619 {
620         preview.audition ();
621 }
622
623 void
624 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
625 {
626         preview.audition ();
627 }
628
629 void
630 SoundFileBrowser::set_session (Session* s)
631 {
632         ArdourDialog::set_session (s);
633         preview.set_session (s);
634
635         if (_session) {
636                 add_gain_meter ();
637         } else {
638                 remove_gain_meter ();
639         }
640 }
641
642 void
643 SoundFileBrowser::add_gain_meter ()
644 {
645         delete gm;
646
647         gm = new GainMeter (_session, 250);
648
649         boost::shared_ptr<Route> r = _session->the_auditioner ();
650
651         gm->set_controls (r, r->shared_peak_meter(), r->amp());
652
653         meter_packer.set_border_width (12);
654         meter_packer.pack_start (*gm, false, true);
655         hpacker.pack_end (meter_packer, false, false);
656         meter_packer.show_all ();
657         start_metering ();
658 }
659
660 void
661 SoundFileBrowser::remove_gain_meter ()
662 {
663         if (gm) {
664                 meter_packer.remove (*gm);
665                 hpacker.remove (meter_packer);
666                 delete gm;
667                 gm = 0;
668         }
669 }
670
671 void
672 SoundFileBrowser::start_metering ()
673 {
674         metering_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
675 }
676
677 void
678 SoundFileBrowser::stop_metering ()
679 {
680         metering_connection.disconnect();
681 }
682
683 void
684 SoundFileBrowser::meter ()
685 {
686         if (is_mapped () && _session && gm) {
687                 gm->update_meters ();
688         }
689 }
690
691 bool
692 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
693 {
694         return AudioFileSource::safe_audio_file_extension (filter_info.filename);
695 }
696
697 bool
698 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
699 {
700         return SMFSource::safe_midi_file_extension (filter_info.filename);
701 }
702
703 void
704 SoundFileBrowser::update_preview ()
705 {
706         if (preview.setup_labels (chooser.get_filename())) {
707                 if (preview.autoplay()) {
708                         Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
709                 }
710         }
711 }
712
713 void
714 SoundFileBrowser::found_list_view_selected ()
715 {
716         if (!reset_options ()) {
717                 set_response_sensitive (RESPONSE_OK, false);
718         } else {
719                 string file;
720
721                 TreeView::Selection::ListHandle_Path rows = found_list_view.get_selection()->get_selected_rows ();
722
723                 if (!rows.empty()) {
724                         TreeIter iter = found_list->get_iter(*rows.begin());
725                         file = (*iter)[found_list_columns.pathname];
726                         chooser.set_filename (file);
727                         set_response_sensitive (RESPONSE_OK, true);
728                 } else {
729                         set_response_sensitive (RESPONSE_OK, false);
730                 }
731
732                 preview.setup_labels (file);
733         }
734 }
735
736 void
737 SoundFileBrowser::freesound_list_view_selected ()
738 {
739         freesound_download_cancel = false;
740
741 #ifdef FREESOUND
742         if (!reset_options ()) {
743                 set_response_sensitive (RESPONSE_OK, false);
744         } else {
745
746                 string file;
747
748                 TreeView::Selection::ListHandle_Path rows = freesound_list_view.get_selection()->get_selected_rows ();
749
750                 if (!rows.empty()) {
751                         TreeIter iter = freesound_list->get_iter(*rows.begin());
752
753                         string id  = (*iter)[freesound_list_columns.id];
754                         string uri = (*iter)[freesound_list_columns.uri];
755                         string ofn = (*iter)[freesound_list_columns.filename];
756
757                         // download the sound file                      
758                         GdkCursor *prev_cursor;
759                         prev_cursor = gdk_window_get_cursor (get_window()->gobj());
760                         gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
761                         gdk_flush();
762
763                         file = mootcher->getAudioFile(ofn, id, uri, this);
764
765                         gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
766
767                         if (file != "") {
768                                 chooser.set_filename (file);
769                                 set_response_sensitive (RESPONSE_OK, true);
770                         }
771                 } else {
772                         set_response_sensitive (RESPONSE_OK, false);
773                 }
774
775                 preview.setup_labels (file);
776         }
777 #endif
778 }
779
780 void
781 SoundFileBrowser::found_search_clicked ()
782 {
783         string tag_string = found_entry.get_text ();
784
785         vector<string> tags;
786
787         if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
788                 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
789                 return;
790         }
791
792         vector<string> results;
793         Library->search_members_and (results, tags);
794
795         found_list->clear();
796         for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
797                 TreeModel::iterator new_row = found_list->append();
798                 TreeModel::Row row = *new_row;
799                 string path = Glib::filename_from_uri (string ("file:") + *i);
800                 row[found_list_columns.pathname] = path;
801         }
802 }
803
804 void
805 SoundFileBrowser::freesound_search_clicked ()
806 {
807         freesound_search_cancel = false;
808         freesound_search();
809 }
810
811 void
812 SoundFileBrowser::freesound_stop_clicked ()
813 {
814         freesound_download_cancel = true;
815         freesound_search_cancel = true;
816 }
817
818
819 void
820 SoundFileBrowser::freesound_search()
821 {
822 #ifdef FREESOUND
823         freesound_list->clear();
824
825         string search_string = freesound_entry.get_text ();
826         enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
827
828         GdkCursor *prev_cursor;
829         prev_cursor = gdk_window_get_cursor (get_window()->gobj());
830         gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
831         gdk_flush();
832         for (int page = 1; page <= 99; page++ ) {
833                 
834                 std::string prog;
835                 prog = string_compose (_("Page %1, [Stop]->"), page);
836                 freesound_progress_bar.set_text(prog);
837                 while (Glib::MainContext::get_default()->iteration (false)) {
838                         /* do nothing */
839                 }
840
841                 std::string theString = mootcher->searchText(
842                         search_string, 
843                         page,
844                         "", // filter, could do, e.g. "type:wav"
845                         sort_method
846                 );
847
848                 XMLTree doc;
849                 doc.read_buffer( theString );
850                 XMLNode *root = doc.root();
851
852                 if (!root) {
853                         cerr << "no root XML node!" << endl;
854                         break;
855                 }
856
857                 if ( strcmp(root->name().c_str(), "response") != 0) {
858                         cerr << "root node name == " << root->name() << ", != \"response\"!" << endl;
859                         break;
860                 }
861
862                 XMLNode *sounds_root = root->child("sounds");
863                 
864                 if (!sounds_root) {
865                         cerr << "no child node \"sounds\" found!" << endl;
866                         break;
867                 }
868                 
869                 XMLNodeList sounds = sounds_root->children();
870                 XMLNodeConstIterator niter;
871                 XMLNode *node;
872                 for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
873                         node = *niter;
874                         if( strcmp( node->name().c_str(), "resource") != 0 ){
875                                 cerr << "node->name()=" << node->name() << ",!= \"resource\"!" << endl;
876                                 freesound_search_cancel = true;
877                                 break;
878                         }
879
880                         // node->dump(cerr, "node:");
881                         
882                         XMLNode *id_node  = node->child ("id");
883                         XMLNode *uri_node = node->child ("serve");
884                         XMLNode *ofn_node = node->child ("original_filename");
885                         XMLNode *dur_node = node->child ("duration");
886
887                         if (id_node && uri_node && ofn_node) {
888                                 
889                                 std::string  id =  id_node->child("text")->content();
890                                 std::string uri = uri_node->child("text")->content();
891                                 std::string ofn = ofn_node->child("text")->content();
892                                 std::string dur = dur_node->child("text")->content();
893
894                                 std::string r;
895                                 // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
896                                 
897                                 double duration_seconds = atof(dur.c_str());
898                                 double h, m, s;
899                                 char duration_hhmmss[16];
900                                 if (duration_seconds >= 99 * 60 * 60) {
901                                         strcpy(duration_hhmmss, ">99h");
902                                 } else {
903                                         s = modf(duration_seconds/60, &m) * 60;
904                                         m = modf(m/60, &h) * 60;
905                                         sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
906                                                 h, m, s
907                                         );
908                                 }
909
910                                 TreeModel::iterator new_row = freesound_list->append();
911                                 TreeModel::Row row = *new_row;
912                                 
913                                 row[freesound_list_columns.id      ] = id;
914                                 row[freesound_list_columns.uri     ] = uri;
915                                 row[freesound_list_columns.filename] = ofn;
916                                 row[freesound_list_columns.duration] = duration_hhmmss;
917
918                         }
919                 }
920         
921                 if (freesound_search_cancel)
922                         break;
923
924         }  //page "for" loop
925
926         gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
927
928         freesound_progress_bar.set_text("");
929
930 #endif
931 }
932
933 vector<string>
934 SoundFileBrowser::get_paths ()
935 {
936         vector<string> results;
937
938         int n = notebook.get_current_page ();
939
940         if (n == 0) {
941                 vector<string> filenames = chooser.get_filenames();
942                 vector<string>::iterator i;
943
944                 for (i = filenames.begin(); i != filenames.end(); ++i) {
945                         struct stat buf;
946                         if ((!stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
947                                 results.push_back (*i);
948                         }
949                 }
950
951         } else if (n==1){
952
953                 typedef TreeView::Selection::ListHandle_Path ListPath;
954
955                 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
956                 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
957                         TreeIter iter = found_list->get_iter(*i);
958                         string str = (*iter)[found_list_columns.pathname];
959
960                         results.push_back (str);
961                 }
962         } else {
963 #ifdef FREESOUND
964                 typedef TreeView::Selection::ListHandle_Path ListPath;
965
966                 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
967                 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
968                         TreeIter iter = freesound_list->get_iter(*i);
969                         string id  = (*iter)[freesound_list_columns.id];
970                         string uri = (*iter)[freesound_list_columns.uri];
971                         string ofn = (*iter)[freesound_list_columns.filename];
972
973                         GdkCursor *prev_cursor;
974                         prev_cursor = gdk_window_get_cursor (get_window()->gobj());
975                         gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
976                         gdk_flush();
977
978                         string str = mootcher->getAudioFile(ofn, id, uri, this);
979                         if (str != "") {
980                                 results.push_back (str);
981                         }
982                         
983                         gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
984
985                 }
986 #endif
987         }
988
989         return results;
990 }
991
992 void
993 SoundFileOmega::reset_options_noret ()
994 {
995         if (!resetting_ourselves) {
996                 (void) reset_options ();
997         }
998 }
999
1000 bool
1001 SoundFileOmega::reset_options ()
1002 {
1003         vector<string> paths = get_paths ();
1004
1005         if (paths.empty()) {
1006
1007                 channel_combo.set_sensitive (false);
1008                 action_combo.set_sensitive (false);
1009                 where_combo.set_sensitive (false);
1010                 copy_files_btn.set_sensitive (false);
1011
1012                 return false;
1013
1014         } else {
1015
1016                 channel_combo.set_sensitive (true);
1017                 action_combo.set_sensitive (true);
1018                 where_combo.set_sensitive (true);
1019
1020                 /* if we get through this function successfully, this may be
1021                    reset at the end, once we know if we can use hard links
1022                    to do embedding
1023                 */
1024
1025                 if (Config->get_only_copy_imported_files()) {
1026                         copy_files_btn.set_sensitive (false);
1027                 } else {
1028                         copy_files_btn.set_sensitive (false);
1029                 }
1030         }
1031
1032         bool same_size;
1033         bool src_needed;
1034         bool selection_includes_multichannel;
1035         bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1036         ImportMode mode;
1037
1038         if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1039                 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1040                 return false;
1041         }
1042
1043         string existing_choice;
1044         vector<string> action_strings;
1045
1046         if (chooser.get_filter() == &audio_filter) {
1047
1048                 /* AUDIO */
1049
1050                 if (selected_audio_track_cnt > 0) {
1051                         if (channel_combo.get_active_text().length()) {
1052                                 ImportDisposition id = get_channel_disposition();
1053                                 
1054                                 switch (id) {
1055                                 case Editing::ImportDistinctFiles:
1056                                         if (selected_audio_track_cnt == paths.size()) {
1057                                                 action_strings.push_back (importmode2string (ImportToTrack));
1058                                         }
1059                                         break;
1060                                         
1061                                 case Editing::ImportDistinctChannels:
1062                                         /* XXX it would be nice to allow channel-per-selected track
1063                                            but its too hard we don't want to deal with all the
1064                                            different per-file + per-track channel configurations.
1065                                         */
1066                                         break;
1067                                         
1068                                 default:
1069                                         action_strings.push_back (importmode2string (ImportToTrack));
1070                                         break;
1071                                 }
1072                         }
1073                 }
1074
1075         }  else {
1076
1077                 /* MIDI */
1078
1079                 if (selected_midi_track_cnt > 0) {
1080                         action_strings.push_back (importmode2string (ImportToTrack));
1081                 }
1082         }
1083
1084         action_strings.push_back (importmode2string (ImportAsTrack));
1085         action_strings.push_back (importmode2string (ImportAsRegion));
1086         action_strings.push_back (importmode2string (ImportAsTapeTrack));
1087
1088         resetting_ourselves = true;
1089
1090         existing_choice = action_combo.get_active_text();
1091
1092         set_popdown_strings (action_combo, action_strings);
1093
1094         /* preserve any existing choice, if possible */
1095
1096
1097         if (existing_choice.length()) {
1098                 vector<string>::iterator x;
1099                 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1100                         if (*x == existing_choice) {
1101                                 action_combo.set_active_text (existing_choice);
1102                                 break;
1103                         }
1104                 }
1105                 if (x == action_strings.end()) {
1106                         action_combo.set_active_text (action_strings.front());
1107                 }
1108         } else {
1109                 action_combo.set_active_text (action_strings.front());
1110         }
1111
1112         resetting_ourselves = false;
1113
1114         if ((mode = get_mode()) == ImportAsRegion) {
1115                 where_combo.set_sensitive (false);
1116         } else {
1117                 where_combo.set_sensitive (true);
1118         }
1119
1120         vector<string> channel_strings;
1121
1122         if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1123                 channel_strings.push_back (_("one track per file"));
1124
1125                 if (selection_includes_multichannel) {
1126                         channel_strings.push_back (_("one track per channel"));
1127                 }
1128
1129                 if (paths.size() > 1) {
1130                         /* tape tracks are a single region per track, so we cannot
1131                            sequence multiple files.
1132                         */
1133                         if (mode != ImportAsTapeTrack) {
1134                                 channel_strings.push_back (_("sequence files"));
1135                         }
1136                         if (same_size) {
1137                                 channel_strings.push_back (_("all files in one track"));
1138                                 channel_strings.push_back (_("merge files"));
1139                         }
1140
1141                 }
1142
1143         } else {
1144                 channel_strings.push_back (_("one region per file"));
1145
1146                 if (selection_includes_multichannel) {
1147                         channel_strings.push_back (_("one region per channel"));
1148                 }
1149
1150                 if (paths.size() > 1) {
1151                         if (same_size) {
1152                                 channel_strings.push_back (_("all files in one region"));
1153                         }
1154                 }
1155         }
1156
1157         resetting_ourselves = true;
1158
1159         existing_choice = channel_combo.get_active_text();
1160
1161         set_popdown_strings (channel_combo, channel_strings);
1162
1163         /* preserve any existing choice, if possible */
1164
1165         if (existing_choice.length()) {
1166                 vector<string>::iterator x;
1167                 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1168                         if (*x == existing_choice) {
1169                                 channel_combo.set_active_text (existing_choice);
1170                                 break;
1171                         }
1172                 }
1173                 if (x == channel_strings.end()) {
1174                         channel_combo.set_active_text (channel_strings.front());
1175                 }
1176         } else {
1177                 channel_combo.set_active_text (channel_strings.front());
1178         }
1179
1180         resetting_ourselves = false;
1181
1182         if (src_needed) {
1183                 src_combo.set_sensitive (true);
1184         } else {
1185                 src_combo.set_sensitive (false);
1186         }
1187
1188         if (Config->get_only_copy_imported_files()) {
1189
1190                 if (selection_can_be_embedded_with_links) {
1191                         copy_files_btn.set_sensitive (true);
1192                 } else {
1193                         copy_files_btn.set_sensitive (false);
1194                 }
1195
1196         }  else {
1197
1198                 copy_files_btn.set_sensitive (true);
1199         }
1200
1201         return true;
1202 }
1203
1204
1205 bool
1206 SoundFileOmega::bad_file_message()
1207 {
1208         MessageDialog msg (*this,
1209                            string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1210                            true,
1211                            Gtk::MESSAGE_INFO,
1212                            Gtk::BUTTONS_OK);
1213         msg.run ();
1214         resetting_ourselves = true;
1215         chooser.unselect_uri (chooser.get_preview_uri());
1216         resetting_ourselves = false;
1217
1218         return false;
1219 }
1220
1221 bool
1222 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1223 {
1224         SoundFileInfo info;
1225         framepos_t sz = 0;
1226         bool err = false;
1227         string errmsg;
1228
1229         same_size = true;
1230         src_needed = false;
1231         multichannel = false;
1232
1233         for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1234
1235                 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1236                         if (info.channels > 1) {
1237                                 multichannel = true;
1238                         }
1239                         if (sz == 0) {
1240                                 sz = info.length;
1241                         } else {
1242                                 if (sz != info.length) {
1243                                         same_size = false;
1244                                 }
1245                         }
1246
1247                         if (info.samplerate != _session->frame_rate()) {
1248                                 src_needed = true;
1249                         }
1250
1251                 } else if (SMFSource::safe_midi_file_extension (*i)) {
1252
1253                         Evoral::SMF reader;
1254                         reader.open(*i);
1255                         if (reader.num_tracks() > 1) {
1256                                 multichannel = true; // "channel" == track here...
1257                         }
1258
1259                         /* XXX we need err = true handling here in case
1260                            we can't check the file
1261                         */
1262
1263                 } else {
1264                         err = true;
1265                 }
1266         }
1267
1268         return err;
1269 }
1270
1271
1272 bool
1273 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1274 {
1275         sys::path path = s->session_directory().sound_path() / "linktest";
1276         string tmpdir = path.to_string();
1277         bool ret = false;
1278
1279         if (mkdir (tmpdir.c_str(), 0744)) {
1280                 if (errno != EEXIST) {
1281                         return false;
1282                 }
1283         }
1284
1285         for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1286
1287                 char tmpc[MAXPATHLEN+1];
1288
1289                 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1290
1291                 /* can we link ? */
1292
1293                 if (link ((*i).c_str(), tmpc)) {
1294                         goto out;
1295                 }
1296
1297                 unlink (tmpc);
1298         }
1299
1300         ret = true;
1301
1302   out:
1303         rmdir (tmpdir.c_str());
1304         return ret;
1305 }
1306
1307 SoundFileChooser::SoundFileChooser (Gtk::Window& parent, string title, ARDOUR::Session* s)
1308         : SoundFileBrowser (parent, title, s, false)
1309 {
1310         chooser.set_select_multiple (false);
1311         found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1312         freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1313 }
1314
1315 void
1316 SoundFileChooser::on_hide ()
1317 {
1318         ArdourDialog::on_hide();
1319         stop_metering ();
1320
1321         if (_session) {
1322                 _session->cancel_audition();
1323         }
1324 }
1325
1326 string
1327 SoundFileChooser::get_filename ()
1328 {
1329         vector<string> paths;
1330
1331         paths = get_paths ();
1332
1333         if (paths.empty()) {
1334                 return string ();
1335         }
1336
1337         if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1338                 return string();
1339         }
1340
1341         return paths.front();
1342 }
1343
1344 SoundFileOmega::SoundFileOmega (Gtk::Window& parent, string title, ARDOUR::Session* s, 
1345                                 uint32_t selected_audio_tracks, 
1346                                 uint32_t selected_midi_tracks, 
1347                                 bool persistent,
1348                                 Editing::ImportMode mode_hint)
1349         : SoundFileBrowser (parent, title, s, persistent)
1350         , copy_files_btn ( _("Copy files to session"))
1351         , selected_audio_track_cnt (selected_audio_tracks)
1352         , selected_midi_track_cnt (selected_midi_tracks)
1353 {
1354         VBox* vbox;
1355         HBox* hbox;
1356         vector<string> str;
1357
1358         set_size_request (-1, 450);
1359
1360         block_two.set_border_width (12);
1361         block_three.set_border_width (12);
1362         block_four.set_border_width (12);
1363
1364         options.set_spacing (12);
1365
1366         str.clear ();
1367         str.push_back (_("file timestamp"));
1368         str.push_back (_("edit point"));
1369         str.push_back (_("playhead"));
1370         str.push_back (_("session start"));
1371         set_popdown_strings (where_combo, str);
1372         where_combo.set_active_text (str.front());
1373
1374         Label* l = manage (new Label);
1375         l->set_text (_("Add files:"));
1376
1377         hbox = manage (new HBox);
1378         hbox->set_border_width (12);
1379         hbox->set_spacing (6);
1380         hbox->pack_start (*l, false, false);
1381         hbox->pack_start (action_combo, false, false);
1382         vbox = manage (new VBox);
1383         vbox->pack_start (*hbox, false, false);
1384         options.pack_start (*vbox, false, false);
1385
1386         /* dummy entry for action combo so that it doesn't look odd if we
1387            come up with no tracks selected.
1388         */
1389
1390         str.clear ();
1391         str.push_back (importmode2string (mode_hint));
1392         set_popdown_strings (action_combo, str);
1393         action_combo.set_active_text (str.front());
1394         action_combo.set_sensitive (false);
1395
1396         l = manage (new Label);
1397         l->set_text (_("Insert at:"));
1398
1399         hbox = manage (new HBox);
1400         hbox->set_border_width (12);
1401         hbox->set_spacing (6);
1402         hbox->pack_start (*l, false, false);
1403         hbox->pack_start (where_combo, false, false);
1404         vbox = manage (new VBox);
1405         vbox->pack_start (*hbox, false, false);
1406         options.pack_start (*vbox, false, false);
1407
1408
1409         l = manage (new Label);
1410         l->set_text (_("Mapping:"));
1411
1412         hbox = manage (new HBox);
1413         hbox->set_border_width (12);
1414         hbox->set_spacing (6);
1415         hbox->pack_start (*l, false, false);
1416         hbox->pack_start (channel_combo, false, false);
1417         vbox = manage (new VBox);
1418         vbox->pack_start (*hbox, false, false);
1419         options.pack_start (*vbox, false, false);
1420
1421         str.clear ();
1422         str.push_back (_("one track per file"));
1423         set_popdown_strings (channel_combo, str);
1424         channel_combo.set_active_text (str.front());
1425         channel_combo.set_sensitive (false);
1426
1427         l = manage (new Label);
1428         l->set_text (_("Conversion quality:"));
1429
1430         hbox = manage (new HBox);
1431         hbox->set_border_width (12);
1432         hbox->set_spacing (6);
1433         hbox->pack_start (*l, false, false);
1434         hbox->pack_start (src_combo, false, false);
1435         vbox = manage (new VBox);
1436         vbox->pack_start (*hbox, false, false);
1437         options.pack_start (*vbox, false, false);
1438
1439         str.clear ();
1440         str.push_back (_("Best"));
1441         str.push_back (_("Good"));
1442         str.push_back (_("Quick"));
1443         str.push_back (_("Fast"));
1444         str.push_back (_("Fastest"));
1445
1446         set_popdown_strings (src_combo, str);
1447         src_combo.set_active_text (str.front());
1448         src_combo.set_sensitive (false);
1449
1450         reset_options ();
1451
1452         action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1453         channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1454
1455         copy_files_btn.set_active (true);
1456
1457         block_four.pack_start (copy_files_btn, false, false);
1458
1459         options.pack_start (block_four, false, false);
1460
1461         get_vbox()->pack_start (options, false, false);
1462
1463         /* setup disposition map */
1464
1465         disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1466         disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1467         disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1468         disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1469
1470         disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1471         disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1472         disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1473         disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1474
1475         chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1476
1477         /* set size requests for a couple of combos to allow them to display the longest text
1478            they will ever be asked to display.  This prevents them being resized when the user
1479            selects a file to import, which in turn prevents the size of the dialog from jumping
1480            around. */
1481
1482         vector<string> t;
1483         t.push_back (_("one track per file"));
1484         t.push_back (_("one track per channel"));
1485         t.push_back (_("sequence files"));
1486         t.push_back (_("all files in one region"));
1487         set_popdown_strings (channel_combo, t);
1488
1489         t.clear ();
1490         t.push_back (importmode2string (ImportAsTrack));
1491         t.push_back (importmode2string (ImportToTrack));
1492         t.push_back (importmode2string (ImportAsRegion));
1493         t.push_back (importmode2string (ImportAsTapeTrack));
1494         set_popdown_strings (action_combo, t);
1495 }
1496
1497 void
1498 SoundFileOmega::set_mode (ImportMode mode)
1499 {
1500         action_combo.set_active_text (importmode2string (mode));
1501 }
1502
1503 ImportMode
1504 SoundFileOmega::get_mode () const
1505 {
1506         return string2importmode (action_combo.get_active_text());
1507 }
1508
1509 void
1510 SoundFileOmega::on_hide ()
1511 {
1512         ArdourDialog::on_hide();
1513         if (_session) {
1514                 _session->cancel_audition();
1515         }
1516 }
1517
1518 ImportPosition
1519 SoundFileOmega::get_position() const
1520 {
1521         string str = where_combo.get_active_text();
1522
1523         if (str == _("file timestamp")) {
1524                 return ImportAtTimestamp;
1525         } else if (str == _("edit point")) {
1526                 return ImportAtEditPoint;
1527         } else if (str == _("playhead")) {
1528                 return ImportAtPlayhead;
1529         } else {
1530                 return ImportAtStart;
1531         }
1532 }
1533
1534 SrcQuality
1535 SoundFileOmega::get_src_quality() const
1536 {
1537         string str = where_combo.get_active_text();
1538
1539         if (str == _("Best")) {
1540                 return SrcBest;
1541         } else if (str == _("Good")) {
1542                 return SrcGood;
1543         } else if (str == _("Quick")) {
1544                 return SrcQuick;
1545         } else if (str == _("Fast")) {
1546                 return SrcFast;
1547         } else {
1548                 return SrcFastest;
1549         }
1550 }
1551
1552 ImportDisposition
1553 SoundFileOmega::get_channel_disposition () const
1554 {
1555         /* we use a map here because the channel combo can contain different strings
1556            depending on the state of the other combos. the map contains all possible strings
1557            and the ImportDisposition enum that corresponds to it.
1558         */
1559
1560         string str = channel_combo.get_active_text();
1561         DispositionMap::const_iterator x = disposition_map.find (str);
1562
1563         if (x == disposition_map.end()) {
1564                 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1565                 /*NOTREACHED*/
1566         }
1567
1568         return x->second;
1569 }
1570
1571 void
1572 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
1573 {
1574         selected_audio_track_cnt = selected_audio_tracks;
1575         selected_midi_track_cnt = selected_midi_tracks;
1576         reset_options ();
1577 }
1578
1579 void
1580 SoundFileOmega::file_selection_changed ()
1581 {
1582         if (resetting_ourselves) {
1583                 return;
1584         }
1585
1586         if (!reset_options ()) {
1587                 set_response_sensitive (RESPONSE_OK, false);
1588         } else {
1589                 if (chooser.get_filenames().size() > 0) {
1590                         set_response_sensitive (RESPONSE_OK, true);
1591                 } else {
1592                         set_response_sensitive (RESPONSE_OK, false);
1593                 }
1594         }
1595 }
1596