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 preview (persistent),
398 found_search_btn (_("Search")),
399 found_list_view (found_list),
400 freesound_search_btn (_("Start Downloading")),
401 freesound_list_view (freesound_list)
403 resetting_ourselves = false;
406 if (ARDOUR::Profile->get_sae()) {
407 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
408 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
411 //add the file chooser
413 chooser.set_border_width (12);
414 custom_filter.add_custom (FILE_FILTER_FILENAME, mem_fun(*this, &SoundFileBrowser::on_custom));
415 custom_filter.set_name (_("Audio files"));
417 matchall_filter.add_pattern ("*.*");
418 matchall_filter.set_name (_("All files"));
420 chooser.add_filter (custom_filter);
421 chooser.add_filter (matchall_filter);
422 chooser.set_select_multiple (true);
423 chooser.signal_update_preview().connect(mem_fun(*this, &SoundFileBrowser::update_preview));
424 chooser.signal_file_activated().connect (mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
426 if (!persistent_folder.empty()) {
427 chooser.set_current_folder (persistent_folder);
429 notebook.append_page (chooser, _("Browse Files"));
432 hpacker.set_spacing (6);
433 hpacker.pack_start (notebook, true, true);
434 hpacker.pack_start (preview, false, false);
436 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 passbox = manage(new HBox);
476 passbox->set_border_width (12);
477 passbox->set_spacing (6);
479 label = manage (new Label);
480 label->set_text (_("User:"));
481 passbox->pack_start (*label, false, false);
482 passbox->pack_start (freesound_name_entry);
483 label = manage (new Label);
484 label->set_text (_("Password:"));
485 passbox->pack_start (*label, false, false);
486 passbox->pack_start (freesound_pass_entry);
487 label = manage (new Label);
488 label->set_text (_("Tags:"));
489 passbox->pack_start (*label, false, false);
490 passbox->pack_start (freesound_entry, false, false);
491 passbox->pack_start (freesound_search_btn, false, false);
493 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
494 scroll->add(freesound_list_view);
495 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
497 vbox = manage(new VBox);
498 vbox->pack_start (*passbox, PACK_SHRINK);
499 vbox->pack_start(*scroll);
501 //vbox->pack_start (freesound_list_view);
503 freesound_list_view.append_column(_("Paths"), freesound_list_columns.pathname);
505 freesound_list_view.get_selection()->signal_changed().connect(mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
507 //freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
508 freesound_list_view.signal_row_activated().connect (mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
510 freesound_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
511 freesound_entry.signal_activate().connect(mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
513 notebook.append_page (*vbox, _("Search Freesound"));
518 notebook.set_size_request (500, -1);
522 add_button (Stock::CANCEL, RESPONSE_CANCEL);
523 add_button (Stock::APPLY, RESPONSE_APPLY);
524 add_button (Stock::OK, RESPONSE_OK);
528 SoundFileBrowser::~SoundFileBrowser ()
530 persistent_folder = chooser.get_current_folder();
535 SoundFileBrowser::on_show ()
537 ArdourDialog::on_show ();
542 SoundFileBrowser::clear_selection ()
544 chooser.unselect_all ();
545 found_list_view.get_selection()->unselect_all ();
549 SoundFileBrowser::chooser_file_activated ()
555 SoundFileBrowser::found_list_view_activated (const TreeModel::Path& path, TreeViewColumn* col)
561 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path& path, TreeViewColumn* col)
567 SoundFileBrowser::set_session (Session* s)
569 ArdourDialog::set_session (s);
570 preview.set_session (s);
574 remove_gain_meter ();
579 SoundFileBrowser::add_gain_meter ()
585 gm = new GainMeter (session->the_auditioner(), *session);
587 meter_packer.set_border_width (12);
588 meter_packer.pack_start (*gm, false, true);
589 hpacker.pack_end (meter_packer, false, false);
590 meter_packer.show_all ();
595 SoundFileBrowser::remove_gain_meter ()
598 meter_packer.remove (*gm);
599 hpacker.remove (meter_packer);
606 SoundFileBrowser::start_metering ()
608 metering_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun(*this, &SoundFileBrowser::meter));
612 SoundFileBrowser::stop_metering ()
614 metering_connection.disconnect();
618 SoundFileBrowser::meter ()
620 if (is_mapped () && session && gm) {
621 gm->update_meters ();
626 SoundFileBrowser::on_custom (const FileFilter::Info& filter_info)
628 return AudioFileSource::safe_file_extension (filter_info.filename);
632 SoundFileBrowser::update_preview ()
634 if (preview.setup_labels (chooser.get_filename())) {
635 if (preview.autoplay()) {
636 Glib::signal_idle().connect (mem_fun (preview, &SoundFileBox::audition_oneshot));
642 SoundFileBrowser::found_list_view_selected ()
644 if (!reset_options ()) {
645 set_response_sensitive (RESPONSE_OK, false);
649 TreeView::Selection::ListHandle_Path rows = found_list_view.get_selection()->get_selected_rows ();
652 TreeIter iter = found_list->get_iter(*rows.begin());
653 file = (*iter)[found_list_columns.pathname];
654 chooser.set_filename (file);
655 set_response_sensitive (RESPONSE_OK, true);
657 set_response_sensitive (RESPONSE_OK, false);
660 preview.setup_labels (file);
665 SoundFileBrowser::freesound_list_view_selected ()
667 if (!reset_options ()) {
668 set_response_sensitive (RESPONSE_OK, false);
672 TreeView::Selection::ListHandle_Path rows = freesound_list_view.get_selection()->get_selected_rows ();
675 TreeIter iter = freesound_list->get_iter(*rows.begin());
676 file = (*iter)[freesound_list_columns.pathname];
677 chooser.set_filename (file);
678 set_response_sensitive (RESPONSE_OK, true);
680 set_response_sensitive (RESPONSE_OK, false);
683 preview.setup_labels (file);
688 SoundFileBrowser::found_search_clicked ()
690 string tag_string = found_entry.get_text ();
694 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
695 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
699 vector<string> results;
700 Library->search_members_and (results, tags);
703 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
704 TreeModel::iterator new_row = found_list->append();
705 TreeModel::Row row = *new_row;
706 string path = Glib::filename_from_uri (string ("file:") + *i);
707 row[found_list_columns.pathname] = path;
712 freesound_search_thread_entry (void* arg)
714 PBD::ThreadCreated (pthread_self(), X_("Freesound Search"));
716 static_cast<SoundFileBrowser*>(arg)->freesound_search_thread ();
721 bool searching = false;
722 bool canceling = false;
725 SoundFileBrowser::freesound_search_clicked ()
727 if (canceling) //already canceling, button does nothing
731 freesound_search_btn.set_label(_("Cancelling.."));
735 freesound_search_btn.set_label(_("Cancel"));
736 pthread_t freesound_thr;
737 pthread_create_and_store ("freesound_search", &freesound_thr, 0, freesound_search_thread_entry, this);
742 SoundFileBrowser::freesound_search_thread()
745 freesound_list->clear();
748 path = Glib::get_home_dir();
749 path += "/Freesound/";
750 Mootcher theMootcher(path.c_str());
752 string name_string = freesound_name_entry.get_text ();
753 string pass_string = freesound_pass_entry.get_text ();
754 string search_string = freesound_entry.get_text ();
756 if ( theMootcher.doLogin( name_string, pass_string ) ) {
758 string theString = theMootcher.searchText(search_string);
761 doc.read_buffer( theString );
762 XMLNode *root = doc.root();
764 if (root==NULL) return;
766 if ( strcmp(root->name().c_str(), "freesound") == 0) {
769 XMLNodeList children = root->children();
770 XMLNodeConstIterator niter;
771 for (niter = children.begin(); niter != children.end() && !canceling; ++niter) {
773 if( strcmp( node->name().c_str(), "sample") == 0 ){
774 XMLProperty *prop=node->property ("id");
775 string filename = theMootcher.getFile( prop->value().c_str() );
776 if ( filename != "" ) {
777 TreeModel::iterator new_row = freesound_list->append();
778 TreeModel::Row row = *new_row;
779 string path = Glib::filename_from_uri (string ("file:") + filename);
780 row[freesound_list_columns.pathname] = path;
789 freesound_search_btn.set_label(_("Start Downloading"));
794 SoundFileBrowser::get_paths ()
796 vector<ustring> results;
798 int n = notebook.get_current_page ();
801 vector<ustring> filenames = chooser.get_filenames();
802 vector<ustring>::iterator i;
804 for (i = filenames.begin(); i != filenames.end(); ++i) {
806 if ((!stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
807 results.push_back (*i);
813 typedef TreeView::Selection::ListHandle_Path ListPath;
815 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
816 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
817 TreeIter iter = found_list->get_iter(*i);
818 ustring str = (*iter)[found_list_columns.pathname];
820 results.push_back (str);
824 typedef TreeView::Selection::ListHandle_Path ListPath;
826 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
827 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
828 TreeIter iter = freesound_list->get_iter(*i);
829 ustring str = (*iter)[freesound_list_columns.pathname];
831 results.push_back (str);
839 SoundFileOmega::reset_options_noret ()
841 if (!resetting_ourselves) {
842 (void) reset_options ();
847 SoundFileOmega::reset_options ()
849 vector<ustring> paths = get_paths ();
853 channel_combo.set_sensitive (false);
854 action_combo.set_sensitive (false);
855 where_combo.set_sensitive (false);
856 copy_files_btn.set_sensitive (false);
862 channel_combo.set_sensitive (true);
863 action_combo.set_sensitive (true);
864 where_combo.set_sensitive (true);
866 /* if we get through this function successfully, this may be
867 reset at the end, once we know if we can use hard links
871 if (Config->get_only_copy_imported_files()) {
872 copy_files_btn.set_sensitive (false);
874 copy_files_btn.set_sensitive (false);
880 bool selection_includes_multichannel;
881 bool selection_can_be_embedded_with_links = check_link_status (*session, paths);
884 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
885 Glib::signal_idle().connect (mem_fun (*this, &SoundFileOmega::bad_file_message));
889 ustring existing_choice;
890 vector<string> action_strings;
892 if (selected_track_cnt > 0) {
893 if (channel_combo.get_active_text().length()) {
894 ImportDisposition id = get_channel_disposition();
897 case Editing::ImportDistinctFiles:
898 if (selected_track_cnt == paths.size()) {
899 action_strings.push_back (importmode2string (ImportToTrack));
903 case Editing::ImportDistinctChannels:
904 /* XXX it would be nice to allow channel-per-selected track
905 but its too hard we don't want to deal with all the
906 different per-file + per-track channel configurations.
911 action_strings.push_back (importmode2string (ImportToTrack));
917 action_strings.push_back (importmode2string (ImportAsTrack));
918 action_strings.push_back (importmode2string (ImportAsRegion));
919 action_strings.push_back (importmode2string (ImportAsTapeTrack));
921 resetting_ourselves = true;
923 existing_choice = action_combo.get_active_text();
925 set_popdown_strings (action_combo, action_strings);
927 /* preserve any existing choice, if possible */
930 if (existing_choice.length()) {
931 vector<string>::iterator x;
932 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
933 if (*x == existing_choice) {
934 action_combo.set_active_text (existing_choice);
938 if (x == action_strings.end()) {
939 action_combo.set_active_text (action_strings.front());
942 action_combo.set_active_text (action_strings.front());
945 resetting_ourselves = false;
947 if ((mode = get_mode()) == ImportAsRegion) {
948 where_combo.set_sensitive (false);
950 where_combo.set_sensitive (true);
953 vector<string> channel_strings;
955 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
956 channel_strings.push_back (_("one track per file"));
958 if (selection_includes_multichannel) {
959 channel_strings.push_back (_("one track per channel"));
962 if (paths.size() > 1) {
963 /* tape tracks are a single region per track, so we cannot
964 sequence multiple files.
966 if (mode != ImportAsTapeTrack) {
967 channel_strings.push_back (_("sequence files"));
970 channel_strings.push_back (_("all files in one region"));
976 channel_strings.push_back (_("one region per file"));
978 if (selection_includes_multichannel) {
979 channel_strings.push_back (_("one region per channel"));
982 if (paths.size() > 1) {
984 channel_strings.push_back (_("all files in one region"));
989 existing_choice = channel_combo.get_active_text();
991 set_popdown_strings (channel_combo, channel_strings);
993 /* preserve any existing choice, if possible */
995 if (existing_choice.length()) {
996 vector<string>::iterator x;
997 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
998 if (*x == existing_choice) {
999 channel_combo.set_active_text (existing_choice);
1003 if (x == channel_strings.end()) {
1004 channel_combo.set_active_text (channel_strings.front());
1007 channel_combo.set_active_text (channel_strings.front());
1011 src_combo.set_sensitive (true);
1013 src_combo.set_sensitive (false);
1016 if (Config->get_only_copy_imported_files()) {
1018 if (selection_can_be_embedded_with_links) {
1019 copy_files_btn.set_sensitive (true);
1021 copy_files_btn.set_sensitive (false);
1026 copy_files_btn.set_sensitive (true);
1034 SoundFileOmega::bad_file_message()
1036 MessageDialog msg (*this,
1037 _("One or more of the selected files\ncannot be used by Ardour"),
1042 resetting_ourselves = true;
1043 chooser.unselect_uri (chooser.get_preview_uri());
1044 resetting_ourselves = false;
1050 SoundFileOmega::check_info (const vector<ustring>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1059 multichannel = false;
1061 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1063 if (!AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1067 if (info.channels > 1) {
1068 multichannel = true;
1074 if (sz != info.length) {
1079 if ((nframes_t) info.samplerate != session->frame_rate()) {
1089 SoundFileOmega::check_link_status (const Session& s, const vector<ustring>& paths)
1091 string tmpdir = s.sound_dir();
1094 tmpdir += "/linktest";
1096 if (mkdir (tmpdir.c_str(), 0744)) {
1097 if (errno != EEXIST) {
1102 for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1104 char tmpc[MAXPATHLEN+1];
1106 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1110 if (link ((*i).c_str(), tmpc)) {
1120 rmdir (tmpdir.c_str());
1124 SoundFileChooser::SoundFileChooser (Gtk::Window& parent, string title, ARDOUR::Session* s)
1125 : SoundFileBrowser (parent, title, s, false)
1127 chooser.set_select_multiple (false);
1128 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1129 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1133 SoundFileChooser::on_hide ()
1135 ArdourDialog::on_hide();
1139 session->cancel_audition();
1144 SoundFileChooser::get_filename ()
1146 vector<ustring> paths;
1148 paths = get_paths ();
1150 if (paths.empty()) {
1154 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1158 return paths.front();
1161 SoundFileOmega::SoundFileOmega (Gtk::Window& parent, string title, ARDOUR::Session* s, int selected_tracks, bool persistent,
1162 Editing::ImportMode mode_hint)
1163 : SoundFileBrowser (parent, title, s, persistent),
1164 copy_files_btn ( _("Copy files to session")),
1165 selected_track_cnt (selected_tracks)
1171 set_size_request (-1, 450);
1173 block_two.set_border_width (12);
1174 block_three.set_border_width (12);
1175 block_four.set_border_width (12);
1177 options.set_spacing (12);
1180 str.push_back (_("use file timestamp"));
1181 str.push_back (_("at edit point"));
1182 str.push_back (_("at playhead"));
1183 str.push_back (_("at session start"));
1184 set_popdown_strings (where_combo, str);
1185 where_combo.set_active_text (str.front());
1187 Label* l = manage (new Label);
1188 l->set_text (_("Add files:"));
1190 hbox = manage (new HBox);
1191 hbox->set_border_width (12);
1192 hbox->set_spacing (6);
1193 hbox->pack_start (*l, false, false);
1194 hbox->pack_start (action_combo, false, false);
1195 vbox = manage (new VBox);
1196 vbox->pack_start (*hbox, false, false);
1197 options.pack_start (*vbox, false, false);
1199 /* dummy entry for action combo so that it doesn't look odd if we
1200 come up with no tracks selected.
1204 str.push_back (importmode2string (mode_hint));
1205 set_popdown_strings (action_combo, str);
1206 action_combo.set_active_text (str.front());
1207 action_combo.set_sensitive (false);
1209 l = manage (new Label);
1210 l->set_text (_("Insert:"));
1212 hbox = manage (new HBox);
1213 hbox->set_border_width (12);
1214 hbox->set_spacing (6);
1215 hbox->pack_start (*l, false, false);
1216 hbox->pack_start (where_combo, false, false);
1217 vbox = manage (new VBox);
1218 vbox->pack_start (*hbox, false, false);
1219 options.pack_start (*vbox, false, false);
1222 l = manage (new Label);
1223 l->set_text (_("Mapping:"));
1225 hbox = manage (new HBox);
1226 hbox->set_border_width (12);
1227 hbox->set_spacing (6);
1228 hbox->pack_start (*l, false, false);
1229 hbox->pack_start (channel_combo, false, false);
1230 vbox = manage (new VBox);
1231 vbox->pack_start (*hbox, false, false);
1232 options.pack_start (*vbox, false, false);
1235 str.push_back (_("one track per file"));
1236 set_popdown_strings (channel_combo, str);
1237 channel_combo.set_active_text (str.front());
1238 channel_combo.set_sensitive (false);
1240 l = manage (new Label);
1241 l->set_text (_("Conversion Quality:"));
1243 hbox = manage (new HBox);
1244 hbox->set_border_width (12);
1245 hbox->set_spacing (6);
1246 hbox->pack_start (*l, false, false);
1247 hbox->pack_start (src_combo, false, false);
1248 vbox = manage (new VBox);
1249 vbox->pack_start (*hbox, false, false);
1250 options.pack_start (*vbox, false, false);
1253 str.push_back (_("Best"));
1254 str.push_back (_("Good"));
1255 str.push_back (_("Quick"));
1256 str.push_back (_("Fast"));
1257 str.push_back (_("Fastest"));
1259 set_popdown_strings (src_combo, str);
1260 src_combo.set_active_text (str.front());
1261 src_combo.set_sensitive (false);
1265 action_combo.signal_changed().connect (mem_fun (*this, &SoundFileOmega::reset_options_noret));
1267 copy_files_btn.set_active (true);
1269 block_four.pack_start (copy_files_btn, false, false);
1271 options.pack_start (block_four, false, false);
1273 get_vbox()->pack_start (options, false, false);
1275 /* setup disposition map */
1277 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1278 disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1279 disposition_map.insert (pair<ustring,ImportDisposition>(_("merge files"), ImportMergeFiles));
1280 disposition_map.insert (pair<ustring,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1282 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1283 disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1284 disposition_map.insert (pair<ustring,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1286 chooser.signal_selection_changed().connect (mem_fun (*this, &SoundFileOmega::file_selection_changed));
1290 SoundFileOmega::set_mode (ImportMode mode)
1292 action_combo.set_active_text (importmode2string (mode));
1296 SoundFileOmega::get_mode () const
1298 return string2importmode (action_combo.get_active_text());
1302 SoundFileOmega::on_hide ()
1304 ArdourDialog::on_hide();
1306 session->cancel_audition();
1311 SoundFileOmega::get_position() const
1313 ustring str = where_combo.get_active_text();
1315 if (str == _("use file timestamp")) {
1316 return ImportAtTimestamp;
1317 } else if (str == _("at edit point")) {
1318 return ImportAtEditPoint;
1319 } else if (str == _("at playhead")) {
1320 return ImportAtPlayhead;
1322 return ImportAtStart;
1327 SoundFileOmega::get_src_quality() const
1329 ustring str = where_combo.get_active_text();
1331 if (str == _("Best")) {
1333 } else if (str == _("Good")) {
1335 } else if (str == _("Quick")) {
1337 } else if (str == _("Fast")) {
1345 SoundFileOmega::get_channel_disposition () const
1347 /* we use a map here because the channel combo can contain different strings
1348 depending on the state of the other combos. the map contains all possible strings
1349 and the ImportDisposition enum that corresponds to it.
1352 ustring str = channel_combo.get_active_text();
1353 DispositionMap::const_iterator x = disposition_map.find (str);
1355 if (x == disposition_map.end()) {
1356 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1364 SoundFileOmega::reset (int selected_tracks)
1366 selected_track_cnt = selected_tracks;
1371 SoundFileOmega::file_selection_changed ()
1373 if (resetting_ourselves) {
1377 if (!reset_options ()) {
1378 set_response_sensitive (RESPONSE_OK, false);
1380 if (chooser.get_filenames().size() > 0) {
1381 set_response_sensitive (RESPONSE_OK, true);
1383 set_response_sensitive (RESPONSE_OK, false);