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"))
614 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
615 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
616 chooser.add_shortcut_folder_uri("file:///Library/Audio/Apple Loops");
617 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
619 catch (Glib::Error & e) {
620 std::cerr << "sfdb.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
623 Gtkmm2ext::add_volume_shortcuts (chooser);
625 //add the file chooser
627 chooser.set_border_width (12);
629 audio_and_midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun (*this, &SoundFileBrowser::on_audio_and_midi_filter));
630 audio_and_midi_filter.set_name (_("Audio and MIDI files"));
632 audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
633 audio_filter.set_name (_("Audio files"));
635 midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
636 midi_filter.set_name (_("MIDI files"));
638 matchall_filter.add_pattern ("*.*");
639 matchall_filter.set_name (_("All files"));
641 chooser.add_filter (audio_and_midi_filter);
642 chooser.add_filter (audio_filter);
643 chooser.add_filter (midi_filter);
644 chooser.add_filter (matchall_filter);
645 chooser.set_select_multiple (true);
646 chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
647 chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
650 /* some broken redraw behaviour - this is a bandaid */
651 chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
654 if (!persistent_folder.empty()) {
655 chooser.set_current_folder (persistent_folder);
658 notebook.append_page (chooser, _("Browse Files"));
660 hpacker.set_spacing (6);
661 hpacker.pack_start (notebook, true, true);
662 hpacker.pack_start (preview, false, false);
664 vpacker.set_spacing (6);
665 vpacker.pack_start (hpacker, true, true);
675 hbox = manage(new HBox);
676 hbox->pack_start (found_entry);
677 hbox->pack_start (found_search_btn);
679 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
680 scroll->add(found_list_view);
681 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
683 vbox = manage(new VBox);
684 vbox->pack_start (*hbox, PACK_SHRINK);
685 vbox->pack_start (*scroll);
687 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
689 found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
691 found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
693 found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
694 found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
696 notebook.append_page (*vbox, _("Search Tags"));
698 //add freesound search
699 #ifdef FREESOUND_GOT_FIXED
704 passbox = manage(new HBox);
705 passbox->set_spacing (6);
707 label = manage (new Label);
708 label->set_text (_("Tags:"));
709 passbox->pack_start (*label, false, false);
710 passbox->pack_start (freesound_entry, true, true);
712 label = manage (new Label);
713 label->set_text (_("Sort:"));
714 passbox->pack_start (*label, false, false);
715 passbox->pack_start (freesound_sort, false, false);
716 freesound_sort.clear_items();
718 // Order of the following must correspond with enum sortMethod
719 // in sfdb_freesound_mootcher.h
720 freesound_sort.append_text(_("None"));
721 freesound_sort.append_text(_("Longest"));
722 freesound_sort.append_text(_("Shortest"));
723 freesound_sort.append_text(_("Newest"));
724 freesound_sort.append_text(_("Oldest"));
725 freesound_sort.append_text(_("Most downloaded"));
726 freesound_sort.append_text(_("Least downloaded"));
727 freesound_sort.append_text(_("Highest rated"));
728 freesound_sort.append_text(_("Lowest rated"));
729 freesound_sort.set_active(0);
731 passbox->pack_start (freesound_search_btn, false, false);
732 passbox->pack_start (freesound_more_btn, false, false);
733 freesound_more_btn.set_label(_("More"));
734 freesound_more_btn.set_sensitive(false);
736 passbox->pack_start (freesound_similar_btn, false, false);
737 freesound_similar_btn.set_label(_("Similar"));
738 freesound_similar_btn.set_sensitive(false);
740 scroll = manage(new ScrolledWindow);
741 scroll->add(freesound_list_view);
742 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
744 vbox = manage(new VBox);
745 vbox->set_spacing (3);
746 vbox->pack_start (*passbox, PACK_SHRINK);
747 vbox->pack_start (*scroll);
749 freesound_list_view.append_column(_("ID") , freesound_list_columns.id);
750 freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
751 // freesound_list_view.append_column(_("URI") , freesound_list_columns.uri);
752 freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
753 freesound_list_view.append_column(_("Size"), freesound_list_columns.filesize);
754 freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
755 freesound_list_view.append_column(_("License"), freesound_list_columns.license);
756 freesound_list_view.get_column(0)->set_alignment(0.5);
757 freesound_list_view.get_column(1)->set_expand(true); // filename
758 freesound_list_view.get_column(1)->set_resizable(true); // filename
759 freesound_list_view.get_column(2)->set_alignment(0.5);
760 freesound_list_view.get_column(3)->set_alignment(0.5);
761 freesound_list_view.get_column(4)->set_alignment(0.5);
762 freesound_list_view.get_column(5)->set_alignment(0.5);
764 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
765 freesound_list_view.set_tooltip_column(1);
767 freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
768 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
769 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
770 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
771 freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
772 freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
773 notebook.append_page (*vbox, _("Search Freesound"));
776 notebook.set_size_request (500, -1);
777 notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
781 Gtk::HButtonBox* button_box = manage (new HButtonBox);
783 button_box->set_layout (BUTTONBOX_END);
785 button_box->pack_start (import_button, false, false);
786 import_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_OK));
788 Gtkmm2ext::UI::instance()->set_tip (import_button, _("Press to import selected files"));
790 vpacker.pack_end (*button_box, false, false);
792 set_wmclass (X_("import"), PROGRAM_NAME);
795 SoundFileBrowser::~SoundFileBrowser ()
797 persistent_folder = chooser.get_current_folder();
801 SoundFileBrowser::run ()
810 gtk_main_iteration ();
817 SoundFileBrowser::set_action_sensitive (bool yn)
819 import_button.set_sensitive (yn);
823 SoundFileBrowser::do_something (int action)
830 SoundFileBrowser::on_show ()
832 ArdourWindow::on_show ();
837 SoundFileBrowser::clear_selection ()
839 chooser.unselect_all ();
840 found_list_view.get_selection()->unselect_all ();
844 SoundFileBrowser::chooser_file_activated ()
850 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
856 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
862 SoundFileBrowser::set_session (Session* s)
864 ArdourWindow::set_session (s);
865 preview.set_session (s);
870 remove_gain_meter ();
875 SoundFileBrowser::add_gain_meter ()
879 gm = new GainMeter (_session, 250);
881 boost::shared_ptr<Route> r = _session->the_auditioner ();
883 gm->set_controls (r, r->shared_peak_meter(), r->amp(), r->gain_control());
884 gm->set_fader_name (X_("GainFader"));
886 meter_packer.set_border_width (12);
887 meter_packer.pack_start (*gm, false, true);
888 hpacker.pack_end (meter_packer, false, false);
889 meter_packer.show_all ();
894 SoundFileBrowser::remove_gain_meter ()
897 meter_packer.remove (*gm);
898 hpacker.remove (meter_packer);
905 SoundFileBrowser::start_metering ()
907 metering_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
911 SoundFileBrowser::stop_metering ()
913 metering_connection.disconnect();
917 SoundFileBrowser::meter ()
919 if (is_mapped () && _session && gm) {
920 gm->update_meters ();
925 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
927 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
931 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
933 return SMFSource::safe_midi_file_extension (filter_info.filename);
937 SoundFileBrowser::on_audio_and_midi_filter (const FileFilter::Info& filter_info)
939 return on_audio_filter (filter_info) || on_midi_filter (filter_info);
943 SoundFileBrowser::update_preview ()
945 if (preview.setup_labels (chooser.get_preview_filename())) {
946 if (preview.autoplay()) {
947 Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
953 SoundFileBrowser::found_list_view_selected ()
955 if (!reset_options ()) {
956 set_action_sensitive (false);
960 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
963 TreeIter iter = found_list->get_iter(*rows.begin());
964 file = (*iter)[found_list_columns.pathname];
965 chooser.set_filename (file);
966 set_action_sensitive (true);
968 set_action_sensitive (false);
971 preview.setup_labels (file);
976 SoundFileBrowser::found_search_clicked ()
978 string tag_string = found_entry.get_text ();
982 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
983 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
987 vector<string> results;
988 Library->search_members_and (results, tags);
991 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
992 TreeModel::iterator new_row = found_list->append();
993 TreeModel::Row row = *new_row;
994 string path = Glib::filename_from_uri (string ("file:") + *i);
995 row[found_list_columns.pathname] = path;
1001 SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
1004 Mootcher *mootcher = new Mootcher;
1007 string id = (*iter)[freesound_list_columns.id];
1008 string uri = (*iter)[freesound_list_columns.uri];
1009 string ofn = (*iter)[freesound_list_columns.filename];
1011 if (mootcher->checkAudioFile(ofn, id)) {
1012 // file already exists, no need to download it again
1013 file = mootcher->audioFileName;
1015 (*iter)[freesound_list_columns.started] = false;
1018 if (!(*iter)[freesound_list_columns.started]) {
1019 // start downloading the sound file
1020 (*iter)[freesound_list_columns.started] = true;
1021 mootcher->fetchAudioFile(ofn, id, uri, this);
1027 SoundFileBrowser::freesound_list_view_selected ()
1030 if (!reset_options ()) {
1031 set_action_sensitive (false);
1034 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1035 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1036 file = freesound_get_audio_file (freesound_list->get_iter(*i));
1039 switch (rows.size()) {
1042 freesound_similar_btn.set_sensitive(false);
1043 set_action_sensitive (false);
1046 // exactly one item selected
1048 // file exists on disk already
1049 chooser.set_filename (file);
1050 preview.setup_labels (file);
1051 set_action_sensitive (true);
1053 freesound_similar_btn.set_sensitive(true);
1056 // multiple items selected
1057 preview.setup_labels ("");
1058 freesound_similar_btn.set_sensitive(false);
1066 SoundFileBrowser::refresh_display(std::string ID, std::string file)
1068 // called when the mootcher has finished downloading a file
1069 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1070 if (rows.size() == 1) {
1071 // there's a single item selected in the freesound list
1072 //XXX make a function to be used to construct the actual file name both here and in the mootcher
1073 Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
1074 std::string selected_ID = (*row)[freesound_list_columns.id];
1075 if (ID == selected_ID) {
1076 // the selected item in the freesound list is the item that has just finished downloading
1077 chooser.set_filename(file);
1078 preview.setup_labels (file);
1079 set_action_sensitive (true);
1085 SoundFileBrowser::freesound_search_clicked ()
1088 freesound_list->clear();
1094 SoundFileBrowser::freesound_more_clicked ()
1099 snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
1100 freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
1104 SoundFileBrowser::freesound_similar_clicked ()
1106 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1107 if (rows.size() == 1) {
1110 Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
1111 id = (*iter)[freesound_list_columns.id];
1112 freesound_list->clear();
1114 GdkCursor *prev_cursor;
1115 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1116 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1119 std::string theString = mootcher.searchSimilar(id);
1121 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1122 handle_freesound_results(theString);
1127 SoundFileBrowser::freesound_search()
1131 string search_string = freesound_entry.get_text ();
1132 enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
1134 GdkCursor *prev_cursor;
1135 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1136 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1139 std::string theString = mootcher.searchText(
1143 "", // OSX eats anything incl mp3
1145 "type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
1150 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1151 handle_freesound_results(theString);
1155 SoundFileBrowser::handle_freesound_results(std::string theString) {
1157 doc.read_buffer( theString );
1158 XMLNode *root = doc.root();
1161 error << "no root XML node!" << endmsg;
1165 if ( strcmp(root->name().c_str(), "response") != 0) {
1166 error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
1170 // find out how many pages are available to search
1171 int freesound_n_pages = 1;
1172 XMLNode *res = root->child("num_pages");
1174 string result = res->child("text")->content();
1175 freesound_n_pages = atoi(result);
1178 int more_pages = freesound_n_pages - freesound_page;
1180 if (more_pages > 0) {
1181 freesound_more_btn.set_sensitive(true);
1182 freesound_more_btn.set_tooltip_text(string_compose(P_(
1183 "%1 more page of 100 results available",
1184 "%1 more pages of 100 results available",
1185 more_pages), more_pages));
1187 freesound_more_btn.set_sensitive(false);
1188 freesound_more_btn.set_tooltip_text(_("No more results available"));
1191 XMLNode *sounds_root = root->child("sounds");
1193 error << "no child node \"sounds\" found!" << endmsg;
1197 XMLNodeList sounds = sounds_root->children();
1198 if (sounds.size() == 0) {
1203 XMLNodeConstIterator niter;
1205 for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
1207 if( strcmp( node->name().c_str(), "resource") != 0 ) {
1208 error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
1212 // node->dump(cerr, "node:");
1215 XMLNode *id_node = node->child ("id");
1216 XMLNode *uri_node = node->child ("serve");
1217 XMLNode *ofn_node = node->child ("original_filename");
1218 XMLNode *dur_node = node->child ("duration");
1219 XMLNode *siz_node = node->child ("filesize");
1220 XMLNode *srt_node = node->child ("samplerate");
1221 XMLNode *lic_node = node->child ("license");
1223 if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
1225 std::string id = id_node->child("text")->content();
1226 std::string uri = uri_node->child("text")->content();
1227 std::string ofn = ofn_node->child("text")->content();
1228 std::string dur = dur_node->child("text")->content();
1229 std::string siz = siz_node->child("text")->content();
1230 std::string srt = srt_node->child("text")->content();
1231 std::string lic = lic_node->child("text")->content();
1234 // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
1236 double duration_seconds = atof(dur);
1238 char duration_hhmmss[16];
1239 if (duration_seconds >= 99 * 60 * 60) {
1240 strcpy(duration_hhmmss, ">99h");
1242 s = modf(duration_seconds/60, &m) * 60;
1243 m = modf(m/60, &h) * 60;
1244 sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
1249 double size_bytes = atof(siz);
1251 if (size_bytes < 1000) {
1252 sprintf(bsize, "%.0f %s", size_bytes, _("B"));
1253 } else if (size_bytes < 1000000 ) {
1254 sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
1255 } else if (size_bytes < 10000000) {
1256 sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
1257 } else if (size_bytes < 1000000000) {
1258 sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
1260 sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
1263 /* see http://www.freesound.org/help/faq/#licenses */
1264 char shortlicense[64];
1265 if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
1266 sprintf(shortlicense, "CC-BY-NC");
1267 } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
1268 sprintf(shortlicense, "CC-BY");
1269 } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
1270 sprintf(shortlicense, "sampling+");
1271 } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
1272 sprintf(shortlicense, "PD");
1274 snprintf(shortlicense, 64, "%s", lic.c_str());
1275 shortlicense[63]= '\0';
1278 TreeModel::iterator new_row = freesound_list->append();
1279 TreeModel::Row row = *new_row;
1281 row[freesound_list_columns.id ] = id;
1282 row[freesound_list_columns.uri ] = uri;
1283 row[freesound_list_columns.filename] = ofn;
1284 row[freesound_list_columns.duration] = duration_hhmmss;
1285 row[freesound_list_columns.filesize] = bsize;
1286 row[freesound_list_columns.smplrate] = srt;
1287 row[freesound_list_columns.license ] = shortlicense;
1294 SoundFileBrowser::get_paths ()
1296 vector<string> results;
1298 int n = notebook.get_current_page ();
1301 vector<string> filenames = chooser.get_filenames();
1302 vector<string>::iterator i;
1304 for (i = filenames.begin(); i != filenames.end(); ++i) {
1306 if ((!g_stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
1307 results.push_back (*i);
1311 } else if (n == 1) {
1313 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1314 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1315 TreeIter iter = found_list->get_iter(*i);
1316 string str = (*iter)[found_list_columns.pathname];
1318 results.push_back (str);
1321 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1322 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1323 string str = freesound_get_audio_file (freesound_list->get_iter(*i));
1325 results.push_back (str);
1334 SoundFileOmega::reset_options_noret ()
1336 if (!resetting_ourselves) {
1337 (void) reset_options ();
1342 SoundFileOmega::reset_options ()
1344 if (_import_active) {
1345 _reset_post_import = true;
1349 vector<string> paths = get_paths ();
1351 if (paths.empty()) {
1353 channel_combo.set_sensitive (false);
1354 action_combo.set_sensitive (false);
1355 where_combo.set_sensitive (false);
1356 copy_files_btn.set_active (true);
1357 copy_files_btn.set_sensitive (false);
1363 channel_combo.set_sensitive (true);
1364 action_combo.set_sensitive (true);
1365 where_combo.set_sensitive (true);
1367 /* if we get through this function successfully, this may be
1368 reset at the end, once we know if we can use hard links
1369 to do embedding (or if we are importing a MIDI file).
1372 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1373 copy_files_btn.set_sensitive (false);
1375 copy_files_btn.set_sensitive (false);
1381 bool selection_includes_multichannel;
1382 bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1385 /* See if we are thinking about importing any MIDI files */
1386 vector<string>::iterator i = paths.begin ();
1387 while (i != paths.end() && SMFSource::valid_midi_file (*i) == false) {
1390 bool const have_a_midi_file = (i != paths.end ());
1392 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1393 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1397 if (have_a_midi_file) {
1398 smf_tempo_btn.show ();
1400 smf_tempo_btn.hide ();
1403 string existing_choice;
1404 vector<string> action_strings;
1406 resetting_ourselves = true;
1408 if (chooser.get_filter() == &audio_filter) {
1412 if (selected_audio_track_cnt > 0) {
1413 if (channel_combo.get_active_text().length()) {
1414 ImportDisposition id = get_channel_disposition();
1417 case Editing::ImportDistinctFiles:
1418 if (selected_audio_track_cnt == paths.size()) {
1419 action_strings.push_back (importmode2string (ImportToTrack));
1423 case Editing::ImportDistinctChannels:
1424 /* XXX it would be nice to allow channel-per-selected track
1425 but its too hard we don't want to deal with all the
1426 different per-file + per-track channel configurations.
1431 action_strings.push_back (importmode2string (ImportToTrack));
1441 if (selected_midi_track_cnt > 0) {
1442 action_strings.push_back (importmode2string (ImportToTrack));
1446 action_strings.push_back (importmode2string (ImportAsTrack));
1447 action_strings.push_back (importmode2string (ImportAsRegion));
1448 if (!Profile->get_mixbus()) {
1449 action_strings.push_back (importmode2string (ImportAsTapeTrack));
1452 existing_choice = action_combo.get_active_text();
1454 set_popdown_strings (action_combo, action_strings);
1456 /* preserve any existing choice, if possible */
1459 if (existing_choice.length()) {
1460 vector<string>::iterator x;
1461 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1462 if (*x == existing_choice) {
1463 action_combo.set_active_text (existing_choice);
1467 if (x == action_strings.end()) {
1468 action_combo.set_active_text (action_strings.front());
1471 action_combo.set_active_text (action_strings.front());
1474 resetting_ourselves = false;
1476 if ((mode = get_mode()) == ImportAsRegion) {
1477 where_combo.set_sensitive (false);
1479 where_combo.set_sensitive (true);
1482 vector<string> channel_strings;
1484 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1486 if (selection_includes_multichannel) {
1487 channel_strings.push_back (_("one track per channel"));
1490 channel_strings.push_back (_("one track per file"));
1492 if (paths.size() > 1) {
1493 /* tape tracks are a single region per track, so we cannot
1494 sequence multiple files.
1496 if (mode != ImportAsTapeTrack) {
1497 channel_strings.push_back (_("sequence files"));
1500 channel_strings.push_back (_("all files in one track"));
1501 channel_strings.push_back (_("merge files"));
1507 channel_strings.push_back (_("one region per file"));
1509 if (selection_includes_multichannel) {
1510 channel_strings.push_back (_("one region per channel"));
1513 if (paths.size() > 1) {
1515 channel_strings.push_back (_("all files in one region"));
1520 resetting_ourselves = true;
1522 existing_choice = channel_combo.get_active_text();
1524 set_popdown_strings (channel_combo, channel_strings);
1526 /* preserve any existing choice, if possible */
1528 if (existing_choice.length()) {
1529 vector<string>::iterator x;
1530 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1531 if (*x == existing_choice) {
1532 channel_combo.set_active_text (existing_choice);
1536 if (x == channel_strings.end()) {
1537 channel_combo.set_active_text (channel_strings.front());
1540 channel_combo.set_active_text (channel_strings.front());
1543 resetting_ourselves = false;
1546 src_combo.set_sensitive (true);
1548 src_combo.set_sensitive (false);
1551 /* We must copy MIDI files or those from Freesound
1552 * or any file if we are under nsm control */
1553 bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
1555 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1557 if (selection_can_be_embedded_with_links && !must_copy) {
1558 copy_files_btn.set_sensitive (true);
1561 copy_files_btn.set_active (true);
1563 copy_files_btn.set_sensitive (false);
1569 copy_files_btn.set_active (true);
1571 copy_files_btn.set_sensitive (!must_copy);
1579 SoundFileOmega::bad_file_message()
1581 MessageDialog msg (*this,
1582 string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1587 resetting_ourselves = true;
1588 chooser.unselect_uri (chooser.get_preview_uri());
1589 resetting_ourselves = false;
1595 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1604 multichannel = false;
1606 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1608 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1609 if (info.channels > 1) {
1610 multichannel = true;
1615 if (sz != info.length) {
1620 if (info.samplerate != _session->frame_rate()) {
1624 } else if (SMFSource::valid_midi_file (*i)) {
1628 if (reader.open (*i)) {
1631 if (reader.is_type0 ()) {
1632 if (reader.channels().size() > 1) {
1633 /* for type-0 files, we can split
1634 * "one track per channel"
1636 multichannel = true;
1639 if (reader.num_tracks() > 1) {
1640 multichannel = true;
1655 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1657 #ifdef PLATFORM_WINDOWS
1660 std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
1663 if (g_mkdir (tmpdir.c_str(), 0744)) {
1664 if (errno != EEXIST) {
1669 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1671 char tmpc[PATH_MAX+1];
1673 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1677 if (link ((*i).c_str(), tmpc)) {
1687 g_rmdir (tmpdir.c_str());
1692 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
1693 : SoundFileBrowser (title, s, false)
1695 chooser.set_select_multiple (false);
1696 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1697 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1701 SoundFileChooser::on_hide ()
1703 ArdourWindow::on_hide();
1707 _session->cancel_audition();
1712 SoundFileChooser::get_filename ()
1714 vector<string> paths;
1716 paths = get_paths ();
1718 if (paths.empty()) {
1722 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1726 return paths.front();
1729 SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s,
1730 uint32_t selected_audio_tracks,
1731 uint32_t selected_midi_tracks,
1733 Editing::ImportMode mode_hint)
1734 : SoundFileBrowser (title, s, persistent)
1735 , copy_files_btn ( _("Copy files to session"))
1736 , smf_tempo_btn (_("Use MIDI Tempo Map (if defined)"))
1737 , selected_audio_track_cnt (selected_audio_tracks)
1738 , selected_midi_track_cnt (selected_midi_tracks)
1739 , _import_active (false)
1740 , _reset_post_import (false)
1744 set_size_request (-1, 550);
1746 block_two.set_border_width (12);
1747 block_three.set_border_width (12);
1748 block_four.set_border_width (12);
1751 str.push_back (_("file timestamp"));
1752 str.push_back (_("edit point"));
1753 str.push_back (_("playhead"));
1754 str.push_back (_("session start"));
1755 set_popdown_strings (where_combo, str);
1756 where_combo.set_active_text (str.back());
1757 where_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::where_combo_changed));
1759 Label* l = manage (new Label);
1760 l->set_markup (_("<b>Add files ...</b>"));
1761 options.attach (*l, 0, 1, 0, 1, FILL, SHRINK, 8, 0);
1762 options.attach (action_combo, 0, 1, 1, 2, FILL, SHRINK, 8, 0);
1764 l = manage (new Label);
1765 l->set_markup (_("<b>Insert at</b>"));
1766 options.attach (*l, 0, 1, 3, 4, FILL, SHRINK, 8, 0);
1767 options.attach (where_combo, 0, 1, 4, 5, FILL, SHRINK, 8, 0);
1769 l = manage (new Label);
1770 l->set_markup (_("<b>Mapping</b>"));
1771 options.attach (*l, 1, 2, 0, 1, FILL, SHRINK, 8, 0);
1772 options.attach (channel_combo, 1, 2, 1, 2, FILL, SHRINK, 8, 0);
1774 l = manage (new Label);
1775 l->set_markup (_("<b>Conversion quality</b>"));
1776 options.attach (*l, 1, 2, 3, 4, FILL, SHRINK, 8, 0);
1777 options.attach (src_combo, 1, 2, 4, 5, FILL, SHRINK, 8, 0);
1779 l = manage (new Label);
1780 l->set_markup (_("<b>MIDI Track Names</b>"));
1781 options.attach (*l, 2, 3, 0, 1, FILL, SHRINK, 8, 0);
1782 options.attach (midi_track_name_combo, 2, 3, 1, 2, FILL, SHRINK, 8, 0);
1784 options.attach (smf_tempo_btn, 2, 3, 3, 4, FILL, SHRINK, 8, 0);
1786 l = manage (new Label);
1787 l->set_markup (_("<b>Instrument</b>"));
1788 options.attach (*l, 3, 4, 0, 1, FILL, SHRINK, 8, 0);
1789 options.attach (instrument_combo, 3, 4, 1, 2, FILL, SHRINK, 8, 0);
1791 Alignment *hspace = manage (new Alignment ());
1792 hspace->set_size_request (2, 2);
1793 options.attach (*hspace, 0, 3, 2, 3, FILL, SHRINK, 0, 8);
1795 Alignment *vspace = manage (new Alignment ());
1796 vspace->set_size_request (2, 2);
1797 options.attach (*vspace, 2, 3, 0, 3, EXPAND, SHRINK, 0, 0);
1800 str.push_back (_("by track number"));
1801 str.push_back (_("by track name"));
1802 str.push_back (_("by instrument name"));
1803 set_popdown_strings (midi_track_name_combo, str);
1804 midi_track_name_combo.set_active_text (str.front());
1807 str.push_back (_("one track per file"));
1808 set_popdown_strings (channel_combo, str);
1809 channel_combo.set_active_text (str.front());
1810 channel_combo.set_sensitive (false);
1813 str.push_back (_("Best"));
1814 str.push_back (_("Good"));
1815 str.push_back (_("Quick"));
1816 str.push_back (_("Fast"));
1817 str.push_back (_("Fastest"));
1819 set_popdown_strings (src_combo, str);
1820 src_combo.set_active_text (str.front());
1821 src_combo.set_sensitive (false);
1822 src_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::src_combo_changed));
1824 action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1825 channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1827 copy_files_btn.set_active (true);
1829 Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1832 copy_label->set_size_request (175, -1);
1833 copy_label->set_line_wrap (true);
1836 block_four.pack_start (copy_files_btn, false, false);
1837 options.attach (block_four, 3, 4, 4, 5, FILL, SHRINK, 8, 0);
1839 vpacker.pack_start (options, false, true);
1841 /* setup disposition map */
1843 disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1844 disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1845 disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1846 disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1848 disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1849 disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1850 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1851 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1853 chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1855 /* set size requests for a couple of combos to allow them to display the longest text
1856 they will ever be asked to display. This prevents them being resized when the user
1857 selects a file to import, which in turn prevents the size of the dialog from jumping
1861 str.push_back (_("one track per file"));
1862 str.push_back (_("one track per channel"));
1863 str.push_back (_("sequence files"));
1864 str.push_back (_("all files in one region"));
1865 set_popdown_strings (channel_combo, str);
1868 str.push_back (importmode2string (ImportAsTrack));
1869 str.push_back (importmode2string (ImportToTrack));
1870 str.push_back (importmode2string (ImportAsRegion));
1871 str.push_back (importmode2string (ImportAsTapeTrack));
1872 set_popdown_strings (action_combo, str);
1873 action_combo.set_active_text (importmode2string(mode_hint));
1875 reset (selected_audio_tracks, selected_midi_tracks);
1879 SoundFileOmega::set_mode (ImportMode mode)
1881 action_combo.set_active_text (importmode2string (mode));
1885 SoundFileOmega::get_mode () const
1887 return string2importmode (action_combo.get_active_text());
1891 SoundFileOmega::on_hide ()
1893 ArdourWindow::on_hide();
1895 _session->cancel_audition();
1900 SoundFileOmega::get_position() const
1902 string str = where_combo.get_active_text();
1904 if (str == _("file timestamp")) {
1905 return ImportAtTimestamp;
1906 } else if (str == _("edit point")) {
1907 return ImportAtEditPoint;
1908 } else if (str == _("playhead")) {
1909 return ImportAtPlayhead;
1911 return ImportAtStart;
1916 SoundFileOmega::get_src_quality() const
1918 string str = src_combo.get_active_text();
1920 if (str == _("Best")) {
1922 } else if (str == _("Good")) {
1924 } else if (str == _("Quick")) {
1926 } else if (str == _("Fast")) {
1934 SoundFileOmega::src_combo_changed()
1936 preview.set_src_quality(get_src_quality());
1940 SoundFileOmega::where_combo_changed()
1942 preview.set_import_position(get_position());
1946 SoundFileOmega::get_midi_track_name_source () const
1948 return string2miditracknamesource (midi_track_name_combo.get_active_text());
1952 SoundFileOmega::get_use_smf_tempo_map () const
1954 return smf_tempo_btn.get_active ();
1958 SoundFileOmega::get_channel_disposition () const
1960 /* we use a map here because the channel combo can contain different strings
1961 depending on the state of the other combos. the map contains all possible strings
1962 and the ImportDisposition enum that corresponds to it.
1965 string str = channel_combo.get_active_text();
1966 DispositionMap::const_iterator x = disposition_map.find (str);
1968 if (x == disposition_map.end()) {
1969 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1970 abort(); /*NOTREACHED*/
1977 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
1979 selected_audio_track_cnt = selected_audio_tracks;
1980 selected_midi_track_cnt = selected_midi_tracks;
1982 if (selected_audio_track_cnt == 0 && selected_midi_track_cnt > 0) {
1983 chooser.set_filter (midi_filter);
1984 } else if (selected_midi_track_cnt == 0 && selected_audio_track_cnt > 0) {
1985 chooser.set_filter (audio_filter);
1987 chooser.set_filter (audio_and_midi_filter);
1994 SoundFileOmega::file_selection_changed ()
1996 if (resetting_ourselves) {
2000 if (!reset_options ()) {
2001 set_action_sensitive (false);
2003 if (chooser.get_filenames().size() > 0) {
2004 set_action_sensitive (true);
2006 set_action_sensitive (false);
2012 SoundFileOmega::do_something (int action)
2014 SoundFileBrowser::do_something (action);
2016 if (action == RESPONSE_CLOSE) {
2023 vector<string> paths = get_paths ();
2024 ImportPosition pos = get_position ();
2025 ImportMode mode = get_mode ();
2026 ImportDisposition chns = get_channel_disposition ();
2027 PluginInfoPtr instrument = instrument_combo.selected_instrument();
2029 MidiTrackNameSource mts = get_midi_track_name_source ();
2030 MidiTempoMapDisposition mtd = (get_use_smf_tempo_map () ? SMFTempoUse : SMFTempoIgnore);
2033 case ImportAtEditPoint:
2034 where = PublicEditor::instance().get_preferred_edit_position ();
2036 case ImportAtTimestamp:
2039 case ImportAtPlayhead:
2040 where = _session->transport_frame();
2043 where = _session->current_start_frame();
2047 SrcQuality quality = get_src_quality();
2049 _import_active = true;
2051 if (copy_files_btn.get_active()) {
2052 PublicEditor::instance().do_import (paths, chns, mode, quality, mts, mtd, where, instrument);
2054 PublicEditor::instance().do_embed (paths, chns, mode, where, instrument);
2057 _import_active = false;
2059 if (_reset_post_import) {
2060 _reset_post_import = false;