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