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/scrolledwindow.h>
35 #include <gtkmm/stock.h>
37 #include "pbd/gstdio_compat.h"
38 #include <glibmm/fileutils.h>
40 #include "pbd/tokenizer.h"
41 #include "pbd/enumwriter.h"
42 #include "pbd/pthread_utils.h"
43 #include "pbd/string_convert.h"
44 #include "pbd/xml++.h"
46 #include <gtkmm2ext/utils.h>
48 #include "evoral/SMF.hpp"
50 #include "ardour/audio_library.h"
51 #include "ardour/auditioner.h"
52 #include "ardour/audioregion.h"
53 #include "ardour/audiofilesource.h"
54 #include "ardour/midi_region.h"
55 #include "ardour/smf_source.h"
56 #include "ardour/region_factory.h"
57 #include "ardour/source_factory.h"
58 #include "ardour/session.h"
59 #include "ardour/session_directory.h"
60 #include "ardour/srcfilesource.h"
61 #include "ardour/profile.h"
63 #include "ardour_ui.h"
65 #include "gui_thread.h"
68 #include "gain_meter.h"
69 #include "main_clock.h"
70 #include "public_editor.h"
72 #include "ui_config.h"
74 #include "sfdb_freesound_mootcher.h"
76 using namespace ARDOUR;
80 using namespace Gtkmm2ext;
81 using namespace Editing;
85 string SoundFileBrowser::persistent_folder;
86 typedef TreeView::Selection::ListHandle_Path ListPath;
88 static MidiTrackNameSource
89 string2miditracknamesource (string const & str)
91 if (str == _("by track number")) {
92 return SMFTrackNumber;
93 } else if (str == _("by track name")) {
95 } else if (str == _("by instrument name")) {
96 return SMFInstrumentName;
99 warning << string_compose (_("programming error: unknown midi track name source string %1"), str) << endmsg;
101 return SMFTrackNumber;
105 string2importmode (string const & str)
107 if (str == _("as new tracks")) {
108 return ImportAsTrack;
109 } else if (str == _("to selected tracks")) {
110 return ImportToTrack;
111 } else if (str == _("to region list")) {
112 return ImportAsRegion;
113 } else if (str == _("as new tape tracks")) {
114 return ImportAsTapeTrack;
117 warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
119 return ImportAsTrack;
123 importmode2string (ImportMode mode)
127 return _("as new tracks");
129 return _("to selected tracks");
131 return _("to region list");
132 case ImportAsTapeTrack:
133 return _("as new tape tracks");
135 abort(); /*NOTREACHED*/
136 return _("as new tracks");
139 SoundFileBox::SoundFileBox (bool /*persistent*/)
141 length_clock ("sfboxLengthClock", true, "", false, false, true, false),
142 timecode_clock ("sfboxTimecodeClock", true, "", false, false, false, false),
144 autoplay_btn (_("Auto-play")),
145 seek_slider(0,1000,1),
147 _src_quality (SrcBest),
148 _import_position (ImportAtTimestamp)
151 set_name (X_("SoundFileBox"));
152 set_size_request (300, -1);
154 preview_label.set_markup (_("<b>Sound File Information</b>"));
156 border_frame.set_label_widget (preview_label);
157 border_frame.add (main_box);
159 pack_start (border_frame, true, true);
160 set_border_width (6);
162 main_box.set_border_width (6);
164 length.set_text (_("Length:"));
165 length.set_alignment (1, 0.5);
166 timecode.set_text (_("Timestamp:"));
167 timecode.set_alignment (1, 0.5);
168 format.set_text (_("Format:"));
169 format.set_alignment (1, 0.5);
170 channels.set_text (_("Channels:"));
171 channels.set_alignment (1, 0.5);
172 samplerate.set_text (_("Sample rate:"));
173 samplerate.set_alignment (1, 0.5);
174 tempomap.set_text (_("Tempo Map:"));
175 tempomap.set_alignment (1, 0.5);
177 preview_label.set_max_width_chars (50);
178 preview_label.set_ellipsize (Pango::ELLIPSIZE_END);
180 format_text.set_max_width_chars (20);
181 format_text.set_ellipsize (Pango::ELLIPSIZE_END);
182 format_text.set_alignment (0, 1);
184 table.set_col_spacings (6);
185 table.set_homogeneous (false);
186 table.set_row_spacings (6);
188 table.attach (channels, 0, 1, 0, 1, FILL, FILL);
189 table.attach (samplerate, 0, 1, 1, 2, FILL, FILL);
190 table.attach (format, 0, 1, 2, 4, FILL, FILL);
191 table.attach (length, 0, 1, 4, 5, FILL, FILL);
192 table.attach (timecode, 0, 1, 5, 6, FILL, FILL);
193 table.attach (tempomap, 0, 1, 6, 7, FILL, FILL);
195 table.attach (channels_value, 1, 2, 0, 1, FILL, FILL);
196 table.attach (samplerate_value, 1, 2, 1, 2, FILL, FILL);
197 table.attach (format_text, 1, 2, 2, 4, FILL, FILL);
198 table.attach (length_clock, 1, 2, 4, 5, FILL, FILL);
199 table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL);
200 table.attach (tempomap_value, 1, 2, 6, 7, FILL, FILL);
202 length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock->mode());
203 timecode_clock.set_mode (AudioClock::Timecode);
205 main_box.pack_start (table, false, false);
207 tags_entry.set_editable (true);
208 tags_entry.set_wrap_mode(Gtk::WRAP_WORD);
209 tags_entry.signal_focus_out_event().connect (sigc::mem_fun (*this, &SoundFileBox::tags_entry_left));
211 Label* label = manage (new Label (_("Tags:")));
212 label->set_alignment (0.0f, 0.5f);
213 main_box.pack_start (*label, false, false);
214 main_box.pack_start (tags_entry, true, true);
216 main_box.pack_start (bottom_box, false, false);
218 play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
219 // play_btn.set_label (_("Play"));
221 stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
222 // stop_btn.set_label (_("Stop"));
224 bottom_box.set_homogeneous (false);
225 bottom_box.set_spacing (6);
226 bottom_box.pack_start(play_btn, true, true);
227 bottom_box.pack_start(stop_btn, true, true);
228 bottom_box.pack_start(autoplay_btn, false, false);
230 seek_slider.set_draw_value(false);
232 seek_slider.add_events(Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
233 seek_slider.signal_button_press_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_press), false);
234 seek_slider.signal_button_release_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_release), false);
235 main_box.pack_start (seek_slider, false, false);
237 play_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::audition));
238 stop_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::stop_audition));
241 autoplay_btn.signal_toggled().connect(sigc::mem_fun (*this, &SoundFileBox::autoplay_toggled));
243 stop_btn.set_sensitive (false);
245 channels_value.set_alignment (0.0f, 0.5f);
246 samplerate_value.set_alignment (0.0f, 0.5f);
250 SoundFileBox::set_session(Session* s)
252 SessionHandlePtr::set_session (s);
254 length_clock.set_session (s);
255 timecode_clock.set_session (s);
258 play_btn.set_sensitive (false);
259 stop_btn.set_sensitive (false);
260 auditioner_connections.drop_connections();
262 auditioner_connections.drop_connections();
263 _session->AuditionActive.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_active, this, _1), gui_context());
264 _session->the_auditioner()->AuditionProgress.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_progress, this, _1, _2), gui_context());
269 SoundFileBox::audition_active(bool active) {
270 stop_btn.set_sensitive (active);
271 seek_slider.set_sensitive (active);
273 seek_slider.set_value(0);
278 SoundFileBox::audition_progress(ARDOUR::framecnt_t pos, ARDOUR::framecnt_t len) {
280 seek_slider.set_value( 1000.0 * pos / len);
281 seek_slider.set_sensitive (true);
286 SoundFileBox::seek_button_press(GdkEventButton*) {
288 return false; // pass on to slider
292 SoundFileBox::seek_button_release(GdkEventButton*) {
294 _session->the_auditioner()->seek_to_percent(seek_slider.get_value() / 10.0);
295 seek_slider.set_sensitive (false);
296 return false; // pass on to slider
300 SoundFileBox::setup_labels (const string& filename)
303 // save existing tags
311 if (SMFSource::valid_midi_file (path)) {
313 boost::shared_ptr<SMFSource> ms;
315 ms = boost::dynamic_pointer_cast<SMFSource> (
316 SourceFactory::createExternal (DataType::MIDI, *_session,
317 path, 0, Source::Flag (0), false));
318 } catch (const std::exception& e) {
319 error << string_compose(_("Could not read file: %1 (%2)."),
320 path, e.what()) << endmsg;
323 preview_label.set_markup (_("<b>Midi File Information</b>"));
325 format_text.set_text ("MIDI");
326 samplerate_value.set_text ("-");
327 tags_entry.get_buffer()->set_text ("");
328 timecode_clock.set (0);
329 tags_entry.set_sensitive (false);
332 if (ms->is_type0()) {
333 channels_value.set_text (to_string<uint32_t>(ms->channels().size()));
335 if (ms->num_tracks() > 1) {
336 channels_value.set_text (to_string(ms->num_tracks()) + _("(Tracks)"));
338 channels_value.set_text (to_string(ms->num_tracks()));
341 length_clock.set (ms->length(ms->timeline_position()));
342 switch (ms->num_tempos()) {
344 tempomap_value.set_text (_("No tempo data"));
347 Evoral::SMF::Tempo* t = ms->nth_tempo (0);
349 tempomap_value.set_text (string_compose (_("%1/%2 \u2669 = %3"),
356 tempomap_value.set_text (string_compose (_("map with %1 sections"),
361 channels_value.set_text ("");
362 length_clock.set (0);
363 tempomap_value.set_text (_("No tempo data"));
366 if (_session && ms) {
367 play_btn.set_sensitive (true);
369 play_btn.set_sensitive (false);
375 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
377 preview_label.set_markup (_("<b>Sound File Information</b>"));
378 format_text.set_text ("");
379 channels_value.set_text ("");
380 samplerate_value.set_text ("");
381 tags_entry.get_buffer()->set_text ("");
383 length_clock.set (0);
384 timecode_clock.set (0);
386 tags_entry.set_sensitive (false);
387 play_btn.set_sensitive (false);
392 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::Markup::escape_text (Glib::path_get_basename (filename))));
393 std::string n = sf_info.format_name;
394 if (n.substr (0, 8) == X_("Format: ")) {
397 format_text.set_text (n);
398 channels_value.set_text (to_string (sf_info.channels));
400 if (_session && sf_info.samplerate != _session->frame_rate()) {
401 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
402 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
403 samplerate_value.set_name ("NewSessionSR1Label");
404 samplerate.set_name ("NewSessionSR1Label");
406 samplerate.set_text (_("Sample rate:"));
407 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
408 samplerate_value.set_name ("NewSessionSR2Label");
409 samplerate.set_name ("NewSessionSR2Label");
412 framecnt_t const nfr = _session ? _session->nominal_frame_rate() : 25;
413 double src_coef = (double) nfr / sf_info.samplerate;
415 length_clock.set (sf_info.length * src_coef + 0.5, true);
416 timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
418 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
420 vector<string> tags = Library->get_tags (string ("//") + filename);
422 stringstream tag_string;
423 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
424 if (i != tags.begin()) {
429 tags_entry.get_buffer()->set_text (tag_string.str());
431 tags_entry.set_sensitive (true);
433 play_btn.set_sensitive (true);
440 SoundFileBox::update_autoplay ()
442 const bool config_autoplay = UIConfiguration::instance().get_autoplay_files();
444 if (autoplay_btn.get_active() != config_autoplay) {
445 autoplay_btn.set_active (config_autoplay);
450 SoundFileBox::autoplay_toggled()
452 UIConfiguration::instance().set_autoplay_files(autoplay_btn.get_active());
456 SoundFileBox::autoplay() const
458 return autoplay_btn.get_active();
462 SoundFileBox::audition_oneshot()
469 SoundFileBox::audition ()
475 _session->cancel_audition();
477 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
478 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
482 boost::shared_ptr<Region> r;
484 if (SMFSource::valid_midi_file (path)) {
486 boost::shared_ptr<SMFSource> ms =
487 boost::dynamic_pointer_cast<SMFSource> (
488 SourceFactory::createExternal (DataType::MIDI, *_session,
489 path, 0, Source::Flag (0), false));
491 string rname = region_name_from_path (ms->path(), false);
495 plist.add (ARDOUR::Properties::start, 0);
496 plist.add (ARDOUR::Properties::length, ms->length(ms->timeline_position()));
497 plist.add (ARDOUR::Properties::name, rname);
498 plist.add (ARDOUR::Properties::layer, 0);
500 r = boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (boost::dynamic_pointer_cast<Source>(ms), plist, false));
506 boost::shared_ptr<AudioFileSource> afs;
507 bool old_sbp = AudioSource::get_build_peakfiles ();
509 /* don't even think of building peakfiles for these files */
511 AudioSource::set_build_peakfiles (false);
513 for (int n = 0; n < sf_info.channels; ++n) {
515 afs = boost::dynamic_pointer_cast<AudioFileSource> (
516 SourceFactory::createExternal (DataType::AUDIO, *_session,
518 Source::Flag (ARDOUR::AudioFileSource::NoPeakFile), false));
519 if (afs->sample_rate() != _session->nominal_frame_rate()) {
520 boost::shared_ptr<SrcFileSource> sfs (new SrcFileSource(*_session, afs, _src_quality));
521 srclist.push_back(sfs);
523 srclist.push_back(afs);
526 } catch (failed_constructor& err) {
527 error << _("Could not access soundfile: ") << path << endmsg;
528 AudioSource::set_build_peakfiles (old_sbp);
533 AudioSource::set_build_peakfiles (old_sbp);
535 if (srclist.empty()) {
539 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
540 string rname = region_name_from_path (afs->path(), false);
544 plist.add (ARDOUR::Properties::start, 0);
545 plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->timeline_position()));
546 plist.add (ARDOUR::Properties::name, rname);
547 plist.add (ARDOUR::Properties::layer, 0);
549 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false));
552 frameoffset_t audition_position = 0;
553 switch(_import_position) {
554 case ImportAtTimestamp:
555 audition_position = 0;
557 case ImportAtPlayhead:
558 audition_position = _session->transport_frame();
561 audition_position = _session->current_start_frame();
563 case ImportAtEditPoint:
564 audition_position = PublicEditor::instance().get_preferred_edit_position ();
567 r->set_position(audition_position);
569 _session->audition_region(r);
573 SoundFileBox::stop_audition ()
576 _session->cancel_audition();
581 SoundFileBox::tags_entry_left (GdkEventFocus *)
588 SoundFileBox::tags_changed ()
590 string tag_string = tags_entry.get_buffer()->get_text ();
592 if (tag_string.empty()) {
598 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
599 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
607 SoundFileBox::save_tags (const vector<string>& tags)
609 Library->set_tags (string ("//") + path, tags);
610 Library->save_changes ();
613 SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persistent)
614 : ArdourWindow (title)
615 , found_list (ListStore::create(found_list_columns))
616 , freesound_list (ListStore::create(freesound_list_columns))
617 , chooser (FILE_CHOOSER_ACTION_OPEN)
618 , preview (persistent)
619 , found_search_btn (_("Search"))
620 , found_list_view (found_list)
621 , freesound_search_btn (_("Search"))
622 , freesound_list_view (freesound_list)
623 , resetting_ourselves (false)
627 , import_button (_("Import"))
633 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
634 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
635 chooser.add_shortcut_folder_uri("file:///Library/Audio/Apple Loops");
636 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
638 catch (Glib::Error & e) {
639 std::cerr << "sfdb.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
642 Gtkmm2ext::add_volume_shortcuts (chooser);
644 //add the file chooser
646 chooser.set_border_width (12);
648 audio_and_midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun (*this, &SoundFileBrowser::on_audio_and_midi_filter));
649 audio_and_midi_filter.set_name (_("Audio and MIDI files"));
651 audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
652 audio_filter.set_name (_("Audio files"));
654 midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
655 midi_filter.set_name (_("MIDI files"));
657 matchall_filter.add_pattern ("*.*");
658 matchall_filter.set_name (_("All files"));
660 chooser.add_filter (audio_and_midi_filter);
661 chooser.add_filter (audio_filter);
662 chooser.add_filter (midi_filter);
663 chooser.add_filter (matchall_filter);
664 chooser.set_select_multiple (true);
665 chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
666 chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
669 /* some broken redraw behaviour - this is a bandaid */
670 chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
673 if (!persistent_folder.empty()) {
674 chooser.set_current_folder (persistent_folder);
677 notebook.append_page (chooser, _("Browse Files"));
679 hpacker.set_spacing (6);
680 hpacker.pack_start (notebook, true, true);
681 hpacker.pack_start (preview, false, false);
683 vpacker.set_spacing (6);
684 vpacker.pack_start (hpacker, true, true);
694 hbox = manage(new HBox);
695 hbox->pack_start (found_entry);
696 hbox->pack_start (found_search_btn);
698 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
699 scroll->add(found_list_view);
700 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
702 vbox = manage(new VBox);
703 vbox->pack_start (*hbox, PACK_SHRINK);
704 vbox->pack_start (*scroll);
706 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
708 found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
710 found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
712 found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
713 found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
715 notebook.append_page (*vbox, _("Search Tags"));
717 //add freesound search
718 #ifdef FREESOUND_GOT_FIXED
723 passbox = manage(new HBox);
724 passbox->set_spacing (6);
726 label = manage (new Label);
727 label->set_text (_("Tags:"));
728 passbox->pack_start (*label, false, false);
729 passbox->pack_start (freesound_entry, true, true);
731 label = manage (new Label);
732 label->set_text (_("Sort:"));
733 passbox->pack_start (*label, false, false);
734 passbox->pack_start (freesound_sort, false, false);
735 freesound_sort.clear_items();
737 // Order of the following must correspond with enum sortMethod
738 // in sfdb_freesound_mootcher.h
739 freesound_sort.append_text(_("None"));
740 freesound_sort.append_text(_("Longest"));
741 freesound_sort.append_text(_("Shortest"));
742 freesound_sort.append_text(_("Newest"));
743 freesound_sort.append_text(_("Oldest"));
744 freesound_sort.append_text(_("Most downloaded"));
745 freesound_sort.append_text(_("Least downloaded"));
746 freesound_sort.append_text(_("Highest rated"));
747 freesound_sort.append_text(_("Lowest rated"));
748 freesound_sort.set_active(0);
750 passbox->pack_start (freesound_search_btn, false, false);
751 passbox->pack_start (freesound_more_btn, false, false);
752 freesound_more_btn.set_label(_("More"));
753 freesound_more_btn.set_sensitive(false);
755 passbox->pack_start (freesound_similar_btn, false, false);
756 freesound_similar_btn.set_label(_("Similar"));
757 freesound_similar_btn.set_sensitive(false);
759 scroll = manage(new ScrolledWindow);
760 scroll->add(freesound_list_view);
761 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
763 vbox = manage(new VBox);
764 vbox->set_spacing (3);
765 vbox->pack_start (*passbox, PACK_SHRINK);
766 vbox->pack_start (*scroll);
768 freesound_list_view.append_column(_("ID") , freesound_list_columns.id);
769 freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
770 // freesound_list_view.append_column(_("URI") , freesound_list_columns.uri);
771 freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
772 freesound_list_view.append_column(_("Size"), freesound_list_columns.filesize);
773 freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
774 freesound_list_view.append_column(_("License"), freesound_list_columns.license);
775 freesound_list_view.get_column(0)->set_alignment(0.5);
776 freesound_list_view.get_column(1)->set_expand(true); // filename
777 freesound_list_view.get_column(1)->set_resizable(true); // filename
778 freesound_list_view.get_column(2)->set_alignment(0.5);
779 freesound_list_view.get_column(3)->set_alignment(0.5);
780 freesound_list_view.get_column(4)->set_alignment(0.5);
781 freesound_list_view.get_column(5)->set_alignment(0.5);
783 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
784 freesound_list_view.set_tooltip_column(1);
786 freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
787 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
788 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
789 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
790 freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
791 freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
792 notebook.append_page (*vbox, _("Search Freesound"));
795 notebook.set_size_request (500, -1);
796 notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
800 Gtk::HButtonBox* button_box = manage (new HButtonBox);
802 button_box->set_layout (BUTTONBOX_END);
804 button_box->pack_start (import_button, false, false);
805 import_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_OK));
807 Gtkmm2ext::UI::instance()->set_tip (import_button, _("Press to import selected files"));
809 vpacker.pack_end (*button_box, false, false);
811 set_wmclass (X_("import"), PROGRAM_NAME);
814 SoundFileBrowser::~SoundFileBrowser ()
816 persistent_folder = chooser.get_current_folder();
820 SoundFileBrowser::run ()
829 gtk_main_iteration ();
836 SoundFileBrowser::set_action_sensitive (bool yn)
838 import_button.set_sensitive (yn);
842 SoundFileBrowser::get_action_sensitive () const
844 return import_button.get_sensitive ();
848 SoundFileBrowser::do_something (int action)
855 SoundFileBrowser::on_show ()
857 ArdourWindow::on_show ();
862 SoundFileBrowser::on_key_press_event (GdkEventKey* ev)
864 if (ev->keyval == GDK_Escape) {
865 do_something (RESPONSE_CLOSE);
868 if (ev->keyval == GDK_space && ev->type == GDK_KEY_PRESS) {
869 if (get_action_sensitive()) {
874 return ArdourWindow::on_key_press_event (ev);
878 SoundFileBrowser::clear_selection ()
880 chooser.unselect_all ();
881 found_list_view.get_selection()->unselect_all ();
885 SoundFileBrowser::chooser_file_activated ()
887 do_something (RESPONSE_OK);
891 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
897 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
903 SoundFileBrowser::set_session (Session* s)
905 ArdourWindow::set_session (s);
906 preview.set_session (s);
911 remove_gain_meter ();
916 SoundFileBrowser::add_gain_meter ()
920 gm = new GainMeter (_session, 250);
922 boost::shared_ptr<Route> r = _session->the_auditioner ();
924 gm->set_controls (r, r->shared_peak_meter(), r->amp(), r->gain_control());
925 gm->set_fader_name (X_("GainFader"));
927 meter_packer.set_border_width (12);
928 meter_packer.pack_start (*gm, false, true);
929 hpacker.pack_end (meter_packer, false, false);
930 meter_packer.show_all ();
935 SoundFileBrowser::remove_gain_meter ()
938 meter_packer.remove (*gm);
939 hpacker.remove (meter_packer);
946 SoundFileBrowser::start_metering ()
948 metering_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
952 SoundFileBrowser::stop_metering ()
954 metering_connection.disconnect();
958 SoundFileBrowser::meter ()
960 if (is_mapped () && _session && gm) {
961 gm->update_meters ();
966 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
968 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
972 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
974 return SMFSource::safe_midi_file_extension (filter_info.filename);
978 SoundFileBrowser::on_audio_and_midi_filter (const FileFilter::Info& filter_info)
980 return on_audio_filter (filter_info) || on_midi_filter (filter_info);
984 SoundFileBrowser::update_preview ()
986 if (preview.setup_labels (chooser.get_preview_filename())) {
987 if (preview.autoplay()) {
988 Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
994 SoundFileBrowser::found_list_view_selected ()
996 if (!reset_options ()) {
997 set_action_sensitive (false);
1001 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1003 if (!rows.empty()) {
1004 TreeIter iter = found_list->get_iter(*rows.begin());
1005 file = (*iter)[found_list_columns.pathname];
1006 chooser.set_filename (file);
1007 set_action_sensitive (true);
1009 set_action_sensitive (false);
1012 preview.setup_labels (file);
1017 SoundFileBrowser::found_search_clicked ()
1019 string tag_string = found_entry.get_text ();
1021 vector<string> tags;
1023 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
1024 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
1028 vector<string> results;
1029 Library->search_members_and (results, tags);
1031 found_list->clear();
1032 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
1033 TreeModel::iterator new_row = found_list->append();
1034 TreeModel::Row row = *new_row;
1035 string path = Glib::filename_from_uri (string ("file:") + *i);
1036 row[found_list_columns.pathname] = path;
1042 SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
1045 Mootcher *mootcher = new Mootcher;
1048 string id = (*iter)[freesound_list_columns.id];
1049 string uri = (*iter)[freesound_list_columns.uri];
1050 string ofn = (*iter)[freesound_list_columns.filename];
1052 if (mootcher->checkAudioFile(ofn, id)) {
1053 // file already exists, no need to download it again
1054 file = mootcher->audioFileName;
1056 (*iter)[freesound_list_columns.started] = false;
1059 if (!(*iter)[freesound_list_columns.started]) {
1060 // start downloading the sound file
1061 (*iter)[freesound_list_columns.started] = true;
1062 mootcher->fetchAudioFile(ofn, id, uri, this);
1068 SoundFileBrowser::freesound_list_view_selected ()
1071 if (!reset_options ()) {
1072 set_action_sensitive (false);
1075 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1076 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1077 file = freesound_get_audio_file (freesound_list->get_iter(*i));
1080 switch (rows.size()) {
1083 freesound_similar_btn.set_sensitive(false);
1084 set_action_sensitive (false);
1087 // exactly one item selected
1089 // file exists on disk already
1090 chooser.set_filename (file);
1091 preview.setup_labels (file);
1092 set_action_sensitive (true);
1094 freesound_similar_btn.set_sensitive(true);
1097 // multiple items selected
1098 preview.setup_labels ("");
1099 freesound_similar_btn.set_sensitive(false);
1107 SoundFileBrowser::refresh_display(std::string ID, std::string file)
1109 // called when the mootcher has finished downloading a file
1110 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1111 if (rows.size() == 1) {
1112 // there's a single item selected in the freesound list
1113 //XXX make a function to be used to construct the actual file name both here and in the mootcher
1114 Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
1115 std::string selected_ID = (*row)[freesound_list_columns.id];
1116 if (ID == selected_ID) {
1117 // the selected item in the freesound list is the item that has just finished downloading
1118 chooser.set_filename(file);
1119 preview.setup_labels (file);
1120 set_action_sensitive (true);
1126 SoundFileBrowser::freesound_search_clicked ()
1129 freesound_list->clear();
1135 SoundFileBrowser::freesound_more_clicked ()
1140 snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
1141 freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
1145 SoundFileBrowser::freesound_similar_clicked ()
1147 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1148 if (rows.size() == 1) {
1151 Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
1152 id = (*iter)[freesound_list_columns.id];
1153 freesound_list->clear();
1155 GdkCursor *prev_cursor;
1156 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1157 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1160 std::string theString = mootcher.searchSimilar(id);
1162 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1163 handle_freesound_results(theString);
1168 SoundFileBrowser::freesound_search()
1172 string search_string = freesound_entry.get_text ();
1173 enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
1175 GdkCursor *prev_cursor;
1176 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1177 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1180 std::string theString = mootcher.searchText(
1184 "", // OSX eats anything incl mp3
1186 "type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
1191 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1192 handle_freesound_results(theString);
1196 SoundFileBrowser::handle_freesound_results(std::string theString) {
1198 doc.read_buffer( theString );
1199 XMLNode *root = doc.root();
1202 error << "no root XML node!" << endmsg;
1206 if ( strcmp(root->name().c_str(), "response") != 0) {
1207 error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
1211 // find out how many pages are available to search
1212 int freesound_n_pages = 1;
1213 XMLNode *res = root->child("num_pages");
1215 string result = res->child("text")->content();
1216 freesound_n_pages = atoi(result);
1219 int more_pages = freesound_n_pages - freesound_page;
1221 if (more_pages > 0) {
1222 freesound_more_btn.set_sensitive(true);
1223 freesound_more_btn.set_tooltip_text(string_compose(P_(
1224 "%1 more page of 100 results available",
1225 "%1 more pages of 100 results available",
1226 more_pages), more_pages));
1228 freesound_more_btn.set_sensitive(false);
1229 freesound_more_btn.set_tooltip_text(_("No more results available"));
1232 XMLNode *sounds_root = root->child("sounds");
1234 error << "no child node \"sounds\" found!" << endmsg;
1238 XMLNodeList sounds = sounds_root->children();
1239 if (sounds.size() == 0) {
1244 XMLNodeConstIterator niter;
1246 for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
1248 if( strcmp( node->name().c_str(), "resource") != 0 ) {
1249 error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
1253 // node->dump(cerr, "node:");
1256 XMLNode *id_node = node->child ("id");
1257 XMLNode *uri_node = node->child ("serve");
1258 XMLNode *ofn_node = node->child ("original_filename");
1259 XMLNode *dur_node = node->child ("duration");
1260 XMLNode *siz_node = node->child ("filesize");
1261 XMLNode *srt_node = node->child ("samplerate");
1262 XMLNode *lic_node = node->child ("license");
1264 if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
1266 std::string id = id_node->child("text")->content();
1267 std::string uri = uri_node->child("text")->content();
1268 std::string ofn = ofn_node->child("text")->content();
1269 std::string dur = dur_node->child("text")->content();
1270 std::string siz = siz_node->child("text")->content();
1271 std::string srt = srt_node->child("text")->content();
1272 std::string lic = lic_node->child("text")->content();
1275 // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
1277 double duration_seconds = atof(dur);
1279 char duration_hhmmss[16];
1280 if (duration_seconds >= 99 * 60 * 60) {
1281 strcpy(duration_hhmmss, ">99h");
1283 s = modf(duration_seconds/60, &m) * 60;
1284 m = modf(m/60, &h) * 60;
1285 sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
1290 double size_bytes = atof(siz);
1292 if (size_bytes < 1000) {
1293 sprintf(bsize, "%.0f %s", size_bytes, _("B"));
1294 } else if (size_bytes < 1000000 ) {
1295 sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
1296 } else if (size_bytes < 10000000) {
1297 sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
1298 } else if (size_bytes < 1000000000) {
1299 sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
1301 sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
1304 /* see http://www.freesound.org/help/faq/#licenses */
1305 char shortlicense[64];
1306 if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
1307 sprintf(shortlicense, "CC-BY-NC");
1308 } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
1309 sprintf(shortlicense, "CC-BY");
1310 } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
1311 sprintf(shortlicense, "sampling+");
1312 } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
1313 sprintf(shortlicense, "PD");
1315 snprintf(shortlicense, 64, "%s", lic.c_str());
1316 shortlicense[63]= '\0';
1319 TreeModel::iterator new_row = freesound_list->append();
1320 TreeModel::Row row = *new_row;
1322 row[freesound_list_columns.id ] = id;
1323 row[freesound_list_columns.uri ] = uri;
1324 row[freesound_list_columns.filename] = ofn;
1325 row[freesound_list_columns.duration] = duration_hhmmss;
1326 row[freesound_list_columns.filesize] = bsize;
1327 row[freesound_list_columns.smplrate] = srt;
1328 row[freesound_list_columns.license ] = shortlicense;
1335 SoundFileBrowser::get_paths ()
1337 vector<string> results;
1339 int n = notebook.get_current_page ();
1342 vector<string> filenames = chooser.get_filenames();
1343 vector<string>::iterator i;
1345 for (i = filenames.begin(); i != filenames.end(); ++i) {
1347 if ((!g_stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
1348 results.push_back (*i);
1352 } else if (n == 1) {
1354 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1355 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1356 TreeIter iter = found_list->get_iter(*i);
1357 string str = (*iter)[found_list_columns.pathname];
1359 results.push_back (str);
1362 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1363 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1364 string str = freesound_get_audio_file (freesound_list->get_iter(*i));
1366 results.push_back (str);
1375 SoundFileOmega::reset_options_noret ()
1377 if (!resetting_ourselves) {
1378 (void) reset_options ();
1383 SoundFileOmega::reset_options ()
1385 if (_import_active) {
1386 _reset_post_import = true;
1390 vector<string> paths = get_paths ();
1392 if (paths.empty()) {
1394 channel_combo.set_sensitive (false);
1395 action_combo.set_sensitive (false);
1396 where_combo.set_sensitive (false);
1397 copy_files_btn.set_active (true);
1398 copy_files_btn.set_sensitive (false);
1404 channel_combo.set_sensitive (true);
1405 action_combo.set_sensitive (true);
1406 where_combo.set_sensitive (true);
1408 /* if we get through this function successfully, this may be
1409 reset at the end, once we know if we can use hard links
1410 to do embedding (or if we are importing a MIDI file).
1413 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1414 copy_files_btn.set_sensitive (false);
1416 copy_files_btn.set_sensitive (false);
1422 bool selection_includes_multichannel;
1423 bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1426 /* See if we are thinking about importing any MIDI files */
1427 vector<string>::iterator i = paths.begin ();
1428 while (i != paths.end() && SMFSource::valid_midi_file (*i) == false) {
1431 bool const have_a_midi_file = (i != paths.end ());
1433 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1434 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1438 if (have_a_midi_file) {
1439 smf_tempo_btn.show ();
1441 smf_tempo_btn.hide ();
1444 string existing_choice;
1445 vector<string> action_strings;
1447 resetting_ourselves = true;
1449 if (chooser.get_filter() == &audio_filter) {
1453 if (selected_audio_track_cnt > 0) {
1454 if (channel_combo.get_active_text().length()) {
1455 ImportDisposition id = get_channel_disposition();
1458 case Editing::ImportDistinctFiles:
1459 if (selected_audio_track_cnt == paths.size()) {
1460 action_strings.push_back (importmode2string (ImportToTrack));
1464 case Editing::ImportDistinctChannels:
1465 /* XXX it would be nice to allow channel-per-selected track
1466 but its too hard we don't want to deal with all the
1467 different per-file + per-track channel configurations.
1472 action_strings.push_back (importmode2string (ImportToTrack));
1482 if (selected_midi_track_cnt > 0) {
1483 action_strings.push_back (importmode2string (ImportToTrack));
1487 action_strings.push_back (importmode2string (ImportAsTrack));
1488 action_strings.push_back (importmode2string (ImportAsRegion));
1489 if (!Profile->get_mixbus()) {
1490 action_strings.push_back (importmode2string (ImportAsTapeTrack));
1493 existing_choice = action_combo.get_active_text();
1495 set_popdown_strings (action_combo, action_strings);
1497 /* preserve any existing choice, if possible */
1500 if (existing_choice.length()) {
1501 vector<string>::iterator x;
1502 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1503 if (*x == existing_choice) {
1504 action_combo.set_active_text (existing_choice);
1508 if (x == action_strings.end()) {
1509 action_combo.set_active_text (action_strings.front());
1512 action_combo.set_active_text (action_strings.front());
1515 resetting_ourselves = false;
1517 if ((mode = get_mode()) == ImportAsRegion) {
1518 where_combo.set_sensitive (false);
1520 where_combo.set_sensitive (true);
1523 vector<string> channel_strings;
1525 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1527 if (selection_includes_multichannel) {
1528 channel_strings.push_back (_("one track per channel"));
1531 channel_strings.push_back (_("one track per file"));
1533 if (paths.size() > 1) {
1534 /* tape tracks are a single region per track, so we cannot
1535 sequence multiple files.
1537 if (mode != ImportAsTapeTrack) {
1538 channel_strings.push_back (_("sequence files"));
1541 channel_strings.push_back (_("all files in one track"));
1542 channel_strings.push_back (_("merge files"));
1548 channel_strings.push_back (_("one region per file"));
1550 if (selection_includes_multichannel) {
1551 channel_strings.push_back (_("one region per channel"));
1554 if (paths.size() > 1) {
1556 channel_strings.push_back (_("all files in one region"));
1561 resetting_ourselves = true;
1563 existing_choice = channel_combo.get_active_text();
1565 set_popdown_strings (channel_combo, channel_strings);
1567 /* preserve any existing choice, if possible */
1569 if (existing_choice.length()) {
1570 vector<string>::iterator x;
1571 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1572 if (*x == existing_choice) {
1573 channel_combo.set_active_text (existing_choice);
1577 if (x == channel_strings.end()) {
1578 channel_combo.set_active_text (channel_strings.front());
1581 channel_combo.set_active_text (channel_strings.front());
1584 resetting_ourselves = false;
1587 src_combo.set_sensitive (true);
1589 src_combo.set_sensitive (false);
1592 /* We must copy MIDI files or those from Freesound
1593 * or any file if we are under nsm control */
1594 bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
1596 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1598 if (selection_can_be_embedded_with_links && !must_copy) {
1599 copy_files_btn.set_sensitive (true);
1602 copy_files_btn.set_active (true);
1604 copy_files_btn.set_sensitive (false);
1610 copy_files_btn.set_active (true);
1612 copy_files_btn.set_sensitive (!must_copy);
1620 SoundFileOmega::bad_file_message()
1622 MessageDialog msg (*this,
1623 string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1628 resetting_ourselves = true;
1629 chooser.unselect_uri (chooser.get_preview_uri());
1630 resetting_ourselves = false;
1636 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1645 multichannel = false;
1647 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1649 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1650 if (info.channels > 1) {
1651 multichannel = true;
1656 if (sz != info.length) {
1661 if (info.samplerate != _session->frame_rate()) {
1665 } else if (SMFSource::valid_midi_file (*i)) {
1669 if (reader.open (*i)) {
1672 if (reader.is_type0 ()) {
1673 if (reader.channels().size() > 1) {
1674 /* for type-0 files, we can split
1675 * "one track per channel"
1677 multichannel = true;
1680 if (reader.num_tracks() > 1) {
1681 multichannel = true;
1696 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1698 #ifdef PLATFORM_WINDOWS
1701 std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
1704 if (g_mkdir (tmpdir.c_str(), 0744)) {
1705 if (errno != EEXIST) {
1710 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1712 char tmpc[PATH_MAX+1];
1714 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1718 if (link ((*i).c_str(), tmpc)) {
1728 g_rmdir (tmpdir.c_str());
1733 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
1734 : SoundFileBrowser (title, s, false)
1736 chooser.set_select_multiple (false);
1737 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1738 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1742 SoundFileChooser::on_hide ()
1744 ArdourWindow::on_hide();
1748 _session->cancel_audition();
1753 SoundFileChooser::get_filename ()
1755 vector<string> paths;
1757 paths = get_paths ();
1759 if (paths.empty()) {
1763 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1767 return paths.front();
1770 SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s,
1771 uint32_t selected_audio_tracks,
1772 uint32_t selected_midi_tracks,
1774 Editing::ImportMode mode_hint)
1775 : SoundFileBrowser (title, s, persistent)
1776 , copy_files_btn ( _("Copy files to session"))
1777 , smf_tempo_btn (_("Use MIDI Tempo Map (if defined)"))
1778 , selected_audio_track_cnt (selected_audio_tracks)
1779 , selected_midi_track_cnt (selected_midi_tracks)
1780 , _import_active (false)
1781 , _reset_post_import (false)
1785 set_size_request (-1, 550);
1787 block_two.set_border_width (12);
1788 block_three.set_border_width (12);
1789 block_four.set_border_width (12);
1792 str.push_back (_("file timestamp"));
1793 str.push_back (_("edit point"));
1794 str.push_back (_("playhead"));
1795 str.push_back (_("session start"));
1796 set_popdown_strings (where_combo, str);
1797 where_combo.set_active_text (str.back());
1798 where_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::where_combo_changed));
1800 Label* l = manage (new Label);
1801 l->set_markup (_("<b>Add files ...</b>"));
1802 options.attach (*l, 0, 1, 0, 1, FILL, SHRINK, 8, 0);
1803 options.attach (action_combo, 0, 1, 1, 2, FILL, SHRINK, 8, 0);
1805 l = manage (new Label);
1806 l->set_markup (_("<b>Insert at</b>"));
1807 options.attach (*l, 0, 1, 3, 4, FILL, SHRINK, 8, 0);
1808 options.attach (where_combo, 0, 1, 4, 5, FILL, SHRINK, 8, 0);
1810 l = manage (new Label);
1811 l->set_markup (_("<b>Mapping</b>"));
1812 options.attach (*l, 1, 2, 0, 1, FILL, SHRINK, 8, 0);
1813 options.attach (channel_combo, 1, 2, 1, 2, FILL, SHRINK, 8, 0);
1815 l = manage (new Label);
1816 l->set_markup (_("<b>Conversion quality</b>"));
1817 options.attach (*l, 1, 2, 3, 4, FILL, SHRINK, 8, 0);
1818 options.attach (src_combo, 1, 2, 4, 5, FILL, SHRINK, 8, 0);
1820 l = manage (new Label);
1821 l->set_markup (_("<b>MIDI Track Names</b>"));
1822 options.attach (*l, 2, 3, 0, 1, FILL, SHRINK, 8, 0);
1823 options.attach (midi_track_name_combo, 2, 3, 1, 2, FILL, SHRINK, 8, 0);
1825 options.attach (smf_tempo_btn, 2, 3, 3, 4, FILL, SHRINK, 8, 0);
1827 l = manage (new Label);
1828 l->set_markup (_("<b>Instrument</b>"));
1829 options.attach (*l, 3, 4, 0, 1, FILL, SHRINK, 8, 0);
1830 options.attach (instrument_combo, 3, 4, 1, 2, FILL, SHRINK, 8, 0);
1832 Alignment *hspace = manage (new Alignment ());
1833 hspace->set_size_request (2, 2);
1834 options.attach (*hspace, 0, 3, 2, 3, FILL, SHRINK, 0, 8);
1836 Alignment *vspace = manage (new Alignment ());
1837 vspace->set_size_request (2, 2);
1838 options.attach (*vspace, 2, 3, 0, 3, EXPAND, SHRINK, 0, 0);
1841 str.push_back (_("by track number"));
1842 str.push_back (_("by track name"));
1843 str.push_back (_("by instrument name"));
1844 set_popdown_strings (midi_track_name_combo, str);
1845 midi_track_name_combo.set_active_text (str.front());
1848 str.push_back (_("one track per file"));
1849 set_popdown_strings (channel_combo, str);
1850 channel_combo.set_active_text (str.front());
1851 channel_combo.set_sensitive (false);
1854 str.push_back (_("Best"));
1855 str.push_back (_("Good"));
1856 str.push_back (_("Quick"));
1857 str.push_back (_("Fast"));
1858 str.push_back (_("Fastest"));
1860 set_popdown_strings (src_combo, str);
1861 src_combo.set_active_text (str.front());
1862 src_combo.set_sensitive (false);
1863 src_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::src_combo_changed));
1865 action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1866 channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1868 copy_files_btn.set_active (true);
1870 Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1873 copy_label->set_size_request (175, -1);
1874 copy_label->set_line_wrap (true);
1877 block_four.pack_start (copy_files_btn, false, false);
1878 options.attach (block_four, 3, 4, 4, 5, FILL, SHRINK, 8, 0);
1880 vpacker.pack_start (options, false, true);
1882 /* setup disposition map */
1884 disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1885 disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1886 disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1887 disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1889 disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1890 disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1891 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1892 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1894 chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1896 /* set size requests for a couple of combos to allow them to display the longest text
1897 they will ever be asked to display. This prevents them being resized when the user
1898 selects a file to import, which in turn prevents the size of the dialog from jumping
1902 str.push_back (_("one track per file"));
1903 str.push_back (_("one track per channel"));
1904 str.push_back (_("sequence files"));
1905 str.push_back (_("all files in one region"));
1906 set_popdown_strings (channel_combo, str);
1909 str.push_back (importmode2string (ImportAsTrack));
1910 str.push_back (importmode2string (ImportToTrack));
1911 str.push_back (importmode2string (ImportAsRegion));
1912 str.push_back (importmode2string (ImportAsTapeTrack));
1913 set_popdown_strings (action_combo, str);
1914 action_combo.set_active_text (importmode2string(mode_hint));
1916 reset (selected_audio_tracks, selected_midi_tracks);
1920 SoundFileOmega::set_mode (ImportMode mode)
1922 action_combo.set_active_text (importmode2string (mode));
1926 SoundFileOmega::get_mode () const
1928 return string2importmode (action_combo.get_active_text());
1932 SoundFileOmega::on_hide ()
1934 ArdourWindow::on_hide();
1936 _session->cancel_audition();
1941 SoundFileOmega::get_position() const
1943 string str = where_combo.get_active_text();
1945 if (str == _("file timestamp")) {
1946 return ImportAtTimestamp;
1947 } else if (str == _("edit point")) {
1948 return ImportAtEditPoint;
1949 } else if (str == _("playhead")) {
1950 return ImportAtPlayhead;
1952 return ImportAtStart;
1957 SoundFileOmega::get_src_quality() const
1959 string str = src_combo.get_active_text();
1961 if (str == _("Best")) {
1963 } else if (str == _("Good")) {
1965 } else if (str == _("Quick")) {
1967 } else if (str == _("Fast")) {
1975 SoundFileOmega::src_combo_changed()
1977 preview.set_src_quality(get_src_quality());
1981 SoundFileOmega::where_combo_changed()
1983 preview.set_import_position(get_position());
1987 SoundFileOmega::get_midi_track_name_source () const
1989 return string2miditracknamesource (midi_track_name_combo.get_active_text());
1993 SoundFileOmega::get_use_smf_tempo_map () const
1995 return smf_tempo_btn.get_active ();
1999 SoundFileOmega::get_channel_disposition () const
2001 /* we use a map here because the channel combo can contain different strings
2002 depending on the state of the other combos. the map contains all possible strings
2003 and the ImportDisposition enum that corresponds to it.
2006 string str = channel_combo.get_active_text();
2007 DispositionMap::const_iterator x = disposition_map.find (str);
2009 if (x == disposition_map.end()) {
2010 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
2011 abort(); /*NOTREACHED*/
2018 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
2020 selected_audio_track_cnt = selected_audio_tracks;
2021 selected_midi_track_cnt = selected_midi_tracks;
2023 if (selected_audio_track_cnt == 0 && selected_midi_track_cnt > 0) {
2024 chooser.set_filter (midi_filter);
2025 } else if (selected_midi_track_cnt == 0 && selected_audio_track_cnt > 0) {
2026 chooser.set_filter (audio_filter);
2028 chooser.set_filter (audio_and_midi_filter);
2035 SoundFileOmega::file_selection_changed ()
2037 if (resetting_ourselves) {
2041 if (!reset_options ()) {
2042 set_action_sensitive (false);
2044 if (chooser.get_filenames().size() > 0) {
2045 set_action_sensitive (true);
2047 set_action_sensitive (false);
2053 SoundFileOmega::do_something (int action)
2055 SoundFileBrowser::do_something (action);
2057 if (action == RESPONSE_CLOSE) {
2064 vector<string> paths = get_paths ();
2065 ImportPosition pos = get_position ();
2066 ImportMode mode = get_mode ();
2067 ImportDisposition chns = get_channel_disposition ();
2068 PluginInfoPtr instrument = instrument_combo.selected_instrument();
2070 MidiTrackNameSource mts = get_midi_track_name_source ();
2071 MidiTempoMapDisposition mtd = (get_use_smf_tempo_map () ? SMFTempoUse : SMFTempoIgnore);
2074 case ImportAtEditPoint:
2075 where = PublicEditor::instance().get_preferred_edit_position ();
2077 case ImportAtTimestamp:
2080 case ImportAtPlayhead:
2081 where = _session->transport_frame();
2084 where = _session->current_start_frame();
2088 SrcQuality quality = get_src_quality();
2090 _import_active = true;
2092 if (copy_files_btn.get_active()) {
2093 PublicEditor::instance().do_import (paths, chns, mode, quality, mts, mtd, where, instrument);
2095 PublicEditor::instance().do_embed (paths, chns, mode, where, instrument);
2098 _import_active = false;
2100 if (_reset_post_import) {
2101 _reset_post_import = false;