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/convert.h"
40 #include "pbd/tokenizer.h"
41 #include "pbd/enumwriter.h"
42 #include "pbd/pthread_utils.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"
61 #include "ardour_ui.h"
63 #include "gui_thread.h"
67 #include "gain_meter.h"
68 #include "main_clock.h"
69 #include "public_editor.h"
71 #include "ui_config.h"
73 #include "sfdb_freesound_mootcher.h"
75 using namespace ARDOUR;
79 using namespace Gtkmm2ext;
80 using namespace Editing;
84 string SoundFileBrowser::persistent_folder;
85 typedef TreeView::Selection::ListHandle_Path ListPath;
87 static MidiTrackNameSource
88 string2miditracknamesource (string const & str)
90 if (str == _("by track number")) {
91 return SMFTrackNumber;
92 } else if (str == _("by track name")) {
94 } else if (str == _("by instrument name")) {
95 return SMFInstrumentName;
98 warning << string_compose (_("programming error: unknown midi track name source string %1"), str) << endmsg;
100 return SMFTrackNumber;
104 string2importmode (string const & str)
106 if (str == _("as new tracks")) {
107 return ImportAsTrack;
108 } else if (str == _("to selected tracks")) {
109 return ImportToTrack;
110 } else if (str == _("to region list")) {
111 return ImportAsRegion;
112 } else if (str == _("as new tape tracks")) {
113 return ImportAsTapeTrack;
116 warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
118 return ImportAsTrack;
122 importmode2string (ImportMode mode)
126 return _("as new tracks");
128 return _("to selected tracks");
130 return _("to region list");
131 case ImportAsTapeTrack:
132 return _("as new tape tracks");
134 abort(); /*NOTREACHED*/
135 return _("as new tracks");
138 SoundFileBox::SoundFileBox (bool /*persistent*/)
140 length_clock ("sfboxLengthClock", true, "", false, false, true, false),
141 timecode_clock ("sfboxTimecodeClock", true, "", false, false, false, false),
143 autoplay_btn (_("Auto-play")),
144 seek_slider(0,1000,1),
148 set_name (X_("SoundFileBox"));
149 set_size_request (300, -1);
151 preview_label.set_markup (_("<b>Sound File Information</b>"));
153 border_frame.set_label_widget (preview_label);
154 border_frame.add (main_box);
156 pack_start (border_frame, true, true);
157 set_border_width (6);
159 main_box.set_border_width (6);
161 length.set_text (_("Length:"));
162 length.set_alignment (1, 0.5);
163 timecode.set_text (_("Timestamp:"));
164 timecode.set_alignment (1, 0.5);
165 format.set_text (_("Format:"));
166 format.set_alignment (1, 0.5);
167 channels.set_text (_("Channels:"));
168 channels.set_alignment (1, 0.5);
169 samplerate.set_text (_("Sample rate:"));
170 samplerate.set_alignment (1, 0.5);
171 tempomap.set_text (_("Tempo Map:"));
172 tempomap.set_alignment (1, 0.5);
174 preview_label.set_max_width_chars (50);
175 preview_label.set_ellipsize (Pango::ELLIPSIZE_END);
177 format_text.set_max_width_chars (20);
178 format_text.set_ellipsize (Pango::ELLIPSIZE_END);
179 format_text.set_alignment (0, 1);
181 table.set_col_spacings (6);
182 table.set_homogeneous (false);
183 table.set_row_spacings (6);
185 table.attach (channels, 0, 1, 0, 1, FILL, FILL);
186 table.attach (samplerate, 0, 1, 1, 2, FILL, FILL);
187 table.attach (format, 0, 1, 2, 4, FILL, FILL);
188 table.attach (length, 0, 1, 4, 5, FILL, FILL);
189 table.attach (timecode, 0, 1, 5, 6, FILL, FILL);
190 table.attach (tempomap, 0, 1, 6, 7, FILL, FILL);
192 table.attach (channels_value, 1, 2, 0, 1, FILL, FILL);
193 table.attach (samplerate_value, 1, 2, 1, 2, FILL, FILL);
194 table.attach (format_text, 1, 2, 2, 4, FILL, FILL);
195 table.attach (length_clock, 1, 2, 4, 5, FILL, FILL);
196 table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL);
197 table.attach (tempomap_value, 1, 2, 6, 7, FILL, FILL);
199 length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock->mode());
200 timecode_clock.set_mode (AudioClock::Timecode);
202 main_box.pack_start (table, false, false);
204 tags_entry.set_editable (true);
205 tags_entry.set_wrap_mode(Gtk::WRAP_WORD);
206 tags_entry.signal_focus_out_event().connect (sigc::mem_fun (*this, &SoundFileBox::tags_entry_left));
208 Label* label = manage (new Label (_("Tags:")));
209 label->set_alignment (0.0f, 0.5f);
210 main_box.pack_start (*label, false, false);
211 main_box.pack_start (tags_entry, true, true);
213 main_box.pack_start (bottom_box, false, false);
215 play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
216 // play_btn.set_label (_("Play"));
218 stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
219 // stop_btn.set_label (_("Stop"));
221 bottom_box.set_homogeneous (false);
222 bottom_box.set_spacing (6);
223 bottom_box.pack_start(play_btn, true, true);
224 bottom_box.pack_start(stop_btn, true, true);
225 bottom_box.pack_start(autoplay_btn, false, false);
227 seek_slider.set_draw_value(false);
229 seek_slider.add_events(Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
230 seek_slider.signal_button_press_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_press), false);
231 seek_slider.signal_button_release_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_release), false);
232 main_box.pack_start (seek_slider, false, false);
234 play_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::audition));
235 stop_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::stop_audition));
237 stop_btn.set_sensitive (false);
239 channels_value.set_alignment (0.0f, 0.5f);
240 samplerate_value.set_alignment (0.0f, 0.5f);
244 SoundFileBox::set_session(Session* s)
246 SessionHandlePtr::set_session (s);
248 length_clock.set_session (s);
249 timecode_clock.set_session (s);
252 play_btn.set_sensitive (false);
253 stop_btn.set_sensitive (false);
254 auditioner_connections.drop_connections();
256 auditioner_connections.drop_connections();
257 _session->AuditionActive.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_active, this, _1), gui_context());
258 _session->the_auditioner()->AuditionProgress.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_progress, this, _1, _2), gui_context());
263 SoundFileBox::audition_active(bool active) {
264 stop_btn.set_sensitive (active);
265 seek_slider.set_sensitive (active);
267 seek_slider.set_value(0);
272 SoundFileBox::audition_progress(ARDOUR::framecnt_t pos, ARDOUR::framecnt_t len) {
274 seek_slider.set_value( 1000.0 * pos / len);
275 seek_slider.set_sensitive (true);
280 SoundFileBox::seek_button_press(GdkEventButton*) {
282 return false; // pass on to slider
286 SoundFileBox::seek_button_release(GdkEventButton*) {
288 _session->the_auditioner()->seek_to_percent(seek_slider.get_value() / 10.0);
289 seek_slider.set_sensitive (false);
290 return false; // pass on to slider
294 SoundFileBox::setup_labels (const string& filename)
297 // save existing tags
305 if (SMFSource::valid_midi_file (path)) {
307 boost::shared_ptr<SMFSource> ms;
309 ms = boost::dynamic_pointer_cast<SMFSource> (
310 SourceFactory::createExternal (DataType::MIDI, *_session,
311 path, 0, Source::Flag (0), false));
312 } catch (const std::exception& e) {
313 error << string_compose(_("Could not read file: %1 (%2)."),
314 path, e.what()) << endmsg;
317 preview_label.set_markup (_("<b>Midi File Information</b>"));
319 format_text.set_text ("MIDI");
320 samplerate_value.set_text ("-");
321 tags_entry.get_buffer()->set_text ("");
322 timecode_clock.set (0);
323 tags_entry.set_sensitive (false);
326 if (ms->is_type0()) {
327 channels_value.set_text (to_string(ms->channels().size(), std::dec));
329 if (ms->num_tracks() > 1) {
330 channels_value.set_text (to_string(ms->num_tracks(), std::dec) + _("(Tracks)"));
332 channels_value.set_text (to_string(ms->num_tracks(), std::dec));
335 length_clock.set (ms->length(ms->timeline_position()));
336 switch (ms->num_tempos()) {
338 tempomap_value.set_text (_("No tempo data"));
341 Evoral::SMF::Tempo* t = ms->nth_tempo (0);
343 tempomap_value.set_text (string_compose (_("%1/%2 \u2669 = %3"),
346 (1000000 / t->microseconds_per_quarter_note) * 60));
350 tempomap_value.set_text (string_compose (_("map with %1 sections"),
355 channels_value.set_text ("");
356 length_clock.set (0);
357 tempomap_value.set_text (_("No tempo data"));
360 if (_session && ms) {
361 play_btn.set_sensitive (true);
363 play_btn.set_sensitive (false);
369 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
371 preview_label.set_markup (_("<b>Sound File Information</b>"));
372 format_text.set_text ("");
373 channels_value.set_text ("");
374 samplerate_value.set_text ("");
375 tags_entry.get_buffer()->set_text ("");
377 length_clock.set (0);
378 timecode_clock.set (0);
380 tags_entry.set_sensitive (false);
381 play_btn.set_sensitive (false);
386 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::Markup::escape_text (Glib::path_get_basename (filename))));
387 std::string n = sf_info.format_name;
388 if (n.substr (0, 8) == X_("Format: ")) {
391 format_text.set_text (n);
392 channels_value.set_text (to_string (sf_info.channels, std::dec));
394 if (_session && sf_info.samplerate != _session->frame_rate()) {
395 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
396 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
397 samplerate_value.set_name ("NewSessionSR1Label");
398 samplerate.set_name ("NewSessionSR1Label");
400 samplerate.set_text (_("Sample rate:"));
401 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
402 samplerate_value.set_name ("NewSessionSR2Label");
403 samplerate.set_name ("NewSessionSR2Label");
406 framecnt_t const nfr = _session ? _session->nominal_frame_rate() : 25;
407 double src_coef = (double) nfr / sf_info.samplerate;
409 length_clock.set (sf_info.length * src_coef + 0.5, true);
410 timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
412 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
414 vector<string> tags = Library->get_tags (string ("//") + filename);
416 stringstream tag_string;
417 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
418 if (i != tags.begin()) {
423 tags_entry.get_buffer()->set_text (tag_string.str());
425 tags_entry.set_sensitive (true);
427 play_btn.set_sensitive (true);
434 SoundFileBox::autoplay() const
436 return autoplay_btn.get_active();
440 SoundFileBox::audition_oneshot()
447 SoundFileBox::audition ()
453 _session->cancel_audition();
455 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
456 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
460 boost::shared_ptr<Region> r;
462 if (SMFSource::valid_midi_file (path)) {
464 boost::shared_ptr<SMFSource> ms =
465 boost::dynamic_pointer_cast<SMFSource> (
466 SourceFactory::createExternal (DataType::MIDI, *_session,
467 path, 0, Source::Flag (0), false));
469 string rname = region_name_from_path (ms->path(), false);
473 plist.add (ARDOUR::Properties::start, 0);
474 plist.add (ARDOUR::Properties::length, ms->length(ms->timeline_position()));
475 plist.add (ARDOUR::Properties::name, rname);
476 plist.add (ARDOUR::Properties::layer, 0);
478 r = boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (boost::dynamic_pointer_cast<Source>(ms), plist, false));
484 boost::shared_ptr<AudioFileSource> afs;
485 bool old_sbp = AudioSource::get_build_peakfiles ();
487 /* don't even think of building peakfiles for these files */
489 AudioSource::set_build_peakfiles (false);
491 for (int n = 0; n < sf_info.channels; ++n) {
493 afs = boost::dynamic_pointer_cast<AudioFileSource> (
494 SourceFactory::createExternal (DataType::AUDIO, *_session,
496 Source::Flag (ARDOUR::AudioFileSource::NoPeakFile), false));
497 if (afs->sample_rate() != _session->nominal_frame_rate()) {
498 boost::shared_ptr<SrcFileSource> sfs (new SrcFileSource(*_session, afs, _src_quality));
499 srclist.push_back(sfs);
501 srclist.push_back(afs);
504 } catch (failed_constructor& err) {
505 error << _("Could not access soundfile: ") << path << endmsg;
506 AudioSource::set_build_peakfiles (old_sbp);
511 AudioSource::set_build_peakfiles (old_sbp);
513 if (srclist.empty()) {
517 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
518 string rname = region_name_from_path (afs->path(), false);
522 plist.add (ARDOUR::Properties::start, 0);
523 plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->timeline_position()));
524 plist.add (ARDOUR::Properties::name, rname);
525 plist.add (ARDOUR::Properties::layer, 0);
527 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false));
530 frameoffset_t audition_position = 0;
531 switch(_import_position) {
532 case ImportAtTimestamp:
533 audition_position = 0;
535 case ImportAtPlayhead:
536 audition_position = _session->transport_frame();
539 audition_position = _session->current_start_frame();
541 case ImportAtEditPoint:
542 audition_position = PublicEditor::instance().get_preferred_edit_position ();
545 r->set_position(audition_position);
547 _session->audition_region(r);
551 SoundFileBox::stop_audition ()
554 _session->cancel_audition();
559 SoundFileBox::tags_entry_left (GdkEventFocus *)
566 SoundFileBox::tags_changed ()
568 string tag_string = tags_entry.get_buffer()->get_text ();
570 if (tag_string.empty()) {
576 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
577 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
585 SoundFileBox::save_tags (const vector<string>& tags)
587 Library->set_tags (string ("//") + path, tags);
588 Library->save_changes ();
591 SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persistent)
592 : ArdourWindow (title)
593 , found_list (ListStore::create(found_list_columns))
594 , freesound_list (ListStore::create(freesound_list_columns))
595 , chooser (FILE_CHOOSER_ACTION_OPEN)
596 , preview (persistent)
597 , found_search_btn (_("Search"))
598 , found_list_view (found_list)
599 , freesound_search_btn (_("Search"))
600 , freesound_list_view (freesound_list)
601 , resetting_ourselves (false)
605 , import_button (_("Import"))
606 , close_button (Stock::CLOSE)
612 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
613 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
614 chooser.add_shortcut_folder_uri("file:///Library/Audio/Apple Loops");
615 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
617 catch (Glib::Error & e) {
618 std::cerr << "sfdb.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
621 Gtkmm2ext::add_volume_shortcuts (chooser);
623 //add the file chooser
625 chooser.set_border_width (12);
627 audio_and_midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun (*this, &SoundFileBrowser::on_audio_and_midi_filter));
628 audio_and_midi_filter.set_name (_("Audio and MIDI files"));
630 audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
631 audio_filter.set_name (_("Audio files"));
633 midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
634 midi_filter.set_name (_("MIDI files"));
636 matchall_filter.add_pattern ("*.*");
637 matchall_filter.set_name (_("All files"));
639 chooser.add_filter (audio_and_midi_filter);
640 chooser.add_filter (audio_filter);
641 chooser.add_filter (midi_filter);
642 chooser.add_filter (matchall_filter);
643 chooser.set_select_multiple (true);
644 chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
645 chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
648 /* some broken redraw behaviour - this is a bandaid */
649 chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
652 if (!persistent_folder.empty()) {
653 chooser.set_current_folder (persistent_folder);
656 notebook.append_page (chooser, _("Browse Files"));
658 hpacker.set_spacing (6);
659 hpacker.pack_start (notebook, true, true);
660 hpacker.pack_start (preview, false, false);
662 vpacker.set_spacing (6);
663 vpacker.pack_start (hpacker, true, true);
673 hbox = manage(new HBox);
674 hbox->pack_start (found_entry);
675 hbox->pack_start (found_search_btn);
677 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
678 scroll->add(found_list_view);
679 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
681 vbox = manage(new VBox);
682 vbox->pack_start (*hbox, PACK_SHRINK);
683 vbox->pack_start (*scroll);
685 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
687 found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
689 found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
691 found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
692 found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
694 notebook.append_page (*vbox, _("Search Tags"));
696 //add freesound search
697 #ifdef FREESOUND_GOT_FIXED
702 passbox = manage(new HBox);
703 passbox->set_spacing (6);
705 label = manage (new Label);
706 label->set_text (_("Tags:"));
707 passbox->pack_start (*label, false, false);
708 passbox->pack_start (freesound_entry, true, true);
710 label = manage (new Label);
711 label->set_text (_("Sort:"));
712 passbox->pack_start (*label, false, false);
713 passbox->pack_start (freesound_sort, false, false);
714 freesound_sort.clear_items();
716 // Order of the following must correspond with enum sortMethod
717 // in sfdb_freesound_mootcher.h
718 freesound_sort.append_text(_("None"));
719 freesound_sort.append_text(_("Longest"));
720 freesound_sort.append_text(_("Shortest"));
721 freesound_sort.append_text(_("Newest"));
722 freesound_sort.append_text(_("Oldest"));
723 freesound_sort.append_text(_("Most downloaded"));
724 freesound_sort.append_text(_("Least downloaded"));
725 freesound_sort.append_text(_("Highest rated"));
726 freesound_sort.append_text(_("Lowest rated"));
727 freesound_sort.set_active(0);
729 passbox->pack_start (freesound_search_btn, false, false);
730 passbox->pack_start (freesound_more_btn, false, false);
731 freesound_more_btn.set_label(_("More"));
732 freesound_more_btn.set_sensitive(false);
734 passbox->pack_start (freesound_similar_btn, false, false);
735 freesound_similar_btn.set_label(_("Similar"));
736 freesound_similar_btn.set_sensitive(false);
738 scroll = manage(new ScrolledWindow);
739 scroll->add(freesound_list_view);
740 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
742 vbox = manage(new VBox);
743 vbox->set_spacing (3);
744 vbox->pack_start (*passbox, PACK_SHRINK);
745 vbox->pack_start (*scroll);
747 freesound_list_view.append_column(_("ID") , freesound_list_columns.id);
748 freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
749 // freesound_list_view.append_column(_("URI") , freesound_list_columns.uri);
750 freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
751 freesound_list_view.append_column(_("Size"), freesound_list_columns.filesize);
752 freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
753 freesound_list_view.append_column(_("License"), freesound_list_columns.license);
754 freesound_list_view.get_column(0)->set_alignment(0.5);
755 freesound_list_view.get_column(1)->set_expand(true); // filename
756 freesound_list_view.get_column(1)->set_resizable(true); // filename
757 freesound_list_view.get_column(2)->set_alignment(0.5);
758 freesound_list_view.get_column(3)->set_alignment(0.5);
759 freesound_list_view.get_column(4)->set_alignment(0.5);
760 freesound_list_view.get_column(5)->set_alignment(0.5);
762 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
763 freesound_list_view.set_tooltip_column(1);
765 freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
766 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
767 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
768 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
769 freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
770 freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
771 notebook.append_page (*vbox, _("Search Freesound"));
774 notebook.set_size_request (500, -1);
775 notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
779 Gtk::HButtonBox* button_box = manage (new HButtonBox);
781 button_box->set_layout (BUTTONBOX_END);
782 button_box->pack_start (close_button, false, false);
783 close_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_CLOSE));
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"));
789 Gtkmm2ext::UI::instance()->set_tip (close_button, _("Press to close this window without importing any files"));
791 vpacker.pack_end (*button_box, false, false);
793 set_wmclass (X_("import"), PROGRAM_NAME);
796 SoundFileBrowser::~SoundFileBrowser ()
798 persistent_folder = chooser.get_current_folder();
802 SoundFileBrowser::run ()
811 gtk_main_iteration ();
818 SoundFileBrowser::set_action_sensitive (bool yn)
820 import_button.set_sensitive (yn);
824 SoundFileBrowser::do_something (int action)
831 SoundFileBrowser::on_show ()
833 ArdourWindow::on_show ();
838 SoundFileBrowser::clear_selection ()
840 chooser.unselect_all ();
841 found_list_view.get_selection()->unselect_all ();
845 SoundFileBrowser::chooser_file_activated ()
851 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
857 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
863 SoundFileBrowser::set_session (Session* s)
865 ArdourWindow::set_session (s);
866 preview.set_session (s);
871 remove_gain_meter ();
876 SoundFileBrowser::add_gain_meter ()
880 gm = new GainMeter (_session, 250);
882 boost::shared_ptr<Route> r = _session->the_auditioner ();
884 gm->set_controls (r, r->shared_peak_meter(), r->amp(), r->gain_control());
885 gm->set_fader_name (X_("GainFader"));
887 meter_packer.set_border_width (12);
888 meter_packer.pack_start (*gm, false, true);
889 hpacker.pack_end (meter_packer, false, false);
890 meter_packer.show_all ();
895 SoundFileBrowser::remove_gain_meter ()
898 meter_packer.remove (*gm);
899 hpacker.remove (meter_packer);
906 SoundFileBrowser::start_metering ()
908 metering_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
912 SoundFileBrowser::stop_metering ()
914 metering_connection.disconnect();
918 SoundFileBrowser::meter ()
920 if (is_mapped () && _session && gm) {
921 gm->update_meters ();
926 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
928 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
932 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
934 return SMFSource::safe_midi_file_extension (filter_info.filename);
938 SoundFileBrowser::on_audio_and_midi_filter (const FileFilter::Info& filter_info)
940 return on_audio_filter (filter_info) || on_midi_filter (filter_info);
944 SoundFileBrowser::update_preview ()
946 if (preview.setup_labels (chooser.get_preview_filename())) {
947 if (preview.autoplay()) {
948 Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
954 SoundFileBrowser::found_list_view_selected ()
956 if (!reset_options ()) {
957 set_action_sensitive (false);
961 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
964 TreeIter iter = found_list->get_iter(*rows.begin());
965 file = (*iter)[found_list_columns.pathname];
966 chooser.set_filename (file);
967 set_action_sensitive (true);
969 set_action_sensitive (false);
972 preview.setup_labels (file);
977 SoundFileBrowser::found_search_clicked ()
979 string tag_string = found_entry.get_text ();
983 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
984 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
988 vector<string> results;
989 Library->search_members_and (results, tags);
992 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
993 TreeModel::iterator new_row = found_list->append();
994 TreeModel::Row row = *new_row;
995 string path = Glib::filename_from_uri (string ("file:") + *i);
996 row[found_list_columns.pathname] = path;
1002 SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
1005 Mootcher *mootcher = new Mootcher;
1008 string id = (*iter)[freesound_list_columns.id];
1009 string uri = (*iter)[freesound_list_columns.uri];
1010 string ofn = (*iter)[freesound_list_columns.filename];
1012 if (mootcher->checkAudioFile(ofn, id)) {
1013 // file already exists, no need to download it again
1014 file = mootcher->audioFileName;
1016 (*iter)[freesound_list_columns.started] = false;
1019 if (!(*iter)[freesound_list_columns.started]) {
1020 // start downloading the sound file
1021 (*iter)[freesound_list_columns.started] = true;
1022 mootcher->fetchAudioFile(ofn, id, uri, this);
1028 SoundFileBrowser::freesound_list_view_selected ()
1031 if (!reset_options ()) {
1032 set_action_sensitive (false);
1035 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1036 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1037 file = freesound_get_audio_file (freesound_list->get_iter(*i));
1040 switch (rows.size()) {
1043 freesound_similar_btn.set_sensitive(false);
1044 set_action_sensitive (false);
1047 // exactly one item selected
1049 // file exists on disk already
1050 chooser.set_filename (file);
1051 preview.setup_labels (file);
1052 set_action_sensitive (true);
1054 freesound_similar_btn.set_sensitive(true);
1057 // multiple items selected
1058 preview.setup_labels ("");
1059 freesound_similar_btn.set_sensitive(false);
1067 SoundFileBrowser::refresh_display(std::string ID, std::string file)
1069 // called when the mootcher has finished downloading a file
1070 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1071 if (rows.size() == 1) {
1072 // there's a single item selected in the freesound list
1073 //XXX make a function to be used to construct the actual file name both here and in the mootcher
1074 Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
1075 std::string selected_ID = (*row)[freesound_list_columns.id];
1076 if (ID == selected_ID) {
1077 // the selected item in the freesound list is the item that has just finished downloading
1078 chooser.set_filename(file);
1079 preview.setup_labels (file);
1080 set_action_sensitive (true);
1086 SoundFileBrowser::freesound_search_clicked ()
1089 freesound_list->clear();
1095 SoundFileBrowser::freesound_more_clicked ()
1100 snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
1101 freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
1105 SoundFileBrowser::freesound_similar_clicked ()
1107 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1108 if (rows.size() == 1) {
1111 Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
1112 id = (*iter)[freesound_list_columns.id];
1113 freesound_list->clear();
1115 GdkCursor *prev_cursor;
1116 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1117 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1120 std::string theString = mootcher.searchSimilar(id);
1122 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1123 handle_freesound_results(theString);
1128 SoundFileBrowser::freesound_search()
1132 string search_string = freesound_entry.get_text ();
1133 enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
1135 GdkCursor *prev_cursor;
1136 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1137 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1140 std::string theString = mootcher.searchText(
1144 "", // OSX eats anything incl mp3
1146 "type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
1151 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1152 handle_freesound_results(theString);
1156 SoundFileBrowser::handle_freesound_results(std::string theString) {
1158 doc.read_buffer( theString );
1159 XMLNode *root = doc.root();
1162 error << "no root XML node!" << endmsg;
1166 if ( strcmp(root->name().c_str(), "response") != 0) {
1167 error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
1171 // find out how many pages are available to search
1172 int freesound_n_pages = 1;
1173 XMLNode *res = root->child("num_pages");
1175 string result = res->child("text")->content();
1176 freesound_n_pages = atoi(result);
1179 int more_pages = freesound_n_pages - freesound_page;
1181 if (more_pages > 0) {
1182 freesound_more_btn.set_sensitive(true);
1183 freesound_more_btn.set_tooltip_text(string_compose(P_(
1184 "%1 more page of 100 results available",
1185 "%1 more pages of 100 results available",
1186 more_pages), more_pages));
1188 freesound_more_btn.set_sensitive(false);
1189 freesound_more_btn.set_tooltip_text(_("No more results available"));
1192 XMLNode *sounds_root = root->child("sounds");
1194 error << "no child node \"sounds\" found!" << endmsg;
1198 XMLNodeList sounds = sounds_root->children();
1199 if (sounds.size() == 0) {
1204 XMLNodeConstIterator niter;
1206 for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
1208 if( strcmp( node->name().c_str(), "resource") != 0 ) {
1209 error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
1213 // node->dump(cerr, "node:");
1216 XMLNode *id_node = node->child ("id");
1217 XMLNode *uri_node = node->child ("serve");
1218 XMLNode *ofn_node = node->child ("original_filename");
1219 XMLNode *dur_node = node->child ("duration");
1220 XMLNode *siz_node = node->child ("filesize");
1221 XMLNode *srt_node = node->child ("samplerate");
1222 XMLNode *lic_node = node->child ("license");
1224 if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
1226 std::string id = id_node->child("text")->content();
1227 std::string uri = uri_node->child("text")->content();
1228 std::string ofn = ofn_node->child("text")->content();
1229 std::string dur = dur_node->child("text")->content();
1230 std::string siz = siz_node->child("text")->content();
1231 std::string srt = srt_node->child("text")->content();
1232 std::string lic = lic_node->child("text")->content();
1235 // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
1237 double duration_seconds = atof(dur);
1239 char duration_hhmmss[16];
1240 if (duration_seconds >= 99 * 60 * 60) {
1241 strcpy(duration_hhmmss, ">99h");
1243 s = modf(duration_seconds/60, &m) * 60;
1244 m = modf(m/60, &h) * 60;
1245 sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
1250 double size_bytes = atof(siz);
1252 if (size_bytes < 1000) {
1253 sprintf(bsize, "%.0f %s", size_bytes, _("B"));
1254 } else if (size_bytes < 1000000 ) {
1255 sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
1256 } else if (size_bytes < 10000000) {
1257 sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
1258 } else if (size_bytes < 1000000000) {
1259 sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
1261 sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
1264 /* see http://www.freesound.org/help/faq/#licenses */
1265 char shortlicense[64];
1266 if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
1267 sprintf(shortlicense, "CC-BY-NC");
1268 } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
1269 sprintf(shortlicense, "CC-BY");
1270 } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
1271 sprintf(shortlicense, "sampling+");
1272 } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
1273 sprintf(shortlicense, "PD");
1275 snprintf(shortlicense, 64, "%s", lic.c_str());
1276 shortlicense[63]= '\0';
1279 TreeModel::iterator new_row = freesound_list->append();
1280 TreeModel::Row row = *new_row;
1282 row[freesound_list_columns.id ] = id;
1283 row[freesound_list_columns.uri ] = uri;
1284 row[freesound_list_columns.filename] = ofn;
1285 row[freesound_list_columns.duration] = duration_hhmmss;
1286 row[freesound_list_columns.filesize] = bsize;
1287 row[freesound_list_columns.smplrate] = srt;
1288 row[freesound_list_columns.license ] = shortlicense;
1295 SoundFileBrowser::get_paths ()
1297 vector<string> results;
1299 int n = notebook.get_current_page ();
1302 vector<string> filenames = chooser.get_filenames();
1303 vector<string>::iterator i;
1305 for (i = filenames.begin(); i != filenames.end(); ++i) {
1307 if ((!g_stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
1308 results.push_back (*i);
1312 } else if (n == 1) {
1314 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1315 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1316 TreeIter iter = found_list->get_iter(*i);
1317 string str = (*iter)[found_list_columns.pathname];
1319 results.push_back (str);
1322 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1323 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1324 string str = freesound_get_audio_file (freesound_list->get_iter(*i));
1326 results.push_back (str);
1335 SoundFileOmega::reset_options_noret ()
1337 if (!resetting_ourselves) {
1338 (void) reset_options ();
1343 SoundFileOmega::reset_options ()
1345 if (_import_active) {
1346 _reset_post_import = true;
1350 vector<string> paths = get_paths ();
1352 if (paths.empty()) {
1354 channel_combo.set_sensitive (false);
1355 action_combo.set_sensitive (false);
1356 where_combo.set_sensitive (false);
1357 copy_files_btn.set_active (true);
1358 copy_files_btn.set_sensitive (false);
1364 channel_combo.set_sensitive (true);
1365 action_combo.set_sensitive (true);
1366 where_combo.set_sensitive (true);
1368 /* if we get through this function successfully, this may be
1369 reset at the end, once we know if we can use hard links
1370 to do embedding (or if we are importing a MIDI file).
1373 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1374 copy_files_btn.set_sensitive (false);
1376 copy_files_btn.set_sensitive (false);
1382 bool selection_includes_multichannel;
1383 bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1386 /* See if we are thinking about importing any MIDI files */
1387 vector<string>::iterator i = paths.begin ();
1388 while (i != paths.end() && SMFSource::valid_midi_file (*i) == false) {
1391 bool const have_a_midi_file = (i != paths.end ());
1393 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1394 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1398 if (have_a_midi_file) {
1399 smf_tempo_btn.show ();
1401 smf_tempo_btn.hide ();
1404 string existing_choice;
1405 vector<string> action_strings;
1407 resetting_ourselves = true;
1409 if (chooser.get_filter() == &audio_filter) {
1413 if (selected_audio_track_cnt > 0) {
1414 if (channel_combo.get_active_text().length()) {
1415 ImportDisposition id = get_channel_disposition();
1418 case Editing::ImportDistinctFiles:
1419 if (selected_audio_track_cnt == paths.size()) {
1420 action_strings.push_back (importmode2string (ImportToTrack));
1424 case Editing::ImportDistinctChannels:
1425 /* XXX it would be nice to allow channel-per-selected track
1426 but its too hard we don't want to deal with all the
1427 different per-file + per-track channel configurations.
1432 action_strings.push_back (importmode2string (ImportToTrack));
1442 if (selected_midi_track_cnt > 0) {
1443 action_strings.push_back (importmode2string (ImportToTrack));
1447 action_strings.push_back (importmode2string (ImportAsTrack));
1448 action_strings.push_back (importmode2string (ImportAsRegion));
1449 action_strings.push_back (importmode2string (ImportAsTapeTrack));
1451 existing_choice = action_combo.get_active_text();
1453 set_popdown_strings (action_combo, action_strings);
1455 /* preserve any existing choice, if possible */
1458 if (existing_choice.length()) {
1459 vector<string>::iterator x;
1460 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1461 if (*x == existing_choice) {
1462 action_combo.set_active_text (existing_choice);
1466 if (x == action_strings.end()) {
1467 action_combo.set_active_text (action_strings.front());
1470 action_combo.set_active_text (action_strings.front());
1473 resetting_ourselves = false;
1475 if ((mode = get_mode()) == ImportAsRegion) {
1476 where_combo.set_sensitive (false);
1478 where_combo.set_sensitive (true);
1481 vector<string> channel_strings;
1483 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1485 if (selection_includes_multichannel) {
1486 channel_strings.push_back (_("one track per channel"));
1489 channel_strings.push_back (_("one track per file"));
1491 if (paths.size() > 1) {
1492 /* tape tracks are a single region per track, so we cannot
1493 sequence multiple files.
1495 if (mode != ImportAsTapeTrack) {
1496 channel_strings.push_back (_("sequence files"));
1499 channel_strings.push_back (_("all files in one track"));
1500 channel_strings.push_back (_("merge files"));
1506 channel_strings.push_back (_("one region per file"));
1508 if (selection_includes_multichannel) {
1509 channel_strings.push_back (_("one region per channel"));
1512 if (paths.size() > 1) {
1514 channel_strings.push_back (_("all files in one region"));
1519 resetting_ourselves = true;
1521 existing_choice = channel_combo.get_active_text();
1523 set_popdown_strings (channel_combo, channel_strings);
1525 /* preserve any existing choice, if possible */
1527 if (existing_choice.length()) {
1528 vector<string>::iterator x;
1529 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1530 if (*x == existing_choice) {
1531 channel_combo.set_active_text (existing_choice);
1535 if (x == channel_strings.end()) {
1536 channel_combo.set_active_text (channel_strings.front());
1539 channel_combo.set_active_text (channel_strings.front());
1542 resetting_ourselves = false;
1545 src_combo.set_sensitive (true);
1547 src_combo.set_sensitive (false);
1550 /* We must copy MIDI files or those from Freesound
1551 * or any file if we are under nsm control */
1552 bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
1554 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1556 if (selection_can_be_embedded_with_links && !must_copy) {
1557 copy_files_btn.set_sensitive (true);
1560 copy_files_btn.set_active (true);
1562 copy_files_btn.set_sensitive (false);
1568 copy_files_btn.set_active (true);
1570 copy_files_btn.set_sensitive (!must_copy);
1578 SoundFileOmega::bad_file_message()
1580 MessageDialog msg (*this,
1581 string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1586 resetting_ourselves = true;
1587 chooser.unselect_uri (chooser.get_preview_uri());
1588 resetting_ourselves = false;
1594 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1603 multichannel = false;
1605 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1607 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1608 if (info.channels > 1) {
1609 multichannel = true;
1614 if (sz != info.length) {
1619 if (info.samplerate != _session->frame_rate()) {
1623 } else if (SMFSource::valid_midi_file (*i)) {
1627 if (reader.open (*i)) {
1630 if (reader.is_type0 ()) {
1631 if (reader.channels().size() > 1) {
1632 /* for type-0 files, we can split
1633 * "one track per channel"
1635 multichannel = true;
1638 if (reader.num_tracks() > 1) {
1639 multichannel = true;
1654 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1656 #ifdef PLATFORM_WINDOWS
1659 std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
1662 if (g_mkdir (tmpdir.c_str(), 0744)) {
1663 if (errno != EEXIST) {
1668 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1670 char tmpc[PATH_MAX+1];
1672 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1676 if (link ((*i).c_str(), tmpc)) {
1686 g_rmdir (tmpdir.c_str());
1691 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
1692 : SoundFileBrowser (title, s, false)
1694 chooser.set_select_multiple (false);
1695 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1696 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1700 SoundFileChooser::on_hide ()
1702 ArdourWindow::on_hide();
1706 _session->cancel_audition();
1711 SoundFileChooser::get_filename ()
1713 vector<string> paths;
1715 paths = get_paths ();
1717 if (paths.empty()) {
1721 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1725 return paths.front();
1728 SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s,
1729 uint32_t selected_audio_tracks,
1730 uint32_t selected_midi_tracks,
1732 Editing::ImportMode mode_hint)
1733 : SoundFileBrowser (title, s, persistent)
1734 , copy_files_btn ( _("Copy files to session"))
1735 , smf_tempo_btn (_("Use MIDI Tempo Map (if defined)"))
1736 , selected_audio_track_cnt (selected_audio_tracks)
1737 , selected_midi_track_cnt (selected_midi_tracks)
1738 , _import_active (false)
1739 , _reset_post_import (false)
1743 set_size_request (-1, 550);
1745 block_two.set_border_width (12);
1746 block_three.set_border_width (12);
1747 block_four.set_border_width (12);
1750 str.push_back (_("file timestamp"));
1751 str.push_back (_("edit point"));
1752 str.push_back (_("playhead"));
1753 str.push_back (_("session start"));
1754 set_popdown_strings (where_combo, str);
1755 where_combo.set_active_text (str.back());
1756 where_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::where_combo_changed));
1758 Label* l = manage (new Label);
1759 l->set_markup (_("<b>Add files ...</b>"));
1760 options.attach (*l, 0, 1, 0, 1, FILL, SHRINK, 8, 0);
1761 options.attach (action_combo, 0, 1, 1, 2, FILL, SHRINK, 8, 0);
1763 l = manage (new Label);
1764 l->set_markup (_("<b>Insert at</b>"));
1765 options.attach (*l, 0, 1, 3, 4, FILL, SHRINK, 8, 0);
1766 options.attach (where_combo, 0, 1, 4, 5, FILL, SHRINK, 8, 0);
1768 l = manage (new Label);
1769 l->set_markup (_("<b>Mapping</b>"));
1770 options.attach (*l, 1, 2, 0, 1, FILL, SHRINK, 8, 0);
1771 options.attach (channel_combo, 1, 2, 1, 2, FILL, SHRINK, 8, 0);
1773 l = manage (new Label);
1774 l->set_markup (_("<b>Conversion quality</b>"));
1775 options.attach (*l, 1, 2, 3, 4, FILL, SHRINK, 8, 0);
1776 options.attach (src_combo, 1, 2, 4, 5, FILL, SHRINK, 8, 0);
1778 l = manage (new Label);
1779 l->set_markup (_("<b>MIDI Track Names</b>"));
1780 options.attach (*l, 2, 3, 0, 1, FILL, SHRINK, 8, 0);
1781 options.attach (midi_track_name_combo, 2, 3, 1, 2, FILL, SHRINK, 8, 0);
1783 options.attach (smf_tempo_btn, 2, 3, 3, 4, FILL, SHRINK, 8, 0);
1785 l = manage (new Label);
1786 l->set_markup (_("<b>Instrument</b>"));
1787 options.attach (*l, 3, 4, 0, 1, FILL, SHRINK, 8, 0);
1788 options.attach (instrument_combo, 3, 4, 1, 2, FILL, SHRINK, 8, 0);
1790 Alignment *hspace = manage (new Alignment ());
1791 hspace->set_size_request (2, 2);
1792 options.attach (*hspace, 0, 3, 2, 3, FILL, SHRINK, 0, 8);
1794 Alignment *vspace = manage (new Alignment ());
1795 vspace->set_size_request (2, 2);
1796 options.attach (*vspace, 2, 3, 0, 3, EXPAND, SHRINK, 0, 0);
1799 str.push_back (_("by track number"));
1800 str.push_back (_("by track name"));
1801 str.push_back (_("by instrument name"));
1802 set_popdown_strings (midi_track_name_combo, str);
1803 midi_track_name_combo.set_active_text (str.front());
1806 str.push_back (_("one track per file"));
1807 set_popdown_strings (channel_combo, str);
1808 channel_combo.set_active_text (str.front());
1809 channel_combo.set_sensitive (false);
1812 str.push_back (_("Best"));
1813 str.push_back (_("Good"));
1814 str.push_back (_("Quick"));
1815 str.push_back (_("Fast"));
1816 str.push_back (_("Fastest"));
1818 set_popdown_strings (src_combo, str);
1819 src_combo.set_active_text (str.front());
1820 src_combo.set_sensitive (false);
1821 src_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::src_combo_changed));
1823 action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1824 channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1826 copy_files_btn.set_active (true);
1828 Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1831 copy_label->set_size_request (175, -1);
1832 copy_label->set_line_wrap (true);
1835 block_four.pack_start (copy_files_btn, false, false);
1836 options.attach (block_four, 3, 4, 4, 5, FILL, SHRINK, 8, 0);
1838 vpacker.pack_start (options, false, true);
1840 /* setup disposition map */
1842 disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1843 disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1844 disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1845 disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1847 disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1848 disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1849 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1850 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1852 chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1854 /* set size requests for a couple of combos to allow them to display the longest text
1855 they will ever be asked to display. This prevents them being resized when the user
1856 selects a file to import, which in turn prevents the size of the dialog from jumping
1860 str.push_back (_("one track per file"));
1861 str.push_back (_("one track per channel"));
1862 str.push_back (_("sequence files"));
1863 str.push_back (_("all files in one region"));
1864 set_popdown_strings (channel_combo, str);
1867 str.push_back (importmode2string (ImportAsTrack));
1868 str.push_back (importmode2string (ImportToTrack));
1869 str.push_back (importmode2string (ImportAsRegion));
1870 str.push_back (importmode2string (ImportAsTapeTrack));
1871 set_popdown_strings (action_combo, str);
1872 action_combo.set_active_text (importmode2string(mode_hint));
1874 reset (selected_audio_tracks, selected_midi_tracks);
1878 SoundFileOmega::set_mode (ImportMode mode)
1880 action_combo.set_active_text (importmode2string (mode));
1884 SoundFileOmega::get_mode () const
1886 return string2importmode (action_combo.get_active_text());
1890 SoundFileOmega::on_hide ()
1892 ArdourWindow::on_hide();
1894 _session->cancel_audition();
1899 SoundFileOmega::get_position() const
1901 string str = where_combo.get_active_text();
1903 if (str == _("file timestamp")) {
1904 return ImportAtTimestamp;
1905 } else if (str == _("edit point")) {
1906 return ImportAtEditPoint;
1907 } else if (str == _("playhead")) {
1908 return ImportAtPlayhead;
1910 return ImportAtStart;
1915 SoundFileOmega::get_src_quality() const
1917 string str = src_combo.get_active_text();
1919 if (str == _("Best")) {
1921 } else if (str == _("Good")) {
1923 } else if (str == _("Quick")) {
1925 } else if (str == _("Fast")) {
1933 SoundFileOmega::src_combo_changed()
1935 preview.set_src_quality(get_src_quality());
1939 SoundFileOmega::where_combo_changed()
1941 preview.set_import_position(get_position());
1945 SoundFileOmega::get_midi_track_name_source () const
1947 return string2miditracknamesource (midi_track_name_combo.get_active_text());
1951 SoundFileOmega::get_use_smf_tempo_map () const
1953 return smf_tempo_btn.get_active ();
1957 SoundFileOmega::get_channel_disposition () const
1959 /* we use a map here because the channel combo can contain different strings
1960 depending on the state of the other combos. the map contains all possible strings
1961 and the ImportDisposition enum that corresponds to it.
1964 string str = channel_combo.get_active_text();
1965 DispositionMap::const_iterator x = disposition_map.find (str);
1967 if (x == disposition_map.end()) {
1968 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1969 abort(); /*NOTREACHED*/
1976 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
1978 selected_audio_track_cnt = selected_audio_tracks;
1979 selected_midi_track_cnt = selected_midi_tracks;
1981 if (selected_audio_track_cnt == 0 && selected_midi_track_cnt > 0) {
1982 chooser.set_filter (midi_filter);
1983 } else if (selected_midi_track_cnt == 0 && selected_audio_track_cnt > 0) {
1984 chooser.set_filter (audio_filter);
1986 chooser.set_filter (audio_and_midi_filter);
1993 SoundFileOmega::file_selection_changed ()
1995 if (resetting_ourselves) {
1999 if (!reset_options ()) {
2000 set_action_sensitive (false);
2002 if (chooser.get_filenames().size() > 0) {
2003 set_action_sensitive (true);
2005 set_action_sensitive (false);
2011 SoundFileOmega::do_something (int action)
2013 SoundFileBrowser::do_something (action);
2015 if (action == RESPONSE_CLOSE) {
2022 vector<string> paths = get_paths ();
2023 ImportPosition pos = get_position ();
2024 ImportMode mode = get_mode ();
2025 ImportDisposition chns = get_channel_disposition ();
2026 PluginInfoPtr instrument = instrument_combo.selected_instrument();
2028 MidiTrackNameSource mts = get_midi_track_name_source ();
2031 case ImportAtEditPoint:
2032 where = PublicEditor::instance().get_preferred_edit_position ();
2034 case ImportAtTimestamp:
2037 case ImportAtPlayhead:
2038 where = _session->transport_frame();
2041 where = _session->current_start_frame();
2045 SrcQuality quality = get_src_quality();
2047 _import_active = true;
2049 if (copy_files_btn.get_active()) {
2050 PublicEditor::instance().do_import (paths, chns, mode, quality, mts, where, instrument);
2052 PublicEditor::instance().do_embed (paths, chns, mode, where, instrument);
2055 _import_active = false;
2057 if (_reset_post_import) {
2058 _reset_post_import = false;