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/region_factory.h>
45 #include <ardour/source_factory.h>
46 #include <ardour/profile.h>
48 #include "ardour_ui.h"
50 #include "gui_thread.h"
55 #include "gain_meter.h"
58 #include "sfdb_freesound_mootcher.h"
63 using namespace ARDOUR;
67 using namespace Gtkmm2ext;
68 using namespace Editing;
72 ustring SoundFileBrowser::persistent_folder;
75 string2importmode (string str)
77 if (str == _("as new tracks")) {
79 } else if (str == _("to selected tracks")) {
81 } else if (str == _("to region list")) {
82 return ImportAsRegion;
83 } else if (str == _("as new tape tracks")) {
84 return ImportAsTapeTrack;
87 warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
93 importmode2string (ImportMode mode)
97 return _("as new tracks");
99 return _("to selected tracks");
101 return _("to region list");
102 case ImportAsTapeTrack:
103 return _("as new tape tracks");
106 return _("as new tracks");
109 SoundFileBox::SoundFileBox (bool persistent)
112 length_clock ("sfboxLengthClock", !persistent, "EditCursorClock", false, true, false),
113 timecode_clock ("sfboxTimecodeClock", !persistent, "EditCursorClock", false, false, false),
115 autoplay_btn (_("Auto-play"))
121 set_name (X_("SoundFileBox"));
122 set_size_request (300, -1);
124 preview_label.set_markup (_("<b>Soundfile Info</b>"));
126 border_frame.set_label_widget (preview_label);
127 border_frame.add (main_box);
129 pack_start (border_frame, true, true);
130 set_border_width (6);
132 main_box.set_border_width (6);
133 main_box.set_spacing (12);
135 length.set_text (_("Length:"));
136 timecode.set_text (_("Timestamp:"));
137 format.set_text (_("Format:"));
138 channels.set_text (_("Channels:"));
139 samplerate.set_text (_("Sample rate:"));
141 table.set_col_spacings (6);
142 table.set_homogeneous (false);
143 table.set_row_spacings (6);
145 table.attach (channels, 0, 1, 0, 1, FILL|EXPAND, (AttachOptions) 0);
146 table.attach (samplerate, 0, 1, 1, 2, FILL|EXPAND, (AttachOptions) 0);
147 table.attach (format, 0, 1, 2, 4, FILL|EXPAND, (AttachOptions) 0);
148 table.attach (length, 0, 1, 4, 5, FILL|EXPAND, (AttachOptions) 0);
149 table.attach (timecode, 0, 1, 5, 6, FILL|EXPAND, (AttachOptions) 0);
151 table.attach (channels_value, 1, 2, 0, 1, FILL, (AttachOptions) 0);
152 table.attach (samplerate_value, 1, 2, 1, 2, FILL, (AttachOptions) 0);
153 table.attach (format_text, 1, 2, 2, 4, FILL, AttachOptions (0));
154 table.attach (length_clock, 1, 2, 4, 5, FILL, (AttachOptions) 0);
155 table.attach (timecode_clock, 1, 2, 5, 6, FILL, (AttachOptions) 0);
157 length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock.mode());
158 timecode_clock.set_mode (AudioClock::SMPTE);
160 hbox = manage (new HBox);
161 hbox->pack_start (table, false, false);
162 main_box.pack_start (*hbox, false, false);
164 tags_entry.set_editable (true);
165 tags_entry.signal_focus_out_event().connect (mem_fun (*this, &SoundFileBox::tags_entry_left));
166 hbox = manage (new HBox);
167 hbox->pack_start (tags_entry, true, true);
169 vbox = manage (new VBox);
171 Label* label = manage (new Label (_("Tags:")));
172 label->set_alignment (0.0f, 0.5f);
173 vbox->set_spacing (6);
174 vbox->pack_start(*label, false, false);
175 vbox->pack_start(*hbox, true, true);
177 main_box.pack_start(*vbox, true, true);
178 main_box.pack_start(bottom_box, false, false);
180 play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
181 play_btn.set_label (_("Play (double click)"));
183 stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
184 stop_btn.set_label (_("Stop"));
186 bottom_box.set_homogeneous (false);
187 bottom_box.set_spacing (6);
188 bottom_box.pack_start(play_btn, true, true);
189 bottom_box.pack_start(stop_btn, true, true);
190 bottom_box.pack_start(autoplay_btn, false, false);
192 play_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::audition));
193 stop_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::stop_audition));
195 length.set_alignment (0.0f, 0.5f);
196 format.set_alignment (0.0f, 0.5f);
197 channels.set_alignment (0.0f, 0.5f);
198 samplerate.set_alignment (0.0f, 0.5f);
199 timecode.set_alignment (0.0f, 0.5f);
201 channels_value.set_alignment (0.0f, 0.5f);
202 samplerate_value.set_alignment (0.0f, 0.5f);
206 SoundFileBox::set_session(Session* s)
211 play_btn.set_sensitive (false);
212 stop_btn.set_sensitive (false);
216 length_clock.set_session (s);
217 timecode_clock.set_session (s);
221 SoundFileBox::setup_labels (const ustring& filename)
224 // save existing tags
232 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
234 preview_label.set_markup (_("<b>Soundfile Info</b>"));
235 format_text.set_text (_("n/a"));
236 channels_value.set_text (_("n/a"));
237 samplerate_value.set_text (_("n/a"));
238 tags_entry.get_buffer()->set_text ("");
240 length_clock.set (0);
241 timecode_clock.set (0);
243 tags_entry.set_sensitive (false);
244 play_btn.set_sensitive (false);
249 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::path_get_basename (filename)));
250 format_text.set_text (sf_info.format_name);
251 channels_value.set_text (to_string (sf_info.channels, std::dec));
253 if (_session && sf_info.samplerate != _session->frame_rate()) {
254 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
255 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
256 samplerate_value.set_name ("NewSessionSR1Label");
257 samplerate.set_name ("NewSessionSR1Label");
259 samplerate.set_text (_("Sample rate:"));
260 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
261 samplerate_value.set_name ("NewSessionSR2Label");
262 samplerate.set_name ("NewSessionSR2Label");
265 length_clock.set (sf_info.length, true);
266 timecode_clock.set (sf_info.timecode, true);
268 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
270 vector<string> tags = Library->get_tags (string ("//") + filename);
272 stringstream tag_string;
273 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
274 if (i != tags.begin()) {
279 tags_entry.get_buffer()->set_text (tag_string.str());
281 tags_entry.set_sensitive (true);
283 play_btn.set_sensitive (true);
290 SoundFileBox::autoplay() const
292 return autoplay_btn.get_active();
296 SoundFileBox::audition_oneshot()
303 SoundFileBox::audition ()
309 _session->cancel_audition();
311 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
312 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
316 boost::shared_ptr<Region> r;
318 boost::shared_ptr<AudioFileSource> afs;
319 bool old_sbp = AudioSource::get_build_peakfiles ();
321 /* don't even think of building peakfiles for these files */
323 AudioSource::set_build_peakfiles (false);
325 for (int n = 0; n < sf_info.channels; ++n) {
327 afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (*_session, path, n, AudioFileSource::Flag (0), false));
329 srclist.push_back(afs);
331 } catch (failed_constructor& err) {
332 error << _("Could not access soundfile: ") << path << endmsg;
333 AudioSource::set_build_peakfiles (old_sbp);
338 AudioSource::set_build_peakfiles (old_sbp);
340 if (srclist.empty()) {
344 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
345 string rname = region_name_from_path (afs->path(), false);
346 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, 0, srclist[0]->length(), rname, 0, Region::DefaultFlags, false));
348 _session->audition_region(r);
352 SoundFileBox::stop_audition ()
355 _session->cancel_audition();
360 SoundFileBox::tags_entry_left (GdkEventFocus *ev)
367 SoundFileBox::tags_changed ()
369 string tag_string = tags_entry.get_buffer()->get_text ();
371 if (tag_string.empty()) {
377 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
378 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
386 SoundFileBox::save_tags (const vector<string>& tags)
388 Library->set_tags (string ("//") + path, tags);
389 Library->save_changes ();
392 SoundFileBrowser::SoundFileBrowser (Gtk::Window& parent, string title, ARDOUR::Session* s, bool persistent)
393 : ArdourDialog (parent, title, false, false),
394 found_list (ListStore::create(found_list_columns)),
395 freesound_list (ListStore::create(freesound_list_columns)),
396 chooser (FILE_CHOOSER_ACTION_OPEN),
397 found_list_view (found_list),
398 freesound_list_view (freesound_list),
399 preview (persistent),
400 found_search_btn (_("Search")),
401 freesound_search_btn (_("Start Downloading"))
404 resetting_ourselves = false;
407 if (ARDOUR::Profile->get_sae()) {
408 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
409 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
412 //add the file chooser
414 chooser.set_border_width (12);
415 custom_filter.add_custom (FILE_FILTER_FILENAME, mem_fun(*this, &SoundFileBrowser::on_custom));
416 custom_filter.set_name (_("Audio files"));
418 matchall_filter.add_pattern ("*.*");
419 matchall_filter.set_name (_("All files"));
421 chooser.add_filter (custom_filter);
422 chooser.add_filter (matchall_filter);
423 chooser.set_select_multiple (true);
424 chooser.signal_update_preview().connect(mem_fun(*this, &SoundFileBrowser::update_preview));
425 chooser.signal_file_activated().connect (mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
427 if (!persistent_folder.empty()) {
428 chooser.set_current_folder (persistent_folder);
430 notebook.append_page (chooser, _("Browse Files"));
438 hpacker.set_spacing (6);
439 hpacker.pack_start (notebook, true, true);
440 hpacker.pack_start (preview, false, false);
442 get_vbox()->pack_start (hpacker, true, true);
444 hbox = manage(new HBox);
445 hbox->pack_start (found_entry);
446 hbox->pack_start (found_search_btn);
448 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
449 scroll->add(found_list_view);
450 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
452 vbox = manage(new VBox);
453 vbox->pack_start (*hbox, PACK_SHRINK);
454 vbox->pack_start (*scroll);
456 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
458 found_list_view.get_selection()->signal_changed().connect(mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
460 found_list_view.signal_row_activated().connect (mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
462 found_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked));
463 found_entry.signal_activate().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked));
465 notebook.append_page (*vbox, _("Search Tags"));
468 //add freesound search
475 hpacker.set_spacing (6);
476 hpacker.pack_start (notebook, true, true);
477 hpacker.pack_start (preview, false, false);
479 get_vbox()->pack_start (hpacker, true, true);
481 passbox = manage(new HBox);
482 passbox->set_border_width (12);
483 passbox->set_spacing (6);
485 label = manage (new Label);
486 label->set_text (_("User:"));
487 passbox->pack_start (*label, false, false);
488 passbox->pack_start (freesound_name_entry);
489 label = manage (new Label);
490 label->set_text (_("Password:"));
491 passbox->pack_start (*label, false, false);
492 passbox->pack_start (freesound_pass_entry);
493 label = manage (new Label);
494 label->set_text (_("Tags:"));
495 passbox->pack_start (*label, false, false);
496 passbox->pack_start (freesound_entry, false, false);
497 passbox->pack_start (freesound_search_btn, false, false);
499 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
500 scroll->add(freesound_list_view);
501 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
503 vbox = manage(new VBox);
504 vbox->pack_start (*passbox, PACK_SHRINK);
505 vbox->pack_start(*scroll);
507 //vbox->pack_start (freesound_list_view);
509 freesound_list_view.append_column(_("Paths"), freesound_list_columns.pathname);
511 freesound_list_view.get_selection()->signal_changed().connect(mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
513 //freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
514 freesound_list_view.signal_row_activated().connect (mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
516 freesound_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
517 freesound_entry.signal_activate().connect(mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
519 notebook.append_page (*vbox, _("Search Freesound"));
524 notebook.set_size_request (500, -1);
528 add_button (Stock::CANCEL, RESPONSE_CANCEL);
529 add_button (Stock::APPLY, RESPONSE_APPLY);
530 add_button (Stock::OK, RESPONSE_OK);
534 SoundFileBrowser::~SoundFileBrowser ()
536 persistent_folder = chooser.get_current_folder();
541 SoundFileBrowser::on_show ()
543 ArdourDialog::on_show ();
548 SoundFileBrowser::clear_selection ()
550 chooser.unselect_all ();
551 found_list_view.get_selection()->unselect_all ();
555 SoundFileBrowser::chooser_file_activated ()
561 SoundFileBrowser::found_list_view_activated (const TreeModel::Path& path, TreeViewColumn* col)
567 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path& path, TreeViewColumn* col)
573 SoundFileBrowser::set_session (Session* s)
575 ArdourDialog::set_session (s);
576 preview.set_session (s);
580 remove_gain_meter ();
585 SoundFileBrowser::add_gain_meter ()
591 gm = new GainMeter (session->the_auditioner(), *session);
593 meter_packer.set_border_width (12);
594 meter_packer.pack_start (*gm, false, true);
595 hpacker.pack_end (meter_packer, false, false);
596 meter_packer.show_all ();
601 SoundFileBrowser::remove_gain_meter ()
604 meter_packer.remove (*gm);
605 hpacker.remove (meter_packer);
612 SoundFileBrowser::start_metering ()
614 metering_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun(*this, &SoundFileBrowser::meter));
618 SoundFileBrowser::stop_metering ()
620 metering_connection.disconnect();
624 SoundFileBrowser::meter ()
626 if (is_mapped () && session && gm) {
627 gm->update_meters ();
632 SoundFileBrowser::on_custom (const FileFilter::Info& filter_info)
634 return AudioFileSource::safe_file_extension (filter_info.filename);
638 SoundFileBrowser::update_preview ()
640 if (preview.setup_labels (chooser.get_filename())) {
641 if (preview.autoplay()) {
642 Glib::signal_idle().connect (mem_fun (preview, &SoundFileBox::audition_oneshot));
648 SoundFileBrowser::found_list_view_selected ()
650 if (!reset_options ()) {
651 set_response_sensitive (RESPONSE_OK, false);
655 TreeView::Selection::ListHandle_Path rows = found_list_view.get_selection()->get_selected_rows ();
658 TreeIter iter = found_list->get_iter(*rows.begin());
659 file = (*iter)[found_list_columns.pathname];
660 chooser.set_filename (file);
661 set_response_sensitive (RESPONSE_OK, true);
663 set_response_sensitive (RESPONSE_OK, false);
666 preview.setup_labels (file);
671 SoundFileBrowser::freesound_list_view_selected ()
673 if (!reset_options ()) {
674 set_response_sensitive (RESPONSE_OK, false);
678 TreeView::Selection::ListHandle_Path rows = freesound_list_view.get_selection()->get_selected_rows ();
681 TreeIter iter = freesound_list->get_iter(*rows.begin());
682 file = (*iter)[freesound_list_columns.pathname];
683 chooser.set_filename (file);
684 set_response_sensitive (RESPONSE_OK, true);
686 set_response_sensitive (RESPONSE_OK, false);
689 preview.setup_labels (file);
694 SoundFileBrowser::found_search_clicked ()
696 string tag_string = found_entry.get_text ();
700 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
701 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
705 vector<string> results;
706 Library->search_members_and (results, tags);
709 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
710 TreeModel::iterator new_row = found_list->append();
711 TreeModel::Row row = *new_row;
712 string path = Glib::filename_from_uri (string ("file:") + *i);
713 row[found_list_columns.pathname] = path;
718 freesound_search_thread_entry (void* arg)
720 PBD::ThreadCreated (pthread_self(), X_("Freesound Search"));
722 static_cast<SoundFileBrowser*>(arg)->freesound_search_thread ();
727 bool searching = false;
728 bool canceling = false;
731 SoundFileBrowser::freesound_search_clicked ()
733 if (canceling) //already canceling, button does nothing
737 freesound_search_btn.set_label(_("Cancelling.."));
741 freesound_search_btn.set_label(_("Cancel"));
742 pthread_t freesound_thr;
743 pthread_create_and_store ("freesound_search", &freesound_thr, 0, freesound_search_thread_entry, this);
748 SoundFileBrowser::freesound_search_thread()
751 freesound_list->clear();
754 path = Glib::get_home_dir();
755 path += "/Freesound/";
756 Mootcher theMootcher(path.c_str());
758 string name_string = freesound_name_entry.get_text ();
759 string pass_string = freesound_pass_entry.get_text ();
760 string search_string = freesound_entry.get_text ();
762 if ( theMootcher.doLogin( name_string, pass_string ) ) {
764 string theString = theMootcher.searchText(search_string);
767 doc.read_buffer( theString );
768 XMLNode *root = doc.root();
770 if (root==NULL) return;
772 if ( strcmp(root->name().c_str(), "freesound") == 0) {
775 XMLNodeList children = root->children();
776 XMLNodeConstIterator niter;
777 for (niter = children.begin(); niter != children.end() && !canceling; ++niter) {
779 if( strcmp( node->name().c_str(), "sample") == 0 ){
780 XMLProperty *prop=node->property ("id");
781 string filename = theMootcher.getFile( prop->value().c_str() );
782 if ( filename != "" ) {
783 TreeModel::iterator new_row = freesound_list->append();
784 TreeModel::Row row = *new_row;
785 string path = Glib::filename_from_uri (string ("file:") + filename);
786 row[freesound_list_columns.pathname] = path;
795 freesound_search_btn.set_label(_("Start Downloading"));
800 SoundFileBrowser::get_paths ()
802 vector<ustring> results;
804 int n = notebook.get_current_page ();
807 vector<ustring> filenames = chooser.get_filenames();
808 vector<ustring>::iterator i;
810 for (i = filenames.begin(); i != filenames.end(); ++i) {
812 if ((!stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
813 results.push_back (*i);
819 typedef TreeView::Selection::ListHandle_Path ListPath;
821 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
822 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
823 TreeIter iter = found_list->get_iter(*i);
824 ustring str = (*iter)[found_list_columns.pathname];
826 results.push_back (str);
830 typedef TreeView::Selection::ListHandle_Path ListPath;
832 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
833 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
834 TreeIter iter = freesound_list->get_iter(*i);
835 ustring str = (*iter)[freesound_list_columns.pathname];
837 results.push_back (str);
845 SoundFileOmega::reset_options_noret ()
847 if (!resetting_ourselves) {
848 (void) reset_options ();
853 SoundFileOmega::reset_options ()
855 vector<ustring> paths = get_paths ();
859 channel_combo.set_sensitive (false);
860 action_combo.set_sensitive (false);
861 where_combo.set_sensitive (false);
862 copy_files_btn.set_sensitive (false);
868 channel_combo.set_sensitive (true);
869 action_combo.set_sensitive (true);
870 where_combo.set_sensitive (true);
872 /* if we get through this function successfully, this may be
873 reset at the end, once we know if we can use hard links
877 if (Config->get_only_copy_imported_files()) {
878 copy_files_btn.set_sensitive (false);
880 copy_files_btn.set_sensitive (false);
886 bool selection_includes_multichannel;
887 bool selection_can_be_embedded_with_links = check_link_status (*session, paths);
890 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
891 Glib::signal_idle().connect (mem_fun (*this, &SoundFileOmega::bad_file_message));
895 ustring existing_choice;
896 vector<string> action_strings;
898 if (selected_track_cnt > 0) {
899 if (channel_combo.get_active_text().length()) {
900 ImportDisposition id = get_channel_disposition();
903 case Editing::ImportDistinctFiles:
904 if (selected_track_cnt == paths.size()) {
905 action_strings.push_back (importmode2string (ImportToTrack));
909 case Editing::ImportDistinctChannels:
910 /* XXX it would be nice to allow channel-per-selected track
911 but its too hard we don't want to deal with all the
912 different per-file + per-track channel configurations.
917 action_strings.push_back (importmode2string (ImportToTrack));
923 action_strings.push_back (importmode2string (ImportAsTrack));
924 action_strings.push_back (importmode2string (ImportAsRegion));
925 action_strings.push_back (importmode2string (ImportAsTapeTrack));
927 resetting_ourselves = true;
929 existing_choice = action_combo.get_active_text();
931 set_popdown_strings (action_combo, action_strings);
933 /* preserve any existing choice, if possible */
936 if (existing_choice.length()) {
937 vector<string>::iterator x;
938 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
939 if (*x == existing_choice) {
940 action_combo.set_active_text (existing_choice);
944 if (x == action_strings.end()) {
945 action_combo.set_active_text (action_strings.front());
948 action_combo.set_active_text (action_strings.front());
951 resetting_ourselves = false;
953 if ((mode = get_mode()) == ImportAsRegion) {
954 where_combo.set_sensitive (false);
956 where_combo.set_sensitive (true);
959 vector<string> channel_strings;
961 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
962 channel_strings.push_back (_("one track per file"));
964 if (selection_includes_multichannel) {
965 channel_strings.push_back (_("one track per channel"));
968 if (paths.size() > 1) {
969 /* tape tracks are a single region per track, so we cannot
970 sequence multiple files.
972 if (mode != ImportAsTapeTrack) {
973 channel_strings.push_back (_("sequence files"));
976 channel_strings.push_back (_("all files in one region"));
982 channel_strings.push_back (_("one region per file"));
984 if (selection_includes_multichannel) {
985 channel_strings.push_back (_("one region per channel"));
988 if (paths.size() > 1) {
990 channel_strings.push_back (_("all files in one region"));
995 existing_choice = channel_combo.get_active_text();
997 set_popdown_strings (channel_combo, channel_strings);
999 /* preserve any existing choice, if possible */
1001 if (existing_choice.length()) {
1002 vector<string>::iterator x;
1003 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1004 if (*x == existing_choice) {
1005 channel_combo.set_active_text (existing_choice);
1009 if (x == channel_strings.end()) {
1010 channel_combo.set_active_text (channel_strings.front());
1013 channel_combo.set_active_text (channel_strings.front());
1017 src_combo.set_sensitive (true);
1019 src_combo.set_sensitive (false);
1022 if (Config->get_only_copy_imported_files()) {
1024 if (selection_can_be_embedded_with_links) {
1025 copy_files_btn.set_sensitive (true);
1027 copy_files_btn.set_sensitive (false);
1032 copy_files_btn.set_sensitive (true);
1040 SoundFileOmega::bad_file_message()
1042 MessageDialog msg (*this,
1043 _("One or more of the selected files\ncannot be used by Ardour"),
1048 resetting_ourselves = true;
1049 chooser.unselect_uri (chooser.get_preview_uri());
1050 resetting_ourselves = false;
1056 SoundFileOmega::check_info (const vector<ustring>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1065 multichannel = false;
1067 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1069 if (!AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1073 if (info.channels > 1) {
1074 multichannel = true;
1080 if (sz != info.length) {
1085 if ((nframes_t) info.samplerate != session->frame_rate()) {
1095 SoundFileOmega::check_link_status (const Session& s, const vector<ustring>& paths)
1097 string tmpdir = s.sound_dir();
1100 tmpdir += "/linktest";
1102 if (mkdir (tmpdir.c_str(), 0744)) {
1103 if (errno != EEXIST) {
1108 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1110 char tmpc[MAXPATHLEN+1];
1112 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1116 if (link ((*i).c_str(), tmpc)) {
1126 rmdir (tmpdir.c_str());
1130 SoundFileChooser::SoundFileChooser (Gtk::Window& parent, string title, ARDOUR::Session* s)
1131 : SoundFileBrowser (parent, title, s, false)
1133 chooser.set_select_multiple (false);
1134 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1135 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1139 SoundFileChooser::on_hide ()
1141 ArdourDialog::on_hide();
1145 session->cancel_audition();
1150 SoundFileChooser::get_filename ()
1152 vector<ustring> paths;
1154 paths = get_paths ();
1156 if (paths.empty()) {
1160 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1164 return paths.front();
1167 SoundFileOmega::SoundFileOmega (Gtk::Window& parent, string title, ARDOUR::Session* s, int selected_tracks, bool persistent,
1168 Editing::ImportMode mode_hint)
1169 : SoundFileBrowser (parent, title, s, persistent),
1170 copy_files_btn ( _("Copy files to session")),
1171 selected_track_cnt (selected_tracks)
1177 set_size_request (-1, 450);
1179 block_two.set_border_width (12);
1180 block_three.set_border_width (12);
1181 block_four.set_border_width (12);
1183 options.set_spacing (12);
1186 str.push_back (_("use file timestamp"));
1187 str.push_back (_("at edit point"));
1188 str.push_back (_("at playhead"));
1189 str.push_back (_("at session start"));
1190 set_popdown_strings (where_combo, str);
1191 where_combo.set_active_text (str.front());
1193 Label* l = manage (new Label);
1194 l->set_text (_("Add files:"));
1196 hbox = manage (new HBox);
1197 hbox->set_border_width (12);
1198 hbox->set_spacing (6);
1199 hbox->pack_start (*l, false, false);
1200 hbox->pack_start (action_combo, false, false);
1201 vbox = manage (new VBox);
1202 vbox->pack_start (*hbox, false, false);
1203 options.pack_start (*vbox, false, false);
1205 /* dummy entry for action combo so that it doesn't look odd if we
1206 come up with no tracks selected.
1210 str.push_back (importmode2string (mode_hint));
1211 set_popdown_strings (action_combo, str);
1212 action_combo.set_active_text (str.front());
1213 action_combo.set_sensitive (false);
1215 l = manage (new Label);
1216 l->set_text (_("Insert:"));
1218 hbox = manage (new HBox);
1219 hbox->set_border_width (12);
1220 hbox->set_spacing (6);
1221 hbox->pack_start (*l, false, false);
1222 hbox->pack_start (where_combo, false, false);
1223 vbox = manage (new VBox);
1224 vbox->pack_start (*hbox, false, false);
1225 options.pack_start (*vbox, false, false);
1228 l = manage (new Label);
1229 l->set_text (_("Mapping:"));
1231 hbox = manage (new HBox);
1232 hbox->set_border_width (12);
1233 hbox->set_spacing (6);
1234 hbox->pack_start (*l, false, false);
1235 hbox->pack_start (channel_combo, false, false);
1236 vbox = manage (new VBox);
1237 vbox->pack_start (*hbox, false, false);
1238 options.pack_start (*vbox, false, false);
1241 str.push_back (_("one track per file"));
1242 set_popdown_strings (channel_combo, str);
1243 channel_combo.set_active_text (str.front());
1244 channel_combo.set_sensitive (false);
1246 l = manage (new Label);
1247 l->set_text (_("Conversion Quality:"));
1249 hbox = manage (new HBox);
1250 hbox->set_border_width (12);
1251 hbox->set_spacing (6);
1252 hbox->pack_start (*l, false, false);
1253 hbox->pack_start (src_combo, false, false);
1254 vbox = manage (new VBox);
1255 vbox->pack_start (*hbox, false, false);
1256 options.pack_start (*vbox, false, false);
1259 str.push_back (_("Best"));
1260 str.push_back (_("Good"));
1261 str.push_back (_("Quick"));
1262 str.push_back (_("Fast"));
1263 str.push_back (_("Fastest"));
1265 set_popdown_strings (src_combo, str);
1266 src_combo.set_active_text (str.front());
1267 src_combo.set_sensitive (false);
1271 action_combo.signal_changed().connect (mem_fun (*this, &SoundFileOmega::reset_options_noret));
1273 copy_files_btn.set_active (true);
1275 block_four.pack_start (copy_files_btn, false, false);
1277 options.pack_start (block_four, false, false);
1279 get_vbox()->pack_start (options, false, false);
1281 /* setup disposition map */
1283 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1284 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1285 disposition_map.insert (pair<ustring,ImportDisposition>(_("merge files"), ImportMergeFiles));
1286 disposition_map.insert (pair<ustring,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1288 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1289 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1290 disposition_map.insert (pair<ustring,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1292 chooser.signal_selection_changed().connect (mem_fun (*this, &SoundFileOmega::file_selection_changed));
1296 SoundFileOmega::set_mode (ImportMode mode)
1298 action_combo.set_active_text (importmode2string (mode));
1302 SoundFileOmega::get_mode () const
1304 return string2importmode (action_combo.get_active_text());
1308 SoundFileOmega::on_hide ()
1310 ArdourDialog::on_hide();
1312 session->cancel_audition();
1317 SoundFileOmega::get_position() const
1319 ustring str = where_combo.get_active_text();
1321 if (str == _("use file timestamp")) {
1322 return ImportAtTimestamp;
1323 } else if (str == _("at edit point")) {
1324 return ImportAtEditPoint;
1325 } else if (str == _("at playhead")) {
1326 return ImportAtPlayhead;
1328 return ImportAtStart;
1333 SoundFileOmega::get_src_quality() const
1335 ustring str = where_combo.get_active_text();
1337 if (str == _("Best")) {
1339 } else if (str == _("Good")) {
1341 } else if (str == _("Quick")) {
1343 } else if (str == _("Fast")) {
1351 SoundFileOmega::get_channel_disposition () const
1353 /* we use a map here because the channel combo can contain different strings
1354 depending on the state of the other combos. the map contains all possible strings
1355 and the ImportDisposition enum that corresponds to it.
1358 ustring str = channel_combo.get_active_text();
1359 DispositionMap::const_iterator x = disposition_map.find (str);
1361 if (x == disposition_map.end()) {
1362 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1370 SoundFileOmega::reset (int selected_tracks)
1372 selected_track_cnt = selected_tracks;
1377 SoundFileOmega::file_selection_changed ()
1379 if (resetting_ourselves) {
1383 if (!reset_options ()) {
1384 set_response_sensitive (RESPONSE_OK, false);
1386 if (chooser.get_filenames().size() > 0) {
1387 set_response_sensitive (RESPONSE_OK, true);
1389 set_response_sensitive (RESPONSE_OK, false);