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)
117 length_clock ("sfboxLengthClock", !persistent, "EditCursorClock", false, false, true, false),
118 timecode_clock ("sfboxTimecodeClock", !persistent, "EditCursorClock", false, false, false, false),
120 autoplay_btn (_("Auto-play"))
123 set_name (X_("SoundFileBox"));
124 set_size_request (300, -1);
126 preview_label.set_markup (_("<b>Sound File Information</b>"));
128 border_frame.set_label_widget (preview_label);
129 border_frame.add (main_box);
131 pack_start (border_frame, true, true);
132 set_border_width (6);
134 main_box.set_border_width (6);
136 length.set_text (_("Length:"));
137 length.set_alignment (1, 0.5);
138 timecode.set_text (_("Timestamp:"));
139 timecode.set_alignment (1, 0.5);
140 format.set_text (_("Format:"));
141 format.set_alignment (1, 0.5);
142 channels.set_text (_("Channels:"));
143 channels.set_alignment (1, 0.5);
144 samplerate.set_text (_("Sample rate:"));
145 samplerate.set_alignment (1, 0.5);
147 format_text.set_max_width_chars (8);
148 format_text.set_ellipsize (Pango::ELLIPSIZE_END);
149 format_text.set_alignment (0, 1);
151 table.set_col_spacings (6);
152 table.set_homogeneous (false);
153 table.set_row_spacings (6);
155 table.attach (channels, 0, 1, 0, 1, FILL, FILL);
156 table.attach (samplerate, 0, 1, 1, 2, FILL, FILL);
157 table.attach (format, 0, 1, 2, 4, FILL, FILL);
158 table.attach (length, 0, 1, 4, 5, FILL, FILL);
159 table.attach (timecode, 0, 1, 5, 6, FILL, FILL);
161 table.attach (channels_value, 1, 2, 0, 1, FILL, FILL);
162 table.attach (samplerate_value, 1, 2, 1, 2, FILL, FILL);
163 table.attach (format_text, 1, 2, 2, 4, FILL, FILL);
164 table.attach (length_clock, 1, 2, 4, 5, FILL, FILL);
165 table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL);
167 length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock.mode());
168 timecode_clock.set_mode (AudioClock::Timecode);
170 main_box.pack_start (table, false, false);
172 tags_entry.set_editable (true);
173 tags_entry.signal_focus_out_event().connect (sigc::mem_fun (*this, &SoundFileBox::tags_entry_left));
175 Label* label = manage (new Label (_("Tags:")));
176 label->set_alignment (0.0f, 0.5f);
177 main_box.pack_start (*label, false, false);
178 main_box.pack_start (tags_entry, true, true);
180 main_box.pack_start (bottom_box, false, false);
182 play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
183 play_btn.set_label (_("Play"));
185 stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
186 stop_btn.set_label (_("Stop"));
188 bottom_box.set_homogeneous (false);
189 bottom_box.set_spacing (6);
190 bottom_box.pack_start(play_btn, true, true);
191 bottom_box.pack_start(stop_btn, true, true);
192 bottom_box.pack_start(autoplay_btn, false, false);
194 play_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::audition));
195 stop_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::stop_audition));
197 channels_value.set_alignment (0.0f, 0.5f);
198 samplerate_value.set_alignment (0.0f, 0.5f);
202 SoundFileBox::set_session(Session* s)
204 SessionHandlePtr::set_session (s);
206 length_clock.set_session (s);
207 timecode_clock.set_session (s);
210 play_btn.set_sensitive (false);
211 stop_btn.set_sensitive (false);
216 SoundFileBox::setup_labels (const ustring& filename)
219 // save existing tags
227 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
229 preview_label.set_markup (_("<b>Sound File Information</b>"));
230 format_text.set_text ("");
231 channels_value.set_text ("");
232 samplerate_value.set_text ("");
233 tags_entry.get_buffer()->set_text ("");
235 length_clock.set (0);
236 timecode_clock.set (0);
238 tags_entry.set_sensitive (false);
239 play_btn.set_sensitive (false);
244 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::path_get_basename (filename)));
245 std::string n = sf_info.format_name;
246 if (n.substr (0, 8) == X_("Format: ")) {
249 format_text.set_text (n);
250 channels_value.set_text (to_string (sf_info.channels, std::dec));
252 if (_session && sf_info.samplerate != _session->frame_rate()) {
253 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
254 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
255 samplerate_value.set_name ("NewSessionSR1Label");
256 samplerate.set_name ("NewSessionSR1Label");
258 samplerate.set_text (_("Sample rate:"));
259 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
260 samplerate_value.set_name ("NewSessionSR2Label");
261 samplerate.set_name ("NewSessionSR2Label");
264 nframes_t const nfr = _session ? _session->nominal_frame_rate() : 25;
265 double src_coef = (double) nfr / sf_info.samplerate;
267 length_clock.set (sf_info.length * src_coef + 0.5, true);
268 timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
270 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
272 vector<string> tags = Library->get_tags (string ("//") + filename);
274 stringstream tag_string;
275 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
276 if (i != tags.begin()) {
281 tags_entry.get_buffer()->set_text (tag_string.str());
283 tags_entry.set_sensitive (true);
285 play_btn.set_sensitive (true);
292 SoundFileBox::autoplay() const
294 return autoplay_btn.get_active();
298 SoundFileBox::audition_oneshot()
305 SoundFileBox::audition ()
311 _session->cancel_audition();
313 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
314 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
318 boost::shared_ptr<Region> r;
320 boost::shared_ptr<AudioFileSource> afs;
321 bool old_sbp = AudioSource::get_build_peakfiles ();
323 /* don't even think of building peakfiles for these files */
325 AudioSource::set_build_peakfiles (false);
327 for (int n = 0; n < sf_info.channels; ++n) {
329 afs = boost::dynamic_pointer_cast<AudioFileSource> (
330 SourceFactory::createReadable (DataType::AUDIO, *_session,
331 path, n, Source::Flag (0), false));
333 srclist.push_back(afs);
335 } catch (failed_constructor& err) {
336 error << _("Could not access soundfile: ") << path << endmsg;
337 AudioSource::set_build_peakfiles (old_sbp);
342 AudioSource::set_build_peakfiles (old_sbp);
344 if (srclist.empty()) {
348 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
349 string rname = region_name_from_path (afs->path(), false);
353 plist.add (ARDOUR::Properties::start, 0);
354 plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->timeline_position()));
355 plist.add (ARDOUR::Properties::name, rname);
356 plist.add (ARDOUR::Properties::layer, 0);
358 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false));
360 _session->audition_region(r);
364 SoundFileBox::stop_audition ()
367 _session->cancel_audition();
372 SoundFileBox::tags_entry_left (GdkEventFocus *)
379 SoundFileBox::tags_changed ()
381 string tag_string = tags_entry.get_buffer()->get_text ();
383 if (tag_string.empty()) {
389 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
390 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
398 SoundFileBox::save_tags (const vector<string>& tags)
400 Library->set_tags (string ("//") + path, tags);
401 Library->save_changes ();
404 SoundFileBrowser::SoundFileBrowser (Gtk::Window& parent, string title, ARDOUR::Session* s, bool persistent)
405 : ArdourDialog (parent, title, false, false),
406 found_list (ListStore::create(found_list_columns)),
407 freesound_list (ListStore::create(freesound_list_columns)),
408 chooser (FILE_CHOOSER_ACTION_OPEN),
409 preview (persistent),
410 found_search_btn (_("Search")),
411 found_list_view (found_list),
412 freesound_search_btn (_("Start Downloading")),
413 freesound_list_view (freesound_list)
415 resetting_ourselves = false;
418 resetting_ourselves = false;
421 if (ARDOUR::Profile->get_sae()) {
422 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
423 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
427 //add the file chooser
429 chooser.set_border_width (12);
431 audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
432 audio_filter.set_name (_("Audio files"));
434 midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
435 midi_filter.set_name (_("MIDI files"));
437 matchall_filter.add_pattern ("*.*");
438 matchall_filter.set_name (_("All files"));
440 chooser.add_filter (audio_filter);
441 chooser.add_filter (midi_filter);
442 chooser.add_filter (matchall_filter);
443 chooser.set_select_multiple (true);
444 chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
445 chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
447 /* some broken redraw behaviour - this is a bandaid */
448 chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
451 if (!persistent_folder.empty()) {
452 chooser.set_current_folder (persistent_folder);
454 notebook.append_page (chooser, _("Browse Files"));
457 hpacker.set_spacing (6);
458 hpacker.pack_start (notebook, true, true);
459 hpacker.pack_start (preview, false, false);
461 get_vbox()->pack_start (hpacker, true, true);
469 hbox = manage(new HBox);
470 hbox->pack_start (found_entry);
471 hbox->pack_start (found_search_btn);
473 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
474 scroll->add(found_list_view);
475 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
477 vbox = manage(new VBox);
478 vbox->pack_start (*hbox, PACK_SHRINK);
479 vbox->pack_start (*scroll);
481 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
483 found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
485 found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
487 found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
488 found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
490 notebook.append_page (*vbox, _("Search Tags"));
493 //add freesound search
500 passbox = manage(new HBox);
501 passbox->set_border_width (12);
502 passbox->set_spacing (6);
504 label = manage (new Label);
505 label->set_text (_("User:"));
506 passbox->pack_start (*label, false, false);
507 passbox->pack_start (freesound_name_entry);
508 label = manage (new Label);
509 label->set_text (_("Password:"));
510 passbox->pack_start (*label, false, false);
511 passbox->pack_start (freesound_pass_entry);
512 label = manage (new Label);
513 label->set_text (_("Tags:"));
514 passbox->pack_start (*label, false, false);
515 passbox->pack_start (freesound_entry, false, false);
516 passbox->pack_start (freesound_search_btn, false, false);
518 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
519 scroll->add(freesound_list_view);
520 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
522 vbox = manage(new VBox);
523 vbox->pack_start (*passbox, PACK_SHRINK);
524 vbox->pack_start(*scroll);
526 //vbox->pack_start (freesound_list_view);
528 freesound_list_view.append_column(_("Paths"), freesound_list_columns.pathname);
529 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
531 //freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
532 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
533 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
534 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
535 notebook.append_page (*vbox, _("Search Freesound"));
540 notebook.set_size_request (500, -1);
544 add_button (Stock::CANCEL, RESPONSE_CANCEL);
545 add_button (Stock::APPLY, RESPONSE_APPLY);
546 add_button (Stock::OK, RESPONSE_OK);
550 SoundFileBrowser::~SoundFileBrowser ()
552 persistent_folder = chooser.get_current_folder();
557 SoundFileBrowser::on_show ()
559 ArdourDialog::on_show ();
564 SoundFileBrowser::clear_selection ()
566 chooser.unselect_all ();
567 found_list_view.get_selection()->unselect_all ();
571 SoundFileBrowser::chooser_file_activated ()
577 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
583 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
589 SoundFileBrowser::set_session (Session* s)
591 ArdourDialog::set_session (s);
592 preview.set_session (s);
597 remove_gain_meter ();
602 SoundFileBrowser::add_gain_meter ()
606 gm = new GainMeter (_session, 250);
608 boost::shared_ptr<Route> r = _session->the_auditioner ();
610 gm->set_controls (r, r->shared_peak_meter(), r->amp());
612 meter_packer.set_border_width (12);
613 meter_packer.pack_start (*gm, false, true);
614 hpacker.pack_end (meter_packer, false, false);
615 meter_packer.show_all ();
620 SoundFileBrowser::remove_gain_meter ()
623 meter_packer.remove (*gm);
624 hpacker.remove (meter_packer);
631 SoundFileBrowser::start_metering ()
633 metering_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
637 SoundFileBrowser::stop_metering ()
639 metering_connection.disconnect();
643 SoundFileBrowser::meter ()
645 if (is_mapped () && _session && gm) {
646 gm->update_meters ();
651 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
653 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
657 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
659 return SMFSource::safe_midi_file_extension (filter_info.filename);
663 SoundFileBrowser::update_preview ()
665 if (preview.setup_labels (chooser.get_filename())) {
666 if (preview.autoplay()) {
667 Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
673 SoundFileBrowser::found_list_view_selected ()
675 if (!reset_options ()) {
676 set_response_sensitive (RESPONSE_OK, false);
680 TreeView::Selection::ListHandle_Path rows = found_list_view.get_selection()->get_selected_rows ();
683 TreeIter iter = found_list->get_iter(*rows.begin());
684 file = (*iter)[found_list_columns.pathname];
685 chooser.set_filename (file);
686 set_response_sensitive (RESPONSE_OK, true);
688 set_response_sensitive (RESPONSE_OK, false);
691 preview.setup_labels (file);
696 SoundFileBrowser::freesound_list_view_selected ()
698 if (!reset_options ()) {
699 set_response_sensitive (RESPONSE_OK, false);
703 TreeView::Selection::ListHandle_Path rows = freesound_list_view.get_selection()->get_selected_rows ();
706 TreeIter iter = freesound_list->get_iter(*rows.begin());
707 file = (*iter)[freesound_list_columns.pathname];
708 chooser.set_filename (file);
709 set_response_sensitive (RESPONSE_OK, true);
711 set_response_sensitive (RESPONSE_OK, false);
714 preview.setup_labels (file);
719 SoundFileBrowser::found_search_clicked ()
721 string tag_string = found_entry.get_text ();
725 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
726 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
730 vector<string> results;
731 Library->search_members_and (results, tags);
734 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
735 TreeModel::iterator new_row = found_list->append();
736 TreeModel::Row row = *new_row;
737 string path = Glib::filename_from_uri (string ("file:") + *i);
738 row[found_list_columns.pathname] = path;
743 freesound_search_thread_entry (void* arg)
745 SessionEvent::create_per_thread_pool ("freesound events", 64);
747 static_cast<SoundFileBrowser*>(arg)->freesound_search_thread ();
752 bool searching = false;
753 bool canceling = false;
756 SoundFileBrowser::freesound_search_clicked ()
758 if (canceling) //already canceling, button does nothing
762 freesound_search_btn.set_label(_("Cancelling.."));
766 freesound_search_btn.set_label(_("Cancel"));
767 pthread_t freesound_thr;
768 pthread_create_and_store ("freesound_search", &freesound_thr, freesound_search_thread_entry, this);
773 SoundFileBrowser::freesound_search_thread()
777 THIS IS ALL TOTALLY THREAD-ILLEGAL ... YOU CANNOT DO GTK STUFF IN THIS THREAD
780 freesound_list->clear();
783 path = Glib::get_home_dir();
784 path += "/Freesound/";
785 Mootcher theMootcher(path.c_str());
787 string name_string = freesound_name_entry.get_text ();
788 string pass_string = freesound_pass_entry.get_text ();
789 string search_string = freesound_entry.get_text ();
791 if ( theMootcher.doLogin( name_string, pass_string ) ) {
793 string theString = theMootcher.searchText(search_string);
796 doc.read_buffer( theString );
797 XMLNode *root = doc.root();
799 if (root==NULL) return;
801 if ( strcmp(root->name().c_str(), "freesound") == 0) {
804 XMLNodeList children = root->children();
805 XMLNodeConstIterator niter;
806 for (niter = children.begin(); niter != children.end() && !canceling; ++niter) {
808 if( strcmp( node->name().c_str(), "sample") == 0 ){
809 XMLProperty *prop=node->property ("id");
810 string filename = theMootcher.getFile( prop->value().c_str() );
811 if ( filename != "" ) {
812 TreeModel::iterator new_row = freesound_list->append();
813 TreeModel::Row row = *new_row;
814 string path = Glib::filename_from_uri (string ("file:") + filename);
815 row[freesound_list_columns.pathname] = path;
824 freesound_search_btn.set_label(_("Start Downloading"));
831 SoundFileBrowser::get_paths ()
833 vector<ustring> results;
835 int n = notebook.get_current_page ();
838 vector<ustring> filenames = chooser.get_filenames();
839 vector<ustring>::iterator i;
841 for (i = filenames.begin(); i != filenames.end(); ++i) {
843 if ((!stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
844 results.push_back (*i);
850 typedef TreeView::Selection::ListHandle_Path ListPath;
852 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
853 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
854 TreeIter iter = found_list->get_iter(*i);
855 ustring str = (*iter)[found_list_columns.pathname];
857 results.push_back (str);
861 typedef TreeView::Selection::ListHandle_Path ListPath;
863 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
864 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
865 TreeIter iter = freesound_list->get_iter(*i);
866 ustring str = (*iter)[freesound_list_columns.pathname];
868 results.push_back (str);
876 SoundFileOmega::reset_options_noret ()
878 if (!resetting_ourselves) {
879 (void) reset_options ();
884 SoundFileOmega::reset_options ()
886 vector<ustring> paths = get_paths ();
890 channel_combo.set_sensitive (false);
891 action_combo.set_sensitive (false);
892 where_combo.set_sensitive (false);
893 copy_files_btn.set_sensitive (false);
899 channel_combo.set_sensitive (true);
900 action_combo.set_sensitive (true);
901 where_combo.set_sensitive (true);
903 /* if we get through this function successfully, this may be
904 reset at the end, once we know if we can use hard links
908 if (Config->get_only_copy_imported_files()) {
909 copy_files_btn.set_sensitive (false);
911 copy_files_btn.set_sensitive (false);
917 bool selection_includes_multichannel;
918 bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
921 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
922 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
926 ustring existing_choice;
927 vector<string> action_strings;
929 if (selected_track_cnt > 0) {
930 if (channel_combo.get_active_text().length()) {
931 ImportDisposition id = get_channel_disposition();
934 case Editing::ImportDistinctFiles:
935 if (selected_track_cnt == paths.size()) {
936 action_strings.push_back (importmode2string (ImportToTrack));
940 case Editing::ImportDistinctChannels:
941 /* XXX it would be nice to allow channel-per-selected track
942 but its too hard we don't want to deal with all the
943 different per-file + per-track channel configurations.
948 action_strings.push_back (importmode2string (ImportToTrack));
954 action_strings.push_back (importmode2string (ImportAsTrack));
955 action_strings.push_back (importmode2string (ImportAsRegion));
956 action_strings.push_back (importmode2string (ImportAsTapeTrack));
958 resetting_ourselves = true;
960 existing_choice = action_combo.get_active_text();
962 set_popdown_strings (action_combo, action_strings);
964 /* preserve any existing choice, if possible */
967 if (existing_choice.length()) {
968 vector<string>::iterator x;
969 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
970 if (*x == existing_choice) {
971 action_combo.set_active_text (existing_choice);
975 if (x == action_strings.end()) {
976 action_combo.set_active_text (action_strings.front());
979 action_combo.set_active_text (action_strings.front());
982 resetting_ourselves = false;
984 if ((mode = get_mode()) == ImportAsRegion) {
985 where_combo.set_sensitive (false);
987 where_combo.set_sensitive (true);
990 vector<string> channel_strings;
992 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
993 channel_strings.push_back (_("one track per file"));
995 if (selection_includes_multichannel) {
996 channel_strings.push_back (_("one track per channel"));
999 if (paths.size() > 1) {
1000 /* tape tracks are a single region per track, so we cannot
1001 sequence multiple files.
1003 if (mode != ImportAsTapeTrack) {
1004 channel_strings.push_back (_("sequence files"));
1007 channel_strings.push_back (_("all files in one track"));
1013 channel_strings.push_back (_("one region per file"));
1015 if (selection_includes_multichannel) {
1016 channel_strings.push_back (_("one region per channel"));
1019 if (paths.size() > 1) {
1021 channel_strings.push_back (_("all files in one region"));
1026 existing_choice = channel_combo.get_active_text();
1028 set_popdown_strings (channel_combo, channel_strings);
1030 /* preserve any existing choice, if possible */
1032 if (existing_choice.length()) {
1033 vector<string>::iterator x;
1034 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1035 if (*x == existing_choice) {
1036 channel_combo.set_active_text (existing_choice);
1040 if (x == channel_strings.end()) {
1041 channel_combo.set_active_text (channel_strings.front());
1044 channel_combo.set_active_text (channel_strings.front());
1048 src_combo.set_sensitive (true);
1050 src_combo.set_sensitive (false);
1053 if (Config->get_only_copy_imported_files()) {
1055 if (selection_can_be_embedded_with_links) {
1056 copy_files_btn.set_sensitive (true);
1058 copy_files_btn.set_sensitive (false);
1063 copy_files_btn.set_sensitive (true);
1071 SoundFileOmega::bad_file_message()
1073 MessageDialog msg (*this,
1074 _("One or more of the selected files\ncannot be used by Ardour"),
1079 resetting_ourselves = true;
1080 chooser.unselect_uri (chooser.get_preview_uri());
1081 resetting_ourselves = false;
1087 SoundFileOmega::check_info (const vector<ustring>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1096 multichannel = false;
1098 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1100 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1101 if (info.channels > 1) {
1102 multichannel = true;
1107 if (sz != info.length) {
1112 if ((nframes_t) info.samplerate != _session->frame_rate()) {
1116 } else if (SMFSource::safe_midi_file_extension (*i)) {
1120 if (reader.num_tracks() > 1) {
1121 multichannel = true; // "channel" == track here...
1124 /* XXX we need err = true handling here in case
1125 we can't check the file
1138 SoundFileOmega::check_link_status (const Session* s, const vector<ustring>& paths)
1140 sys::path path = s->session_directory().sound_path() / "linktest";
1141 string tmpdir = path.to_string();
1144 if (mkdir (tmpdir.c_str(), 0744)) {
1145 if (errno != EEXIST) {
1150 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1152 char tmpc[MAXPATHLEN+1];
1154 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1158 if (link ((*i).c_str(), tmpc)) {
1168 rmdir (tmpdir.c_str());
1172 SoundFileChooser::SoundFileChooser (Gtk::Window& parent, string title, ARDOUR::Session* s)
1173 : SoundFileBrowser (parent, title, s, false)
1175 chooser.set_select_multiple (false);
1176 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1177 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1181 SoundFileChooser::on_hide ()
1183 ArdourDialog::on_hide();
1187 _session->cancel_audition();
1192 SoundFileChooser::get_filename ()
1194 vector<ustring> paths;
1196 paths = get_paths ();
1198 if (paths.empty()) {
1202 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1206 return paths.front();
1209 SoundFileOmega::SoundFileOmega (Gtk::Window& parent, string title, ARDOUR::Session* s, int selected_tracks, bool persistent,
1210 Editing::ImportMode mode_hint)
1211 : SoundFileBrowser (parent, title, s, persistent),
1212 copy_files_btn ( _("Copy files to session")),
1213 selected_track_cnt (selected_tracks)
1219 set_size_request (-1, 450);
1221 block_two.set_border_width (12);
1222 block_three.set_border_width (12);
1223 block_four.set_border_width (12);
1225 options.set_spacing (12);
1228 str.push_back (_("file timestamp"));
1229 str.push_back (_("edit point"));
1230 str.push_back (_("playhead"));
1231 str.push_back (_("session start"));
1232 set_popdown_strings (where_combo, str);
1233 where_combo.set_active_text (str.front());
1235 Label* l = manage (new Label);
1236 l->set_text (_("Add files:"));
1238 hbox = manage (new HBox);
1239 hbox->set_border_width (12);
1240 hbox->set_spacing (6);
1241 hbox->pack_start (*l, false, false);
1242 hbox->pack_start (action_combo, false, false);
1243 vbox = manage (new VBox);
1244 vbox->pack_start (*hbox, false, false);
1245 options.pack_start (*vbox, false, false);
1247 /* dummy entry for action combo so that it doesn't look odd if we
1248 come up with no tracks selected.
1252 str.push_back (importmode2string (mode_hint));
1253 set_popdown_strings (action_combo, str);
1254 action_combo.set_active_text (str.front());
1255 action_combo.set_sensitive (false);
1257 l = manage (new Label);
1258 l->set_text (_("Insert at:"));
1260 hbox = manage (new HBox);
1261 hbox->set_border_width (12);
1262 hbox->set_spacing (6);
1263 hbox->pack_start (*l, false, false);
1264 hbox->pack_start (where_combo, false, false);
1265 vbox = manage (new VBox);
1266 vbox->pack_start (*hbox, false, false);
1267 options.pack_start (*vbox, false, false);
1270 l = manage (new Label);
1271 l->set_text (_("Mapping:"));
1273 hbox = manage (new HBox);
1274 hbox->set_border_width (12);
1275 hbox->set_spacing (6);
1276 hbox->pack_start (*l, false, false);
1277 hbox->pack_start (channel_combo, false, false);
1278 vbox = manage (new VBox);
1279 vbox->pack_start (*hbox, false, false);
1280 options.pack_start (*vbox, false, false);
1283 str.push_back (_("one track per file"));
1284 set_popdown_strings (channel_combo, str);
1285 channel_combo.set_active_text (str.front());
1286 channel_combo.set_sensitive (false);
1288 l = manage (new Label);
1289 l->set_text (_("Conversion quality:"));
1291 hbox = manage (new HBox);
1292 hbox->set_border_width (12);
1293 hbox->set_spacing (6);
1294 hbox->pack_start (*l, false, false);
1295 hbox->pack_start (src_combo, false, false);
1296 vbox = manage (new VBox);
1297 vbox->pack_start (*hbox, false, false);
1298 options.pack_start (*vbox, false, false);
1301 str.push_back (_("Best"));
1302 str.push_back (_("Good"));
1303 str.push_back (_("Quick"));
1304 str.push_back (_("Fast"));
1305 str.push_back (_("Fastest"));
1307 set_popdown_strings (src_combo, str);
1308 src_combo.set_active_text (str.front());
1309 src_combo.set_sensitive (false);
1313 action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1315 copy_files_btn.set_active (true);
1317 block_four.pack_start (copy_files_btn, false, false);
1319 options.pack_start (block_four, false, false);
1321 get_vbox()->pack_start (options, false, false);
1323 /* setup disposition map */
1325 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1326 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1327 disposition_map.insert (pair<ustring,ImportDisposition>(_("merge files"), ImportMergeFiles));
1328 disposition_map.insert (pair<ustring,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1330 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1331 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1332 disposition_map.insert (pair<ustring,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1334 chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1336 /* set size requests for a couple of combos to allow them to display the longest text
1337 they will ever be asked to display. This prevents them being resized when the user
1338 selects a file to import, which in turn prevents the size of the dialog from jumping
1342 t.push_back (_("one track per file"));
1343 t.push_back (_("one track per channel"));
1344 t.push_back (_("sequence files"));
1345 t.push_back (_("all files in one region"));
1346 set_size_request_to_display_given_text (channel_combo, t, COMBO_FUDGE + 10, 15);
1349 t.push_back (importmode2string (ImportAsTrack));
1350 t.push_back (importmode2string (ImportToTrack));
1351 t.push_back (importmode2string (ImportAsRegion));
1352 t.push_back (importmode2string (ImportAsTapeTrack));
1353 set_size_request_to_display_given_text (action_combo, t, COMBO_FUDGE + 10, 15);
1357 SoundFileOmega::set_mode (ImportMode mode)
1359 action_combo.set_active_text (importmode2string (mode));
1363 SoundFileOmega::get_mode () const
1365 return string2importmode (action_combo.get_active_text());
1369 SoundFileOmega::on_hide ()
1371 ArdourDialog::on_hide();
1373 _session->cancel_audition();
1378 SoundFileOmega::get_position() const
1380 ustring str = where_combo.get_active_text();
1382 if (str == _("file timestamp")) {
1383 return ImportAtTimestamp;
1384 } else if (str == _("edit point")) {
1385 return ImportAtEditPoint;
1386 } else if (str == _("playhead")) {
1387 return ImportAtPlayhead;
1389 return ImportAtStart;
1394 SoundFileOmega::get_src_quality() const
1396 ustring str = where_combo.get_active_text();
1398 if (str == _("Best")) {
1400 } else if (str == _("Good")) {
1402 } else if (str == _("Quick")) {
1404 } else if (str == _("Fast")) {
1412 SoundFileOmega::get_channel_disposition () const
1414 /* we use a map here because the channel combo can contain different strings
1415 depending on the state of the other combos. the map contains all possible strings
1416 and the ImportDisposition enum that corresponds to it.
1419 ustring str = channel_combo.get_active_text();
1420 DispositionMap::const_iterator x = disposition_map.find (str);
1422 if (x == disposition_map.end()) {
1423 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1431 SoundFileOmega::reset (int selected_tracks)
1433 selected_track_cnt = selected_tracks;
1438 SoundFileOmega::file_selection_changed ()
1440 if (resetting_ourselves) {
1444 if (!reset_options ()) {
1445 set_response_sensitive (RESPONSE_OK, false);
1447 if (chooser.get_filenames().size() > 0) {
1448 set_response_sensitive (RESPONSE_OK, true);
1450 set_response_sensitive (RESPONSE_OK, false);