2 Copyright (C) 2005-2006 Paul Davis
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.
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.
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.
26 #include <sys/param.h>
28 #include <gtkmm/box.h>
29 #include <gtkmm/stock.h>
30 #include <glibmm/fileutils.h>
32 #include <pbd/convert.h>
33 #include <pbd/tokenizer.h>
34 #include <pbd/enumwriter.h>
36 #include <gtkmm2ext/utils.h>
38 #include <ardour/audio_library.h>
39 #include <ardour/auditioner.h>
40 #include <ardour/audioregion.h>
41 #include <ardour/audiofilesource.h>
42 #include <ardour/smf_source.h>
43 #include <ardour/smf_reader.h>
44 #include <ardour/region_factory.h>
45 #include <ardour/source_factory.h>
46 #include <ardour/session.h>
47 #include <ardour/session_directory.h>
48 #include <ardour/profile.h>
50 #include "ardour_ui.h"
52 #include "gui_thread.h"
57 #include "gain_meter.h"
61 using namespace ARDOUR;
65 using namespace Gtkmm2ext;
66 using namespace Editing;
70 ustring SoundFileBrowser::persistent_folder;
73 string2importmode (string str)
75 if (str == "as new tracks") {
77 } else if (str == "to selected tracks") {
79 } else if (str == "to region list") {
80 return ImportAsRegion;
81 } else if (str == "as new tape tracks") {
82 return ImportAsTapeTrack;
85 warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
91 importmode2string (ImportMode mode)
95 return _("as new tracks");
97 return _("to selected tracks");
99 return _("to region list");
100 case ImportAsTapeTrack:
101 return _("as new tape tracks");
104 return _("as new tracks");
107 SoundFileBox::SoundFileBox (bool persistent)
110 length_clock ("sfboxLengthClock", !persistent, "EditCursorClock", false, true, false),
111 timecode_clock ("sfboxTimecodeClock", !persistent, "EditCursorClock", false, false, false),
113 autoplay_btn (_("Auto-play"))
119 set_name (X_("SoundFileBox"));
120 set_size_request (300, -1);
122 preview_label.set_markup (_("<b>Soundfile Info</b>"));
124 border_frame.set_label_widget (preview_label);
125 border_frame.add (main_box);
127 pack_start (border_frame, true, true);
128 set_border_width (6);
130 main_box.set_border_width (6);
131 main_box.set_spacing (12);
133 length.set_text (_("Length:"));
134 timecode.set_text (_("Timestamp:"));
135 format.set_text (_("Format:"));
136 channels.set_text (_("Channels:"));
137 samplerate.set_text (_("Sample rate:"));
139 table.set_col_spacings (6);
140 table.set_homogeneous (false);
141 table.set_row_spacings (6);
143 table.attach (channels, 0, 1, 0, 1, FILL|EXPAND, (AttachOptions) 0);
144 table.attach (samplerate, 0, 1, 1, 2, FILL|EXPAND, (AttachOptions) 0);
145 table.attach (format, 0, 1, 2, 4, FILL|EXPAND, (AttachOptions) 0);
146 table.attach (length, 0, 1, 4, 5, FILL|EXPAND, (AttachOptions) 0);
147 table.attach (timecode, 0, 1, 5, 6, FILL|EXPAND, (AttachOptions) 0);
149 table.attach (channels_value, 1, 2, 0, 1, FILL, (AttachOptions) 0);
150 table.attach (samplerate_value, 1, 2, 1, 2, FILL, (AttachOptions) 0);
151 table.attach (format_text, 1, 2, 2, 4, FILL, AttachOptions (0));
152 table.attach (length_clock, 1, 2, 4, 5, FILL, (AttachOptions) 0);
153 table.attach (timecode_clock, 1, 2, 5, 6, FILL, (AttachOptions) 0);
155 length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock.mode());
156 timecode_clock.set_mode (AudioClock::SMPTE);
158 hbox = manage (new HBox);
159 hbox->pack_start (table, false, false);
160 main_box.pack_start (*hbox, false, false);
162 tags_entry.set_editable (true);
163 tags_entry.signal_focus_out_event().connect (mem_fun (*this, &SoundFileBox::tags_entry_left));
164 hbox = manage (new HBox);
165 hbox->pack_start (tags_entry, true, true);
167 vbox = manage (new VBox);
169 Label* label = manage (new Label (_("Tags:")));
170 label->set_alignment (0.0f, 0.5f);
171 vbox->set_spacing (6);
172 vbox->pack_start(*label, false, false);
173 vbox->pack_start(*hbox, true, true);
175 main_box.pack_start(*vbox, true, true);
176 main_box.pack_start(bottom_box, false, false);
178 play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
179 play_btn.set_label (_("Play (double click)"));
181 stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
182 stop_btn.set_label (_("Stop"));
184 bottom_box.set_homogeneous (false);
185 bottom_box.set_spacing (6);
186 bottom_box.pack_start(play_btn, true, true);
187 bottom_box.pack_start(stop_btn, true, true);
188 bottom_box.pack_start(autoplay_btn, false, false);
190 play_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::audition));
191 stop_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::stop_audition));
193 length.set_alignment (0.0f, 0.5f);
194 format.set_alignment (0.0f, 0.5f);
195 channels.set_alignment (0.0f, 0.5f);
196 samplerate.set_alignment (0.0f, 0.5f);
197 timecode.set_alignment (0.0f, 0.5f);
199 channels_value.set_alignment (0.0f, 0.5f);
200 samplerate_value.set_alignment (0.0f, 0.5f);
204 SoundFileBox::set_session(Session* s)
209 play_btn.set_sensitive (false);
210 stop_btn.set_sensitive (false);
214 length_clock.set_session (s);
215 timecode_clock.set_session (s);
219 SoundFileBox::setup_labels (const ustring& filename)
222 // save existing tags
230 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
232 preview_label.set_markup (_("<b>Soundfile Info</b>"));
233 format_text.set_text (_("n/a"));
234 channels_value.set_text (_("n/a"));
235 samplerate_value.set_text (_("n/a"));
236 tags_entry.get_buffer()->set_text ("");
238 length_clock.set (0);
239 timecode_clock.set (0);
241 tags_entry.set_sensitive (false);
242 play_btn.set_sensitive (false);
247 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::path_get_basename (filename)));
248 format_text.set_text (sf_info.format_name);
249 channels_value.set_text (to_string (sf_info.channels, std::dec));
251 if (_session && sf_info.samplerate != _session->frame_rate()) {
252 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
253 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
254 samplerate_value.set_name ("NewSessionSR1Label");
255 samplerate.set_name ("NewSessionSR1Label");
257 samplerate.set_text (_("Sample rate:"));
258 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
259 samplerate_value.set_name ("NewSessionSR2Label");
260 samplerate.set_name ("NewSessionSR2Label");
263 length_clock.set (sf_info.length, true);
264 timecode_clock.set (sf_info.timecode, true);
266 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
268 vector<string> tags = Library->get_tags (string ("//") + filename);
270 stringstream tag_string;
271 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
272 if (i != tags.begin()) {
277 tags_entry.get_buffer()->set_text (tag_string.str());
279 tags_entry.set_sensitive (true);
281 play_btn.set_sensitive (true);
288 SoundFileBox::autoplay() const
290 return autoplay_btn.get_active();
294 SoundFileBox::audition_oneshot()
301 SoundFileBox::audition ()
307 _session->cancel_audition();
309 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
310 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
314 boost::shared_ptr<Region> r;
316 boost::shared_ptr<AudioFileSource> afs;
317 bool old_sbp = AudioSource::get_build_peakfiles ();
319 /* don't even think of building peakfiles for these files */
321 AudioSource::set_build_peakfiles (false);
323 for (int n = 0; n < sf_info.channels; ++n) {
325 afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, *_session, path,
326 n, AudioFileSource::Flag (0), false));
328 srclist.push_back(afs);
330 } catch (failed_constructor& err) {
331 error << _("Could not access soundfile: ") << path << endmsg;
332 AudioSource::set_build_peakfiles (old_sbp);
337 AudioSource::set_build_peakfiles (old_sbp);
339 if (srclist.empty()) {
343 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
344 string rname = region_name_from_path (afs->path(), false);
345 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, 0, srclist[0]->length(), rname, 0, Region::DefaultFlags, false));
347 _session->audition_region(r);
351 SoundFileBox::stop_audition ()
354 _session->cancel_audition();
359 SoundFileBox::tags_entry_left (GdkEventFocus *ev)
366 SoundFileBox::tags_changed ()
368 string tag_string = tags_entry.get_buffer()->get_text ();
370 if (tag_string.empty()) {
376 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
377 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
385 SoundFileBox::save_tags (const vector<string>& tags)
387 Library->set_tags (string ("//") + path, tags);
388 Library->save_changes ();
391 SoundFileBrowser::SoundFileBrowser (Gtk::Window& parent, string title, ARDOUR::Session* s, bool persistent)
392 : ArdourDialog (parent, title, false, false),
393 found_list (ListStore::create(found_list_columns)),
394 chooser (FILE_CHOOSER_ACTION_OPEN),
395 found_list_view (found_list),
396 preview (persistent),
397 found_search_btn (_("Search"))
400 if (ARDOUR::Profile->get_sae()) {
401 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
402 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
411 resetting_ourselves = false;
413 hpacker.set_spacing (6);
414 hpacker.pack_start (notebook, true, true);
415 hpacker.pack_start (preview, false, false);
417 get_vbox()->pack_start (hpacker, true, true);
419 hbox = manage(new HBox);
420 hbox->pack_start (found_entry);
421 hbox->pack_start (found_search_btn);
423 vbox = manage(new VBox);
424 vbox->pack_start (*hbox, PACK_SHRINK);
425 vbox->pack_start (found_list_view);
426 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
428 chooser.set_border_width (12);
430 notebook.append_page (chooser, _("Browse Files"));
431 notebook.append_page (*vbox, _("Search Tags"));
433 notebook.set_size_request (500, -1);
435 found_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
436 found_list_view.signal_row_activated().connect (mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
438 audio_filter.add_custom (FILE_FILTER_FILENAME, mem_fun(*this, &SoundFileBrowser::on_audio_filter));
439 audio_filter.set_name (_("Audio files"));
441 midi_filter.add_custom (FILE_FILTER_FILENAME, mem_fun(*this, &SoundFileBrowser::on_midi_filter));
442 midi_filter.set_name (_("MIDI files"));
444 matchall_filter.add_pattern ("*.*");
445 matchall_filter.set_name (_("All files"));
447 chooser.add_filter (audio_filter);
448 chooser.add_filter (midi_filter);
449 chooser.add_filter (matchall_filter);
450 chooser.set_select_multiple (true);
451 chooser.signal_update_preview().connect(mem_fun(*this, &SoundFileBrowser::update_preview));
452 chooser.signal_file_activated().connect (mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
454 if (!persistent_folder.empty()) {
455 chooser.set_current_folder (persistent_folder);
458 found_list_view.get_selection()->signal_changed().connect(mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
460 found_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked));
461 found_entry.signal_activate().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked));
463 add_button (Stock::CANCEL, RESPONSE_CANCEL);
464 add_button (Stock::APPLY, RESPONSE_APPLY);
465 add_button (Stock::OK, RESPONSE_OK);
469 SoundFileBrowser::~SoundFileBrowser ()
471 persistent_folder = chooser.get_current_folder();
476 SoundFileBrowser::on_show ()
478 ArdourDialog::on_show ();
483 SoundFileBrowser::clear_selection ()
485 chooser.unselect_all ();
486 found_list_view.get_selection()->unselect_all ();
490 SoundFileBrowser::chooser_file_activated ()
496 SoundFileBrowser::found_list_view_activated (const TreeModel::Path& path, TreeViewColumn* col)
502 SoundFileBrowser::set_session (Session* s)
504 ArdourDialog::set_session (s);
505 preview.set_session (s);
509 remove_gain_meter ();
514 SoundFileBrowser::add_gain_meter ()
520 gm = new GainMeter (session->the_auditioner(), *session);
522 meter_packer.set_border_width (12);
523 meter_packer.pack_start (*gm, false, true);
524 hpacker.pack_end (meter_packer, false, false);
525 meter_packer.show_all ();
530 SoundFileBrowser::remove_gain_meter ()
533 meter_packer.remove (*gm);
534 hpacker.remove (meter_packer);
541 SoundFileBrowser::start_metering ()
543 metering_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun(*this, &SoundFileBrowser::meter));
547 SoundFileBrowser::stop_metering ()
549 metering_connection.disconnect();
553 SoundFileBrowser::meter ()
555 if (is_mapped () && session && gm) {
556 gm->update_meters ();
561 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
563 return AudioFileSource::safe_file_extension (filter_info.filename);
567 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
569 return SMFSource::safe_file_extension (filter_info.filename);
573 SoundFileBrowser::update_preview ()
575 if (preview.setup_labels (chooser.get_filename())) {
576 if (preview.autoplay()) {
577 Glib::signal_idle().connect (mem_fun (preview, &SoundFileBox::audition_oneshot));
583 SoundFileBrowser::found_list_view_selected ()
585 if (!reset_options ()) {
586 set_response_sensitive (RESPONSE_OK, false);
590 TreeView::Selection::ListHandle_Path rows = found_list_view.get_selection()->get_selected_rows ();
593 TreeIter iter = found_list->get_iter(*rows.begin());
594 file = (*iter)[found_list_columns.pathname];
595 chooser.set_filename (file);
596 set_response_sensitive (RESPONSE_OK, true);
598 set_response_sensitive (RESPONSE_OK, false);
601 preview.setup_labels (file);
606 SoundFileBrowser::found_search_clicked ()
608 string tag_string = found_entry.get_text ();
612 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
613 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
617 vector<string> results;
618 Library->search_members_and (results, tags);
621 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
622 TreeModel::iterator new_row = found_list->append();
623 TreeModel::Row row = *new_row;
624 string path = Glib::filename_from_uri (string ("file:") + *i);
625 row[found_list_columns.pathname] = path;
630 SoundFileBrowser::get_paths ()
632 vector<ustring> results;
634 int n = notebook.get_current_page ();
637 vector<ustring> filenames = chooser.get_filenames();
638 vector<ustring>::iterator i;
640 for (i = filenames.begin(); i != filenames.end(); ++i) {
642 if ((!stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
643 results.push_back (*i);
649 typedef TreeView::Selection::ListHandle_Path ListPath;
651 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
652 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
653 TreeIter iter = found_list->get_iter(*i);
654 ustring str = (*iter)[found_list_columns.pathname];
656 results.push_back (str);
664 SoundFileOmega::reset_options_noret ()
666 if (!resetting_ourselves) {
667 (void) reset_options ();
672 SoundFileOmega::reset_options ()
674 vector<ustring> paths = get_paths ();
678 channel_combo.set_sensitive (false);
679 action_combo.set_sensitive (false);
680 where_combo.set_sensitive (false);
681 copy_files_btn.set_sensitive (false);
687 channel_combo.set_sensitive (true);
688 action_combo.set_sensitive (true);
689 where_combo.set_sensitive (true);
691 /* if we get through this function successfully, this may be
692 reset at the end, once we know if we can use hard links
696 if (Config->get_only_copy_imported_files()) {
697 copy_files_btn.set_sensitive (false);
699 copy_files_btn.set_sensitive (false);
705 bool selection_includes_multichannel;
706 bool selection_can_be_embedded_with_links = check_link_status (*session, paths);
709 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
710 Glib::signal_idle().connect (mem_fun (*this, &SoundFileOmega::bad_file_message));
714 ustring existing_choice;
715 vector<string> action_strings;
717 if (selected_track_cnt > 0) {
718 if (channel_combo.get_active_text().length()) {
719 ImportDisposition id = get_channel_disposition();
722 case Editing::ImportDistinctFiles:
723 if (selected_track_cnt == paths.size()) {
724 action_strings.push_back (importmode2string (ImportToTrack));
728 case Editing::ImportDistinctChannels:
729 /* XXX it would be nice to allow channel-per-selected track
730 but its too hard we don't want to deal with all the
731 different per-file + per-track channel configurations.
736 action_strings.push_back (importmode2string (ImportToTrack));
742 action_strings.push_back (importmode2string (ImportAsTrack));
743 action_strings.push_back (importmode2string (ImportAsRegion));
744 action_strings.push_back (importmode2string (ImportAsTapeTrack));
746 resetting_ourselves = true;
748 existing_choice = action_combo.get_active_text();
750 set_popdown_strings (action_combo, action_strings);
752 /* preserve any existing choice, if possible */
755 if (existing_choice.length()) {
756 vector<string>::iterator x;
757 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
758 if (*x == existing_choice) {
759 action_combo.set_active_text (existing_choice);
763 if (x == action_strings.end()) {
764 action_combo.set_active_text (action_strings.front());
767 action_combo.set_active_text (action_strings.front());
770 resetting_ourselves = false;
772 if ((mode = get_mode()) == ImportAsRegion) {
773 where_combo.set_sensitive (false);
775 where_combo.set_sensitive (true);
778 vector<string> channel_strings;
780 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
781 channel_strings.push_back (_("one track per file"));
783 if (selection_includes_multichannel) {
784 channel_strings.push_back (_("one track per channel"));
787 if (paths.size() > 1) {
788 /* tape tracks are a single region per track, so we cannot
789 sequence multiple files.
791 if (mode != ImportAsTapeTrack) {
792 channel_strings.push_back (_("sequence files"));
795 channel_strings.push_back (_("all files in one region"));
801 channel_strings.push_back (_("one region per file"));
803 if (selection_includes_multichannel) {
804 channel_strings.push_back (_("one region per channel"));
807 if (paths.size() > 1) {
809 channel_strings.push_back (_("all files in one region"));
814 existing_choice = channel_combo.get_active_text();
816 set_popdown_strings (channel_combo, channel_strings);
818 /* preserve any existing choice, if possible */
820 if (existing_choice.length()) {
821 vector<string>::iterator x;
822 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
823 if (*x == existing_choice) {
824 channel_combo.set_active_text (existing_choice);
828 if (x == channel_strings.end()) {
829 channel_combo.set_active_text (channel_strings.front());
832 channel_combo.set_active_text (channel_strings.front());
836 src_combo.set_sensitive (true);
838 src_combo.set_sensitive (false);
841 if (Config->get_only_copy_imported_files()) {
843 if (selection_can_be_embedded_with_links) {
844 copy_files_btn.set_sensitive (true);
846 copy_files_btn.set_sensitive (false);
851 copy_files_btn.set_sensitive (true);
859 SoundFileOmega::bad_file_message()
861 MessageDialog msg (*this,
862 _("One or more of the selected files\ncannot be used by Ardour"),
867 resetting_ourselves = true;
868 chooser.unselect_uri (chooser.get_preview_uri());
869 resetting_ourselves = false;
875 SoundFileOmega::check_info (const vector<ustring>& paths, bool& same_size, bool& src_needed, bool& multichannel)
884 multichannel = false;
886 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
888 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
890 if (info.channels > 1) {
897 if (sz != info.length) {
902 if ((nframes_t) info.samplerate != session->frame_rate()) {
906 } else if (SMFSource::safe_file_extension (*i)) {
908 SMFReader reader(*i);
909 if (reader.num_tracks() > 1) {
910 multichannel = true; // "channel" == track here...
913 /* XXX we need err = true handling here in case
914 we can't check the file
927 SoundFileOmega::check_link_status (const Session& s, const vector<ustring>& paths)
929 sys::path path = s.session_directory().sound_path() / "linktest";
930 string tmpdir = path.to_string();
933 if (mkdir (tmpdir.c_str(), 0744)) {
934 if (errno != EEXIST) {
939 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
941 char tmpc[MAXPATHLEN+1];
943 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
947 if (link ((*i).c_str(), tmpc)) {
957 rmdir (tmpdir.c_str());
961 SoundFileChooser::SoundFileChooser (Gtk::Window& parent, string title, ARDOUR::Session* s)
962 : SoundFileBrowser (parent, title, s, false)
964 chooser.set_select_multiple (false);
965 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
969 SoundFileChooser::on_hide ()
971 ArdourDialog::on_hide();
975 session->cancel_audition();
980 SoundFileChooser::get_filename ()
982 vector<ustring> paths;
984 paths = get_paths ();
990 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
994 return paths.front();
997 SoundFileOmega::SoundFileOmega (Gtk::Window& parent, string title, ARDOUR::Session* s, int selected_tracks, bool persistent,
998 Editing::ImportMode mode_hint)
999 : SoundFileBrowser (parent, title, s, persistent),
1000 copy_files_btn ( _("Copy files to session")),
1001 selected_track_cnt (selected_tracks)
1007 set_size_request (-1, 450);
1009 block_two.set_border_width (12);
1010 block_three.set_border_width (12);
1011 block_four.set_border_width (12);
1013 options.set_spacing (12);
1016 str.push_back (_("use file timestamp"));
1017 str.push_back (_("at edit point"));
1018 str.push_back (_("at playhead"));
1019 str.push_back (_("at session start"));
1020 set_popdown_strings (where_combo, str);
1021 where_combo.set_active_text (str.front());
1023 Label* l = manage (new Label);
1024 l->set_text (_("Add files:"));
1026 hbox = manage (new HBox);
1027 hbox->set_border_width (12);
1028 hbox->set_spacing (6);
1029 hbox->pack_start (*l, false, false);
1030 hbox->pack_start (action_combo, false, false);
1031 vbox = manage (new VBox);
1032 vbox->pack_start (*hbox, false, false);
1033 options.pack_start (*vbox, false, false);
1035 /* dummy entry for action combo so that it doesn't look odd if we
1036 come up with no tracks selected.
1040 str.push_back (importmode2string (mode_hint));
1041 set_popdown_strings (action_combo, str);
1042 action_combo.set_active_text (str.front());
1043 action_combo.set_sensitive (false);
1045 l = manage (new Label);
1046 l->set_text (_("Insert:"));
1048 hbox = manage (new HBox);
1049 hbox->set_border_width (12);
1050 hbox->set_spacing (6);
1051 hbox->pack_start (*l, false, false);
1052 hbox->pack_start (where_combo, false, false);
1053 vbox = manage (new VBox);
1054 vbox->pack_start (*hbox, false, false);
1055 options.pack_start (*vbox, false, false);
1058 l = manage (new Label);
1059 l->set_text (_("Mapping:"));
1061 hbox = manage (new HBox);
1062 hbox->set_border_width (12);
1063 hbox->set_spacing (6);
1064 hbox->pack_start (*l, false, false);
1065 hbox->pack_start (channel_combo, false, false);
1066 vbox = manage (new VBox);
1067 vbox->pack_start (*hbox, false, false);
1068 options.pack_start (*vbox, false, false);
1071 str.push_back (_("one track per file"));
1072 set_popdown_strings (channel_combo, str);
1073 channel_combo.set_active_text (str.front());
1074 channel_combo.set_sensitive (false);
1076 l = manage (new Label);
1077 l->set_text (_("Conversion Quality:"));
1079 hbox = manage (new HBox);
1080 hbox->set_border_width (12);
1081 hbox->set_spacing (6);
1082 hbox->pack_start (*l, false, false);
1083 hbox->pack_start (src_combo, false, false);
1084 vbox = manage (new VBox);
1085 vbox->pack_start (*hbox, false, false);
1086 options.pack_start (*vbox, false, false);
1089 str.push_back (_("Best"));
1090 str.push_back (_("Good"));
1091 str.push_back (_("Quick"));
1092 str.push_back (_("Fast"));
1093 str.push_back (_("Fastest"));
1095 set_popdown_strings (src_combo, str);
1096 src_combo.set_active_text (str.front());
1097 src_combo.set_sensitive (false);
1101 action_combo.signal_changed().connect (mem_fun (*this, &SoundFileOmega::reset_options_noret));
1103 copy_files_btn.set_active (true);
1105 block_four.pack_start (copy_files_btn, false, false);
1107 options.pack_start (block_four, false, false);
1109 get_vbox()->pack_start (options, false, false);
1111 /* setup disposition map */
1113 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1114 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1115 disposition_map.insert (pair<ustring,ImportDisposition>(_("merge files"), ImportMergeFiles));
1116 disposition_map.insert (pair<ustring,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1118 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1119 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1120 disposition_map.insert (pair<ustring,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1122 chooser.signal_selection_changed().connect (mem_fun (*this, &SoundFileOmega::file_selection_changed));
1126 SoundFileOmega::set_mode (ImportMode mode)
1128 action_combo.set_active_text (importmode2string (mode));
1132 SoundFileOmega::get_mode () const
1134 return string2importmode (action_combo.get_active_text());
1138 SoundFileOmega::on_hide ()
1140 ArdourDialog::on_hide();
1142 session->cancel_audition();
1147 SoundFileOmega::get_position() const
1149 ustring str = where_combo.get_active_text();
1151 if (str == _("use file timestamp")) {
1152 return ImportAtTimestamp;
1153 } else if (str == _("at edit point")) {
1154 return ImportAtEditPoint;
1155 } else if (str == _("at playhead")) {
1156 return ImportAtPlayhead;
1158 return ImportAtStart;
1163 SoundFileOmega::get_src_quality() const
1165 ustring str = where_combo.get_active_text();
1167 if (str == _("Best")) {
1169 } else if (str == _("Good")) {
1171 } else if (str == _("Quick")) {
1173 } else if (str == _("Fast")) {
1181 SoundFileOmega::get_channel_disposition () const
1183 /* we use a map here because the channel combo can contain different strings
1184 depending on the state of the other combos. the map contains all possible strings
1185 and the ImportDisposition enum that corresponds to it.
1188 ustring str = channel_combo.get_active_text();
1189 DispositionMap::const_iterator x = disposition_map.find (str);
1191 if (x == disposition_map.end()) {
1192 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1200 SoundFileOmega::reset (int selected_tracks)
1202 selected_track_cnt = selected_tracks;
1207 SoundFileOmega::file_selection_changed ()
1209 if (resetting_ourselves) {
1213 if (!reset_options ()) {
1214 set_response_sensitive (RESPONSE_OK, false);
1216 if (chooser.get_filenames().size() > 0) {
1217 set_response_sensitive (RESPONSE_OK, true);
1219 set_response_sensitive (RESPONSE_OK, false);