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>
35 #include <gtkmm2ext/utils.h>
37 #include <ardour/audio_library.h>
38 #include <ardour/audioregion.h>
39 #include <ardour/audiofilesource.h>
40 #include <ardour/region_factory.h>
41 #include <ardour/source_factory.h>
42 #include <ardour/profile.h>
44 #include "ardour_ui.h"
46 #include "gui_thread.h"
54 using namespace ARDOUR;
58 using namespace Gtkmm2ext;
59 using namespace Editing;
63 ustring SoundFileBrowser::persistent_folder;
65 SoundFileBox::SoundFileBox ()
70 length_clock ("sfboxLengthClock", true, "EditCursorClock", false, true, false),
71 timecode_clock ("sfboxTimecodeClock", true, "EditCursorClock", false, false, false),
74 stop_btn (Stock::MEDIA_STOP)
76 set_name (X_("SoundFileBox"));
78 preview_label.set_markup (_("<b>Soundfile Info</b>"));
80 border_frame.set_label_widget (preview_label);
81 border_frame.add (main_box);
83 pack_start (border_frame, true, true);
86 main_box.set_border_width (6);
88 length.set_text (_("Length:"));
89 timecode.set_text (_("Timestamp:"));
90 format.set_text (_("Format:"));
91 channels.set_text (_("Channels:"));
92 samplerate.set_text (_("Sample rate:"));
94 format_text.set_editable (false);
96 table.set_col_spacings (6);
97 table.set_homogeneous (false);
99 table.attach (channels, 0, 1, 0, 1, FILL|EXPAND, (AttachOptions) 0);
100 table.attach (samplerate, 0, 1, 1, 2, FILL|EXPAND, (AttachOptions) 0);
101 table.attach (format, 0, 1, 2, 4, FILL|EXPAND, (AttachOptions) 0);
102 table.attach (length, 0, 1, 4, 5, FILL|EXPAND, (AttachOptions) 0);
103 table.attach (timecode, 0, 1, 5, 6, FILL|EXPAND, (AttachOptions) 0);
105 table.attach (channels_value, 1, 2, 0, 1, FILL, (AttachOptions) 0);
106 table.attach (samplerate_value, 1, 2, 1, 2, FILL, (AttachOptions) 0);
107 table.attach (format_text, 1, 2, 2, 4, FILL, AttachOptions (0));
108 table.attach (length_clock, 1, 2, 4, 5, FILL, (AttachOptions) 0);
109 table.attach (timecode_clock, 1, 2, 5, 6, FILL, (AttachOptions) 0);
111 length_clock.set_mode (AudioClock::MinSec);
112 timecode_clock.set_mode (AudioClock::SMPTE);
114 tags_entry.set_editable (true);
115 tags_entry.signal_focus_out_event().connect (mem_fun (*this, &SoundFileBox::tags_entry_left));
116 HBox* hbox = manage (new HBox);
117 hbox->pack_start (tags_entry, true, true);
119 main_box.pack_start (table, false, false);
121 VBox* vbox = manage (new VBox);
123 Label* label = manage (new Label (_("Tags:")));
124 label->set_alignment (0.0f, 0.5f);
125 vbox->set_spacing (6);
126 vbox->pack_start(*label, false, false);
127 vbox->pack_start(*hbox, true, true);
129 main_box.pack_start(*vbox, true, true);
130 main_box.pack_start(bottom_box, false, false);
132 play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
133 play_btn.set_label (_("Play (double click)"));
135 bottom_box.set_homogeneous(true);
136 bottom_box.pack_start(play_btn);
137 bottom_box.pack_start(stop_btn);
139 play_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::audition));
140 stop_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::stop_btn_clicked));
142 length.set_alignment (0.0f, 0.5f);
143 format.set_alignment (0.0f, 0.5f);
144 channels.set_alignment (0.0f, 0.5f);
145 samplerate.set_alignment (0.0f, 0.5f);
146 timecode.set_alignment (0.0f, 0.5f);
148 channels_value.set_alignment (0.0f, 0.5f);
149 samplerate_value.set_alignment (0.0f, 0.5f);
151 stop_btn.set_no_show_all (true);
156 SoundFileBox::set_session(Session* s)
158 audition_connection.disconnect ();
163 play_btn.set_sensitive(false);
165 audition_connection = _session->AuditionActive.connect(mem_fun (*this, &SoundFileBox::audition_status_changed));
168 length_clock.set_session (s);
169 timecode_clock.set_session (s);
173 SoundFileBox::setup_labels (const ustring& filename)
179 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
181 preview_label.set_markup (_("<b>Soundfile Info</b>"));
182 format_text.get_buffer()->set_text (_("n/a"));
183 channels_value.set_text (_("n/a"));
184 samplerate_value.set_text (_("n/a"));
185 tags_entry.get_buffer()->set_text ("");
187 length_clock.set (0);
188 timecode_clock.set (0);
190 tags_entry.set_sensitive (false);
191 play_btn.set_sensitive (false);
196 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::path_get_basename (filename)));
197 format_text.get_buffer()->set_text (sf_info.format_name);
198 channels_value.set_text (to_string (sf_info.channels, std::dec));
199 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
201 length_clock.set (sf_info.length, true);
202 timecode_clock.set (sf_info.timecode, true);
204 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
206 vector<string> tags = Library->get_tags (string ("//") + filename);
208 stringstream tag_string;
209 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
210 if (i != tags.begin()) {
215 tags_entry.get_buffer()->set_text (tag_string.str());
217 tags_entry.set_sensitive (true);
219 play_btn.set_sensitive (true);
226 SoundFileBox::audition ()
232 _session->cancel_audition();
234 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
235 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
239 typedef std::map<ustring, boost::shared_ptr<AudioRegion> > RegionCache;
240 static RegionCache region_cache;
241 RegionCache::iterator the_region;
243 if ((the_region = region_cache.find (path)) == region_cache.end()) {
246 boost::shared_ptr<AudioFileSource> afs;
248 for (int n = 0; n < sf_info.channels; ++n) {
250 afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (*_session, path, n, AudioFileSource::Flag (0)));
251 srclist.push_back(afs);
253 } catch (failed_constructor& err) {
254 error << _("Could not access soundfile: ") << path << endmsg;
259 if (srclist.empty()) {
265 _session->region_name (rname, Glib::path_get_basename(srclist[0]->name()), false);
267 pair<string,boost::shared_ptr<AudioRegion> > newpair;
268 pair<RegionCache::iterator,bool> res;
270 newpair.first = path;
271 newpair.second = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, 0, srclist[0]->length(), rname, 0, Region::DefaultFlags, false));
273 res = region_cache.insert (newpair);
274 the_region = res.first;
280 boost::shared_ptr<Region> r = boost::static_pointer_cast<Region> (the_region->second);
282 _session->audition_region(r);
286 SoundFileBox::stop_btn_clicked ()
289 _session->cancel_audition();
296 SoundFileBox::tags_entry_left (GdkEventFocus *ev)
303 SoundFileBox::tags_changed ()
305 string tag_string = tags_entry.get_buffer()->get_text ();
307 if (tag_string.empty()) {
313 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
314 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
318 Library->set_tags (string ("//") + path, tags);
319 Library->save_changes ();
323 SoundFileBox::audition_status_changed (bool active)
325 ENSURE_GUI_THREAD(bind (mem_fun (*this, &SoundFileBox::audition_status_changed), active));
332 SoundFileBrowser::SoundFileBrowser (Gtk::Window& parent, string title, ARDOUR::Session* s, int selected_tracks)
333 : ArdourDialog (parent, title, false, false),
334 found_list (ListStore::create(found_list_columns)),
335 chooser (FILE_CHOOSER_ACTION_OPEN),
336 found_list_view (found_list),
337 import (rgroup2, _("Copy to Ardour-native files")),
338 embed (rgroup2, _("Use file without copying")),
339 found_search_btn (_("Search")),
340 selected_track_cnt (selected_tracks)
346 set_size_request (-1, 450);
349 resetting_ourselves = false;
351 hpacker = manage (new HBox);
352 hpacker->set_spacing (6);
353 hpacker->pack_start (notebook, true, true);
354 hpacker->pack_start (preview, false, false);
356 block_two.set_border_width (12);
357 block_three.set_border_width (12);
358 block_four.set_border_width (12);
360 options.set_spacing (12);
362 vector<string> where_strings;
364 where_strings.push_back (_("use file timestamp"));
365 where_strings.push_back (_("at edit cursor"));
366 where_strings.push_back (_("at playhead"));
367 where_strings.push_back (_("at session start"));
368 set_popdown_strings (where_combo, where_strings);
369 where_combo.set_active_text (where_strings.front());
371 Label* l = manage (new Label);
372 l->set_text (_("Add files:"));
374 hbox = manage (new HBox);
375 hbox->set_border_width (12);
376 hbox->set_spacing (6);
377 hbox->pack_start (*l, false, false);
378 hbox->pack_start (action_combo, false, false);
379 vbox = manage (new VBox);
380 vbox->pack_start (*hbox, false, false);
381 options.pack_start (*vbox, false, false);
383 l = manage (new Label);
384 l->set_text (_("Insert:"));
386 hbox = manage (new HBox);
387 hbox->set_border_width (12);
388 hbox->set_spacing (6);
389 hbox->pack_start (*l, false, false);
390 hbox->pack_start (where_combo, false, false);
391 vbox = manage (new VBox);
392 vbox->pack_start (*hbox, false, false);
393 options.pack_start (*vbox, false, false);
396 l = manage (new Label);
397 l->set_text (_("Mapping:"));
399 hbox = manage (new HBox);
400 hbox->set_border_width (12);
401 hbox->set_spacing (6);
402 hbox->pack_start (*l, false, false);
403 hbox->pack_start (channel_combo, false, false);
404 vbox = manage (new VBox);
405 vbox->pack_start (*hbox, false, false);
406 options.pack_start (*vbox, false, false);
410 action_combo.signal_changed().connect (mem_fun (*this, &SoundFileBrowser::reset_options_noret));
412 block_four.pack_start (import, false, false);
413 block_four.pack_start (embed, false, false);
415 options.pack_start (block_four, false, false);
417 get_vbox()->pack_start (*hpacker, true, true);
418 get_vbox()->pack_start (options, false, false);
420 hbox = manage(new HBox);
421 hbox->pack_start (found_entry);
422 hbox->pack_start (found_search_btn);
424 vbox = manage(new VBox);
425 vbox->pack_start (*hbox, PACK_SHRINK);
426 vbox->pack_start (found_list_view);
427 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
429 chooser.set_border_width (12);
431 notebook.append_page (chooser, _("Browse Files"));
432 notebook.append_page (*vbox, _("Search Tags"));
434 found_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
435 found_list_view.signal_row_activated().connect (mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
437 custom_filter.add_custom (FILE_FILTER_FILENAME, mem_fun(*this, &SoundFileBrowser::on_custom));
438 custom_filter.set_name (_("Audio files"));
440 matchall_filter.add_pattern ("*.*");
441 matchall_filter.set_name (_("All files"));
443 chooser.add_filter (custom_filter);
444 chooser.add_filter (matchall_filter);
445 chooser.set_select_multiple (true);
446 chooser.signal_update_preview().connect(mem_fun(*this, &SoundFileBrowser::update_preview));
447 chooser.signal_selection_changed().connect (mem_fun (*this, &SoundFileBrowser::file_selection_changed));
448 chooser.signal_file_activated().connect (mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
450 if (!persistent_folder.empty()) {
451 chooser.set_current_folder (persistent_folder);
454 found_list_view.get_selection()->signal_changed().connect(mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
456 found_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked));
457 found_entry.signal_activate().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked));
459 add_button (Stock::CANCEL, RESPONSE_CANCEL);
460 add_button (Stock::OK, RESPONSE_OK);
462 /* setup disposition map */
464 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
465 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
466 disposition_map.insert (pair<ustring,ImportDisposition>(_("merge files"), ImportMergeFiles));
467 disposition_map.insert (pair<ustring,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
469 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
470 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
471 disposition_map.insert (pair<ustring,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
474 SoundFileBrowser::~SoundFileBrowser ()
476 persistent_folder = chooser.get_current_folder();
480 SoundFileBrowser::reset (int selected_tracks)
482 selected_track_cnt = selected_tracks;
487 SoundFileBrowser::file_selection_changed ()
489 if (resetting_ourselves) {
493 if (!reset_options ()) {
494 set_response_sensitive (RESPONSE_OK, false);
496 if (chooser.get_filenames().size() > 0) {
497 set_response_sensitive (RESPONSE_OK, true);
499 set_response_sensitive (RESPONSE_OK, false);
505 SoundFileBrowser::chooser_file_activated ()
511 SoundFileBrowser::found_list_view_activated (const TreeModel::Path& path, TreeViewColumn* col)
517 SoundFileBrowser::set_session (Session* s)
519 ArdourDialog::set_session (s);
520 preview.set_session (s);
525 SoundFileBrowser::on_custom (const FileFilter::Info& filter_info)
527 return AudioFileSource::safe_file_extension (filter_info.filename);
531 SoundFileBrowser::update_preview ()
533 preview.setup_labels (chooser.get_filename());
537 SoundFileBrowser::found_list_view_selected ()
539 if (!reset_options ()) {
540 set_response_sensitive (RESPONSE_OK, false);
544 TreeView::Selection::ListHandle_Path rows = found_list_view.get_selection()->get_selected_rows ();
547 TreeIter iter = found_list->get_iter(*rows.begin());
548 file = (*iter)[found_list_columns.pathname];
549 chooser.set_filename (file);
550 set_response_sensitive (RESPONSE_OK, true);
552 set_response_sensitive (RESPONSE_OK, false);
555 preview.setup_labels (file);
560 SoundFileBrowser::found_search_clicked ()
562 string tag_string = found_entry.get_text ();
566 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
567 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
571 vector<string> results;
572 Library->search_members_and (results, tags);
575 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
576 TreeModel::iterator new_row = found_list->append();
577 TreeModel::Row row = *new_row;
578 string path = Glib::filename_from_uri (string ("file:") + *i);
579 row[found_list_columns.pathname] = path;
584 SoundFileBrowser::get_paths ()
586 vector<ustring> results;
588 int n = notebook.get_current_page ();
591 vector<ustring> filenames = chooser.get_filenames();
592 vector<ustring>::iterator i;
593 for (i = filenames.begin(); i != filenames.end(); ++i) {
595 if ((!stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
596 results.push_back (*i);
603 typedef TreeView::Selection::ListHandle_Path ListPath;
605 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
606 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
607 TreeIter iter = found_list->get_iter(*i);
608 ustring str = (*iter)[found_list_columns.pathname];
610 results.push_back (str);
617 SoundFileBrowser::reset_options_noret ()
619 if (!resetting_ourselves) {
620 (void) reset_options ();
625 SoundFileBrowser::reset_options ()
627 vector<ustring> paths = get_paths ();
631 channel_combo.set_sensitive (false);
632 action_combo.set_sensitive (false);
633 where_combo.set_sensitive (false);
634 import.set_sensitive (false);
635 embed.set_sensitive (false);
641 channel_combo.set_sensitive (true);
642 action_combo.set_sensitive (true);
643 where_combo.set_sensitive (true);
644 import.set_sensitive (true);
645 embed.set_sensitive (true);
651 bool selection_includes_multichannel = check_multichannel_status (paths, same_size, err);
652 bool selection_can_be_embedded_with_links = check_link_status (*session, paths);
656 Glib::signal_idle().connect (mem_fun (*this, &SoundFileBrowser::bad_file_message));
660 ustring existing_choice;
661 vector<string> action_strings;
663 if (selected_track_cnt > 0) {
664 if (channel_combo.get_active_text().length()) {
665 ImportDisposition id = get_channel_disposition();
668 case Editing::ImportDistinctFiles:
669 if (selected_track_cnt == paths.size()) {
670 action_strings.push_back (_("to selected tracks"));
674 case Editing::ImportDistinctChannels:
675 /* XXX it would be nice to allow channel-per-selected track
676 but its too hard we don't want to deal with all the
677 different per-file + per-track channel configurations.
682 action_strings.push_back (_("to selected tracks"));
688 action_strings.push_back (_("as new tracks"));
689 action_strings.push_back (_("to the region list"));
690 action_strings.push_back (_("as new tape tracks"));
692 existing_choice = action_combo.get_active_text();
694 set_popdown_strings (action_combo, action_strings);
696 /* preserve any existing choice, if possible */
698 resetting_ourselves = true;
700 if (existing_choice.length()) {
701 vector<string>::iterator x;
702 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
703 if (*x == existing_choice) {
704 action_combo.set_active_text (existing_choice);
708 if (x == action_strings.end()) {
709 action_combo.set_active_text (action_strings.front());
712 action_combo.set_active_text (action_strings.front());
715 resetting_ourselves = false;
717 if ((mode = get_mode()) == ImportAsRegion) {
718 where_combo.set_sensitive (false);
720 where_combo.set_sensitive (true);
723 vector<string> channel_strings;
725 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
726 channel_strings.push_back (_("one track per file"));
728 if (selection_includes_multichannel) {
729 channel_strings.push_back (_("one track per channel"));
732 if (paths.size() > 1) {
733 /* tape tracks are a single region per track, so we cannot
734 sequence multiple files.
736 if (mode != ImportAsTapeTrack) {
737 channel_strings.push_back (_("sequence files"));
740 channel_strings.push_back (_("all files in one region"));
746 channel_strings.push_back (_("one region per file"));
748 if (selection_includes_multichannel) {
749 channel_strings.push_back (_("one region per channel"));
752 if (paths.size() > 1) {
754 channel_strings.push_back (_("all files in one region"));
759 existing_choice = channel_combo.get_active_text();
761 set_popdown_strings (channel_combo, channel_strings);
763 /* preserve any existing choice, if possible */
765 if (existing_choice.length()) {
766 vector<string>::iterator x;
767 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
768 if (*x == existing_choice) {
769 channel_combo.set_active_text (existing_choice);
773 if (x == channel_strings.end()) {
774 channel_combo.set_active_text (channel_strings.front());
777 channel_combo.set_active_text (channel_strings.front());
780 if (Profile->get_sae()) {
781 if (selection_can_be_embedded_with_links) {
782 embed.set_sensitive (true);
784 embed.set_sensitive (false);
787 embed.set_sensitive (true);
795 SoundFileBrowser::bad_file_message()
797 MessageDialog msg (*this,
798 _("One or more of the selected files\ncannot be used by Ardour"),
803 resetting_ourselves = true;
804 chooser.unselect_uri (chooser.get_preview_uri());
805 resetting_ourselves = false;
809 SoundFileBrowser::check_multichannel_status (const vector<ustring>& paths, bool& same_size, bool& err)
814 bool some_mult = false;
819 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
821 info.format = 0; // libsndfile says to clear this before sf_open().
823 if ((sf = sf_open ((char*) (*i).c_str(), SFM_READ, &info)) != 0) {
826 if (info.channels > 1) {
833 if (sz != info.frames) {
846 SoundFileBrowser::check_link_status (const Session& s, const vector<ustring>& paths)
848 string tmpdir = s.sound_dir();
851 tmpdir += "/linktest";
853 if (mkdir (tmpdir.c_str(), 0744)) {
854 if (errno != EEXIST) {
859 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
861 char tmpc[MAXPATHLEN+1];
863 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
867 if (link ((*i).c_str(), tmpc)) {
877 rmdir (tmpdir.c_str());
881 SoundFileChooser::SoundFileChooser (Gtk::Window& parent, string title, ARDOUR::Session* s)
882 : SoundFileBrowser (parent, title, s, 0)
884 set_default_size (700, 300);
886 // get_vbox()->pack_start (browser, false, false);
888 // add_button (Stock::OPEN, RESPONSE_OK);
889 // add_button (Stock::CANCEL, RESPONSE_CANCEL);
891 // chooser.set_select_multiple (false);
892 // browser.found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
898 SoundFileChooser::get_filename ()
900 vector<ustring> paths;
902 paths = browser.get_paths ();
908 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
912 return paths.front();
916 SoundFileBrowser::get_mode () const
918 ustring str = action_combo.get_active_text();
920 if (str == _("as new tracks")) {
921 return ImportAsTrack;
922 } else if (str == _("to the region list")) {
923 return ImportAsRegion;
924 } else if (str == _("to selected tracks")) {
925 return ImportToTrack;
927 return ImportAsTapeTrack;
932 SoundFileBrowser::get_position() const
934 ustring str = where_combo.get_active_text();
936 if (str == _("use file timestamp")) {
937 return ImportAtTimestamp;
938 } else if (str == _("at edit cursor")) {
939 return ImportAtEditCursor;
940 } else if (str == _("at playhead")) {
941 return ImportAtPlayhead;
943 return ImportAtStart;
948 SoundFileBrowser::get_channel_disposition () const
950 /* we use a map here because the channel combo can contain different strings
951 depending on the state of the other combos. the map contains all possible strings
952 and the ImportDisposition enum that corresponds to it.
955 ustring str = channel_combo.get_active_text();
956 DispositionMap::const_iterator x = disposition_map.find (str);
958 if (x == disposition_map.end()) {
959 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;