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> (
335 SourceFactory::createReadable (DataType::AUDIO, *_session,
336 path, false, n, Source::Flag (0), false));
338 srclist.push_back(afs);
340 } catch (failed_constructor& err) {
341 error << _("Could not access soundfile: ") << path << endmsg;
342 AudioSource::set_build_peakfiles (old_sbp);
347 AudioSource::set_build_peakfiles (old_sbp);
349 if (srclist.empty()) {
353 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
354 string rname = region_name_from_path (afs->path(), false);
355 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, 0,
356 srclist[0]->length(srclist[0]->timeline_position()),
357 rname, 0, Region::DefaultFlags, false));
359 _session->audition_region(r);
363 SoundFileBox::stop_audition ()
366 _session->cancel_audition();
371 SoundFileBox::tags_entry_left (GdkEventFocus *ev)
378 SoundFileBox::tags_changed ()
380 string tag_string = tags_entry.get_buffer()->get_text ();
382 if (tag_string.empty()) {
388 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
389 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
397 SoundFileBox::save_tags (const vector<string>& tags)
399 Library->set_tags (string ("//") + path, tags);
400 Library->save_changes ();
403 SoundFileBrowser::SoundFileBrowser (Gtk::Window& parent, string title, ARDOUR::Session* s, bool persistent)
404 : ArdourDialog (parent, title, false, false),
405 found_list (ListStore::create(found_list_columns)),
406 freesound_list (ListStore::create(freesound_list_columns)),
407 chooser (FILE_CHOOSER_ACTION_OPEN),
408 preview (persistent),
409 found_search_btn (_("Search")),
410 found_list_view (found_list),
411 freesound_search_btn (_("Start Downloading")),
412 freesound_list_view (freesound_list)
414 resetting_ourselves = false;
417 resetting_ourselves = false;
420 if (ARDOUR::Profile->get_sae()) {
421 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
422 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
426 //add the file chooser
428 chooser.set_border_width (12);
430 audio_filter.add_custom (FILE_FILTER_FILENAME, mem_fun(*this, &SoundFileBrowser::on_audio_filter));
431 audio_filter.set_name (_("Audio files"));
433 midi_filter.add_custom (FILE_FILTER_FILENAME, mem_fun(*this, &SoundFileBrowser::on_midi_filter));
434 midi_filter.set_name (_("MIDI files"));
436 matchall_filter.add_pattern ("*.*");
437 matchall_filter.set_name (_("All files"));
439 chooser.add_filter (audio_filter);
440 chooser.add_filter (midi_filter);
441 chooser.add_filter (matchall_filter);
442 chooser.set_select_multiple (true);
443 chooser.signal_update_preview().connect(mem_fun(*this, &SoundFileBrowser::update_preview));
444 chooser.signal_file_activated().connect (mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
446 if (!persistent_folder.empty()) {
447 chooser.set_current_folder (persistent_folder);
449 notebook.append_page (chooser, _("Browse Files"));
452 hpacker.set_spacing (6);
453 hpacker.pack_start (notebook, true, true);
454 hpacker.pack_start (preview, false, false);
456 get_vbox()->pack_start (hpacker, true, true);
464 hbox = manage(new HBox);
465 hbox->pack_start (found_entry);
466 hbox->pack_start (found_search_btn);
468 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
469 scroll->add(found_list_view);
470 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
472 vbox = manage(new VBox);
473 vbox->pack_start (*hbox, PACK_SHRINK);
474 vbox->pack_start (*scroll);
476 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
478 found_list_view.get_selection()->signal_changed().connect(mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
480 found_list_view.signal_row_activated().connect (mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
482 found_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked));
483 found_entry.signal_activate().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked));
485 notebook.append_page (*vbox, _("Search Tags"));
488 //add freesound search
495 passbox = manage(new HBox);
496 passbox->set_border_width (12);
497 passbox->set_spacing (6);
499 label = manage (new Label);
500 label->set_text (_("User:"));
501 passbox->pack_start (*label, false, false);
502 passbox->pack_start (freesound_name_entry);
503 label = manage (new Label);
504 label->set_text (_("Password:"));
505 passbox->pack_start (*label, false, false);
506 passbox->pack_start (freesound_pass_entry);
507 label = manage (new Label);
508 label->set_text (_("Tags:"));
509 passbox->pack_start (*label, false, false);
510 passbox->pack_start (freesound_entry, false, false);
511 passbox->pack_start (freesound_search_btn, false, false);
513 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
514 scroll->add(freesound_list_view);
515 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
517 vbox = manage(new VBox);
518 vbox->pack_start (*passbox, PACK_SHRINK);
519 vbox->pack_start(*scroll);
521 //vbox->pack_start (freesound_list_view);
523 freesound_list_view.append_column(_("Paths"), freesound_list_columns.pathname);
524 freesound_list_view.get_selection()->signal_changed().connect(mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
526 //freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
527 freesound_list_view.signal_row_activated().connect (mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
528 freesound_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
529 freesound_entry.signal_activate().connect(mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
530 notebook.append_page (*vbox, _("Search Freesound"));
535 notebook.set_size_request (500, -1);
539 add_button (Stock::CANCEL, RESPONSE_CANCEL);
540 add_button (Stock::APPLY, RESPONSE_APPLY);
541 add_button (Stock::OK, RESPONSE_OK);
545 SoundFileBrowser::~SoundFileBrowser ()
547 persistent_folder = chooser.get_current_folder();
552 SoundFileBrowser::on_show ()
554 ArdourDialog::on_show ();
559 SoundFileBrowser::clear_selection ()
561 chooser.unselect_all ();
562 found_list_view.get_selection()->unselect_all ();
566 SoundFileBrowser::chooser_file_activated ()
572 SoundFileBrowser::found_list_view_activated (const TreeModel::Path& path, TreeViewColumn* col)
578 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path& path, TreeViewColumn* col)
584 SoundFileBrowser::set_session (Session* s)
586 ArdourDialog::set_session (s);
587 preview.set_session (s);
591 remove_gain_meter ();
596 SoundFileBrowser::add_gain_meter ()
600 gm = new GainMeter (*session);
601 gm->set_io (session->the_auditioner());
603 meter_packer.set_border_width (12);
604 meter_packer.pack_start (*gm, false, true);
605 hpacker.pack_end (meter_packer, false, false);
606 meter_packer.show_all ();
611 SoundFileBrowser::remove_gain_meter ()
614 meter_packer.remove (*gm);
615 hpacker.remove (meter_packer);
622 SoundFileBrowser::start_metering ()
624 metering_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun(*this, &SoundFileBrowser::meter));
628 SoundFileBrowser::stop_metering ()
630 metering_connection.disconnect();
634 SoundFileBrowser::meter ()
636 if (is_mapped () && session && gm) {
637 gm->update_meters ();
642 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
644 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
648 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
650 return SMFSource::safe_midi_file_extension (filter_info.filename);
654 SoundFileBrowser::update_preview ()
656 if (preview.setup_labels (chooser.get_filename())) {
657 if (preview.autoplay()) {
658 Glib::signal_idle().connect (mem_fun (preview, &SoundFileBox::audition_oneshot));
664 SoundFileBrowser::found_list_view_selected ()
666 if (!reset_options ()) {
667 set_response_sensitive (RESPONSE_OK, false);
671 TreeView::Selection::ListHandle_Path rows = found_list_view.get_selection()->get_selected_rows ();
674 TreeIter iter = found_list->get_iter(*rows.begin());
675 file = (*iter)[found_list_columns.pathname];
676 chooser.set_filename (file);
677 set_response_sensitive (RESPONSE_OK, true);
679 set_response_sensitive (RESPONSE_OK, false);
682 preview.setup_labels (file);
687 SoundFileBrowser::freesound_list_view_selected ()
689 if (!reset_options ()) {
690 set_response_sensitive (RESPONSE_OK, false);
694 TreeView::Selection::ListHandle_Path rows = freesound_list_view.get_selection()->get_selected_rows ();
697 TreeIter iter = freesound_list->get_iter(*rows.begin());
698 file = (*iter)[freesound_list_columns.pathname];
699 chooser.set_filename (file);
700 set_response_sensitive (RESPONSE_OK, true);
702 set_response_sensitive (RESPONSE_OK, false);
705 preview.setup_labels (file);
710 SoundFileBrowser::found_search_clicked ()
712 string tag_string = found_entry.get_text ();
716 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
717 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
721 vector<string> results;
722 Library->search_members_and (results, tags);
725 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
726 TreeModel::iterator new_row = found_list->append();
727 TreeModel::Row row = *new_row;
728 string path = Glib::filename_from_uri (string ("file:") + *i);
729 row[found_list_columns.pathname] = path;
734 freesound_search_thread_entry (void* arg)
736 PBD::notify_gui_about_thread_creation (pthread_self(), X_("Freesound Search"));
738 static_cast<SoundFileBrowser*>(arg)->freesound_search_thread ();
743 bool searching = false;
744 bool canceling = false;
747 SoundFileBrowser::freesound_search_clicked ()
749 if (canceling) //already canceling, button does nothing
753 freesound_search_btn.set_label(_("Cancelling.."));
757 freesound_search_btn.set_label(_("Cancel"));
758 pthread_t freesound_thr;
759 pthread_create_and_store ("freesound_search", &freesound_thr, 0, freesound_search_thread_entry, this);
764 SoundFileBrowser::freesound_search_thread()
767 freesound_list->clear();
770 path = Glib::get_home_dir();
771 path += "/Freesound/";
772 Mootcher theMootcher(path.c_str());
774 string name_string = freesound_name_entry.get_text ();
775 string pass_string = freesound_pass_entry.get_text ();
776 string search_string = freesound_entry.get_text ();
778 if ( theMootcher.doLogin( name_string, pass_string ) ) {
780 string theString = theMootcher.searchText(search_string);
783 doc.read_buffer( theString );
784 XMLNode *root = doc.root();
786 if (root==NULL) return;
788 if ( strcmp(root->name().c_str(), "freesound") == 0) {
791 XMLNodeList children = root->children();
792 XMLNodeConstIterator niter;
793 for (niter = children.begin(); niter != children.end() && !canceling; ++niter) {
795 if( strcmp( node->name().c_str(), "sample") == 0 ){
796 XMLProperty *prop=node->property ("id");
797 string filename = theMootcher.getFile( prop->value().c_str() );
798 if ( filename != "" ) {
799 TreeModel::iterator new_row = freesound_list->append();
800 TreeModel::Row row = *new_row;
801 string path = Glib::filename_from_uri (string ("file:") + filename);
802 row[freesound_list_columns.pathname] = path;
811 freesound_search_btn.set_label(_("Start Downloading"));
816 SoundFileBrowser::get_paths ()
818 vector<ustring> results;
820 int n = notebook.get_current_page ();
823 vector<ustring> filenames = chooser.get_filenames();
824 vector<ustring>::iterator i;
826 for (i = filenames.begin(); i != filenames.end(); ++i) {
828 if ((!stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
829 results.push_back (*i);
835 typedef TreeView::Selection::ListHandle_Path ListPath;
837 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
838 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
839 TreeIter iter = found_list->get_iter(*i);
840 ustring str = (*iter)[found_list_columns.pathname];
842 results.push_back (str);
846 typedef TreeView::Selection::ListHandle_Path ListPath;
848 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
849 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
850 TreeIter iter = freesound_list->get_iter(*i);
851 ustring str = (*iter)[freesound_list_columns.pathname];
853 results.push_back (str);
861 SoundFileOmega::reset_options_noret ()
863 if (!resetting_ourselves) {
864 (void) reset_options ();
869 SoundFileOmega::reset_options ()
871 vector<ustring> paths = get_paths ();
875 channel_combo.set_sensitive (false);
876 action_combo.set_sensitive (false);
877 where_combo.set_sensitive (false);
878 copy_files_btn.set_sensitive (false);
884 channel_combo.set_sensitive (true);
885 action_combo.set_sensitive (true);
886 where_combo.set_sensitive (true);
888 /* if we get through this function successfully, this may be
889 reset at the end, once we know if we can use hard links
893 if (Config->get_only_copy_imported_files()) {
894 copy_files_btn.set_sensitive (false);
896 copy_files_btn.set_sensitive (false);
902 bool selection_includes_multichannel;
903 bool selection_can_be_embedded_with_links = check_link_status (*session, paths);
906 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
907 Glib::signal_idle().connect (mem_fun (*this, &SoundFileOmega::bad_file_message));
911 ustring existing_choice;
912 vector<string> action_strings;
914 if (selected_track_cnt > 0) {
915 if (channel_combo.get_active_text().length()) {
916 ImportDisposition id = get_channel_disposition();
919 case Editing::ImportDistinctFiles:
920 if (selected_track_cnt == paths.size()) {
921 action_strings.push_back (importmode2string (ImportToTrack));
925 case Editing::ImportDistinctChannels:
926 /* XXX it would be nice to allow channel-per-selected track
927 but its too hard we don't want to deal with all the
928 different per-file + per-track channel configurations.
933 action_strings.push_back (importmode2string (ImportToTrack));
939 action_strings.push_back (importmode2string (ImportAsTrack));
940 action_strings.push_back (importmode2string (ImportAsRegion));
941 action_strings.push_back (importmode2string (ImportAsTapeTrack));
943 resetting_ourselves = true;
945 existing_choice = action_combo.get_active_text();
947 set_popdown_strings (action_combo, action_strings);
949 /* preserve any existing choice, if possible */
952 if (existing_choice.length()) {
953 vector<string>::iterator x;
954 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
955 if (*x == existing_choice) {
956 action_combo.set_active_text (existing_choice);
960 if (x == action_strings.end()) {
961 action_combo.set_active_text (action_strings.front());
964 action_combo.set_active_text (action_strings.front());
967 resetting_ourselves = false;
969 if ((mode = get_mode()) == ImportAsRegion) {
970 where_combo.set_sensitive (false);
972 where_combo.set_sensitive (true);
975 vector<string> channel_strings;
977 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
978 channel_strings.push_back (_("one track per file"));
980 if (selection_includes_multichannel) {
981 channel_strings.push_back (_("one track per channel"));
984 if (paths.size() > 1) {
985 /* tape tracks are a single region per track, so we cannot
986 sequence multiple files.
988 if (mode != ImportAsTapeTrack) {
989 channel_strings.push_back (_("sequence files"));
992 channel_strings.push_back (_("all files in one region"));
998 channel_strings.push_back (_("one region per file"));
1000 if (selection_includes_multichannel) {
1001 channel_strings.push_back (_("one region per channel"));
1004 if (paths.size() > 1) {
1006 channel_strings.push_back (_("all files in one region"));
1011 existing_choice = channel_combo.get_active_text();
1013 set_popdown_strings (channel_combo, channel_strings);
1015 /* preserve any existing choice, if possible */
1017 if (existing_choice.length()) {
1018 vector<string>::iterator x;
1019 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1020 if (*x == existing_choice) {
1021 channel_combo.set_active_text (existing_choice);
1025 if (x == channel_strings.end()) {
1026 channel_combo.set_active_text (channel_strings.front());
1029 channel_combo.set_active_text (channel_strings.front());
1033 src_combo.set_sensitive (true);
1035 src_combo.set_sensitive (false);
1038 if (Config->get_only_copy_imported_files()) {
1040 if (selection_can_be_embedded_with_links) {
1041 copy_files_btn.set_sensitive (true);
1043 copy_files_btn.set_sensitive (false);
1048 copy_files_btn.set_sensitive (true);
1056 SoundFileOmega::bad_file_message()
1058 MessageDialog msg (*this,
1059 _("One or more of the selected files\ncannot be used by Ardour"),
1064 resetting_ourselves = true;
1065 chooser.unselect_uri (chooser.get_preview_uri());
1066 resetting_ourselves = false;
1072 SoundFileOmega::check_info (const vector<ustring>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1081 multichannel = false;
1083 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1085 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1086 if (info.channels > 1) {
1087 multichannel = true;
1092 if (sz != info.length) {
1097 if ((nframes_t) info.samplerate != session->frame_rate()) {
1101 } else if (SMFSource::safe_midi_file_extension (*i)) {
1103 Evoral::SMFReader reader(*i);
1104 if (reader.num_tracks() > 1) {
1105 multichannel = true; // "channel" == track here...
1108 /* XXX we need err = true handling here in case
1109 we can't check the file
1122 SoundFileOmega::check_link_status (const Session& s, const vector<ustring>& paths)
1124 sys::path path = s.session_directory().sound_path() / "linktest";
1125 string tmpdir = path.to_string();
1128 if (mkdir (tmpdir.c_str(), 0744)) {
1129 if (errno != EEXIST) {
1134 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1136 char tmpc[MAXPATHLEN+1];
1138 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1142 if (link ((*i).c_str(), tmpc)) {
1152 rmdir (tmpdir.c_str());
1156 SoundFileChooser::SoundFileChooser (Gtk::Window& parent, string title, ARDOUR::Session* s)
1157 : SoundFileBrowser (parent, title, s, false)
1159 chooser.set_select_multiple (false);
1160 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1161 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1165 SoundFileChooser::on_hide ()
1167 ArdourDialog::on_hide();
1171 session->cancel_audition();
1176 SoundFileChooser::get_filename ()
1178 vector<ustring> paths;
1180 paths = get_paths ();
1182 if (paths.empty()) {
1186 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1190 return paths.front();
1193 SoundFileOmega::SoundFileOmega (Gtk::Window& parent, string title, ARDOUR::Session* s, int selected_tracks, bool persistent,
1194 Editing::ImportMode mode_hint)
1195 : SoundFileBrowser (parent, title, s, persistent),
1196 copy_files_btn ( _("Copy files to session")),
1197 selected_track_cnt (selected_tracks)
1203 set_size_request (-1, 450);
1205 block_two.set_border_width (12);
1206 block_three.set_border_width (12);
1207 block_four.set_border_width (12);
1209 options.set_spacing (12);
1212 str.push_back (_("use file timestamp"));
1213 str.push_back (_("at edit point"));
1214 str.push_back (_("at playhead"));
1215 str.push_back (_("at session start"));
1216 set_popdown_strings (where_combo, str);
1217 where_combo.set_active_text (str.front());
1219 Label* l = manage (new Label);
1220 l->set_text (_("Add files:"));
1222 hbox = manage (new HBox);
1223 hbox->set_border_width (12);
1224 hbox->set_spacing (6);
1225 hbox->pack_start (*l, false, false);
1226 hbox->pack_start (action_combo, false, false);
1227 vbox = manage (new VBox);
1228 vbox->pack_start (*hbox, false, false);
1229 options.pack_start (*vbox, false, false);
1231 /* dummy entry for action combo so that it doesn't look odd if we
1232 come up with no tracks selected.
1236 str.push_back (importmode2string (mode_hint));
1237 set_popdown_strings (action_combo, str);
1238 action_combo.set_active_text (str.front());
1239 action_combo.set_sensitive (false);
1241 l = manage (new Label);
1242 l->set_text (_("Insert:"));
1244 hbox = manage (new HBox);
1245 hbox->set_border_width (12);
1246 hbox->set_spacing (6);
1247 hbox->pack_start (*l, false, false);
1248 hbox->pack_start (where_combo, false, false);
1249 vbox = manage (new VBox);
1250 vbox->pack_start (*hbox, false, false);
1251 options.pack_start (*vbox, false, false);
1254 l = manage (new Label);
1255 l->set_text (_("Mapping:"));
1257 hbox = manage (new HBox);
1258 hbox->set_border_width (12);
1259 hbox->set_spacing (6);
1260 hbox->pack_start (*l, false, false);
1261 hbox->pack_start (channel_combo, false, false);
1262 vbox = manage (new VBox);
1263 vbox->pack_start (*hbox, false, false);
1264 options.pack_start (*vbox, false, false);
1267 str.push_back (_("one track per file"));
1268 set_popdown_strings (channel_combo, str);
1269 channel_combo.set_active_text (str.front());
1270 channel_combo.set_sensitive (false);
1272 l = manage (new Label);
1273 l->set_text (_("Conversion Quality:"));
1275 hbox = manage (new HBox);
1276 hbox->set_border_width (12);
1277 hbox->set_spacing (6);
1278 hbox->pack_start (*l, false, false);
1279 hbox->pack_start (src_combo, false, false);
1280 vbox = manage (new VBox);
1281 vbox->pack_start (*hbox, false, false);
1282 options.pack_start (*vbox, false, false);
1285 str.push_back (_("Best"));
1286 str.push_back (_("Good"));
1287 str.push_back (_("Quick"));
1288 str.push_back (_("Fast"));
1289 str.push_back (_("Fastest"));
1291 set_popdown_strings (src_combo, str);
1292 src_combo.set_active_text (str.front());
1293 src_combo.set_sensitive (false);
1297 action_combo.signal_changed().connect (mem_fun (*this, &SoundFileOmega::reset_options_noret));
1299 copy_files_btn.set_active (true);
1301 block_four.pack_start (copy_files_btn, false, false);
1303 options.pack_start (block_four, false, false);
1305 get_vbox()->pack_start (options, false, false);
1307 /* setup disposition map */
1309 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1310 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1311 disposition_map.insert (pair<ustring,ImportDisposition>(_("merge files"), ImportMergeFiles));
1312 disposition_map.insert (pair<ustring,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1314 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1315 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1316 disposition_map.insert (pair<ustring,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1318 chooser.signal_selection_changed().connect (mem_fun (*this, &SoundFileOmega::file_selection_changed));
1322 SoundFileOmega::set_mode (ImportMode mode)
1324 action_combo.set_active_text (importmode2string (mode));
1328 SoundFileOmega::get_mode () const
1330 return string2importmode (action_combo.get_active_text());
1334 SoundFileOmega::on_hide ()
1336 ArdourDialog::on_hide();
1338 session->cancel_audition();
1343 SoundFileOmega::get_position() const
1345 ustring str = where_combo.get_active_text();
1347 if (str == _("use file timestamp")) {
1348 return ImportAtTimestamp;
1349 } else if (str == _("at edit point")) {
1350 return ImportAtEditPoint;
1351 } else if (str == _("at playhead")) {
1352 return ImportAtPlayhead;
1354 return ImportAtStart;
1359 SoundFileOmega::get_src_quality() const
1361 ustring str = where_combo.get_active_text();
1363 if (str == _("Best")) {
1365 } else if (str == _("Good")) {
1367 } else if (str == _("Quick")) {
1369 } else if (str == _("Fast")) {
1377 SoundFileOmega::get_channel_disposition () const
1379 /* we use a map here because the channel combo can contain different strings
1380 depending on the state of the other combos. the map contains all possible strings
1381 and the ImportDisposition enum that corresponds to it.
1384 ustring str = channel_combo.get_active_text();
1385 DispositionMap::const_iterator x = disposition_map.find (str);
1387 if (x == disposition_map.end()) {
1388 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1396 SoundFileOmega::reset (int selected_tracks)
1398 selected_track_cnt = selected_tracks;
1403 SoundFileOmega::file_selection_changed ()
1405 if (resetting_ourselves) {
1409 if (!reset_options ()) {
1410 set_response_sensitive (RESPONSE_OK, false);
1412 if (chooser.get_filenames().size() > 0) {
1413 set_response_sensitive (RESPONSE_OK, true);
1415 set_response_sensitive (RESPONSE_OK, false);