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::on_key_press_event (GdkEventKey* ev)
839 if (ev->keyval == GDK_Escape) {
840 do_something (RESPONSE_CLOSE);
843 return ArdourWindow::on_key_press_event (ev);
847 SoundFileBrowser::clear_selection ()
849 chooser.unselect_all ();
850 found_list_view.get_selection()->unselect_all ();
854 SoundFileBrowser::chooser_file_activated ()
860 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
866 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
872 SoundFileBrowser::set_session (Session* s)
874 ArdourWindow::set_session (s);
875 preview.set_session (s);
880 remove_gain_meter ();
885 SoundFileBrowser::add_gain_meter ()
889 gm = new GainMeter (_session, 250);
891 boost::shared_ptr<Route> r = _session->the_auditioner ();
893 gm->set_controls (r, r->shared_peak_meter(), r->amp(), r->gain_control());
894 gm->set_fader_name (X_("GainFader"));
896 meter_packer.set_border_width (12);
897 meter_packer.pack_start (*gm, false, true);
898 hpacker.pack_end (meter_packer, false, false);
899 meter_packer.show_all ();
904 SoundFileBrowser::remove_gain_meter ()
907 meter_packer.remove (*gm);
908 hpacker.remove (meter_packer);
915 SoundFileBrowser::start_metering ()
917 metering_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
921 SoundFileBrowser::stop_metering ()
923 metering_connection.disconnect();
927 SoundFileBrowser::meter ()
929 if (is_mapped () && _session && gm) {
930 gm->update_meters ();
935 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
937 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
941 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
943 return SMFSource::safe_midi_file_extension (filter_info.filename);
947 SoundFileBrowser::on_audio_and_midi_filter (const FileFilter::Info& filter_info)
949 return on_audio_filter (filter_info) || on_midi_filter (filter_info);
953 SoundFileBrowser::update_preview ()
955 if (preview.setup_labels (chooser.get_preview_filename())) {
956 if (preview.autoplay()) {
957 Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
963 SoundFileBrowser::found_list_view_selected ()
965 if (!reset_options ()) {
966 set_action_sensitive (false);
970 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
973 TreeIter iter = found_list->get_iter(*rows.begin());
974 file = (*iter)[found_list_columns.pathname];
975 chooser.set_filename (file);
976 set_action_sensitive (true);
978 set_action_sensitive (false);
981 preview.setup_labels (file);
986 SoundFileBrowser::found_search_clicked ()
988 string tag_string = found_entry.get_text ();
992 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
993 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
997 vector<string> results;
998 Library->search_members_and (results, tags);
1000 found_list->clear();
1001 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
1002 TreeModel::iterator new_row = found_list->append();
1003 TreeModel::Row row = *new_row;
1004 string path = Glib::filename_from_uri (string ("file:") + *i);
1005 row[found_list_columns.pathname] = path;
1011 SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
1014 Mootcher *mootcher = new Mootcher;
1017 string id = (*iter)[freesound_list_columns.id];
1018 string uri = (*iter)[freesound_list_columns.uri];
1019 string ofn = (*iter)[freesound_list_columns.filename];
1021 if (mootcher->checkAudioFile(ofn, id)) {
1022 // file already exists, no need to download it again
1023 file = mootcher->audioFileName;
1025 (*iter)[freesound_list_columns.started] = false;
1028 if (!(*iter)[freesound_list_columns.started]) {
1029 // start downloading the sound file
1030 (*iter)[freesound_list_columns.started] = true;
1031 mootcher->fetchAudioFile(ofn, id, uri, this);
1037 SoundFileBrowser::freesound_list_view_selected ()
1040 if (!reset_options ()) {
1041 set_action_sensitive (false);
1044 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1045 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1046 file = freesound_get_audio_file (freesound_list->get_iter(*i));
1049 switch (rows.size()) {
1052 freesound_similar_btn.set_sensitive(false);
1053 set_action_sensitive (false);
1056 // exactly one item selected
1058 // file exists on disk already
1059 chooser.set_filename (file);
1060 preview.setup_labels (file);
1061 set_action_sensitive (true);
1063 freesound_similar_btn.set_sensitive(true);
1066 // multiple items selected
1067 preview.setup_labels ("");
1068 freesound_similar_btn.set_sensitive(false);
1076 SoundFileBrowser::refresh_display(std::string ID, std::string file)
1078 // called when the mootcher has finished downloading a file
1079 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1080 if (rows.size() == 1) {
1081 // there's a single item selected in the freesound list
1082 //XXX make a function to be used to construct the actual file name both here and in the mootcher
1083 Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
1084 std::string selected_ID = (*row)[freesound_list_columns.id];
1085 if (ID == selected_ID) {
1086 // the selected item in the freesound list is the item that has just finished downloading
1087 chooser.set_filename(file);
1088 preview.setup_labels (file);
1089 set_action_sensitive (true);
1095 SoundFileBrowser::freesound_search_clicked ()
1098 freesound_list->clear();
1104 SoundFileBrowser::freesound_more_clicked ()
1109 snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
1110 freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
1114 SoundFileBrowser::freesound_similar_clicked ()
1116 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1117 if (rows.size() == 1) {
1120 Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
1121 id = (*iter)[freesound_list_columns.id];
1122 freesound_list->clear();
1124 GdkCursor *prev_cursor;
1125 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1126 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1129 std::string theString = mootcher.searchSimilar(id);
1131 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1132 handle_freesound_results(theString);
1137 SoundFileBrowser::freesound_search()
1141 string search_string = freesound_entry.get_text ();
1142 enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
1144 GdkCursor *prev_cursor;
1145 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1146 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1149 std::string theString = mootcher.searchText(
1153 "", // OSX eats anything incl mp3
1155 "type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
1160 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1161 handle_freesound_results(theString);
1165 SoundFileBrowser::handle_freesound_results(std::string theString) {
1167 doc.read_buffer( theString );
1168 XMLNode *root = doc.root();
1171 error << "no root XML node!" << endmsg;
1175 if ( strcmp(root->name().c_str(), "response") != 0) {
1176 error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
1180 // find out how many pages are available to search
1181 int freesound_n_pages = 1;
1182 XMLNode *res = root->child("num_pages");
1184 string result = res->child("text")->content();
1185 freesound_n_pages = atoi(result);
1188 int more_pages = freesound_n_pages - freesound_page;
1190 if (more_pages > 0) {
1191 freesound_more_btn.set_sensitive(true);
1192 freesound_more_btn.set_tooltip_text(string_compose(P_(
1193 "%1 more page of 100 results available",
1194 "%1 more pages of 100 results available",
1195 more_pages), more_pages));
1197 freesound_more_btn.set_sensitive(false);
1198 freesound_more_btn.set_tooltip_text(_("No more results available"));
1201 XMLNode *sounds_root = root->child("sounds");
1203 error << "no child node \"sounds\" found!" << endmsg;
1207 XMLNodeList sounds = sounds_root->children();
1208 if (sounds.size() == 0) {
1213 XMLNodeConstIterator niter;
1215 for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
1217 if( strcmp( node->name().c_str(), "resource") != 0 ) {
1218 error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
1222 // node->dump(cerr, "node:");
1225 XMLNode *id_node = node->child ("id");
1226 XMLNode *uri_node = node->child ("serve");
1227 XMLNode *ofn_node = node->child ("original_filename");
1228 XMLNode *dur_node = node->child ("duration");
1229 XMLNode *siz_node = node->child ("filesize");
1230 XMLNode *srt_node = node->child ("samplerate");
1231 XMLNode *lic_node = node->child ("license");
1233 if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
1235 std::string id = id_node->child("text")->content();
1236 std::string uri = uri_node->child("text")->content();
1237 std::string ofn = ofn_node->child("text")->content();
1238 std::string dur = dur_node->child("text")->content();
1239 std::string siz = siz_node->child("text")->content();
1240 std::string srt = srt_node->child("text")->content();
1241 std::string lic = lic_node->child("text")->content();
1244 // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
1246 double duration_seconds = atof(dur);
1248 char duration_hhmmss[16];
1249 if (duration_seconds >= 99 * 60 * 60) {
1250 strcpy(duration_hhmmss, ">99h");
1252 s = modf(duration_seconds/60, &m) * 60;
1253 m = modf(m/60, &h) * 60;
1254 sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
1259 double size_bytes = atof(siz);
1261 if (size_bytes < 1000) {
1262 sprintf(bsize, "%.0f %s", size_bytes, _("B"));
1263 } else if (size_bytes < 1000000 ) {
1264 sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
1265 } else if (size_bytes < 10000000) {
1266 sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
1267 } else if (size_bytes < 1000000000) {
1268 sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
1270 sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
1273 /* see http://www.freesound.org/help/faq/#licenses */
1274 char shortlicense[64];
1275 if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
1276 sprintf(shortlicense, "CC-BY-NC");
1277 } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
1278 sprintf(shortlicense, "CC-BY");
1279 } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
1280 sprintf(shortlicense, "sampling+");
1281 } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
1282 sprintf(shortlicense, "PD");
1284 snprintf(shortlicense, 64, "%s", lic.c_str());
1285 shortlicense[63]= '\0';
1288 TreeModel::iterator new_row = freesound_list->append();
1289 TreeModel::Row row = *new_row;
1291 row[freesound_list_columns.id ] = id;
1292 row[freesound_list_columns.uri ] = uri;
1293 row[freesound_list_columns.filename] = ofn;
1294 row[freesound_list_columns.duration] = duration_hhmmss;
1295 row[freesound_list_columns.filesize] = bsize;
1296 row[freesound_list_columns.smplrate] = srt;
1297 row[freesound_list_columns.license ] = shortlicense;
1304 SoundFileBrowser::get_paths ()
1306 vector<string> results;
1308 int n = notebook.get_current_page ();
1311 vector<string> filenames = chooser.get_filenames();
1312 vector<string>::iterator i;
1314 for (i = filenames.begin(); i != filenames.end(); ++i) {
1316 if ((!g_stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
1317 results.push_back (*i);
1321 } else if (n == 1) {
1323 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1324 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1325 TreeIter iter = found_list->get_iter(*i);
1326 string str = (*iter)[found_list_columns.pathname];
1328 results.push_back (str);
1331 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1332 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1333 string str = freesound_get_audio_file (freesound_list->get_iter(*i));
1335 results.push_back (str);
1344 SoundFileOmega::reset_options_noret ()
1346 if (!resetting_ourselves) {
1347 (void) reset_options ();
1352 SoundFileOmega::reset_options ()
1354 if (_import_active) {
1355 _reset_post_import = true;
1359 vector<string> paths = get_paths ();
1361 if (paths.empty()) {
1363 channel_combo.set_sensitive (false);
1364 action_combo.set_sensitive (false);
1365 where_combo.set_sensitive (false);
1366 copy_files_btn.set_active (true);
1367 copy_files_btn.set_sensitive (false);
1373 channel_combo.set_sensitive (true);
1374 action_combo.set_sensitive (true);
1375 where_combo.set_sensitive (true);
1377 /* if we get through this function successfully, this may be
1378 reset at the end, once we know if we can use hard links
1379 to do embedding (or if we are importing a MIDI file).
1382 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1383 copy_files_btn.set_sensitive (false);
1385 copy_files_btn.set_sensitive (false);
1391 bool selection_includes_multichannel;
1392 bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1395 /* See if we are thinking about importing any MIDI files */
1396 vector<string>::iterator i = paths.begin ();
1397 while (i != paths.end() && SMFSource::valid_midi_file (*i) == false) {
1400 bool const have_a_midi_file = (i != paths.end ());
1402 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1403 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1407 if (have_a_midi_file) {
1408 smf_tempo_btn.show ();
1410 smf_tempo_btn.hide ();
1413 string existing_choice;
1414 vector<string> action_strings;
1416 resetting_ourselves = true;
1418 if (chooser.get_filter() == &audio_filter) {
1422 if (selected_audio_track_cnt > 0) {
1423 if (channel_combo.get_active_text().length()) {
1424 ImportDisposition id = get_channel_disposition();
1427 case Editing::ImportDistinctFiles:
1428 if (selected_audio_track_cnt == paths.size()) {
1429 action_strings.push_back (importmode2string (ImportToTrack));
1433 case Editing::ImportDistinctChannels:
1434 /* XXX it would be nice to allow channel-per-selected track
1435 but its too hard we don't want to deal with all the
1436 different per-file + per-track channel configurations.
1441 action_strings.push_back (importmode2string (ImportToTrack));
1451 if (selected_midi_track_cnt > 0) {
1452 action_strings.push_back (importmode2string (ImportToTrack));
1456 action_strings.push_back (importmode2string (ImportAsTrack));
1457 action_strings.push_back (importmode2string (ImportAsRegion));
1458 if (!Profile->get_mixbus()) {
1459 action_strings.push_back (importmode2string (ImportAsTapeTrack));
1462 existing_choice = action_combo.get_active_text();
1464 set_popdown_strings (action_combo, action_strings);
1466 /* preserve any existing choice, if possible */
1469 if (existing_choice.length()) {
1470 vector<string>::iterator x;
1471 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1472 if (*x == existing_choice) {
1473 action_combo.set_active_text (existing_choice);
1477 if (x == action_strings.end()) {
1478 action_combo.set_active_text (action_strings.front());
1481 action_combo.set_active_text (action_strings.front());
1484 resetting_ourselves = false;
1486 if ((mode = get_mode()) == ImportAsRegion) {
1487 where_combo.set_sensitive (false);
1489 where_combo.set_sensitive (true);
1492 vector<string> channel_strings;
1494 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1496 if (selection_includes_multichannel) {
1497 channel_strings.push_back (_("one track per channel"));
1500 channel_strings.push_back (_("one track per file"));
1502 if (paths.size() > 1) {
1503 /* tape tracks are a single region per track, so we cannot
1504 sequence multiple files.
1506 if (mode != ImportAsTapeTrack) {
1507 channel_strings.push_back (_("sequence files"));
1510 channel_strings.push_back (_("all files in one track"));
1511 channel_strings.push_back (_("merge files"));
1517 channel_strings.push_back (_("one region per file"));
1519 if (selection_includes_multichannel) {
1520 channel_strings.push_back (_("one region per channel"));
1523 if (paths.size() > 1) {
1525 channel_strings.push_back (_("all files in one region"));
1530 resetting_ourselves = true;
1532 existing_choice = channel_combo.get_active_text();
1534 set_popdown_strings (channel_combo, channel_strings);
1536 /* preserve any existing choice, if possible */
1538 if (existing_choice.length()) {
1539 vector<string>::iterator x;
1540 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1541 if (*x == existing_choice) {
1542 channel_combo.set_active_text (existing_choice);
1546 if (x == channel_strings.end()) {
1547 channel_combo.set_active_text (channel_strings.front());
1550 channel_combo.set_active_text (channel_strings.front());
1553 resetting_ourselves = false;
1556 src_combo.set_sensitive (true);
1558 src_combo.set_sensitive (false);
1561 /* We must copy MIDI files or those from Freesound
1562 * or any file if we are under nsm control */
1563 bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
1565 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1567 if (selection_can_be_embedded_with_links && !must_copy) {
1568 copy_files_btn.set_sensitive (true);
1571 copy_files_btn.set_active (true);
1573 copy_files_btn.set_sensitive (false);
1579 copy_files_btn.set_active (true);
1581 copy_files_btn.set_sensitive (!must_copy);
1589 SoundFileOmega::bad_file_message()
1591 MessageDialog msg (*this,
1592 string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1597 resetting_ourselves = true;
1598 chooser.unselect_uri (chooser.get_preview_uri());
1599 resetting_ourselves = false;
1605 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1614 multichannel = false;
1616 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1618 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1619 if (info.channels > 1) {
1620 multichannel = true;
1625 if (sz != info.length) {
1630 if (info.samplerate != _session->frame_rate()) {
1634 } else if (SMFSource::valid_midi_file (*i)) {
1638 if (reader.open (*i)) {
1641 if (reader.is_type0 ()) {
1642 if (reader.channels().size() > 1) {
1643 /* for type-0 files, we can split
1644 * "one track per channel"
1646 multichannel = true;
1649 if (reader.num_tracks() > 1) {
1650 multichannel = true;
1665 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1667 #ifdef PLATFORM_WINDOWS
1670 std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
1673 if (g_mkdir (tmpdir.c_str(), 0744)) {
1674 if (errno != EEXIST) {
1679 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1681 char tmpc[PATH_MAX+1];
1683 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1687 if (link ((*i).c_str(), tmpc)) {
1697 g_rmdir (tmpdir.c_str());
1702 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
1703 : SoundFileBrowser (title, s, false)
1705 chooser.set_select_multiple (false);
1706 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1707 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1711 SoundFileChooser::on_hide ()
1713 ArdourWindow::on_hide();
1717 _session->cancel_audition();
1722 SoundFileChooser::get_filename ()
1724 vector<string> paths;
1726 paths = get_paths ();
1728 if (paths.empty()) {
1732 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1736 return paths.front();
1739 SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s,
1740 uint32_t selected_audio_tracks,
1741 uint32_t selected_midi_tracks,
1743 Editing::ImportMode mode_hint)
1744 : SoundFileBrowser (title, s, persistent)
1745 , copy_files_btn ( _("Copy files to session"))
1746 , smf_tempo_btn (_("Use MIDI Tempo Map (if defined)"))
1747 , selected_audio_track_cnt (selected_audio_tracks)
1748 , selected_midi_track_cnt (selected_midi_tracks)
1749 , _import_active (false)
1750 , _reset_post_import (false)
1754 set_size_request (-1, 550);
1756 block_two.set_border_width (12);
1757 block_three.set_border_width (12);
1758 block_four.set_border_width (12);
1761 str.push_back (_("file timestamp"));
1762 str.push_back (_("edit point"));
1763 str.push_back (_("playhead"));
1764 str.push_back (_("session start"));
1765 set_popdown_strings (where_combo, str);
1766 where_combo.set_active_text (str.back());
1767 where_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::where_combo_changed));
1769 Label* l = manage (new Label);
1770 l->set_markup (_("<b>Add files ...</b>"));
1771 options.attach (*l, 0, 1, 0, 1, FILL, SHRINK, 8, 0);
1772 options.attach (action_combo, 0, 1, 1, 2, FILL, SHRINK, 8, 0);
1774 l = manage (new Label);
1775 l->set_markup (_("<b>Insert at</b>"));
1776 options.attach (*l, 0, 1, 3, 4, FILL, SHRINK, 8, 0);
1777 options.attach (where_combo, 0, 1, 4, 5, FILL, SHRINK, 8, 0);
1779 l = manage (new Label);
1780 l->set_markup (_("<b>Mapping</b>"));
1781 options.attach (*l, 1, 2, 0, 1, FILL, SHRINK, 8, 0);
1782 options.attach (channel_combo, 1, 2, 1, 2, FILL, SHRINK, 8, 0);
1784 l = manage (new Label);
1785 l->set_markup (_("<b>Conversion quality</b>"));
1786 options.attach (*l, 1, 2, 3, 4, FILL, SHRINK, 8, 0);
1787 options.attach (src_combo, 1, 2, 4, 5, FILL, SHRINK, 8, 0);
1789 l = manage (new Label);
1790 l->set_markup (_("<b>MIDI Track Names</b>"));
1791 options.attach (*l, 2, 3, 0, 1, FILL, SHRINK, 8, 0);
1792 options.attach (midi_track_name_combo, 2, 3, 1, 2, FILL, SHRINK, 8, 0);
1794 options.attach (smf_tempo_btn, 2, 3, 3, 4, FILL, SHRINK, 8, 0);
1796 l = manage (new Label);
1797 l->set_markup (_("<b>Instrument</b>"));
1798 options.attach (*l, 3, 4, 0, 1, FILL, SHRINK, 8, 0);
1799 options.attach (instrument_combo, 3, 4, 1, 2, FILL, SHRINK, 8, 0);
1801 Alignment *hspace = manage (new Alignment ());
1802 hspace->set_size_request (2, 2);
1803 options.attach (*hspace, 0, 3, 2, 3, FILL, SHRINK, 0, 8);
1805 Alignment *vspace = manage (new Alignment ());
1806 vspace->set_size_request (2, 2);
1807 options.attach (*vspace, 2, 3, 0, 3, EXPAND, SHRINK, 0, 0);
1810 str.push_back (_("by track number"));
1811 str.push_back (_("by track name"));
1812 str.push_back (_("by instrument name"));
1813 set_popdown_strings (midi_track_name_combo, str);
1814 midi_track_name_combo.set_active_text (str.front());
1817 str.push_back (_("one track per file"));
1818 set_popdown_strings (channel_combo, str);
1819 channel_combo.set_active_text (str.front());
1820 channel_combo.set_sensitive (false);
1823 str.push_back (_("Best"));
1824 str.push_back (_("Good"));
1825 str.push_back (_("Quick"));
1826 str.push_back (_("Fast"));
1827 str.push_back (_("Fastest"));
1829 set_popdown_strings (src_combo, str);
1830 src_combo.set_active_text (str.front());
1831 src_combo.set_sensitive (false);
1832 src_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::src_combo_changed));
1834 action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1835 channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1837 copy_files_btn.set_active (true);
1839 Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1842 copy_label->set_size_request (175, -1);
1843 copy_label->set_line_wrap (true);
1846 block_four.pack_start (copy_files_btn, false, false);
1847 options.attach (block_four, 3, 4, 4, 5, FILL, SHRINK, 8, 0);
1849 vpacker.pack_start (options, false, true);
1851 /* setup disposition map */
1853 disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1854 disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1855 disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1856 disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1858 disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1859 disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1860 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1861 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1863 chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1865 /* set size requests for a couple of combos to allow them to display the longest text
1866 they will ever be asked to display. This prevents them being resized when the user
1867 selects a file to import, which in turn prevents the size of the dialog from jumping
1871 str.push_back (_("one track per file"));
1872 str.push_back (_("one track per channel"));
1873 str.push_back (_("sequence files"));
1874 str.push_back (_("all files in one region"));
1875 set_popdown_strings (channel_combo, str);
1878 str.push_back (importmode2string (ImportAsTrack));
1879 str.push_back (importmode2string (ImportToTrack));
1880 str.push_back (importmode2string (ImportAsRegion));
1881 str.push_back (importmode2string (ImportAsTapeTrack));
1882 set_popdown_strings (action_combo, str);
1883 action_combo.set_active_text (importmode2string(mode_hint));
1885 reset (selected_audio_tracks, selected_midi_tracks);
1889 SoundFileOmega::set_mode (ImportMode mode)
1891 action_combo.set_active_text (importmode2string (mode));
1895 SoundFileOmega::get_mode () const
1897 return string2importmode (action_combo.get_active_text());
1901 SoundFileOmega::on_hide ()
1903 ArdourWindow::on_hide();
1905 _session->cancel_audition();
1910 SoundFileOmega::get_position() const
1912 string str = where_combo.get_active_text();
1914 if (str == _("file timestamp")) {
1915 return ImportAtTimestamp;
1916 } else if (str == _("edit point")) {
1917 return ImportAtEditPoint;
1918 } else if (str == _("playhead")) {
1919 return ImportAtPlayhead;
1921 return ImportAtStart;
1926 SoundFileOmega::get_src_quality() const
1928 string str = src_combo.get_active_text();
1930 if (str == _("Best")) {
1932 } else if (str == _("Good")) {
1934 } else if (str == _("Quick")) {
1936 } else if (str == _("Fast")) {
1944 SoundFileOmega::src_combo_changed()
1946 preview.set_src_quality(get_src_quality());
1950 SoundFileOmega::where_combo_changed()
1952 preview.set_import_position(get_position());
1956 SoundFileOmega::get_midi_track_name_source () const
1958 return string2miditracknamesource (midi_track_name_combo.get_active_text());
1962 SoundFileOmega::get_use_smf_tempo_map () const
1964 return smf_tempo_btn.get_active ();
1968 SoundFileOmega::get_channel_disposition () const
1970 /* we use a map here because the channel combo can contain different strings
1971 depending on the state of the other combos. the map contains all possible strings
1972 and the ImportDisposition enum that corresponds to it.
1975 string str = channel_combo.get_active_text();
1976 DispositionMap::const_iterator x = disposition_map.find (str);
1978 if (x == disposition_map.end()) {
1979 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1980 abort(); /*NOTREACHED*/
1987 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
1989 selected_audio_track_cnt = selected_audio_tracks;
1990 selected_midi_track_cnt = selected_midi_tracks;
1992 if (selected_audio_track_cnt == 0 && selected_midi_track_cnt > 0) {
1993 chooser.set_filter (midi_filter);
1994 } else if (selected_midi_track_cnt == 0 && selected_audio_track_cnt > 0) {
1995 chooser.set_filter (audio_filter);
1997 chooser.set_filter (audio_and_midi_filter);
2004 SoundFileOmega::file_selection_changed ()
2006 if (resetting_ourselves) {
2010 if (!reset_options ()) {
2011 set_action_sensitive (false);
2013 if (chooser.get_filenames().size() > 0) {
2014 set_action_sensitive (true);
2016 set_action_sensitive (false);
2022 SoundFileOmega::do_something (int action)
2024 SoundFileBrowser::do_something (action);
2026 if (action == RESPONSE_CLOSE) {
2033 vector<string> paths = get_paths ();
2034 ImportPosition pos = get_position ();
2035 ImportMode mode = get_mode ();
2036 ImportDisposition chns = get_channel_disposition ();
2037 PluginInfoPtr instrument = instrument_combo.selected_instrument();
2039 MidiTrackNameSource mts = get_midi_track_name_source ();
2040 MidiTempoMapDisposition mtd = (get_use_smf_tempo_map () ? SMFTempoUse : SMFTempoIgnore);
2043 case ImportAtEditPoint:
2044 where = PublicEditor::instance().get_preferred_edit_position ();
2046 case ImportAtTimestamp:
2049 case ImportAtPlayhead:
2050 where = _session->transport_frame();
2053 where = _session->current_start_frame();
2057 SrcQuality quality = get_src_quality();
2059 _import_active = true;
2061 if (copy_files_btn.get_active()) {
2062 PublicEditor::instance().do_import (paths, chns, mode, quality, mts, mtd, where, instrument);
2064 PublicEditor::instance().do_embed (paths, chns, mode, where, instrument);
2067 _import_active = false;
2069 if (_reset_post_import) {
2070 _reset_post_import = false;