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