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/stock.h>
36 #include "pbd/gstdio_compat.h"
37 #include <glibmm/fileutils.h>
39 #include "pbd/tokenizer.h"
40 #include "pbd/enumwriter.h"
41 #include "pbd/pthread_utils.h"
42 #include "pbd/string_convert.h"
43 #include "pbd/xml++.h"
45 #include <gtkmm2ext/utils.h>
47 #include "evoral/SMF.hpp"
49 #include "ardour/audio_library.h"
50 #include "ardour/auditioner.h"
51 #include "ardour/audioregion.h"
52 #include "ardour/audiofilesource.h"
53 #include "ardour/midi_region.h"
54 #include "ardour/smf_source.h"
55 #include "ardour/region_factory.h"
56 #include "ardour/source_factory.h"
57 #include "ardour/session.h"
58 #include "ardour/session_directory.h"
59 #include "ardour/srcfilesource.h"
60 #include "ardour/profile.h"
62 #include "ardour_ui.h"
64 #include "gui_thread.h"
68 #include "gain_meter.h"
69 #include "main_clock.h"
70 #include "public_editor.h"
72 #include "ui_config.h"
74 #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()->secondary_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));
240 stop_btn.set_sensitive (false);
242 channels_value.set_alignment (0.0f, 0.5f);
243 samplerate_value.set_alignment (0.0f, 0.5f);
247 SoundFileBox::set_session(Session* s)
249 SessionHandlePtr::set_session (s);
251 length_clock.set_session (s);
252 timecode_clock.set_session (s);
255 play_btn.set_sensitive (false);
256 stop_btn.set_sensitive (false);
257 auditioner_connections.drop_connections();
259 auditioner_connections.drop_connections();
260 _session->AuditionActive.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_active, this, _1), gui_context());
261 _session->the_auditioner()->AuditionProgress.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_progress, this, _1, _2), gui_context());
266 SoundFileBox::audition_active(bool active) {
267 stop_btn.set_sensitive (active);
268 seek_slider.set_sensitive (active);
270 seek_slider.set_value(0);
275 SoundFileBox::audition_progress(ARDOUR::framecnt_t pos, ARDOUR::framecnt_t len) {
277 seek_slider.set_value( 1000.0 * pos / len);
278 seek_slider.set_sensitive (true);
283 SoundFileBox::seek_button_press(GdkEventButton*) {
285 return false; // pass on to slider
289 SoundFileBox::seek_button_release(GdkEventButton*) {
291 _session->the_auditioner()->seek_to_percent(seek_slider.get_value() / 10.0);
292 seek_slider.set_sensitive (false);
293 return false; // pass on to slider
297 SoundFileBox::setup_labels (const string& filename)
300 // save existing tags
308 if (SMFSource::valid_midi_file (path)) {
310 boost::shared_ptr<SMFSource> ms;
312 ms = boost::dynamic_pointer_cast<SMFSource> (
313 SourceFactory::createExternal (DataType::MIDI, *_session,
314 path, 0, Source::Flag (0), false));
315 } catch (const std::exception& e) {
316 error << string_compose(_("Could not read file: %1 (%2)."),
317 path, e.what()) << endmsg;
320 preview_label.set_markup (_("<b>Midi File Information</b>"));
322 format_text.set_text ("MIDI");
323 samplerate_value.set_text ("-");
324 tags_entry.get_buffer()->set_text ("");
325 timecode_clock.set (0);
326 tags_entry.set_sensitive (false);
329 if (ms->is_type0()) {
330 channels_value.set_text (to_string<uint32_t>(ms->channels().size()));
332 if (ms->num_tracks() > 1) {
333 channels_value.set_text (to_string(ms->num_tracks()) + _("(Tracks)"));
335 channels_value.set_text (to_string(ms->num_tracks()));
338 length_clock.set (ms->length(ms->timeline_position()));
339 switch (ms->num_tempos()) {
341 tempomap_value.set_text (_("No tempo data"));
344 Evoral::SMF::Tempo* t = ms->nth_tempo (0);
346 tempomap_value.set_text (string_compose (_("%1/%2 \u2669 = %3"),
353 tempomap_value.set_text (string_compose (_("map with %1 sections"),
358 channels_value.set_text ("");
359 length_clock.set (0);
360 tempomap_value.set_text (_("No tempo data"));
363 if (_session && ms) {
364 play_btn.set_sensitive (true);
366 play_btn.set_sensitive (false);
372 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
374 preview_label.set_markup (_("<b>Sound File Information</b>"));
375 format_text.set_text ("");
376 channels_value.set_text ("");
377 samplerate_value.set_text ("");
378 tags_entry.get_buffer()->set_text ("");
380 length_clock.set (0);
381 timecode_clock.set (0);
383 tags_entry.set_sensitive (false);
384 play_btn.set_sensitive (false);
389 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::Markup::escape_text (Glib::path_get_basename (filename))));
390 std::string n = sf_info.format_name;
391 if (n.substr (0, 8) == X_("Format: ")) {
394 format_text.set_text (n);
395 channels_value.set_text (to_string (sf_info.channels));
397 if (_session && sf_info.samplerate != _session->frame_rate()) {
398 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
399 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
400 samplerate_value.set_name ("NewSessionSR1Label");
401 samplerate.set_name ("NewSessionSR1Label");
403 samplerate.set_text (_("Sample rate:"));
404 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
405 samplerate_value.set_name ("NewSessionSR2Label");
406 samplerate.set_name ("NewSessionSR2Label");
409 framecnt_t const nfr = _session ? _session->nominal_frame_rate() : 25;
410 double src_coef = (double) nfr / sf_info.samplerate;
412 length_clock.set (sf_info.length * src_coef + 0.5, true);
413 timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
415 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
417 vector<string> tags = Library->get_tags (string ("//") + filename);
419 stringstream tag_string;
420 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
421 if (i != tags.begin()) {
426 tags_entry.get_buffer()->set_text (tag_string.str());
428 tags_entry.set_sensitive (true);
430 play_btn.set_sensitive (true);
437 SoundFileBox::autoplay() const
439 return autoplay_btn.get_active();
443 SoundFileBox::audition_oneshot()
450 SoundFileBox::audition ()
456 _session->cancel_audition();
458 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
459 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
463 boost::shared_ptr<Region> r;
465 if (SMFSource::valid_midi_file (path)) {
467 boost::shared_ptr<SMFSource> ms =
468 boost::dynamic_pointer_cast<SMFSource> (
469 SourceFactory::createExternal (DataType::MIDI, *_session,
470 path, 0, Source::Flag (0), false));
472 string rname = region_name_from_path (ms->path(), false);
476 plist.add (ARDOUR::Properties::start, 0);
477 plist.add (ARDOUR::Properties::length, ms->length(ms->timeline_position()));
478 plist.add (ARDOUR::Properties::name, rname);
479 plist.add (ARDOUR::Properties::layer, 0);
481 r = boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (boost::dynamic_pointer_cast<Source>(ms), plist, false));
487 boost::shared_ptr<AudioFileSource> afs;
488 bool old_sbp = AudioSource::get_build_peakfiles ();
490 /* don't even think of building peakfiles for these files */
492 AudioSource::set_build_peakfiles (false);
494 for (int n = 0; n < sf_info.channels; ++n) {
496 afs = boost::dynamic_pointer_cast<AudioFileSource> (
497 SourceFactory::createExternal (DataType::AUDIO, *_session,
499 Source::Flag (ARDOUR::AudioFileSource::NoPeakFile), false));
500 if (afs->sample_rate() != _session->nominal_frame_rate()) {
501 boost::shared_ptr<SrcFileSource> sfs (new SrcFileSource(*_session, afs, _src_quality));
502 srclist.push_back(sfs);
504 srclist.push_back(afs);
507 } catch (failed_constructor& err) {
508 error << _("Could not access soundfile: ") << path << endmsg;
509 AudioSource::set_build_peakfiles (old_sbp);
514 AudioSource::set_build_peakfiles (old_sbp);
516 if (srclist.empty()) {
520 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
521 string rname = region_name_from_path (afs->path(), false);
525 plist.add (ARDOUR::Properties::start, 0);
526 plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->timeline_position()));
527 plist.add (ARDOUR::Properties::name, rname);
528 plist.add (ARDOUR::Properties::layer, 0);
530 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false));
533 frameoffset_t audition_position = 0;
534 switch(_import_position) {
535 case ImportAtTimestamp:
536 audition_position = 0;
538 case ImportAtPlayhead:
539 audition_position = _session->transport_frame();
542 audition_position = _session->current_start_frame();
544 case ImportAtEditPoint:
545 audition_position = PublicEditor::instance().get_preferred_edit_position ();
548 r->set_position(audition_position);
550 _session->audition_region(r);
554 SoundFileBox::stop_audition ()
557 _session->cancel_audition();
562 SoundFileBox::tags_entry_left (GdkEventFocus *)
569 SoundFileBox::tags_changed ()
571 string tag_string = tags_entry.get_buffer()->get_text ();
573 if (tag_string.empty()) {
579 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
580 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
588 SoundFileBox::save_tags (const vector<string>& tags)
590 Library->set_tags (string ("//") + path, tags);
591 Library->save_changes ();
594 SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persistent)
595 : ArdourWindow (title)
596 , found_list (ListStore::create(found_list_columns))
597 , freesound_list (ListStore::create(freesound_list_columns))
598 , chooser (FILE_CHOOSER_ACTION_OPEN)
599 , preview (persistent)
600 , found_search_btn (_("Search"))
601 , found_list_view (found_list)
602 , freesound_search_btn (_("Search"))
603 , freesound_list_view (freesound_list)
604 , resetting_ourselves (false)
608 , import_button (_("Import"))
609 , close_button (Stock::CLOSE)
615 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
616 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
617 chooser.add_shortcut_folder_uri("file:///Library/Audio/Apple Loops");
618 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
620 catch (Glib::Error & e) {
621 std::cerr << "sfdb.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
624 Gtkmm2ext::add_volume_shortcuts (chooser);
626 //add the file chooser
628 chooser.set_border_width (12);
630 audio_and_midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun (*this, &SoundFileBrowser::on_audio_and_midi_filter));
631 audio_and_midi_filter.set_name (_("Audio and MIDI files"));
633 audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
634 audio_filter.set_name (_("Audio files"));
636 midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
637 midi_filter.set_name (_("MIDI files"));
639 matchall_filter.add_pattern ("*.*");
640 matchall_filter.set_name (_("All files"));
642 chooser.add_filter (audio_and_midi_filter);
643 chooser.add_filter (audio_filter);
644 chooser.add_filter (midi_filter);
645 chooser.add_filter (matchall_filter);
646 chooser.set_select_multiple (true);
647 chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
648 chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
651 /* some broken redraw behaviour - this is a bandaid */
652 chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
655 if (!persistent_folder.empty()) {
656 chooser.set_current_folder (persistent_folder);
659 notebook.append_page (chooser, _("Browse Files"));
661 hpacker.set_spacing (6);
662 hpacker.pack_start (notebook, true, true);
663 hpacker.pack_start (preview, false, false);
665 vpacker.set_spacing (6);
666 vpacker.pack_start (hpacker, true, true);
676 hbox = manage(new HBox);
677 hbox->pack_start (found_entry);
678 hbox->pack_start (found_search_btn);
680 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
681 scroll->add(found_list_view);
682 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
684 vbox = manage(new VBox);
685 vbox->pack_start (*hbox, PACK_SHRINK);
686 vbox->pack_start (*scroll);
688 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
690 found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
692 found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
694 found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
695 found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
697 notebook.append_page (*vbox, _("Search Tags"));
699 //add freesound search
700 #ifdef FREESOUND_GOT_FIXED
705 passbox = manage(new HBox);
706 passbox->set_spacing (6);
708 label = manage (new Label);
709 label->set_text (_("Tags:"));
710 passbox->pack_start (*label, false, false);
711 passbox->pack_start (freesound_entry, true, true);
713 label = manage (new Label);
714 label->set_text (_("Sort:"));
715 passbox->pack_start (*label, false, false);
716 passbox->pack_start (freesound_sort, false, false);
717 freesound_sort.clear_items();
719 // Order of the following must correspond with enum sortMethod
720 // in sfdb_freesound_mootcher.h
721 freesound_sort.append_text(_("None"));
722 freesound_sort.append_text(_("Longest"));
723 freesound_sort.append_text(_("Shortest"));
724 freesound_sort.append_text(_("Newest"));
725 freesound_sort.append_text(_("Oldest"));
726 freesound_sort.append_text(_("Most downloaded"));
727 freesound_sort.append_text(_("Least downloaded"));
728 freesound_sort.append_text(_("Highest rated"));
729 freesound_sort.append_text(_("Lowest rated"));
730 freesound_sort.set_active(0);
732 passbox->pack_start (freesound_search_btn, false, false);
733 passbox->pack_start (freesound_more_btn, false, false);
734 freesound_more_btn.set_label(_("More"));
735 freesound_more_btn.set_sensitive(false);
737 passbox->pack_start (freesound_similar_btn, false, false);
738 freesound_similar_btn.set_label(_("Similar"));
739 freesound_similar_btn.set_sensitive(false);
741 scroll = manage(new ScrolledWindow);
742 scroll->add(freesound_list_view);
743 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
745 vbox = manage(new VBox);
746 vbox->set_spacing (3);
747 vbox->pack_start (*passbox, PACK_SHRINK);
748 vbox->pack_start (*scroll);
750 freesound_list_view.append_column(_("ID") , freesound_list_columns.id);
751 freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
752 // freesound_list_view.append_column(_("URI") , freesound_list_columns.uri);
753 freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
754 freesound_list_view.append_column(_("Size"), freesound_list_columns.filesize);
755 freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
756 freesound_list_view.append_column(_("License"), freesound_list_columns.license);
757 freesound_list_view.get_column(0)->set_alignment(0.5);
758 freesound_list_view.get_column(1)->set_expand(true); // filename
759 freesound_list_view.get_column(1)->set_resizable(true); // filename
760 freesound_list_view.get_column(2)->set_alignment(0.5);
761 freesound_list_view.get_column(3)->set_alignment(0.5);
762 freesound_list_view.get_column(4)->set_alignment(0.5);
763 freesound_list_view.get_column(5)->set_alignment(0.5);
765 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
766 freesound_list_view.set_tooltip_column(1);
768 freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
769 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
770 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
771 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
772 freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
773 freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
774 notebook.append_page (*vbox, _("Search Freesound"));
777 notebook.set_size_request (500, -1);
778 notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
782 Gtk::HButtonBox* button_box = manage (new HButtonBox);
784 button_box->set_layout (BUTTONBOX_END);
785 button_box->pack_start (close_button, false, false);
786 close_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_CLOSE));
788 button_box->pack_start (import_button, false, false);
789 import_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_OK));
791 Gtkmm2ext::UI::instance()->set_tip (import_button, _("Press to import selected files"));
792 Gtkmm2ext::UI::instance()->set_tip (close_button, _("Press to close this window without importing any files"));
794 vpacker.pack_end (*button_box, false, false);
796 set_wmclass (X_("import"), PROGRAM_NAME);
799 SoundFileBrowser::~SoundFileBrowser ()
801 persistent_folder = chooser.get_current_folder();
805 SoundFileBrowser::run ()
814 gtk_main_iteration ();
821 SoundFileBrowser::set_action_sensitive (bool yn)
823 import_button.set_sensitive (yn);
827 SoundFileBrowser::do_something (int action)
834 SoundFileBrowser::on_show ()
836 ArdourWindow::on_show ();
841 SoundFileBrowser::clear_selection ()
843 chooser.unselect_all ();
844 found_list_view.get_selection()->unselect_all ();
848 SoundFileBrowser::chooser_file_activated ()
854 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
860 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
866 SoundFileBrowser::set_session (Session* s)
868 ArdourWindow::set_session (s);
869 preview.set_session (s);
874 remove_gain_meter ();
879 SoundFileBrowser::add_gain_meter ()
883 gm = new GainMeter (_session, 250);
885 boost::shared_ptr<Route> r = _session->the_auditioner ();
887 gm->set_controls (r, r->shared_peak_meter(), r->amp(), r->gain_control());
888 gm->set_fader_name (X_("GainFader"));
890 meter_packer.set_border_width (12);
891 meter_packer.pack_start (*gm, false, true);
892 hpacker.pack_end (meter_packer, false, false);
893 meter_packer.show_all ();
898 SoundFileBrowser::remove_gain_meter ()
901 meter_packer.remove (*gm);
902 hpacker.remove (meter_packer);
909 SoundFileBrowser::start_metering ()
911 metering_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
915 SoundFileBrowser::stop_metering ()
917 metering_connection.disconnect();
921 SoundFileBrowser::meter ()
923 if (is_mapped () && _session && gm) {
924 gm->update_meters ();
929 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
931 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
935 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
937 return SMFSource::safe_midi_file_extension (filter_info.filename);
941 SoundFileBrowser::on_audio_and_midi_filter (const FileFilter::Info& filter_info)
943 return on_audio_filter (filter_info) || on_midi_filter (filter_info);
947 SoundFileBrowser::update_preview ()
949 if (preview.setup_labels (chooser.get_preview_filename())) {
950 if (preview.autoplay()) {
951 Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
957 SoundFileBrowser::found_list_view_selected ()
959 if (!reset_options ()) {
960 set_action_sensitive (false);
964 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
967 TreeIter iter = found_list->get_iter(*rows.begin());
968 file = (*iter)[found_list_columns.pathname];
969 chooser.set_filename (file);
970 set_action_sensitive (true);
972 set_action_sensitive (false);
975 preview.setup_labels (file);
980 SoundFileBrowser::found_search_clicked ()
982 string tag_string = found_entry.get_text ();
986 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
987 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
991 vector<string> results;
992 Library->search_members_and (results, tags);
995 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
996 TreeModel::iterator new_row = found_list->append();
997 TreeModel::Row row = *new_row;
998 string path = Glib::filename_from_uri (string ("file:") + *i);
999 row[found_list_columns.pathname] = path;
1005 SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
1008 Mootcher *mootcher = new Mootcher;
1011 string id = (*iter)[freesound_list_columns.id];
1012 string uri = (*iter)[freesound_list_columns.uri];
1013 string ofn = (*iter)[freesound_list_columns.filename];
1015 if (mootcher->checkAudioFile(ofn, id)) {
1016 // file already exists, no need to download it again
1017 file = mootcher->audioFileName;
1019 (*iter)[freesound_list_columns.started] = false;
1022 if (!(*iter)[freesound_list_columns.started]) {
1023 // start downloading the sound file
1024 (*iter)[freesound_list_columns.started] = true;
1025 mootcher->fetchAudioFile(ofn, id, uri, this);
1031 SoundFileBrowser::freesound_list_view_selected ()
1034 if (!reset_options ()) {
1035 set_action_sensitive (false);
1038 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1039 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1040 file = freesound_get_audio_file (freesound_list->get_iter(*i));
1043 switch (rows.size()) {
1046 freesound_similar_btn.set_sensitive(false);
1047 set_action_sensitive (false);
1050 // exactly one item selected
1052 // file exists on disk already
1053 chooser.set_filename (file);
1054 preview.setup_labels (file);
1055 set_action_sensitive (true);
1057 freesound_similar_btn.set_sensitive(true);
1060 // multiple items selected
1061 preview.setup_labels ("");
1062 freesound_similar_btn.set_sensitive(false);
1070 SoundFileBrowser::refresh_display(std::string ID, std::string file)
1072 // called when the mootcher has finished downloading a file
1073 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1074 if (rows.size() == 1) {
1075 // there's a single item selected in the freesound list
1076 //XXX make a function to be used to construct the actual file name both here and in the mootcher
1077 Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
1078 std::string selected_ID = (*row)[freesound_list_columns.id];
1079 if (ID == selected_ID) {
1080 // the selected item in the freesound list is the item that has just finished downloading
1081 chooser.set_filename(file);
1082 preview.setup_labels (file);
1083 set_action_sensitive (true);
1089 SoundFileBrowser::freesound_search_clicked ()
1092 freesound_list->clear();
1098 SoundFileBrowser::freesound_more_clicked ()
1103 snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
1104 freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
1108 SoundFileBrowser::freesound_similar_clicked ()
1110 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1111 if (rows.size() == 1) {
1114 Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
1115 id = (*iter)[freesound_list_columns.id];
1116 freesound_list->clear();
1118 GdkCursor *prev_cursor;
1119 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1120 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1123 std::string theString = mootcher.searchSimilar(id);
1125 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1126 handle_freesound_results(theString);
1131 SoundFileBrowser::freesound_search()
1135 string search_string = freesound_entry.get_text ();
1136 enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
1138 GdkCursor *prev_cursor;
1139 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1140 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1143 std::string theString = mootcher.searchText(
1147 "", // OSX eats anything incl mp3
1149 "type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
1154 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1155 handle_freesound_results(theString);
1159 SoundFileBrowser::handle_freesound_results(std::string theString) {
1161 doc.read_buffer( theString );
1162 XMLNode *root = doc.root();
1165 error << "no root XML node!" << endmsg;
1169 if ( strcmp(root->name().c_str(), "response") != 0) {
1170 error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
1174 // find out how many pages are available to search
1175 int freesound_n_pages = 1;
1176 XMLNode *res = root->child("num_pages");
1178 string result = res->child("text")->content();
1179 freesound_n_pages = atoi(result);
1182 int more_pages = freesound_n_pages - freesound_page;
1184 if (more_pages > 0) {
1185 freesound_more_btn.set_sensitive(true);
1186 freesound_more_btn.set_tooltip_text(string_compose(P_(
1187 "%1 more page of 100 results available",
1188 "%1 more pages of 100 results available",
1189 more_pages), more_pages));
1191 freesound_more_btn.set_sensitive(false);
1192 freesound_more_btn.set_tooltip_text(_("No more results available"));
1195 XMLNode *sounds_root = root->child("sounds");
1197 error << "no child node \"sounds\" found!" << endmsg;
1201 XMLNodeList sounds = sounds_root->children();
1202 if (sounds.size() == 0) {
1207 XMLNodeConstIterator niter;
1209 for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
1211 if( strcmp( node->name().c_str(), "resource") != 0 ) {
1212 error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
1216 // node->dump(cerr, "node:");
1219 XMLNode *id_node = node->child ("id");
1220 XMLNode *uri_node = node->child ("serve");
1221 XMLNode *ofn_node = node->child ("original_filename");
1222 XMLNode *dur_node = node->child ("duration");
1223 XMLNode *siz_node = node->child ("filesize");
1224 XMLNode *srt_node = node->child ("samplerate");
1225 XMLNode *lic_node = node->child ("license");
1227 if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
1229 std::string id = id_node->child("text")->content();
1230 std::string uri = uri_node->child("text")->content();
1231 std::string ofn = ofn_node->child("text")->content();
1232 std::string dur = dur_node->child("text")->content();
1233 std::string siz = siz_node->child("text")->content();
1234 std::string srt = srt_node->child("text")->content();
1235 std::string lic = lic_node->child("text")->content();
1238 // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
1240 double duration_seconds = atof(dur);
1242 char duration_hhmmss[16];
1243 if (duration_seconds >= 99 * 60 * 60) {
1244 strcpy(duration_hhmmss, ">99h");
1246 s = modf(duration_seconds/60, &m) * 60;
1247 m = modf(m/60, &h) * 60;
1248 sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
1253 double size_bytes = atof(siz);
1255 if (size_bytes < 1000) {
1256 sprintf(bsize, "%.0f %s", size_bytes, _("B"));
1257 } else if (size_bytes < 1000000 ) {
1258 sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
1259 } else if (size_bytes < 10000000) {
1260 sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
1261 } else if (size_bytes < 1000000000) {
1262 sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
1264 sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
1267 /* see http://www.freesound.org/help/faq/#licenses */
1268 char shortlicense[64];
1269 if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
1270 sprintf(shortlicense, "CC-BY-NC");
1271 } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
1272 sprintf(shortlicense, "CC-BY");
1273 } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
1274 sprintf(shortlicense, "sampling+");
1275 } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
1276 sprintf(shortlicense, "PD");
1278 snprintf(shortlicense, 64, "%s", lic.c_str());
1279 shortlicense[63]= '\0';
1282 TreeModel::iterator new_row = freesound_list->append();
1283 TreeModel::Row row = *new_row;
1285 row[freesound_list_columns.id ] = id;
1286 row[freesound_list_columns.uri ] = uri;
1287 row[freesound_list_columns.filename] = ofn;
1288 row[freesound_list_columns.duration] = duration_hhmmss;
1289 row[freesound_list_columns.filesize] = bsize;
1290 row[freesound_list_columns.smplrate] = srt;
1291 row[freesound_list_columns.license ] = shortlicense;
1298 SoundFileBrowser::get_paths ()
1300 vector<string> results;
1302 int n = notebook.get_current_page ();
1305 vector<string> filenames = chooser.get_filenames();
1306 vector<string>::iterator i;
1308 for (i = filenames.begin(); i != filenames.end(); ++i) {
1310 if ((!g_stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
1311 results.push_back (*i);
1315 } else if (n == 1) {
1317 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1318 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1319 TreeIter iter = found_list->get_iter(*i);
1320 string str = (*iter)[found_list_columns.pathname];
1322 results.push_back (str);
1325 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1326 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1327 string str = freesound_get_audio_file (freesound_list->get_iter(*i));
1329 results.push_back (str);
1338 SoundFileOmega::reset_options_noret ()
1340 if (!resetting_ourselves) {
1341 (void) reset_options ();
1346 SoundFileOmega::reset_options ()
1348 if (_import_active) {
1349 _reset_post_import = true;
1353 vector<string> paths = get_paths ();
1355 if (paths.empty()) {
1357 channel_combo.set_sensitive (false);
1358 action_combo.set_sensitive (false);
1359 where_combo.set_sensitive (false);
1360 copy_files_btn.set_active (true);
1361 copy_files_btn.set_sensitive (false);
1367 channel_combo.set_sensitive (true);
1368 action_combo.set_sensitive (true);
1369 where_combo.set_sensitive (true);
1371 /* if we get through this function successfully, this may be
1372 reset at the end, once we know if we can use hard links
1373 to do embedding (or if we are importing a MIDI file).
1376 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1377 copy_files_btn.set_sensitive (false);
1379 copy_files_btn.set_sensitive (false);
1385 bool selection_includes_multichannel;
1386 bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1389 /* See if we are thinking about importing any MIDI files */
1390 vector<string>::iterator i = paths.begin ();
1391 while (i != paths.end() && SMFSource::valid_midi_file (*i) == false) {
1394 bool const have_a_midi_file = (i != paths.end ());
1396 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1397 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1401 if (have_a_midi_file) {
1402 smf_tempo_btn.show ();
1404 smf_tempo_btn.hide ();
1407 string existing_choice;
1408 vector<string> action_strings;
1410 resetting_ourselves = true;
1412 if (chooser.get_filter() == &audio_filter) {
1416 if (selected_audio_track_cnt > 0) {
1417 if (channel_combo.get_active_text().length()) {
1418 ImportDisposition id = get_channel_disposition();
1421 case Editing::ImportDistinctFiles:
1422 if (selected_audio_track_cnt == paths.size()) {
1423 action_strings.push_back (importmode2string (ImportToTrack));
1427 case Editing::ImportDistinctChannels:
1428 /* XXX it would be nice to allow channel-per-selected track
1429 but its too hard we don't want to deal with all the
1430 different per-file + per-track channel configurations.
1435 action_strings.push_back (importmode2string (ImportToTrack));
1445 if (selected_midi_track_cnt > 0) {
1446 action_strings.push_back (importmode2string (ImportToTrack));
1450 action_strings.push_back (importmode2string (ImportAsTrack));
1451 action_strings.push_back (importmode2string (ImportAsRegion));
1452 if (!Profile->get_mixbus()) {
1453 action_strings.push_back (importmode2string (ImportAsTapeTrack));
1456 existing_choice = action_combo.get_active_text();
1458 set_popdown_strings (action_combo, action_strings);
1460 /* preserve any existing choice, if possible */
1463 if (existing_choice.length()) {
1464 vector<string>::iterator x;
1465 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1466 if (*x == existing_choice) {
1467 action_combo.set_active_text (existing_choice);
1471 if (x == action_strings.end()) {
1472 action_combo.set_active_text (action_strings.front());
1475 action_combo.set_active_text (action_strings.front());
1478 resetting_ourselves = false;
1480 if ((mode = get_mode()) == ImportAsRegion) {
1481 where_combo.set_sensitive (false);
1483 where_combo.set_sensitive (true);
1486 vector<string> channel_strings;
1488 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1490 if (selection_includes_multichannel) {
1491 channel_strings.push_back (_("one track per channel"));
1494 channel_strings.push_back (_("one track per file"));
1496 if (paths.size() > 1) {
1497 /* tape tracks are a single region per track, so we cannot
1498 sequence multiple files.
1500 if (mode != ImportAsTapeTrack) {
1501 channel_strings.push_back (_("sequence files"));
1504 channel_strings.push_back (_("all files in one track"));
1505 channel_strings.push_back (_("merge files"));
1511 channel_strings.push_back (_("one region per file"));
1513 if (selection_includes_multichannel) {
1514 channel_strings.push_back (_("one region per channel"));
1517 if (paths.size() > 1) {
1519 channel_strings.push_back (_("all files in one region"));
1524 resetting_ourselves = true;
1526 existing_choice = channel_combo.get_active_text();
1528 set_popdown_strings (channel_combo, channel_strings);
1530 /* preserve any existing choice, if possible */
1532 if (existing_choice.length()) {
1533 vector<string>::iterator x;
1534 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1535 if (*x == existing_choice) {
1536 channel_combo.set_active_text (existing_choice);
1540 if (x == channel_strings.end()) {
1541 channel_combo.set_active_text (channel_strings.front());
1544 channel_combo.set_active_text (channel_strings.front());
1547 resetting_ourselves = false;
1550 src_combo.set_sensitive (true);
1552 src_combo.set_sensitive (false);
1555 /* We must copy MIDI files or those from Freesound
1556 * or any file if we are under nsm control */
1557 bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
1559 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1561 if (selection_can_be_embedded_with_links && !must_copy) {
1562 copy_files_btn.set_sensitive (true);
1565 copy_files_btn.set_active (true);
1567 copy_files_btn.set_sensitive (false);
1573 copy_files_btn.set_active (true);
1575 copy_files_btn.set_sensitive (!must_copy);
1583 SoundFileOmega::bad_file_message()
1585 MessageDialog msg (*this,
1586 string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1591 resetting_ourselves = true;
1592 chooser.unselect_uri (chooser.get_preview_uri());
1593 resetting_ourselves = false;
1599 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1608 multichannel = false;
1610 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1612 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1613 if (info.channels > 1) {
1614 multichannel = true;
1619 if (sz != info.length) {
1624 if (info.samplerate != _session->frame_rate()) {
1628 } else if (SMFSource::valid_midi_file (*i)) {
1632 if (reader.open (*i)) {
1635 if (reader.is_type0 ()) {
1636 if (reader.channels().size() > 1) {
1637 /* for type-0 files, we can split
1638 * "one track per channel"
1640 multichannel = true;
1643 if (reader.num_tracks() > 1) {
1644 multichannel = true;
1659 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1661 #ifdef PLATFORM_WINDOWS
1664 std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
1667 if (g_mkdir (tmpdir.c_str(), 0744)) {
1668 if (errno != EEXIST) {
1673 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1675 char tmpc[PATH_MAX+1];
1677 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1681 if (link ((*i).c_str(), tmpc)) {
1691 g_rmdir (tmpdir.c_str());
1696 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
1697 : SoundFileBrowser (title, s, false)
1699 chooser.set_select_multiple (false);
1700 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1701 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1705 SoundFileChooser::on_hide ()
1707 ArdourWindow::on_hide();
1711 _session->cancel_audition();
1716 SoundFileChooser::get_filename ()
1718 vector<string> paths;
1720 paths = get_paths ();
1722 if (paths.empty()) {
1726 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1730 return paths.front();
1733 SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s,
1734 uint32_t selected_audio_tracks,
1735 uint32_t selected_midi_tracks,
1737 Editing::ImportMode mode_hint)
1738 : SoundFileBrowser (title, s, persistent)
1739 , copy_files_btn ( _("Copy files to session"))
1740 , smf_tempo_btn (_("Use MIDI Tempo Map (if defined)"))
1741 , selected_audio_track_cnt (selected_audio_tracks)
1742 , selected_midi_track_cnt (selected_midi_tracks)
1743 , _import_active (false)
1744 , _reset_post_import (false)
1748 set_size_request (-1, 550);
1750 block_two.set_border_width (12);
1751 block_three.set_border_width (12);
1752 block_four.set_border_width (12);
1755 str.push_back (_("file timestamp"));
1756 str.push_back (_("edit point"));
1757 str.push_back (_("playhead"));
1758 str.push_back (_("session start"));
1759 set_popdown_strings (where_combo, str);
1760 where_combo.set_active_text (str.back());
1761 where_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::where_combo_changed));
1763 Label* l = manage (new Label);
1764 l->set_markup (_("<b>Add files ...</b>"));
1765 options.attach (*l, 0, 1, 0, 1, FILL, SHRINK, 8, 0);
1766 options.attach (action_combo, 0, 1, 1, 2, FILL, SHRINK, 8, 0);
1768 l = manage (new Label);
1769 l->set_markup (_("<b>Insert at</b>"));
1770 options.attach (*l, 0, 1, 3, 4, FILL, SHRINK, 8, 0);
1771 options.attach (where_combo, 0, 1, 4, 5, FILL, SHRINK, 8, 0);
1773 l = manage (new Label);
1774 l->set_markup (_("<b>Mapping</b>"));
1775 options.attach (*l, 1, 2, 0, 1, FILL, SHRINK, 8, 0);
1776 options.attach (channel_combo, 1, 2, 1, 2, FILL, SHRINK, 8, 0);
1778 l = manage (new Label);
1779 l->set_markup (_("<b>Conversion quality</b>"));
1780 options.attach (*l, 1, 2, 3, 4, FILL, SHRINK, 8, 0);
1781 options.attach (src_combo, 1, 2, 4, 5, FILL, SHRINK, 8, 0);
1783 l = manage (new Label);
1784 l->set_markup (_("<b>MIDI Track Names</b>"));
1785 options.attach (*l, 2, 3, 0, 1, FILL, SHRINK, 8, 0);
1786 options.attach (midi_track_name_combo, 2, 3, 1, 2, FILL, SHRINK, 8, 0);
1788 options.attach (smf_tempo_btn, 2, 3, 3, 4, FILL, SHRINK, 8, 0);
1790 l = manage (new Label);
1791 l->set_markup (_("<b>Instrument</b>"));
1792 options.attach (*l, 3, 4, 0, 1, FILL, SHRINK, 8, 0);
1793 options.attach (instrument_combo, 3, 4, 1, 2, FILL, SHRINK, 8, 0);
1795 Alignment *hspace = manage (new Alignment ());
1796 hspace->set_size_request (2, 2);
1797 options.attach (*hspace, 0, 3, 2, 3, FILL, SHRINK, 0, 8);
1799 Alignment *vspace = manage (new Alignment ());
1800 vspace->set_size_request (2, 2);
1801 options.attach (*vspace, 2, 3, 0, 3, EXPAND, SHRINK, 0, 0);
1804 str.push_back (_("by track number"));
1805 str.push_back (_("by track name"));
1806 str.push_back (_("by instrument name"));
1807 set_popdown_strings (midi_track_name_combo, str);
1808 midi_track_name_combo.set_active_text (str.front());
1811 str.push_back (_("one track per file"));
1812 set_popdown_strings (channel_combo, str);
1813 channel_combo.set_active_text (str.front());
1814 channel_combo.set_sensitive (false);
1817 str.push_back (_("Best"));
1818 str.push_back (_("Good"));
1819 str.push_back (_("Quick"));
1820 str.push_back (_("Fast"));
1821 str.push_back (_("Fastest"));
1823 set_popdown_strings (src_combo, str);
1824 src_combo.set_active_text (str.front());
1825 src_combo.set_sensitive (false);
1826 src_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::src_combo_changed));
1828 action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1829 channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1831 copy_files_btn.set_active (true);
1833 Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1836 copy_label->set_size_request (175, -1);
1837 copy_label->set_line_wrap (true);
1840 block_four.pack_start (copy_files_btn, false, false);
1841 options.attach (block_four, 3, 4, 4, 5, FILL, SHRINK, 8, 0);
1843 vpacker.pack_start (options, false, true);
1845 /* setup disposition map */
1847 disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1848 disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1849 disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1850 disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1852 disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1853 disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1854 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1855 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1857 chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1859 /* set size requests for a couple of combos to allow them to display the longest text
1860 they will ever be asked to display. This prevents them being resized when the user
1861 selects a file to import, which in turn prevents the size of the dialog from jumping
1865 str.push_back (_("one track per file"));
1866 str.push_back (_("one track per channel"));
1867 str.push_back (_("sequence files"));
1868 str.push_back (_("all files in one region"));
1869 set_popdown_strings (channel_combo, str);
1872 str.push_back (importmode2string (ImportAsTrack));
1873 str.push_back (importmode2string (ImportToTrack));
1874 str.push_back (importmode2string (ImportAsRegion));
1875 str.push_back (importmode2string (ImportAsTapeTrack));
1876 set_popdown_strings (action_combo, str);
1877 action_combo.set_active_text (importmode2string(mode_hint));
1879 reset (selected_audio_tracks, selected_midi_tracks);
1883 SoundFileOmega::set_mode (ImportMode mode)
1885 action_combo.set_active_text (importmode2string (mode));
1889 SoundFileOmega::get_mode () const
1891 return string2importmode (action_combo.get_active_text());
1895 SoundFileOmega::on_hide ()
1897 ArdourWindow::on_hide();
1899 _session->cancel_audition();
1904 SoundFileOmega::get_position() const
1906 string str = where_combo.get_active_text();
1908 if (str == _("file timestamp")) {
1909 return ImportAtTimestamp;
1910 } else if (str == _("edit point")) {
1911 return ImportAtEditPoint;
1912 } else if (str == _("playhead")) {
1913 return ImportAtPlayhead;
1915 return ImportAtStart;
1920 SoundFileOmega::get_src_quality() const
1922 string str = src_combo.get_active_text();
1924 if (str == _("Best")) {
1926 } else if (str == _("Good")) {
1928 } else if (str == _("Quick")) {
1930 } else if (str == _("Fast")) {
1938 SoundFileOmega::src_combo_changed()
1940 preview.set_src_quality(get_src_quality());
1944 SoundFileOmega::where_combo_changed()
1946 preview.set_import_position(get_position());
1950 SoundFileOmega::get_midi_track_name_source () const
1952 return string2miditracknamesource (midi_track_name_combo.get_active_text());
1956 SoundFileOmega::get_use_smf_tempo_map () const
1958 return smf_tempo_btn.get_active ();
1962 SoundFileOmega::get_channel_disposition () const
1964 /* we use a map here because the channel combo can contain different strings
1965 depending on the state of the other combos. the map contains all possible strings
1966 and the ImportDisposition enum that corresponds to it.
1969 string str = channel_combo.get_active_text();
1970 DispositionMap::const_iterator x = disposition_map.find (str);
1972 if (x == disposition_map.end()) {
1973 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1974 abort(); /*NOTREACHED*/
1981 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
1983 selected_audio_track_cnt = selected_audio_tracks;
1984 selected_midi_track_cnt = selected_midi_tracks;
1986 if (selected_audio_track_cnt == 0 && selected_midi_track_cnt > 0) {
1987 chooser.set_filter (midi_filter);
1988 } else if (selected_midi_track_cnt == 0 && selected_audio_track_cnt > 0) {
1989 chooser.set_filter (audio_filter);
1991 chooser.set_filter (audio_and_midi_filter);
1998 SoundFileOmega::file_selection_changed ()
2000 if (resetting_ourselves) {
2004 if (!reset_options ()) {
2005 set_action_sensitive (false);
2007 if (chooser.get_filenames().size() > 0) {
2008 set_action_sensitive (true);
2010 set_action_sensitive (false);
2016 SoundFileOmega::do_something (int action)
2018 SoundFileBrowser::do_something (action);
2020 if (action == RESPONSE_CLOSE) {
2027 vector<string> paths = get_paths ();
2028 ImportPosition pos = get_position ();
2029 ImportMode mode = get_mode ();
2030 ImportDisposition chns = get_channel_disposition ();
2031 PluginInfoPtr instrument = instrument_combo.selected_instrument();
2033 MidiTrackNameSource mts = get_midi_track_name_source ();
2034 MidiTempoMapDisposition mtd = (get_use_smf_tempo_map () ? SMFTempoUse : SMFTempoIgnore);
2037 case ImportAtEditPoint:
2038 where = PublicEditor::instance().get_preferred_edit_position ();
2040 case ImportAtTimestamp:
2043 case ImportAtPlayhead:
2044 where = _session->transport_frame();
2047 where = _session->current_start_frame();
2051 SrcQuality quality = get_src_quality();
2053 _import_active = true;
2055 if (copy_files_btn.get_active()) {
2056 PublicEditor::instance().do_import (paths, chns, mode, quality, mts, mtd, where, instrument);
2058 PublicEditor::instance().do_embed (paths, chns, mode, where, instrument);
2061 _import_active = false;
2063 if (_reset_post_import) {
2064 _reset_post_import = false;