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.
21 #include "gtk2ardour-config.h"
34 #include <gtkmm/box.h>
35 #include <gtkmm/stock.h>
37 #include <glib/gstdio.h>
38 #include <glibmm/fileutils.h>
40 #include "pbd/convert.h"
41 #include "pbd/tokenizer.h"
42 #include "pbd/enumwriter.h"
43 #include "pbd/pthread_utils.h"
44 #include "pbd/xml++.h"
46 #include <gtkmm2ext/utils.h>
48 #include "evoral/SMF.hpp"
50 #include "ardour/audio_library.h"
51 #include "ardour/auditioner.h"
52 #include "ardour/audioregion.h"
53 #include "ardour/audiofilesource.h"
54 #include "ardour/smf_source.h"
55 #include "ardour/region_factory.h"
56 #include "ardour/source_factory.h"
57 #include "ardour/session.h"
58 #include "ardour/session_directory.h"
59 #include "ardour/srcfilesource.h"
61 #include "ardour_ui.h"
63 #include "gui_thread.h"
68 #include "gain_meter.h"
69 #include "main_clock.h"
70 #include "public_editor.h"
72 #include "sfdb_freesound_mootcher.h"
74 using namespace ARDOUR;
78 using namespace Gtkmm2ext;
79 using namespace Editing;
83 string SoundFileBrowser::persistent_folder;
84 typedef TreeView::Selection::ListHandle_Path ListPath;
87 string2importmode (string str)
89 if (str == _("as new tracks")) {
91 } else if (str == _("to selected tracks")) {
93 } else if (str == _("to region list")) {
94 return ImportAsRegion;
95 } else if (str == _("as new tape tracks")) {
96 return ImportAsTapeTrack;
99 warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
101 return ImportAsTrack;
105 importmode2string (ImportMode mode)
109 return _("as new tracks");
111 return _("to selected tracks");
113 return _("to region list");
114 case ImportAsTapeTrack:
115 return _("as new tape tracks");
118 return _("as new tracks");
121 SoundFileBox::SoundFileBox (bool /*persistent*/)
123 length_clock ("sfboxLengthClock", true, "", false, false, true, false),
124 timecode_clock ("sfboxTimecodeClock", true, "", false, false, false, false),
126 autoplay_btn (_("Auto-play")),
127 seek_slider(0,1000,1),
131 set_name (X_("SoundFileBox"));
132 set_size_request (300, -1);
134 preview_label.set_markup (_("<b>Sound File Information</b>"));
136 border_frame.set_label_widget (preview_label);
137 border_frame.add (main_box);
139 pack_start (border_frame, true, true);
140 set_border_width (6);
142 main_box.set_border_width (6);
144 length.set_text (_("Length:"));
145 length.set_alignment (1, 0.5);
146 timecode.set_text (_("Timestamp:"));
147 timecode.set_alignment (1, 0.5);
148 format.set_text (_("Format:"));
149 format.set_alignment (1, 0.5);
150 channels.set_text (_("Channels:"));
151 channels.set_alignment (1, 0.5);
152 samplerate.set_text (_("Sample rate:"));
153 samplerate.set_alignment (1, 0.5);
155 preview_label.set_max_width_chars (50);
156 preview_label.set_ellipsize (Pango::ELLIPSIZE_END);
158 format_text.set_max_width_chars (20);
159 format_text.set_ellipsize (Pango::ELLIPSIZE_END);
160 format_text.set_alignment (0, 1);
162 table.set_col_spacings (6);
163 table.set_homogeneous (false);
164 table.set_row_spacings (6);
166 table.attach (channels, 0, 1, 0, 1, FILL, FILL);
167 table.attach (samplerate, 0, 1, 1, 2, FILL, FILL);
168 table.attach (format, 0, 1, 2, 4, FILL, FILL);
169 table.attach (length, 0, 1, 4, 5, FILL, FILL);
170 table.attach (timecode, 0, 1, 5, 6, FILL, FILL);
172 table.attach (channels_value, 1, 2, 0, 1, FILL, FILL);
173 table.attach (samplerate_value, 1, 2, 1, 2, FILL, FILL);
174 table.attach (format_text, 1, 2, 2, 4, FILL, FILL);
175 table.attach (length_clock, 1, 2, 4, 5, FILL, FILL);
176 table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL);
178 length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock->mode());
179 timecode_clock.set_mode (AudioClock::Timecode);
181 main_box.pack_start (table, false, false);
183 tags_entry.set_editable (true);
184 tags_entry.set_wrap_mode(Gtk::WRAP_WORD);
185 tags_entry.signal_focus_out_event().connect (sigc::mem_fun (*this, &SoundFileBox::tags_entry_left));
187 Label* label = manage (new Label (_("Tags:")));
188 label->set_alignment (0.0f, 0.5f);
189 main_box.pack_start (*label, false, false);
190 main_box.pack_start (tags_entry, true, true);
192 main_box.pack_start (bottom_box, false, false);
194 play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
195 // play_btn.set_label (_("Play"));
197 stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
198 // stop_btn.set_label (_("Stop"));
200 bottom_box.set_homogeneous (false);
201 bottom_box.set_spacing (6);
202 bottom_box.pack_start(play_btn, true, true);
203 bottom_box.pack_start(stop_btn, true, true);
204 bottom_box.pack_start(autoplay_btn, false, false);
206 seek_slider.set_draw_value(false);
208 seek_slider.add_events(Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
209 seek_slider.signal_button_press_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_press), false);
210 seek_slider.signal_button_release_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_release), false);
211 main_box.pack_start (seek_slider, false, false);
213 play_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::audition));
214 stop_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::stop_audition));
216 stop_btn.set_sensitive (false);
218 channels_value.set_alignment (0.0f, 0.5f);
219 samplerate_value.set_alignment (0.0f, 0.5f);
223 SoundFileBox::set_session(Session* s)
225 SessionHandlePtr::set_session (s);
227 length_clock.set_session (s);
228 timecode_clock.set_session (s);
231 play_btn.set_sensitive (false);
232 stop_btn.set_sensitive (false);
233 auditioner_connections.drop_connections();
235 auditioner_connections.drop_connections();
236 _session->AuditionActive.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_active, this, _1), gui_context());
237 _session->the_auditioner()->AuditionProgress.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_progress, this, _1, _2), gui_context());
242 SoundFileBox::audition_active(bool active) {
243 stop_btn.set_sensitive (active);
244 seek_slider.set_sensitive (active);
246 seek_slider.set_value(0);
251 SoundFileBox::audition_progress(ARDOUR::framecnt_t pos, ARDOUR::framecnt_t len) {
253 seek_slider.set_value( 1000.0 * pos / len);
254 seek_slider.set_sensitive (true);
259 SoundFileBox::seek_button_press(GdkEventButton*) {
261 return false; // pass on to slider
265 SoundFileBox::seek_button_release(GdkEventButton*) {
267 _session->the_auditioner()->seek_to_percent(seek_slider.get_value() / 10.0);
268 seek_slider.set_sensitive (false);
269 return false; // pass on to slider
273 SoundFileBox::setup_labels (const string& filename)
276 // save existing tags
284 if (SMFSource::safe_midi_file_extension (path)) {
286 boost::shared_ptr<SMFSource> ms =
287 boost::dynamic_pointer_cast<SMFSource> (
288 SourceFactory::createExternal (DataType::MIDI, *_session,
289 path, 0, Source::Flag (0), false));
291 preview_label.set_markup (_("<b>Midi File Information</b>"));
293 format_text.set_text ("MIDI");
294 samplerate_value.set_text ("-");
295 tags_entry.get_buffer()->set_text ("");
296 timecode_clock.set (0);
297 tags_entry.set_sensitive (false);
300 channels_value.set_text (to_string(ms->num_tracks(), std::dec));
301 length_clock.set (ms->length(ms->timeline_position()));
303 channels_value.set_text ("");
304 length_clock.set (0);
307 if (_session && ms) {
308 play_btn.set_sensitive (true);
310 play_btn.set_sensitive (false);
316 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
318 preview_label.set_markup (_("<b>Sound File Information</b>"));
319 format_text.set_text ("");
320 channels_value.set_text ("");
321 samplerate_value.set_text ("");
322 tags_entry.get_buffer()->set_text ("");
324 length_clock.set (0);
325 timecode_clock.set (0);
327 tags_entry.set_sensitive (false);
328 play_btn.set_sensitive (false);
333 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::Markup::escape_text (Glib::path_get_basename (filename))));
334 std::string n = sf_info.format_name;
335 if (n.substr (0, 8) == X_("Format: ")) {
338 format_text.set_text (n);
339 channels_value.set_text (to_string (sf_info.channels, std::dec));
341 if (_session && sf_info.samplerate != _session->frame_rate()) {
342 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
343 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
344 samplerate_value.set_name ("NewSessionSR1Label");
345 samplerate.set_name ("NewSessionSR1Label");
347 samplerate.set_text (_("Sample rate:"));
348 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
349 samplerate_value.set_name ("NewSessionSR2Label");
350 samplerate.set_name ("NewSessionSR2Label");
353 framecnt_t const nfr = _session ? _session->nominal_frame_rate() : 25;
354 double src_coef = (double) nfr / sf_info.samplerate;
356 length_clock.set (sf_info.length * src_coef + 0.5, true);
357 timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
359 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
361 vector<string> tags = Library->get_tags (string ("//") + filename);
363 stringstream tag_string;
364 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
365 if (i != tags.begin()) {
370 tags_entry.get_buffer()->set_text (tag_string.str());
372 tags_entry.set_sensitive (true);
374 play_btn.set_sensitive (true);
381 SoundFileBox::autoplay() const
383 return autoplay_btn.get_active();
387 SoundFileBox::audition_oneshot()
394 SoundFileBox::audition ()
400 _session->cancel_audition();
402 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
403 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
407 boost::shared_ptr<Region> r;
409 if (SMFSource::safe_midi_file_extension (path)) {
411 boost::shared_ptr<SMFSource> ms =
412 boost::dynamic_pointer_cast<SMFSource> (
413 SourceFactory::createExternal (DataType::MIDI, *_session,
414 path, 0, Source::Flag (0), false));
416 string rname = region_name_from_path (ms->path(), false);
420 plist.add (ARDOUR::Properties::start, 0);
421 plist.add (ARDOUR::Properties::length, ms->length(ms->timeline_position()));
422 plist.add (ARDOUR::Properties::name, rname);
423 plist.add (ARDOUR::Properties::layer, 0);
425 r = boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (boost::dynamic_pointer_cast<Source>(ms), plist, false));
431 boost::shared_ptr<AudioFileSource> afs;
432 bool old_sbp = AudioSource::get_build_peakfiles ();
434 /* don't even think of building peakfiles for these files */
436 AudioSource::set_build_peakfiles (false);
438 for (int n = 0; n < sf_info.channels; ++n) {
440 afs = boost::dynamic_pointer_cast<AudioFileSource> (
441 SourceFactory::createExternal (DataType::AUDIO, *_session,
443 Source::Flag (0), false));
444 if (afs->sample_rate() != _session->nominal_frame_rate()) {
445 boost::shared_ptr<SrcFileSource> sfs (new SrcFileSource(*_session, afs, _src_quality));
446 srclist.push_back(sfs);
448 srclist.push_back(afs);
451 } catch (failed_constructor& err) {
452 error << _("Could not access soundfile: ") << path << endmsg;
453 AudioSource::set_build_peakfiles (old_sbp);
458 AudioSource::set_build_peakfiles (old_sbp);
460 if (srclist.empty()) {
464 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
465 string rname = region_name_from_path (afs->path(), false);
469 plist.add (ARDOUR::Properties::start, 0);
470 plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->timeline_position()));
471 plist.add (ARDOUR::Properties::name, rname);
472 plist.add (ARDOUR::Properties::layer, 0);
474 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false));
477 frameoffset_t audition_position = 0;
478 switch(_import_position) {
479 case ImportAtTimestamp:
480 audition_position = 0;
482 case ImportAtPlayhead:
483 audition_position = _session->transport_frame();
486 audition_position = _session->current_start_frame();
488 case ImportAtEditPoint:
489 audition_position = PublicEditor::instance().get_preferred_edit_position ();
492 r->set_position(audition_position);
494 _session->audition_region(r);
498 SoundFileBox::stop_audition ()
501 _session->cancel_audition();
506 SoundFileBox::tags_entry_left (GdkEventFocus *)
513 SoundFileBox::tags_changed ()
515 string tag_string = tags_entry.get_buffer()->get_text ();
517 if (tag_string.empty()) {
523 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
524 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
532 SoundFileBox::save_tags (const vector<string>& tags)
534 Library->set_tags (string ("//") + path, tags);
535 Library->save_changes ();
538 SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persistent)
539 : ArdourWindow (title)
540 , found_list (ListStore::create(found_list_columns))
541 , freesound_list (ListStore::create(freesound_list_columns))
542 , chooser (FILE_CHOOSER_ACTION_OPEN)
543 , preview (persistent)
544 , found_search_btn (_("Search"))
545 , found_list_view (found_list)
546 , freesound_search_btn (_("Search"))
547 , freesound_list_view (freesound_list)
548 , resetting_ourselves (false)
552 , ok_button (Stock::OK)
553 , cancel_button (Stock::CANCEL)
554 , apply_button (Stock::APPLY)
559 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
560 chooser.add_shortcut_folder_uri("file:///Library/Audio/Apple Loops");
561 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
562 chooser.add_shortcut_folder_uri("file:///Volumes");
565 //add the file chooser
567 chooser.set_border_width (12);
569 audio_and_midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun (*this, &SoundFileBrowser::on_audio_and_midi_filter));
570 audio_and_midi_filter.set_name (_("Audio and MIDI files"));
572 audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
573 audio_filter.set_name (_("Audio files"));
575 midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
576 midi_filter.set_name (_("MIDI files"));
578 matchall_filter.add_pattern ("*.*");
579 matchall_filter.set_name (_("All files"));
581 chooser.add_filter (audio_and_midi_filter);
582 chooser.add_filter (audio_filter);
583 chooser.add_filter (midi_filter);
584 chooser.add_filter (matchall_filter);
585 chooser.set_select_multiple (true);
586 chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
587 chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
590 /* some broken redraw behaviour - this is a bandaid */
591 chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
594 if (!persistent_folder.empty()) {
595 chooser.set_current_folder (persistent_folder);
598 notebook.append_page (chooser, _("Browse Files"));
600 hpacker.set_spacing (6);
601 hpacker.pack_start (notebook, true, true);
602 hpacker.pack_start (preview, false, false);
604 vpacker.set_spacing (6);
605 vpacker.pack_start (hpacker, true, true);
615 hbox = manage(new HBox);
616 hbox->pack_start (found_entry);
617 hbox->pack_start (found_search_btn);
619 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
620 scroll->add(found_list_view);
621 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
623 vbox = manage(new VBox);
624 vbox->pack_start (*hbox, PACK_SHRINK);
625 vbox->pack_start (*scroll);
627 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
629 found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
631 found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
633 found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
634 found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
636 notebook.append_page (*vbox, _("Search Tags"));
638 //add freesound search
643 passbox = manage(new HBox);
644 passbox->set_spacing (6);
646 label = manage (new Label);
647 label->set_text (_("Tags:"));
648 passbox->pack_start (*label, false, false);
649 passbox->pack_start (freesound_entry, true, true);
651 label = manage (new Label);
652 label->set_text (_("Sort:"));
653 passbox->pack_start (*label, false, false);
654 passbox->pack_start (freesound_sort, false, false);
655 freesound_sort.clear_items();
657 // Order of the following must correspond with enum sortMethod
658 // in sfdb_freesound_mootcher.h
659 freesound_sort.append_text(_("None"));
660 freesound_sort.append_text(_("Longest"));
661 freesound_sort.append_text(_("Shortest"));
662 freesound_sort.append_text(_("Newest"));
663 freesound_sort.append_text(_("Oldest"));
664 freesound_sort.append_text(_("Most downloaded"));
665 freesound_sort.append_text(_("Least downloaded"));
666 freesound_sort.append_text(_("Highest rated"));
667 freesound_sort.append_text(_("Lowest rated"));
668 freesound_sort.set_active(0);
670 passbox->pack_start (freesound_search_btn, false, false);
671 passbox->pack_start (freesound_more_btn, false, false);
672 freesound_more_btn.set_label(_("More"));
673 freesound_more_btn.set_sensitive(false);
675 passbox->pack_start (freesound_similar_btn, false, false);
676 freesound_similar_btn.set_label(_("Similar"));
677 freesound_similar_btn.set_sensitive(false);
679 scroll = manage(new ScrolledWindow);
680 scroll->add(freesound_list_view);
681 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
683 vbox = manage(new VBox);
684 vbox->set_spacing (3);
685 vbox->pack_start (*passbox, PACK_SHRINK);
686 vbox->pack_start (*scroll);
688 freesound_list_view.append_column(_("ID") , freesound_list_columns.id);
689 freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
690 // freesound_list_view.append_column(_("URI") , freesound_list_columns.uri);
691 freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
692 freesound_list_view.append_column(_("Size"), freesound_list_columns.filesize);
693 freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
694 freesound_list_view.append_column(_("License"), freesound_list_columns.license);
695 freesound_list_view.get_column(0)->set_alignment(0.5);
696 freesound_list_view.get_column(1)->set_expand(true); // filename
697 freesound_list_view.get_column(1)->set_resizable(true); // filename
698 freesound_list_view.get_column(2)->set_alignment(0.5);
699 freesound_list_view.get_column(3)->set_alignment(0.5);
700 freesound_list_view.get_column(4)->set_alignment(0.5);
701 freesound_list_view.get_column(5)->set_alignment(0.5);
703 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
704 freesound_list_view.set_tooltip_column(1);
706 freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
707 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
708 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
709 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
710 freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
711 freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
712 notebook.append_page (*vbox, _("Search Freesound"));
714 notebook.set_size_request (500, -1);
715 notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
719 Gtk::HButtonBox* button_box = manage (new HButtonBox);
721 button_box->set_layout (BUTTONBOX_END);
722 button_box->pack_start (cancel_button, false, false);
723 cancel_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_CANCEL));
725 button_box->pack_start (apply_button, false, false);
726 apply_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_APPLY));
729 button_box->pack_start (ok_button, false, false);
730 ok_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_OK));
732 Gtkmm2ext::UI::instance()->set_tip (ok_button, _("Press to import selected files and close this window"));
733 Gtkmm2ext::UI::instance()->set_tip (apply_button, _("Press to import selected files and leave this window open"));
734 Gtkmm2ext::UI::instance()->set_tip (cancel_button, _("Press to close this window without importing any files"));
736 vpacker.pack_end (*button_box, false, false);
738 set_wmclass (X_("import"), PROGRAM_NAME);
741 SoundFileBrowser::~SoundFileBrowser ()
743 persistent_folder = chooser.get_current_folder();
747 SoundFileBrowser::run ()
756 gtk_main_iteration ();
763 SoundFileBrowser::set_action_sensitive (bool yn)
765 ok_button.set_sensitive (yn);
766 apply_button.set_sensitive (yn);
770 SoundFileBrowser::do_something (int action)
777 SoundFileBrowser::on_show ()
779 ArdourWindow::on_show ();
784 SoundFileBrowser::clear_selection ()
786 chooser.unselect_all ();
787 found_list_view.get_selection()->unselect_all ();
791 SoundFileBrowser::chooser_file_activated ()
797 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
803 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
809 SoundFileBrowser::set_session (Session* s)
811 ArdourWindow::set_session (s);
812 preview.set_session (s);
817 remove_gain_meter ();
822 SoundFileBrowser::add_gain_meter ()
826 gm = new GainMeter (_session, 250);
828 boost::shared_ptr<Route> r = _session->the_auditioner ();
830 gm->set_controls (r, r->shared_peak_meter(), r->amp());
831 gm->set_fader_name (X_("GainFader"));
833 meter_packer.set_border_width (12);
834 meter_packer.pack_start (*gm, false, true);
835 hpacker.pack_end (meter_packer, false, false);
836 meter_packer.show_all ();
841 SoundFileBrowser::remove_gain_meter ()
844 meter_packer.remove (*gm);
845 hpacker.remove (meter_packer);
852 SoundFileBrowser::start_metering ()
854 metering_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
858 SoundFileBrowser::stop_metering ()
860 metering_connection.disconnect();
864 SoundFileBrowser::meter ()
866 if (is_mapped () && _session && gm) {
867 gm->update_meters ();
872 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
874 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
878 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
880 return SMFSource::safe_midi_file_extension (filter_info.filename);
884 SoundFileBrowser::on_audio_and_midi_filter (const FileFilter::Info& filter_info)
886 return on_audio_filter (filter_info) || on_midi_filter (filter_info);
890 SoundFileBrowser::update_preview ()
892 if (preview.setup_labels (chooser.get_preview_filename())) {
893 if (preview.autoplay()) {
894 Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
900 SoundFileBrowser::found_list_view_selected ()
902 if (!reset_options ()) {
903 set_action_sensitive (false);
907 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
910 TreeIter iter = found_list->get_iter(*rows.begin());
911 file = (*iter)[found_list_columns.pathname];
912 chooser.set_filename (file);
913 set_action_sensitive (true);
915 set_action_sensitive (false);
918 preview.setup_labels (file);
923 SoundFileBrowser::found_search_clicked ()
925 string tag_string = found_entry.get_text ();
929 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
930 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
934 vector<string> results;
935 Library->search_members_and (results, tags);
938 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
939 TreeModel::iterator new_row = found_list->append();
940 TreeModel::Row row = *new_row;
941 string path = Glib::filename_from_uri (string ("file:") + *i);
942 row[found_list_columns.pathname] = path;
948 SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
951 Mootcher *mootcher = new Mootcher;
954 string id = (*iter)[freesound_list_columns.id];
955 string uri = (*iter)[freesound_list_columns.uri];
956 string ofn = (*iter)[freesound_list_columns.filename];
958 if (mootcher->checkAudioFile(ofn, id)) {
959 // file already exists, no need to download it again
960 file = mootcher->audioFileName;
962 (*iter)[freesound_list_columns.started] = false;
965 if (!(*iter)[freesound_list_columns.started]) {
966 // start downloading the sound file
967 (*iter)[freesound_list_columns.started] = true;
968 mootcher->fetchAudioFile(ofn, id, uri, this);
974 SoundFileBrowser::freesound_list_view_selected ()
977 if (!reset_options ()) {
978 set_action_sensitive (false);
981 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
982 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
983 file = freesound_get_audio_file (freesound_list->get_iter(*i));
986 switch (rows.size()) {
989 freesound_similar_btn.set_sensitive(false);
990 set_action_sensitive (false);
993 // exactly one item selected
995 // file exists on disk already
996 chooser.set_filename (file);
997 preview.setup_labels (file);
998 set_action_sensitive (true);
1000 freesound_similar_btn.set_sensitive(true);
1003 // multiple items selected
1004 preview.setup_labels ("");
1005 freesound_similar_btn.set_sensitive(false);
1013 SoundFileBrowser::refresh_display(std::string ID, std::string file)
1015 // called when the mootcher has finished downloading a file
1016 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1017 if (rows.size() == 1) {
1018 // there's a single item selected in the freesound list
1019 //XXX make a function to be used to construct the actual file name both here and in the mootcher
1020 Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
1021 std::string selected_ID = (*row)[freesound_list_columns.id];
1022 if (ID == selected_ID) {
1023 // the selected item in the freesound list is the item that has just finished downloading
1024 chooser.set_filename(file);
1025 preview.setup_labels (file);
1026 set_action_sensitive (true);
1032 SoundFileBrowser::freesound_search_clicked ()
1035 freesound_list->clear();
1041 SoundFileBrowser::freesound_more_clicked ()
1046 snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
1047 freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
1051 SoundFileBrowser::freesound_similar_clicked ()
1053 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1054 if (rows.size() == 1) {
1057 Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
1058 id = (*iter)[freesound_list_columns.id];
1059 freesound_list->clear();
1061 GdkCursor *prev_cursor;
1062 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1063 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1066 std::string theString = mootcher.searchSimilar(id);
1068 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1069 handle_freesound_results(theString);
1074 SoundFileBrowser::freesound_search()
1078 string search_string = freesound_entry.get_text ();
1079 enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
1081 GdkCursor *prev_cursor;
1082 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1083 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1086 std::string theString = mootcher.searchText(
1090 "", // OSX eats anything incl mp3
1092 "type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
1097 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1098 handle_freesound_results(theString);
1102 SoundFileBrowser::handle_freesound_results(std::string theString) {
1104 doc.read_buffer( theString );
1105 XMLNode *root = doc.root();
1108 error << "no root XML node!" << endmsg;
1112 if ( strcmp(root->name().c_str(), "response") != 0) {
1113 error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
1117 // find out how many pages are available to search
1118 int freesound_n_pages = 1;
1119 XMLNode *res = root->child("num_pages");
1121 string result = res->child("text")->content();
1122 freesound_n_pages = atoi(result);
1125 int more_pages = freesound_n_pages - freesound_page;
1127 if (more_pages > 0) {
1128 freesound_more_btn.set_sensitive(true);
1129 freesound_more_btn.set_tooltip_text(string_compose(P_(
1130 "%1 more page of 100 results available",
1131 "%1 more pages of 100 results available",
1132 more_pages), more_pages));
1134 freesound_more_btn.set_sensitive(false);
1135 freesound_more_btn.set_tooltip_text(_("No more results available"));
1138 XMLNode *sounds_root = root->child("sounds");
1140 error << "no child node \"sounds\" found!" << endmsg;
1144 XMLNodeList sounds = sounds_root->children();
1145 if (sounds.size() == 0) {
1150 XMLNodeConstIterator niter;
1152 for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
1154 if( strcmp( node->name().c_str(), "resource") != 0 ) {
1155 error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
1159 // node->dump(cerr, "node:");
1162 XMLNode *id_node = node->child ("id");
1163 XMLNode *uri_node = node->child ("serve");
1164 XMLNode *ofn_node = node->child ("original_filename");
1165 XMLNode *dur_node = node->child ("duration");
1166 XMLNode *siz_node = node->child ("filesize");
1167 XMLNode *srt_node = node->child ("samplerate");
1168 XMLNode *lic_node = node->child ("license");
1170 if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
1172 std::string id = id_node->child("text")->content();
1173 std::string uri = uri_node->child("text")->content();
1174 std::string ofn = ofn_node->child("text")->content();
1175 std::string dur = dur_node->child("text")->content();
1176 std::string siz = siz_node->child("text")->content();
1177 std::string srt = srt_node->child("text")->content();
1178 std::string lic = lic_node->child("text")->content();
1181 // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
1183 double duration_seconds = atof(dur);
1185 char duration_hhmmss[16];
1186 if (duration_seconds >= 99 * 60 * 60) {
1187 strcpy(duration_hhmmss, ">99h");
1189 s = modf(duration_seconds/60, &m) * 60;
1190 m = modf(m/60, &h) * 60;
1191 sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
1196 double size_bytes = atof(siz);
1198 if (size_bytes < 1000) {
1199 sprintf(bsize, "%.0f %s", size_bytes, _("B"));
1200 } else if (size_bytes < 1000000 ) {
1201 sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
1202 } else if (size_bytes < 10000000) {
1203 sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
1204 } else if (size_bytes < 1000000000) {
1205 sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
1207 sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
1210 /* see http://www.freesound.org/help/faq/#licenses */
1211 char shortlicense[64];
1212 if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
1213 sprintf(shortlicense, "CC-BY-NC");
1214 } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
1215 sprintf(shortlicense, "CC-BY");
1216 } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
1217 sprintf(shortlicense, "sampling+");
1218 } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
1219 sprintf(shortlicense, "PD");
1221 snprintf(shortlicense, 64, "%s", lic.c_str());
1222 shortlicense[63]= '\0';
1225 TreeModel::iterator new_row = freesound_list->append();
1226 TreeModel::Row row = *new_row;
1228 row[freesound_list_columns.id ] = id;
1229 row[freesound_list_columns.uri ] = uri;
1230 row[freesound_list_columns.filename] = ofn;
1231 row[freesound_list_columns.duration] = duration_hhmmss;
1232 row[freesound_list_columns.filesize] = bsize;
1233 row[freesound_list_columns.smplrate] = srt;
1234 row[freesound_list_columns.license ] = shortlicense;
1241 SoundFileBrowser::get_paths ()
1243 vector<string> results;
1245 int n = notebook.get_current_page ();
1248 vector<string> filenames = chooser.get_filenames();
1249 vector<string>::iterator i;
1251 for (i = filenames.begin(); i != filenames.end(); ++i) {
1253 if ((!stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
1254 results.push_back (*i);
1258 } else if (n == 1) {
1260 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1261 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1262 TreeIter iter = found_list->get_iter(*i);
1263 string str = (*iter)[found_list_columns.pathname];
1265 results.push_back (str);
1268 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1269 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1270 string str = freesound_get_audio_file (freesound_list->get_iter(*i));
1272 results.push_back (str);
1281 SoundFileOmega::reset_options_noret ()
1283 if (!resetting_ourselves) {
1284 (void) reset_options ();
1289 SoundFileOmega::reset_options ()
1291 vector<string> paths = get_paths ();
1293 if (paths.empty()) {
1295 channel_combo.set_sensitive (false);
1296 action_combo.set_sensitive (false);
1297 where_combo.set_sensitive (false);
1298 copy_files_btn.set_active (true);
1299 copy_files_btn.set_sensitive (false);
1305 channel_combo.set_sensitive (true);
1306 action_combo.set_sensitive (true);
1307 where_combo.set_sensitive (true);
1309 /* if we get through this function successfully, this may be
1310 reset at the end, once we know if we can use hard links
1311 to do embedding (or if we are importing a MIDI file).
1314 if (Config->get_only_copy_imported_files()) {
1315 copy_files_btn.set_sensitive (false);
1317 copy_files_btn.set_sensitive (false);
1323 bool selection_includes_multichannel;
1324 bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1327 /* See if we are thinking about importing any MIDI files */
1328 vector<string>::iterator i = paths.begin ();
1329 while (i != paths.end() && SMFSource::safe_midi_file_extension (*i) == false) {
1332 bool const have_a_midi_file = (i != paths.end ());
1334 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1335 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1339 string existing_choice;
1340 vector<string> action_strings;
1342 resetting_ourselves = true;
1344 if (chooser.get_filter() == &audio_filter) {
1348 if (selected_audio_track_cnt > 0) {
1349 if (channel_combo.get_active_text().length()) {
1350 ImportDisposition id = get_channel_disposition();
1353 case Editing::ImportDistinctFiles:
1354 if (selected_audio_track_cnt == paths.size()) {
1355 action_strings.push_back (importmode2string (ImportToTrack));
1359 case Editing::ImportDistinctChannels:
1360 /* XXX it would be nice to allow channel-per-selected track
1361 but its too hard we don't want to deal with all the
1362 different per-file + per-track channel configurations.
1367 action_strings.push_back (importmode2string (ImportToTrack));
1377 if (selected_midi_track_cnt > 0) {
1378 action_strings.push_back (importmode2string (ImportToTrack));
1382 action_strings.push_back (importmode2string (ImportAsTrack));
1383 action_strings.push_back (importmode2string (ImportAsRegion));
1384 action_strings.push_back (importmode2string (ImportAsTapeTrack));
1386 existing_choice = action_combo.get_active_text();
1388 set_popdown_strings (action_combo, action_strings);
1390 /* preserve any existing choice, if possible */
1393 if (existing_choice.length()) {
1394 vector<string>::iterator x;
1395 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1396 if (*x == existing_choice) {
1397 action_combo.set_active_text (existing_choice);
1401 if (x == action_strings.end()) {
1402 action_combo.set_active_text (action_strings.front());
1405 action_combo.set_active_text (action_strings.front());
1408 resetting_ourselves = false;
1410 if ((mode = get_mode()) == ImportAsRegion) {
1411 where_combo.set_sensitive (false);
1413 where_combo.set_sensitive (true);
1416 vector<string> channel_strings;
1418 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1419 channel_strings.push_back (_("one track per file"));
1421 if (selection_includes_multichannel) {
1422 channel_strings.push_back (_("one track per channel"));
1425 if (paths.size() > 1) {
1426 /* tape tracks are a single region per track, so we cannot
1427 sequence multiple files.
1429 if (mode != ImportAsTapeTrack) {
1430 channel_strings.push_back (_("sequence files"));
1433 channel_strings.push_back (_("all files in one track"));
1434 channel_strings.push_back (_("merge files"));
1440 channel_strings.push_back (_("one region per file"));
1442 if (selection_includes_multichannel) {
1443 channel_strings.push_back (_("one region per channel"));
1446 if (paths.size() > 1) {
1448 channel_strings.push_back (_("all files in one region"));
1453 resetting_ourselves = true;
1455 existing_choice = channel_combo.get_active_text();
1457 set_popdown_strings (channel_combo, channel_strings);
1459 /* preserve any existing choice, if possible */
1461 if (existing_choice.length()) {
1462 vector<string>::iterator x;
1463 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1464 if (*x == existing_choice) {
1465 channel_combo.set_active_text (existing_choice);
1469 if (x == channel_strings.end()) {
1470 channel_combo.set_active_text (channel_strings.front());
1473 channel_combo.set_active_text (channel_strings.front());
1476 resetting_ourselves = false;
1479 src_combo.set_sensitive (true);
1481 src_combo.set_sensitive (false);
1484 /* We must copy MIDI files or those from Freesound
1485 * or any file if we are under nsm control */
1486 bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
1488 if (Config->get_only_copy_imported_files()) {
1490 if (selection_can_be_embedded_with_links && !must_copy) {
1491 copy_files_btn.set_sensitive (true);
1494 copy_files_btn.set_active (true);
1496 copy_files_btn.set_sensitive (false);
1502 copy_files_btn.set_active (true);
1504 copy_files_btn.set_sensitive (!must_copy);
1512 SoundFileOmega::bad_file_message()
1514 MessageDialog msg (*this,
1515 string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1520 resetting_ourselves = true;
1521 chooser.unselect_uri (chooser.get_preview_uri());
1522 resetting_ourselves = false;
1528 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1537 multichannel = false;
1539 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1541 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1542 if (info.channels > 1) {
1543 multichannel = true;
1548 if (sz != info.length) {
1553 if (info.samplerate != _session->frame_rate()) {
1557 } else if (SMFSource::safe_midi_file_extension (*i)) {
1561 if (reader.num_tracks() > 1) {
1562 multichannel = true; // "channel" == track here...
1565 /* XXX we need err = true handling here in case
1566 we can't check the file
1579 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1581 #ifdef PLATFORM_WINDOWS
1584 std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
1587 if (mkdir (tmpdir.c_str(), 0744)) {
1588 if (errno != EEXIST) {
1593 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1595 char tmpc[PATH_MAX+1];
1597 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1601 if (link ((*i).c_str(), tmpc)) {
1611 rmdir (tmpdir.c_str());
1616 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
1617 : SoundFileBrowser (title, s, false)
1619 chooser.set_select_multiple (false);
1620 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1621 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1625 SoundFileChooser::on_hide ()
1627 ArdourWindow::on_hide();
1631 _session->cancel_audition();
1636 SoundFileChooser::get_filename ()
1638 vector<string> paths;
1640 paths = get_paths ();
1642 if (paths.empty()) {
1646 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1650 return paths.front();
1653 SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s,
1654 uint32_t selected_audio_tracks,
1655 uint32_t selected_midi_tracks,
1657 Editing::ImportMode mode_hint)
1658 : SoundFileBrowser (title, s, persistent)
1659 , copy_files_btn ( _("Copy files to session"))
1660 , selected_audio_track_cnt (selected_audio_tracks)
1661 , selected_midi_track_cnt (selected_midi_tracks)
1667 set_size_request (-1, 450);
1669 block_two.set_border_width (12);
1670 block_three.set_border_width (12);
1671 block_four.set_border_width (12);
1673 options.set_spacing (12);
1676 str.push_back (_("file timestamp"));
1677 str.push_back (_("edit point"));
1678 str.push_back (_("playhead"));
1679 str.push_back (_("session start"));
1680 set_popdown_strings (where_combo, str);
1681 where_combo.set_active_text (str.front());
1682 where_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::where_combo_changed));
1684 Label* l = manage (new Label);
1685 l->set_markup (_("<b>Add files as ...</b>"));
1687 vbox = manage (new VBox);
1688 vbox->set_border_width (12);
1689 vbox->set_spacing (6);
1690 vbox->pack_start (*l, false, false);
1691 vbox->pack_start (action_combo, false, false);
1692 hbox = manage (new HBox);
1693 hbox->pack_start (*vbox, false, false);
1694 options.pack_start (*hbox, false, false);
1696 /* dummy entry for action combo so that it doesn't look odd if we
1697 come up with no tracks selected.
1701 str.push_back (importmode2string (mode_hint));
1702 set_popdown_strings (action_combo, str);
1703 action_combo.set_active_text (str.front());
1704 action_combo.set_sensitive (false);
1706 l = manage (new Label);
1707 l->set_markup (_("<b>Insert at</b>"));
1709 vbox = manage (new VBox);
1710 vbox->set_border_width (12);
1711 vbox->set_spacing (6);
1712 vbox->pack_start (*l, false, false);
1713 vbox->pack_start (where_combo, false, false);
1714 hbox = manage (new HBox);
1715 hbox->pack_start (*vbox, false, false);
1716 options.pack_start (*hbox, false, false);
1719 l = manage (new Label);
1720 l->set_markup (_("<b>Mapping</b>"));
1722 vbox = manage (new VBox);
1723 vbox->set_border_width (12);
1724 vbox->set_spacing (6);
1725 vbox->pack_start (*l, false, false);
1726 vbox->pack_start (channel_combo, false, false);
1727 hbox = manage (new HBox);
1728 hbox->pack_start (*vbox, false, false);
1729 options.pack_start (*hbox, false, false);
1732 str.push_back (_("one track per file"));
1733 set_popdown_strings (channel_combo, str);
1734 channel_combo.set_active_text (str.front());
1735 channel_combo.set_sensitive (false);
1737 l = manage (new Label);
1738 l->set_markup (_("<b>Conversion quality</b>"));
1740 vbox = manage (new VBox);
1741 vbox->set_border_width (12);
1742 vbox->set_spacing (6);
1743 vbox->pack_start (*l, false, false);
1744 vbox->pack_start (src_combo, false, false);
1745 hbox = manage (new HBox);
1746 hbox->pack_start (*vbox, false, false);
1747 options.pack_start (*hbox, false, false);
1750 str.push_back (_("Best"));
1751 str.push_back (_("Good"));
1752 str.push_back (_("Quick"));
1753 str.push_back (_("Fast"));
1754 str.push_back (_("Fastest"));
1756 set_popdown_strings (src_combo, str);
1757 src_combo.set_active_text (str.front());
1758 src_combo.set_sensitive (false);
1759 src_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::src_combo_changed));
1763 action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1764 channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1766 copy_files_btn.set_active (true);
1768 Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1771 copy_label->set_size_request (175, -1);
1772 copy_label->set_line_wrap (true);
1775 block_four.pack_start (copy_files_btn, false, false);
1777 options.pack_start (block_four, false, false);
1779 vpacker.pack_start (options, false, false);
1781 /* setup disposition map */
1783 disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1784 disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1785 disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1786 disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1788 disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1789 disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1790 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1791 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1793 chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1795 /* set size requests for a couple of combos to allow them to display the longest text
1796 they will ever be asked to display. This prevents them being resized when the user
1797 selects a file to import, which in turn prevents the size of the dialog from jumping
1801 t.push_back (_("one track per file"));
1802 t.push_back (_("one track per channel"));
1803 t.push_back (_("sequence files"));
1804 t.push_back (_("all files in one region"));
1805 set_popdown_strings (channel_combo, t);
1808 t.push_back (importmode2string (ImportAsTrack));
1809 t.push_back (importmode2string (ImportToTrack));
1810 t.push_back (importmode2string (ImportAsRegion));
1811 t.push_back (importmode2string (ImportAsTapeTrack));
1812 set_popdown_strings (action_combo, t);
1816 SoundFileOmega::set_mode (ImportMode mode)
1818 action_combo.set_active_text (importmode2string (mode));
1822 SoundFileOmega::get_mode () const
1824 return string2importmode (action_combo.get_active_text());
1828 SoundFileOmega::on_hide ()
1830 ArdourWindow::on_hide();
1832 _session->cancel_audition();
1837 SoundFileOmega::get_position() const
1839 string str = where_combo.get_active_text();
1841 if (str == _("file timestamp")) {
1842 return ImportAtTimestamp;
1843 } else if (str == _("edit point")) {
1844 return ImportAtEditPoint;
1845 } else if (str == _("playhead")) {
1846 return ImportAtPlayhead;
1848 return ImportAtStart;
1853 SoundFileOmega::get_src_quality() const
1855 string str = src_combo.get_active_text();
1857 if (str == _("Best")) {
1859 } else if (str == _("Good")) {
1861 } else if (str == _("Quick")) {
1863 } else if (str == _("Fast")) {
1871 SoundFileOmega::src_combo_changed()
1873 preview.set_src_quality(get_src_quality());
1877 SoundFileOmega::where_combo_changed()
1879 preview.set_import_position(get_position());
1883 SoundFileOmega::get_channel_disposition () const
1885 /* we use a map here because the channel combo can contain different strings
1886 depending on the state of the other combos. the map contains all possible strings
1887 and the ImportDisposition enum that corresponds to it.
1890 string str = channel_combo.get_active_text();
1891 DispositionMap::const_iterator x = disposition_map.find (str);
1893 if (x == disposition_map.end()) {
1894 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1902 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
1904 selected_audio_track_cnt = selected_audio_tracks;
1905 selected_midi_track_cnt = selected_midi_tracks;
1907 if (selected_audio_track_cnt == 0 && selected_midi_track_cnt > 0) {
1908 chooser.set_filter (midi_filter);
1909 } else if (selected_midi_track_cnt == 0 && selected_audio_track_cnt > 0) {
1910 chooser.set_filter (audio_filter);
1912 chooser.set_filter (audio_and_midi_filter);
1919 SoundFileOmega::file_selection_changed ()
1921 if (resetting_ourselves) {
1925 if (!reset_options ()) {
1926 set_action_sensitive (false);
1928 if (chooser.get_filenames().size() > 0) {
1929 set_action_sensitive (true);
1931 set_action_sensitive (false);
1937 SoundFileOmega::do_something (int action)
1939 SoundFileBrowser::do_something (action);
1941 if (action == RESPONSE_CANCEL) {
1948 vector<string> paths = get_paths ();
1949 ImportPosition pos = get_position ();
1950 ImportMode mode = get_mode ();
1951 ImportDisposition chns = get_channel_disposition ();
1955 case ImportAtEditPoint:
1956 where = PublicEditor::instance().get_preferred_edit_position ();
1958 case ImportAtTimestamp:
1961 case ImportAtPlayhead:
1962 where = _session->transport_frame();
1965 where = _session->current_start_frame();
1969 SrcQuality quality = get_src_quality();
1971 if (copy_files_btn.get_active()) {
1972 PublicEditor::instance().do_import (paths, chns, mode, quality, where);
1974 PublicEditor::instance().do_embed (paths, chns, mode, where);
1977 if (action == RESPONSE_OK) {