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 <ardour/audio_library.h>
41 #include <ardour/auditioner.h>
42 #include <ardour/audioregion.h>
43 #include <ardour/audiofilesource.h>
44 #include <ardour/smf_source.h>
45 #include <ardour/smf_reader.h>
46 #include <ardour/region_factory.h>
47 #include <ardour/source_factory.h>
48 #include <ardour/session.h>
49 #include <ardour/session_directory.h>
50 #include <ardour/profile.h>
52 #include "ardour_ui.h"
54 #include "gui_thread.h"
59 #include "gain_meter.h"
62 #include "sfdb_freesound_mootcher.h"
67 using namespace ARDOUR;
71 using namespace Gtkmm2ext;
72 using namespace Editing;
76 ustring SoundFileBrowser::persistent_folder;
79 string2importmode (string str)
81 if (str == _("as new tracks")) {
83 } else if (str == _("to selected tracks")) {
85 } else if (str == _("to region list")) {
86 return ImportAsRegion;
87 } else if (str == _("as new tape tracks")) {
88 return ImportAsTapeTrack;
91 warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
97 importmode2string (ImportMode mode)
101 return _("as new tracks");
103 return _("to selected tracks");
105 return _("to region list");
106 case ImportAsTapeTrack:
107 return _("as new tape tracks");
110 return _("as new tracks");
113 SoundFileBox::SoundFileBox (bool persistent)
116 length_clock ("sfboxLengthClock", !persistent, "EditCursorClock", false, true, false),
117 timecode_clock ("sfboxTimecodeClock", !persistent, "EditCursorClock", false, false, false),
119 autoplay_btn (_("Auto-play"))
125 set_name (X_("SoundFileBox"));
126 set_size_request (300, -1);
128 preview_label.set_markup (_("<b>Soundfile Info</b>"));
130 border_frame.set_label_widget (preview_label);
131 border_frame.add (main_box);
133 pack_start (border_frame, true, true);
134 set_border_width (6);
136 main_box.set_border_width (6);
137 main_box.set_spacing (12);
139 length.set_text (_("Length:"));
140 timecode.set_text (_("Timestamp:"));
141 format.set_text (_("Format:"));
142 channels.set_text (_("Channels:"));
143 samplerate.set_text (_("Sample rate:"));
145 table.set_col_spacings (6);
146 table.set_homogeneous (false);
147 table.set_row_spacings (6);
149 table.attach (channels, 0, 1, 0, 1, FILL|EXPAND, (AttachOptions) 0);
150 table.attach (samplerate, 0, 1, 1, 2, FILL|EXPAND, (AttachOptions) 0);
151 table.attach (format, 0, 1, 2, 4, FILL|EXPAND, (AttachOptions) 0);
152 table.attach (length, 0, 1, 4, 5, FILL|EXPAND, (AttachOptions) 0);
153 table.attach (timecode, 0, 1, 5, 6, FILL|EXPAND, (AttachOptions) 0);
155 table.attach (channels_value, 1, 2, 0, 1, FILL, (AttachOptions) 0);
156 table.attach (samplerate_value, 1, 2, 1, 2, FILL, (AttachOptions) 0);
157 table.attach (format_text, 1, 2, 2, 4, FILL, AttachOptions (0));
158 table.attach (length_clock, 1, 2, 4, 5, FILL, (AttachOptions) 0);
159 table.attach (timecode_clock, 1, 2, 5, 6, FILL, (AttachOptions) 0);
161 length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock.mode());
162 timecode_clock.set_mode (AudioClock::SMPTE);
164 hbox = manage (new HBox);
165 hbox->pack_start (table, false, false);
166 main_box.pack_start (*hbox, false, false);
168 tags_entry.set_editable (true);
169 tags_entry.signal_focus_out_event().connect (mem_fun (*this, &SoundFileBox::tags_entry_left));
170 hbox = manage (new HBox);
171 hbox->pack_start (tags_entry, true, true);
173 vbox = manage (new VBox);
175 Label* label = manage (new Label (_("Tags:")));
176 label->set_alignment (0.0f, 0.5f);
177 vbox->set_spacing (6);
178 vbox->pack_start(*label, false, false);
179 vbox->pack_start(*hbox, true, true);
181 main_box.pack_start(*vbox, true, true);
182 main_box.pack_start(bottom_box, false, false);
184 play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
185 play_btn.set_label (_("Play (double click)"));
187 stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
188 stop_btn.set_label (_("Stop"));
190 bottom_box.set_homogeneous (false);
191 bottom_box.set_spacing (6);
192 bottom_box.pack_start(play_btn, true, true);
193 bottom_box.pack_start(stop_btn, true, true);
194 bottom_box.pack_start(autoplay_btn, false, false);
196 play_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::audition));
197 stop_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::stop_audition));
199 length.set_alignment (0.0f, 0.5f);
200 format.set_alignment (0.0f, 0.5f);
201 channels.set_alignment (0.0f, 0.5f);
202 samplerate.set_alignment (0.0f, 0.5f);
203 timecode.set_alignment (0.0f, 0.5f);
205 channels_value.set_alignment (0.0f, 0.5f);
206 samplerate_value.set_alignment (0.0f, 0.5f);
210 SoundFileBox::set_session(Session* s)
215 play_btn.set_sensitive (false);
216 stop_btn.set_sensitive (false);
220 length_clock.set_session (s);
221 timecode_clock.set_session (s);
225 SoundFileBox::setup_labels (const ustring& filename)
228 // save existing tags
236 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
238 preview_label.set_markup (_("<b>Soundfile Info</b>"));
239 format_text.set_text (_("n/a"));
240 channels_value.set_text (_("n/a"));
241 samplerate_value.set_text (_("n/a"));
242 tags_entry.get_buffer()->set_text ("");
244 length_clock.set (0);
245 timecode_clock.set (0);
247 tags_entry.set_sensitive (false);
248 play_btn.set_sensitive (false);
253 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::path_get_basename (filename)));
254 format_text.set_text (sf_info.format_name);
255 channels_value.set_text (to_string (sf_info.channels, std::dec));
257 if (_session && sf_info.samplerate != _session->frame_rate()) {
258 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
259 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
260 samplerate_value.set_name ("NewSessionSR1Label");
261 samplerate.set_name ("NewSessionSR1Label");
263 samplerate.set_text (_("Sample rate:"));
264 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
265 samplerate_value.set_name ("NewSessionSR2Label");
266 samplerate.set_name ("NewSessionSR2Label");
269 length_clock.set (sf_info.length, true);
270 timecode_clock.set (sf_info.timecode, 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> (SourceFactory::createReadable (DataType::AUDIO, *_session, path,
332 n, AudioFileSource::Flag (0), false));
334 srclist.push_back(afs);
336 } catch (failed_constructor& err) {
337 error << _("Could not access soundfile: ") << path << endmsg;
338 AudioSource::set_build_peakfiles (old_sbp);
343 AudioSource::set_build_peakfiles (old_sbp);
345 if (srclist.empty()) {
349 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
350 string rname = region_name_from_path (afs->path(), false);
351 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, 0, srclist[0]->length(), rname, 0, Region::DefaultFlags, false));
353 _session->audition_region(r);
357 SoundFileBox::stop_audition ()
360 _session->cancel_audition();
365 SoundFileBox::tags_entry_left (GdkEventFocus *ev)
372 SoundFileBox::tags_changed ()
374 string tag_string = tags_entry.get_buffer()->get_text ();
376 if (tag_string.empty()) {
382 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
383 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
391 SoundFileBox::save_tags (const vector<string>& tags)
393 Library->set_tags (string ("//") + path, tags);
394 Library->save_changes ();
397 SoundFileBrowser::SoundFileBrowser (Gtk::Window& parent, string title, ARDOUR::Session* s, bool persistent)
398 : ArdourDialog (parent, title, false, false),
399 found_list (ListStore::create(found_list_columns)),
400 freesound_list (ListStore::create(freesound_list_columns)),
401 chooser (FILE_CHOOSER_ACTION_OPEN),
402 found_list_view (found_list),
403 freesound_list_view (freesound_list),
404 preview (persistent),
405 found_search_btn (_("Search")),
406 freesound_search_btn (_("Start Downloading"))
409 resetting_ourselves = false;
412 if (ARDOUR::Profile->get_sae()) {
413 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
414 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
417 //add the file chooser
419 chooser.set_border_width (12);
421 audio_filter.add_custom (FILE_FILTER_FILENAME, mem_fun(*this, &SoundFileBrowser::on_audio_filter));
422 audio_filter.set_name (_("Audio files"));
424 midi_filter.add_custom (FILE_FILTER_FILENAME, mem_fun(*this, &SoundFileBrowser::on_midi_filter));
425 midi_filter.set_name (_("MIDI files"));
427 matchall_filter.add_pattern ("*.*");
428 matchall_filter.set_name (_("All files"));
430 chooser.add_filter (audio_filter);
431 chooser.add_filter (midi_filter);
432 chooser.add_filter (matchall_filter);
433 chooser.set_select_multiple (true);
434 chooser.signal_update_preview().connect(mem_fun(*this, &SoundFileBrowser::update_preview));
435 chooser.signal_file_activated().connect (mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
437 if (!persistent_folder.empty()) {
438 chooser.set_current_folder (persistent_folder);
440 notebook.append_page (chooser, _("Browse Files"));
448 hpacker.set_spacing (6);
449 hpacker.pack_start (notebook, true, true);
450 hpacker.pack_start (preview, false, false);
452 get_vbox()->pack_start (hpacker, true, true);
454 hbox = manage(new HBox);
455 hbox->pack_start (found_entry);
456 hbox->pack_start (found_search_btn);
458 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
459 scroll->add(found_list_view);
460 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
462 vbox = manage(new VBox);
463 vbox->pack_start (*hbox, PACK_SHRINK);
464 vbox->pack_start (*scroll);
466 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
468 found_list_view.get_selection()->signal_changed().connect(mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
470 found_list_view.signal_row_activated().connect (mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
472 found_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked));
473 found_entry.signal_activate().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked));
475 notebook.append_page (*vbox, _("Search Tags"));
479 //add freesound search
486 hpacker.set_spacing (6);
487 hpacker.pack_start (notebook, true, true);
488 hpacker.pack_start (preview, false, false);
490 get_vbox()->pack_start (hpacker, true, true);
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));
526 freesound_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
527 freesound_entry.signal_activate().connect(mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
529 notebook.append_page (*vbox, _("Search Freesound"));
534 notebook.set_size_request (500, -1);
538 add_button (Stock::CANCEL, RESPONSE_CANCEL);
539 add_button (Stock::APPLY, RESPONSE_APPLY);
540 add_button (Stock::OK, RESPONSE_OK);
544 SoundFileBrowser::~SoundFileBrowser ()
546 persistent_folder = chooser.get_current_folder();
551 SoundFileBrowser::on_show ()
553 ArdourDialog::on_show ();
558 SoundFileBrowser::clear_selection ()
560 chooser.unselect_all ();
561 found_list_view.get_selection()->unselect_all ();
565 SoundFileBrowser::chooser_file_activated ()
571 SoundFileBrowser::found_list_view_activated (const TreeModel::Path& path, TreeViewColumn* col)
577 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path& path, TreeViewColumn* col)
583 SoundFileBrowser::set_session (Session* s)
585 ArdourDialog::set_session (s);
586 preview.set_session (s);
590 remove_gain_meter ();
595 SoundFileBrowser::add_gain_meter ()
601 gm = new GainMeter (session->the_auditioner(), *session);
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_file_extension (filter_info.filename);
648 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
650 return SMFSource::safe_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::ThreadCreated (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)) {
1087 if (info.channels > 1) {
1088 multichannel = true;
1094 if (sz != info.length) {
1099 if ((nframes_t) info.samplerate != session->frame_rate()) {
1103 } else if (SMFSource::safe_file_extension (*i)) {
1105 SMFReader reader(*i);
1106 if (reader.num_tracks() > 1) {
1107 multichannel = true; // "channel" == track here...
1110 /* XXX we need err = true handling here in case
1111 we can't check the file
1124 SoundFileOmega::check_link_status (const Session& s, const vector<ustring>& paths)
1126 sys::path path = s.session_directory().sound_path() / "linktest";
1127 string tmpdir = path.to_string();
1130 if (mkdir (tmpdir.c_str(), 0744)) {
1131 if (errno != EEXIST) {
1136 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1138 char tmpc[MAXPATHLEN+1];
1140 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1144 if (link ((*i).c_str(), tmpc)) {
1154 rmdir (tmpdir.c_str());
1158 SoundFileChooser::SoundFileChooser (Gtk::Window& parent, string title, ARDOUR::Session* s)
1159 : SoundFileBrowser (parent, title, s, false)
1161 chooser.set_select_multiple (false);
1162 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1163 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1167 SoundFileChooser::on_hide ()
1169 ArdourDialog::on_hide();
1173 session->cancel_audition();
1178 SoundFileChooser::get_filename ()
1180 vector<ustring> paths;
1182 paths = get_paths ();
1184 if (paths.empty()) {
1188 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1192 return paths.front();
1195 SoundFileOmega::SoundFileOmega (Gtk::Window& parent, string title, ARDOUR::Session* s, int selected_tracks, bool persistent,
1196 Editing::ImportMode mode_hint)
1197 : SoundFileBrowser (parent, title, s, persistent),
1198 copy_files_btn ( _("Copy files to session")),
1199 selected_track_cnt (selected_tracks)
1205 set_size_request (-1, 450);
1207 block_two.set_border_width (12);
1208 block_three.set_border_width (12);
1209 block_four.set_border_width (12);
1211 options.set_spacing (12);
1214 str.push_back (_("use file timestamp"));
1215 str.push_back (_("at edit point"));
1216 str.push_back (_("at playhead"));
1217 str.push_back (_("at session start"));
1218 set_popdown_strings (where_combo, str);
1219 where_combo.set_active_text (str.front());
1221 Label* l = manage (new Label);
1222 l->set_text (_("Add files:"));
1224 hbox = manage (new HBox);
1225 hbox->set_border_width (12);
1226 hbox->set_spacing (6);
1227 hbox->pack_start (*l, false, false);
1228 hbox->pack_start (action_combo, false, false);
1229 vbox = manage (new VBox);
1230 vbox->pack_start (*hbox, false, false);
1231 options.pack_start (*vbox, false, false);
1233 /* dummy entry for action combo so that it doesn't look odd if we
1234 come up with no tracks selected.
1238 str.push_back (importmode2string (mode_hint));
1239 set_popdown_strings (action_combo, str);
1240 action_combo.set_active_text (str.front());
1241 action_combo.set_sensitive (false);
1243 l = manage (new Label);
1244 l->set_text (_("Insert:"));
1246 hbox = manage (new HBox);
1247 hbox->set_border_width (12);
1248 hbox->set_spacing (6);
1249 hbox->pack_start (*l, false, false);
1250 hbox->pack_start (where_combo, false, false);
1251 vbox = manage (new VBox);
1252 vbox->pack_start (*hbox, false, false);
1253 options.pack_start (*vbox, false, false);
1256 l = manage (new Label);
1257 l->set_text (_("Mapping:"));
1259 hbox = manage (new HBox);
1260 hbox->set_border_width (12);
1261 hbox->set_spacing (6);
1262 hbox->pack_start (*l, false, false);
1263 hbox->pack_start (channel_combo, false, false);
1264 vbox = manage (new VBox);
1265 vbox->pack_start (*hbox, false, false);
1266 options.pack_start (*vbox, false, false);
1269 str.push_back (_("one track per file"));
1270 set_popdown_strings (channel_combo, str);
1271 channel_combo.set_active_text (str.front());
1272 channel_combo.set_sensitive (false);
1274 l = manage (new Label);
1275 l->set_text (_("Conversion Quality:"));
1277 hbox = manage (new HBox);
1278 hbox->set_border_width (12);
1279 hbox->set_spacing (6);
1280 hbox->pack_start (*l, false, false);
1281 hbox->pack_start (src_combo, false, false);
1282 vbox = manage (new VBox);
1283 vbox->pack_start (*hbox, false, false);
1284 options.pack_start (*vbox, false, false);
1287 str.push_back (_("Best"));
1288 str.push_back (_("Good"));
1289 str.push_back (_("Quick"));
1290 str.push_back (_("Fast"));
1291 str.push_back (_("Fastest"));
1293 set_popdown_strings (src_combo, str);
1294 src_combo.set_active_text (str.front());
1295 src_combo.set_sensitive (false);
1299 action_combo.signal_changed().connect (mem_fun (*this, &SoundFileOmega::reset_options_noret));
1301 copy_files_btn.set_active (true);
1303 block_four.pack_start (copy_files_btn, false, false);
1305 options.pack_start (block_four, false, false);
1307 get_vbox()->pack_start (options, false, false);
1309 /* setup disposition map */
1311 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1312 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1313 disposition_map.insert (pair<ustring,ImportDisposition>(_("merge files"), ImportMergeFiles));
1314 disposition_map.insert (pair<ustring,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1316 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1317 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1318 disposition_map.insert (pair<ustring,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1320 chooser.signal_selection_changed().connect (mem_fun (*this, &SoundFileOmega::file_selection_changed));
1324 SoundFileOmega::set_mode (ImportMode mode)
1326 action_combo.set_active_text (importmode2string (mode));
1330 SoundFileOmega::get_mode () const
1332 return string2importmode (action_combo.get_active_text());
1336 SoundFileOmega::on_hide ()
1338 ArdourDialog::on_hide();
1340 session->cancel_audition();
1345 SoundFileOmega::get_position() const
1347 ustring str = where_combo.get_active_text();
1349 if (str == _("use file timestamp")) {
1350 return ImportAtTimestamp;
1351 } else if (str == _("at edit point")) {
1352 return ImportAtEditPoint;
1353 } else if (str == _("at playhead")) {
1354 return ImportAtPlayhead;
1356 return ImportAtStart;
1361 SoundFileOmega::get_src_quality() const
1363 ustring str = where_combo.get_active_text();
1365 if (str == _("Best")) {
1367 } else if (str == _("Good")) {
1369 } else if (str == _("Quick")) {
1371 } else if (str == _("Fast")) {
1379 SoundFileOmega::get_channel_disposition () const
1381 /* we use a map here because the channel combo can contain different strings
1382 depending on the state of the other combos. the map contains all possible strings
1383 and the ImportDisposition enum that corresponds to it.
1386 ustring str = channel_combo.get_active_text();
1387 DispositionMap::const_iterator x = disposition_map.find (str);
1389 if (x == disposition_map.end()) {
1390 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1398 SoundFileOmega::reset (int selected_tracks)
1400 selected_track_cnt = selected_tracks;
1405 SoundFileOmega::file_selection_changed ()
1407 if (resetting_ourselves) {
1411 if (!reset_options ()) {
1412 set_response_sensitive (RESPONSE_OK, false);
1414 if (chooser.get_filenames().size() > 0) {
1415 set_response_sensitive (RESPONSE_OK, true);
1417 set_response_sensitive (RESPONSE_OK, false);