allow compilation without --freesound
[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, "EditCursorClock", false, false, true, false),
122           timecode_clock ("sfboxTimecodeClock", !persistent, "EditCursorClock", 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                 
552                 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
553                 scroll->add(freesound_list_view);
554                 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
555
556                 vbox = manage(new VBox);
557                 vbox->pack_start (*passbox, PACK_SHRINK);
558                 vbox->pack_start (*scroll);
559
560                 freesound_list_view.append_column(_("ID")      , freesound_list_columns.id);
561                 freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
562                 freesound_list_view.append_column(_("URI")     , freesound_list_columns.uri);
563                 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
564
565                 freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
566                 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
567                 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
568                 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
569                 notebook.append_page (*vbox, _("Search Freesound"));
570         }
571 #endif
572
573
574         notebook.set_size_request (500, -1);
575
576         set_session (s);
577
578         add_button (Stock::CANCEL, RESPONSE_CANCEL);
579         add_button (Stock::APPLY, RESPONSE_APPLY);
580         add_button (Stock::OK, RESPONSE_OK);
581
582 }
583
584 SoundFileBrowser::~SoundFileBrowser ()
585 {
586         persistent_folder = chooser.get_current_folder();
587 }
588
589
590 void
591 SoundFileBrowser::on_show ()
592 {
593         ArdourDialog::on_show ();
594         start_metering ();
595 }
596
597 void
598 SoundFileBrowser::clear_selection ()
599 {
600         chooser.unselect_all ();
601         found_list_view.get_selection()->unselect_all ();
602 }
603
604 void
605 SoundFileBrowser::chooser_file_activated ()
606 {
607         preview.audition ();
608 }
609
610 void
611 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
612 {
613         preview.audition ();
614 }
615
616 void
617 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
618 {
619         preview.audition ();
620 }
621
622 void
623 SoundFileBrowser::set_session (Session* s)
624 {
625         ArdourDialog::set_session (s);
626         preview.set_session (s);
627
628         if (_session) {
629                 add_gain_meter ();
630         } else {
631                 remove_gain_meter ();
632         }
633 }
634
635 void
636 SoundFileBrowser::add_gain_meter ()
637 {
638         delete gm;
639
640         gm = new GainMeter (_session, 250);
641
642         boost::shared_ptr<Route> r = _session->the_auditioner ();
643
644         gm->set_controls (r, r->shared_peak_meter(), r->amp());
645
646         meter_packer.set_border_width (12);
647         meter_packer.pack_start (*gm, false, true);
648         hpacker.pack_end (meter_packer, false, false);
649         meter_packer.show_all ();
650         start_metering ();
651 }
652
653 void
654 SoundFileBrowser::remove_gain_meter ()
655 {
656         if (gm) {
657                 meter_packer.remove (*gm);
658                 hpacker.remove (meter_packer);
659                 delete gm;
660                 gm = 0;
661         }
662 }
663
664 void
665 SoundFileBrowser::start_metering ()
666 {
667         metering_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
668 }
669
670 void
671 SoundFileBrowser::stop_metering ()
672 {
673         metering_connection.disconnect();
674 }
675
676 void
677 SoundFileBrowser::meter ()
678 {
679         if (is_mapped () && _session && gm) {
680                 gm->update_meters ();
681         }
682 }
683
684 bool
685 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
686 {
687         return AudioFileSource::safe_audio_file_extension (filter_info.filename);
688 }
689
690 bool
691 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
692 {
693         return SMFSource::safe_midi_file_extension (filter_info.filename);
694 }
695
696 void
697 SoundFileBrowser::update_preview ()
698 {
699         if (preview.setup_labels (chooser.get_filename())) {
700                 if (preview.autoplay()) {
701                         Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
702                 }
703         }
704 }
705
706 void
707 SoundFileBrowser::found_list_view_selected ()
708 {
709         if (!reset_options ()) {
710                 set_response_sensitive (RESPONSE_OK, false);
711         } else {
712                 string file;
713
714                 TreeView::Selection::ListHandle_Path rows = found_list_view.get_selection()->get_selected_rows ();
715
716                 if (!rows.empty()) {
717                         TreeIter iter = found_list->get_iter(*rows.begin());
718                         file = (*iter)[found_list_columns.pathname];
719                         chooser.set_filename (file);
720                         set_response_sensitive (RESPONSE_OK, true);
721                 } else {
722                         set_response_sensitive (RESPONSE_OK, false);
723                 }
724
725                 preview.setup_labels (file);
726         }
727 }
728
729 void
730 SoundFileBrowser::freesound_list_view_selected ()
731 {
732 #ifdef FREESOUND
733         if (!reset_options ()) {
734                 set_response_sensitive (RESPONSE_OK, false);
735         } else {
736
737                 string path;
738                 path = Glib::get_home_dir();
739                 path += "/Freesound/";
740                 Mootcher theMootcher(path.c_str()); // XXX should be a member of SoundFileBrowser
741
742                 string file;
743
744                 TreeView::Selection::ListHandle_Path rows = freesound_list_view.get_selection()->get_selected_rows ();
745
746                 if (!rows.empty()) {
747                         TreeIter iter = freesound_list->get_iter(*rows.begin());
748
749                         string id  = (*iter)[freesound_list_columns.id];
750                         string uri = (*iter)[freesound_list_columns.uri];
751                         string ofn = (*iter)[freesound_list_columns.filename];
752
753                         // download the sound file                      
754                         GdkCursor *prev_cursor;
755                         prev_cursor = gdk_window_get_cursor (get_window()->gobj());
756                         gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
757                         gdk_flush();
758
759                         file = theMootcher.getAudioFile(ofn, id, uri, &progress_bar);
760
761                         gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
762
763                         chooser.set_filename (file);
764                         set_response_sensitive (RESPONSE_OK, true);
765                 } else {
766                         set_response_sensitive (RESPONSE_OK, false);
767                 }
768
769                 preview.setup_labels (file);
770         }
771 #endif
772 }
773
774 void
775 SoundFileBrowser::found_search_clicked ()
776 {
777         string tag_string = found_entry.get_text ();
778
779         vector<string> tags;
780
781         if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
782                 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
783                 return;
784         }
785
786         vector<string> results;
787         Library->search_members_and (results, tags);
788
789         found_list->clear();
790         for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
791                 TreeModel::iterator new_row = found_list->append();
792                 TreeModel::Row row = *new_row;
793                 string path = Glib::filename_from_uri (string ("file:") + *i);
794                 row[found_list_columns.pathname] = path;
795         }
796 }
797
798 void
799 SoundFileBrowser::freesound_search_clicked ()
800 {
801         freesound_search();
802 }
803
804
805 void
806 SoundFileBrowser::freesound_search()
807 {
808 #ifdef FREESOUND
809         freesound_list->clear();
810
811         string path;
812         path = Glib::get_home_dir();
813         path += "/Freesound/";
814         Mootcher theMootcher(path.c_str());
815
816         string search_string = freesound_entry.get_text ();
817         enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
818         int page = freesound_page.get_value_as_int();
819
820         GdkCursor *prev_cursor;
821         prev_cursor = gdk_window_get_cursor (get_window()->gobj());
822         gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
823         gdk_flush();
824
825         string theString = theMootcher.searchText(
826                 search_string, 
827                 page,
828                 "", // filter, could do, e.g. "type:wav"
829                 sort_method
830         );
831
832         gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
833
834         XMLTree doc;
835         doc.read_buffer( theString );
836         XMLNode *root = doc.root();
837
838         if (!root) {
839                 cerr << "no root XML node!" << endl;
840                 return;
841         }
842
843         if ( strcmp(root->name().c_str(), "response") != 0) {
844                 cerr << "root node name == " << root->name() << ", != \"response\"!" << endl;
845                 return;
846         }
847
848         XMLNode *sounds_root = root->child("sounds");
849         
850         if (!sounds_root) {
851                 cerr << "no child node \"sounds\" found!" << endl;
852                 return;
853         }
854         
855         XMLNodeList sounds = sounds_root->children();
856         XMLNodeConstIterator niter;
857         XMLNode *node;
858         for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
859                 node = *niter;
860                 if( strcmp( node->name().c_str(), "resource") != 0 ){
861                         cerr << "node->name()=" << node->name() << ",!= \"resource\"!" << endl;
862                         continue; // return;
863                 }
864
865                 // node->dump(cerr, "node:");
866                 
867                 XMLNode *id_node  = node->child ("id");
868                 XMLNode *uri_node = node->child ("serve");
869                 XMLNode *ofn_node = node->child ("original_filename");
870
871                 if (id_node && uri_node && ofn_node) {
872                         
873                         std::string  id =  id_node->child("text")->content();
874                         std::string uri = uri_node->child("text")->content();
875                         std::string ofn = ofn_node->child("text")->content();
876
877                         std::string r;
878                         // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << endl;
879
880                         TreeModel::iterator new_row = freesound_list->append();
881                         TreeModel::Row row = *new_row;
882                         
883                         row[freesound_list_columns.id      ] = id;
884                         row[freesound_list_columns.uri     ] = uri;
885                         row[freesound_list_columns.filename] = ofn;
886
887                 }
888         }
889 #endif
890 }
891
892 vector<string>
893 SoundFileBrowser::get_paths ()
894 {
895         vector<string> results;
896
897         int n = notebook.get_current_page ();
898
899         if (n == 0) {
900                 vector<string> filenames = chooser.get_filenames();
901                 vector<string>::iterator i;
902
903                 for (i = filenames.begin(); i != filenames.end(); ++i) {
904                         struct stat buf;
905                         if ((!stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
906                                 results.push_back (*i);
907                         }
908                 }
909
910         } else if (n==1){
911
912                 typedef TreeView::Selection::ListHandle_Path ListPath;
913
914                 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
915                 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
916                         TreeIter iter = found_list->get_iter(*i);
917                         string str = (*iter)[found_list_columns.pathname];
918
919                         results.push_back (str);
920                 }
921         } else {
922 #ifdef FREESOUND
923                 typedef TreeView::Selection::ListHandle_Path ListPath;
924
925                 string path;
926                 path = Glib::get_home_dir();
927                 path += "/Freesound/";
928                 Mootcher theMootcher(path.c_str()); // XXX should be a member of SoundFileBrowser
929
930
931                 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
932                 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
933                         TreeIter iter = freesound_list->get_iter(*i);
934                         string id  = (*iter)[freesound_list_columns.id];
935                         string uri = (*iter)[freesound_list_columns.uri];
936                         string ofn = (*iter)[freesound_list_columns.filename];
937
938                         GdkCursor *prev_cursor;
939                         prev_cursor = gdk_window_get_cursor (get_window()->gobj());
940                         gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
941                         gdk_flush();
942
943                         string str = theMootcher.getAudioFile(ofn, id, uri, &progress_bar);
944                         results.push_back (str);
945                         
946                         gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
947
948                 }
949 #endif
950         }
951
952         return results;
953 }
954
955 void
956 SoundFileOmega::reset_options_noret ()
957 {
958         if (!resetting_ourselves) {
959                 (void) reset_options ();
960         }
961 }
962
963 bool
964 SoundFileOmega::reset_options ()
965 {
966         vector<string> paths = get_paths ();
967
968         if (paths.empty()) {
969
970                 channel_combo.set_sensitive (false);
971                 action_combo.set_sensitive (false);
972                 where_combo.set_sensitive (false);
973                 copy_files_btn.set_sensitive (false);
974
975                 return false;
976
977         } else {
978
979                 channel_combo.set_sensitive (true);
980                 action_combo.set_sensitive (true);
981                 where_combo.set_sensitive (true);
982
983                 /* if we get through this function successfully, this may be
984                    reset at the end, once we know if we can use hard links
985                    to do embedding
986                 */
987
988                 if (Config->get_only_copy_imported_files()) {
989                         copy_files_btn.set_sensitive (false);
990                 } else {
991                         copy_files_btn.set_sensitive (false);
992                 }
993         }
994
995         bool same_size;
996         bool src_needed;
997         bool selection_includes_multichannel;
998         bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
999         ImportMode mode;
1000
1001         if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1002                 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1003                 return false;
1004         }
1005
1006         string existing_choice;
1007         vector<string> action_strings;
1008
1009         if (chooser.get_filter() == &audio_filter) {
1010
1011                 /* AUDIO */
1012
1013                 if (selected_audio_track_cnt > 0) {
1014                         if (channel_combo.get_active_text().length()) {
1015                                 ImportDisposition id = get_channel_disposition();
1016                                 
1017                                 switch (id) {
1018                                 case Editing::ImportDistinctFiles:
1019                                         if (selected_audio_track_cnt == paths.size()) {
1020                                                 action_strings.push_back (importmode2string (ImportToTrack));
1021                                         }
1022                                         break;
1023                                         
1024                                 case Editing::ImportDistinctChannels:
1025                                         /* XXX it would be nice to allow channel-per-selected track
1026                                            but its too hard we don't want to deal with all the
1027                                            different per-file + per-track channel configurations.
1028                                         */
1029                                         break;
1030                                         
1031                                 default:
1032                                         action_strings.push_back (importmode2string (ImportToTrack));
1033                                         break;
1034                                 }
1035                         }
1036                 }
1037
1038         }  else {
1039
1040                 /* MIDI */
1041
1042                 if (selected_midi_track_cnt > 0) {
1043                         action_strings.push_back (importmode2string (ImportToTrack));
1044                 }
1045         }
1046
1047         action_strings.push_back (importmode2string (ImportAsTrack));
1048         action_strings.push_back (importmode2string (ImportAsRegion));
1049         action_strings.push_back (importmode2string (ImportAsTapeTrack));
1050
1051         resetting_ourselves = true;
1052
1053         existing_choice = action_combo.get_active_text();
1054
1055         set_popdown_strings (action_combo, action_strings);
1056
1057         /* preserve any existing choice, if possible */
1058
1059
1060         if (existing_choice.length()) {
1061                 vector<string>::iterator x;
1062                 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1063                         if (*x == existing_choice) {
1064                                 action_combo.set_active_text (existing_choice);
1065                                 break;
1066                         }
1067                 }
1068                 if (x == action_strings.end()) {
1069                         action_combo.set_active_text (action_strings.front());
1070                 }
1071         } else {
1072                 action_combo.set_active_text (action_strings.front());
1073         }
1074
1075         resetting_ourselves = false;
1076
1077         if ((mode = get_mode()) == ImportAsRegion) {
1078                 where_combo.set_sensitive (false);
1079         } else {
1080                 where_combo.set_sensitive (true);
1081         }
1082
1083         vector<string> channel_strings;
1084
1085         if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1086                 channel_strings.push_back (_("one track per file"));
1087
1088                 if (selection_includes_multichannel) {
1089                         channel_strings.push_back (_("one track per channel"));
1090                 }
1091
1092                 if (paths.size() > 1) {
1093                         /* tape tracks are a single region per track, so we cannot
1094                            sequence multiple files.
1095                         */
1096                         if (mode != ImportAsTapeTrack) {
1097                                 channel_strings.push_back (_("sequence files"));
1098                         }
1099                         if (same_size) {
1100                                 channel_strings.push_back (_("all files in one track"));
1101                                 channel_strings.push_back (_("merge files"));
1102                         }
1103
1104                 }
1105
1106         } else {
1107                 channel_strings.push_back (_("one region per file"));
1108
1109                 if (selection_includes_multichannel) {
1110                         channel_strings.push_back (_("one region per channel"));
1111                 }
1112
1113                 if (paths.size() > 1) {
1114                         if (same_size) {
1115                                 channel_strings.push_back (_("all files in one region"));
1116                         }
1117                 }
1118         }
1119
1120         resetting_ourselves = true;
1121
1122         existing_choice = channel_combo.get_active_text();
1123
1124         set_popdown_strings (channel_combo, channel_strings);
1125
1126         /* preserve any existing choice, if possible */
1127
1128         if (existing_choice.length()) {
1129                 vector<string>::iterator x;
1130                 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1131                         if (*x == existing_choice) {
1132                                 channel_combo.set_active_text (existing_choice);
1133                                 break;
1134                         }
1135                 }
1136                 if (x == channel_strings.end()) {
1137                         channel_combo.set_active_text (channel_strings.front());
1138                 }
1139         } else {
1140                 channel_combo.set_active_text (channel_strings.front());
1141         }
1142
1143         resetting_ourselves = false;
1144
1145         if (src_needed) {
1146                 src_combo.set_sensitive (true);
1147         } else {
1148                 src_combo.set_sensitive (false);
1149         }
1150
1151         if (Config->get_only_copy_imported_files()) {
1152
1153                 if (selection_can_be_embedded_with_links) {
1154                         copy_files_btn.set_sensitive (true);
1155                 } else {
1156                         copy_files_btn.set_sensitive (false);
1157                 }
1158
1159         }  else {
1160
1161                 copy_files_btn.set_sensitive (true);
1162         }
1163
1164         return true;
1165 }
1166
1167
1168 bool
1169 SoundFileOmega::bad_file_message()
1170 {
1171         MessageDialog msg (*this,
1172                            string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1173                            true,
1174                            Gtk::MESSAGE_INFO,
1175                            Gtk::BUTTONS_OK);
1176         msg.run ();
1177         resetting_ourselves = true;
1178         chooser.unselect_uri (chooser.get_preview_uri());
1179         resetting_ourselves = false;
1180
1181         return false;
1182 }
1183
1184 bool
1185 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1186 {
1187         SoundFileInfo info;
1188         framepos_t sz = 0;
1189         bool err = false;
1190         string errmsg;
1191
1192         same_size = true;
1193         src_needed = false;
1194         multichannel = false;
1195
1196         for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1197
1198                 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1199                         if (info.channels > 1) {
1200                                 multichannel = true;
1201                         }
1202                         if (sz == 0) {
1203                                 sz = info.length;
1204                         } else {
1205                                 if (sz != info.length) {
1206                                         same_size = false;
1207                                 }
1208                         }
1209
1210                         if (info.samplerate != _session->frame_rate()) {
1211                                 src_needed = true;
1212                         }
1213
1214                 } else if (SMFSource::safe_midi_file_extension (*i)) {
1215
1216                         Evoral::SMF reader;
1217                         reader.open(*i);
1218                         if (reader.num_tracks() > 1) {
1219                                 multichannel = true; // "channel" == track here...
1220                         }
1221
1222                         /* XXX we need err = true handling here in case
1223                            we can't check the file
1224                         */
1225
1226                 } else {
1227                         err = true;
1228                 }
1229         }
1230
1231         return err;
1232 }
1233
1234
1235 bool
1236 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1237 {
1238         sys::path path = s->session_directory().sound_path() / "linktest";
1239         string tmpdir = path.to_string();
1240         bool ret = false;
1241
1242         if (mkdir (tmpdir.c_str(), 0744)) {
1243                 if (errno != EEXIST) {
1244                         return false;
1245                 }
1246         }
1247
1248         for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1249
1250                 char tmpc[MAXPATHLEN+1];
1251
1252                 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1253
1254                 /* can we link ? */
1255
1256                 if (link ((*i).c_str(), tmpc)) {
1257                         goto out;
1258                 }
1259
1260                 unlink (tmpc);
1261         }
1262
1263         ret = true;
1264
1265   out:
1266         rmdir (tmpdir.c_str());
1267         return ret;
1268 }
1269
1270 SoundFileChooser::SoundFileChooser (Gtk::Window& parent, string title, ARDOUR::Session* s)
1271         : SoundFileBrowser (parent, title, s, false)
1272 {
1273         chooser.set_select_multiple (false);
1274         found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1275         freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1276 }
1277
1278 void
1279 SoundFileChooser::on_hide ()
1280 {
1281         ArdourDialog::on_hide();
1282         stop_metering ();
1283
1284         if (_session) {
1285                 _session->cancel_audition();
1286         }
1287 }
1288
1289 string
1290 SoundFileChooser::get_filename ()
1291 {
1292         vector<string> paths;
1293
1294         paths = get_paths ();
1295
1296         if (paths.empty()) {
1297                 return string ();
1298         }
1299
1300         if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1301                 return string();
1302         }
1303
1304         return paths.front();
1305 }
1306
1307 SoundFileOmega::SoundFileOmega (Gtk::Window& parent, string title, ARDOUR::Session* s, 
1308                                 uint32_t selected_audio_tracks, 
1309                                 uint32_t selected_midi_tracks, 
1310                                 bool persistent,
1311                                 Editing::ImportMode mode_hint)
1312         : SoundFileBrowser (parent, title, s, persistent)
1313         , copy_files_btn ( _("Copy files to session"))
1314         , selected_audio_track_cnt (selected_audio_tracks)
1315         , selected_midi_track_cnt (selected_midi_tracks)
1316 {
1317         VBox* vbox;
1318         HBox* hbox;
1319         vector<string> str;
1320
1321         set_size_request (-1, 450);
1322
1323         block_two.set_border_width (12);
1324         block_three.set_border_width (12);
1325         block_four.set_border_width (12);
1326
1327         options.set_spacing (12);
1328
1329         str.clear ();
1330         str.push_back (_("file timestamp"));
1331         str.push_back (_("edit point"));
1332         str.push_back (_("playhead"));
1333         str.push_back (_("session start"));
1334         set_popdown_strings (where_combo, str);
1335         where_combo.set_active_text (str.front());
1336
1337         Label* l = manage (new Label);
1338         l->set_text (_("Add files:"));
1339
1340         hbox = manage (new HBox);
1341         hbox->set_border_width (12);
1342         hbox->set_spacing (6);
1343         hbox->pack_start (*l, false, false);
1344         hbox->pack_start (action_combo, false, false);
1345         vbox = manage (new VBox);
1346         vbox->pack_start (*hbox, false, false);
1347         options.pack_start (*vbox, false, false);
1348
1349         /* dummy entry for action combo so that it doesn't look odd if we
1350            come up with no tracks selected.
1351         */
1352
1353         str.clear ();
1354         str.push_back (importmode2string (mode_hint));
1355         set_popdown_strings (action_combo, str);
1356         action_combo.set_active_text (str.front());
1357         action_combo.set_sensitive (false);
1358
1359         l = manage (new Label);
1360         l->set_text (_("Insert at:"));
1361
1362         hbox = manage (new HBox);
1363         hbox->set_border_width (12);
1364         hbox->set_spacing (6);
1365         hbox->pack_start (*l, false, false);
1366         hbox->pack_start (where_combo, false, false);
1367         vbox = manage (new VBox);
1368         vbox->pack_start (*hbox, false, false);
1369         options.pack_start (*vbox, false, false);
1370
1371
1372         l = manage (new Label);
1373         l->set_text (_("Mapping:"));
1374
1375         hbox = manage (new HBox);
1376         hbox->set_border_width (12);
1377         hbox->set_spacing (6);
1378         hbox->pack_start (*l, false, false);
1379         hbox->pack_start (channel_combo, false, false);
1380         vbox = manage (new VBox);
1381         vbox->pack_start (*hbox, false, false);
1382         options.pack_start (*vbox, false, false);
1383
1384         str.clear ();
1385         str.push_back (_("one track per file"));
1386         set_popdown_strings (channel_combo, str);
1387         channel_combo.set_active_text (str.front());
1388         channel_combo.set_sensitive (false);
1389
1390         l = manage (new Label);
1391         l->set_text (_("Conversion quality:"));
1392
1393         hbox = manage (new HBox);
1394         hbox->set_border_width (12);
1395         hbox->set_spacing (6);
1396         hbox->pack_start (*l, false, false);
1397         hbox->pack_start (src_combo, false, false);
1398         vbox = manage (new VBox);
1399         vbox->pack_start (*hbox, false, false);
1400         options.pack_start (*vbox, false, false);
1401
1402         str.clear ();
1403         str.push_back (_("Best"));
1404         str.push_back (_("Good"));
1405         str.push_back (_("Quick"));
1406         str.push_back (_("Fast"));
1407         str.push_back (_("Fastest"));
1408
1409         set_popdown_strings (src_combo, str);
1410         src_combo.set_active_text (str.front());
1411         src_combo.set_sensitive (false);
1412
1413         reset_options ();
1414
1415         action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1416         channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1417
1418         copy_files_btn.set_active (true);
1419
1420         block_four.pack_start (copy_files_btn, false, false);
1421
1422         options.pack_start (block_four, false, false);
1423
1424         get_vbox()->pack_start (options, false, false);
1425
1426         /* setup disposition map */
1427
1428         disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1429         disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1430         disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1431         disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1432
1433         disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1434         disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1435         disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1436         disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1437
1438         chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1439
1440         /* set size requests for a couple of combos to allow them to display the longest text
1441            they will ever be asked to display.  This prevents them being resized when the user
1442            selects a file to import, which in turn prevents the size of the dialog from jumping
1443            around. */
1444
1445         vector<string> t;
1446         t.push_back (_("one track per file"));
1447         t.push_back (_("one track per channel"));
1448         t.push_back (_("sequence files"));
1449         t.push_back (_("all files in one region"));
1450         set_size_request_to_display_given_text (channel_combo, t, COMBO_FUDGE + 10, 15);
1451
1452         t.clear ();
1453         t.push_back (importmode2string (ImportAsTrack));
1454         t.push_back (importmode2string (ImportToTrack));
1455         t.push_back (importmode2string (ImportAsRegion));
1456         t.push_back (importmode2string (ImportAsTapeTrack));
1457         set_size_request_to_display_given_text (action_combo, t, COMBO_FUDGE + 10, 15);
1458 }
1459
1460 void
1461 SoundFileOmega::set_mode (ImportMode mode)
1462 {
1463         action_combo.set_active_text (importmode2string (mode));
1464 }
1465
1466 ImportMode
1467 SoundFileOmega::get_mode () const
1468 {
1469         return string2importmode (action_combo.get_active_text());
1470 }
1471
1472 void
1473 SoundFileOmega::on_hide ()
1474 {
1475         ArdourDialog::on_hide();
1476         if (_session) {
1477                 _session->cancel_audition();
1478         }
1479 }
1480
1481 ImportPosition
1482 SoundFileOmega::get_position() const
1483 {
1484         string str = where_combo.get_active_text();
1485
1486         if (str == _("file timestamp")) {
1487                 return ImportAtTimestamp;
1488         } else if (str == _("edit point")) {
1489                 return ImportAtEditPoint;
1490         } else if (str == _("playhead")) {
1491                 return ImportAtPlayhead;
1492         } else {
1493                 return ImportAtStart;
1494         }
1495 }
1496
1497 SrcQuality
1498 SoundFileOmega::get_src_quality() const
1499 {
1500         string str = where_combo.get_active_text();
1501
1502         if (str == _("Best")) {
1503                 return SrcBest;
1504         } else if (str == _("Good")) {
1505                 return SrcGood;
1506         } else if (str == _("Quick")) {
1507                 return SrcQuick;
1508         } else if (str == _("Fast")) {
1509                 return SrcFast;
1510         } else {
1511                 return SrcFastest;
1512         }
1513 }
1514
1515 ImportDisposition
1516 SoundFileOmega::get_channel_disposition () const
1517 {
1518         /* we use a map here because the channel combo can contain different strings
1519            depending on the state of the other combos. the map contains all possible strings
1520            and the ImportDisposition enum that corresponds to it.
1521         */
1522
1523         string str = channel_combo.get_active_text();
1524         DispositionMap::const_iterator x = disposition_map.find (str);
1525
1526         if (x == disposition_map.end()) {
1527                 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1528                 /*NOTREACHED*/
1529         }
1530
1531         return x->second;
1532 }
1533
1534 void
1535 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
1536 {
1537         selected_audio_track_cnt = selected_audio_tracks;
1538         selected_midi_track_cnt = selected_midi_tracks;
1539         reset_options ();
1540 }
1541
1542 void
1543 SoundFileOmega::file_selection_changed ()
1544 {
1545         if (resetting_ourselves) {
1546                 return;
1547         }
1548
1549         if (!reset_options ()) {
1550                 set_response_sensitive (RESPONSE_OK, false);
1551         } else {
1552                 if (chooser.get_filenames().size() > 0) {
1553                         set_response_sensitive (RESPONSE_OK, true);
1554                 } else {
1555                         set_response_sensitive (RESPONSE_OK, false);
1556                 }
1557         }
1558 }
1559