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"
31 #include <gtkmm/box.h>
32 #include <gtkmm/scrolledwindow.h>
33 #include <gtkmm/stock.h>
35 #include "pbd/gstdio_compat.h"
36 #include <glibmm/fileutils.h>
38 #include "pbd/tokenizer.h"
39 #include "pbd/enumwriter.h"
40 #include "pbd/pthread_utils.h"
41 #include "pbd/string_convert.h"
42 #include "pbd/xml++.h"
44 #include <gtkmm2ext/utils.h>
46 #include "evoral/SMF.hpp"
48 #include "ardour/audio_library.h"
49 #include "ardour/auditioner.h"
50 #include "ardour/audioregion.h"
51 #include "ardour/audiofilesource.h"
52 #include "ardour/midi_region.h"
53 #include "ardour/smf_source.h"
54 #include "ardour/region_factory.h"
55 #include "ardour/source_factory.h"
56 #include "ardour/session.h"
57 #include "ardour/session_directory.h"
58 #include "ardour/srcfilesource.h"
59 #include "ardour/profile.h"
61 #include "ardour_ui.h"
63 #include "gui_thread.h"
66 #include "gain_meter.h"
67 #include "main_clock.h"
68 #include "public_editor.h"
70 #include "ui_config.h"
72 #include "sfdb_freesound_mootcher.h"
76 using namespace ARDOUR;
80 using namespace Gtkmm2ext;
81 using namespace Editing;
85 string SoundFileBrowser::persistent_folder;
86 typedef TreeView::Selection::ListHandle_Path ListPath;
88 static MidiTrackNameSource
89 string2miditracknamesource (string const & str)
91 if (str == _("by track number")) {
92 return SMFTrackNumber;
93 } else if (str == _("by track name")) {
95 } else if (str == _("by instrument name")) {
96 return SMFInstrumentName;
99 warning << string_compose (_("programming error: unknown midi track name source string %1"), str) << endmsg;
101 return SMFTrackNumber;
105 string2importmode (string const & str)
107 if (str == _("as new tracks")) {
108 return ImportAsTrack;
109 } else if (str == _("to selected tracks")) {
110 return ImportToTrack;
111 } else if (str == _("to region list")) {
112 return ImportAsRegion;
113 } else if (str == _("as new tape tracks")) {
114 return ImportAsTapeTrack;
117 warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
119 return ImportAsTrack;
123 importmode2string (ImportMode mode)
127 return _("as new tracks");
129 return _("to selected tracks");
131 return _("to region list");
132 case ImportAsTapeTrack:
133 return _("as new tape tracks");
135 abort(); /*NOTREACHED*/
136 return _("as new tracks");
139 SoundFileBox::SoundFileBox (bool /*persistent*/)
141 length_clock ("sfboxLengthClock", true, "", false, false, true, false),
142 timecode_clock ("sfboxTimecodeClock", true, "", false, false, false, false),
144 autoplay_btn (_("Auto-play")),
145 seek_slider(0,1000,1),
147 _src_quality (SrcBest),
148 _import_position (ImportAtTimestamp)
151 set_name (X_("SoundFileBox"));
152 set_size_request (300, -1);
154 preview_label.set_markup (_("<b>Sound File Information</b>"));
156 border_frame.set_label_widget (preview_label);
157 border_frame.add (main_box);
159 pack_start (border_frame, true, true);
160 set_border_width (6);
162 main_box.set_border_width (6);
164 length.set_text (_("Length:"));
165 length.set_alignment (1, 0.5);
166 timecode.set_text (_("Timestamp:"));
167 timecode.set_alignment (1, 0.5);
168 format.set_text (_("Format:"));
169 format.set_alignment (1, 0.5);
170 channels.set_text (_("Channels:"));
171 channels.set_alignment (1, 0.5);
172 samplerate.set_text (_("Sample rate:"));
173 samplerate.set_alignment (1, 0.5);
174 tempomap.set_text (_("Tempo Map:"));
175 tempomap.set_alignment (1, 0.5);
177 preview_label.set_max_width_chars (50);
178 preview_label.set_ellipsize (Pango::ELLIPSIZE_END);
180 format_text.set_max_width_chars (20);
181 format_text.set_ellipsize (Pango::ELLIPSIZE_END);
182 format_text.set_alignment (0, 1);
184 table.set_col_spacings (6);
185 table.set_homogeneous (false);
186 table.set_row_spacings (6);
188 table.attach (channels, 0, 1, 0, 1, FILL, FILL);
189 table.attach (samplerate, 0, 1, 1, 2, FILL, FILL);
190 table.attach (format, 0, 1, 2, 4, FILL, FILL);
191 table.attach (length, 0, 1, 4, 5, FILL, FILL);
192 table.attach (timecode, 0, 1, 5, 6, FILL, FILL);
193 table.attach (tempomap, 0, 1, 6, 7, FILL, FILL);
195 table.attach (channels_value, 1, 2, 0, 1, FILL, FILL);
196 table.attach (samplerate_value, 1, 2, 1, 2, FILL, FILL);
197 table.attach (format_text, 1, 2, 2, 4, FILL, FILL);
198 table.attach (length_clock, 1, 2, 4, 5, FILL, FILL);
199 table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL);
200 table.attach (tempomap_value, 1, 2, 6, 7, FILL, FILL);
202 length_clock.set_mode (ARDOUR_UI::instance()->primary_clock->mode());
203 timecode_clock.set_mode (AudioClock::Timecode);
205 main_box.pack_start (table, false, false);
207 tags_entry.set_editable (true);
208 tags_entry.set_wrap_mode(Gtk::WRAP_WORD);
209 tags_entry.signal_focus_out_event().connect (sigc::mem_fun (*this, &SoundFileBox::tags_entry_left));
211 Label* label = manage (new Label (_("Tags:")));
212 label->set_alignment (0.0f, 0.5f);
213 main_box.pack_start (*label, false, false);
214 main_box.pack_start (tags_entry, true, true);
216 main_box.pack_start (bottom_box, false, false);
218 play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
219 // play_btn.set_label (_("Play"));
221 stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
222 // stop_btn.set_label (_("Stop"));
224 bottom_box.set_homogeneous (false);
225 bottom_box.set_spacing (6);
226 bottom_box.pack_start(play_btn, true, true);
227 bottom_box.pack_start(stop_btn, true, true);
228 bottom_box.pack_start(autoplay_btn, false, false);
230 seek_slider.set_draw_value(false);
232 seek_slider.add_events(Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
233 seek_slider.signal_button_press_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_press), false);
234 seek_slider.signal_button_release_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_release), false);
235 main_box.pack_start (seek_slider, false, false);
237 play_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::audition));
238 stop_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::stop_audition));
241 autoplay_btn.signal_toggled().connect(sigc::mem_fun (*this, &SoundFileBox::autoplay_toggled));
243 stop_btn.set_sensitive (false);
245 channels_value.set_alignment (0.0f, 0.5f);
246 samplerate_value.set_alignment (0.0f, 0.5f);
250 SoundFileBox::set_session(Session* s)
252 SessionHandlePtr::set_session (s);
254 length_clock.set_session (s);
255 timecode_clock.set_session (s);
258 play_btn.set_sensitive (false);
259 stop_btn.set_sensitive (false);
260 auditioner_connections.drop_connections();
262 auditioner_connections.drop_connections();
263 _session->AuditionActive.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_active, this, _1), gui_context());
264 _session->the_auditioner()->AuditionProgress.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_progress, this, _1, _2), gui_context());
269 SoundFileBox::audition_active(bool active) {
270 stop_btn.set_sensitive (active);
271 seek_slider.set_sensitive (active);
273 seek_slider.set_value(0);
278 SoundFileBox::audition_progress(ARDOUR::samplecnt_t pos, ARDOUR::samplecnt_t len) {
280 seek_slider.set_value( 1000.0 * pos / len);
281 seek_slider.set_sensitive (true);
286 SoundFileBox::seek_button_press(GdkEventButton*) {
288 return false; // pass on to slider
292 SoundFileBox::seek_button_release(GdkEventButton*) {
294 _session->the_auditioner()->seek_to_percent(seek_slider.get_value() / 10.0);
295 seek_slider.set_sensitive (false);
296 return false; // pass on to slider
300 SoundFileBox::setup_labels (const string& filename)
303 // save existing tags
311 if (SMFSource::valid_midi_file (path)) {
313 boost::shared_ptr<SMFSource> ms;
315 ms = boost::dynamic_pointer_cast<SMFSource> (
316 SourceFactory::createExternal (DataType::MIDI, *_session,
317 path, 0, Source::Flag (0), false));
318 } catch (const std::exception& e) {
319 error << string_compose(_("Could not read file: %1 (%2)."),
320 path, e.what()) << endmsg;
323 preview_label.set_markup (_("<b>Midi File Information</b>"));
325 format_text.set_text ("MIDI");
326 samplerate_value.set_text ("-");
327 tags_entry.get_buffer()->set_text ("");
328 timecode_clock.set (0);
329 tags_entry.set_sensitive (false);
332 if (ms->is_type0()) {
333 channels_value.set_text (to_string<uint32_t>(ms->channels().size()));
335 if (ms->num_tracks() > 1) {
336 channels_value.set_text (to_string(ms->num_tracks()) + _("(Tracks)"));
338 channels_value.set_text (to_string(ms->num_tracks()));
341 length_clock.set (ms->length(ms->timeline_position()));
342 switch (ms->num_tempos()) {
344 tempomap_value.set_text (_("No tempo data"));
347 Evoral::SMF::Tempo* t = ms->nth_tempo (0);
349 tempomap_value.set_text (string_compose (_("%1/%2 \u2669 = %3"),
356 tempomap_value.set_text (string_compose (_("map with %1 sections"),
361 channels_value.set_text ("");
362 length_clock.set (0);
363 tempomap_value.set_text (_("No tempo data"));
366 if (_session && ms) {
367 play_btn.set_sensitive (true);
369 play_btn.set_sensitive (false);
375 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
377 preview_label.set_markup (_("<b>Sound File Information</b>"));
378 format_text.set_text ("");
379 channels_value.set_text ("");
380 samplerate_value.set_text ("");
381 tags_entry.get_buffer()->set_text ("");
383 length_clock.set (0);
384 timecode_clock.set (0);
386 tags_entry.set_sensitive (false);
387 play_btn.set_sensitive (false);
392 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::Markup::escape_text (Glib::path_get_basename (filename))));
393 std::string n = sf_info.format_name;
394 if (n.substr (0, 8) == X_("Format: ")) {
397 format_text.set_text (n);
398 channels_value.set_text (to_string (sf_info.channels));
400 if (_session && sf_info.samplerate != _session->sample_rate()) {
401 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
402 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
403 samplerate_value.set_name ("NewSessionSR1Label");
404 samplerate.set_name ("NewSessionSR1Label");
406 samplerate.set_text (_("Sample rate:"));
407 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
408 samplerate_value.set_name ("NewSessionSR2Label");
409 samplerate.set_name ("NewSessionSR2Label");
412 samplecnt_t const nfr = _session ? _session->nominal_sample_rate() : 25;
413 double src_coef = (double) nfr / sf_info.samplerate;
415 length_clock.set (sf_info.length * src_coef + 0.5, true);
416 timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
418 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
420 vector<string> tags = Library->get_tags (string ("//") + filename);
422 stringstream tag_string;
423 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
424 if (i != tags.begin()) {
429 tags_entry.get_buffer()->set_text (tag_string.str());
431 tags_entry.set_sensitive (true);
433 play_btn.set_sensitive (true);
440 SoundFileBox::update_autoplay ()
442 const bool config_autoplay = UIConfiguration::instance().get_autoplay_files();
444 if (autoplay_btn.get_active() != config_autoplay) {
445 autoplay_btn.set_active (config_autoplay);
450 SoundFileBox::autoplay_toggled()
452 UIConfiguration::instance().set_autoplay_files(autoplay_btn.get_active());
456 SoundFileBox::autoplay() const
458 return autoplay_btn.get_active();
462 SoundFileBox::audition_oneshot()
469 SoundFileBox::audition ()
475 _session->cancel_audition();
477 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
478 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
482 boost::shared_ptr<Region> r;
484 if (SMFSource::valid_midi_file (path)) {
486 boost::shared_ptr<SMFSource> ms =
487 boost::dynamic_pointer_cast<SMFSource> (
488 SourceFactory::createExternal (DataType::MIDI, *_session,
489 path, 0, Source::Flag (0), false));
491 string rname = region_name_from_path (ms->path(), false);
495 plist.add (ARDOUR::Properties::start, 0);
496 plist.add (ARDOUR::Properties::length, ms->length(ms->timeline_position()));
497 plist.add (ARDOUR::Properties::name, rname);
498 plist.add (ARDOUR::Properties::layer, 0);
500 r = boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (boost::dynamic_pointer_cast<Source>(ms), plist, false));
506 boost::shared_ptr<AudioFileSource> afs;
507 bool old_sbp = AudioSource::get_build_peakfiles ();
509 /* don't even think of building peakfiles for these files */
511 AudioSource::set_build_peakfiles (false);
513 for (int n = 0; n < sf_info.channels; ++n) {
515 afs = boost::dynamic_pointer_cast<AudioFileSource> (
516 SourceFactory::createExternal (DataType::AUDIO, *_session,
518 Source::Flag (ARDOUR::AudioFileSource::NoPeakFile), false));
519 if (afs->sample_rate() != _session->nominal_sample_rate()) {
520 boost::shared_ptr<SrcFileSource> sfs (new SrcFileSource(*_session, afs, _src_quality));
521 srclist.push_back(sfs);
523 srclist.push_back(afs);
526 } catch (failed_constructor& err) {
527 error << _("Could not access soundfile: ") << path << endmsg;
528 AudioSource::set_build_peakfiles (old_sbp);
533 AudioSource::set_build_peakfiles (old_sbp);
535 if (srclist.empty()) {
539 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
540 string rname = region_name_from_path (afs->path(), false);
544 plist.add (ARDOUR::Properties::start, 0);
545 plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->timeline_position()));
546 plist.add (ARDOUR::Properties::name, rname);
547 plist.add (ARDOUR::Properties::layer, 0);
549 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false));
552 sampleoffset_t audition_position = 0;
553 switch(_import_position) {
554 case ImportAtTimestamp:
555 audition_position = 0;
557 case ImportAtPlayhead:
558 audition_position = _session->transport_sample();
561 audition_position = _session->current_start_sample();
563 case ImportAtEditPoint:
564 audition_position = PublicEditor::instance().get_preferred_edit_position ();
567 r->set_position(audition_position);
569 _session->audition_region(r);
573 SoundFileBox::stop_audition ()
576 _session->cancel_audition();
581 SoundFileBox::tags_entry_left (GdkEventFocus *)
588 SoundFileBox::tags_changed ()
590 string tag_string = tags_entry.get_buffer()->get_text ();
592 if (tag_string.empty()) {
598 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
599 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
607 SoundFileBox::save_tags (const vector<string>& tags)
609 Library->set_tags (string ("//") + path, tags);
610 Library->save_changes ();
613 SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persistent)
614 : ArdourWindow (title)
615 , found_list (ListStore::create(found_list_columns))
616 , freesound_list (ListStore::create(freesound_list_columns))
617 , chooser (FILE_CHOOSER_ACTION_OPEN)
618 , preview (persistent)
619 , found_search_btn (_("Search"))
620 , found_list_view (found_list)
621 , freesound_search_btn (_("Search"))
622 , freesound_list_view (freesound_list)
623 , resetting_ourselves (false)
627 , import_button (_("Import"))
633 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
634 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
635 chooser.add_shortcut_folder_uri("file:///Library/Audio/Apple Loops");
636 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
638 catch (Glib::Error & e) {
639 std::cerr << "sfdb.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
642 Gtkmm2ext::add_volume_shortcuts (chooser);
644 //add the file chooser
646 chooser.set_border_width (12);
648 audio_and_midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun (*this, &SoundFileBrowser::on_audio_and_midi_filter));
649 audio_and_midi_filter.set_name (_("Audio and MIDI files"));
651 audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
652 audio_filter.set_name (_("Audio files"));
654 midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
655 midi_filter.set_name (_("MIDI files"));
657 matchall_filter.add_pattern ("*.*");
658 matchall_filter.set_name (_("All files"));
660 chooser.add_filter (audio_and_midi_filter);
661 chooser.add_filter (audio_filter);
662 chooser.add_filter (midi_filter);
663 chooser.add_filter (matchall_filter);
664 chooser.set_select_multiple (true);
665 chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
666 chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
669 /* some broken redraw behaviour - this is a bandaid */
670 chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
673 if (!persistent_folder.empty()) {
674 chooser.set_current_folder (persistent_folder);
677 notebook.append_page (chooser, _("Browse Files"));
679 hpacker.set_spacing (6);
680 hpacker.pack_start (notebook, true, true);
681 hpacker.pack_start (preview, false, false);
683 vpacker.set_spacing (6);
684 vpacker.pack_start (hpacker, true, true);
694 hbox = manage(new HBox);
695 hbox->pack_start (found_entry);
696 hbox->pack_start (found_search_btn);
698 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
699 scroll->add(found_list_view);
700 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
702 vbox = manage(new VBox);
703 vbox->pack_start (*hbox, PACK_SHRINK);
704 vbox->pack_start (*scroll);
706 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
708 found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
710 found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
712 found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
713 found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
715 notebook.append_page (*vbox, _("Search Tags"));
717 //add freesound search
718 #ifdef FREESOUND_GOT_FIXED
723 passbox = manage(new HBox);
724 passbox->set_spacing (6);
726 label = manage (new Label);
727 label->set_text (_("Tags:"));
728 passbox->pack_start (*label, false, false);
729 passbox->pack_start (freesound_entry, true, true);
731 label = manage (new Label);
732 label->set_text (_("Sort:"));
733 passbox->pack_start (*label, false, false);
734 passbox->pack_start (freesound_sort, false, false);
735 freesound_sort.clear_items();
737 // Order of the following must correspond with enum sortMethod
738 // in sfdb_freesound_mootcher.h
739 freesound_sort.append_text(_("None"));
740 freesound_sort.append_text(_("Longest"));
741 freesound_sort.append_text(_("Shortest"));
742 freesound_sort.append_text(_("Newest"));
743 freesound_sort.append_text(_("Oldest"));
744 freesound_sort.append_text(_("Most downloaded"));
745 freesound_sort.append_text(_("Least downloaded"));
746 freesound_sort.append_text(_("Highest rated"));
747 freesound_sort.append_text(_("Lowest rated"));
748 freesound_sort.set_active(0);
750 passbox->pack_start (freesound_search_btn, false, false);
751 passbox->pack_start (freesound_more_btn, false, false);
752 freesound_more_btn.set_label(_("More"));
753 freesound_more_btn.set_sensitive(false);
755 passbox->pack_start (freesound_similar_btn, false, false);
756 freesound_similar_btn.set_label(_("Similar"));
757 freesound_similar_btn.set_sensitive(false);
759 scroll = manage(new ScrolledWindow);
760 scroll->add(freesound_list_view);
761 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
763 vbox = manage(new VBox);
764 vbox->set_spacing (3);
765 vbox->pack_start (*passbox, PACK_SHRINK);
766 vbox->pack_start (*scroll);
768 freesound_list_view.append_column(_("ID") , freesound_list_columns.id);
769 freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
770 // freesound_list_view.append_column(_("URI") , freesound_list_columns.uri);
771 freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
772 freesound_list_view.append_column(_("Size"), freesound_list_columns.filesize);
773 freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
774 freesound_list_view.append_column(_("License"), freesound_list_columns.license);
775 freesound_list_view.get_column(0)->set_alignment(0.5);
776 freesound_list_view.get_column(1)->set_expand(true); // filename
777 freesound_list_view.get_column(1)->set_resizable(true); // filename
778 freesound_list_view.get_column(2)->set_alignment(0.5);
779 freesound_list_view.get_column(3)->set_alignment(0.5);
780 freesound_list_view.get_column(4)->set_alignment(0.5);
781 freesound_list_view.get_column(5)->set_alignment(0.5);
783 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
784 freesound_list_view.set_tooltip_column(1);
786 freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
787 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
788 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
789 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
790 freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
791 freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
792 notebook.append_page (*vbox, _("Search Freesound"));
795 notebook.set_size_request (500, -1);
796 notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
800 Gtk::HButtonBox* button_box = manage (new HButtonBox);
802 button_box->set_layout (BUTTONBOX_END);
804 button_box->pack_start (import_button, false, false);
805 import_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_OK));
807 Gtkmm2ext::UI::instance()->set_tip (import_button, _("Press to import selected files"));
809 vpacker.pack_end (*button_box, false, false);
811 set_wmclass (X_("import"), PROGRAM_NAME);
814 SoundFileBrowser::~SoundFileBrowser ()
816 persistent_folder = chooser.get_current_folder();
820 SoundFileBrowser::run ()
829 gtk_main_iteration ();
836 SoundFileBrowser::set_action_sensitive (bool yn)
838 import_button.set_sensitive (yn);
842 SoundFileBrowser::get_action_sensitive () const
844 return import_button.get_sensitive ();
848 SoundFileBrowser::do_something (int action)
855 SoundFileBrowser::on_show ()
857 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->sample_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);
2038 SoundFileOmega::file_selection_changed ()
2040 if (resetting_ourselves || !is_visible ()) {
2044 if (!reset_options ()) {
2045 set_action_sensitive (false);
2047 if (chooser.get_filenames().size() > 0) {
2048 set_action_sensitive (true);
2050 set_action_sensitive (false);
2056 SoundFileOmega::do_something (int action)
2058 SoundFileBrowser::do_something (action);
2060 if (action == RESPONSE_CLOSE || !ARDOUR_UI_UTILS::engine_is_running ()) {
2067 vector<string> paths = get_paths ();
2068 ImportPosition pos = get_position ();
2069 ImportMode mode = get_mode ();
2070 ImportDisposition chns = get_channel_disposition ();
2071 PluginInfoPtr instrument = instrument_combo.selected_instrument();
2073 MidiTrackNameSource mts = get_midi_track_name_source ();
2074 MidiTempoMapDisposition mtd = (get_use_smf_tempo_map () ? SMFTempoUse : SMFTempoIgnore);
2077 case ImportAtEditPoint:
2078 where = PublicEditor::instance().get_preferred_edit_position ();
2080 case ImportAtTimestamp:
2083 case ImportAtPlayhead:
2084 where = _session->transport_sample();
2087 where = _session->current_start_sample();
2091 SrcQuality quality = get_src_quality();
2093 _import_active = true;
2095 if (copy_files_btn.get_active()) {
2096 PublicEditor::instance().do_import (paths, chns, mode, quality, mts, mtd, where, instrument);
2098 PublicEditor::instance().do_embed (paths, chns, mode, where, instrument);
2101 _import_active = false;
2103 if (_reset_post_import) {
2104 _reset_post_import = false;