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"
33 #include <gtkmm/box.h>
34 #include <gtkmm/scrolledwindow.h>
35 #include <gtkmm/stock.h>
37 #include "pbd/gstdio_compat.h"
38 #include <glibmm/fileutils.h>
40 #include "pbd/tokenizer.h"
41 #include "pbd/enumwriter.h"
42 #include "pbd/pthread_utils.h"
43 #include "pbd/string_convert.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/midi_region.h"
55 #include "ardour/smf_source.h"
56 #include "ardour/region_factory.h"
57 #include "ardour/source_factory.h"
58 #include "ardour/session.h"
59 #include "ardour/session_directory.h"
60 #include "ardour/srcfilesource.h"
61 #include "ardour/profile.h"
63 #include "ardour_ui.h"
65 #include "gui_thread.h"
69 #include "gain_meter.h"
70 #include "main_clock.h"
71 #include "public_editor.h"
73 #include "ui_config.h"
75 #include "sfdb_freesound_mootcher.h"
77 using namespace ARDOUR;
81 using namespace Gtkmm2ext;
82 using namespace Editing;
86 string SoundFileBrowser::persistent_folder;
87 typedef TreeView::Selection::ListHandle_Path ListPath;
89 static MidiTrackNameSource
90 string2miditracknamesource (string const & str)
92 if (str == _("by track number")) {
93 return SMFTrackNumber;
94 } else if (str == _("by track name")) {
96 } else if (str == _("by instrument name")) {
97 return SMFInstrumentName;
100 warning << string_compose (_("programming error: unknown midi track name source string %1"), str) << endmsg;
102 return SMFTrackNumber;
106 string2importmode (string const & str)
108 if (str == _("as new tracks")) {
109 return ImportAsTrack;
110 } else if (str == _("to selected tracks")) {
111 return ImportToTrack;
112 } else if (str == _("to region list")) {
113 return ImportAsRegion;
114 } else if (str == _("as new tape tracks")) {
115 return ImportAsTapeTrack;
118 warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
120 return ImportAsTrack;
124 importmode2string (ImportMode mode)
128 return _("as new tracks");
130 return _("to selected tracks");
132 return _("to region list");
133 case ImportAsTapeTrack:
134 return _("as new tape tracks");
136 abort(); /*NOTREACHED*/
137 return _("as new tracks");
140 SoundFileBox::SoundFileBox (bool /*persistent*/)
142 length_clock ("sfboxLengthClock", true, "", false, false, true, false),
143 timecode_clock ("sfboxTimecodeClock", true, "", false, false, false, false),
145 autoplay_btn (_("Auto-play")),
146 seek_slider(0,1000,1),
148 _src_quality (SrcBest),
149 _import_position (ImportAtTimestamp)
152 set_name (X_("SoundFileBox"));
153 set_size_request (300, -1);
155 preview_label.set_markup (_("<b>Sound File Information</b>"));
157 border_frame.set_label_widget (preview_label);
158 border_frame.add (main_box);
160 pack_start (border_frame, true, true);
161 set_border_width (6);
163 main_box.set_border_width (6);
165 length.set_text (_("Length:"));
166 length.set_alignment (1, 0.5);
167 timecode.set_text (_("Timestamp:"));
168 timecode.set_alignment (1, 0.5);
169 format.set_text (_("Format:"));
170 format.set_alignment (1, 0.5);
171 channels.set_text (_("Channels:"));
172 channels.set_alignment (1, 0.5);
173 samplerate.set_text (_("Sample rate:"));
174 samplerate.set_alignment (1, 0.5);
175 tempomap.set_text (_("Tempo Map:"));
176 tempomap.set_alignment (1, 0.5);
178 preview_label.set_max_width_chars (50);
179 preview_label.set_ellipsize (Pango::ELLIPSIZE_END);
181 format_text.set_max_width_chars (20);
182 format_text.set_ellipsize (Pango::ELLIPSIZE_END);
183 format_text.set_alignment (0, 1);
185 table.set_col_spacings (6);
186 table.set_homogeneous (false);
187 table.set_row_spacings (6);
189 table.attach (channels, 0, 1, 0, 1, FILL, FILL);
190 table.attach (samplerate, 0, 1, 1, 2, FILL, FILL);
191 table.attach (format, 0, 1, 2, 4, FILL, FILL);
192 table.attach (length, 0, 1, 4, 5, FILL, FILL);
193 table.attach (timecode, 0, 1, 5, 6, FILL, FILL);
194 table.attach (tempomap, 0, 1, 6, 7, FILL, FILL);
196 table.attach (channels_value, 1, 2, 0, 1, FILL, FILL);
197 table.attach (samplerate_value, 1, 2, 1, 2, FILL, FILL);
198 table.attach (format_text, 1, 2, 2, 4, FILL, FILL);
199 table.attach (length_clock, 1, 2, 4, 5, FILL, FILL);
200 table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL);
201 table.attach (tempomap_value, 1, 2, 6, 7, FILL, FILL);
203 length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock->mode());
204 timecode_clock.set_mode (AudioClock::Timecode);
206 main_box.pack_start (table, false, false);
208 tags_entry.set_editable (true);
209 tags_entry.set_wrap_mode(Gtk::WRAP_WORD);
210 tags_entry.signal_focus_out_event().connect (sigc::mem_fun (*this, &SoundFileBox::tags_entry_left));
212 Label* label = manage (new Label (_("Tags:")));
213 label->set_alignment (0.0f, 0.5f);
214 main_box.pack_start (*label, false, false);
215 main_box.pack_start (tags_entry, true, true);
217 main_box.pack_start (bottom_box, false, false);
219 play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
220 // play_btn.set_label (_("Play"));
222 stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
223 // stop_btn.set_label (_("Stop"));
225 bottom_box.set_homogeneous (false);
226 bottom_box.set_spacing (6);
227 bottom_box.pack_start(play_btn, true, true);
228 bottom_box.pack_start(stop_btn, true, true);
229 bottom_box.pack_start(autoplay_btn, false, false);
231 seek_slider.set_draw_value(false);
233 seek_slider.add_events(Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
234 seek_slider.signal_button_press_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_press), false);
235 seek_slider.signal_button_release_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_release), false);
236 main_box.pack_start (seek_slider, false, false);
238 play_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::audition));
239 stop_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::stop_audition));
242 autoplay_btn.signal_toggled().connect(sigc::mem_fun (*this, &SoundFileBox::autoplay_toggled));
244 stop_btn.set_sensitive (false);
246 channels_value.set_alignment (0.0f, 0.5f);
247 samplerate_value.set_alignment (0.0f, 0.5f);
251 SoundFileBox::set_session(Session* s)
253 SessionHandlePtr::set_session (s);
255 length_clock.set_session (s);
256 timecode_clock.set_session (s);
259 play_btn.set_sensitive (false);
260 stop_btn.set_sensitive (false);
261 auditioner_connections.drop_connections();
263 auditioner_connections.drop_connections();
264 _session->AuditionActive.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_active, this, _1), gui_context());
265 _session->the_auditioner()->AuditionProgress.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_progress, this, _1, _2), gui_context());
270 SoundFileBox::audition_active(bool active) {
271 stop_btn.set_sensitive (active);
272 seek_slider.set_sensitive (active);
274 seek_slider.set_value(0);
279 SoundFileBox::audition_progress(ARDOUR::framecnt_t pos, ARDOUR::framecnt_t len) {
281 seek_slider.set_value( 1000.0 * pos / len);
282 seek_slider.set_sensitive (true);
287 SoundFileBox::seek_button_press(GdkEventButton*) {
289 return false; // pass on to slider
293 SoundFileBox::seek_button_release(GdkEventButton*) {
295 _session->the_auditioner()->seek_to_percent(seek_slider.get_value() / 10.0);
296 seek_slider.set_sensitive (false);
297 return false; // pass on to slider
301 SoundFileBox::setup_labels (const string& filename)
304 // save existing tags
312 if (SMFSource::valid_midi_file (path)) {
314 boost::shared_ptr<SMFSource> ms;
316 ms = boost::dynamic_pointer_cast<SMFSource> (
317 SourceFactory::createExternal (DataType::MIDI, *_session,
318 path, 0, Source::Flag (0), false));
319 } catch (const std::exception& e) {
320 error << string_compose(_("Could not read file: %1 (%2)."),
321 path, e.what()) << endmsg;
324 preview_label.set_markup (_("<b>Midi File Information</b>"));
326 format_text.set_text ("MIDI");
327 samplerate_value.set_text ("-");
328 tags_entry.get_buffer()->set_text ("");
329 timecode_clock.set (0);
330 tags_entry.set_sensitive (false);
333 if (ms->is_type0()) {
334 channels_value.set_text (to_string<uint32_t>(ms->channels().size()));
336 if (ms->num_tracks() > 1) {
337 channels_value.set_text (to_string(ms->num_tracks()) + _("(Tracks)"));
339 channels_value.set_text (to_string(ms->num_tracks()));
342 length_clock.set (ms->length(ms->timeline_position()));
343 switch (ms->num_tempos()) {
345 tempomap_value.set_text (_("No tempo data"));
348 Evoral::SMF::Tempo* t = ms->nth_tempo (0);
350 tempomap_value.set_text (string_compose (_("%1/%2 \u2669 = %3"),
357 tempomap_value.set_text (string_compose (_("map with %1 sections"),
362 channels_value.set_text ("");
363 length_clock.set (0);
364 tempomap_value.set_text (_("No tempo data"));
367 if (_session && ms) {
368 play_btn.set_sensitive (true);
370 play_btn.set_sensitive (false);
376 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
378 preview_label.set_markup (_("<b>Sound File Information</b>"));
379 format_text.set_text ("");
380 channels_value.set_text ("");
381 samplerate_value.set_text ("");
382 tags_entry.get_buffer()->set_text ("");
384 length_clock.set (0);
385 timecode_clock.set (0);
387 tags_entry.set_sensitive (false);
388 play_btn.set_sensitive (false);
393 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::Markup::escape_text (Glib::path_get_basename (filename))));
394 std::string n = sf_info.format_name;
395 if (n.substr (0, 8) == X_("Format: ")) {
398 format_text.set_text (n);
399 channels_value.set_text (to_string (sf_info.channels));
401 if (_session && sf_info.samplerate != _session->frame_rate()) {
402 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
403 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
404 samplerate_value.set_name ("NewSessionSR1Label");
405 samplerate.set_name ("NewSessionSR1Label");
407 samplerate.set_text (_("Sample rate:"));
408 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
409 samplerate_value.set_name ("NewSessionSR2Label");
410 samplerate.set_name ("NewSessionSR2Label");
413 framecnt_t const nfr = _session ? _session->nominal_frame_rate() : 25;
414 double src_coef = (double) nfr / sf_info.samplerate;
416 length_clock.set (sf_info.length * src_coef + 0.5, true);
417 timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
419 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
421 vector<string> tags = Library->get_tags (string ("//") + filename);
423 stringstream tag_string;
424 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
425 if (i != tags.begin()) {
430 tags_entry.get_buffer()->set_text (tag_string.str());
432 tags_entry.set_sensitive (true);
434 play_btn.set_sensitive (true);
441 SoundFileBox::update_autoplay ()
443 const bool config_autoplay = UIConfiguration::instance().get_autoplay_files();
445 if (autoplay_btn.get_active() != config_autoplay) {
446 autoplay_btn.set_active (config_autoplay);
451 SoundFileBox::autoplay_toggled()
453 UIConfiguration::instance().set_autoplay_files(autoplay_btn.get_active());
457 SoundFileBox::autoplay() const
459 return autoplay_btn.get_active();
463 SoundFileBox::audition_oneshot()
470 SoundFileBox::audition ()
476 _session->cancel_audition();
478 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
479 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
483 boost::shared_ptr<Region> r;
485 if (SMFSource::valid_midi_file (path)) {
487 boost::shared_ptr<SMFSource> ms =
488 boost::dynamic_pointer_cast<SMFSource> (
489 SourceFactory::createExternal (DataType::MIDI, *_session,
490 path, 0, Source::Flag (0), false));
492 string rname = region_name_from_path (ms->path(), false);
496 plist.add (ARDOUR::Properties::start, 0);
497 plist.add (ARDOUR::Properties::length, ms->length(ms->timeline_position()));
498 plist.add (ARDOUR::Properties::name, rname);
499 plist.add (ARDOUR::Properties::layer, 0);
501 r = boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (boost::dynamic_pointer_cast<Source>(ms), plist, false));
507 boost::shared_ptr<AudioFileSource> afs;
508 bool old_sbp = AudioSource::get_build_peakfiles ();
510 /* don't even think of building peakfiles for these files */
512 AudioSource::set_build_peakfiles (false);
514 for (int n = 0; n < sf_info.channels; ++n) {
516 afs = boost::dynamic_pointer_cast<AudioFileSource> (
517 SourceFactory::createExternal (DataType::AUDIO, *_session,
519 Source::Flag (ARDOUR::AudioFileSource::NoPeakFile), false));
520 if (afs->sample_rate() != _session->nominal_frame_rate()) {
521 boost::shared_ptr<SrcFileSource> sfs (new SrcFileSource(*_session, afs, _src_quality));
522 srclist.push_back(sfs);
524 srclist.push_back(afs);
527 } catch (failed_constructor& err) {
528 error << _("Could not access soundfile: ") << path << endmsg;
529 AudioSource::set_build_peakfiles (old_sbp);
534 AudioSource::set_build_peakfiles (old_sbp);
536 if (srclist.empty()) {
540 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
541 string rname = region_name_from_path (afs->path(), false);
545 plist.add (ARDOUR::Properties::start, 0);
546 plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->timeline_position()));
547 plist.add (ARDOUR::Properties::name, rname);
548 plist.add (ARDOUR::Properties::layer, 0);
550 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false));
553 frameoffset_t audition_position = 0;
554 switch(_import_position) {
555 case ImportAtTimestamp:
556 audition_position = 0;
558 case ImportAtPlayhead:
559 audition_position = _session->transport_frame();
562 audition_position = _session->current_start_frame();
564 case ImportAtEditPoint:
565 audition_position = PublicEditor::instance().get_preferred_edit_position ();
568 r->set_position(audition_position);
570 _session->audition_region(r);
574 SoundFileBox::stop_audition ()
577 _session->cancel_audition();
582 SoundFileBox::tags_entry_left (GdkEventFocus *)
589 SoundFileBox::tags_changed ()
591 string tag_string = tags_entry.get_buffer()->get_text ();
593 if (tag_string.empty()) {
599 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
600 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
608 SoundFileBox::save_tags (const vector<string>& tags)
610 Library->set_tags (string ("//") + path, tags);
611 Library->save_changes ();
614 SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persistent)
615 : ArdourWindow (title)
616 , found_list (ListStore::create(found_list_columns))
617 , freesound_list (ListStore::create(freesound_list_columns))
618 , chooser (FILE_CHOOSER_ACTION_OPEN)
619 , preview (persistent)
620 , found_search_btn (_("Search"))
621 , found_list_view (found_list)
622 , freesound_search_btn (_("Search"))
623 , freesound_list_view (freesound_list)
624 , resetting_ourselves (false)
628 , import_button (_("Import"))
634 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
635 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
636 chooser.add_shortcut_folder_uri("file:///Library/Audio/Apple Loops");
637 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
639 catch (Glib::Error & e) {
640 std::cerr << "sfdb.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
643 Gtkmm2ext::add_volume_shortcuts (chooser);
645 //add the file chooser
647 chooser.set_border_width (12);
649 audio_and_midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun (*this, &SoundFileBrowser::on_audio_and_midi_filter));
650 audio_and_midi_filter.set_name (_("Audio and MIDI files"));
652 audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
653 audio_filter.set_name (_("Audio files"));
655 midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
656 midi_filter.set_name (_("MIDI files"));
658 matchall_filter.add_pattern ("*.*");
659 matchall_filter.set_name (_("All files"));
661 chooser.add_filter (audio_and_midi_filter);
662 chooser.add_filter (audio_filter);
663 chooser.add_filter (midi_filter);
664 chooser.add_filter (matchall_filter);
665 chooser.set_select_multiple (true);
666 chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
667 chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
670 /* some broken redraw behaviour - this is a bandaid */
671 chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
674 if (!persistent_folder.empty()) {
675 chooser.set_current_folder (persistent_folder);
678 notebook.append_page (chooser, _("Browse Files"));
680 hpacker.set_spacing (6);
681 hpacker.pack_start (notebook, true, true);
682 hpacker.pack_start (preview, false, false);
684 vpacker.set_spacing (6);
685 vpacker.pack_start (hpacker, true, true);
695 hbox = manage(new HBox);
696 hbox->pack_start (found_entry);
697 hbox->pack_start (found_search_btn);
699 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
700 scroll->add(found_list_view);
701 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
703 vbox = manage(new VBox);
704 vbox->pack_start (*hbox, PACK_SHRINK);
705 vbox->pack_start (*scroll);
707 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
709 found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
711 found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
713 found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
714 found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
716 notebook.append_page (*vbox, _("Search Tags"));
718 //add freesound search
719 #ifdef FREESOUND_GOT_FIXED
724 passbox = manage(new HBox);
725 passbox->set_spacing (6);
727 label = manage (new Label);
728 label->set_text (_("Tags:"));
729 passbox->pack_start (*label, false, false);
730 passbox->pack_start (freesound_entry, true, true);
732 label = manage (new Label);
733 label->set_text (_("Sort:"));
734 passbox->pack_start (*label, false, false);
735 passbox->pack_start (freesound_sort, false, false);
736 freesound_sort.clear_items();
738 // Order of the following must correspond with enum sortMethod
739 // in sfdb_freesound_mootcher.h
740 freesound_sort.append_text(_("None"));
741 freesound_sort.append_text(_("Longest"));
742 freesound_sort.append_text(_("Shortest"));
743 freesound_sort.append_text(_("Newest"));
744 freesound_sort.append_text(_("Oldest"));
745 freesound_sort.append_text(_("Most downloaded"));
746 freesound_sort.append_text(_("Least downloaded"));
747 freesound_sort.append_text(_("Highest rated"));
748 freesound_sort.append_text(_("Lowest rated"));
749 freesound_sort.set_active(0);
751 passbox->pack_start (freesound_search_btn, false, false);
752 passbox->pack_start (freesound_more_btn, false, false);
753 freesound_more_btn.set_label(_("More"));
754 freesound_more_btn.set_sensitive(false);
756 passbox->pack_start (freesound_similar_btn, false, false);
757 freesound_similar_btn.set_label(_("Similar"));
758 freesound_similar_btn.set_sensitive(false);
760 scroll = manage(new ScrolledWindow);
761 scroll->add(freesound_list_view);
762 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
764 vbox = manage(new VBox);
765 vbox->set_spacing (3);
766 vbox->pack_start (*passbox, PACK_SHRINK);
767 vbox->pack_start (*scroll);
769 freesound_list_view.append_column(_("ID") , freesound_list_columns.id);
770 freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
771 // freesound_list_view.append_column(_("URI") , freesound_list_columns.uri);
772 freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
773 freesound_list_view.append_column(_("Size"), freesound_list_columns.filesize);
774 freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
775 freesound_list_view.append_column(_("License"), freesound_list_columns.license);
776 freesound_list_view.get_column(0)->set_alignment(0.5);
777 freesound_list_view.get_column(1)->set_expand(true); // filename
778 freesound_list_view.get_column(1)->set_resizable(true); // filename
779 freesound_list_view.get_column(2)->set_alignment(0.5);
780 freesound_list_view.get_column(3)->set_alignment(0.5);
781 freesound_list_view.get_column(4)->set_alignment(0.5);
782 freesound_list_view.get_column(5)->set_alignment(0.5);
784 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
785 freesound_list_view.set_tooltip_column(1);
787 freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
788 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
789 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
790 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
791 freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
792 freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
793 notebook.append_page (*vbox, _("Search Freesound"));
796 notebook.set_size_request (500, -1);
797 notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
801 Gtk::HButtonBox* button_box = manage (new HButtonBox);
803 button_box->set_layout (BUTTONBOX_END);
805 button_box->pack_start (import_button, false, false);
806 import_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_OK));
808 Gtkmm2ext::UI::instance()->set_tip (import_button, _("Press to import selected files"));
810 vpacker.pack_end (*button_box, false, false);
812 set_wmclass (X_("import"), PROGRAM_NAME);
815 SoundFileBrowser::~SoundFileBrowser ()
817 persistent_folder = chooser.get_current_folder();
821 SoundFileBrowser::run ()
830 gtk_main_iteration ();
837 SoundFileBrowser::set_action_sensitive (bool yn)
839 import_button.set_sensitive (yn);
843 SoundFileBrowser::get_action_sensitive () const
845 return import_button.get_sensitive ();
849 SoundFileBrowser::do_something (int action)
856 SoundFileBrowser::on_show ()
858 ArdourWindow::on_show ();
863 SoundFileBrowser::on_key_press_event (GdkEventKey* ev)
865 if (ev->keyval == GDK_Escape) {
866 do_something (RESPONSE_CLOSE);
869 if (ev->keyval == GDK_space && ev->type == GDK_KEY_PRESS) {
870 if (get_action_sensitive()) {
875 return ArdourWindow::on_key_press_event (ev);
879 SoundFileBrowser::clear_selection ()
881 chooser.unselect_all ();
882 found_list_view.get_selection()->unselect_all ();
886 SoundFileBrowser::chooser_file_activated ()
888 do_something (RESPONSE_OK);
892 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
898 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
904 SoundFileBrowser::set_session (Session* s)
906 ArdourWindow::set_session (s);
907 preview.set_session (s);
912 remove_gain_meter ();
917 SoundFileBrowser::add_gain_meter ()
921 gm = new GainMeter (_session, 250);
923 boost::shared_ptr<Route> r = _session->the_auditioner ();
925 gm->set_controls (r, r->shared_peak_meter(), r->amp(), r->gain_control());
926 gm->set_fader_name (X_("GainFader"));
928 meter_packer.set_border_width (12);
929 meter_packer.pack_start (*gm, false, true);
930 hpacker.pack_end (meter_packer, false, false);
931 meter_packer.show_all ();
936 SoundFileBrowser::remove_gain_meter ()
939 meter_packer.remove (*gm);
940 hpacker.remove (meter_packer);
947 SoundFileBrowser::start_metering ()
949 metering_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
953 SoundFileBrowser::stop_metering ()
955 metering_connection.disconnect();
959 SoundFileBrowser::meter ()
961 if (is_mapped () && _session && gm) {
962 gm->update_meters ();
967 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
969 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
973 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
975 return SMFSource::safe_midi_file_extension (filter_info.filename);
979 SoundFileBrowser::on_audio_and_midi_filter (const FileFilter::Info& filter_info)
981 return on_audio_filter (filter_info) || on_midi_filter (filter_info);
985 SoundFileBrowser::update_preview ()
987 if (preview.setup_labels (chooser.get_preview_filename())) {
988 if (preview.autoplay()) {
989 Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
995 SoundFileBrowser::found_list_view_selected ()
997 if (!reset_options ()) {
998 set_action_sensitive (false);
1002 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1004 if (!rows.empty()) {
1005 TreeIter iter = found_list->get_iter(*rows.begin());
1006 file = (*iter)[found_list_columns.pathname];
1007 chooser.set_filename (file);
1008 set_action_sensitive (true);
1010 set_action_sensitive (false);
1013 preview.setup_labels (file);
1018 SoundFileBrowser::found_search_clicked ()
1020 string tag_string = found_entry.get_text ();
1022 vector<string> tags;
1024 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
1025 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
1029 vector<string> results;
1030 Library->search_members_and (results, tags);
1032 found_list->clear();
1033 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
1034 TreeModel::iterator new_row = found_list->append();
1035 TreeModel::Row row = *new_row;
1036 string path = Glib::filename_from_uri (string ("file:") + *i);
1037 row[found_list_columns.pathname] = path;
1043 SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
1046 Mootcher *mootcher = new Mootcher;
1049 string id = (*iter)[freesound_list_columns.id];
1050 string uri = (*iter)[freesound_list_columns.uri];
1051 string ofn = (*iter)[freesound_list_columns.filename];
1053 if (mootcher->checkAudioFile(ofn, id)) {
1054 // file already exists, no need to download it again
1055 file = mootcher->audioFileName;
1057 (*iter)[freesound_list_columns.started] = false;
1060 if (!(*iter)[freesound_list_columns.started]) {
1061 // start downloading the sound file
1062 (*iter)[freesound_list_columns.started] = true;
1063 mootcher->fetchAudioFile(ofn, id, uri, this);
1069 SoundFileBrowser::freesound_list_view_selected ()
1072 if (!reset_options ()) {
1073 set_action_sensitive (false);
1076 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1077 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1078 file = freesound_get_audio_file (freesound_list->get_iter(*i));
1081 switch (rows.size()) {
1084 freesound_similar_btn.set_sensitive(false);
1085 set_action_sensitive (false);
1088 // exactly one item selected
1090 // file exists on disk already
1091 chooser.set_filename (file);
1092 preview.setup_labels (file);
1093 set_action_sensitive (true);
1095 freesound_similar_btn.set_sensitive(true);
1098 // multiple items selected
1099 preview.setup_labels ("");
1100 freesound_similar_btn.set_sensitive(false);
1108 SoundFileBrowser::refresh_display(std::string ID, std::string file)
1110 // called when the mootcher has finished downloading a file
1111 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1112 if (rows.size() == 1) {
1113 // there's a single item selected in the freesound list
1114 //XXX make a function to be used to construct the actual file name both here and in the mootcher
1115 Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
1116 std::string selected_ID = (*row)[freesound_list_columns.id];
1117 if (ID == selected_ID) {
1118 // the selected item in the freesound list is the item that has just finished downloading
1119 chooser.set_filename(file);
1120 preview.setup_labels (file);
1121 set_action_sensitive (true);
1127 SoundFileBrowser::freesound_search_clicked ()
1130 freesound_list->clear();
1136 SoundFileBrowser::freesound_more_clicked ()
1141 snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
1142 freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
1146 SoundFileBrowser::freesound_similar_clicked ()
1148 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1149 if (rows.size() == 1) {
1152 Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
1153 id = (*iter)[freesound_list_columns.id];
1154 freesound_list->clear();
1156 GdkCursor *prev_cursor;
1157 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1158 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1161 std::string theString = mootcher.searchSimilar(id);
1163 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1164 handle_freesound_results(theString);
1169 SoundFileBrowser::freesound_search()
1173 string search_string = freesound_entry.get_text ();
1174 enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
1176 GdkCursor *prev_cursor;
1177 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1178 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1181 std::string theString = mootcher.searchText(
1185 "", // OSX eats anything incl mp3
1187 "type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
1192 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1193 handle_freesound_results(theString);
1197 SoundFileBrowser::handle_freesound_results(std::string theString) {
1199 doc.read_buffer( theString );
1200 XMLNode *root = doc.root();
1203 error << "no root XML node!" << endmsg;
1207 if ( strcmp(root->name().c_str(), "response") != 0) {
1208 error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
1212 // find out how many pages are available to search
1213 int freesound_n_pages = 1;
1214 XMLNode *res = root->child("num_pages");
1216 string result = res->child("text")->content();
1217 freesound_n_pages = atoi(result);
1220 int more_pages = freesound_n_pages - freesound_page;
1222 if (more_pages > 0) {
1223 freesound_more_btn.set_sensitive(true);
1224 freesound_more_btn.set_tooltip_text(string_compose(P_(
1225 "%1 more page of 100 results available",
1226 "%1 more pages of 100 results available",
1227 more_pages), more_pages));
1229 freesound_more_btn.set_sensitive(false);
1230 freesound_more_btn.set_tooltip_text(_("No more results available"));
1233 XMLNode *sounds_root = root->child("sounds");
1235 error << "no child node \"sounds\" found!" << endmsg;
1239 XMLNodeList sounds = sounds_root->children();
1240 if (sounds.size() == 0) {
1245 XMLNodeConstIterator niter;
1247 for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
1249 if( strcmp( node->name().c_str(), "resource") != 0 ) {
1250 error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
1254 // node->dump(cerr, "node:");
1257 XMLNode *id_node = node->child ("id");
1258 XMLNode *uri_node = node->child ("serve");
1259 XMLNode *ofn_node = node->child ("original_filename");
1260 XMLNode *dur_node = node->child ("duration");
1261 XMLNode *siz_node = node->child ("filesize");
1262 XMLNode *srt_node = node->child ("samplerate");
1263 XMLNode *lic_node = node->child ("license");
1265 if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
1267 std::string id = id_node->child("text")->content();
1268 std::string uri = uri_node->child("text")->content();
1269 std::string ofn = ofn_node->child("text")->content();
1270 std::string dur = dur_node->child("text")->content();
1271 std::string siz = siz_node->child("text")->content();
1272 std::string srt = srt_node->child("text")->content();
1273 std::string lic = lic_node->child("text")->content();
1276 // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
1278 double duration_seconds = atof(dur);
1280 char duration_hhmmss[16];
1281 if (duration_seconds >= 99 * 60 * 60) {
1282 strcpy(duration_hhmmss, ">99h");
1284 s = modf(duration_seconds/60, &m) * 60;
1285 m = modf(m/60, &h) * 60;
1286 sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
1291 double size_bytes = atof(siz);
1293 if (size_bytes < 1000) {
1294 sprintf(bsize, "%.0f %s", size_bytes, _("B"));
1295 } else if (size_bytes < 1000000 ) {
1296 sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
1297 } else if (size_bytes < 10000000) {
1298 sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
1299 } else if (size_bytes < 1000000000) {
1300 sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
1302 sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
1305 /* see http://www.freesound.org/help/faq/#licenses */
1306 char shortlicense[64];
1307 if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
1308 sprintf(shortlicense, "CC-BY-NC");
1309 } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
1310 sprintf(shortlicense, "CC-BY");
1311 } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
1312 sprintf(shortlicense, "sampling+");
1313 } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
1314 sprintf(shortlicense, "PD");
1316 snprintf(shortlicense, 64, "%s", lic.c_str());
1317 shortlicense[63]= '\0';
1320 TreeModel::iterator new_row = freesound_list->append();
1321 TreeModel::Row row = *new_row;
1323 row[freesound_list_columns.id ] = id;
1324 row[freesound_list_columns.uri ] = uri;
1325 row[freesound_list_columns.filename] = ofn;
1326 row[freesound_list_columns.duration] = duration_hhmmss;
1327 row[freesound_list_columns.filesize] = bsize;
1328 row[freesound_list_columns.smplrate] = srt;
1329 row[freesound_list_columns.license ] = shortlicense;
1336 SoundFileBrowser::get_paths ()
1338 vector<string> results;
1340 int n = notebook.get_current_page ();
1343 vector<string> filenames = chooser.get_filenames();
1344 vector<string>::iterator i;
1346 for (i = filenames.begin(); i != filenames.end(); ++i) {
1348 if ((!g_stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
1349 results.push_back (*i);
1353 } else if (n == 1) {
1355 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1356 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1357 TreeIter iter = found_list->get_iter(*i);
1358 string str = (*iter)[found_list_columns.pathname];
1360 results.push_back (str);
1363 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1364 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1365 string str = freesound_get_audio_file (freesound_list->get_iter(*i));
1367 results.push_back (str);
1376 SoundFileOmega::reset_options_noret ()
1378 if (!resetting_ourselves) {
1379 (void) reset_options ();
1384 SoundFileOmega::reset_options ()
1386 if (_import_active) {
1387 _reset_post_import = true;
1391 vector<string> paths = get_paths ();
1393 if (paths.empty()) {
1395 channel_combo.set_sensitive (false);
1396 action_combo.set_sensitive (false);
1397 where_combo.set_sensitive (false);
1398 copy_files_btn.set_active (true);
1399 copy_files_btn.set_sensitive (false);
1405 channel_combo.set_sensitive (true);
1406 action_combo.set_sensitive (true);
1407 where_combo.set_sensitive (true);
1409 /* if we get through this function successfully, this may be
1410 reset at the end, once we know if we can use hard links
1411 to do embedding (or if we are importing a MIDI file).
1414 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1415 copy_files_btn.set_sensitive (false);
1417 copy_files_btn.set_sensitive (false);
1423 bool selection_includes_multichannel;
1424 bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1427 /* See if we are thinking about importing any MIDI files */
1428 vector<string>::iterator i = paths.begin ();
1429 while (i != paths.end() && SMFSource::valid_midi_file (*i) == false) {
1432 bool const have_a_midi_file = (i != paths.end ());
1434 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1435 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1439 if (have_a_midi_file) {
1440 smf_tempo_btn.show ();
1442 smf_tempo_btn.hide ();
1445 string existing_choice;
1446 vector<string> action_strings;
1448 resetting_ourselves = true;
1450 if (chooser.get_filter() == &audio_filter) {
1454 if (selected_audio_track_cnt > 0) {
1455 if (channel_combo.get_active_text().length()) {
1456 ImportDisposition id = get_channel_disposition();
1459 case Editing::ImportDistinctFiles:
1460 if (selected_audio_track_cnt == paths.size()) {
1461 action_strings.push_back (importmode2string (ImportToTrack));
1465 case Editing::ImportDistinctChannels:
1466 /* XXX it would be nice to allow channel-per-selected track
1467 but its too hard we don't want to deal with all the
1468 different per-file + per-track channel configurations.
1473 action_strings.push_back (importmode2string (ImportToTrack));
1483 if (selected_midi_track_cnt > 0) {
1484 action_strings.push_back (importmode2string (ImportToTrack));
1488 action_strings.push_back (importmode2string (ImportAsTrack));
1489 action_strings.push_back (importmode2string (ImportAsRegion));
1490 if (!Profile->get_mixbus()) {
1491 action_strings.push_back (importmode2string (ImportAsTapeTrack));
1494 existing_choice = action_combo.get_active_text();
1496 set_popdown_strings (action_combo, action_strings);
1498 /* preserve any existing choice, if possible */
1501 if (existing_choice.length()) {
1502 vector<string>::iterator x;
1503 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1504 if (*x == existing_choice) {
1505 action_combo.set_active_text (existing_choice);
1509 if (x == action_strings.end()) {
1510 action_combo.set_active_text (action_strings.front());
1513 action_combo.set_active_text (action_strings.front());
1516 resetting_ourselves = false;
1518 if ((mode = get_mode()) == ImportAsRegion) {
1519 where_combo.set_sensitive (false);
1521 where_combo.set_sensitive (true);
1524 vector<string> channel_strings;
1526 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1528 if (selection_includes_multichannel) {
1529 channel_strings.push_back (_("one track per channel"));
1532 channel_strings.push_back (_("one track per file"));
1534 if (paths.size() > 1) {
1535 /* tape tracks are a single region per track, so we cannot
1536 sequence multiple files.
1538 if (mode != ImportAsTapeTrack) {
1539 channel_strings.push_back (_("sequence files"));
1542 channel_strings.push_back (_("all files in one track"));
1543 channel_strings.push_back (_("merge files"));
1549 channel_strings.push_back (_("one region per file"));
1551 if (selection_includes_multichannel) {
1552 channel_strings.push_back (_("one region per channel"));
1555 if (paths.size() > 1) {
1557 channel_strings.push_back (_("all files in one region"));
1562 resetting_ourselves = true;
1564 existing_choice = channel_combo.get_active_text();
1566 set_popdown_strings (channel_combo, channel_strings);
1568 /* preserve any existing choice, if possible */
1570 if (existing_choice.length()) {
1571 vector<string>::iterator x;
1572 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1573 if (*x == existing_choice) {
1574 channel_combo.set_active_text (existing_choice);
1578 if (x == channel_strings.end()) {
1579 channel_combo.set_active_text (channel_strings.front());
1582 channel_combo.set_active_text (channel_strings.front());
1585 resetting_ourselves = false;
1588 src_combo.set_sensitive (true);
1590 src_combo.set_sensitive (false);
1593 /* We must copy MIDI files or those from Freesound
1594 * or any file if we are under nsm control */
1595 bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
1597 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1599 if (selection_can_be_embedded_with_links && !must_copy) {
1600 copy_files_btn.set_sensitive (true);
1603 copy_files_btn.set_active (true);
1605 copy_files_btn.set_sensitive (false);
1611 copy_files_btn.set_active (true);
1613 copy_files_btn.set_sensitive (!must_copy);
1621 SoundFileOmega::bad_file_message()
1623 MessageDialog msg (*this,
1624 string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1629 resetting_ourselves = true;
1630 chooser.unselect_uri (chooser.get_preview_uri());
1631 resetting_ourselves = false;
1637 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1646 multichannel = false;
1648 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1650 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1651 if (info.channels > 1) {
1652 multichannel = true;
1657 if (sz != info.length) {
1662 if (info.samplerate != _session->frame_rate()) {
1666 } else if (SMFSource::valid_midi_file (*i)) {
1670 if (reader.open (*i)) {
1673 if (reader.is_type0 ()) {
1674 if (reader.channels().size() > 1) {
1675 /* for type-0 files, we can split
1676 * "one track per channel"
1678 multichannel = true;
1681 if (reader.num_tracks() > 1) {
1682 multichannel = true;
1697 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1699 #ifdef PLATFORM_WINDOWS
1702 std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
1705 if (g_mkdir (tmpdir.c_str(), 0744)) {
1706 if (errno != EEXIST) {
1711 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1713 char tmpc[PATH_MAX+1];
1715 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1719 if (link ((*i).c_str(), tmpc)) {
1729 g_rmdir (tmpdir.c_str());
1734 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
1735 : SoundFileBrowser (title, s, false)
1737 chooser.set_select_multiple (false);
1738 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1739 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1743 SoundFileChooser::on_hide ()
1745 ArdourWindow::on_hide();
1749 _session->cancel_audition();
1754 SoundFileChooser::get_filename ()
1756 vector<string> paths;
1758 paths = get_paths ();
1760 if (paths.empty()) {
1764 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1768 return paths.front();
1771 SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s,
1772 uint32_t selected_audio_tracks,
1773 uint32_t selected_midi_tracks,
1775 Editing::ImportMode mode_hint)
1776 : SoundFileBrowser (title, s, persistent)
1777 , copy_files_btn ( _("Copy files to session"))
1778 , smf_tempo_btn (_("Use MIDI Tempo Map (if defined)"))
1779 , selected_audio_track_cnt (selected_audio_tracks)
1780 , selected_midi_track_cnt (selected_midi_tracks)
1781 , _import_active (false)
1782 , _reset_post_import (false)
1786 set_size_request (-1, 550);
1788 block_two.set_border_width (12);
1789 block_three.set_border_width (12);
1790 block_four.set_border_width (12);
1793 str.push_back (_("file timestamp"));
1794 str.push_back (_("edit point"));
1795 str.push_back (_("playhead"));
1796 str.push_back (_("session start"));
1797 set_popdown_strings (where_combo, str);
1798 where_combo.set_active_text (str.back());
1799 where_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::where_combo_changed));
1801 Label* l = manage (new Label);
1802 l->set_markup (_("<b>Add files ...</b>"));
1803 options.attach (*l, 0, 1, 0, 1, FILL, SHRINK, 8, 0);
1804 options.attach (action_combo, 0, 1, 1, 2, FILL, SHRINK, 8, 0);
1806 l = manage (new Label);
1807 l->set_markup (_("<b>Insert at</b>"));
1808 options.attach (*l, 0, 1, 3, 4, FILL, SHRINK, 8, 0);
1809 options.attach (where_combo, 0, 1, 4, 5, FILL, SHRINK, 8, 0);
1811 l = manage (new Label);
1812 l->set_markup (_("<b>Mapping</b>"));
1813 options.attach (*l, 1, 2, 0, 1, FILL, SHRINK, 8, 0);
1814 options.attach (channel_combo, 1, 2, 1, 2, FILL, SHRINK, 8, 0);
1816 l = manage (new Label);
1817 l->set_markup (_("<b>Conversion quality</b>"));
1818 options.attach (*l, 1, 2, 3, 4, FILL, SHRINK, 8, 0);
1819 options.attach (src_combo, 1, 2, 4, 5, FILL, SHRINK, 8, 0);
1821 l = manage (new Label);
1822 l->set_markup (_("<b>MIDI Track Names</b>"));
1823 options.attach (*l, 2, 3, 0, 1, FILL, SHRINK, 8, 0);
1824 options.attach (midi_track_name_combo, 2, 3, 1, 2, FILL, SHRINK, 8, 0);
1826 options.attach (smf_tempo_btn, 2, 3, 3, 4, FILL, SHRINK, 8, 0);
1828 l = manage (new Label);
1829 l->set_markup (_("<b>Instrument</b>"));
1830 options.attach (*l, 3, 4, 0, 1, FILL, SHRINK, 8, 0);
1831 options.attach (instrument_combo, 3, 4, 1, 2, FILL, SHRINK, 8, 0);
1833 Alignment *hspace = manage (new Alignment ());
1834 hspace->set_size_request (2, 2);
1835 options.attach (*hspace, 0, 3, 2, 3, FILL, SHRINK, 0, 8);
1837 Alignment *vspace = manage (new Alignment ());
1838 vspace->set_size_request (2, 2);
1839 options.attach (*vspace, 2, 3, 0, 3, EXPAND, SHRINK, 0, 0);
1842 str.push_back (_("by track number"));
1843 str.push_back (_("by track name"));
1844 str.push_back (_("by instrument name"));
1845 set_popdown_strings (midi_track_name_combo, str);
1846 midi_track_name_combo.set_active_text (str.front());
1849 str.push_back (_("one track per file"));
1850 set_popdown_strings (channel_combo, str);
1851 channel_combo.set_active_text (str.front());
1852 channel_combo.set_sensitive (false);
1855 str.push_back (_("Best"));
1856 str.push_back (_("Good"));
1857 str.push_back (_("Quick"));
1858 str.push_back (_("Fast"));
1859 str.push_back (_("Fastest"));
1861 set_popdown_strings (src_combo, str);
1862 src_combo.set_active_text (str.front());
1863 src_combo.set_sensitive (false);
1864 src_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::src_combo_changed));
1866 action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1867 channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1869 copy_files_btn.set_active (true);
1871 Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1874 copy_label->set_size_request (175, -1);
1875 copy_label->set_line_wrap (true);
1878 block_four.pack_start (copy_files_btn, false, false);
1879 options.attach (block_four, 3, 4, 4, 5, FILL, SHRINK, 8, 0);
1881 vpacker.pack_start (options, false, true);
1883 /* setup disposition map */
1885 disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1886 disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1887 disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1888 disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1890 disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1891 disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1892 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1893 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1895 chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1897 /* set size requests for a couple of combos to allow them to display the longest text
1898 they will ever be asked to display. This prevents them being resized when the user
1899 selects a file to import, which in turn prevents the size of the dialog from jumping
1903 str.push_back (_("one track per file"));
1904 str.push_back (_("one track per channel"));
1905 str.push_back (_("sequence files"));
1906 str.push_back (_("all files in one region"));
1907 set_popdown_strings (channel_combo, str);
1910 str.push_back (importmode2string (ImportAsTrack));
1911 str.push_back (importmode2string (ImportToTrack));
1912 str.push_back (importmode2string (ImportAsRegion));
1913 str.push_back (importmode2string (ImportAsTapeTrack));
1914 set_popdown_strings (action_combo, str);
1915 action_combo.set_active_text (importmode2string(mode_hint));
1917 reset (selected_audio_tracks, selected_midi_tracks);
1921 SoundFileOmega::set_mode (ImportMode mode)
1923 action_combo.set_active_text (importmode2string (mode));
1927 SoundFileOmega::get_mode () const
1929 return string2importmode (action_combo.get_active_text());
1933 SoundFileOmega::on_hide ()
1935 ArdourWindow::on_hide();
1937 _session->cancel_audition();
1942 SoundFileOmega::get_position() const
1944 string str = where_combo.get_active_text();
1946 if (str == _("file timestamp")) {
1947 return ImportAtTimestamp;
1948 } else if (str == _("edit point")) {
1949 return ImportAtEditPoint;
1950 } else if (str == _("playhead")) {
1951 return ImportAtPlayhead;
1953 return ImportAtStart;
1958 SoundFileOmega::get_src_quality() const
1960 string str = src_combo.get_active_text();
1962 if (str == _("Best")) {
1964 } else if (str == _("Good")) {
1966 } else if (str == _("Quick")) {
1968 } else if (str == _("Fast")) {
1976 SoundFileOmega::src_combo_changed()
1978 preview.set_src_quality(get_src_quality());
1982 SoundFileOmega::where_combo_changed()
1984 preview.set_import_position(get_position());
1988 SoundFileOmega::get_midi_track_name_source () const
1990 return string2miditracknamesource (midi_track_name_combo.get_active_text());
1994 SoundFileOmega::get_use_smf_tempo_map () const
1996 return smf_tempo_btn.get_active ();
2000 SoundFileOmega::get_channel_disposition () const
2002 /* we use a map here because the channel combo can contain different strings
2003 depending on the state of the other combos. the map contains all possible strings
2004 and the ImportDisposition enum that corresponds to it.
2007 string str = channel_combo.get_active_text();
2008 DispositionMap::const_iterator x = disposition_map.find (str);
2010 if (x == disposition_map.end()) {
2011 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
2012 abort(); /*NOTREACHED*/
2019 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
2021 selected_audio_track_cnt = selected_audio_tracks;
2022 selected_midi_track_cnt = selected_midi_tracks;
2024 if (selected_audio_track_cnt == 0 && selected_midi_track_cnt > 0) {
2025 chooser.set_filter (midi_filter);
2026 } else if (selected_midi_track_cnt == 0 && selected_audio_track_cnt > 0) {
2027 chooser.set_filter (audio_filter);
2029 chooser.set_filter (audio_and_midi_filter);
2036 SoundFileOmega::file_selection_changed ()
2038 if (resetting_ourselves) {
2042 if (!reset_options ()) {
2043 set_action_sensitive (false);
2045 if (chooser.get_filenames().size() > 0) {
2046 set_action_sensitive (true);
2048 set_action_sensitive (false);
2054 SoundFileOmega::do_something (int action)
2056 SoundFileBrowser::do_something (action);
2058 if (action == RESPONSE_CLOSE) {
2065 vector<string> paths = get_paths ();
2066 ImportPosition pos = get_position ();
2067 ImportMode mode = get_mode ();
2068 ImportDisposition chns = get_channel_disposition ();
2069 PluginInfoPtr instrument = instrument_combo.selected_instrument();
2071 MidiTrackNameSource mts = get_midi_track_name_source ();
2072 MidiTempoMapDisposition mtd = (get_use_smf_tempo_map () ? SMFTempoUse : SMFTempoIgnore);
2075 case ImportAtEditPoint:
2076 where = PublicEditor::instance().get_preferred_edit_position ();
2078 case ImportAtTimestamp:
2081 case ImportAtPlayhead:
2082 where = _session->transport_frame();
2085 where = _session->current_start_frame();
2089 SrcQuality quality = get_src_quality();
2091 _import_active = true;
2093 if (copy_files_btn.get_active()) {
2094 PublicEditor::instance().do_import (paths, chns, mode, quality, mts, mtd, where, instrument);
2096 PublicEditor::instance().do_embed (paths, chns, mode, where, instrument);
2099 _import_active = false;
2101 if (_reset_post_import) {
2102 _reset_post_import = false;