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 <ardour/audio_library.h>
41 #include <ardour/auditioner.h>
42 #include <ardour/audioregion.h>
43 #include <ardour/audiofilesource.h>
44 #include <ardour/smf_source.h>
45 #include <ardour/smf_reader.h>
46 #include <ardour/region_factory.h>
47 #include <ardour/source_factory.h>
48 #include <ardour/session.h>
49 #include <ardour/session_directory.h>
50 #include <ardour/profile.h>
52 #include "ardour_ui.h"
54 #include "gui_thread.h"
59 #include "gain_meter.h"
62 #include "sfdb_freesound_mootcher.h"
67 using namespace ARDOUR;
71 using namespace Gtkmm2ext;
72 using namespace Editing;
76 ustring SoundFileBrowser::persistent_folder;
79 string2importmode (string str)
81 if (str == _("as new tracks")) {
83 } else if (str == _("to selected tracks")) {
85 } else if (str == _("to region list")) {
86 return ImportAsRegion;
87 } else if (str == _("as new tape tracks")) {
88 return ImportAsTapeTrack;
91 warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
97 importmode2string (ImportMode mode)
101 return _("as new tracks");
103 return _("to selected tracks");
105 return _("to region list");
106 case ImportAsTapeTrack:
107 return _("as new tape tracks");
110 return _("as new tracks");
113 SoundFileBox::SoundFileBox (bool persistent)
116 length_clock ("sfboxLengthClock", !persistent, "EditCursorClock", false, true, false),
117 timecode_clock ("sfboxTimecodeClock", !persistent, "EditCursorClock", false, false, false),
119 autoplay_btn (_("Auto-play"))
125 set_name (X_("SoundFileBox"));
126 set_size_request (300, -1);
128 preview_label.set_markup (_("<b>Soundfile Info</b>"));
130 border_frame.set_label_widget (preview_label);
131 border_frame.add (main_box);
133 pack_start (border_frame, true, true);
134 set_border_width (6);
136 main_box.set_border_width (6);
137 main_box.set_spacing (12);
139 length.set_text (_("Length:"));
140 timecode.set_text (_("Timestamp:"));
141 format.set_text (_("Format:"));
142 channels.set_text (_("Channels:"));
143 samplerate.set_text (_("Sample rate:"));
145 table.set_col_spacings (6);
146 table.set_homogeneous (false);
147 table.set_row_spacings (6);
149 table.attach (channels, 0, 1, 0, 1, FILL|EXPAND, (AttachOptions) 0);
150 table.attach (samplerate, 0, 1, 1, 2, FILL|EXPAND, (AttachOptions) 0);
151 table.attach (format, 0, 1, 2, 4, FILL|EXPAND, (AttachOptions) 0);
152 table.attach (length, 0, 1, 4, 5, FILL|EXPAND, (AttachOptions) 0);
153 table.attach (timecode, 0, 1, 5, 6, FILL|EXPAND, (AttachOptions) 0);
155 table.attach (channels_value, 1, 2, 0, 1, FILL, (AttachOptions) 0);
156 table.attach (samplerate_value, 1, 2, 1, 2, FILL, (AttachOptions) 0);
157 table.attach (format_text, 1, 2, 2, 4, FILL, AttachOptions (0));
158 table.attach (length_clock, 1, 2, 4, 5, FILL, (AttachOptions) 0);
159 table.attach (timecode_clock, 1, 2, 5, 6, FILL, (AttachOptions) 0);
161 length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock.mode());
162 timecode_clock.set_mode (AudioClock::SMPTE);
164 hbox = manage (new HBox);
165 hbox->pack_start (table, false, false);
166 main_box.pack_start (*hbox, false, false);
168 tags_entry.set_editable (true);
169 tags_entry.signal_focus_out_event().connect (mem_fun (*this, &SoundFileBox::tags_entry_left));
170 hbox = manage (new HBox);
171 hbox->pack_start (tags_entry, true, true);
173 vbox = manage (new VBox);
175 Label* label = manage (new Label (_("Tags:")));
176 label->set_alignment (0.0f, 0.5f);
177 vbox->set_spacing (6);
178 vbox->pack_start(*label, false, false);
179 vbox->pack_start(*hbox, true, true);
181 main_box.pack_start(*vbox, true, true);
182 main_box.pack_start(bottom_box, false, false);
184 play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
185 play_btn.set_label (_("Play (double click)"));
187 stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
188 stop_btn.set_label (_("Stop"));
190 bottom_box.set_homogeneous (false);
191 bottom_box.set_spacing (6);
192 bottom_box.pack_start(play_btn, true, true);
193 bottom_box.pack_start(stop_btn, true, true);
194 bottom_box.pack_start(autoplay_btn, false, false);
196 play_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::audition));
197 stop_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::stop_audition));
199 length.set_alignment (0.0f, 0.5f);
200 format.set_alignment (0.0f, 0.5f);
201 channels.set_alignment (0.0f, 0.5f);
202 samplerate.set_alignment (0.0f, 0.5f);
203 timecode.set_alignment (0.0f, 0.5f);
205 channels_value.set_alignment (0.0f, 0.5f);
206 samplerate_value.set_alignment (0.0f, 0.5f);
210 SoundFileBox::set_session(Session* s)
215 play_btn.set_sensitive (false);
216 stop_btn.set_sensitive (false);
220 length_clock.set_session (s);
221 timecode_clock.set_session (s);
225 SoundFileBox::setup_labels (const ustring& filename)
228 // save existing tags
236 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
238 preview_label.set_markup (_("<b>Soundfile Info</b>"));
239 format_text.set_text (_("n/a"));
240 channels_value.set_text (_("n/a"));
241 samplerate_value.set_text (_("n/a"));
242 tags_entry.get_buffer()->set_text ("");
244 length_clock.set (0);
245 timecode_clock.set (0);
247 tags_entry.set_sensitive (false);
248 play_btn.set_sensitive (false);
253 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::path_get_basename (filename)));
254 format_text.set_text (sf_info.format_name);
255 channels_value.set_text (to_string (sf_info.channels, std::dec));
257 if (_session && sf_info.samplerate != _session->frame_rate()) {
258 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
259 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
260 samplerate_value.set_name ("NewSessionSR1Label");
261 samplerate.set_name ("NewSessionSR1Label");
263 samplerate.set_text (_("Sample rate:"));
264 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
265 samplerate_value.set_name ("NewSessionSR2Label");
266 samplerate.set_name ("NewSessionSR2Label");
269 length_clock.set (sf_info.length, true);
270 timecode_clock.set (sf_info.timecode, true);
272 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
274 vector<string> tags = Library->get_tags (string ("//") + filename);
276 stringstream tag_string;
277 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
278 if (i != tags.begin()) {
283 tags_entry.get_buffer()->set_text (tag_string.str());
285 tags_entry.set_sensitive (true);
287 play_btn.set_sensitive (true);
294 SoundFileBox::autoplay() const
296 return autoplay_btn.get_active();
300 SoundFileBox::audition_oneshot()
307 SoundFileBox::audition ()
313 _session->cancel_audition();
315 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
316 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
320 boost::shared_ptr<Region> r;
322 boost::shared_ptr<AudioFileSource> afs;
323 bool old_sbp = AudioSource::get_build_peakfiles ();
325 /* don't even think of building peakfiles for these files */
327 AudioSource::set_build_peakfiles (false);
329 for (int n = 0; n < sf_info.channels; ++n) {
331 afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, *_session, path,
332 n, AudioFileSource::Flag (0), false));
334 srclist.push_back(afs);
336 } catch (failed_constructor& err) {
337 error << _("Could not access soundfile: ") << path << endmsg;
338 AudioSource::set_build_peakfiles (old_sbp);
343 AudioSource::set_build_peakfiles (old_sbp);
345 if (srclist.empty()) {
349 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
350 string rname = region_name_from_path (afs->path(), false);
351 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, 0, srclist[0]->length(), rname, 0, Region::DefaultFlags, false));
353 _session->audition_region(r);
357 SoundFileBox::stop_audition ()
360 _session->cancel_audition();
365 SoundFileBox::tags_entry_left (GdkEventFocus *ev)
372 SoundFileBox::tags_changed ()
374 string tag_string = tags_entry.get_buffer()->get_text ();
376 if (tag_string.empty()) {
382 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
383 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
391 SoundFileBox::save_tags (const vector<string>& tags)
393 Library->set_tags (string ("//") + path, tags);
394 Library->save_changes ();
397 SoundFileBrowser::SoundFileBrowser (Gtk::Window& parent, string title, ARDOUR::Session* s, bool persistent)
398 : ArdourDialog (parent, title, false, false),
399 found_list (ListStore::create(found_list_columns)),
400 freesound_list (ListStore::create(freesound_list_columns)),
401 chooser (FILE_CHOOSER_ACTION_OPEN),
402 preview (persistent),
403 found_search_btn (_("Search")),
404 found_list_view (found_list),
405 freesound_search_btn (_("Start Downloading")),
406 freesound_list_view (freesound_list)
408 resetting_ourselves = false;
411 resetting_ourselves = false;
414 if (ARDOUR::Profile->get_sae()) {
415 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
416 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
420 //add the file chooser
422 chooser.set_border_width (12);
424 audio_filter.add_custom (FILE_FILTER_FILENAME, mem_fun(*this, &SoundFileBrowser::on_audio_filter));
425 audio_filter.set_name (_("Audio files"));
427 midi_filter.add_custom (FILE_FILTER_FILENAME, mem_fun(*this, &SoundFileBrowser::on_midi_filter));
428 midi_filter.set_name (_("MIDI files"));
430 matchall_filter.add_pattern ("*.*");
431 matchall_filter.set_name (_("All files"));
433 chooser.add_filter (audio_filter);
434 chooser.add_filter (midi_filter);
435 chooser.add_filter (matchall_filter);
436 chooser.set_select_multiple (true);
437 chooser.signal_update_preview().connect(mem_fun(*this, &SoundFileBrowser::update_preview));
438 chooser.signal_file_activated().connect (mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
440 if (!persistent_folder.empty()) {
441 chooser.set_current_folder (persistent_folder);
443 notebook.append_page (chooser, _("Browse Files"));
452 hbox = manage(new HBox);
453 hbox->pack_start (found_entry);
454 hbox->pack_start (found_search_btn);
456 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
457 scroll->add(found_list_view);
458 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
460 vbox = manage(new VBox);
461 vbox->pack_start (*hbox, PACK_SHRINK);
462 vbox->pack_start (*scroll);
464 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
466 found_list_view.get_selection()->signal_changed().connect(mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
468 found_list_view.signal_row_activated().connect (mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
470 found_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked));
471 found_entry.signal_activate().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked));
473 notebook.append_page (*vbox, _("Search Tags"));
476 //add freesound search
483 passbox = manage(new HBox);
484 passbox->set_border_width (12);
485 passbox->set_spacing (6);
487 label = manage (new Label);
488 label->set_text (_("User:"));
489 passbox->pack_start (*label, false, false);
490 passbox->pack_start (freesound_name_entry);
491 label = manage (new Label);
492 label->set_text (_("Password:"));
493 passbox->pack_start (*label, false, false);
494 passbox->pack_start (freesound_pass_entry);
495 label = manage (new Label);
496 label->set_text (_("Tags:"));
497 passbox->pack_start (*label, false, false);
498 passbox->pack_start (freesound_entry, false, false);
499 passbox->pack_start (freesound_search_btn, false, false);
501 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
502 scroll->add(freesound_list_view);
503 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
505 vbox = manage(new VBox);
506 vbox->pack_start (*passbox, PACK_SHRINK);
507 vbox->pack_start(*scroll);
509 //vbox->pack_start (freesound_list_view);
511 freesound_list_view.append_column(_("Paths"), freesound_list_columns.pathname);
512 freesound_list_view.get_selection()->signal_changed().connect(mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
514 //freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
515 freesound_list_view.signal_row_activated().connect (mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
516 freesound_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
517 freesound_entry.signal_activate().connect(mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
518 notebook.append_page (*vbox, _("Search Freesound"));
523 notebook.set_size_request (500, -1);
527 add_button (Stock::CANCEL, RESPONSE_CANCEL);
528 add_button (Stock::APPLY, RESPONSE_APPLY);
529 add_button (Stock::OK, RESPONSE_OK);
533 SoundFileBrowser::~SoundFileBrowser ()
535 persistent_folder = chooser.get_current_folder();
540 SoundFileBrowser::on_show ()
542 ArdourDialog::on_show ();
547 SoundFileBrowser::clear_selection ()
549 chooser.unselect_all ();
550 found_list_view.get_selection()->unselect_all ();
554 SoundFileBrowser::chooser_file_activated ()
560 SoundFileBrowser::found_list_view_activated (const TreeModel::Path& path, TreeViewColumn* col)
566 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path& path, TreeViewColumn* col)
572 SoundFileBrowser::set_session (Session* s)
574 ArdourDialog::set_session (s);
575 preview.set_session (s);
579 remove_gain_meter ();
584 SoundFileBrowser::add_gain_meter ()
590 gm = new GainMeter (session->the_auditioner(), *session);
592 meter_packer.set_border_width (12);
593 meter_packer.pack_start (*gm, false, true);
594 hpacker.pack_end (meter_packer, false, false);
595 meter_packer.show_all ();
600 SoundFileBrowser::remove_gain_meter ()
603 meter_packer.remove (*gm);
604 hpacker.remove (meter_packer);
611 SoundFileBrowser::start_metering ()
613 metering_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun(*this, &SoundFileBrowser::meter));
617 SoundFileBrowser::stop_metering ()
619 metering_connection.disconnect();
623 SoundFileBrowser::meter ()
625 if (is_mapped () && session && gm) {
626 gm->update_meters ();
631 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
633 return AudioFileSource::safe_file_extension (filter_info.filename);
637 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
639 return SMFSource::safe_file_extension (filter_info.filename);
643 SoundFileBrowser::update_preview ()
645 if (preview.setup_labels (chooser.get_filename())) {
646 if (preview.autoplay()) {
647 Glib::signal_idle().connect (mem_fun (preview, &SoundFileBox::audition_oneshot));
653 SoundFileBrowser::found_list_view_selected ()
655 if (!reset_options ()) {
656 set_response_sensitive (RESPONSE_OK, false);
660 TreeView::Selection::ListHandle_Path rows = found_list_view.get_selection()->get_selected_rows ();
663 TreeIter iter = found_list->get_iter(*rows.begin());
664 file = (*iter)[found_list_columns.pathname];
665 chooser.set_filename (file);
666 set_response_sensitive (RESPONSE_OK, true);
668 set_response_sensitive (RESPONSE_OK, false);
671 preview.setup_labels (file);
676 SoundFileBrowser::freesound_list_view_selected ()
678 if (!reset_options ()) {
679 set_response_sensitive (RESPONSE_OK, false);
683 TreeView::Selection::ListHandle_Path rows = freesound_list_view.get_selection()->get_selected_rows ();
686 TreeIter iter = freesound_list->get_iter(*rows.begin());
687 file = (*iter)[freesound_list_columns.pathname];
688 chooser.set_filename (file);
689 set_response_sensitive (RESPONSE_OK, true);
691 set_response_sensitive (RESPONSE_OK, false);
694 preview.setup_labels (file);
699 SoundFileBrowser::found_search_clicked ()
701 string tag_string = found_entry.get_text ();
705 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
706 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
710 vector<string> results;
711 Library->search_members_and (results, tags);
714 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
715 TreeModel::iterator new_row = found_list->append();
716 TreeModel::Row row = *new_row;
717 string path = Glib::filename_from_uri (string ("file:") + *i);
718 row[found_list_columns.pathname] = path;
723 freesound_search_thread_entry (void* arg)
725 PBD::ThreadCreated (pthread_self(), X_("Freesound Search"));
727 static_cast<SoundFileBrowser*>(arg)->freesound_search_thread ();
732 bool searching = false;
733 bool canceling = false;
736 SoundFileBrowser::freesound_search_clicked ()
738 if (canceling) //already canceling, button does nothing
742 freesound_search_btn.set_label(_("Cancelling.."));
746 freesound_search_btn.set_label(_("Cancel"));
747 pthread_t freesound_thr;
748 pthread_create_and_store ("freesound_search", &freesound_thr, 0, freesound_search_thread_entry, this);
753 SoundFileBrowser::freesound_search_thread()
756 freesound_list->clear();
759 path = Glib::get_home_dir();
760 path += "/Freesound/";
761 Mootcher theMootcher(path.c_str());
763 string name_string = freesound_name_entry.get_text ();
764 string pass_string = freesound_pass_entry.get_text ();
765 string search_string = freesound_entry.get_text ();
767 if ( theMootcher.doLogin( name_string, pass_string ) ) {
769 string theString = theMootcher.searchText(search_string);
772 doc.read_buffer( theString );
773 XMLNode *root = doc.root();
775 if (root==NULL) return;
777 if ( strcmp(root->name().c_str(), "freesound") == 0) {
780 XMLNodeList children = root->children();
781 XMLNodeConstIterator niter;
782 for (niter = children.begin(); niter != children.end() && !canceling; ++niter) {
784 if( strcmp( node->name().c_str(), "sample") == 0 ){
785 XMLProperty *prop=node->property ("id");
786 string filename = theMootcher.getFile( prop->value().c_str() );
787 if ( filename != "" ) {
788 TreeModel::iterator new_row = freesound_list->append();
789 TreeModel::Row row = *new_row;
790 string path = Glib::filename_from_uri (string ("file:") + filename);
791 row[freesound_list_columns.pathname] = path;
800 freesound_search_btn.set_label(_("Start Downloading"));
805 SoundFileBrowser::get_paths ()
807 vector<ustring> results;
809 int n = notebook.get_current_page ();
812 vector<ustring> filenames = chooser.get_filenames();
813 vector<ustring>::iterator i;
815 for (i = filenames.begin(); i != filenames.end(); ++i) {
817 if ((!stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
818 results.push_back (*i);
824 typedef TreeView::Selection::ListHandle_Path ListPath;
826 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
827 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
828 TreeIter iter = found_list->get_iter(*i);
829 ustring str = (*iter)[found_list_columns.pathname];
831 results.push_back (str);
835 typedef TreeView::Selection::ListHandle_Path ListPath;
837 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
838 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
839 TreeIter iter = freesound_list->get_iter(*i);
840 ustring str = (*iter)[freesound_list_columns.pathname];
842 results.push_back (str);
850 SoundFileOmega::reset_options_noret ()
852 if (!resetting_ourselves) {
853 (void) reset_options ();
858 SoundFileOmega::reset_options ()
860 vector<ustring> paths = get_paths ();
864 channel_combo.set_sensitive (false);
865 action_combo.set_sensitive (false);
866 where_combo.set_sensitive (false);
867 copy_files_btn.set_sensitive (false);
873 channel_combo.set_sensitive (true);
874 action_combo.set_sensitive (true);
875 where_combo.set_sensitive (true);
877 /* if we get through this function successfully, this may be
878 reset at the end, once we know if we can use hard links
882 if (Config->get_only_copy_imported_files()) {
883 copy_files_btn.set_sensitive (false);
885 copy_files_btn.set_sensitive (false);
891 bool selection_includes_multichannel;
892 bool selection_can_be_embedded_with_links = check_link_status (*session, paths);
895 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
896 Glib::signal_idle().connect (mem_fun (*this, &SoundFileOmega::bad_file_message));
900 ustring existing_choice;
901 vector<string> action_strings;
903 if (selected_track_cnt > 0) {
904 if (channel_combo.get_active_text().length()) {
905 ImportDisposition id = get_channel_disposition();
908 case Editing::ImportDistinctFiles:
909 if (selected_track_cnt == paths.size()) {
910 action_strings.push_back (importmode2string (ImportToTrack));
914 case Editing::ImportDistinctChannels:
915 /* XXX it would be nice to allow channel-per-selected track
916 but its too hard we don't want to deal with all the
917 different per-file + per-track channel configurations.
922 action_strings.push_back (importmode2string (ImportToTrack));
928 action_strings.push_back (importmode2string (ImportAsTrack));
929 action_strings.push_back (importmode2string (ImportAsRegion));
930 action_strings.push_back (importmode2string (ImportAsTapeTrack));
932 resetting_ourselves = true;
934 existing_choice = action_combo.get_active_text();
936 set_popdown_strings (action_combo, action_strings);
938 /* preserve any existing choice, if possible */
941 if (existing_choice.length()) {
942 vector<string>::iterator x;
943 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
944 if (*x == existing_choice) {
945 action_combo.set_active_text (existing_choice);
949 if (x == action_strings.end()) {
950 action_combo.set_active_text (action_strings.front());
953 action_combo.set_active_text (action_strings.front());
956 resetting_ourselves = false;
958 if ((mode = get_mode()) == ImportAsRegion) {
959 where_combo.set_sensitive (false);
961 where_combo.set_sensitive (true);
964 vector<string> channel_strings;
966 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
967 channel_strings.push_back (_("one track per file"));
969 if (selection_includes_multichannel) {
970 channel_strings.push_back (_("one track per channel"));
973 if (paths.size() > 1) {
974 /* tape tracks are a single region per track, so we cannot
975 sequence multiple files.
977 if (mode != ImportAsTapeTrack) {
978 channel_strings.push_back (_("sequence files"));
981 channel_strings.push_back (_("all files in one region"));
987 channel_strings.push_back (_("one region per file"));
989 if (selection_includes_multichannel) {
990 channel_strings.push_back (_("one region per channel"));
993 if (paths.size() > 1) {
995 channel_strings.push_back (_("all files in one region"));
1000 existing_choice = channel_combo.get_active_text();
1002 set_popdown_strings (channel_combo, channel_strings);
1004 /* preserve any existing choice, if possible */
1006 if (existing_choice.length()) {
1007 vector<string>::iterator x;
1008 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1009 if (*x == existing_choice) {
1010 channel_combo.set_active_text (existing_choice);
1014 if (x == channel_strings.end()) {
1015 channel_combo.set_active_text (channel_strings.front());
1018 channel_combo.set_active_text (channel_strings.front());
1022 src_combo.set_sensitive (true);
1024 src_combo.set_sensitive (false);
1027 if (Config->get_only_copy_imported_files()) {
1029 if (selection_can_be_embedded_with_links) {
1030 copy_files_btn.set_sensitive (true);
1032 copy_files_btn.set_sensitive (false);
1037 copy_files_btn.set_sensitive (true);
1045 SoundFileOmega::bad_file_message()
1047 MessageDialog msg (*this,
1048 _("One or more of the selected files\ncannot be used by Ardour"),
1053 resetting_ourselves = true;
1054 chooser.unselect_uri (chooser.get_preview_uri());
1055 resetting_ourselves = false;
1061 SoundFileOmega::check_info (const vector<ustring>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1070 multichannel = false;
1072 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1074 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1075 if (info.channels > 1) {
1076 multichannel = true;
1081 if (sz != info.length) {
1086 if ((nframes_t) info.samplerate != session->frame_rate()) {
1090 } else if (SMFSource::safe_file_extension (*i)) {
1092 SMFReader reader(*i);
1093 if (reader.num_tracks() > 1) {
1094 multichannel = true; // "channel" == track here...
1097 /* XXX we need err = true handling here in case
1098 we can't check the file
1111 SoundFileOmega::check_link_status (const Session& s, const vector<ustring>& paths)
1113 sys::path path = s.session_directory().sound_path() / "linktest";
1114 string tmpdir = path.to_string();
1117 if (mkdir (tmpdir.c_str(), 0744)) {
1118 if (errno != EEXIST) {
1123 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1125 char tmpc[MAXPATHLEN+1];
1127 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1131 if (link ((*i).c_str(), tmpc)) {
1141 rmdir (tmpdir.c_str());
1145 SoundFileChooser::SoundFileChooser (Gtk::Window& parent, string title, ARDOUR::Session* s)
1146 : SoundFileBrowser (parent, title, s, false)
1148 chooser.set_select_multiple (false);
1149 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1150 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1154 SoundFileChooser::on_hide ()
1156 ArdourDialog::on_hide();
1160 session->cancel_audition();
1165 SoundFileChooser::get_filename ()
1167 vector<ustring> paths;
1169 paths = get_paths ();
1171 if (paths.empty()) {
1175 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1179 return paths.front();
1182 SoundFileOmega::SoundFileOmega (Gtk::Window& parent, string title, ARDOUR::Session* s, int selected_tracks, bool persistent,
1183 Editing::ImportMode mode_hint)
1184 : SoundFileBrowser (parent, title, s, persistent),
1185 copy_files_btn ( _("Copy files to session")),
1186 selected_track_cnt (selected_tracks)
1192 set_size_request (-1, 450);
1194 block_two.set_border_width (12);
1195 block_three.set_border_width (12);
1196 block_four.set_border_width (12);
1198 options.set_spacing (12);
1201 str.push_back (_("use file timestamp"));
1202 str.push_back (_("at edit point"));
1203 str.push_back (_("at playhead"));
1204 str.push_back (_("at session start"));
1205 set_popdown_strings (where_combo, str);
1206 where_combo.set_active_text (str.front());
1208 Label* l = manage (new Label);
1209 l->set_text (_("Add files:"));
1211 hbox = manage (new HBox);
1212 hbox->set_border_width (12);
1213 hbox->set_spacing (6);
1214 hbox->pack_start (*l, false, false);
1215 hbox->pack_start (action_combo, false, false);
1216 vbox = manage (new VBox);
1217 vbox->pack_start (*hbox, false, false);
1218 options.pack_start (*vbox, false, false);
1220 /* dummy entry for action combo so that it doesn't look odd if we
1221 come up with no tracks selected.
1225 str.push_back (importmode2string (mode_hint));
1226 set_popdown_strings (action_combo, str);
1227 action_combo.set_active_text (str.front());
1228 action_combo.set_sensitive (false);
1230 l = manage (new Label);
1231 l->set_text (_("Insert:"));
1233 hbox = manage (new HBox);
1234 hbox->set_border_width (12);
1235 hbox->set_spacing (6);
1236 hbox->pack_start (*l, false, false);
1237 hbox->pack_start (where_combo, false, false);
1238 vbox = manage (new VBox);
1239 vbox->pack_start (*hbox, false, false);
1240 options.pack_start (*vbox, false, false);
1243 l = manage (new Label);
1244 l->set_text (_("Mapping:"));
1246 hbox = manage (new HBox);
1247 hbox->set_border_width (12);
1248 hbox->set_spacing (6);
1249 hbox->pack_start (*l, false, false);
1250 hbox->pack_start (channel_combo, false, false);
1251 vbox = manage (new VBox);
1252 vbox->pack_start (*hbox, false, false);
1253 options.pack_start (*vbox, false, false);
1256 str.push_back (_("one track per file"));
1257 set_popdown_strings (channel_combo, str);
1258 channel_combo.set_active_text (str.front());
1259 channel_combo.set_sensitive (false);
1261 l = manage (new Label);
1262 l->set_text (_("Conversion Quality:"));
1264 hbox = manage (new HBox);
1265 hbox->set_border_width (12);
1266 hbox->set_spacing (6);
1267 hbox->pack_start (*l, false, false);
1268 hbox->pack_start (src_combo, false, false);
1269 vbox = manage (new VBox);
1270 vbox->pack_start (*hbox, false, false);
1271 options.pack_start (*vbox, false, false);
1274 str.push_back (_("Best"));
1275 str.push_back (_("Good"));
1276 str.push_back (_("Quick"));
1277 str.push_back (_("Fast"));
1278 str.push_back (_("Fastest"));
1280 set_popdown_strings (src_combo, str);
1281 src_combo.set_active_text (str.front());
1282 src_combo.set_sensitive (false);
1286 action_combo.signal_changed().connect (mem_fun (*this, &SoundFileOmega::reset_options_noret));
1288 copy_files_btn.set_active (true);
1290 block_four.pack_start (copy_files_btn, false, false);
1292 options.pack_start (block_four, false, false);
1294 get_vbox()->pack_start (options, false, false);
1296 /* setup disposition map */
1298 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1299 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1300 disposition_map.insert (pair<ustring,ImportDisposition>(_("merge files"), ImportMergeFiles));
1301 disposition_map.insert (pair<ustring,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1303 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1304 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1305 disposition_map.insert (pair<ustring,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1307 chooser.signal_selection_changed().connect (mem_fun (*this, &SoundFileOmega::file_selection_changed));
1311 SoundFileOmega::set_mode (ImportMode mode)
1313 action_combo.set_active_text (importmode2string (mode));
1317 SoundFileOmega::get_mode () const
1319 return string2importmode (action_combo.get_active_text());
1323 SoundFileOmega::on_hide ()
1325 ArdourDialog::on_hide();
1327 session->cancel_audition();
1332 SoundFileOmega::get_position() const
1334 ustring str = where_combo.get_active_text();
1336 if (str == _("use file timestamp")) {
1337 return ImportAtTimestamp;
1338 } else if (str == _("at edit point")) {
1339 return ImportAtEditPoint;
1340 } else if (str == _("at playhead")) {
1341 return ImportAtPlayhead;
1343 return ImportAtStart;
1348 SoundFileOmega::get_src_quality() const
1350 ustring str = where_combo.get_active_text();
1352 if (str == _("Best")) {
1354 } else if (str == _("Good")) {
1356 } else if (str == _("Quick")) {
1358 } else if (str == _("Fast")) {
1366 SoundFileOmega::get_channel_disposition () const
1368 /* we use a map here because the channel combo can contain different strings
1369 depending on the state of the other combos. the map contains all possible strings
1370 and the ImportDisposition enum that corresponds to it.
1373 ustring str = channel_combo.get_active_text();
1374 DispositionMap::const_iterator x = disposition_map.find (str);
1376 if (x == disposition_map.end()) {
1377 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1385 SoundFileOmega::reset (int selected_tracks)
1387 selected_track_cnt = selected_tracks;
1392 SoundFileOmega::file_selection_changed ()
1394 if (resetting_ourselves) {
1398 if (!reset_options ()) {
1399 set_response_sensitive (RESPONSE_OK, false);
1401 if (chooser.get_filenames().size() > 0) {
1402 set_response_sensitive (RESPONSE_OK, true);
1404 set_response_sensitive (RESPONSE_OK, false);