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