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 ()
597 gm = new GainMeter (*session);
598 gm->set_io (session->the_auditioner());
600 meter_packer.set_border_width (12);
601 meter_packer.pack_start (*gm, false, true);
602 hpacker.pack_end (meter_packer, false, false);
603 meter_packer.show_all ();
608 SoundFileBrowser::remove_gain_meter ()
611 meter_packer.remove (*gm);
612 hpacker.remove (meter_packer);
619 SoundFileBrowser::start_metering ()
621 metering_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun(*this, &SoundFileBrowser::meter));
625 SoundFileBrowser::stop_metering ()
627 metering_connection.disconnect();
631 SoundFileBrowser::meter ()
633 if (is_mapped () && session && gm) {
634 gm->update_meters ();
639 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
641 return AudioFileSource::safe_file_extension (filter_info.filename);
645 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
647 return SMFSource::safe_file_extension (filter_info.filename);
651 SoundFileBrowser::update_preview ()
653 if (preview.setup_labels (chooser.get_filename())) {
654 if (preview.autoplay()) {
655 Glib::signal_idle().connect (mem_fun (preview, &SoundFileBox::audition_oneshot));
661 SoundFileBrowser::found_list_view_selected ()
663 if (!reset_options ()) {
664 set_response_sensitive (RESPONSE_OK, false);
668 TreeView::Selection::ListHandle_Path rows = found_list_view.get_selection()->get_selected_rows ();
671 TreeIter iter = found_list->get_iter(*rows.begin());
672 file = (*iter)[found_list_columns.pathname];
673 chooser.set_filename (file);
674 set_response_sensitive (RESPONSE_OK, true);
676 set_response_sensitive (RESPONSE_OK, false);
679 preview.setup_labels (file);
684 SoundFileBrowser::freesound_list_view_selected ()
686 if (!reset_options ()) {
687 set_response_sensitive (RESPONSE_OK, false);
691 TreeView::Selection::ListHandle_Path rows = freesound_list_view.get_selection()->get_selected_rows ();
694 TreeIter iter = freesound_list->get_iter(*rows.begin());
695 file = (*iter)[freesound_list_columns.pathname];
696 chooser.set_filename (file);
697 set_response_sensitive (RESPONSE_OK, true);
699 set_response_sensitive (RESPONSE_OK, false);
702 preview.setup_labels (file);
707 SoundFileBrowser::found_search_clicked ()
709 string tag_string = found_entry.get_text ();
713 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
714 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
718 vector<string> results;
719 Library->search_members_and (results, tags);
722 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
723 TreeModel::iterator new_row = found_list->append();
724 TreeModel::Row row = *new_row;
725 string path = Glib::filename_from_uri (string ("file:") + *i);
726 row[found_list_columns.pathname] = path;
731 freesound_search_thread_entry (void* arg)
733 PBD::notify_gui_about_thread_creation (pthread_self(), X_("Freesound Search"));
735 static_cast<SoundFileBrowser*>(arg)->freesound_search_thread ();
740 bool searching = false;
741 bool canceling = false;
744 SoundFileBrowser::freesound_search_clicked ()
746 if (canceling) //already canceling, button does nothing
750 freesound_search_btn.set_label(_("Cancelling.."));
754 freesound_search_btn.set_label(_("Cancel"));
755 pthread_t freesound_thr;
756 pthread_create_and_store ("freesound_search", &freesound_thr, 0, freesound_search_thread_entry, this);
761 SoundFileBrowser::freesound_search_thread()
764 freesound_list->clear();
767 path = Glib::get_home_dir();
768 path += "/Freesound/";
769 Mootcher theMootcher(path.c_str());
771 string name_string = freesound_name_entry.get_text ();
772 string pass_string = freesound_pass_entry.get_text ();
773 string search_string = freesound_entry.get_text ();
775 if ( theMootcher.doLogin( name_string, pass_string ) ) {
777 string theString = theMootcher.searchText(search_string);
780 doc.read_buffer( theString );
781 XMLNode *root = doc.root();
783 if (root==NULL) return;
785 if ( strcmp(root->name().c_str(), "freesound") == 0) {
788 XMLNodeList children = root->children();
789 XMLNodeConstIterator niter;
790 for (niter = children.begin(); niter != children.end() && !canceling; ++niter) {
792 if( strcmp( node->name().c_str(), "sample") == 0 ){
793 XMLProperty *prop=node->property ("id");
794 string filename = theMootcher.getFile( prop->value().c_str() );
795 if ( filename != "" ) {
796 TreeModel::iterator new_row = freesound_list->append();
797 TreeModel::Row row = *new_row;
798 string path = Glib::filename_from_uri (string ("file:") + filename);
799 row[freesound_list_columns.pathname] = path;
808 freesound_search_btn.set_label(_("Start Downloading"));
813 SoundFileBrowser::get_paths ()
815 vector<ustring> results;
817 int n = notebook.get_current_page ();
820 vector<ustring> filenames = chooser.get_filenames();
821 vector<ustring>::iterator i;
823 for (i = filenames.begin(); i != filenames.end(); ++i) {
825 if ((!stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
826 results.push_back (*i);
832 typedef TreeView::Selection::ListHandle_Path ListPath;
834 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
835 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
836 TreeIter iter = found_list->get_iter(*i);
837 ustring str = (*iter)[found_list_columns.pathname];
839 results.push_back (str);
843 typedef TreeView::Selection::ListHandle_Path ListPath;
845 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
846 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
847 TreeIter iter = freesound_list->get_iter(*i);
848 ustring str = (*iter)[freesound_list_columns.pathname];
850 results.push_back (str);
858 SoundFileOmega::reset_options_noret ()
860 if (!resetting_ourselves) {
861 (void) reset_options ();
866 SoundFileOmega::reset_options ()
868 vector<ustring> paths = get_paths ();
872 channel_combo.set_sensitive (false);
873 action_combo.set_sensitive (false);
874 where_combo.set_sensitive (false);
875 copy_files_btn.set_sensitive (false);
881 channel_combo.set_sensitive (true);
882 action_combo.set_sensitive (true);
883 where_combo.set_sensitive (true);
885 /* if we get through this function successfully, this may be
886 reset at the end, once we know if we can use hard links
890 if (Config->get_only_copy_imported_files()) {
891 copy_files_btn.set_sensitive (false);
893 copy_files_btn.set_sensitive (false);
899 bool selection_includes_multichannel;
900 bool selection_can_be_embedded_with_links = check_link_status (*session, paths);
903 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
904 Glib::signal_idle().connect (mem_fun (*this, &SoundFileOmega::bad_file_message));
908 ustring existing_choice;
909 vector<string> action_strings;
911 if (selected_track_cnt > 0) {
912 if (channel_combo.get_active_text().length()) {
913 ImportDisposition id = get_channel_disposition();
916 case Editing::ImportDistinctFiles:
917 if (selected_track_cnt == paths.size()) {
918 action_strings.push_back (importmode2string (ImportToTrack));
922 case Editing::ImportDistinctChannels:
923 /* XXX it would be nice to allow channel-per-selected track
924 but its too hard we don't want to deal with all the
925 different per-file + per-track channel configurations.
930 action_strings.push_back (importmode2string (ImportToTrack));
936 action_strings.push_back (importmode2string (ImportAsTrack));
937 action_strings.push_back (importmode2string (ImportAsRegion));
938 action_strings.push_back (importmode2string (ImportAsTapeTrack));
940 resetting_ourselves = true;
942 existing_choice = action_combo.get_active_text();
944 set_popdown_strings (action_combo, action_strings);
946 /* preserve any existing choice, if possible */
949 if (existing_choice.length()) {
950 vector<string>::iterator x;
951 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
952 if (*x == existing_choice) {
953 action_combo.set_active_text (existing_choice);
957 if (x == action_strings.end()) {
958 action_combo.set_active_text (action_strings.front());
961 action_combo.set_active_text (action_strings.front());
964 resetting_ourselves = false;
966 if ((mode = get_mode()) == ImportAsRegion) {
967 where_combo.set_sensitive (false);
969 where_combo.set_sensitive (true);
972 vector<string> channel_strings;
974 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
975 channel_strings.push_back (_("one track per file"));
977 if (selection_includes_multichannel) {
978 channel_strings.push_back (_("one track per channel"));
981 if (paths.size() > 1) {
982 /* tape tracks are a single region per track, so we cannot
983 sequence multiple files.
985 if (mode != ImportAsTapeTrack) {
986 channel_strings.push_back (_("sequence files"));
989 channel_strings.push_back (_("all files in one region"));
995 channel_strings.push_back (_("one region per file"));
997 if (selection_includes_multichannel) {
998 channel_strings.push_back (_("one region per channel"));
1001 if (paths.size() > 1) {
1003 channel_strings.push_back (_("all files in one region"));
1008 existing_choice = channel_combo.get_active_text();
1010 set_popdown_strings (channel_combo, channel_strings);
1012 /* preserve any existing choice, if possible */
1014 if (existing_choice.length()) {
1015 vector<string>::iterator x;
1016 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1017 if (*x == existing_choice) {
1018 channel_combo.set_active_text (existing_choice);
1022 if (x == channel_strings.end()) {
1023 channel_combo.set_active_text (channel_strings.front());
1026 channel_combo.set_active_text (channel_strings.front());
1030 src_combo.set_sensitive (true);
1032 src_combo.set_sensitive (false);
1035 if (Config->get_only_copy_imported_files()) {
1037 if (selection_can_be_embedded_with_links) {
1038 copy_files_btn.set_sensitive (true);
1040 copy_files_btn.set_sensitive (false);
1045 copy_files_btn.set_sensitive (true);
1053 SoundFileOmega::bad_file_message()
1055 MessageDialog msg (*this,
1056 _("One or more of the selected files\ncannot be used by Ardour"),
1061 resetting_ourselves = true;
1062 chooser.unselect_uri (chooser.get_preview_uri());
1063 resetting_ourselves = false;
1069 SoundFileOmega::check_info (const vector<ustring>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1078 multichannel = false;
1080 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1082 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1083 if (info.channels > 1) {
1084 multichannel = true;
1089 if (sz != info.length) {
1094 if ((nframes_t) info.samplerate != session->frame_rate()) {
1098 } else if (SMFSource::safe_file_extension (*i)) {
1100 Evoral::SMFReader reader(*i);
1101 if (reader.num_tracks() > 1) {
1102 multichannel = true; // "channel" == track here...
1105 /* XXX we need err = true handling here in case
1106 we can't check the file
1119 SoundFileOmega::check_link_status (const Session& s, const vector<ustring>& paths)
1121 sys::path path = s.session_directory().sound_path() / "linktest";
1122 string tmpdir = path.to_string();
1125 if (mkdir (tmpdir.c_str(), 0744)) {
1126 if (errno != EEXIST) {
1131 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1133 char tmpc[MAXPATHLEN+1];
1135 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1139 if (link ((*i).c_str(), tmpc)) {
1149 rmdir (tmpdir.c_str());
1153 SoundFileChooser::SoundFileChooser (Gtk::Window& parent, string title, ARDOUR::Session* s)
1154 : SoundFileBrowser (parent, title, s, false)
1156 chooser.set_select_multiple (false);
1157 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1158 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1162 SoundFileChooser::on_hide ()
1164 ArdourDialog::on_hide();
1168 session->cancel_audition();
1173 SoundFileChooser::get_filename ()
1175 vector<ustring> paths;
1177 paths = get_paths ();
1179 if (paths.empty()) {
1183 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1187 return paths.front();
1190 SoundFileOmega::SoundFileOmega (Gtk::Window& parent, string title, ARDOUR::Session* s, int selected_tracks, bool persistent,
1191 Editing::ImportMode mode_hint)
1192 : SoundFileBrowser (parent, title, s, persistent),
1193 copy_files_btn ( _("Copy files to session")),
1194 selected_track_cnt (selected_tracks)
1200 set_size_request (-1, 450);
1202 block_two.set_border_width (12);
1203 block_three.set_border_width (12);
1204 block_four.set_border_width (12);
1206 options.set_spacing (12);
1209 str.push_back (_("use file timestamp"));
1210 str.push_back (_("at edit point"));
1211 str.push_back (_("at playhead"));
1212 str.push_back (_("at session start"));
1213 set_popdown_strings (where_combo, str);
1214 where_combo.set_active_text (str.front());
1216 Label* l = manage (new Label);
1217 l->set_text (_("Add files:"));
1219 hbox = manage (new HBox);
1220 hbox->set_border_width (12);
1221 hbox->set_spacing (6);
1222 hbox->pack_start (*l, false, false);
1223 hbox->pack_start (action_combo, false, false);
1224 vbox = manage (new VBox);
1225 vbox->pack_start (*hbox, false, false);
1226 options.pack_start (*vbox, false, false);
1228 /* dummy entry for action combo so that it doesn't look odd if we
1229 come up with no tracks selected.
1233 str.push_back (importmode2string (mode_hint));
1234 set_popdown_strings (action_combo, str);
1235 action_combo.set_active_text (str.front());
1236 action_combo.set_sensitive (false);
1238 l = manage (new Label);
1239 l->set_text (_("Insert:"));
1241 hbox = manage (new HBox);
1242 hbox->set_border_width (12);
1243 hbox->set_spacing (6);
1244 hbox->pack_start (*l, false, false);
1245 hbox->pack_start (where_combo, false, false);
1246 vbox = manage (new VBox);
1247 vbox->pack_start (*hbox, false, false);
1248 options.pack_start (*vbox, false, false);
1251 l = manage (new Label);
1252 l->set_text (_("Mapping:"));
1254 hbox = manage (new HBox);
1255 hbox->set_border_width (12);
1256 hbox->set_spacing (6);
1257 hbox->pack_start (*l, false, false);
1258 hbox->pack_start (channel_combo, false, false);
1259 vbox = manage (new VBox);
1260 vbox->pack_start (*hbox, false, false);
1261 options.pack_start (*vbox, false, false);
1264 str.push_back (_("one track per file"));
1265 set_popdown_strings (channel_combo, str);
1266 channel_combo.set_active_text (str.front());
1267 channel_combo.set_sensitive (false);
1269 l = manage (new Label);
1270 l->set_text (_("Conversion Quality:"));
1272 hbox = manage (new HBox);
1273 hbox->set_border_width (12);
1274 hbox->set_spacing (6);
1275 hbox->pack_start (*l, false, false);
1276 hbox->pack_start (src_combo, false, false);
1277 vbox = manage (new VBox);
1278 vbox->pack_start (*hbox, false, false);
1279 options.pack_start (*vbox, false, false);
1282 str.push_back (_("Best"));
1283 str.push_back (_("Good"));
1284 str.push_back (_("Quick"));
1285 str.push_back (_("Fast"));
1286 str.push_back (_("Fastest"));
1288 set_popdown_strings (src_combo, str);
1289 src_combo.set_active_text (str.front());
1290 src_combo.set_sensitive (false);
1294 action_combo.signal_changed().connect (mem_fun (*this, &SoundFileOmega::reset_options_noret));
1296 copy_files_btn.set_active (true);
1298 block_four.pack_start (copy_files_btn, false, false);
1300 options.pack_start (block_four, false, false);
1302 get_vbox()->pack_start (options, false, false);
1304 /* setup disposition map */
1306 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1307 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1308 disposition_map.insert (pair<ustring,ImportDisposition>(_("merge files"), ImportMergeFiles));
1309 disposition_map.insert (pair<ustring,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1311 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1312 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1313 disposition_map.insert (pair<ustring,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1315 chooser.signal_selection_changed().connect (mem_fun (*this, &SoundFileOmega::file_selection_changed));
1319 SoundFileOmega::set_mode (ImportMode mode)
1321 action_combo.set_active_text (importmode2string (mode));
1325 SoundFileOmega::get_mode () const
1327 return string2importmode (action_combo.get_active_text());
1331 SoundFileOmega::on_hide ()
1333 ArdourDialog::on_hide();
1335 session->cancel_audition();
1340 SoundFileOmega::get_position() const
1342 ustring str = where_combo.get_active_text();
1344 if (str == _("use file timestamp")) {
1345 return ImportAtTimestamp;
1346 } else if (str == _("at edit point")) {
1347 return ImportAtEditPoint;
1348 } else if (str == _("at playhead")) {
1349 return ImportAtPlayhead;
1351 return ImportAtStart;
1356 SoundFileOmega::get_src_quality() const
1358 ustring str = where_combo.get_active_text();
1360 if (str == _("Best")) {
1362 } else if (str == _("Good")) {
1364 } else if (str == _("Quick")) {
1366 } else if (str == _("Fast")) {
1374 SoundFileOmega::get_channel_disposition () const
1376 /* we use a map here because the channel combo can contain different strings
1377 depending on the state of the other combos. the map contains all possible strings
1378 and the ImportDisposition enum that corresponds to it.
1381 ustring str = channel_combo.get_active_text();
1382 DispositionMap::const_iterator x = disposition_map.find (str);
1384 if (x == disposition_map.end()) {
1385 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1393 SoundFileOmega::reset (int selected_tracks)
1395 selected_track_cnt = selected_tracks;
1400 SoundFileOmega::file_selection_changed ()
1402 if (resetting_ourselves) {
1406 if (!reset_options ()) {
1407 set_response_sensitive (RESPONSE_OK, false);
1409 if (chooser.get_filenames().size() > 0) {
1410 set_response_sensitive (RESPONSE_OK, true);
1412 set_response_sensitive (RESPONSE_OK, false);