2 Copyright (C) 2005-2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include <sys/param.h>
28 #include <gtkmm/box.h>
29 #include <gtkmm/stock.h>
30 #include <glibmm/fileutils.h>
32 #include "pbd/convert.h"
33 #include "pbd/tokenizer.h"
34 #include "pbd/enumwriter.h"
35 #include "pbd/pthread_utils.h"
36 #include "pbd/xml++.h"
38 #include <gtkmm2ext/utils.h>
40 #include "evoral/SMF.hpp"
42 #include "ardour/amp.h"
43 #include "ardour/audio_library.h"
44 #include "ardour/auditioner.h"
45 #include "ardour/audioregion.h"
46 #include "ardour/audiofilesource.h"
47 #include "ardour/smf_source.h"
48 #include "ardour/region_factory.h"
49 #include "ardour/source_factory.h"
50 #include "ardour/session.h"
51 #include "ardour/session_directory.h"
52 #include "ardour/profile.h"
54 #include "ardour_ui.h"
56 #include "gui_thread.h"
61 #include "gain_meter.h"
64 #include "sfdb_freesound_mootcher.h"
69 using namespace ARDOUR;
73 using namespace Gtkmm2ext;
74 using namespace Editing;
78 ustring SoundFileBrowser::persistent_folder;
81 string2importmode (string str)
83 if (str == _("as new tracks")) {
85 } else if (str == _("to selected tracks")) {
87 } else if (str == _("to region list")) {
88 return ImportAsRegion;
89 } else if (str == _("as new tape tracks")) {
90 return ImportAsTapeTrack;
93 warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
99 importmode2string (ImportMode mode)
103 return _("as new tracks");
105 return _("to selected tracks");
107 return _("to region list");
108 case ImportAsTapeTrack:
109 return _("as new tape tracks");
112 return _("as new tracks");
115 SoundFileBox::SoundFileBox (bool persistent)
118 length_clock ("sfboxLengthClock", !persistent, "EditCursorClock", false, true, false),
119 timecode_clock ("sfboxTimecodeClock", !persistent, "EditCursorClock", false, false, false),
121 autoplay_btn (_("Auto-play"))
124 set_name (X_("SoundFileBox"));
125 set_size_request (300, -1);
127 preview_label.set_markup (_("<b>Sound File Information</b>"));
129 border_frame.set_label_widget (preview_label);
130 border_frame.add (main_box);
132 pack_start (border_frame, true, true);
133 set_border_width (6);
135 main_box.set_border_width (6);
137 length.set_text (_("Length:"));
138 length.set_alignment (1, 0.5);
139 timecode.set_text (_("Timestamp:"));
140 timecode.set_alignment (1, 0.5);
141 format.set_text (_("Format:"));
142 format.set_alignment (1, 0.5);
143 channels.set_text (_("Channels:"));
144 channels.set_alignment (1, 0.5);
145 samplerate.set_text (_("Sample rate:"));
146 samplerate.set_alignment (1, 0.5);
148 format_text.set_max_width_chars (8);
149 format_text.set_ellipsize (Pango::ELLIPSIZE_END);
150 format_text.set_alignment (0, 1);
152 table.set_col_spacings (6);
153 table.set_homogeneous (false);
154 table.set_row_spacings (6);
156 table.attach (channels, 0, 1, 0, 1, FILL, FILL);
157 table.attach (samplerate, 0, 1, 1, 2, FILL, FILL);
158 table.attach (format, 0, 1, 2, 4, FILL, FILL);
159 table.attach (length, 0, 1, 4, 5, FILL, FILL);
160 table.attach (timecode, 0, 1, 5, 6, FILL, FILL);
162 table.attach (channels_value, 1, 2, 0, 1, FILL, FILL);
163 table.attach (samplerate_value, 1, 2, 1, 2, FILL, FILL);
164 table.attach (format_text, 1, 2, 2, 4, FILL, FILL);
165 table.attach (length_clock, 1, 2, 4, 5, FILL, FILL);
166 table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL);
168 length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock.mode());
169 timecode_clock.set_mode (AudioClock::SMPTE);
171 main_box.pack_start (table, false, false);
173 tags_entry.set_editable (true);
174 tags_entry.signal_focus_out_event().connect (mem_fun (*this, &SoundFileBox::tags_entry_left));
176 Label* label = manage (new Label (_("Tags:")));
177 label->set_alignment (0.0f, 0.5f);
178 main_box.pack_start (*label, false, false);
179 main_box.pack_start (tags_entry, true, true);
181 main_box.pack_start (bottom_box, false, false);
183 play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
184 play_btn.set_label (_("Play"));
186 stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
187 stop_btn.set_label (_("Stop"));
189 bottom_box.set_homogeneous (false);
190 bottom_box.set_spacing (6);
191 bottom_box.pack_start(play_btn, true, true);
192 bottom_box.pack_start(stop_btn, true, true);
193 bottom_box.pack_start(autoplay_btn, false, false);
195 play_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::audition));
196 stop_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::stop_audition));
198 channels_value.set_alignment (0.0f, 0.5f);
199 samplerate_value.set_alignment (0.0f, 0.5f);
203 SoundFileBox::set_session(Session* s)
208 play_btn.set_sensitive (false);
209 stop_btn.set_sensitive (false);
213 length_clock.set_session (s);
214 timecode_clock.set_session (s);
218 SoundFileBox::setup_labels (const ustring& filename)
221 // save existing tags
229 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
231 preview_label.set_markup (_("<b>Sound File Information</b>"));
232 format_text.set_text ("");
233 channels_value.set_text ("");
234 samplerate_value.set_text ("");
235 tags_entry.get_buffer()->set_text ("");
237 length_clock.set (0);
238 timecode_clock.set (0);
240 tags_entry.set_sensitive (false);
241 play_btn.set_sensitive (false);
246 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::path_get_basename (filename)));
247 std::string n = sf_info.format_name;
248 if (n.substr (0, 8) == X_("Format: ")) {
251 format_text.set_text (n);
252 channels_value.set_text (to_string (sf_info.channels, std::dec));
254 if (_session && sf_info.samplerate != _session->frame_rate()) {
255 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
256 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
257 samplerate_value.set_name ("NewSessionSR1Label");
258 samplerate.set_name ("NewSessionSR1Label");
260 samplerate.set_text (_("Sample rate:"));
261 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
262 samplerate_value.set_name ("NewSessionSR2Label");
263 samplerate.set_name ("NewSessionSR2Label");
266 nframes_t const nfr = _session ? _session->nominal_frame_rate() : 25;
267 double src_coef = (double) nfr / sf_info.samplerate;
269 length_clock.set (sf_info.length * src_coef + 0.5, true);
270 timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
272 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
274 vector<string> tags = Library->get_tags (string ("//") + filename);
276 stringstream tag_string;
277 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
278 if (i != tags.begin()) {
283 tags_entry.get_buffer()->set_text (tag_string.str());
285 tags_entry.set_sensitive (true);
287 play_btn.set_sensitive (true);
294 SoundFileBox::autoplay() const
296 return autoplay_btn.get_active();
300 SoundFileBox::audition_oneshot()
307 SoundFileBox::audition ()
313 _session->cancel_audition();
315 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
316 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
320 boost::shared_ptr<Region> r;
322 boost::shared_ptr<AudioFileSource> afs;
323 bool old_sbp = AudioSource::get_build_peakfiles ();
325 /* don't even think of building peakfiles for these files */
327 AudioSource::set_build_peakfiles (false);
329 for (int n = 0; n < sf_info.channels; ++n) {
331 afs = boost::dynamic_pointer_cast<AudioFileSource> (
332 SourceFactory::createReadable (DataType::AUDIO, *_session,
333 path, false, n, Source::Flag (0), false));
335 srclist.push_back(afs);
337 } catch (failed_constructor& err) {
338 error << _("Could not access soundfile: ") << path << endmsg;
339 AudioSource::set_build_peakfiles (old_sbp);
344 AudioSource::set_build_peakfiles (old_sbp);
346 if (srclist.empty()) {
350 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
351 string rname = region_name_from_path (afs->path(), false);
352 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, 0,
353 srclist[0]->length(srclist[0]->timeline_position()),
354 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);
599 boost::shared_ptr<Route> r = session->the_auditioner ();
601 gm->set_controls (r, r->shared_peak_meter(), r->gain_control(), r->amp());
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)) {
1105 if (reader.num_tracks() > 1) {
1106 multichannel = true; // "channel" == track here...
1109 /* XXX we need err = true handling here in case
1110 we can't check the file
1123 SoundFileOmega::check_link_status (const Session& s, const vector<ustring>& paths)
1125 sys::path path = s.session_directory().sound_path() / "linktest";
1126 string tmpdir = path.to_string();
1129 if (mkdir (tmpdir.c_str(), 0744)) {
1130 if (errno != EEXIST) {
1135 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1137 char tmpc[MAXPATHLEN+1];
1139 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1143 if (link ((*i).c_str(), tmpc)) {
1153 rmdir (tmpdir.c_str());
1157 SoundFileChooser::SoundFileChooser (Gtk::Window& parent, string title, ARDOUR::Session* s)
1158 : SoundFileBrowser (parent, title, s, false)
1160 chooser.set_select_multiple (false);
1161 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1162 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1166 SoundFileChooser::on_hide ()
1168 ArdourDialog::on_hide();
1172 session->cancel_audition();
1177 SoundFileChooser::get_filename ()
1179 vector<ustring> paths;
1181 paths = get_paths ();
1183 if (paths.empty()) {
1187 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1191 return paths.front();
1194 SoundFileOmega::SoundFileOmega (Gtk::Window& parent, string title, ARDOUR::Session* s, int selected_tracks, bool persistent,
1195 Editing::ImportMode mode_hint)
1196 : SoundFileBrowser (parent, title, s, persistent),
1197 copy_files_btn ( _("Copy files to session")),
1198 selected_track_cnt (selected_tracks)
1204 set_size_request (-1, 450);
1206 block_two.set_border_width (12);
1207 block_three.set_border_width (12);
1208 block_four.set_border_width (12);
1210 options.set_spacing (12);
1213 str.push_back (_("use file timestamp"));
1214 str.push_back (_("at edit point"));
1215 str.push_back (_("at playhead"));
1216 str.push_back (_("at session start"));
1217 set_popdown_strings (where_combo, str);
1218 where_combo.set_active_text (str.front());
1220 Label* l = manage (new Label);
1221 l->set_text (_("Add files:"));
1223 hbox = manage (new HBox);
1224 hbox->set_border_width (12);
1225 hbox->set_spacing (6);
1226 hbox->pack_start (*l, false, false);
1227 hbox->pack_start (action_combo, false, false);
1228 vbox = manage (new VBox);
1229 vbox->pack_start (*hbox, false, false);
1230 options.pack_start (*vbox, false, false);
1232 /* dummy entry for action combo so that it doesn't look odd if we
1233 come up with no tracks selected.
1237 str.push_back (importmode2string (mode_hint));
1238 set_popdown_strings (action_combo, str);
1239 action_combo.set_active_text (str.front());
1240 action_combo.set_sensitive (false);
1242 l = manage (new Label);
1243 l->set_text (_("Insert:"));
1245 hbox = manage (new HBox);
1246 hbox->set_border_width (12);
1247 hbox->set_spacing (6);
1248 hbox->pack_start (*l, false, false);
1249 hbox->pack_start (where_combo, false, false);
1250 vbox = manage (new VBox);
1251 vbox->pack_start (*hbox, false, false);
1252 options.pack_start (*vbox, false, false);
1255 l = manage (new Label);
1256 l->set_text (_("Mapping:"));
1258 hbox = manage (new HBox);
1259 hbox->set_border_width (12);
1260 hbox->set_spacing (6);
1261 hbox->pack_start (*l, false, false);
1262 hbox->pack_start (channel_combo, false, false);
1263 vbox = manage (new VBox);
1264 vbox->pack_start (*hbox, false, false);
1265 options.pack_start (*vbox, false, false);
1268 str.push_back (_("one track per file"));
1269 set_popdown_strings (channel_combo, str);
1270 channel_combo.set_active_text (str.front());
1271 channel_combo.set_sensitive (false);
1273 l = manage (new Label);
1274 l->set_text (_("Conversion quality:"));
1276 hbox = manage (new HBox);
1277 hbox->set_border_width (12);
1278 hbox->set_spacing (6);
1279 hbox->pack_start (*l, false, false);
1280 hbox->pack_start (src_combo, false, false);
1281 vbox = manage (new VBox);
1282 vbox->pack_start (*hbox, false, false);
1283 options.pack_start (*vbox, false, false);
1286 str.push_back (_("Best"));
1287 str.push_back (_("Good"));
1288 str.push_back (_("Quick"));
1289 str.push_back (_("Fast"));
1290 str.push_back (_("Fastest"));
1292 set_popdown_strings (src_combo, str);
1293 src_combo.set_active_text (str.front());
1294 src_combo.set_sensitive (false);
1298 action_combo.signal_changed().connect (mem_fun (*this, &SoundFileOmega::reset_options_noret));
1300 copy_files_btn.set_active (true);
1302 block_four.pack_start (copy_files_btn, false, false);
1304 options.pack_start (block_four, false, false);
1306 get_vbox()->pack_start (options, false, false);
1308 /* setup disposition map */
1310 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1311 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1312 disposition_map.insert (pair<ustring,ImportDisposition>(_("merge files"), ImportMergeFiles));
1313 disposition_map.insert (pair<ustring,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1315 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1316 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1317 disposition_map.insert (pair<ustring,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1319 chooser.signal_selection_changed().connect (mem_fun (*this, &SoundFileOmega::file_selection_changed));
1323 SoundFileOmega::set_mode (ImportMode mode)
1325 action_combo.set_active_text (importmode2string (mode));
1329 SoundFileOmega::get_mode () const
1331 return string2importmode (action_combo.get_active_text());
1335 SoundFileOmega::on_hide ()
1337 ArdourDialog::on_hide();
1339 session->cancel_audition();
1344 SoundFileOmega::get_position() const
1346 ustring str = where_combo.get_active_text();
1348 if (str == _("use file timestamp")) {
1349 return ImportAtTimestamp;
1350 } else if (str == _("at edit point")) {
1351 return ImportAtEditPoint;
1352 } else if (str == _("at playhead")) {
1353 return ImportAtPlayhead;
1355 return ImportAtStart;
1360 SoundFileOmega::get_src_quality() const
1362 ustring str = where_combo.get_active_text();
1364 if (str == _("Best")) {
1366 } else if (str == _("Good")) {
1368 } else if (str == _("Quick")) {
1370 } else if (str == _("Fast")) {
1378 SoundFileOmega::get_channel_disposition () const
1380 /* we use a map here because the channel combo can contain different strings
1381 depending on the state of the other combos. the map contains all possible strings
1382 and the ImportDisposition enum that corresponds to it.
1385 ustring str = channel_combo.get_active_text();
1386 DispositionMap::const_iterator x = disposition_map.find (str);
1388 if (x == disposition_map.end()) {
1389 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1397 SoundFileOmega::reset (int selected_tracks)
1399 selected_track_cnt = selected_tracks;
1404 SoundFileOmega::file_selection_changed ()
1406 if (resetting_ourselves) {
1410 if (!reset_options ()) {
1411 set_response_sensitive (RESPONSE_OK, false);
1413 if (chooser.get_filenames().size() > 0) {
1414 set_response_sensitive (RESPONSE_OK, true);
1416 set_response_sensitive (RESPONSE_OK, false);