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"
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),
149 set_name (X_("SoundFileBox"));
150 set_size_request (300, -1);
152 preview_label.set_markup (_("<b>Sound File Information</b>"));
154 border_frame.set_label_widget (preview_label);
155 border_frame.add (main_box);
157 pack_start (border_frame, true, true);
158 set_border_width (6);
160 main_box.set_border_width (6);
162 length.set_text (_("Length:"));
163 length.set_alignment (1, 0.5);
164 timecode.set_text (_("Timestamp:"));
165 timecode.set_alignment (1, 0.5);
166 format.set_text (_("Format:"));
167 format.set_alignment (1, 0.5);
168 channels.set_text (_("Channels:"));
169 channels.set_alignment (1, 0.5);
170 samplerate.set_text (_("Sample rate:"));
171 samplerate.set_alignment (1, 0.5);
172 tempomap.set_text (_("Tempo Map:"));
173 tempomap.set_alignment (1, 0.5);
175 preview_label.set_max_width_chars (50);
176 preview_label.set_ellipsize (Pango::ELLIPSIZE_END);
178 format_text.set_max_width_chars (20);
179 format_text.set_ellipsize (Pango::ELLIPSIZE_END);
180 format_text.set_alignment (0, 1);
182 table.set_col_spacings (6);
183 table.set_homogeneous (false);
184 table.set_row_spacings (6);
186 table.attach (channels, 0, 1, 0, 1, FILL, FILL);
187 table.attach (samplerate, 0, 1, 1, 2, FILL, FILL);
188 table.attach (format, 0, 1, 2, 4, FILL, FILL);
189 table.attach (length, 0, 1, 4, 5, FILL, FILL);
190 table.attach (timecode, 0, 1, 5, 6, FILL, FILL);
191 table.attach (tempomap, 0, 1, 6, 7, FILL, FILL);
193 table.attach (channels_value, 1, 2, 0, 1, FILL, FILL);
194 table.attach (samplerate_value, 1, 2, 1, 2, FILL, FILL);
195 table.attach (format_text, 1, 2, 2, 4, FILL, FILL);
196 table.attach (length_clock, 1, 2, 4, 5, FILL, FILL);
197 table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL);
198 table.attach (tempomap_value, 1, 2, 6, 7, FILL, FILL);
200 length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock->mode());
201 timecode_clock.set_mode (AudioClock::Timecode);
203 main_box.pack_start (table, false, false);
205 tags_entry.set_editable (true);
206 tags_entry.set_wrap_mode(Gtk::WRAP_WORD);
207 tags_entry.signal_focus_out_event().connect (sigc::mem_fun (*this, &SoundFileBox::tags_entry_left));
209 Label* label = manage (new Label (_("Tags:")));
210 label->set_alignment (0.0f, 0.5f);
211 main_box.pack_start (*label, false, false);
212 main_box.pack_start (tags_entry, true, true);
214 main_box.pack_start (bottom_box, false, false);
216 play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
217 // play_btn.set_label (_("Play"));
219 stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
220 // stop_btn.set_label (_("Stop"));
222 bottom_box.set_homogeneous (false);
223 bottom_box.set_spacing (6);
224 bottom_box.pack_start(play_btn, true, true);
225 bottom_box.pack_start(stop_btn, true, true);
226 bottom_box.pack_start(autoplay_btn, false, false);
228 seek_slider.set_draw_value(false);
230 seek_slider.add_events(Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
231 seek_slider.signal_button_press_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_press), false);
232 seek_slider.signal_button_release_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_release), false);
233 main_box.pack_start (seek_slider, false, false);
235 play_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::audition));
236 stop_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::stop_audition));
238 stop_btn.set_sensitive (false);
240 channels_value.set_alignment (0.0f, 0.5f);
241 samplerate_value.set_alignment (0.0f, 0.5f);
245 SoundFileBox::set_session(Session* s)
247 SessionHandlePtr::set_session (s);
249 length_clock.set_session (s);
250 timecode_clock.set_session (s);
253 play_btn.set_sensitive (false);
254 stop_btn.set_sensitive (false);
255 auditioner_connections.drop_connections();
257 auditioner_connections.drop_connections();
258 _session->AuditionActive.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_active, this, _1), gui_context());
259 _session->the_auditioner()->AuditionProgress.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_progress, this, _1, _2), gui_context());
264 SoundFileBox::audition_active(bool active) {
265 stop_btn.set_sensitive (active);
266 seek_slider.set_sensitive (active);
268 seek_slider.set_value(0);
273 SoundFileBox::audition_progress(ARDOUR::framecnt_t pos, ARDOUR::framecnt_t len) {
275 seek_slider.set_value( 1000.0 * pos / len);
276 seek_slider.set_sensitive (true);
281 SoundFileBox::seek_button_press(GdkEventButton*) {
283 return false; // pass on to slider
287 SoundFileBox::seek_button_release(GdkEventButton*) {
289 _session->the_auditioner()->seek_to_percent(seek_slider.get_value() / 10.0);
290 seek_slider.set_sensitive (false);
291 return false; // pass on to slider
295 SoundFileBox::setup_labels (const string& filename)
298 // save existing tags
306 if (SMFSource::valid_midi_file (path)) {
308 boost::shared_ptr<SMFSource> ms;
310 ms = boost::dynamic_pointer_cast<SMFSource> (
311 SourceFactory::createExternal (DataType::MIDI, *_session,
312 path, 0, Source::Flag (0), false));
313 } catch (const std::exception& e) {
314 error << string_compose(_("Could not read file: %1 (%2)."),
315 path, e.what()) << endmsg;
318 preview_label.set_markup (_("<b>Midi File Information</b>"));
320 format_text.set_text ("MIDI");
321 samplerate_value.set_text ("-");
322 tags_entry.get_buffer()->set_text ("");
323 timecode_clock.set (0);
324 tags_entry.set_sensitive (false);
327 if (ms->is_type0()) {
328 channels_value.set_text (to_string(ms->channels().size(), std::dec));
330 if (ms->num_tracks() > 1) {
331 channels_value.set_text (to_string(ms->num_tracks(), std::dec) + _("(Tracks)"));
333 channels_value.set_text (to_string(ms->num_tracks(), std::dec));
336 length_clock.set (ms->length(ms->timeline_position()));
337 switch (ms->num_tempos()) {
339 tempomap_value.set_text (_("No tempo data"));
342 Evoral::SMF::Tempo* t = ms->nth_tempo (0);
344 tempomap_value.set_text (string_compose (_("%1/%2 \u2669 = %3"),
347 (1000000 / t->microseconds_per_quarter_note) * 60));
351 tempomap_value.set_text (string_compose (_("map with %1 sections"),
356 channels_value.set_text ("");
357 length_clock.set (0);
358 tempomap_value.set_text (_("No tempo data"));
361 if (_session && ms) {
362 play_btn.set_sensitive (true);
364 play_btn.set_sensitive (false);
370 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
372 preview_label.set_markup (_("<b>Sound File Information</b>"));
373 format_text.set_text ("");
374 channels_value.set_text ("");
375 samplerate_value.set_text ("");
376 tags_entry.get_buffer()->set_text ("");
378 length_clock.set (0);
379 timecode_clock.set (0);
381 tags_entry.set_sensitive (false);
382 play_btn.set_sensitive (false);
387 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::Markup::escape_text (Glib::path_get_basename (filename))));
388 std::string n = sf_info.format_name;
389 if (n.substr (0, 8) == X_("Format: ")) {
392 format_text.set_text (n);
393 channels_value.set_text (to_string (sf_info.channels, std::dec));
395 if (_session && sf_info.samplerate != _session->frame_rate()) {
396 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
397 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
398 samplerate_value.set_name ("NewSessionSR1Label");
399 samplerate.set_name ("NewSessionSR1Label");
401 samplerate.set_text (_("Sample rate:"));
402 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
403 samplerate_value.set_name ("NewSessionSR2Label");
404 samplerate.set_name ("NewSessionSR2Label");
407 framecnt_t const nfr = _session ? _session->nominal_frame_rate() : 25;
408 double src_coef = (double) nfr / sf_info.samplerate;
410 length_clock.set (sf_info.length * src_coef + 0.5, true);
411 timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
413 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
415 vector<string> tags = Library->get_tags (string ("//") + filename);
417 stringstream tag_string;
418 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
419 if (i != tags.begin()) {
424 tags_entry.get_buffer()->set_text (tag_string.str());
426 tags_entry.set_sensitive (true);
428 play_btn.set_sensitive (true);
435 SoundFileBox::autoplay() const
437 return autoplay_btn.get_active();
441 SoundFileBox::audition_oneshot()
448 SoundFileBox::audition ()
454 _session->cancel_audition();
456 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
457 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
461 boost::shared_ptr<Region> r;
463 if (SMFSource::valid_midi_file (path)) {
465 boost::shared_ptr<SMFSource> ms =
466 boost::dynamic_pointer_cast<SMFSource> (
467 SourceFactory::createExternal (DataType::MIDI, *_session,
468 path, 0, Source::Flag (0), false));
470 string rname = region_name_from_path (ms->path(), false);
474 plist.add (ARDOUR::Properties::start, 0);
475 plist.add (ARDOUR::Properties::length, ms->length(ms->timeline_position()));
476 plist.add (ARDOUR::Properties::name, rname);
477 plist.add (ARDOUR::Properties::layer, 0);
479 r = boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (boost::dynamic_pointer_cast<Source>(ms), plist, false));
485 boost::shared_ptr<AudioFileSource> afs;
486 bool old_sbp = AudioSource::get_build_peakfiles ();
488 /* don't even think of building peakfiles for these files */
490 AudioSource::set_build_peakfiles (false);
492 for (int n = 0; n < sf_info.channels; ++n) {
494 afs = boost::dynamic_pointer_cast<AudioFileSource> (
495 SourceFactory::createExternal (DataType::AUDIO, *_session,
497 Source::Flag (ARDOUR::AudioFileSource::NoPeakFile), false));
498 if (afs->sample_rate() != _session->nominal_frame_rate()) {
499 boost::shared_ptr<SrcFileSource> sfs (new SrcFileSource(*_session, afs, _src_quality));
500 srclist.push_back(sfs);
502 srclist.push_back(afs);
505 } catch (failed_constructor& err) {
506 error << _("Could not access soundfile: ") << path << endmsg;
507 AudioSource::set_build_peakfiles (old_sbp);
512 AudioSource::set_build_peakfiles (old_sbp);
514 if (srclist.empty()) {
518 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
519 string rname = region_name_from_path (afs->path(), false);
523 plist.add (ARDOUR::Properties::start, 0);
524 plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->timeline_position()));
525 plist.add (ARDOUR::Properties::name, rname);
526 plist.add (ARDOUR::Properties::layer, 0);
528 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false));
531 frameoffset_t audition_position = 0;
532 switch(_import_position) {
533 case ImportAtTimestamp:
534 audition_position = 0;
536 case ImportAtPlayhead:
537 audition_position = _session->transport_frame();
540 audition_position = _session->current_start_frame();
542 case ImportAtEditPoint:
543 audition_position = PublicEditor::instance().get_preferred_edit_position ();
546 r->set_position(audition_position);
548 _session->audition_region(r);
552 SoundFileBox::stop_audition ()
555 _session->cancel_audition();
560 SoundFileBox::tags_entry_left (GdkEventFocus *)
567 SoundFileBox::tags_changed ()
569 string tag_string = tags_entry.get_buffer()->get_text ();
571 if (tag_string.empty()) {
577 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
578 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
586 SoundFileBox::save_tags (const vector<string>& tags)
588 Library->set_tags (string ("//") + path, tags);
589 Library->save_changes ();
592 SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persistent)
593 : ArdourWindow (title)
594 , found_list (ListStore::create(found_list_columns))
595 , freesound_list (ListStore::create(freesound_list_columns))
596 , chooser (FILE_CHOOSER_ACTION_OPEN)
597 , preview (persistent)
598 , found_search_btn (_("Search"))
599 , found_list_view (found_list)
600 , freesound_search_btn (_("Search"))
601 , freesound_list_view (freesound_list)
602 , resetting_ourselves (false)
606 , import_button (_("Import"))
607 , close_button (Stock::CLOSE)
613 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
614 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
615 chooser.add_shortcut_folder_uri("file:///Library/Audio/Apple Loops");
616 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
618 catch (Glib::Error & e) {
619 std::cerr << "sfdb.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
622 Gtkmm2ext::add_volume_shortcuts (chooser);
624 //add the file chooser
626 chooser.set_border_width (12);
628 audio_and_midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun (*this, &SoundFileBrowser::on_audio_and_midi_filter));
629 audio_and_midi_filter.set_name (_("Audio and MIDI files"));
631 audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
632 audio_filter.set_name (_("Audio files"));
634 midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
635 midi_filter.set_name (_("MIDI files"));
637 matchall_filter.add_pattern ("*.*");
638 matchall_filter.set_name (_("All files"));
640 chooser.add_filter (audio_and_midi_filter);
641 chooser.add_filter (audio_filter);
642 chooser.add_filter (midi_filter);
643 chooser.add_filter (matchall_filter);
644 chooser.set_select_multiple (true);
645 chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
646 chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
649 /* some broken redraw behaviour - this is a bandaid */
650 chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
653 if (!persistent_folder.empty()) {
654 chooser.set_current_folder (persistent_folder);
657 notebook.append_page (chooser, _("Browse Files"));
659 hpacker.set_spacing (6);
660 hpacker.pack_start (notebook, true, true);
661 hpacker.pack_start (preview, false, false);
663 vpacker.set_spacing (6);
664 vpacker.pack_start (hpacker, true, true);
674 hbox = manage(new HBox);
675 hbox->pack_start (found_entry);
676 hbox->pack_start (found_search_btn);
678 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
679 scroll->add(found_list_view);
680 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
682 vbox = manage(new VBox);
683 vbox->pack_start (*hbox, PACK_SHRINK);
684 vbox->pack_start (*scroll);
686 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
688 found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
690 found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
692 found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
693 found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
695 notebook.append_page (*vbox, _("Search Tags"));
697 //add freesound search
698 #ifdef FREESOUND_GOT_FIXED
703 passbox = manage(new HBox);
704 passbox->set_spacing (6);
706 label = manage (new Label);
707 label->set_text (_("Tags:"));
708 passbox->pack_start (*label, false, false);
709 passbox->pack_start (freesound_entry, true, true);
711 label = manage (new Label);
712 label->set_text (_("Sort:"));
713 passbox->pack_start (*label, false, false);
714 passbox->pack_start (freesound_sort, false, false);
715 freesound_sort.clear_items();
717 // Order of the following must correspond with enum sortMethod
718 // in sfdb_freesound_mootcher.h
719 freesound_sort.append_text(_("None"));
720 freesound_sort.append_text(_("Longest"));
721 freesound_sort.append_text(_("Shortest"));
722 freesound_sort.append_text(_("Newest"));
723 freesound_sort.append_text(_("Oldest"));
724 freesound_sort.append_text(_("Most downloaded"));
725 freesound_sort.append_text(_("Least downloaded"));
726 freesound_sort.append_text(_("Highest rated"));
727 freesound_sort.append_text(_("Lowest rated"));
728 freesound_sort.set_active(0);
730 passbox->pack_start (freesound_search_btn, false, false);
731 passbox->pack_start (freesound_more_btn, false, false);
732 freesound_more_btn.set_label(_("More"));
733 freesound_more_btn.set_sensitive(false);
735 passbox->pack_start (freesound_similar_btn, false, false);
736 freesound_similar_btn.set_label(_("Similar"));
737 freesound_similar_btn.set_sensitive(false);
739 scroll = manage(new ScrolledWindow);
740 scroll->add(freesound_list_view);
741 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
743 vbox = manage(new VBox);
744 vbox->set_spacing (3);
745 vbox->pack_start (*passbox, PACK_SHRINK);
746 vbox->pack_start (*scroll);
748 freesound_list_view.append_column(_("ID") , freesound_list_columns.id);
749 freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
750 // freesound_list_view.append_column(_("URI") , freesound_list_columns.uri);
751 freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
752 freesound_list_view.append_column(_("Size"), freesound_list_columns.filesize);
753 freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
754 freesound_list_view.append_column(_("License"), freesound_list_columns.license);
755 freesound_list_view.get_column(0)->set_alignment(0.5);
756 freesound_list_view.get_column(1)->set_expand(true); // filename
757 freesound_list_view.get_column(1)->set_resizable(true); // filename
758 freesound_list_view.get_column(2)->set_alignment(0.5);
759 freesound_list_view.get_column(3)->set_alignment(0.5);
760 freesound_list_view.get_column(4)->set_alignment(0.5);
761 freesound_list_view.get_column(5)->set_alignment(0.5);
763 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
764 freesound_list_view.set_tooltip_column(1);
766 freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
767 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
768 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
769 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
770 freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
771 freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
772 notebook.append_page (*vbox, _("Search Freesound"));
775 notebook.set_size_request (500, -1);
776 notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
780 Gtk::HButtonBox* button_box = manage (new HButtonBox);
782 button_box->set_layout (BUTTONBOX_END);
783 button_box->pack_start (close_button, false, false);
784 close_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_CLOSE));
786 button_box->pack_start (import_button, false, false);
787 import_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_OK));
789 Gtkmm2ext::UI::instance()->set_tip (import_button, _("Press to import selected files"));
790 Gtkmm2ext::UI::instance()->set_tip (close_button, _("Press to close this window without importing any files"));
792 vpacker.pack_end (*button_box, false, false);
794 set_wmclass (X_("import"), PROGRAM_NAME);
797 SoundFileBrowser::~SoundFileBrowser ()
799 persistent_folder = chooser.get_current_folder();
803 SoundFileBrowser::run ()
812 gtk_main_iteration ();
819 SoundFileBrowser::set_action_sensitive (bool yn)
821 import_button.set_sensitive (yn);
825 SoundFileBrowser::do_something (int action)
832 SoundFileBrowser::on_show ()
834 ArdourWindow::on_show ();
839 SoundFileBrowser::clear_selection ()
841 chooser.unselect_all ();
842 found_list_view.get_selection()->unselect_all ();
846 SoundFileBrowser::chooser_file_activated ()
852 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
858 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
864 SoundFileBrowser::set_session (Session* s)
866 ArdourWindow::set_session (s);
867 preview.set_session (s);
872 remove_gain_meter ();
877 SoundFileBrowser::add_gain_meter ()
881 gm = new GainMeter (_session, 250);
883 boost::shared_ptr<Route> r = _session->the_auditioner ();
885 gm->set_controls (r, r->shared_peak_meter(), r->amp(), r->gain_control());
886 gm->set_fader_name (X_("GainFader"));
888 meter_packer.set_border_width (12);
889 meter_packer.pack_start (*gm, false, true);
890 hpacker.pack_end (meter_packer, false, false);
891 meter_packer.show_all ();
896 SoundFileBrowser::remove_gain_meter ()
899 meter_packer.remove (*gm);
900 hpacker.remove (meter_packer);
907 SoundFileBrowser::start_metering ()
909 metering_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
913 SoundFileBrowser::stop_metering ()
915 metering_connection.disconnect();
919 SoundFileBrowser::meter ()
921 if (is_mapped () && _session && gm) {
922 gm->update_meters ();
927 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
929 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
933 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
935 return SMFSource::safe_midi_file_extension (filter_info.filename);
939 SoundFileBrowser::on_audio_and_midi_filter (const FileFilter::Info& filter_info)
941 return on_audio_filter (filter_info) || on_midi_filter (filter_info);
945 SoundFileBrowser::update_preview ()
947 if (preview.setup_labels (chooser.get_preview_filename())) {
948 if (preview.autoplay()) {
949 Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
955 SoundFileBrowser::found_list_view_selected ()
957 if (!reset_options ()) {
958 set_action_sensitive (false);
962 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
965 TreeIter iter = found_list->get_iter(*rows.begin());
966 file = (*iter)[found_list_columns.pathname];
967 chooser.set_filename (file);
968 set_action_sensitive (true);
970 set_action_sensitive (false);
973 preview.setup_labels (file);
978 SoundFileBrowser::found_search_clicked ()
980 string tag_string = found_entry.get_text ();
984 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
985 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
989 vector<string> results;
990 Library->search_members_and (results, tags);
993 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
994 TreeModel::iterator new_row = found_list->append();
995 TreeModel::Row row = *new_row;
996 string path = Glib::filename_from_uri (string ("file:") + *i);
997 row[found_list_columns.pathname] = path;
1003 SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
1006 Mootcher *mootcher = new Mootcher;
1009 string id = (*iter)[freesound_list_columns.id];
1010 string uri = (*iter)[freesound_list_columns.uri];
1011 string ofn = (*iter)[freesound_list_columns.filename];
1013 if (mootcher->checkAudioFile(ofn, id)) {
1014 // file already exists, no need to download it again
1015 file = mootcher->audioFileName;
1017 (*iter)[freesound_list_columns.started] = false;
1020 if (!(*iter)[freesound_list_columns.started]) {
1021 // start downloading the sound file
1022 (*iter)[freesound_list_columns.started] = true;
1023 mootcher->fetchAudioFile(ofn, id, uri, this);
1029 SoundFileBrowser::freesound_list_view_selected ()
1032 if (!reset_options ()) {
1033 set_action_sensitive (false);
1036 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1037 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1038 file = freesound_get_audio_file (freesound_list->get_iter(*i));
1041 switch (rows.size()) {
1044 freesound_similar_btn.set_sensitive(false);
1045 set_action_sensitive (false);
1048 // exactly one item selected
1050 // file exists on disk already
1051 chooser.set_filename (file);
1052 preview.setup_labels (file);
1053 set_action_sensitive (true);
1055 freesound_similar_btn.set_sensitive(true);
1058 // multiple items selected
1059 preview.setup_labels ("");
1060 freesound_similar_btn.set_sensitive(false);
1068 SoundFileBrowser::refresh_display(std::string ID, std::string file)
1070 // called when the mootcher has finished downloading a file
1071 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1072 if (rows.size() == 1) {
1073 // there's a single item selected in the freesound list
1074 //XXX make a function to be used to construct the actual file name both here and in the mootcher
1075 Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
1076 std::string selected_ID = (*row)[freesound_list_columns.id];
1077 if (ID == selected_ID) {
1078 // the selected item in the freesound list is the item that has just finished downloading
1079 chooser.set_filename(file);
1080 preview.setup_labels (file);
1081 set_action_sensitive (true);
1087 SoundFileBrowser::freesound_search_clicked ()
1090 freesound_list->clear();
1096 SoundFileBrowser::freesound_more_clicked ()
1101 snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
1102 freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
1106 SoundFileBrowser::freesound_similar_clicked ()
1108 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1109 if (rows.size() == 1) {
1112 Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
1113 id = (*iter)[freesound_list_columns.id];
1114 freesound_list->clear();
1116 GdkCursor *prev_cursor;
1117 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1118 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1121 std::string theString = mootcher.searchSimilar(id);
1123 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1124 handle_freesound_results(theString);
1129 SoundFileBrowser::freesound_search()
1133 string search_string = freesound_entry.get_text ();
1134 enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
1136 GdkCursor *prev_cursor;
1137 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1138 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1141 std::string theString = mootcher.searchText(
1145 "", // OSX eats anything incl mp3
1147 "type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
1152 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1153 handle_freesound_results(theString);
1157 SoundFileBrowser::handle_freesound_results(std::string theString) {
1159 doc.read_buffer( theString );
1160 XMLNode *root = doc.root();
1163 error << "no root XML node!" << endmsg;
1167 if ( strcmp(root->name().c_str(), "response") != 0) {
1168 error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
1172 // find out how many pages are available to search
1173 int freesound_n_pages = 1;
1174 XMLNode *res = root->child("num_pages");
1176 string result = res->child("text")->content();
1177 freesound_n_pages = atoi(result);
1180 int more_pages = freesound_n_pages - freesound_page;
1182 if (more_pages > 0) {
1183 freesound_more_btn.set_sensitive(true);
1184 freesound_more_btn.set_tooltip_text(string_compose(P_(
1185 "%1 more page of 100 results available",
1186 "%1 more pages of 100 results available",
1187 more_pages), more_pages));
1189 freesound_more_btn.set_sensitive(false);
1190 freesound_more_btn.set_tooltip_text(_("No more results available"));
1193 XMLNode *sounds_root = root->child("sounds");
1195 error << "no child node \"sounds\" found!" << endmsg;
1199 XMLNodeList sounds = sounds_root->children();
1200 if (sounds.size() == 0) {
1205 XMLNodeConstIterator niter;
1207 for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
1209 if( strcmp( node->name().c_str(), "resource") != 0 ) {
1210 error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
1214 // node->dump(cerr, "node:");
1217 XMLNode *id_node = node->child ("id");
1218 XMLNode *uri_node = node->child ("serve");
1219 XMLNode *ofn_node = node->child ("original_filename");
1220 XMLNode *dur_node = node->child ("duration");
1221 XMLNode *siz_node = node->child ("filesize");
1222 XMLNode *srt_node = node->child ("samplerate");
1223 XMLNode *lic_node = node->child ("license");
1225 if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
1227 std::string id = id_node->child("text")->content();
1228 std::string uri = uri_node->child("text")->content();
1229 std::string ofn = ofn_node->child("text")->content();
1230 std::string dur = dur_node->child("text")->content();
1231 std::string siz = siz_node->child("text")->content();
1232 std::string srt = srt_node->child("text")->content();
1233 std::string lic = lic_node->child("text")->content();
1236 // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
1238 double duration_seconds = atof(dur);
1240 char duration_hhmmss[16];
1241 if (duration_seconds >= 99 * 60 * 60) {
1242 strcpy(duration_hhmmss, ">99h");
1244 s = modf(duration_seconds/60, &m) * 60;
1245 m = modf(m/60, &h) * 60;
1246 sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
1251 double size_bytes = atof(siz);
1253 if (size_bytes < 1000) {
1254 sprintf(bsize, "%.0f %s", size_bytes, _("B"));
1255 } else if (size_bytes < 1000000 ) {
1256 sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
1257 } else if (size_bytes < 10000000) {
1258 sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
1259 } else if (size_bytes < 1000000000) {
1260 sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
1262 sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
1265 /* see http://www.freesound.org/help/faq/#licenses */
1266 char shortlicense[64];
1267 if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
1268 sprintf(shortlicense, "CC-BY-NC");
1269 } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
1270 sprintf(shortlicense, "CC-BY");
1271 } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
1272 sprintf(shortlicense, "sampling+");
1273 } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
1274 sprintf(shortlicense, "PD");
1276 snprintf(shortlicense, 64, "%s", lic.c_str());
1277 shortlicense[63]= '\0';
1280 TreeModel::iterator new_row = freesound_list->append();
1281 TreeModel::Row row = *new_row;
1283 row[freesound_list_columns.id ] = id;
1284 row[freesound_list_columns.uri ] = uri;
1285 row[freesound_list_columns.filename] = ofn;
1286 row[freesound_list_columns.duration] = duration_hhmmss;
1287 row[freesound_list_columns.filesize] = bsize;
1288 row[freesound_list_columns.smplrate] = srt;
1289 row[freesound_list_columns.license ] = shortlicense;
1296 SoundFileBrowser::get_paths ()
1298 vector<string> results;
1300 int n = notebook.get_current_page ();
1303 vector<string> filenames = chooser.get_filenames();
1304 vector<string>::iterator i;
1306 for (i = filenames.begin(); i != filenames.end(); ++i) {
1308 if ((!g_stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
1309 results.push_back (*i);
1313 } else if (n == 1) {
1315 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1316 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1317 TreeIter iter = found_list->get_iter(*i);
1318 string str = (*iter)[found_list_columns.pathname];
1320 results.push_back (str);
1323 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1324 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1325 string str = freesound_get_audio_file (freesound_list->get_iter(*i));
1327 results.push_back (str);
1336 SoundFileOmega::reset_options_noret ()
1338 if (!resetting_ourselves) {
1339 (void) reset_options ();
1344 SoundFileOmega::reset_options ()
1346 if (_import_active) {
1347 _reset_post_import = true;
1351 vector<string> paths = get_paths ();
1353 if (paths.empty()) {
1355 channel_combo.set_sensitive (false);
1356 action_combo.set_sensitive (false);
1357 where_combo.set_sensitive (false);
1358 copy_files_btn.set_active (true);
1359 copy_files_btn.set_sensitive (false);
1365 channel_combo.set_sensitive (true);
1366 action_combo.set_sensitive (true);
1367 where_combo.set_sensitive (true);
1369 /* if we get through this function successfully, this may be
1370 reset at the end, once we know if we can use hard links
1371 to do embedding (or if we are importing a MIDI file).
1374 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1375 copy_files_btn.set_sensitive (false);
1377 copy_files_btn.set_sensitive (false);
1383 bool selection_includes_multichannel;
1384 bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1387 /* See if we are thinking about importing any MIDI files */
1388 vector<string>::iterator i = paths.begin ();
1389 while (i != paths.end() && SMFSource::valid_midi_file (*i) == false) {
1392 bool const have_a_midi_file = (i != paths.end ());
1394 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1395 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1399 if (have_a_midi_file) {
1400 smf_tempo_btn.show ();
1402 smf_tempo_btn.hide ();
1405 string existing_choice;
1406 vector<string> action_strings;
1408 resetting_ourselves = true;
1410 if (chooser.get_filter() == &audio_filter) {
1414 if (selected_audio_track_cnt > 0) {
1415 if (channel_combo.get_active_text().length()) {
1416 ImportDisposition id = get_channel_disposition();
1419 case Editing::ImportDistinctFiles:
1420 if (selected_audio_track_cnt == paths.size()) {
1421 action_strings.push_back (importmode2string (ImportToTrack));
1425 case Editing::ImportDistinctChannels:
1426 /* XXX it would be nice to allow channel-per-selected track
1427 but its too hard we don't want to deal with all the
1428 different per-file + per-track channel configurations.
1433 action_strings.push_back (importmode2string (ImportToTrack));
1443 if (selected_midi_track_cnt > 0) {
1444 action_strings.push_back (importmode2string (ImportToTrack));
1448 action_strings.push_back (importmode2string (ImportAsTrack));
1449 action_strings.push_back (importmode2string (ImportAsRegion));
1450 if (!Profile->get_mixbus()) {
1451 action_strings.push_back (importmode2string (ImportAsTapeTrack));
1454 existing_choice = action_combo.get_active_text();
1456 set_popdown_strings (action_combo, action_strings);
1458 /* preserve any existing choice, if possible */
1461 if (existing_choice.length()) {
1462 vector<string>::iterator x;
1463 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1464 if (*x == existing_choice) {
1465 action_combo.set_active_text (existing_choice);
1469 if (x == action_strings.end()) {
1470 action_combo.set_active_text (action_strings.front());
1473 action_combo.set_active_text (action_strings.front());
1476 resetting_ourselves = false;
1478 if ((mode = get_mode()) == ImportAsRegion) {
1479 where_combo.set_sensitive (false);
1481 where_combo.set_sensitive (true);
1484 vector<string> channel_strings;
1486 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1488 if (selection_includes_multichannel) {
1489 channel_strings.push_back (_("one track per channel"));
1492 channel_strings.push_back (_("one track per file"));
1494 if (paths.size() > 1) {
1495 /* tape tracks are a single region per track, so we cannot
1496 sequence multiple files.
1498 if (mode != ImportAsTapeTrack) {
1499 channel_strings.push_back (_("sequence files"));
1502 channel_strings.push_back (_("all files in one track"));
1503 channel_strings.push_back (_("merge files"));
1509 channel_strings.push_back (_("one region per file"));
1511 if (selection_includes_multichannel) {
1512 channel_strings.push_back (_("one region per channel"));
1515 if (paths.size() > 1) {
1517 channel_strings.push_back (_("all files in one region"));
1522 resetting_ourselves = true;
1524 existing_choice = channel_combo.get_active_text();
1526 set_popdown_strings (channel_combo, channel_strings);
1528 /* preserve any existing choice, if possible */
1530 if (existing_choice.length()) {
1531 vector<string>::iterator x;
1532 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1533 if (*x == existing_choice) {
1534 channel_combo.set_active_text (existing_choice);
1538 if (x == channel_strings.end()) {
1539 channel_combo.set_active_text (channel_strings.front());
1542 channel_combo.set_active_text (channel_strings.front());
1545 resetting_ourselves = false;
1548 src_combo.set_sensitive (true);
1550 src_combo.set_sensitive (false);
1553 /* We must copy MIDI files or those from Freesound
1554 * or any file if we are under nsm control */
1555 bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
1557 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1559 if (selection_can_be_embedded_with_links && !must_copy) {
1560 copy_files_btn.set_sensitive (true);
1563 copy_files_btn.set_active (true);
1565 copy_files_btn.set_sensitive (false);
1571 copy_files_btn.set_active (true);
1573 copy_files_btn.set_sensitive (!must_copy);
1581 SoundFileOmega::bad_file_message()
1583 MessageDialog msg (*this,
1584 string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1589 resetting_ourselves = true;
1590 chooser.unselect_uri (chooser.get_preview_uri());
1591 resetting_ourselves = false;
1597 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1606 multichannel = false;
1608 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1610 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1611 if (info.channels > 1) {
1612 multichannel = true;
1617 if (sz != info.length) {
1622 if (info.samplerate != _session->frame_rate()) {
1626 } else if (SMFSource::valid_midi_file (*i)) {
1630 if (reader.open (*i)) {
1633 if (reader.is_type0 ()) {
1634 if (reader.channels().size() > 1) {
1635 /* for type-0 files, we can split
1636 * "one track per channel"
1638 multichannel = true;
1641 if (reader.num_tracks() > 1) {
1642 multichannel = true;
1657 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1659 #ifdef PLATFORM_WINDOWS
1662 std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
1665 if (g_mkdir (tmpdir.c_str(), 0744)) {
1666 if (errno != EEXIST) {
1671 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1673 char tmpc[PATH_MAX+1];
1675 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1679 if (link ((*i).c_str(), tmpc)) {
1689 g_rmdir (tmpdir.c_str());
1694 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
1695 : SoundFileBrowser (title, s, false)
1697 chooser.set_select_multiple (false);
1698 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1699 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1703 SoundFileChooser::on_hide ()
1705 ArdourWindow::on_hide();
1709 _session->cancel_audition();
1714 SoundFileChooser::get_filename ()
1716 vector<string> paths;
1718 paths = get_paths ();
1720 if (paths.empty()) {
1724 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1728 return paths.front();
1731 SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s,
1732 uint32_t selected_audio_tracks,
1733 uint32_t selected_midi_tracks,
1735 Editing::ImportMode mode_hint)
1736 : SoundFileBrowser (title, s, persistent)
1737 , copy_files_btn ( _("Copy files to session"))
1738 , smf_tempo_btn (_("Use MIDI Tempo Map (if defined)"))
1739 , selected_audio_track_cnt (selected_audio_tracks)
1740 , selected_midi_track_cnt (selected_midi_tracks)
1741 , _import_active (false)
1742 , _reset_post_import (false)
1746 set_size_request (-1, 550);
1748 block_two.set_border_width (12);
1749 block_three.set_border_width (12);
1750 block_four.set_border_width (12);
1753 str.push_back (_("file timestamp"));
1754 str.push_back (_("edit point"));
1755 str.push_back (_("playhead"));
1756 str.push_back (_("session start"));
1757 set_popdown_strings (where_combo, str);
1758 where_combo.set_active_text (str.back());
1759 where_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::where_combo_changed));
1761 Label* l = manage (new Label);
1762 l->set_markup (_("<b>Add files ...</b>"));
1763 options.attach (*l, 0, 1, 0, 1, FILL, SHRINK, 8, 0);
1764 options.attach (action_combo, 0, 1, 1, 2, FILL, SHRINK, 8, 0);
1766 l = manage (new Label);
1767 l->set_markup (_("<b>Insert at</b>"));
1768 options.attach (*l, 0, 1, 3, 4, FILL, SHRINK, 8, 0);
1769 options.attach (where_combo, 0, 1, 4, 5, FILL, SHRINK, 8, 0);
1771 l = manage (new Label);
1772 l->set_markup (_("<b>Mapping</b>"));
1773 options.attach (*l, 1, 2, 0, 1, FILL, SHRINK, 8, 0);
1774 options.attach (channel_combo, 1, 2, 1, 2, FILL, SHRINK, 8, 0);
1776 l = manage (new Label);
1777 l->set_markup (_("<b>Conversion quality</b>"));
1778 options.attach (*l, 1, 2, 3, 4, FILL, SHRINK, 8, 0);
1779 options.attach (src_combo, 1, 2, 4, 5, FILL, SHRINK, 8, 0);
1781 l = manage (new Label);
1782 l->set_markup (_("<b>MIDI Track Names</b>"));
1783 options.attach (*l, 2, 3, 0, 1, FILL, SHRINK, 8, 0);
1784 options.attach (midi_track_name_combo, 2, 3, 1, 2, FILL, SHRINK, 8, 0);
1786 options.attach (smf_tempo_btn, 2, 3, 3, 4, FILL, SHRINK, 8, 0);
1788 l = manage (new Label);
1789 l->set_markup (_("<b>Instrument</b>"));
1790 options.attach (*l, 3, 4, 0, 1, FILL, SHRINK, 8, 0);
1791 options.attach (instrument_combo, 3, 4, 1, 2, FILL, SHRINK, 8, 0);
1793 Alignment *hspace = manage (new Alignment ());
1794 hspace->set_size_request (2, 2);
1795 options.attach (*hspace, 0, 3, 2, 3, FILL, SHRINK, 0, 8);
1797 Alignment *vspace = manage (new Alignment ());
1798 vspace->set_size_request (2, 2);
1799 options.attach (*vspace, 2, 3, 0, 3, EXPAND, SHRINK, 0, 0);
1802 str.push_back (_("by track number"));
1803 str.push_back (_("by track name"));
1804 str.push_back (_("by instrument name"));
1805 set_popdown_strings (midi_track_name_combo, str);
1806 midi_track_name_combo.set_active_text (str.front());
1809 str.push_back (_("one track per file"));
1810 set_popdown_strings (channel_combo, str);
1811 channel_combo.set_active_text (str.front());
1812 channel_combo.set_sensitive (false);
1815 str.push_back (_("Best"));
1816 str.push_back (_("Good"));
1817 str.push_back (_("Quick"));
1818 str.push_back (_("Fast"));
1819 str.push_back (_("Fastest"));
1821 set_popdown_strings (src_combo, str);
1822 src_combo.set_active_text (str.front());
1823 src_combo.set_sensitive (false);
1824 src_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::src_combo_changed));
1826 action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1827 channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1829 copy_files_btn.set_active (true);
1831 Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1834 copy_label->set_size_request (175, -1);
1835 copy_label->set_line_wrap (true);
1838 block_four.pack_start (copy_files_btn, false, false);
1839 options.attach (block_four, 3, 4, 4, 5, FILL, SHRINK, 8, 0);
1841 vpacker.pack_start (options, false, true);
1843 /* setup disposition map */
1845 disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1846 disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1847 disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1848 disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1850 disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1851 disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1852 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1853 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1855 chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1857 /* set size requests for a couple of combos to allow them to display the longest text
1858 they will ever be asked to display. This prevents them being resized when the user
1859 selects a file to import, which in turn prevents the size of the dialog from jumping
1863 str.push_back (_("one track per file"));
1864 str.push_back (_("one track per channel"));
1865 str.push_back (_("sequence files"));
1866 str.push_back (_("all files in one region"));
1867 set_popdown_strings (channel_combo, str);
1870 str.push_back (importmode2string (ImportAsTrack));
1871 str.push_back (importmode2string (ImportToTrack));
1872 str.push_back (importmode2string (ImportAsRegion));
1873 str.push_back (importmode2string (ImportAsTapeTrack));
1874 set_popdown_strings (action_combo, str);
1875 action_combo.set_active_text (importmode2string(mode_hint));
1877 reset (selected_audio_tracks, selected_midi_tracks);
1881 SoundFileOmega::set_mode (ImportMode mode)
1883 action_combo.set_active_text (importmode2string (mode));
1887 SoundFileOmega::get_mode () const
1889 return string2importmode (action_combo.get_active_text());
1893 SoundFileOmega::on_hide ()
1895 ArdourWindow::on_hide();
1897 _session->cancel_audition();
1902 SoundFileOmega::get_position() const
1904 string str = where_combo.get_active_text();
1906 if (str == _("file timestamp")) {
1907 return ImportAtTimestamp;
1908 } else if (str == _("edit point")) {
1909 return ImportAtEditPoint;
1910 } else if (str == _("playhead")) {
1911 return ImportAtPlayhead;
1913 return ImportAtStart;
1918 SoundFileOmega::get_src_quality() const
1920 string str = src_combo.get_active_text();
1922 if (str == _("Best")) {
1924 } else if (str == _("Good")) {
1926 } else if (str == _("Quick")) {
1928 } else if (str == _("Fast")) {
1936 SoundFileOmega::src_combo_changed()
1938 preview.set_src_quality(get_src_quality());
1942 SoundFileOmega::where_combo_changed()
1944 preview.set_import_position(get_position());
1948 SoundFileOmega::get_midi_track_name_source () const
1950 return string2miditracknamesource (midi_track_name_combo.get_active_text());
1954 SoundFileOmega::get_use_smf_tempo_map () const
1956 return smf_tempo_btn.get_active ();
1960 SoundFileOmega::get_channel_disposition () const
1962 /* we use a map here because the channel combo can contain different strings
1963 depending on the state of the other combos. the map contains all possible strings
1964 and the ImportDisposition enum that corresponds to it.
1967 string str = channel_combo.get_active_text();
1968 DispositionMap::const_iterator x = disposition_map.find (str);
1970 if (x == disposition_map.end()) {
1971 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1972 abort(); /*NOTREACHED*/
1979 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
1981 selected_audio_track_cnt = selected_audio_tracks;
1982 selected_midi_track_cnt = selected_midi_tracks;
1984 if (selected_audio_track_cnt == 0 && selected_midi_track_cnt > 0) {
1985 chooser.set_filter (midi_filter);
1986 } else if (selected_midi_track_cnt == 0 && selected_audio_track_cnt > 0) {
1987 chooser.set_filter (audio_filter);
1989 chooser.set_filter (audio_and_midi_filter);
1996 SoundFileOmega::file_selection_changed ()
1998 if (resetting_ourselves) {
2002 if (!reset_options ()) {
2003 set_action_sensitive (false);
2005 if (chooser.get_filenames().size() > 0) {
2006 set_action_sensitive (true);
2008 set_action_sensitive (false);
2014 SoundFileOmega::do_something (int action)
2016 SoundFileBrowser::do_something (action);
2018 if (action == RESPONSE_CLOSE) {
2025 vector<string> paths = get_paths ();
2026 ImportPosition pos = get_position ();
2027 ImportMode mode = get_mode ();
2028 ImportDisposition chns = get_channel_disposition ();
2029 PluginInfoPtr instrument = instrument_combo.selected_instrument();
2031 MidiTrackNameSource mts = get_midi_track_name_source ();
2032 MidiTempoMapDisposition mtd = (get_use_smf_tempo_map () ? SMFTempoUse : SMFTempoIgnore);
2035 case ImportAtEditPoint:
2036 where = PublicEditor::instance().get_preferred_edit_position ();
2038 case ImportAtTimestamp:
2041 case ImportAtPlayhead:
2042 where = _session->transport_frame();
2045 where = _session->current_start_frame();
2049 SrcQuality quality = get_src_quality();
2051 _import_active = true;
2053 if (copy_files_btn.get_active()) {
2054 PublicEditor::instance().do_import (paths, chns, mode, quality, mts, mtd, where, instrument);
2056 PublicEditor::instance().do_embed (paths, chns, mode, where, instrument);
2059 _import_active = false;
2061 if (_reset_post_import) {
2062 _reset_post_import = false;