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/SMFReader.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"))
126 set_name (X_("SoundFileBox"));
127 set_size_request (300, -1);
129 preview_label.set_markup (_("<b>Soundfile Info</b>"));
131 border_frame.set_label_widget (preview_label);
132 border_frame.add (main_box);
134 pack_start (border_frame, true, true);
135 set_border_width (6);
137 main_box.set_border_width (6);
138 main_box.set_spacing (12);
140 length.set_text (_("Length:"));
141 timecode.set_text (_("Timestamp:"));
142 format.set_text (_("Format:"));
143 channels.set_text (_("Channels:"));
144 samplerate.set_text (_("Sample rate:"));
146 table.set_col_spacings (6);
147 table.set_homogeneous (false);
148 table.set_row_spacings (6);
150 table.attach (channels, 0, 1, 0, 1, FILL|EXPAND, (AttachOptions) 0);
151 table.attach (samplerate, 0, 1, 1, 2, FILL|EXPAND, (AttachOptions) 0);
152 table.attach (format, 0, 1, 2, 4, FILL|EXPAND, (AttachOptions) 0);
153 table.attach (length, 0, 1, 4, 5, FILL|EXPAND, (AttachOptions) 0);
154 table.attach (timecode, 0, 1, 5, 6, FILL|EXPAND, (AttachOptions) 0);
156 table.attach (channels_value, 1, 2, 0, 1, FILL, (AttachOptions) 0);
157 table.attach (samplerate_value, 1, 2, 1, 2, FILL, (AttachOptions) 0);
158 table.attach (format_text, 1, 2, 2, 4, FILL, AttachOptions (0));
159 table.attach (length_clock, 1, 2, 4, 5, FILL, (AttachOptions) 0);
160 table.attach (timecode_clock, 1, 2, 5, 6, FILL, (AttachOptions) 0);
162 length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock.mode());
163 timecode_clock.set_mode (AudioClock::SMPTE);
165 hbox = manage (new HBox);
166 hbox->pack_start (table, false, false);
167 main_box.pack_start (*hbox, false, false);
169 tags_entry.set_editable (true);
170 tags_entry.signal_focus_out_event().connect (mem_fun (*this, &SoundFileBox::tags_entry_left));
171 hbox = manage (new HBox);
172 hbox->pack_start (tags_entry, true, true);
174 vbox = manage (new VBox);
176 Label* label = manage (new Label (_("Tags:")));
177 label->set_alignment (0.0f, 0.5f);
178 vbox->set_spacing (6);
179 vbox->pack_start(*label, false, false);
180 vbox->pack_start(*hbox, true, true);
182 main_box.pack_start(*vbox, true, true);
183 main_box.pack_start(bottom_box, false, false);
185 play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
186 play_btn.set_label (_("Play (double click)"));
188 stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
189 stop_btn.set_label (_("Stop"));
191 bottom_box.set_homogeneous (false);
192 bottom_box.set_spacing (6);
193 bottom_box.pack_start(play_btn, true, true);
194 bottom_box.pack_start(stop_btn, true, true);
195 bottom_box.pack_start(autoplay_btn, false, false);
197 play_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::audition));
198 stop_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::stop_audition));
200 length.set_alignment (0.0f, 0.5f);
201 format.set_alignment (0.0f, 0.5f);
202 channels.set_alignment (0.0f, 0.5f);
203 samplerate.set_alignment (0.0f, 0.5f);
204 timecode.set_alignment (0.0f, 0.5f);
206 channels_value.set_alignment (0.0f, 0.5f);
207 samplerate_value.set_alignment (0.0f, 0.5f);
211 SoundFileBox::set_session(Session* s)
216 play_btn.set_sensitive (false);
217 stop_btn.set_sensitive (false);
221 length_clock.set_session (s);
222 timecode_clock.set_session (s);
226 SoundFileBox::setup_labels (const ustring& filename)
229 // save existing tags
237 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
239 preview_label.set_markup (_("<b>Soundfile Info</b>"));
240 format_text.set_text (_("n/a"));
241 channels_value.set_text (_("n/a"));
242 samplerate_value.set_text (_("n/a"));
243 tags_entry.get_buffer()->set_text ("");
245 length_clock.set (0);
246 timecode_clock.set (0);
248 tags_entry.set_sensitive (false);
249 play_btn.set_sensitive (false);
254 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::path_get_basename (filename)));
255 format_text.set_text (sf_info.format_name);
256 channels_value.set_text (to_string (sf_info.channels, std::dec));
258 if (_session && sf_info.samplerate != _session->frame_rate()) {
259 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
260 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
261 samplerate_value.set_name ("NewSessionSR1Label");
262 samplerate.set_name ("NewSessionSR1Label");
264 samplerate.set_text (_("Sample rate:"));
265 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
266 samplerate_value.set_name ("NewSessionSR2Label");
267 samplerate.set_name ("NewSessionSR2Label");
270 double src_coef = (double) _session->nominal_frame_rate() / sf_info.samplerate;
272 length_clock.set (sf_info.length * src_coef + 0.5, true);
273 timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
275 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
277 vector<string> tags = Library->get_tags (string ("//") + filename);
279 stringstream tag_string;
280 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
281 if (i != tags.begin()) {
286 tags_entry.get_buffer()->set_text (tag_string.str());
288 tags_entry.set_sensitive (true);
290 play_btn.set_sensitive (true);
297 SoundFileBox::autoplay() const
299 return autoplay_btn.get_active();
303 SoundFileBox::audition_oneshot()
310 SoundFileBox::audition ()
316 _session->cancel_audition();
318 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
319 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
323 boost::shared_ptr<Region> r;
325 boost::shared_ptr<AudioFileSource> afs;
326 bool old_sbp = AudioSource::get_build_peakfiles ();
328 /* don't even think of building peakfiles for these files */
330 AudioSource::set_build_peakfiles (false);
332 for (int n = 0; n < sf_info.channels; ++n) {
334 afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, *_session, path,
335 n, AudioFileSource::Flag (0), false));
337 srclist.push_back(afs);
339 } catch (failed_constructor& err) {
340 error << _("Could not access soundfile: ") << path << endmsg;
341 AudioSource::set_build_peakfiles (old_sbp);
346 AudioSource::set_build_peakfiles (old_sbp);
348 if (srclist.empty()) {
352 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
353 string rname = region_name_from_path (afs->path(), false);
354 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, 0, srclist[0]->length(), rname, 0, Region::DefaultFlags, false));
356 _session->audition_region(r);
360 SoundFileBox::stop_audition ()
363 _session->cancel_audition();
368 SoundFileBox::tags_entry_left (GdkEventFocus *ev)
375 SoundFileBox::tags_changed ()
377 string tag_string = tags_entry.get_buffer()->get_text ();
379 if (tag_string.empty()) {
385 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
386 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
394 SoundFileBox::save_tags (const vector<string>& tags)
396 Library->set_tags (string ("//") + path, tags);
397 Library->save_changes ();
400 SoundFileBrowser::SoundFileBrowser (Gtk::Window& parent, string title, ARDOUR::Session* s, bool persistent)
401 : ArdourDialog (parent, title, false, false),
402 found_list (ListStore::create(found_list_columns)),
403 freesound_list (ListStore::create(freesound_list_columns)),
404 chooser (FILE_CHOOSER_ACTION_OPEN),
405 preview (persistent),
406 found_search_btn (_("Search")),
407 found_list_view (found_list),
408 freesound_search_btn (_("Start Downloading")),
409 freesound_list_view (freesound_list)
411 resetting_ourselves = false;
414 resetting_ourselves = false;
417 if (ARDOUR::Profile->get_sae()) {
418 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
419 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
423 //add the file chooser
425 chooser.set_border_width (12);
427 audio_filter.add_custom (FILE_FILTER_FILENAME, mem_fun(*this, &SoundFileBrowser::on_audio_filter));
428 audio_filter.set_name (_("Audio files"));
430 midi_filter.add_custom (FILE_FILTER_FILENAME, mem_fun(*this, &SoundFileBrowser::on_midi_filter));
431 midi_filter.set_name (_("MIDI files"));
433 matchall_filter.add_pattern ("*.*");
434 matchall_filter.set_name (_("All files"));
436 chooser.add_filter (audio_filter);
437 chooser.add_filter (midi_filter);
438 chooser.add_filter (matchall_filter);
439 chooser.set_select_multiple (true);
440 chooser.signal_update_preview().connect(mem_fun(*this, &SoundFileBrowser::update_preview));
441 chooser.signal_file_activated().connect (mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
443 if (!persistent_folder.empty()) {
444 chooser.set_current_folder (persistent_folder);
446 notebook.append_page (chooser, _("Browse Files"));
449 hpacker.set_spacing (6);
450 hpacker.pack_start (notebook, true, true);
451 hpacker.pack_start (preview, false, false);
453 get_vbox()->pack_start (hpacker, true, true);
461 hbox = manage(new HBox);
462 hbox->pack_start (found_entry);
463 hbox->pack_start (found_search_btn);
465 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
466 scroll->add(found_list_view);
467 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
469 vbox = manage(new VBox);
470 vbox->pack_start (*hbox, PACK_SHRINK);
471 vbox->pack_start (*scroll);
473 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
475 found_list_view.get_selection()->signal_changed().connect(mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
477 found_list_view.signal_row_activated().connect (mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
479 found_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked));
480 found_entry.signal_activate().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked));
482 notebook.append_page (*vbox, _("Search Tags"));
485 //add freesound search
492 passbox = manage(new HBox);
493 passbox->set_border_width (12);
494 passbox->set_spacing (6);
496 label = manage (new Label);
497 label->set_text (_("User:"));
498 passbox->pack_start (*label, false, false);
499 passbox->pack_start (freesound_name_entry);
500 label = manage (new Label);
501 label->set_text (_("Password:"));
502 passbox->pack_start (*label, false, false);
503 passbox->pack_start (freesound_pass_entry);
504 label = manage (new Label);
505 label->set_text (_("Tags:"));
506 passbox->pack_start (*label, false, false);
507 passbox->pack_start (freesound_entry, false, false);
508 passbox->pack_start (freesound_search_btn, false, false);
510 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
511 scroll->add(freesound_list_view);
512 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
514 vbox = manage(new VBox);
515 vbox->pack_start (*passbox, PACK_SHRINK);
516 vbox->pack_start(*scroll);
518 //vbox->pack_start (freesound_list_view);
520 freesound_list_view.append_column(_("Paths"), freesound_list_columns.pathname);
521 freesound_list_view.get_selection()->signal_changed().connect(mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
523 //freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
524 freesound_list_view.signal_row_activated().connect (mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
525 freesound_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
526 freesound_entry.signal_activate().connect(mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
527 notebook.append_page (*vbox, _("Search Freesound"));
532 notebook.set_size_request (500, -1);
536 add_button (Stock::CANCEL, RESPONSE_CANCEL);
537 add_button (Stock::APPLY, RESPONSE_APPLY);
538 add_button (Stock::OK, RESPONSE_OK);
542 SoundFileBrowser::~SoundFileBrowser ()
544 persistent_folder = chooser.get_current_folder();
549 SoundFileBrowser::on_show ()
551 ArdourDialog::on_show ();
556 SoundFileBrowser::clear_selection ()
558 chooser.unselect_all ();
559 found_list_view.get_selection()->unselect_all ();
563 SoundFileBrowser::chooser_file_activated ()
569 SoundFileBrowser::found_list_view_activated (const TreeModel::Path& path, TreeViewColumn* col)
575 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path& path, TreeViewColumn* col)
581 SoundFileBrowser::set_session (Session* s)
583 ArdourDialog::set_session (s);
584 preview.set_session (s);
588 remove_gain_meter ();
593 SoundFileBrowser::add_gain_meter ()
599 gm = new GainMeter (*session);
600 gm->set_io (session->the_auditioner());
602 meter_packer.set_border_width (12);
603 meter_packer.pack_start (*gm, false, true);
604 hpacker.pack_end (meter_packer, false, false);
605 meter_packer.show_all ();
610 SoundFileBrowser::remove_gain_meter ()
613 meter_packer.remove (*gm);
614 hpacker.remove (meter_packer);
621 SoundFileBrowser::start_metering ()
623 metering_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun(*this, &SoundFileBrowser::meter));
627 SoundFileBrowser::stop_metering ()
629 metering_connection.disconnect();
633 SoundFileBrowser::meter ()
635 if (is_mapped () && session && gm) {
636 gm->update_meters ();
641 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
643 return AudioFileSource::safe_file_extension (filter_info.filename);
647 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
649 return SMFSource::safe_file_extension (filter_info.filename);
653 SoundFileBrowser::update_preview ()
655 if (preview.setup_labels (chooser.get_filename())) {
656 if (preview.autoplay()) {
657 Glib::signal_idle().connect (mem_fun (preview, &SoundFileBox::audition_oneshot));
663 SoundFileBrowser::found_list_view_selected ()
665 if (!reset_options ()) {
666 set_response_sensitive (RESPONSE_OK, false);
670 TreeView::Selection::ListHandle_Path rows = found_list_view.get_selection()->get_selected_rows ();
673 TreeIter iter = found_list->get_iter(*rows.begin());
674 file = (*iter)[found_list_columns.pathname];
675 chooser.set_filename (file);
676 set_response_sensitive (RESPONSE_OK, true);
678 set_response_sensitive (RESPONSE_OK, false);
681 preview.setup_labels (file);
686 SoundFileBrowser::freesound_list_view_selected ()
688 if (!reset_options ()) {
689 set_response_sensitive (RESPONSE_OK, false);
693 TreeView::Selection::ListHandle_Path rows = freesound_list_view.get_selection()->get_selected_rows ();
696 TreeIter iter = freesound_list->get_iter(*rows.begin());
697 file = (*iter)[freesound_list_columns.pathname];
698 chooser.set_filename (file);
699 set_response_sensitive (RESPONSE_OK, true);
701 set_response_sensitive (RESPONSE_OK, false);
704 preview.setup_labels (file);
709 SoundFileBrowser::found_search_clicked ()
711 string tag_string = found_entry.get_text ();
715 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
716 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
720 vector<string> results;
721 Library->search_members_and (results, tags);
724 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
725 TreeModel::iterator new_row = found_list->append();
726 TreeModel::Row row = *new_row;
727 string path = Glib::filename_from_uri (string ("file:") + *i);
728 row[found_list_columns.pathname] = path;
733 freesound_search_thread_entry (void* arg)
735 PBD::notify_gui_about_thread_creation (pthread_self(), X_("Freesound Search"));
737 static_cast<SoundFileBrowser*>(arg)->freesound_search_thread ();
742 bool searching = false;
743 bool canceling = false;
746 SoundFileBrowser::freesound_search_clicked ()
748 if (canceling) //already canceling, button does nothing
752 freesound_search_btn.set_label(_("Cancelling.."));
756 freesound_search_btn.set_label(_("Cancel"));
757 pthread_t freesound_thr;
758 pthread_create_and_store ("freesound_search", &freesound_thr, 0, freesound_search_thread_entry, this);
763 SoundFileBrowser::freesound_search_thread()
766 freesound_list->clear();
769 path = Glib::get_home_dir();
770 path += "/Freesound/";
771 Mootcher theMootcher(path.c_str());
773 string name_string = freesound_name_entry.get_text ();
774 string pass_string = freesound_pass_entry.get_text ();
775 string search_string = freesound_entry.get_text ();
777 if ( theMootcher.doLogin( name_string, pass_string ) ) {
779 string theString = theMootcher.searchText(search_string);
782 doc.read_buffer( theString );
783 XMLNode *root = doc.root();
785 if (root==NULL) return;
787 if ( strcmp(root->name().c_str(), "freesound") == 0) {
790 XMLNodeList children = root->children();
791 XMLNodeConstIterator niter;
792 for (niter = children.begin(); niter != children.end() && !canceling; ++niter) {
794 if( strcmp( node->name().c_str(), "sample") == 0 ){
795 XMLProperty *prop=node->property ("id");
796 string filename = theMootcher.getFile( prop->value().c_str() );
797 if ( filename != "" ) {
798 TreeModel::iterator new_row = freesound_list->append();
799 TreeModel::Row row = *new_row;
800 string path = Glib::filename_from_uri (string ("file:") + filename);
801 row[freesound_list_columns.pathname] = path;
810 freesound_search_btn.set_label(_("Start Downloading"));
815 SoundFileBrowser::get_paths ()
817 vector<ustring> results;
819 int n = notebook.get_current_page ();
822 vector<ustring> filenames = chooser.get_filenames();
823 vector<ustring>::iterator i;
825 for (i = filenames.begin(); i != filenames.end(); ++i) {
827 if ((!stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
828 results.push_back (*i);
834 typedef TreeView::Selection::ListHandle_Path ListPath;
836 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
837 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
838 TreeIter iter = found_list->get_iter(*i);
839 ustring str = (*iter)[found_list_columns.pathname];
841 results.push_back (str);
845 typedef TreeView::Selection::ListHandle_Path ListPath;
847 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
848 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
849 TreeIter iter = freesound_list->get_iter(*i);
850 ustring str = (*iter)[freesound_list_columns.pathname];
852 results.push_back (str);
860 SoundFileOmega::reset_options_noret ()
862 if (!resetting_ourselves) {
863 (void) reset_options ();
868 SoundFileOmega::reset_options ()
870 vector<ustring> paths = get_paths ();
874 channel_combo.set_sensitive (false);
875 action_combo.set_sensitive (false);
876 where_combo.set_sensitive (false);
877 copy_files_btn.set_sensitive (false);
883 channel_combo.set_sensitive (true);
884 action_combo.set_sensitive (true);
885 where_combo.set_sensitive (true);
887 /* if we get through this function successfully, this may be
888 reset at the end, once we know if we can use hard links
892 if (Config->get_only_copy_imported_files()) {
893 copy_files_btn.set_sensitive (false);
895 copy_files_btn.set_sensitive (false);
901 bool selection_includes_multichannel;
902 bool selection_can_be_embedded_with_links = check_link_status (*session, paths);
905 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
906 Glib::signal_idle().connect (mem_fun (*this, &SoundFileOmega::bad_file_message));
910 ustring existing_choice;
911 vector<string> action_strings;
913 if (selected_track_cnt > 0) {
914 if (channel_combo.get_active_text().length()) {
915 ImportDisposition id = get_channel_disposition();
918 case Editing::ImportDistinctFiles:
919 if (selected_track_cnt == paths.size()) {
920 action_strings.push_back (importmode2string (ImportToTrack));
924 case Editing::ImportDistinctChannels:
925 /* XXX it would be nice to allow channel-per-selected track
926 but its too hard we don't want to deal with all the
927 different per-file + per-track channel configurations.
932 action_strings.push_back (importmode2string (ImportToTrack));
938 action_strings.push_back (importmode2string (ImportAsTrack));
939 action_strings.push_back (importmode2string (ImportAsRegion));
940 action_strings.push_back (importmode2string (ImportAsTapeTrack));
942 resetting_ourselves = true;
944 existing_choice = action_combo.get_active_text();
946 set_popdown_strings (action_combo, action_strings);
948 /* preserve any existing choice, if possible */
951 if (existing_choice.length()) {
952 vector<string>::iterator x;
953 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
954 if (*x == existing_choice) {
955 action_combo.set_active_text (existing_choice);
959 if (x == action_strings.end()) {
960 action_combo.set_active_text (action_strings.front());
963 action_combo.set_active_text (action_strings.front());
966 resetting_ourselves = false;
968 if ((mode = get_mode()) == ImportAsRegion) {
969 where_combo.set_sensitive (false);
971 where_combo.set_sensitive (true);
974 vector<string> channel_strings;
976 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
977 channel_strings.push_back (_("one track per file"));
979 if (selection_includes_multichannel) {
980 channel_strings.push_back (_("one track per channel"));
983 if (paths.size() > 1) {
984 /* tape tracks are a single region per track, so we cannot
985 sequence multiple files.
987 if (mode != ImportAsTapeTrack) {
988 channel_strings.push_back (_("sequence files"));
991 channel_strings.push_back (_("all files in one region"));
997 channel_strings.push_back (_("one region per file"));
999 if (selection_includes_multichannel) {
1000 channel_strings.push_back (_("one region per channel"));
1003 if (paths.size() > 1) {
1005 channel_strings.push_back (_("all files in one region"));
1010 existing_choice = channel_combo.get_active_text();
1012 set_popdown_strings (channel_combo, channel_strings);
1014 /* preserve any existing choice, if possible */
1016 if (existing_choice.length()) {
1017 vector<string>::iterator x;
1018 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1019 if (*x == existing_choice) {
1020 channel_combo.set_active_text (existing_choice);
1024 if (x == channel_strings.end()) {
1025 channel_combo.set_active_text (channel_strings.front());
1028 channel_combo.set_active_text (channel_strings.front());
1032 src_combo.set_sensitive (true);
1034 src_combo.set_sensitive (false);
1037 if (Config->get_only_copy_imported_files()) {
1039 if (selection_can_be_embedded_with_links) {
1040 copy_files_btn.set_sensitive (true);
1042 copy_files_btn.set_sensitive (false);
1047 copy_files_btn.set_sensitive (true);
1055 SoundFileOmega::bad_file_message()
1057 MessageDialog msg (*this,
1058 _("One or more of the selected files\ncannot be used by Ardour"),
1063 resetting_ourselves = true;
1064 chooser.unselect_uri (chooser.get_preview_uri());
1065 resetting_ourselves = false;
1071 SoundFileOmega::check_info (const vector<ustring>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1080 multichannel = false;
1082 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1084 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1085 if (info.channels > 1) {
1086 multichannel = true;
1091 if (sz != info.length) {
1096 if ((nframes_t) info.samplerate != session->frame_rate()) {
1100 } else if (SMFSource::safe_file_extension (*i)) {
1102 Evoral::SMFReader reader(*i);
1103 if (reader.num_tracks() > 1) {
1104 multichannel = true; // "channel" == track here...
1107 /* XXX we need err = true handling here in case
1108 we can't check the file
1121 SoundFileOmega::check_link_status (const Session& s, const vector<ustring>& paths)
1123 sys::path path = s.session_directory().sound_path() / "linktest";
1124 string tmpdir = path.to_string();
1127 if (mkdir (tmpdir.c_str(), 0744)) {
1128 if (errno != EEXIST) {
1133 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1135 char tmpc[MAXPATHLEN+1];
1137 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1141 if (link ((*i).c_str(), tmpc)) {
1151 rmdir (tmpdir.c_str());
1155 SoundFileChooser::SoundFileChooser (Gtk::Window& parent, string title, ARDOUR::Session* s)
1156 : SoundFileBrowser (parent, title, s, false)
1158 chooser.set_select_multiple (false);
1159 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1160 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1164 SoundFileChooser::on_hide ()
1166 ArdourDialog::on_hide();
1170 session->cancel_audition();
1175 SoundFileChooser::get_filename ()
1177 vector<ustring> paths;
1179 paths = get_paths ();
1181 if (paths.empty()) {
1185 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1189 return paths.front();
1192 SoundFileOmega::SoundFileOmega (Gtk::Window& parent, string title, ARDOUR::Session* s, int selected_tracks, bool persistent,
1193 Editing::ImportMode mode_hint)
1194 : SoundFileBrowser (parent, title, s, persistent),
1195 copy_files_btn ( _("Copy files to session")),
1196 selected_track_cnt (selected_tracks)
1202 set_size_request (-1, 450);
1204 block_two.set_border_width (12);
1205 block_three.set_border_width (12);
1206 block_four.set_border_width (12);
1208 options.set_spacing (12);
1211 str.push_back (_("use file timestamp"));
1212 str.push_back (_("at edit point"));
1213 str.push_back (_("at playhead"));
1214 str.push_back (_("at session start"));
1215 set_popdown_strings (where_combo, str);
1216 where_combo.set_active_text (str.front());
1218 Label* l = manage (new Label);
1219 l->set_text (_("Add files:"));
1221 hbox = manage (new HBox);
1222 hbox->set_border_width (12);
1223 hbox->set_spacing (6);
1224 hbox->pack_start (*l, false, false);
1225 hbox->pack_start (action_combo, false, false);
1226 vbox = manage (new VBox);
1227 vbox->pack_start (*hbox, false, false);
1228 options.pack_start (*vbox, false, false);
1230 /* dummy entry for action combo so that it doesn't look odd if we
1231 come up with no tracks selected.
1235 str.push_back (importmode2string (mode_hint));
1236 set_popdown_strings (action_combo, str);
1237 action_combo.set_active_text (str.front());
1238 action_combo.set_sensitive (false);
1240 l = manage (new Label);
1241 l->set_text (_("Insert:"));
1243 hbox = manage (new HBox);
1244 hbox->set_border_width (12);
1245 hbox->set_spacing (6);
1246 hbox->pack_start (*l, false, false);
1247 hbox->pack_start (where_combo, false, false);
1248 vbox = manage (new VBox);
1249 vbox->pack_start (*hbox, false, false);
1250 options.pack_start (*vbox, false, false);
1253 l = manage (new Label);
1254 l->set_text (_("Mapping:"));
1256 hbox = manage (new HBox);
1257 hbox->set_border_width (12);
1258 hbox->set_spacing (6);
1259 hbox->pack_start (*l, false, false);
1260 hbox->pack_start (channel_combo, false, false);
1261 vbox = manage (new VBox);
1262 vbox->pack_start (*hbox, false, false);
1263 options.pack_start (*vbox, false, false);
1266 str.push_back (_("one track per file"));
1267 set_popdown_strings (channel_combo, str);
1268 channel_combo.set_active_text (str.front());
1269 channel_combo.set_sensitive (false);
1271 l = manage (new Label);
1272 l->set_text (_("Conversion Quality:"));
1274 hbox = manage (new HBox);
1275 hbox->set_border_width (12);
1276 hbox->set_spacing (6);
1277 hbox->pack_start (*l, false, false);
1278 hbox->pack_start (src_combo, false, false);
1279 vbox = manage (new VBox);
1280 vbox->pack_start (*hbox, false, false);
1281 options.pack_start (*vbox, false, false);
1284 str.push_back (_("Best"));
1285 str.push_back (_("Good"));
1286 str.push_back (_("Quick"));
1287 str.push_back (_("Fast"));
1288 str.push_back (_("Fastest"));
1290 set_popdown_strings (src_combo, str);
1291 src_combo.set_active_text (str.front());
1292 src_combo.set_sensitive (false);
1296 action_combo.signal_changed().connect (mem_fun (*this, &SoundFileOmega::reset_options_noret));
1298 copy_files_btn.set_active (true);
1300 block_four.pack_start (copy_files_btn, false, false);
1302 options.pack_start (block_four, false, false);
1304 get_vbox()->pack_start (options, false, false);
1306 /* setup disposition map */
1308 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1309 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1310 disposition_map.insert (pair<ustring,ImportDisposition>(_("merge files"), ImportMergeFiles));
1311 disposition_map.insert (pair<ustring,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1313 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1314 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1315 disposition_map.insert (pair<ustring,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1317 chooser.signal_selection_changed().connect (mem_fun (*this, &SoundFileOmega::file_selection_changed));
1321 SoundFileOmega::set_mode (ImportMode mode)
1323 action_combo.set_active_text (importmode2string (mode));
1327 SoundFileOmega::get_mode () const
1329 return string2importmode (action_combo.get_active_text());
1333 SoundFileOmega::on_hide ()
1335 ArdourDialog::on_hide();
1337 session->cancel_audition();
1342 SoundFileOmega::get_position() const
1344 ustring str = where_combo.get_active_text();
1346 if (str == _("use file timestamp")) {
1347 return ImportAtTimestamp;
1348 } else if (str == _("at edit point")) {
1349 return ImportAtEditPoint;
1350 } else if (str == _("at playhead")) {
1351 return ImportAtPlayhead;
1353 return ImportAtStart;
1358 SoundFileOmega::get_src_quality() const
1360 ustring str = where_combo.get_active_text();
1362 if (str == _("Best")) {
1364 } else if (str == _("Good")) {
1366 } else if (str == _("Quick")) {
1368 } else if (str == _("Fast")) {
1376 SoundFileOmega::get_channel_disposition () const
1378 /* we use a map here because the channel combo can contain different strings
1379 depending on the state of the other combos. the map contains all possible strings
1380 and the ImportDisposition enum that corresponds to it.
1383 ustring str = channel_combo.get_active_text();
1384 DispositionMap::const_iterator x = disposition_map.find (str);
1386 if (x == disposition_map.end()) {
1387 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1395 SoundFileOmega::reset (int selected_tracks)
1397 selected_track_cnt = selected_tracks;
1402 SoundFileOmega::file_selection_changed ()
1404 if (resetting_ourselves) {
1408 if (!reset_options ()) {
1409 set_response_sensitive (RESPONSE_OK, false);
1411 if (chooser.get_filenames().size() > 0) {
1412 set_response_sensitive (RESPONSE_OK, true);
1414 set_response_sensitive (RESPONSE_OK, false);