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"
35 #include "pbd/pthread_utils.h"
36 #include "pbd/xml++.h"
38 #include <gtkmm2ext/utils.h>
40 #include "evoral/SMF.hpp"
42 #include "ardour/audio_library.h"
43 #include "ardour/auditioner.h"
44 #include "ardour/audioregion.h"
45 #include "ardour/audiofilesource.h"
46 #include "ardour/smf_source.h"
47 #include "ardour/region_factory.h"
48 #include "ardour/source_factory.h"
49 #include "ardour/session.h"
50 #include "ardour/session_directory.h"
51 #include "ardour/profile.h"
53 #include "ardour_ui.h"
55 #include "gui_thread.h"
60 #include "gain_meter.h"
63 #include "sfdb_freesound_mootcher.h"
68 using namespace ARDOUR;
72 using namespace Gtkmm2ext;
73 using namespace Editing;
77 ustring SoundFileBrowser::persistent_folder;
80 string2importmode (string str)
82 if (str == _("as new tracks")) {
84 } else if (str == _("to selected tracks")) {
86 } else if (str == _("to region list")) {
87 return ImportAsRegion;
88 } else if (str == _("as new tape tracks")) {
89 return ImportAsTapeTrack;
92 warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
98 importmode2string (ImportMode mode)
102 return _("as new tracks");
104 return _("to selected tracks");
106 return _("to region list");
107 case ImportAsTapeTrack:
108 return _("as new tape tracks");
111 return _("as new tracks");
114 SoundFileBox::SoundFileBox (bool persistent)
117 length_clock ("sfboxLengthClock", !persistent, "EditCursorClock", false, true, false),
118 timecode_clock ("sfboxTimecodeClock", !persistent, "EditCursorClock", false, false, false),
120 autoplay_btn (_("Auto-play"))
123 set_name (X_("SoundFileBox"));
124 set_size_request (300, -1);
126 preview_label.set_markup (_("<b>Sound File Information</b>"));
128 border_frame.set_label_widget (preview_label);
129 border_frame.add (main_box);
131 pack_start (border_frame, true, true);
132 set_border_width (6);
134 main_box.set_border_width (6);
136 length.set_text (_("Length:"));
137 length.set_alignment (1, 0.5);
138 timecode.set_text (_("Timestamp:"));
139 timecode.set_alignment (1, 0.5);
140 format.set_text (_("Format:"));
141 format.set_alignment (1, 0.5);
142 channels.set_text (_("Channels:"));
143 channels.set_alignment (1, 0.5);
144 samplerate.set_text (_("Sample rate:"));
145 samplerate.set_alignment (1, 0.5);
147 format_text.set_max_width_chars (8);
148 format_text.set_ellipsize (Pango::ELLIPSIZE_END);
149 format_text.set_alignment (0, 1);
151 table.set_col_spacings (6);
152 table.set_homogeneous (false);
153 table.set_row_spacings (6);
155 table.attach (channels, 0, 1, 0, 1, FILL, FILL);
156 table.attach (samplerate, 0, 1, 1, 2, FILL, FILL);
157 table.attach (format, 0, 1, 2, 4, FILL, FILL);
158 table.attach (length, 0, 1, 4, 5, FILL, FILL);
159 table.attach (timecode, 0, 1, 5, 6, FILL, FILL);
161 table.attach (channels_value, 1, 2, 0, 1, FILL, FILL);
162 table.attach (samplerate_value, 1, 2, 1, 2, FILL, FILL);
163 table.attach (format_text, 1, 2, 2, 4, FILL, FILL);
164 table.attach (length_clock, 1, 2, 4, 5, FILL, FILL);
165 table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL);
167 length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock.mode());
168 timecode_clock.set_mode (AudioClock::SMPTE);
170 main_box.pack_start (table, false, false);
172 tags_entry.set_editable (true);
173 tags_entry.signal_focus_out_event().connect (mem_fun (*this, &SoundFileBox::tags_entry_left));
175 Label* label = manage (new Label (_("Tags:")));
176 label->set_alignment (0.0f, 0.5f);
177 main_box.pack_start (*label, false, false);
178 main_box.pack_start (tags_entry, true, true);
180 main_box.pack_start (bottom_box, false, false);
182 play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
183 play_btn.set_label (_("Play"));
185 stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
186 stop_btn.set_label (_("Stop"));
188 bottom_box.set_homogeneous (false);
189 bottom_box.set_spacing (6);
190 bottom_box.pack_start(play_btn, true, true);
191 bottom_box.pack_start(stop_btn, true, true);
192 bottom_box.pack_start(autoplay_btn, false, false);
194 play_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::audition));
195 stop_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::stop_audition));
197 channels_value.set_alignment (0.0f, 0.5f);
198 samplerate_value.set_alignment (0.0f, 0.5f);
202 SoundFileBox::set_session(Session* s)
207 play_btn.set_sensitive (false);
208 stop_btn.set_sensitive (false);
212 length_clock.set_session (s);
213 timecode_clock.set_session (s);
217 SoundFileBox::setup_labels (const ustring& filename)
220 // save existing tags
228 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
230 preview_label.set_markup (_("<b>Sound File Information</b>"));
231 format_text.set_text ("");
232 channels_value.set_text ("");
233 samplerate_value.set_text ("");
234 tags_entry.get_buffer()->set_text ("");
236 length_clock.set (0);
237 timecode_clock.set (0);
239 tags_entry.set_sensitive (false);
240 play_btn.set_sensitive (false);
245 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::path_get_basename (filename)));
246 std::string n = sf_info.format_name;
247 if (n.substr (0, 8) == X_("Format: ")) {
250 format_text.set_text (n);
251 channels_value.set_text (to_string (sf_info.channels, std::dec));
253 if (_session && sf_info.samplerate != _session->frame_rate()) {
254 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
255 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
256 samplerate_value.set_name ("NewSessionSR1Label");
257 samplerate.set_name ("NewSessionSR1Label");
259 samplerate.set_text (_("Sample rate:"));
260 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
261 samplerate_value.set_name ("NewSessionSR2Label");
262 samplerate.set_name ("NewSessionSR2Label");
265 double src_coef = (double) _session->nominal_frame_rate() / sf_info.samplerate;
267 length_clock.set (sf_info.length * src_coef + 0.5, true);
268 timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
270 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
272 vector<string> tags = Library->get_tags (string ("//") + filename);
274 stringstream tag_string;
275 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
276 if (i != tags.begin()) {
281 tags_entry.get_buffer()->set_text (tag_string.str());
283 tags_entry.set_sensitive (true);
285 play_btn.set_sensitive (true);
292 SoundFileBox::autoplay() const
294 return autoplay_btn.get_active();
298 SoundFileBox::audition_oneshot()
305 SoundFileBox::audition ()
311 _session->cancel_audition();
313 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
314 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
318 boost::shared_ptr<Region> r;
320 boost::shared_ptr<AudioFileSource> afs;
321 bool old_sbp = AudioSource::get_build_peakfiles ();
323 /* don't even think of building peakfiles for these files */
325 AudioSource::set_build_peakfiles (false);
327 for (int n = 0; n < sf_info.channels; ++n) {
329 afs = boost::dynamic_pointer_cast<AudioFileSource> (
330 SourceFactory::createReadable (DataType::AUDIO, *_session,
331 path, false, n, Source::Flag (0), false));
333 srclist.push_back(afs);
335 } catch (failed_constructor& err) {
336 error << _("Could not access soundfile: ") << path << endmsg;
337 AudioSource::set_build_peakfiles (old_sbp);
342 AudioSource::set_build_peakfiles (old_sbp);
344 if (srclist.empty()) {
348 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
349 string rname = region_name_from_path (afs->path(), false);
350 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, 0,
351 srclist[0]->length(srclist[0]->timeline_position()),
352 rname, 0, Region::DefaultFlags, false));
354 _session->audition_region(r);
358 SoundFileBox::stop_audition ()
361 _session->cancel_audition();
366 SoundFileBox::tags_entry_left (GdkEventFocus *ev)
373 SoundFileBox::tags_changed ()
375 string tag_string = tags_entry.get_buffer()->get_text ();
377 if (tag_string.empty()) {
383 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
384 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
392 SoundFileBox::save_tags (const vector<string>& tags)
394 Library->set_tags (string ("//") + path, tags);
395 Library->save_changes ();
398 SoundFileBrowser::SoundFileBrowser (Gtk::Window& parent, string title, ARDOUR::Session* s, bool persistent)
399 : ArdourDialog (parent, title, false, false),
400 found_list (ListStore::create(found_list_columns)),
401 freesound_list (ListStore::create(freesound_list_columns)),
402 chooser (FILE_CHOOSER_ACTION_OPEN),
403 preview (persistent),
404 found_search_btn (_("Search")),
405 found_list_view (found_list),
406 freesound_search_btn (_("Start Downloading")),
407 freesound_list_view (freesound_list)
409 resetting_ourselves = false;
412 resetting_ourselves = false;
415 if (ARDOUR::Profile->get_sae()) {
416 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
417 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
421 //add the file chooser
423 chooser.set_border_width (12);
425 audio_filter.add_custom (FILE_FILTER_FILENAME, mem_fun(*this, &SoundFileBrowser::on_audio_filter));
426 audio_filter.set_name (_("Audio files"));
428 midi_filter.add_custom (FILE_FILTER_FILENAME, mem_fun(*this, &SoundFileBrowser::on_midi_filter));
429 midi_filter.set_name (_("MIDI files"));
431 matchall_filter.add_pattern ("*.*");
432 matchall_filter.set_name (_("All files"));
434 chooser.add_filter (audio_filter);
435 chooser.add_filter (midi_filter);
436 chooser.add_filter (matchall_filter);
437 chooser.set_select_multiple (true);
438 chooser.signal_update_preview().connect(mem_fun(*this, &SoundFileBrowser::update_preview));
439 chooser.signal_file_activated().connect (mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
441 if (!persistent_folder.empty()) {
442 chooser.set_current_folder (persistent_folder);
444 notebook.append_page (chooser, _("Browse Files"));
447 hpacker.set_spacing (6);
448 hpacker.pack_start (notebook, true, true);
449 hpacker.pack_start (preview, false, false);
451 get_vbox()->pack_start (hpacker, true, true);
459 hbox = manage(new HBox);
460 hbox->pack_start (found_entry);
461 hbox->pack_start (found_search_btn);
463 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
464 scroll->add(found_list_view);
465 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
467 vbox = manage(new VBox);
468 vbox->pack_start (*hbox, PACK_SHRINK);
469 vbox->pack_start (*scroll);
471 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
473 found_list_view.get_selection()->signal_changed().connect(mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
475 found_list_view.signal_row_activated().connect (mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
477 found_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked));
478 found_entry.signal_activate().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked));
480 notebook.append_page (*vbox, _("Search Tags"));
483 //add freesound search
490 passbox = manage(new HBox);
491 passbox->set_border_width (12);
492 passbox->set_spacing (6);
494 label = manage (new Label);
495 label->set_text (_("User:"));
496 passbox->pack_start (*label, false, false);
497 passbox->pack_start (freesound_name_entry);
498 label = manage (new Label);
499 label->set_text (_("Password:"));
500 passbox->pack_start (*label, false, false);
501 passbox->pack_start (freesound_pass_entry);
502 label = manage (new Label);
503 label->set_text (_("Tags:"));
504 passbox->pack_start (*label, false, false);
505 passbox->pack_start (freesound_entry, false, false);
506 passbox->pack_start (freesound_search_btn, false, false);
508 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
509 scroll->add(freesound_list_view);
510 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
512 vbox = manage(new VBox);
513 vbox->pack_start (*passbox, PACK_SHRINK);
514 vbox->pack_start(*scroll);
516 //vbox->pack_start (freesound_list_view);
518 freesound_list_view.append_column(_("Paths"), freesound_list_columns.pathname);
519 freesound_list_view.get_selection()->signal_changed().connect(mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
521 //freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
522 freesound_list_view.signal_row_activated().connect (mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
523 freesound_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
524 freesound_entry.signal_activate().connect(mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
525 notebook.append_page (*vbox, _("Search Freesound"));
530 notebook.set_size_request (500, -1);
534 add_button (Stock::CANCEL, RESPONSE_CANCEL);
535 add_button (Stock::APPLY, RESPONSE_APPLY);
536 add_button (Stock::OK, RESPONSE_OK);
540 SoundFileBrowser::~SoundFileBrowser ()
542 persistent_folder = chooser.get_current_folder();
547 SoundFileBrowser::on_show ()
549 ArdourDialog::on_show ();
554 SoundFileBrowser::clear_selection ()
556 chooser.unselect_all ();
557 found_list_view.get_selection()->unselect_all ();
561 SoundFileBrowser::chooser_file_activated ()
567 SoundFileBrowser::found_list_view_activated (const TreeModel::Path& path, TreeViewColumn* col)
573 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path& path, TreeViewColumn* col)
579 SoundFileBrowser::set_session (Session* s)
581 ArdourDialog::set_session (s);
582 preview.set_session (s);
586 remove_gain_meter ();
591 SoundFileBrowser::add_gain_meter ()
595 gm = new GainMeter (*session);
596 gm->set_io (session->the_auditioner());
598 meter_packer.set_border_width (12);
599 meter_packer.pack_start (*gm, false, true);
600 hpacker.pack_end (meter_packer, false, false);
601 meter_packer.show_all ();
606 SoundFileBrowser::remove_gain_meter ()
609 meter_packer.remove (*gm);
610 hpacker.remove (meter_packer);
617 SoundFileBrowser::start_metering ()
619 metering_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun(*this, &SoundFileBrowser::meter));
623 SoundFileBrowser::stop_metering ()
625 metering_connection.disconnect();
629 SoundFileBrowser::meter ()
631 if (is_mapped () && session && gm) {
632 gm->update_meters ();
637 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
639 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
643 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
645 return SMFSource::safe_midi_file_extension (filter_info.filename);
649 SoundFileBrowser::update_preview ()
651 if (preview.setup_labels (chooser.get_filename())) {
652 if (preview.autoplay()) {
653 Glib::signal_idle().connect (mem_fun (preview, &SoundFileBox::audition_oneshot));
659 SoundFileBrowser::found_list_view_selected ()
661 if (!reset_options ()) {
662 set_response_sensitive (RESPONSE_OK, false);
666 TreeView::Selection::ListHandle_Path rows = found_list_view.get_selection()->get_selected_rows ();
669 TreeIter iter = found_list->get_iter(*rows.begin());
670 file = (*iter)[found_list_columns.pathname];
671 chooser.set_filename (file);
672 set_response_sensitive (RESPONSE_OK, true);
674 set_response_sensitive (RESPONSE_OK, false);
677 preview.setup_labels (file);
682 SoundFileBrowser::freesound_list_view_selected ()
684 if (!reset_options ()) {
685 set_response_sensitive (RESPONSE_OK, false);
689 TreeView::Selection::ListHandle_Path rows = freesound_list_view.get_selection()->get_selected_rows ();
692 TreeIter iter = freesound_list->get_iter(*rows.begin());
693 file = (*iter)[freesound_list_columns.pathname];
694 chooser.set_filename (file);
695 set_response_sensitive (RESPONSE_OK, true);
697 set_response_sensitive (RESPONSE_OK, false);
700 preview.setup_labels (file);
705 SoundFileBrowser::found_search_clicked ()
707 string tag_string = found_entry.get_text ();
711 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
712 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
716 vector<string> results;
717 Library->search_members_and (results, tags);
720 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
721 TreeModel::iterator new_row = found_list->append();
722 TreeModel::Row row = *new_row;
723 string path = Glib::filename_from_uri (string ("file:") + *i);
724 row[found_list_columns.pathname] = path;
729 freesound_search_thread_entry (void* arg)
731 PBD::notify_gui_about_thread_creation (pthread_self(), X_("Freesound Search"));
733 static_cast<SoundFileBrowser*>(arg)->freesound_search_thread ();
738 bool searching = false;
739 bool canceling = false;
742 SoundFileBrowser::freesound_search_clicked ()
744 if (canceling) //already canceling, button does nothing
748 freesound_search_btn.set_label(_("Cancelling.."));
752 freesound_search_btn.set_label(_("Cancel"));
753 pthread_t freesound_thr;
754 pthread_create_and_store ("freesound_search", &freesound_thr, 0, freesound_search_thread_entry, this);
759 SoundFileBrowser::freesound_search_thread()
762 freesound_list->clear();
765 path = Glib::get_home_dir();
766 path += "/Freesound/";
767 Mootcher theMootcher(path.c_str());
769 string name_string = freesound_name_entry.get_text ();
770 string pass_string = freesound_pass_entry.get_text ();
771 string search_string = freesound_entry.get_text ();
773 if ( theMootcher.doLogin( name_string, pass_string ) ) {
775 string theString = theMootcher.searchText(search_string);
778 doc.read_buffer( theString );
779 XMLNode *root = doc.root();
781 if (root==NULL) return;
783 if ( strcmp(root->name().c_str(), "freesound") == 0) {
786 XMLNodeList children = root->children();
787 XMLNodeConstIterator niter;
788 for (niter = children.begin(); niter != children.end() && !canceling; ++niter) {
790 if( strcmp( node->name().c_str(), "sample") == 0 ){
791 XMLProperty *prop=node->property ("id");
792 string filename = theMootcher.getFile( prop->value().c_str() );
793 if ( filename != "" ) {
794 TreeModel::iterator new_row = freesound_list->append();
795 TreeModel::Row row = *new_row;
796 string path = Glib::filename_from_uri (string ("file:") + filename);
797 row[freesound_list_columns.pathname] = path;
806 freesound_search_btn.set_label(_("Start Downloading"));
811 SoundFileBrowser::get_paths ()
813 vector<ustring> results;
815 int n = notebook.get_current_page ();
818 vector<ustring> filenames = chooser.get_filenames();
819 vector<ustring>::iterator i;
821 for (i = filenames.begin(); i != filenames.end(); ++i) {
823 if ((!stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
824 results.push_back (*i);
830 typedef TreeView::Selection::ListHandle_Path ListPath;
832 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
833 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
834 TreeIter iter = found_list->get_iter(*i);
835 ustring str = (*iter)[found_list_columns.pathname];
837 results.push_back (str);
841 typedef TreeView::Selection::ListHandle_Path ListPath;
843 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
844 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
845 TreeIter iter = freesound_list->get_iter(*i);
846 ustring str = (*iter)[freesound_list_columns.pathname];
848 results.push_back (str);
856 SoundFileOmega::reset_options_noret ()
858 if (!resetting_ourselves) {
859 (void) reset_options ();
864 SoundFileOmega::reset_options ()
866 vector<ustring> paths = get_paths ();
870 channel_combo.set_sensitive (false);
871 action_combo.set_sensitive (false);
872 where_combo.set_sensitive (false);
873 copy_files_btn.set_sensitive (false);
879 channel_combo.set_sensitive (true);
880 action_combo.set_sensitive (true);
881 where_combo.set_sensitive (true);
883 /* if we get through this function successfully, this may be
884 reset at the end, once we know if we can use hard links
888 if (Config->get_only_copy_imported_files()) {
889 copy_files_btn.set_sensitive (false);
891 copy_files_btn.set_sensitive (false);
897 bool selection_includes_multichannel;
898 bool selection_can_be_embedded_with_links = check_link_status (*session, paths);
901 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
902 Glib::signal_idle().connect (mem_fun (*this, &SoundFileOmega::bad_file_message));
906 ustring existing_choice;
907 vector<string> action_strings;
909 if (selected_track_cnt > 0) {
910 if (channel_combo.get_active_text().length()) {
911 ImportDisposition id = get_channel_disposition();
914 case Editing::ImportDistinctFiles:
915 if (selected_track_cnt == paths.size()) {
916 action_strings.push_back (importmode2string (ImportToTrack));
920 case Editing::ImportDistinctChannels:
921 /* XXX it would be nice to allow channel-per-selected track
922 but its too hard we don't want to deal with all the
923 different per-file + per-track channel configurations.
928 action_strings.push_back (importmode2string (ImportToTrack));
934 action_strings.push_back (importmode2string (ImportAsTrack));
935 action_strings.push_back (importmode2string (ImportAsRegion));
936 action_strings.push_back (importmode2string (ImportAsTapeTrack));
938 resetting_ourselves = true;
940 existing_choice = action_combo.get_active_text();
942 set_popdown_strings (action_combo, action_strings);
944 /* preserve any existing choice, if possible */
947 if (existing_choice.length()) {
948 vector<string>::iterator x;
949 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
950 if (*x == existing_choice) {
951 action_combo.set_active_text (existing_choice);
955 if (x == action_strings.end()) {
956 action_combo.set_active_text (action_strings.front());
959 action_combo.set_active_text (action_strings.front());
962 resetting_ourselves = false;
964 if ((mode = get_mode()) == ImportAsRegion) {
965 where_combo.set_sensitive (false);
967 where_combo.set_sensitive (true);
970 vector<string> channel_strings;
972 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
973 channel_strings.push_back (_("one track per file"));
975 if (selection_includes_multichannel) {
976 channel_strings.push_back (_("one track per channel"));
979 if (paths.size() > 1) {
980 /* tape tracks are a single region per track, so we cannot
981 sequence multiple files.
983 if (mode != ImportAsTapeTrack) {
984 channel_strings.push_back (_("sequence files"));
987 channel_strings.push_back (_("all files in one region"));
993 channel_strings.push_back (_("one region per file"));
995 if (selection_includes_multichannel) {
996 channel_strings.push_back (_("one region per channel"));
999 if (paths.size() > 1) {
1001 channel_strings.push_back (_("all files in one region"));
1006 existing_choice = channel_combo.get_active_text();
1008 set_popdown_strings (channel_combo, channel_strings);
1010 /* preserve any existing choice, if possible */
1012 if (existing_choice.length()) {
1013 vector<string>::iterator x;
1014 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1015 if (*x == existing_choice) {
1016 channel_combo.set_active_text (existing_choice);
1020 if (x == channel_strings.end()) {
1021 channel_combo.set_active_text (channel_strings.front());
1024 channel_combo.set_active_text (channel_strings.front());
1028 src_combo.set_sensitive (true);
1030 src_combo.set_sensitive (false);
1033 if (Config->get_only_copy_imported_files()) {
1035 if (selection_can_be_embedded_with_links) {
1036 copy_files_btn.set_sensitive (true);
1038 copy_files_btn.set_sensitive (false);
1043 copy_files_btn.set_sensitive (true);
1051 SoundFileOmega::bad_file_message()
1053 MessageDialog msg (*this,
1054 _("One or more of the selected files\ncannot be used by Ardour"),
1059 resetting_ourselves = true;
1060 chooser.unselect_uri (chooser.get_preview_uri());
1061 resetting_ourselves = false;
1067 SoundFileOmega::check_info (const vector<ustring>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1076 multichannel = false;
1078 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1080 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1081 if (info.channels > 1) {
1082 multichannel = true;
1087 if (sz != info.length) {
1092 if ((nframes_t) info.samplerate != session->frame_rate()) {
1096 } else if (SMFSource::safe_midi_file_extension (*i)) {
1100 if (reader.num_tracks() > 1) {
1101 multichannel = true; // "channel" == track here...
1104 /* XXX we need err = true handling here in case
1105 we can't check the file
1118 SoundFileOmega::check_link_status (const Session& s, const vector<ustring>& paths)
1120 sys::path path = s.session_directory().sound_path() / "linktest";
1121 string tmpdir = path.to_string();
1124 if (mkdir (tmpdir.c_str(), 0744)) {
1125 if (errno != EEXIST) {
1130 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1132 char tmpc[MAXPATHLEN+1];
1134 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1138 if (link ((*i).c_str(), tmpc)) {
1148 rmdir (tmpdir.c_str());
1152 SoundFileChooser::SoundFileChooser (Gtk::Window& parent, string title, ARDOUR::Session* s)
1153 : SoundFileBrowser (parent, title, s, false)
1155 chooser.set_select_multiple (false);
1156 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1157 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1161 SoundFileChooser::on_hide ()
1163 ArdourDialog::on_hide();
1167 session->cancel_audition();
1172 SoundFileChooser::get_filename ()
1174 vector<ustring> paths;
1176 paths = get_paths ();
1178 if (paths.empty()) {
1182 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1186 return paths.front();
1189 SoundFileOmega::SoundFileOmega (Gtk::Window& parent, string title, ARDOUR::Session* s, int selected_tracks, bool persistent,
1190 Editing::ImportMode mode_hint)
1191 : SoundFileBrowser (parent, title, s, persistent),
1192 copy_files_btn ( _("Copy files to session")),
1193 selected_track_cnt (selected_tracks)
1199 set_size_request (-1, 450);
1201 block_two.set_border_width (12);
1202 block_three.set_border_width (12);
1203 block_four.set_border_width (12);
1205 options.set_spacing (12);
1208 str.push_back (_("use file timestamp"));
1209 str.push_back (_("at edit point"));
1210 str.push_back (_("at playhead"));
1211 str.push_back (_("at session start"));
1212 set_popdown_strings (where_combo, str);
1213 where_combo.set_active_text (str.front());
1215 Label* l = manage (new Label);
1216 l->set_text (_("Add files:"));
1218 hbox = manage (new HBox);
1219 hbox->set_border_width (12);
1220 hbox->set_spacing (6);
1221 hbox->pack_start (*l, false, false);
1222 hbox->pack_start (action_combo, false, false);
1223 vbox = manage (new VBox);
1224 vbox->pack_start (*hbox, false, false);
1225 options.pack_start (*vbox, false, false);
1227 /* dummy entry for action combo so that it doesn't look odd if we
1228 come up with no tracks selected.
1232 str.push_back (importmode2string (mode_hint));
1233 set_popdown_strings (action_combo, str);
1234 action_combo.set_active_text (str.front());
1235 action_combo.set_sensitive (false);
1237 l = manage (new Label);
1238 l->set_text (_("Insert:"));
1240 hbox = manage (new HBox);
1241 hbox->set_border_width (12);
1242 hbox->set_spacing (6);
1243 hbox->pack_start (*l, false, false);
1244 hbox->pack_start (where_combo, false, false);
1245 vbox = manage (new VBox);
1246 vbox->pack_start (*hbox, false, false);
1247 options.pack_start (*vbox, false, false);
1250 l = manage (new Label);
1251 l->set_text (_("Mapping:"));
1253 hbox = manage (new HBox);
1254 hbox->set_border_width (12);
1255 hbox->set_spacing (6);
1256 hbox->pack_start (*l, false, false);
1257 hbox->pack_start (channel_combo, false, false);
1258 vbox = manage (new VBox);
1259 vbox->pack_start (*hbox, false, false);
1260 options.pack_start (*vbox, false, false);
1263 str.push_back (_("one track per file"));
1264 set_popdown_strings (channel_combo, str);
1265 channel_combo.set_active_text (str.front());
1266 channel_combo.set_sensitive (false);
1268 l = manage (new Label);
1269 l->set_text (_("Conversion quality:"));
1271 hbox = manage (new HBox);
1272 hbox->set_border_width (12);
1273 hbox->set_spacing (6);
1274 hbox->pack_start (*l, false, false);
1275 hbox->pack_start (src_combo, false, false);
1276 vbox = manage (new VBox);
1277 vbox->pack_start (*hbox, false, false);
1278 options.pack_start (*vbox, false, false);
1281 str.push_back (_("Best"));
1282 str.push_back (_("Good"));
1283 str.push_back (_("Quick"));
1284 str.push_back (_("Fast"));
1285 str.push_back (_("Fastest"));
1287 set_popdown_strings (src_combo, str);
1288 src_combo.set_active_text (str.front());
1289 src_combo.set_sensitive (false);
1293 action_combo.signal_changed().connect (mem_fun (*this, &SoundFileOmega::reset_options_noret));
1295 copy_files_btn.set_active (true);
1297 block_four.pack_start (copy_files_btn, false, false);
1299 options.pack_start (block_four, false, false);
1301 get_vbox()->pack_start (options, false, false);
1303 /* setup disposition map */
1305 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1306 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1307 disposition_map.insert (pair<ustring,ImportDisposition>(_("merge files"), ImportMergeFiles));
1308 disposition_map.insert (pair<ustring,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1310 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1311 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1312 disposition_map.insert (pair<ustring,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1314 chooser.signal_selection_changed().connect (mem_fun (*this, &SoundFileOmega::file_selection_changed));
1318 SoundFileOmega::set_mode (ImportMode mode)
1320 action_combo.set_active_text (importmode2string (mode));
1324 SoundFileOmega::get_mode () const
1326 return string2importmode (action_combo.get_active_text());
1330 SoundFileOmega::on_hide ()
1332 ArdourDialog::on_hide();
1334 session->cancel_audition();
1339 SoundFileOmega::get_position() const
1341 ustring str = where_combo.get_active_text();
1343 if (str == _("use file timestamp")) {
1344 return ImportAtTimestamp;
1345 } else if (str == _("at edit point")) {
1346 return ImportAtEditPoint;
1347 } else if (str == _("at playhead")) {
1348 return ImportAtPlayhead;
1350 return ImportAtStart;
1355 SoundFileOmega::get_src_quality() const
1357 ustring str = where_combo.get_active_text();
1359 if (str == _("Best")) {
1361 } else if (str == _("Good")) {
1363 } else if (str == _("Quick")) {
1365 } else if (str == _("Fast")) {
1373 SoundFileOmega::get_channel_disposition () const
1375 /* we use a map here because the channel combo can contain different strings
1376 depending on the state of the other combos. the map contains all possible strings
1377 and the ImportDisposition enum that corresponds to it.
1380 ustring str = channel_combo.get_active_text();
1381 DispositionMap::const_iterator x = disposition_map.find (str);
1383 if (x == disposition_map.end()) {
1384 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1392 SoundFileOmega::reset (int selected_tracks)
1394 selected_track_cnt = selected_tracks;
1399 SoundFileOmega::file_selection_changed ()
1401 if (resetting_ourselves) {
1405 if (!reset_options ()) {
1406 set_response_sensitive (RESPONSE_OK, false);
1408 if (chooser.get_filenames().size() > 0) {
1409 set_response_sensitive (RESPONSE_OK, true);
1411 set_response_sensitive (RESPONSE_OK, false);