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"
24 #ifdef PLATFORM_WINDOWS
35 #include <gtkmm/box.h>
36 #include <gtkmm/scrolledwindow.h>
37 #include <gtkmm/stock.h>
39 #include "pbd/gstdio_compat.h"
40 #include <glibmm/fileutils.h>
42 #include "pbd/tokenizer.h"
43 #include "pbd/enumwriter.h"
44 #include "pbd/pthread_utils.h"
45 #include "pbd/string_convert.h"
46 #include "pbd/xml++.h"
48 #include <gtkmm2ext/utils.h>
50 #include "evoral/SMF.hpp"
52 #include "ardour/audio_library.h"
53 #include "ardour/auditioner.h"
54 #include "ardour/audioregion.h"
55 #include "ardour/audiofilesource.h"
56 #include "ardour/midi_region.h"
57 #include "ardour/smf_source.h"
58 #include "ardour/region_factory.h"
59 #include "ardour/source_factory.h"
60 #include "ardour/session.h"
61 #include "ardour/session_directory.h"
62 #include "ardour/srcfilesource.h"
63 #include "ardour/profile.h"
65 #include "ardour_ui.h"
67 #include "gui_thread.h"
70 #include "gain_meter.h"
71 #include "main_clock.h"
72 #include "public_editor.h"
74 #include "ui_config.h"
76 #include "sfdb_freesound_mootcher.h"
80 using namespace ARDOUR;
84 using namespace Gtkmm2ext;
85 using namespace Editing;
89 string SoundFileBrowser::persistent_folder;
90 typedef TreeView::Selection::ListHandle_Path ListPath;
92 static MidiTrackNameSource
93 string2miditracknamesource (string const & str)
95 if (str == _("by track number")) {
96 return SMFTrackNumber;
97 } else if (str == _("by track name")) {
99 } else if (str == _("by instrument name")) {
100 return SMFInstrumentName;
103 warning << string_compose (_("programming error: unknown midi track name source string %1"), str) << endmsg;
105 return SMFTrackNumber;
109 string2importmode (string const & str)
111 if (str == _("as new tracks")) {
112 return ImportAsTrack;
113 } else if (str == _("to selected tracks")) {
114 return ImportToTrack;
115 } else if (str == _("to region list")) {
116 return ImportAsRegion;
117 } else if (str == _("as new tape tracks")) {
118 return ImportAsTapeTrack;
121 warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
123 return ImportAsTrack;
127 importmode2string (ImportMode mode)
131 return _("as new tracks");
133 return _("to selected tracks");
135 return _("to region list");
136 case ImportAsTapeTrack:
137 return _("as new tape tracks");
139 abort(); /*NOTREACHED*/
140 return _("as new tracks");
143 SoundFileBox::SoundFileBox (bool /*persistent*/)
145 length_clock ("sfboxLengthClock", true, "", false, false, true, false),
146 timecode_clock ("sfboxTimecodeClock", true, "", false, false, false, false),
148 autoplay_btn (_("Auto-play")),
149 seek_slider(0,1000,1),
151 _src_quality (SrcBest),
152 _import_position (ImportAtTimestamp)
155 set_name (X_("SoundFileBox"));
156 set_size_request (300, -1);
158 preview_label.set_markup (_("<b>Sound File Information</b>"));
160 border_frame.set_label_widget (preview_label);
161 border_frame.add (main_box);
163 pack_start (border_frame, true, true);
164 set_border_width (6);
166 main_box.set_border_width (6);
168 length.set_text (_("Length:"));
169 length.set_alignment (1, 0.5);
170 timecode.set_text (_("Timestamp:"));
171 timecode.set_alignment (1, 0.5);
172 format.set_text (_("Format:"));
173 format.set_alignment (1, 0.5);
174 channels.set_text (_("Channels:"));
175 channels.set_alignment (1, 0.5);
176 samplerate.set_text (_("Sample rate:"));
177 samplerate.set_alignment (1, 0.5);
178 tempomap.set_text (_("Tempo Map:"));
179 tempomap.set_alignment (1, 0.5);
181 preview_label.set_max_width_chars (50);
182 preview_label.set_ellipsize (Pango::ELLIPSIZE_END);
184 format_text.set_max_width_chars (20);
185 format_text.set_ellipsize (Pango::ELLIPSIZE_END);
186 format_text.set_alignment (0, 1);
188 table.set_col_spacings (6);
189 table.set_homogeneous (false);
190 table.set_row_spacings (6);
192 table.attach (channels, 0, 1, 0, 1, FILL, FILL);
193 table.attach (samplerate, 0, 1, 1, 2, FILL, FILL);
194 table.attach (format, 0, 1, 2, 4, FILL, FILL);
195 table.attach (length, 0, 1, 4, 5, FILL, FILL);
196 table.attach (timecode, 0, 1, 5, 6, FILL, FILL);
197 table.attach (tempomap, 0, 1, 6, 7, FILL, FILL);
199 table.attach (channels_value, 1, 2, 0, 1, FILL, FILL);
200 table.attach (samplerate_value, 1, 2, 1, 2, FILL, FILL);
201 table.attach (format_text, 1, 2, 2, 4, FILL, FILL);
202 table.attach (length_clock, 1, 2, 4, 5, FILL, FILL);
203 table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL);
204 table.attach (tempomap_value, 1, 2, 6, 7, FILL, FILL);
206 length_clock.set_mode (ARDOUR_UI::instance()->primary_clock->mode());
207 timecode_clock.set_mode (AudioClock::Timecode);
209 main_box.pack_start (table, false, false);
211 tags_entry.set_editable (true);
212 tags_entry.set_wrap_mode(Gtk::WRAP_WORD);
213 tags_entry.signal_focus_out_event().connect (sigc::mem_fun (*this, &SoundFileBox::tags_entry_left));
215 Label* label = manage (new Label (_("Tags:")));
216 label->set_alignment (0.0f, 0.5f);
217 main_box.pack_start (*label, false, false);
218 main_box.pack_start (tags_entry, true, true);
220 main_box.pack_start (bottom_box, false, false);
222 play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
223 // play_btn.set_label (_("Play"));
225 stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
226 // stop_btn.set_label (_("Stop"));
228 bottom_box.set_homogeneous (false);
229 bottom_box.set_spacing (6);
230 bottom_box.pack_start(play_btn, true, true);
231 bottom_box.pack_start(stop_btn, true, true);
232 bottom_box.pack_start(autoplay_btn, false, false);
234 seek_slider.set_draw_value(false);
236 seek_slider.add_events(Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
237 seek_slider.signal_button_press_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_press), false);
238 seek_slider.signal_button_release_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_release), false);
239 main_box.pack_start (seek_slider, false, false);
241 play_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::audition));
242 stop_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::stop_audition));
245 autoplay_btn.signal_toggled().connect(sigc::mem_fun (*this, &SoundFileBox::autoplay_toggled));
247 stop_btn.set_sensitive (false);
249 channels_value.set_alignment (0.0f, 0.5f);
250 samplerate_value.set_alignment (0.0f, 0.5f);
254 SoundFileBox::set_session(Session* s)
256 SessionHandlePtr::set_session (s);
258 length_clock.set_session (s);
259 timecode_clock.set_session (s);
262 play_btn.set_sensitive (false);
263 stop_btn.set_sensitive (false);
264 auditioner_connections.drop_connections();
266 auditioner_connections.drop_connections();
267 _session->AuditionActive.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_active, this, _1), gui_context());
268 _session->the_auditioner()->AuditionProgress.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_progress, this, _1, _2), gui_context());
273 SoundFileBox::audition_active(bool active) {
274 stop_btn.set_sensitive (active);
275 seek_slider.set_sensitive (active);
277 seek_slider.set_value(0);
282 SoundFileBox::audition_progress(ARDOUR::samplecnt_t pos, ARDOUR::samplecnt_t len) {
284 seek_slider.set_value( 1000.0 * pos / len);
285 seek_slider.set_sensitive (true);
290 SoundFileBox::seek_button_press(GdkEventButton*) {
292 return false; // pass on to slider
296 SoundFileBox::seek_button_release(GdkEventButton*) {
298 _session->the_auditioner()->seek_to_percent(seek_slider.get_value() / 10.0);
299 seek_slider.set_sensitive (false);
300 return false; // pass on to slider
304 SoundFileBox::setup_labels (const string& filename)
307 // save existing tags
315 if (SMFSource::valid_midi_file (path)) {
317 boost::shared_ptr<SMFSource> ms;
319 ms = boost::dynamic_pointer_cast<SMFSource> (
320 SourceFactory::createExternal (DataType::MIDI, *_session,
321 path, 0, Source::Flag (0), false));
322 } catch (const std::exception& e) {
323 error << string_compose(_("Could not read file: %1 (%2)."),
324 path, e.what()) << endmsg;
327 preview_label.set_markup (_("<b>Midi File Information</b>"));
329 format_text.set_text ("MIDI");
330 samplerate_value.set_text ("-");
331 tags_entry.get_buffer()->set_text ("");
332 timecode_clock.set (0);
333 tags_entry.set_sensitive (false);
336 if (ms->is_type0()) {
337 channels_value.set_text (to_string<uint32_t>(ms->channels().size()));
339 if (ms->num_tracks() > 1) {
340 channels_value.set_text (to_string(ms->num_tracks()) + _("(Tracks)"));
342 channels_value.set_text (to_string(ms->num_tracks()));
345 length_clock.set (ms->length(ms->natural_position()));
346 switch (ms->num_tempos()) {
348 tempomap_value.set_text (_("No tempo data"));
351 Evoral::SMF::Tempo* t = ms->nth_tempo (0);
353 tempomap_value.set_text (string_compose (_("%1/%2 \u2669 = %3"),
360 tempomap_value.set_text (string_compose (_("map with %1 sections"),
365 channels_value.set_text ("");
366 length_clock.set (0);
367 tempomap_value.set_text (_("No tempo data"));
370 if (_session && ms) {
371 play_btn.set_sensitive (true);
373 play_btn.set_sensitive (false);
379 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
381 preview_label.set_markup (_("<b>Sound File Information</b>"));
382 format_text.set_text ("");
383 channels_value.set_text ("");
384 samplerate_value.set_text ("");
385 tags_entry.get_buffer()->set_text ("");
387 length_clock.set (0);
388 timecode_clock.set (0);
390 tags_entry.set_sensitive (false);
391 play_btn.set_sensitive (false);
396 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::Markup::escape_text (Glib::path_get_basename (filename))));
397 std::string n = sf_info.format_name;
398 if (n.substr (0, 8) == X_("Format: ")) {
401 format_text.set_text (n);
402 channels_value.set_text (to_string (sf_info.channels));
404 if (_session && sf_info.samplerate != _session->sample_rate()) {
405 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
406 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
407 samplerate_value.set_name ("NewSessionSR1Label");
408 samplerate.set_name ("NewSessionSR1Label");
410 samplerate.set_text (_("Sample rate:"));
411 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
412 samplerate_value.set_name ("NewSessionSR2Label");
413 samplerate.set_name ("NewSessionSR2Label");
416 samplecnt_t const nfr = _session ? _session->nominal_sample_rate() : 25;
417 double src_coef = (double) nfr / sf_info.samplerate;
419 length_clock.set (sf_info.length * src_coef + 0.5, true);
420 timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
422 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
424 vector<string> tags = Library->get_tags (string ("//") + filename);
426 stringstream tag_string;
427 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
428 if (i != tags.begin()) {
433 tags_entry.get_buffer()->set_text (tag_string.str());
435 tags_entry.set_sensitive (true);
437 play_btn.set_sensitive (true);
444 SoundFileBox::update_autoplay ()
446 const bool config_autoplay = UIConfiguration::instance().get_autoplay_files();
448 if (autoplay_btn.get_active() != config_autoplay) {
449 autoplay_btn.set_active (config_autoplay);
454 SoundFileBox::autoplay_toggled()
456 UIConfiguration::instance().set_autoplay_files(autoplay_btn.get_active());
460 SoundFileBox::autoplay() const
462 return autoplay_btn.get_active();
466 SoundFileBox::audition_oneshot()
473 SoundFileBox::audition ()
479 _session->cancel_audition();
481 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
482 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
486 boost::shared_ptr<Region> r;
488 if (SMFSource::valid_midi_file (path)) {
490 boost::shared_ptr<SMFSource> ms =
491 boost::dynamic_pointer_cast<SMFSource> (
492 SourceFactory::createExternal (DataType::MIDI, *_session,
493 path, 0, Source::Flag (0), false));
495 string rname = region_name_from_path (ms->path(), false);
499 plist.add (ARDOUR::Properties::start, 0);
500 plist.add (ARDOUR::Properties::length, ms->length(ms->natural_position()));
501 plist.add (ARDOUR::Properties::name, rname);
502 plist.add (ARDOUR::Properties::layer, 0);
504 r = boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (boost::dynamic_pointer_cast<Source>(ms), plist, false));
510 boost::shared_ptr<AudioFileSource> afs;
511 bool old_sbp = AudioSource::get_build_peakfiles ();
513 /* don't even think of building peakfiles for these files */
515 AudioSource::set_build_peakfiles (false);
517 for (int n = 0; n < sf_info.channels; ++n) {
519 afs = boost::dynamic_pointer_cast<AudioFileSource> (
520 SourceFactory::createExternal (DataType::AUDIO, *_session,
522 Source::Flag (ARDOUR::AudioFileSource::NoPeakFile), false));
523 if (afs->sample_rate() != _session->nominal_sample_rate()) {
524 boost::shared_ptr<SrcFileSource> sfs (new SrcFileSource(*_session, afs, _src_quality));
525 srclist.push_back(sfs);
527 srclist.push_back(afs);
530 } catch (failed_constructor& err) {
531 error << _("Could not access soundfile: ") << path << endmsg;
532 AudioSource::set_build_peakfiles (old_sbp);
537 AudioSource::set_build_peakfiles (old_sbp);
539 if (srclist.empty()) {
543 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
544 string rname = region_name_from_path (afs->path(), false);
548 plist.add (ARDOUR::Properties::start, 0);
549 plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->natural_position()));
550 plist.add (ARDOUR::Properties::name, rname);
551 plist.add (ARDOUR::Properties::layer, 0);
553 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false));
556 sampleoffset_t audition_position = 0;
557 switch(_import_position) {
558 case ImportAtTimestamp:
559 audition_position = 0;
561 case ImportAtPlayhead:
562 audition_position = _session->transport_sample();
565 audition_position = _session->current_start_sample();
567 case ImportAtEditPoint:
568 audition_position = PublicEditor::instance().get_preferred_edit_position ();
571 r->set_position(audition_position);
573 _session->audition_region(r);
577 SoundFileBox::stop_audition ()
580 _session->cancel_audition();
585 SoundFileBox::tags_entry_left (GdkEventFocus *)
592 SoundFileBox::tags_changed ()
594 string tag_string = tags_entry.get_buffer()->get_text ();
596 if (tag_string.empty()) {
602 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
603 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
611 SoundFileBox::save_tags (const vector<string>& tags)
613 Library->set_tags (string ("//") + path, tags);
614 Library->save_changes ();
617 SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persistent)
618 : ArdourWindow (title)
619 , found_list (ListStore::create(found_list_columns))
620 , freesound_list (ListStore::create(freesound_list_columns))
621 , chooser (FILE_CHOOSER_ACTION_OPEN)
622 , preview (persistent)
623 , found_search_btn (_("Search"))
624 , found_list_view (found_list)
625 , freesound_search_btn (_("Search"))
626 , freesound_list_view (freesound_list)
627 , resetting_ourselves (false)
631 , import_button (_("Import"))
637 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
638 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
639 chooser.add_shortcut_folder_uri("file:///Library/Audio/Apple Loops");
640 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
642 catch (Glib::Error & e) {
643 std::cerr << "sfdb.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
646 Gtkmm2ext::add_volume_shortcuts (chooser);
648 //add the file chooser
650 chooser.set_border_width (12);
652 audio_and_midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun (*this, &SoundFileBrowser::on_audio_and_midi_filter));
653 audio_and_midi_filter.set_name (_("Audio and MIDI files"));
655 audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
656 audio_filter.set_name (_("Audio files"));
658 midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
659 midi_filter.set_name (_("MIDI files"));
661 matchall_filter.add_pattern ("*.*");
662 matchall_filter.set_name (_("All files"));
664 chooser.add_filter (audio_and_midi_filter);
665 chooser.add_filter (audio_filter);
666 chooser.add_filter (midi_filter);
667 chooser.add_filter (matchall_filter);
668 chooser.set_select_multiple (true);
669 chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
670 chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
673 /* some broken redraw behaviour - this is a bandaid */
674 chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
677 if (!persistent_folder.empty()) {
678 chooser.set_current_folder (persistent_folder);
681 notebook.append_page (chooser, _("Browse Files"));
683 hpacker.set_spacing (6);
684 hpacker.pack_start (notebook, true, true);
685 hpacker.pack_start (preview, false, false);
687 vpacker.set_spacing (6);
688 vpacker.pack_start (hpacker, true, true);
698 hbox = manage(new HBox);
699 hbox->pack_start (found_entry);
700 hbox->pack_start (found_search_btn);
702 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
703 scroll->add(found_list_view);
704 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
706 vbox = manage(new VBox);
707 vbox->pack_start (*hbox, PACK_SHRINK);
708 vbox->pack_start (*scroll);
710 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
712 found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
714 found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
716 found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
717 found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
719 notebook.append_page (*vbox, _("Search Tags"));
721 //add freesound search
722 #ifdef FREESOUND_GOT_FIXED
727 passbox = manage(new HBox);
728 passbox->set_spacing (6);
730 label = manage (new Label);
731 label->set_text (_("Tags:"));
732 passbox->pack_start (*label, false, false);
733 passbox->pack_start (freesound_entry, true, true);
735 label = manage (new Label);
736 label->set_text (_("Sort:"));
737 passbox->pack_start (*label, false, false);
738 passbox->pack_start (freesound_sort, false, false);
739 freesound_sort.clear_items();
741 // Order of the following must correspond with enum sortMethod
742 // in sfdb_freesound_mootcher.h
743 freesound_sort.append_text(_("None"));
744 freesound_sort.append_text(_("Longest"));
745 freesound_sort.append_text(_("Shortest"));
746 freesound_sort.append_text(_("Newest"));
747 freesound_sort.append_text(_("Oldest"));
748 freesound_sort.append_text(_("Most downloaded"));
749 freesound_sort.append_text(_("Least downloaded"));
750 freesound_sort.append_text(_("Highest rated"));
751 freesound_sort.append_text(_("Lowest rated"));
752 freesound_sort.set_active(0);
754 passbox->pack_start (freesound_search_btn, false, false);
755 passbox->pack_start (freesound_more_btn, false, false);
756 freesound_more_btn.set_label(_("More"));
757 freesound_more_btn.set_sensitive(false);
759 passbox->pack_start (freesound_similar_btn, false, false);
760 freesound_similar_btn.set_label(_("Similar"));
761 freesound_similar_btn.set_sensitive(false);
763 scroll = manage(new ScrolledWindow);
764 scroll->add(freesound_list_view);
765 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
767 vbox = manage(new VBox);
768 vbox->set_spacing (3);
769 vbox->pack_start (*passbox, PACK_SHRINK);
770 vbox->pack_start (*scroll);
772 freesound_list_view.append_column(_("ID") , freesound_list_columns.id);
773 freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
774 // freesound_list_view.append_column(_("URI") , freesound_list_columns.uri);
775 freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
776 freesound_list_view.append_column(_("Size"), freesound_list_columns.filesize);
777 freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
778 freesound_list_view.append_column(_("License"), freesound_list_columns.license);
779 freesound_list_view.get_column(0)->set_alignment(0.5);
780 freesound_list_view.get_column(1)->set_expand(true); // filename
781 freesound_list_view.get_column(1)->set_resizable(true); // filename
782 freesound_list_view.get_column(2)->set_alignment(0.5);
783 freesound_list_view.get_column(3)->set_alignment(0.5);
784 freesound_list_view.get_column(4)->set_alignment(0.5);
785 freesound_list_view.get_column(5)->set_alignment(0.5);
787 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
788 freesound_list_view.set_tooltip_column(1);
790 freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
791 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
792 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
793 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
794 freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
795 freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
796 notebook.append_page (*vbox, _("Search Freesound"));
799 notebook.set_size_request (500, -1);
800 notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
804 Gtk::HButtonBox* button_box = manage (new HButtonBox);
806 button_box->set_layout (BUTTONBOX_END);
808 button_box->pack_start (import_button, false, false);
809 import_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_OK));
811 Gtkmm2ext::UI::instance()->set_tip (import_button, _("Press to import selected files"));
813 vpacker.pack_end (*button_box, false, false);
815 set_wmclass (X_("import"), PROGRAM_NAME);
818 SoundFileBrowser::~SoundFileBrowser ()
820 persistent_folder = chooser.get_current_folder();
824 SoundFileBrowser::run ()
833 gtk_main_iteration ();
840 SoundFileBrowser::set_action_sensitive (bool yn)
842 import_button.set_sensitive (yn);
846 SoundFileBrowser::get_action_sensitive () const
848 return import_button.get_sensitive ();
852 SoundFileBrowser::do_something (int action)
859 SoundFileBrowser::on_show ()
861 ArdourWindow::on_show ();
867 SoundFileBrowser::on_key_press_event (GdkEventKey* ev)
869 if (ev->keyval == GDK_Escape) {
870 do_something (RESPONSE_CLOSE);
873 if (ev->keyval == GDK_space && ev->type == GDK_KEY_PRESS) {
874 if (get_action_sensitive()) {
879 return ArdourWindow::on_key_press_event (ev);
883 SoundFileBrowser::clear_selection ()
885 chooser.unselect_all ();
886 found_list_view.get_selection()->unselect_all ();
890 SoundFileBrowser::chooser_file_activated ()
892 do_something (RESPONSE_OK);
896 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
902 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
908 SoundFileBrowser::set_session (Session* s)
910 ArdourWindow::set_session (s);
911 preview.set_session (s);
916 remove_gain_meter ();
921 SoundFileBrowser::add_gain_meter ()
925 gm = new GainMeter (_session, 250);
927 boost::shared_ptr<Route> r = _session->the_auditioner ();
929 gm->set_controls (r, r->shared_peak_meter(), r->amp(), r->gain_control());
930 gm->set_fader_name (X_("GainFader"));
932 meter_packer.set_border_width (12);
933 meter_packer.pack_start (*gm, false, true);
934 hpacker.pack_end (meter_packer, false, false);
935 meter_packer.show_all ();
940 SoundFileBrowser::remove_gain_meter ()
943 meter_packer.remove (*gm);
944 hpacker.remove (meter_packer);
951 SoundFileBrowser::start_metering ()
953 metering_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
957 SoundFileBrowser::stop_metering ()
959 metering_connection.disconnect();
963 SoundFileBrowser::meter ()
965 if (is_mapped () && _session && gm) {
966 gm->update_meters ();
971 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
973 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
977 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
979 return SMFSource::safe_midi_file_extension (filter_info.filename);
983 SoundFileBrowser::on_audio_and_midi_filter (const FileFilter::Info& filter_info)
985 return on_audio_filter (filter_info) || on_midi_filter (filter_info);
989 SoundFileBrowser::update_preview ()
991 if (preview.setup_labels (chooser.get_preview_filename())) {
992 if (preview.autoplay()) {
993 Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
999 SoundFileBrowser::found_list_view_selected ()
1001 if (!reset_options ()) {
1002 set_action_sensitive (false);
1006 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1008 if (!rows.empty()) {
1009 TreeIter iter = found_list->get_iter(*rows.begin());
1010 file = (*iter)[found_list_columns.pathname];
1011 chooser.set_filename (file);
1012 set_action_sensitive (true);
1014 set_action_sensitive (false);
1017 preview.setup_labels (file);
1022 SoundFileBrowser::found_search_clicked ()
1024 string tag_string = found_entry.get_text ();
1026 vector<string> tags;
1028 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
1029 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
1033 vector<string> results;
1034 Library->search_members_and (results, tags);
1036 found_list->clear();
1037 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
1038 TreeModel::iterator new_row = found_list->append();
1039 TreeModel::Row row = *new_row;
1040 string path = Glib::filename_from_uri (string ("file:") + *i);
1041 row[found_list_columns.pathname] = path;
1047 SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
1050 Mootcher *mootcher = new Mootcher;
1053 string id = (*iter)[freesound_list_columns.id];
1054 string uri = (*iter)[freesound_list_columns.uri];
1055 string ofn = (*iter)[freesound_list_columns.filename];
1057 if (mootcher->checkAudioFile(ofn, id)) {
1058 // file already exists, no need to download it again
1059 file = mootcher->audioFileName;
1061 (*iter)[freesound_list_columns.started] = false;
1064 if (!(*iter)[freesound_list_columns.started]) {
1065 // start downloading the sound file
1066 (*iter)[freesound_list_columns.started] = true;
1067 mootcher->fetchAudioFile(ofn, id, uri, this);
1073 SoundFileBrowser::freesound_list_view_selected ()
1076 if (!reset_options ()) {
1077 set_action_sensitive (false);
1080 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1081 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1082 file = freesound_get_audio_file (freesound_list->get_iter(*i));
1085 switch (rows.size()) {
1088 freesound_similar_btn.set_sensitive(false);
1089 set_action_sensitive (false);
1092 // exactly one item selected
1094 // file exists on disk already
1095 chooser.set_filename (file);
1096 preview.setup_labels (file);
1097 set_action_sensitive (true);
1099 freesound_similar_btn.set_sensitive(true);
1102 // multiple items selected
1103 preview.setup_labels ("");
1104 freesound_similar_btn.set_sensitive(false);
1112 SoundFileBrowser::refresh_display(std::string ID, std::string file)
1114 // called when the mootcher has finished downloading a file
1115 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1116 if (rows.size() == 1) {
1117 // there's a single item selected in the freesound list
1118 //XXX make a function to be used to construct the actual file name both here and in the mootcher
1119 Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
1120 std::string selected_ID = (*row)[freesound_list_columns.id];
1121 if (ID == selected_ID) {
1122 // the selected item in the freesound list is the item that has just finished downloading
1123 chooser.set_filename(file);
1124 preview.setup_labels (file);
1125 set_action_sensitive (true);
1131 SoundFileBrowser::freesound_search_clicked ()
1134 freesound_list->clear();
1140 SoundFileBrowser::freesound_more_clicked ()
1145 snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
1146 freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
1150 SoundFileBrowser::freesound_similar_clicked ()
1152 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1153 if (rows.size() == 1) {
1156 Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
1157 id = (*iter)[freesound_list_columns.id];
1158 freesound_list->clear();
1160 GdkCursor *prev_cursor;
1161 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1162 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1165 std::string theString = mootcher.searchSimilar(id);
1167 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1168 handle_freesound_results(theString);
1173 SoundFileBrowser::freesound_search()
1177 string search_string = freesound_entry.get_text ();
1178 enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
1180 GdkCursor *prev_cursor;
1181 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1182 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1185 std::string theString = mootcher.searchText(
1189 "", // OSX eats anything incl mp3
1191 "type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
1196 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1197 handle_freesound_results(theString);
1201 SoundFileBrowser::handle_freesound_results(std::string theString) {
1203 doc.read_buffer( theString );
1204 XMLNode *root = doc.root();
1207 error << "no root XML node!" << endmsg;
1211 if ( strcmp(root->name().c_str(), "response") != 0) {
1212 error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
1216 // find out how many pages are available to search
1217 int freesound_n_pages = 1;
1218 XMLNode *res = root->child("num_pages");
1220 string result = res->child("text")->content();
1221 freesound_n_pages = atoi(result);
1224 int more_pages = freesound_n_pages - freesound_page;
1226 if (more_pages > 0) {
1227 freesound_more_btn.set_sensitive(true);
1228 freesound_more_btn.set_tooltip_text(string_compose(P_(
1229 "%1 more page of 100 results available",
1230 "%1 more pages of 100 results available",
1231 more_pages), more_pages));
1233 freesound_more_btn.set_sensitive(false);
1234 freesound_more_btn.set_tooltip_text(_("No more results available"));
1237 XMLNode *sounds_root = root->child("sounds");
1239 error << "no child node \"sounds\" found!" << endmsg;
1243 XMLNodeList sounds = sounds_root->children();
1244 if (sounds.size() == 0) {
1249 XMLNodeConstIterator niter;
1251 for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
1253 if( strcmp( node->name().c_str(), "resource") != 0 ) {
1254 error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
1258 // node->dump(cerr, "node:");
1261 XMLNode *id_node = node->child ("id");
1262 XMLNode *uri_node = node->child ("serve");
1263 XMLNode *ofn_node = node->child ("original_filename");
1264 XMLNode *dur_node = node->child ("duration");
1265 XMLNode *siz_node = node->child ("filesize");
1266 XMLNode *srt_node = node->child ("samplerate");
1267 XMLNode *lic_node = node->child ("license");
1269 if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
1271 std::string id = id_node->child("text")->content();
1272 std::string uri = uri_node->child("text")->content();
1273 std::string ofn = ofn_node->child("text")->content();
1274 std::string dur = dur_node->child("text")->content();
1275 std::string siz = siz_node->child("text")->content();
1276 std::string srt = srt_node->child("text")->content();
1277 std::string lic = lic_node->child("text")->content();
1280 // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
1282 double duration_seconds = atof(dur);
1284 char duration_hhmmss[16];
1285 if (duration_seconds >= 99 * 60 * 60) {
1286 strcpy(duration_hhmmss, ">99h");
1288 s = modf(duration_seconds/60, &m) * 60;
1289 m = modf(m/60, &h) * 60;
1290 sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
1295 double size_bytes = atof(siz);
1297 if (size_bytes < 1000) {
1298 sprintf(bsize, "%.0f %s", size_bytes, _("B"));
1299 } else if (size_bytes < 1000000 ) {
1300 sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
1301 } else if (size_bytes < 10000000) {
1302 sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
1303 } else if (size_bytes < 1000000000) {
1304 sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
1306 sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
1309 /* see http://www.freesound.org/help/faq/#licenses */
1310 char shortlicense[64];
1311 if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
1312 sprintf(shortlicense, "CC-BY-NC");
1313 } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
1314 sprintf(shortlicense, "CC-BY");
1315 } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
1316 sprintf(shortlicense, "sampling+");
1317 } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
1318 sprintf(shortlicense, "PD");
1320 snprintf(shortlicense, 64, "%s", lic.c_str());
1321 shortlicense[63]= '\0';
1324 TreeModel::iterator new_row = freesound_list->append();
1325 TreeModel::Row row = *new_row;
1327 row[freesound_list_columns.id ] = id;
1328 row[freesound_list_columns.uri ] = uri;
1329 row[freesound_list_columns.filename] = ofn;
1330 row[freesound_list_columns.duration] = duration_hhmmss;
1331 row[freesound_list_columns.filesize] = bsize;
1332 row[freesound_list_columns.smplrate] = srt;
1333 row[freesound_list_columns.license ] = shortlicense;
1340 SoundFileBrowser::get_paths ()
1342 vector<string> results;
1344 int n = notebook.get_current_page ();
1347 vector<string> filenames = chooser.get_filenames();
1348 vector<string>::iterator i;
1350 for (i = filenames.begin(); i != filenames.end(); ++i) {
1352 if ((!g_stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
1353 results.push_back (*i);
1357 } else if (n == 1) {
1359 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1360 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1361 TreeIter iter = found_list->get_iter(*i);
1362 string str = (*iter)[found_list_columns.pathname];
1364 results.push_back (str);
1367 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1368 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1369 string str = freesound_get_audio_file (freesound_list->get_iter(*i));
1371 results.push_back (str);
1380 SoundFileOmega::reset_options_noret ()
1382 if (!resetting_ourselves) {
1383 (void) reset_options ();
1388 SoundFileOmega::reset_options ()
1390 if (_import_active) {
1391 _reset_post_import = true;
1395 vector<string> paths = get_paths ();
1397 if (paths.empty()) {
1399 channel_combo.set_sensitive (false);
1400 action_combo.set_sensitive (false);
1401 where_combo.set_sensitive (false);
1402 copy_files_btn.set_active (true);
1403 copy_files_btn.set_sensitive (false);
1409 channel_combo.set_sensitive (true);
1410 action_combo.set_sensitive (true);
1411 where_combo.set_sensitive (true);
1413 /* if we get through this function successfully, this may be
1414 reset at the end, once we know if we can use hard links
1415 to do embedding (or if we are importing a MIDI file).
1418 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1419 copy_files_btn.set_sensitive (false);
1421 copy_files_btn.set_sensitive (false);
1427 bool selection_includes_multichannel;
1428 bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1431 /* See if we are thinking about importing any MIDI files */
1432 vector<string>::iterator i = paths.begin ();
1433 while (i != paths.end() && SMFSource::valid_midi_file (*i) == false) {
1436 bool const have_a_midi_file = (i != paths.end ());
1438 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1439 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1443 if (have_a_midi_file) {
1444 smf_tempo_btn.show ();
1446 smf_tempo_btn.hide ();
1449 string existing_choice;
1450 vector<string> action_strings;
1452 resetting_ourselves = true;
1454 if (chooser.get_filter() == &audio_filter) {
1458 if (selected_audio_track_cnt > 0) {
1459 if (channel_combo.get_active_text().length()) {
1460 ImportDisposition id = get_channel_disposition();
1463 case Editing::ImportDistinctFiles:
1464 if (selected_audio_track_cnt == paths.size()) {
1465 action_strings.push_back (importmode2string (ImportToTrack));
1469 case Editing::ImportDistinctChannels:
1470 /* XXX it would be nice to allow channel-per-selected track
1471 but its too hard we don't want to deal with all the
1472 different per-file + per-track channel configurations.
1477 action_strings.push_back (importmode2string (ImportToTrack));
1487 if (selected_midi_track_cnt > 0) {
1488 action_strings.push_back (importmode2string (ImportToTrack));
1492 action_strings.push_back (importmode2string (ImportAsTrack));
1493 action_strings.push_back (importmode2string (ImportAsRegion));
1494 if (!Profile->get_mixbus()) {
1495 action_strings.push_back (importmode2string (ImportAsTapeTrack));
1498 existing_choice = action_combo.get_active_text();
1500 set_popdown_strings (action_combo, action_strings);
1502 /* preserve any existing choice, if possible */
1505 if (existing_choice.length()) {
1506 vector<string>::iterator x;
1507 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1508 if (*x == existing_choice) {
1509 action_combo.set_active_text (existing_choice);
1513 if (x == action_strings.end()) {
1514 action_combo.set_active_text (action_strings.front());
1517 action_combo.set_active_text (action_strings.front());
1520 resetting_ourselves = false;
1522 if ((mode = get_mode()) == ImportAsRegion) {
1523 where_combo.set_sensitive (false);
1525 where_combo.set_sensitive (true);
1528 vector<string> channel_strings;
1530 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1532 if (selection_includes_multichannel) {
1533 channel_strings.push_back (_("one track per channel"));
1536 channel_strings.push_back (_("one track per file"));
1538 if (paths.size() > 1) {
1539 /* tape tracks are a single region per track, so we cannot
1540 sequence multiple files.
1542 if (mode != ImportAsTapeTrack) {
1543 channel_strings.push_back (_("sequence files"));
1546 channel_strings.push_back (_("all files in one track"));
1547 channel_strings.push_back (_("merge files"));
1553 channel_strings.push_back (_("one region per file"));
1555 if (selection_includes_multichannel) {
1556 channel_strings.push_back (_("one region per channel"));
1559 if (paths.size() > 1) {
1561 channel_strings.push_back (_("all files in one region"));
1566 resetting_ourselves = true;
1568 existing_choice = channel_combo.get_active_text();
1570 set_popdown_strings (channel_combo, channel_strings);
1572 /* preserve any existing choice, if possible */
1574 if (existing_choice.length()) {
1575 vector<string>::iterator x;
1576 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1577 if (*x == existing_choice) {
1578 channel_combo.set_active_text (existing_choice);
1582 if (x == channel_strings.end()) {
1583 channel_combo.set_active_text (channel_strings.front());
1586 channel_combo.set_active_text (channel_strings.front());
1589 resetting_ourselves = false;
1592 src_combo.set_sensitive (true);
1594 src_combo.set_sensitive (false);
1597 /* We must copy MIDI files or those from Freesound
1598 * or any file if we are under nsm control */
1599 bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
1601 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1603 if (selection_can_be_embedded_with_links && !must_copy) {
1604 copy_files_btn.set_sensitive (true);
1607 copy_files_btn.set_active (true);
1609 copy_files_btn.set_sensitive (false);
1615 copy_files_btn.set_active (true);
1617 copy_files_btn.set_sensitive (!must_copy);
1625 SoundFileOmega::bad_file_message()
1627 MessageDialog msg (*this,
1628 string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1633 resetting_ourselves = true;
1634 chooser.unselect_uri (chooser.get_preview_uri());
1635 resetting_ourselves = false;
1641 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1650 multichannel = false;
1652 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1654 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1655 if (info.channels > 1) {
1656 multichannel = true;
1661 if (sz != info.length) {
1666 if (info.samplerate != _session->sample_rate()) {
1670 } else if (SMFSource::valid_midi_file (*i)) {
1674 if (reader.open (*i)) {
1677 if (reader.is_type0 ()) {
1678 if (reader.channels().size() > 1) {
1679 /* for type-0 files, we can split
1680 * "one track per channel"
1682 multichannel = true;
1685 if (reader.num_tracks() > 1) {
1686 multichannel = true;
1701 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1703 std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
1706 if (g_mkdir (tmpdir.c_str(), 0744)) {
1707 if (errno != EEXIST) {
1712 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1714 char tmpc[PATH_MAX+1];
1716 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1719 #ifdef PLATFORM_WINDOWS
1720 /* see also ntfs_link -- msvc only pbd extension */
1721 if (false == CreateHardLinkA (/*new link*/ tmpc, /*existing file*/ (*i).c_str(), NULL)) {
1725 if (link (/*existing file*/(*i).c_str(), tmpc)) {
1736 g_rmdir (tmpdir.c_str());
1740 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
1741 : SoundFileBrowser (title, s, false)
1743 chooser.set_select_multiple (false);
1744 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1745 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1749 SoundFileChooser::on_hide ()
1751 ArdourWindow::on_hide();
1755 _session->cancel_audition();
1760 SoundFileChooser::get_filename ()
1762 vector<string> paths;
1764 paths = get_paths ();
1766 if (paths.empty()) {
1770 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1774 return paths.front();
1777 SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s,
1778 uint32_t selected_audio_tracks,
1779 uint32_t selected_midi_tracks,
1781 Editing::ImportMode mode_hint)
1782 : SoundFileBrowser (title, s, persistent)
1783 , copy_files_btn ( _("Copy files to session"))
1784 , smf_tempo_btn (_("Use MIDI Tempo Map (if defined)"))
1785 , selected_audio_track_cnt (selected_audio_tracks)
1786 , selected_midi_track_cnt (selected_midi_tracks)
1787 , _import_active (false)
1788 , _reset_post_import (false)
1792 set_size_request (-1, 550);
1794 block_two.set_border_width (12);
1795 block_three.set_border_width (12);
1796 block_four.set_border_width (12);
1799 str.push_back (_("file timestamp"));
1800 str.push_back (_("edit point"));
1801 str.push_back (_("playhead"));
1802 str.push_back (_("session start"));
1803 set_popdown_strings (where_combo, str);
1804 where_combo.set_active_text (str.back());
1805 where_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::where_combo_changed));
1807 instrument_combo_changed();
1808 instrument_combo.signal_changed().connect(sigc::mem_fun(*this, &SoundFileOmega::instrument_combo_changed) );
1810 Label* l = manage (new Label);
1811 l->set_markup (_("<b>Add files ...</b>"));
1812 options.attach (*l, 0, 1, 0, 1, FILL, SHRINK, 8, 0);
1813 options.attach (action_combo, 0, 1, 1, 2, FILL, SHRINK, 8, 0);
1815 l = manage (new Label);
1816 l->set_markup (_("<b>Insert at</b>"));
1817 options.attach (*l, 0, 1, 3, 4, FILL, SHRINK, 8, 0);
1818 options.attach (where_combo, 0, 1, 4, 5, FILL, SHRINK, 8, 0);
1820 l = manage (new Label);
1821 l->set_markup (_("<b>Mapping</b>"));
1822 options.attach (*l, 1, 2, 0, 1, FILL, SHRINK, 8, 0);
1823 options.attach (channel_combo, 1, 2, 1, 2, FILL, SHRINK, 8, 0);
1825 l = manage (new Label);
1826 l->set_markup (_("<b>Conversion quality</b>"));
1827 options.attach (*l, 1, 2, 3, 4, FILL, SHRINK, 8, 0);
1828 options.attach (src_combo, 1, 2, 4, 5, FILL, SHRINK, 8, 0);
1830 l = manage (new Label);
1831 l->set_markup (_("<b>MIDI Track Names</b>"));
1832 options.attach (*l, 2, 3, 0, 1, FILL, SHRINK, 8, 0);
1833 options.attach (midi_track_name_combo, 2, 3, 1, 2, FILL, SHRINK, 8, 0);
1835 options.attach (smf_tempo_btn, 2, 3, 3, 4, FILL, SHRINK, 8, 0);
1837 l = manage (new Label);
1838 l->set_markup (_("<b>Instrument</b>"));
1839 options.attach (*l, 3, 4, 0, 1, FILL, SHRINK, 8, 0);
1840 options.attach (instrument_combo, 3, 4, 1, 2, FILL, SHRINK, 8, 0);
1842 Alignment *hspace = manage (new Alignment ());
1843 hspace->set_size_request (2, 2);
1844 options.attach (*hspace, 0, 3, 2, 3, FILL, SHRINK, 0, 8);
1846 Alignment *vspace = manage (new Alignment ());
1847 vspace->set_size_request (2, 2);
1848 options.attach (*vspace, 2, 3, 0, 3, EXPAND, SHRINK, 0, 0);
1851 str.push_back (_("by track number"));
1852 str.push_back (_("by track name"));
1853 str.push_back (_("by instrument name"));
1854 set_popdown_strings (midi_track_name_combo, str);
1855 midi_track_name_combo.set_active_text (str.front());
1858 str.push_back (_("one track per file"));
1859 set_popdown_strings (channel_combo, str);
1860 channel_combo.set_active_text (str.front());
1861 channel_combo.set_sensitive (false);
1864 str.push_back (_("Best"));
1865 str.push_back (_("Good"));
1866 str.push_back (_("Quick"));
1867 str.push_back (_("Fast"));
1868 str.push_back (_("Fastest"));
1870 set_popdown_strings (src_combo, str);
1871 src_combo.set_active_text (str.front());
1872 src_combo.set_sensitive (false);
1873 src_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::src_combo_changed));
1875 action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1876 channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1878 copy_files_btn.set_active (true);
1880 Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1883 copy_label->set_size_request (175, -1);
1884 copy_label->set_line_wrap (true);
1887 block_four.pack_start (copy_files_btn, false, false);
1888 options.attach (block_four, 3, 4, 4, 5, FILL, SHRINK, 8, 0);
1890 vpacker.pack_start (options, false, true);
1892 /* setup disposition map */
1894 disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1895 disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1896 disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1897 disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1899 disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1900 disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1901 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1902 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1904 chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1906 /* set size requests for a couple of combos to allow them to display the longest text
1907 they will ever be asked to display. This prevents them being resized when the user
1908 selects a file to import, which in turn prevents the size of the dialog from jumping
1912 str.push_back (_("one track per file"));
1913 str.push_back (_("one track per channel"));
1914 str.push_back (_("sequence files"));
1915 str.push_back (_("all files in one region"));
1916 set_popdown_strings (channel_combo, str);
1919 str.push_back (importmode2string (ImportAsTrack));
1920 str.push_back (importmode2string (ImportToTrack));
1921 str.push_back (importmode2string (ImportAsRegion));
1922 str.push_back (importmode2string (ImportAsTapeTrack));
1923 set_popdown_strings (action_combo, str);
1924 action_combo.set_active_text (importmode2string(mode_hint));
1926 reset (selected_audio_tracks, selected_midi_tracks);
1930 SoundFileOmega::set_mode (ImportMode mode)
1932 action_combo.set_active_text (importmode2string (mode));
1936 SoundFileOmega::get_mode () const
1938 return string2importmode (action_combo.get_active_text());
1942 SoundFileOmega::on_hide ()
1944 ArdourWindow::on_hide();
1946 _session->cancel_audition();
1951 SoundFileOmega::get_position() const
1953 string str = where_combo.get_active_text();
1955 if (str == _("file timestamp")) {
1956 return ImportAtTimestamp;
1957 } else if (str == _("edit point")) {
1958 return ImportAtEditPoint;
1959 } else if (str == _("playhead")) {
1960 return ImportAtPlayhead;
1962 return ImportAtStart;
1967 SoundFileOmega::get_src_quality() const
1969 string str = src_combo.get_active_text();
1971 if (str == _("Best")) {
1973 } else if (str == _("Good")) {
1975 } else if (str == _("Quick")) {
1977 } else if (str == _("Fast")) {
1985 SoundFileOmega::src_combo_changed()
1987 preview.set_src_quality(get_src_quality());
1991 SoundFileOmega::where_combo_changed()
1993 preview.set_import_position(get_position());
1997 SoundFileOmega::instrument_combo_changed()
1999 _session->the_auditioner()->set_audition_synth_info( instrument_combo.selected_instrument() );
2003 SoundFileOmega::get_midi_track_name_source () const
2005 return string2miditracknamesource (midi_track_name_combo.get_active_text());
2009 SoundFileOmega::get_use_smf_tempo_map () const
2011 return smf_tempo_btn.get_active ();
2015 SoundFileOmega::get_channel_disposition () const
2017 /* we use a map here because the channel combo can contain different strings
2018 depending on the state of the other combos. the map contains all possible strings
2019 and the ImportDisposition enum that corresponds to it.
2022 string str = channel_combo.get_active_text();
2023 DispositionMap::const_iterator x = disposition_map.find (str);
2025 if (x == disposition_map.end()) {
2026 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
2027 abort(); /*NOTREACHED*/
2034 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
2036 selected_audio_track_cnt = selected_audio_tracks;
2037 selected_midi_track_cnt = selected_midi_tracks;
2039 if (selected_audio_track_cnt == 0 && selected_midi_track_cnt > 0) {
2040 chooser.set_filter (midi_filter);
2041 } else if (selected_midi_track_cnt == 0 && selected_audio_track_cnt > 0) {
2042 chooser.set_filter (audio_filter);
2044 chooser.set_filter (audio_and_midi_filter);
2053 SoundFileOmega::file_selection_changed ()
2055 if (resetting_ourselves || !is_visible ()) {
2059 if (!reset_options ()) {
2060 set_action_sensitive (false);
2062 if (chooser.get_filenames().size() > 0) {
2063 set_action_sensitive (true);
2065 set_action_sensitive (false);
2071 SoundFileOmega::do_something (int action)
2073 SoundFileBrowser::do_something (action);
2075 if (action == RESPONSE_CLOSE || !ARDOUR_UI_UTILS::engine_is_running ()) {
2082 vector<string> paths = get_paths ();
2083 ImportPosition pos = get_position ();
2084 ImportMode mode = get_mode ();
2085 ImportDisposition chns = get_channel_disposition ();
2086 PluginInfoPtr instrument = instrument_combo.selected_instrument();
2088 MidiTrackNameSource mts = get_midi_track_name_source ();
2089 MidiTempoMapDisposition mtd = (get_use_smf_tempo_map () ? SMFTempoUse : SMFTempoIgnore);
2092 case ImportAtEditPoint:
2093 where = PublicEditor::instance().get_preferred_edit_position ();
2095 case ImportAtTimestamp:
2098 case ImportAtPlayhead:
2099 where = _session->transport_sample();
2102 where = _session->current_start_sample();
2106 SrcQuality quality = get_src_quality();
2108 _import_active = true;
2110 if (copy_files_btn.get_active()) {
2111 PublicEditor::instance().do_import (paths, chns, mode, quality, mts, mtd, where, instrument);
2113 PublicEditor::instance().do_embed (paths, chns, mode, where, instrument);
2116 _import_active = false;
2118 if (_reset_post_import) {
2119 _reset_post_import = false;