2 Copyright (C) 2005-2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "gtk2ardour-config.h"
33 #include <gtkmm/box.h>
34 #include <gtkmm/stock.h>
36 #include "pbd/gstdio_compat.h"
37 #include <glibmm/fileutils.h>
39 #include "pbd/convert.h"
40 #include "pbd/tokenizer.h"
41 #include "pbd/enumwriter.h"
42 #include "pbd/pthread_utils.h"
43 #include "pbd/xml++.h"
45 #include <gtkmm2ext/utils.h>
47 #include "evoral/SMF.hpp"
49 #include "ardour/audio_library.h"
50 #include "ardour/auditioner.h"
51 #include "ardour/audioregion.h"
52 #include "ardour/audiofilesource.h"
53 #include "ardour/midi_region.h"
54 #include "ardour/smf_source.h"
55 #include "ardour/region_factory.h"
56 #include "ardour/source_factory.h"
57 #include "ardour/session.h"
58 #include "ardour/session_directory.h"
59 #include "ardour/srcfilesource.h"
61 #include "ardour_ui.h"
63 #include "gui_thread.h"
67 #include "gain_meter.h"
68 #include "main_clock.h"
69 #include "public_editor.h"
71 #include "ui_config.h"
73 #include "sfdb_freesound_mootcher.h"
75 using namespace ARDOUR;
79 using namespace Gtkmm2ext;
80 using namespace Editing;
84 string SoundFileBrowser::persistent_folder;
85 typedef TreeView::Selection::ListHandle_Path ListPath;
88 string2importmode (string str)
90 if (str == _("as new tracks")) {
92 } else if (str == _("to selected tracks")) {
94 } else if (str == _("to region list")) {
95 return ImportAsRegion;
96 } else if (str == _("as new tape tracks")) {
97 return ImportAsTapeTrack;
100 warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
102 return ImportAsTrack;
106 importmode2string (ImportMode mode)
110 return _("as new tracks");
112 return _("to selected tracks");
114 return _("to region list");
115 case ImportAsTapeTrack:
116 return _("as new tape tracks");
118 abort(); /*NOTREACHED*/
119 return _("as new tracks");
122 SoundFileBox::SoundFileBox (bool /*persistent*/)
124 length_clock ("sfboxLengthClock", true, "", false, false, true, false),
125 timecode_clock ("sfboxTimecodeClock", true, "", false, false, false, false),
127 autoplay_btn (_("Auto-play")),
128 seek_slider(0,1000,1),
132 set_name (X_("SoundFileBox"));
133 set_size_request (300, -1);
135 preview_label.set_markup (_("<b>Sound File Information</b>"));
137 border_frame.set_label_widget (preview_label);
138 border_frame.add (main_box);
140 pack_start (border_frame, true, true);
141 set_border_width (6);
143 main_box.set_border_width (6);
145 length.set_text (_("Length:"));
146 length.set_alignment (1, 0.5);
147 timecode.set_text (_("Timestamp:"));
148 timecode.set_alignment (1, 0.5);
149 format.set_text (_("Format:"));
150 format.set_alignment (1, 0.5);
151 channels.set_text (_("Channels:"));
152 channels.set_alignment (1, 0.5);
153 samplerate.set_text (_("Sample rate:"));
154 samplerate.set_alignment (1, 0.5);
156 preview_label.set_max_width_chars (50);
157 preview_label.set_ellipsize (Pango::ELLIPSIZE_END);
159 format_text.set_max_width_chars (20);
160 format_text.set_ellipsize (Pango::ELLIPSIZE_END);
161 format_text.set_alignment (0, 1);
163 table.set_col_spacings (6);
164 table.set_homogeneous (false);
165 table.set_row_spacings (6);
167 table.attach (channels, 0, 1, 0, 1, FILL, FILL);
168 table.attach (samplerate, 0, 1, 1, 2, FILL, FILL);
169 table.attach (format, 0, 1, 2, 4, FILL, FILL);
170 table.attach (length, 0, 1, 4, 5, FILL, FILL);
171 table.attach (timecode, 0, 1, 5, 6, FILL, FILL);
173 table.attach (channels_value, 1, 2, 0, 1, FILL, FILL);
174 table.attach (samplerate_value, 1, 2, 1, 2, FILL, FILL);
175 table.attach (format_text, 1, 2, 2, 4, FILL, FILL);
176 table.attach (length_clock, 1, 2, 4, 5, FILL, FILL);
177 table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL);
179 length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock->mode());
180 timecode_clock.set_mode (AudioClock::Timecode);
182 main_box.pack_start (table, false, false);
184 tags_entry.set_editable (true);
185 tags_entry.set_wrap_mode(Gtk::WRAP_WORD);
186 tags_entry.signal_focus_out_event().connect (sigc::mem_fun (*this, &SoundFileBox::tags_entry_left));
188 Label* label = manage (new Label (_("Tags:")));
189 label->set_alignment (0.0f, 0.5f);
190 main_box.pack_start (*label, false, false);
191 main_box.pack_start (tags_entry, true, true);
193 main_box.pack_start (bottom_box, false, false);
195 play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
196 // play_btn.set_label (_("Play"));
198 stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
199 // stop_btn.set_label (_("Stop"));
201 bottom_box.set_homogeneous (false);
202 bottom_box.set_spacing (6);
203 bottom_box.pack_start(play_btn, true, true);
204 bottom_box.pack_start(stop_btn, true, true);
205 bottom_box.pack_start(autoplay_btn, false, false);
207 seek_slider.set_draw_value(false);
209 seek_slider.add_events(Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
210 seek_slider.signal_button_press_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_press), false);
211 seek_slider.signal_button_release_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_release), false);
212 main_box.pack_start (seek_slider, false, false);
214 play_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::audition));
215 stop_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::stop_audition));
217 stop_btn.set_sensitive (false);
219 channels_value.set_alignment (0.0f, 0.5f);
220 samplerate_value.set_alignment (0.0f, 0.5f);
224 SoundFileBox::set_session(Session* s)
226 SessionHandlePtr::set_session (s);
228 length_clock.set_session (s);
229 timecode_clock.set_session (s);
232 play_btn.set_sensitive (false);
233 stop_btn.set_sensitive (false);
234 auditioner_connections.drop_connections();
236 auditioner_connections.drop_connections();
237 _session->AuditionActive.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_active, this, _1), gui_context());
238 _session->the_auditioner()->AuditionProgress.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_progress, this, _1, _2), gui_context());
243 SoundFileBox::audition_active(bool active) {
244 stop_btn.set_sensitive (active);
245 seek_slider.set_sensitive (active);
247 seek_slider.set_value(0);
252 SoundFileBox::audition_progress(ARDOUR::framecnt_t pos, ARDOUR::framecnt_t len) {
254 seek_slider.set_value( 1000.0 * pos / len);
255 seek_slider.set_sensitive (true);
260 SoundFileBox::seek_button_press(GdkEventButton*) {
262 return false; // pass on to slider
266 SoundFileBox::seek_button_release(GdkEventButton*) {
268 _session->the_auditioner()->seek_to_percent(seek_slider.get_value() / 10.0);
269 seek_slider.set_sensitive (false);
270 return false; // pass on to slider
274 SoundFileBox::setup_labels (const string& filename)
277 // save existing tags
285 if (SMFSource::valid_midi_file (path)) {
287 boost::shared_ptr<SMFSource> ms;
289 ms = boost::dynamic_pointer_cast<SMFSource> (
290 SourceFactory::createExternal (DataType::MIDI, *_session,
291 path, 0, Source::Flag (0), false));
292 } catch (const std::exception& e) {
293 error << string_compose(_("Could not read file: %1 (%2)."),
294 path, e.what()) << endmsg;
297 preview_label.set_markup (_("<b>Midi File Information</b>"));
299 format_text.set_text ("MIDI");
300 samplerate_value.set_text ("-");
301 tags_entry.get_buffer()->set_text ("");
302 timecode_clock.set (0);
303 tags_entry.set_sensitive (false);
306 if (ms->is_type0()) {
307 channels_value.set_text (to_string(ms->channels().size(), std::dec));
309 if (ms->num_tracks() > 1) {
310 channels_value.set_text (to_string(ms->num_tracks(), std::dec) + _("(Tracks)"));
312 channels_value.set_text (to_string(ms->num_tracks(), std::dec));
315 length_clock.set (ms->length(ms->timeline_position()));
317 channels_value.set_text ("");
318 length_clock.set (0);
321 if (_session && ms) {
322 play_btn.set_sensitive (true);
324 play_btn.set_sensitive (false);
330 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
332 preview_label.set_markup (_("<b>Sound File Information</b>"));
333 format_text.set_text ("");
334 channels_value.set_text ("");
335 samplerate_value.set_text ("");
336 tags_entry.get_buffer()->set_text ("");
338 length_clock.set (0);
339 timecode_clock.set (0);
341 tags_entry.set_sensitive (false);
342 play_btn.set_sensitive (false);
347 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::Markup::escape_text (Glib::path_get_basename (filename))));
348 std::string n = sf_info.format_name;
349 if (n.substr (0, 8) == X_("Format: ")) {
352 format_text.set_text (n);
353 channels_value.set_text (to_string (sf_info.channels, std::dec));
355 if (_session && sf_info.samplerate != _session->frame_rate()) {
356 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
357 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
358 samplerate_value.set_name ("NewSessionSR1Label");
359 samplerate.set_name ("NewSessionSR1Label");
361 samplerate.set_text (_("Sample rate:"));
362 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
363 samplerate_value.set_name ("NewSessionSR2Label");
364 samplerate.set_name ("NewSessionSR2Label");
367 framecnt_t const nfr = _session ? _session->nominal_frame_rate() : 25;
368 double src_coef = (double) nfr / sf_info.samplerate;
370 length_clock.set (sf_info.length * src_coef + 0.5, true);
371 timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
373 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
375 vector<string> tags = Library->get_tags (string ("//") + filename);
377 stringstream tag_string;
378 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
379 if (i != tags.begin()) {
384 tags_entry.get_buffer()->set_text (tag_string.str());
386 tags_entry.set_sensitive (true);
388 play_btn.set_sensitive (true);
395 SoundFileBox::autoplay() const
397 return autoplay_btn.get_active();
401 SoundFileBox::audition_oneshot()
408 SoundFileBox::audition ()
414 _session->cancel_audition();
416 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
417 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
421 boost::shared_ptr<Region> r;
423 if (SMFSource::valid_midi_file (path)) {
425 boost::shared_ptr<SMFSource> ms =
426 boost::dynamic_pointer_cast<SMFSource> (
427 SourceFactory::createExternal (DataType::MIDI, *_session,
428 path, 0, Source::Flag (0), false));
430 string rname = region_name_from_path (ms->path(), false);
434 plist.add (ARDOUR::Properties::start, 0);
435 plist.add (ARDOUR::Properties::length, ms->length(ms->timeline_position()));
436 plist.add (ARDOUR::Properties::name, rname);
437 plist.add (ARDOUR::Properties::layer, 0);
439 r = boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (boost::dynamic_pointer_cast<Source>(ms), plist, false));
445 boost::shared_ptr<AudioFileSource> afs;
446 bool old_sbp = AudioSource::get_build_peakfiles ();
448 /* don't even think of building peakfiles for these files */
450 AudioSource::set_build_peakfiles (false);
452 for (int n = 0; n < sf_info.channels; ++n) {
454 afs = boost::dynamic_pointer_cast<AudioFileSource> (
455 SourceFactory::createExternal (DataType::AUDIO, *_session,
457 Source::Flag (ARDOUR::AudioFileSource::NoPeakFile), false));
458 if (afs->sample_rate() != _session->nominal_frame_rate()) {
459 boost::shared_ptr<SrcFileSource> sfs (new SrcFileSource(*_session, afs, _src_quality));
460 srclist.push_back(sfs);
462 srclist.push_back(afs);
465 } catch (failed_constructor& err) {
466 error << _("Could not access soundfile: ") << path << endmsg;
467 AudioSource::set_build_peakfiles (old_sbp);
472 AudioSource::set_build_peakfiles (old_sbp);
474 if (srclist.empty()) {
478 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
479 string rname = region_name_from_path (afs->path(), false);
483 plist.add (ARDOUR::Properties::start, 0);
484 plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->timeline_position()));
485 plist.add (ARDOUR::Properties::name, rname);
486 plist.add (ARDOUR::Properties::layer, 0);
488 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false));
491 frameoffset_t audition_position = 0;
492 switch(_import_position) {
493 case ImportAtTimestamp:
494 audition_position = 0;
496 case ImportAtPlayhead:
497 audition_position = _session->transport_frame();
500 audition_position = _session->current_start_frame();
502 case ImportAtEditPoint:
503 audition_position = PublicEditor::instance().get_preferred_edit_position ();
506 r->set_position(audition_position);
508 _session->audition_region(r);
512 SoundFileBox::stop_audition ()
515 _session->cancel_audition();
520 SoundFileBox::tags_entry_left (GdkEventFocus *)
527 SoundFileBox::tags_changed ()
529 string tag_string = tags_entry.get_buffer()->get_text ();
531 if (tag_string.empty()) {
537 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
538 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
546 SoundFileBox::save_tags (const vector<string>& tags)
548 Library->set_tags (string ("//") + path, tags);
549 Library->save_changes ();
552 SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persistent)
553 : ArdourWindow (title)
554 , found_list (ListStore::create(found_list_columns))
555 , freesound_list (ListStore::create(freesound_list_columns))
556 , chooser (FILE_CHOOSER_ACTION_OPEN)
557 , preview (persistent)
558 , found_search_btn (_("Search"))
559 , found_list_view (found_list)
560 , freesound_search_btn (_("Search"))
561 , freesound_list_view (freesound_list)
562 , resetting_ourselves (false)
566 , import_button (_("Import"))
567 , close_button (Stock::CLOSE)
573 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
574 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
575 chooser.add_shortcut_folder_uri("file:///Library/Audio/Apple Loops");
576 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
578 catch (Glib::Error & e) {
579 std::cerr << "sfdb.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
582 Gtkmm2ext::add_volume_shortcuts (chooser);
584 //add the file chooser
586 chooser.set_border_width (12);
588 audio_and_midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun (*this, &SoundFileBrowser::on_audio_and_midi_filter));
589 audio_and_midi_filter.set_name (_("Audio and MIDI files"));
591 audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
592 audio_filter.set_name (_("Audio files"));
594 midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
595 midi_filter.set_name (_("MIDI files"));
597 matchall_filter.add_pattern ("*.*");
598 matchall_filter.set_name (_("All files"));
600 chooser.add_filter (audio_and_midi_filter);
601 chooser.add_filter (audio_filter);
602 chooser.add_filter (midi_filter);
603 chooser.add_filter (matchall_filter);
604 chooser.set_select_multiple (true);
605 chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
606 chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
609 /* some broken redraw behaviour - this is a bandaid */
610 chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
613 if (!persistent_folder.empty()) {
614 chooser.set_current_folder (persistent_folder);
617 notebook.append_page (chooser, _("Browse Files"));
619 hpacker.set_spacing (6);
620 hpacker.pack_start (notebook, true, true);
621 hpacker.pack_start (preview, false, false);
623 vpacker.set_spacing (6);
624 vpacker.pack_start (hpacker, true, true);
634 hbox = manage(new HBox);
635 hbox->pack_start (found_entry);
636 hbox->pack_start (found_search_btn);
638 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
639 scroll->add(found_list_view);
640 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
642 vbox = manage(new VBox);
643 vbox->pack_start (*hbox, PACK_SHRINK);
644 vbox->pack_start (*scroll);
646 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
648 found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
650 found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
652 found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
653 found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
655 notebook.append_page (*vbox, _("Search Tags"));
657 //add freesound search
658 #ifdef FREESOUND_GOT_FIXED
663 passbox = manage(new HBox);
664 passbox->set_spacing (6);
666 label = manage (new Label);
667 label->set_text (_("Tags:"));
668 passbox->pack_start (*label, false, false);
669 passbox->pack_start (freesound_entry, true, true);
671 label = manage (new Label);
672 label->set_text (_("Sort:"));
673 passbox->pack_start (*label, false, false);
674 passbox->pack_start (freesound_sort, false, false);
675 freesound_sort.clear_items();
677 // Order of the following must correspond with enum sortMethod
678 // in sfdb_freesound_mootcher.h
679 freesound_sort.append_text(_("None"));
680 freesound_sort.append_text(_("Longest"));
681 freesound_sort.append_text(_("Shortest"));
682 freesound_sort.append_text(_("Newest"));
683 freesound_sort.append_text(_("Oldest"));
684 freesound_sort.append_text(_("Most downloaded"));
685 freesound_sort.append_text(_("Least downloaded"));
686 freesound_sort.append_text(_("Highest rated"));
687 freesound_sort.append_text(_("Lowest rated"));
688 freesound_sort.set_active(0);
690 passbox->pack_start (freesound_search_btn, false, false);
691 passbox->pack_start (freesound_more_btn, false, false);
692 freesound_more_btn.set_label(_("More"));
693 freesound_more_btn.set_sensitive(false);
695 passbox->pack_start (freesound_similar_btn, false, false);
696 freesound_similar_btn.set_label(_("Similar"));
697 freesound_similar_btn.set_sensitive(false);
699 scroll = manage(new ScrolledWindow);
700 scroll->add(freesound_list_view);
701 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
703 vbox = manage(new VBox);
704 vbox->set_spacing (3);
705 vbox->pack_start (*passbox, PACK_SHRINK);
706 vbox->pack_start (*scroll);
708 freesound_list_view.append_column(_("ID") , freesound_list_columns.id);
709 freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
710 // freesound_list_view.append_column(_("URI") , freesound_list_columns.uri);
711 freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
712 freesound_list_view.append_column(_("Size"), freesound_list_columns.filesize);
713 freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
714 freesound_list_view.append_column(_("License"), freesound_list_columns.license);
715 freesound_list_view.get_column(0)->set_alignment(0.5);
716 freesound_list_view.get_column(1)->set_expand(true); // filename
717 freesound_list_view.get_column(1)->set_resizable(true); // filename
718 freesound_list_view.get_column(2)->set_alignment(0.5);
719 freesound_list_view.get_column(3)->set_alignment(0.5);
720 freesound_list_view.get_column(4)->set_alignment(0.5);
721 freesound_list_view.get_column(5)->set_alignment(0.5);
723 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
724 freesound_list_view.set_tooltip_column(1);
726 freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
727 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
728 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
729 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
730 freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
731 freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
732 notebook.append_page (*vbox, _("Search Freesound"));
735 notebook.set_size_request (500, -1);
736 notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
740 Gtk::HButtonBox* button_box = manage (new HButtonBox);
742 button_box->set_layout (BUTTONBOX_END);
743 button_box->pack_start (close_button, false, false);
744 close_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_CLOSE));
746 button_box->pack_start (import_button, false, false);
747 import_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_OK));
749 Gtkmm2ext::UI::instance()->set_tip (import_button, _("Press to import selected files"));
750 Gtkmm2ext::UI::instance()->set_tip (close_button, _("Press to close this window without importing any files"));
752 vpacker.pack_end (*button_box, false, false);
754 set_wmclass (X_("import"), PROGRAM_NAME);
757 SoundFileBrowser::~SoundFileBrowser ()
759 persistent_folder = chooser.get_current_folder();
763 SoundFileBrowser::run ()
772 gtk_main_iteration ();
779 SoundFileBrowser::set_action_sensitive (bool yn)
781 import_button.set_sensitive (yn);
785 SoundFileBrowser::do_something (int action)
792 SoundFileBrowser::on_show ()
794 ArdourWindow::on_show ();
799 SoundFileBrowser::clear_selection ()
801 chooser.unselect_all ();
802 found_list_view.get_selection()->unselect_all ();
806 SoundFileBrowser::chooser_file_activated ()
812 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
818 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
824 SoundFileBrowser::set_session (Session* s)
826 ArdourWindow::set_session (s);
827 preview.set_session (s);
832 remove_gain_meter ();
837 SoundFileBrowser::add_gain_meter ()
841 gm = new GainMeter (_session, 250);
843 boost::shared_ptr<Route> r = _session->the_auditioner ();
845 gm->set_controls (r, r->shared_peak_meter(), r->amp(), r->gain_control());
846 gm->set_fader_name (X_("GainFader"));
848 meter_packer.set_border_width (12);
849 meter_packer.pack_start (*gm, false, true);
850 hpacker.pack_end (meter_packer, false, false);
851 meter_packer.show_all ();
856 SoundFileBrowser::remove_gain_meter ()
859 meter_packer.remove (*gm);
860 hpacker.remove (meter_packer);
867 SoundFileBrowser::start_metering ()
869 metering_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
873 SoundFileBrowser::stop_metering ()
875 metering_connection.disconnect();
879 SoundFileBrowser::meter ()
881 if (is_mapped () && _session && gm) {
882 gm->update_meters ();
887 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
889 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
893 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
895 return SMFSource::safe_midi_file_extension (filter_info.filename);
899 SoundFileBrowser::on_audio_and_midi_filter (const FileFilter::Info& filter_info)
901 return on_audio_filter (filter_info) || on_midi_filter (filter_info);
905 SoundFileBrowser::update_preview ()
907 if (preview.setup_labels (chooser.get_preview_filename())) {
908 if (preview.autoplay()) {
909 Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
915 SoundFileBrowser::found_list_view_selected ()
917 if (!reset_options ()) {
918 set_action_sensitive (false);
922 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
925 TreeIter iter = found_list->get_iter(*rows.begin());
926 file = (*iter)[found_list_columns.pathname];
927 chooser.set_filename (file);
928 set_action_sensitive (true);
930 set_action_sensitive (false);
933 preview.setup_labels (file);
938 SoundFileBrowser::found_search_clicked ()
940 string tag_string = found_entry.get_text ();
944 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
945 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
949 vector<string> results;
950 Library->search_members_and (results, tags);
953 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
954 TreeModel::iterator new_row = found_list->append();
955 TreeModel::Row row = *new_row;
956 string path = Glib::filename_from_uri (string ("file:") + *i);
957 row[found_list_columns.pathname] = path;
963 SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
966 Mootcher *mootcher = new Mootcher;
969 string id = (*iter)[freesound_list_columns.id];
970 string uri = (*iter)[freesound_list_columns.uri];
971 string ofn = (*iter)[freesound_list_columns.filename];
973 if (mootcher->checkAudioFile(ofn, id)) {
974 // file already exists, no need to download it again
975 file = mootcher->audioFileName;
977 (*iter)[freesound_list_columns.started] = false;
980 if (!(*iter)[freesound_list_columns.started]) {
981 // start downloading the sound file
982 (*iter)[freesound_list_columns.started] = true;
983 mootcher->fetchAudioFile(ofn, id, uri, this);
989 SoundFileBrowser::freesound_list_view_selected ()
992 if (!reset_options ()) {
993 set_action_sensitive (false);
996 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
997 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
998 file = freesound_get_audio_file (freesound_list->get_iter(*i));
1001 switch (rows.size()) {
1004 freesound_similar_btn.set_sensitive(false);
1005 set_action_sensitive (false);
1008 // exactly one item selected
1010 // file exists on disk already
1011 chooser.set_filename (file);
1012 preview.setup_labels (file);
1013 set_action_sensitive (true);
1015 freesound_similar_btn.set_sensitive(true);
1018 // multiple items selected
1019 preview.setup_labels ("");
1020 freesound_similar_btn.set_sensitive(false);
1028 SoundFileBrowser::refresh_display(std::string ID, std::string file)
1030 // called when the mootcher has finished downloading a file
1031 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1032 if (rows.size() == 1) {
1033 // there's a single item selected in the freesound list
1034 //XXX make a function to be used to construct the actual file name both here and in the mootcher
1035 Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
1036 std::string selected_ID = (*row)[freesound_list_columns.id];
1037 if (ID == selected_ID) {
1038 // the selected item in the freesound list is the item that has just finished downloading
1039 chooser.set_filename(file);
1040 preview.setup_labels (file);
1041 set_action_sensitive (true);
1047 SoundFileBrowser::freesound_search_clicked ()
1050 freesound_list->clear();
1056 SoundFileBrowser::freesound_more_clicked ()
1061 snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
1062 freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
1066 SoundFileBrowser::freesound_similar_clicked ()
1068 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1069 if (rows.size() == 1) {
1072 Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
1073 id = (*iter)[freesound_list_columns.id];
1074 freesound_list->clear();
1076 GdkCursor *prev_cursor;
1077 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1078 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1081 std::string theString = mootcher.searchSimilar(id);
1083 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1084 handle_freesound_results(theString);
1089 SoundFileBrowser::freesound_search()
1093 string search_string = freesound_entry.get_text ();
1094 enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
1096 GdkCursor *prev_cursor;
1097 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1098 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1101 std::string theString = mootcher.searchText(
1105 "", // OSX eats anything incl mp3
1107 "type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
1112 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1113 handle_freesound_results(theString);
1117 SoundFileBrowser::handle_freesound_results(std::string theString) {
1119 doc.read_buffer( theString );
1120 XMLNode *root = doc.root();
1123 error << "no root XML node!" << endmsg;
1127 if ( strcmp(root->name().c_str(), "response") != 0) {
1128 error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
1132 // find out how many pages are available to search
1133 int freesound_n_pages = 1;
1134 XMLNode *res = root->child("num_pages");
1136 string result = res->child("text")->content();
1137 freesound_n_pages = atoi(result);
1140 int more_pages = freesound_n_pages - freesound_page;
1142 if (more_pages > 0) {
1143 freesound_more_btn.set_sensitive(true);
1144 freesound_more_btn.set_tooltip_text(string_compose(P_(
1145 "%1 more page of 100 results available",
1146 "%1 more pages of 100 results available",
1147 more_pages), more_pages));
1149 freesound_more_btn.set_sensitive(false);
1150 freesound_more_btn.set_tooltip_text(_("No more results available"));
1153 XMLNode *sounds_root = root->child("sounds");
1155 error << "no child node \"sounds\" found!" << endmsg;
1159 XMLNodeList sounds = sounds_root->children();
1160 if (sounds.size() == 0) {
1165 XMLNodeConstIterator niter;
1167 for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
1169 if( strcmp( node->name().c_str(), "resource") != 0 ) {
1170 error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
1174 // node->dump(cerr, "node:");
1177 XMLNode *id_node = node->child ("id");
1178 XMLNode *uri_node = node->child ("serve");
1179 XMLNode *ofn_node = node->child ("original_filename");
1180 XMLNode *dur_node = node->child ("duration");
1181 XMLNode *siz_node = node->child ("filesize");
1182 XMLNode *srt_node = node->child ("samplerate");
1183 XMLNode *lic_node = node->child ("license");
1185 if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
1187 std::string id = id_node->child("text")->content();
1188 std::string uri = uri_node->child("text")->content();
1189 std::string ofn = ofn_node->child("text")->content();
1190 std::string dur = dur_node->child("text")->content();
1191 std::string siz = siz_node->child("text")->content();
1192 std::string srt = srt_node->child("text")->content();
1193 std::string lic = lic_node->child("text")->content();
1196 // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
1198 double duration_seconds = atof(dur);
1200 char duration_hhmmss[16];
1201 if (duration_seconds >= 99 * 60 * 60) {
1202 strcpy(duration_hhmmss, ">99h");
1204 s = modf(duration_seconds/60, &m) * 60;
1205 m = modf(m/60, &h) * 60;
1206 sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
1211 double size_bytes = atof(siz);
1213 if (size_bytes < 1000) {
1214 sprintf(bsize, "%.0f %s", size_bytes, _("B"));
1215 } else if (size_bytes < 1000000 ) {
1216 sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
1217 } else if (size_bytes < 10000000) {
1218 sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
1219 } else if (size_bytes < 1000000000) {
1220 sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
1222 sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
1225 /* see http://www.freesound.org/help/faq/#licenses */
1226 char shortlicense[64];
1227 if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
1228 sprintf(shortlicense, "CC-BY-NC");
1229 } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
1230 sprintf(shortlicense, "CC-BY");
1231 } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
1232 sprintf(shortlicense, "sampling+");
1233 } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
1234 sprintf(shortlicense, "PD");
1236 snprintf(shortlicense, 64, "%s", lic.c_str());
1237 shortlicense[63]= '\0';
1240 TreeModel::iterator new_row = freesound_list->append();
1241 TreeModel::Row row = *new_row;
1243 row[freesound_list_columns.id ] = id;
1244 row[freesound_list_columns.uri ] = uri;
1245 row[freesound_list_columns.filename] = ofn;
1246 row[freesound_list_columns.duration] = duration_hhmmss;
1247 row[freesound_list_columns.filesize] = bsize;
1248 row[freesound_list_columns.smplrate] = srt;
1249 row[freesound_list_columns.license ] = shortlicense;
1256 SoundFileBrowser::get_paths ()
1258 vector<string> results;
1260 int n = notebook.get_current_page ();
1263 vector<string> filenames = chooser.get_filenames();
1264 vector<string>::iterator i;
1266 for (i = filenames.begin(); i != filenames.end(); ++i) {
1268 if ((!g_stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
1269 results.push_back (*i);
1273 } else if (n == 1) {
1275 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1276 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1277 TreeIter iter = found_list->get_iter(*i);
1278 string str = (*iter)[found_list_columns.pathname];
1280 results.push_back (str);
1283 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1284 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1285 string str = freesound_get_audio_file (freesound_list->get_iter(*i));
1287 results.push_back (str);
1296 SoundFileOmega::reset_options_noret ()
1298 if (!resetting_ourselves) {
1299 (void) reset_options ();
1304 SoundFileOmega::reset_options ()
1306 if (_import_active) {
1307 _reset_post_import = true;
1311 vector<string> paths = get_paths ();
1313 if (paths.empty()) {
1315 channel_combo.set_sensitive (false);
1316 action_combo.set_sensitive (false);
1317 where_combo.set_sensitive (false);
1318 copy_files_btn.set_active (true);
1319 copy_files_btn.set_sensitive (false);
1325 channel_combo.set_sensitive (true);
1326 action_combo.set_sensitive (true);
1327 where_combo.set_sensitive (true);
1329 /* if we get through this function successfully, this may be
1330 reset at the end, once we know if we can use hard links
1331 to do embedding (or if we are importing a MIDI file).
1334 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1335 copy_files_btn.set_sensitive (false);
1337 copy_files_btn.set_sensitive (false);
1343 bool selection_includes_multichannel;
1344 bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1347 /* See if we are thinking about importing any MIDI files */
1348 vector<string>::iterator i = paths.begin ();
1349 while (i != paths.end() && SMFSource::valid_midi_file (*i) == false) {
1352 bool const have_a_midi_file = (i != paths.end ());
1354 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1355 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1359 string existing_choice;
1360 vector<string> action_strings;
1362 resetting_ourselves = true;
1364 if (chooser.get_filter() == &audio_filter) {
1368 if (selected_audio_track_cnt > 0) {
1369 if (channel_combo.get_active_text().length()) {
1370 ImportDisposition id = get_channel_disposition();
1373 case Editing::ImportDistinctFiles:
1374 if (selected_audio_track_cnt == paths.size()) {
1375 action_strings.push_back (importmode2string (ImportToTrack));
1379 case Editing::ImportDistinctChannels:
1380 /* XXX it would be nice to allow channel-per-selected track
1381 but its too hard we don't want to deal with all the
1382 different per-file + per-track channel configurations.
1387 action_strings.push_back (importmode2string (ImportToTrack));
1397 if (selected_midi_track_cnt > 0) {
1398 action_strings.push_back (importmode2string (ImportToTrack));
1402 action_strings.push_back (importmode2string (ImportAsTrack));
1403 action_strings.push_back (importmode2string (ImportAsRegion));
1404 action_strings.push_back (importmode2string (ImportAsTapeTrack));
1406 existing_choice = action_combo.get_active_text();
1408 set_popdown_strings (action_combo, action_strings);
1410 /* preserve any existing choice, if possible */
1413 if (existing_choice.length()) {
1414 vector<string>::iterator x;
1415 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1416 if (*x == existing_choice) {
1417 action_combo.set_active_text (existing_choice);
1421 if (x == action_strings.end()) {
1422 action_combo.set_active_text (action_strings.front());
1425 action_combo.set_active_text (action_strings.front());
1428 resetting_ourselves = false;
1430 if ((mode = get_mode()) == ImportAsRegion) {
1431 where_combo.set_sensitive (false);
1433 where_combo.set_sensitive (true);
1436 vector<string> channel_strings;
1438 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1439 /// XXX needs special casing for MIDI type-1 files
1440 channel_strings.push_back (_("one track per file"));
1442 if (selection_includes_multichannel) {
1443 channel_strings.push_back (_("one track per channel"));
1446 if (paths.size() > 1) {
1447 /* tape tracks are a single region per track, so we cannot
1448 sequence multiple files.
1450 if (mode != ImportAsTapeTrack) {
1451 channel_strings.push_back (_("sequence files"));
1454 channel_strings.push_back (_("all files in one track"));
1455 channel_strings.push_back (_("merge files"));
1461 channel_strings.push_back (_("one region per file"));
1463 if (selection_includes_multichannel) {
1464 channel_strings.push_back (_("one region per channel"));
1467 if (paths.size() > 1) {
1469 channel_strings.push_back (_("all files in one region"));
1474 resetting_ourselves = true;
1476 existing_choice = channel_combo.get_active_text();
1478 set_popdown_strings (channel_combo, channel_strings);
1480 /* preserve any existing choice, if possible */
1482 if (existing_choice.length()) {
1483 vector<string>::iterator x;
1484 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1485 if (*x == existing_choice) {
1486 channel_combo.set_active_text (existing_choice);
1490 if (x == channel_strings.end()) {
1491 channel_combo.set_active_text (channel_strings.front());
1494 channel_combo.set_active_text (channel_strings.front());
1497 resetting_ourselves = false;
1500 src_combo.set_sensitive (true);
1502 src_combo.set_sensitive (false);
1505 /* We must copy MIDI files or those from Freesound
1506 * or any file if we are under nsm control */
1507 bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
1509 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1511 if (selection_can_be_embedded_with_links && !must_copy) {
1512 copy_files_btn.set_sensitive (true);
1515 copy_files_btn.set_active (true);
1517 copy_files_btn.set_sensitive (false);
1523 copy_files_btn.set_active (true);
1525 copy_files_btn.set_sensitive (!must_copy);
1533 SoundFileOmega::bad_file_message()
1535 MessageDialog msg (*this,
1536 string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1541 resetting_ourselves = true;
1542 chooser.unselect_uri (chooser.get_preview_uri());
1543 resetting_ourselves = false;
1549 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1558 multichannel = false;
1560 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1562 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1563 if (info.channels > 1) {
1564 multichannel = true;
1569 if (sz != info.length) {
1574 if (info.samplerate != _session->frame_rate()) {
1578 } else if (SMFSource::valid_midi_file (*i)) {
1582 if (reader.num_tracks() > 1) {
1583 /* NOTE: we cannot merge midi-tracks.
1584 * they will always be on separate tracks
1585 * "one track per file" is not possible.
1587 //multichannel = true; // "channel" == track here...
1589 if (reader.is_type0 () && reader.channels().size() > 1) {
1590 /* for type-0 files, we can split
1591 * "one track per channel"
1593 multichannel = true;
1596 /* XXX we need err = true handling here in case
1597 we can't check the file
1610 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1612 #ifdef PLATFORM_WINDOWS
1615 std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
1618 if (g_mkdir (tmpdir.c_str(), 0744)) {
1619 if (errno != EEXIST) {
1624 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1626 char tmpc[PATH_MAX+1];
1628 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1632 if (link ((*i).c_str(), tmpc)) {
1642 g_rmdir (tmpdir.c_str());
1647 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
1648 : SoundFileBrowser (title, s, false)
1650 chooser.set_select_multiple (false);
1651 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1652 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1656 SoundFileChooser::on_hide ()
1658 ArdourWindow::on_hide();
1662 _session->cancel_audition();
1667 SoundFileChooser::get_filename ()
1669 vector<string> paths;
1671 paths = get_paths ();
1673 if (paths.empty()) {
1677 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1681 return paths.front();
1684 SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s,
1685 uint32_t selected_audio_tracks,
1686 uint32_t selected_midi_tracks,
1688 Editing::ImportMode mode_hint)
1689 : SoundFileBrowser (title, s, persistent)
1690 , copy_files_btn ( _("Copy files to session"))
1691 , selected_audio_track_cnt (selected_audio_tracks)
1692 , selected_midi_track_cnt (selected_midi_tracks)
1693 , _import_active (false)
1694 , _reset_post_import (false)
1698 set_size_request (-1, 550);
1700 block_two.set_border_width (12);
1701 block_three.set_border_width (12);
1702 block_four.set_border_width (12);
1705 str.push_back (_("file timestamp"));
1706 str.push_back (_("edit point"));
1707 str.push_back (_("playhead"));
1708 str.push_back (_("session start"));
1709 set_popdown_strings (where_combo, str);
1710 where_combo.set_active_text (str.back());
1711 where_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::where_combo_changed));
1713 Label* l = manage (new Label);
1714 l->set_markup (_("<b>Add files ...</b>"));
1715 options.attach (*l, 0, 1, 0, 1, FILL, SHRINK, 8, 0);
1716 options.attach (action_combo, 0, 1, 1, 2, FILL, SHRINK, 8, 0);
1718 l = manage (new Label);
1719 l->set_markup (_("<b>Insert at</b>"));
1720 options.attach (*l, 0, 1, 3, 4, FILL, SHRINK, 8, 0);
1721 options.attach (where_combo, 0, 1, 4, 5, FILL, SHRINK, 8, 0);
1723 l = manage (new Label);
1724 l->set_markup (_("<b>Mapping</b>"));
1725 options.attach (*l, 1, 2, 0, 1, FILL, SHRINK, 8, 0);
1726 options.attach (channel_combo, 1, 2, 1, 2, FILL, SHRINK, 8, 0);
1728 l = manage (new Label);
1729 l->set_markup (_("<b>Conversion quality</b>"));
1730 options.attach (*l, 1, 2, 3, 4, FILL, SHRINK, 8, 0);
1731 options.attach (src_combo, 1, 2, 4, 5, FILL, SHRINK, 8, 0);
1733 l = manage (new Label);
1734 l->set_markup (_("<b>Instrument</b>"));
1735 options.attach (*l, 3, 4, 0, 1, FILL, SHRINK, 8, 0);
1736 options.attach (instrument_combo, 3, 4, 1, 2, FILL, SHRINK, 8, 0);
1738 Alignment *hspace = manage (new Alignment ());
1739 hspace->set_size_request (2, 2);
1740 options.attach (*hspace, 0, 3, 2, 3, FILL, SHRINK, 0, 8);
1742 Alignment *vspace = manage (new Alignment ());
1743 vspace->set_size_request (2, 2);
1744 options.attach (*vspace, 2, 3, 0, 3, EXPAND, SHRINK, 0, 0);
1747 str.push_back (_("one track per file"));
1748 set_popdown_strings (channel_combo, str);
1749 channel_combo.set_active_text (str.front());
1750 channel_combo.set_sensitive (false);
1753 str.push_back (_("Best"));
1754 str.push_back (_("Good"));
1755 str.push_back (_("Quick"));
1756 str.push_back (_("Fast"));
1757 str.push_back (_("Fastest"));
1759 set_popdown_strings (src_combo, str);
1760 src_combo.set_active_text (str.front());
1761 src_combo.set_sensitive (false);
1762 src_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::src_combo_changed));
1764 action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1765 channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1767 copy_files_btn.set_active (true);
1769 Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1772 copy_label->set_size_request (175, -1);
1773 copy_label->set_line_wrap (true);
1776 block_four.pack_start (copy_files_btn, false, false);
1777 options.attach (block_four, 3, 4, 4, 5, FILL, SHRINK, 8, 0);
1779 vpacker.pack_start (options, false, true);
1781 /* setup disposition map */
1783 disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1784 disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1785 disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1786 disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1788 disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1789 disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1790 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1791 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1793 chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1795 /* set size requests for a couple of combos to allow them to display the longest text
1796 they will ever be asked to display. This prevents them being resized when the user
1797 selects a file to import, which in turn prevents the size of the dialog from jumping
1801 str.push_back (_("one track per file"));
1802 str.push_back (_("one track per channel"));
1803 str.push_back (_("sequence files"));
1804 str.push_back (_("all files in one region"));
1805 set_popdown_strings (channel_combo, str);
1808 str.push_back (importmode2string (ImportAsTrack));
1809 str.push_back (importmode2string (ImportToTrack));
1810 str.push_back (importmode2string (ImportAsRegion));
1811 str.push_back (importmode2string (ImportAsTapeTrack));
1812 set_popdown_strings (action_combo, str);
1813 action_combo.set_active_text (importmode2string(mode_hint));
1815 reset (selected_audio_tracks, selected_midi_tracks);
1819 SoundFileOmega::set_mode (ImportMode mode)
1821 action_combo.set_active_text (importmode2string (mode));
1825 SoundFileOmega::get_mode () const
1827 return string2importmode (action_combo.get_active_text());
1831 SoundFileOmega::on_hide ()
1833 ArdourWindow::on_hide();
1835 _session->cancel_audition();
1840 SoundFileOmega::get_position() const
1842 string str = where_combo.get_active_text();
1844 if (str == _("file timestamp")) {
1845 return ImportAtTimestamp;
1846 } else if (str == _("edit point")) {
1847 return ImportAtEditPoint;
1848 } else if (str == _("playhead")) {
1849 return ImportAtPlayhead;
1851 return ImportAtStart;
1856 SoundFileOmega::get_src_quality() const
1858 string str = src_combo.get_active_text();
1860 if (str == _("Best")) {
1862 } else if (str == _("Good")) {
1864 } else if (str == _("Quick")) {
1866 } else if (str == _("Fast")) {
1874 SoundFileOmega::src_combo_changed()
1876 preview.set_src_quality(get_src_quality());
1880 SoundFileOmega::where_combo_changed()
1882 preview.set_import_position(get_position());
1886 SoundFileOmega::get_channel_disposition () const
1888 /* we use a map here because the channel combo can contain different strings
1889 depending on the state of the other combos. the map contains all possible strings
1890 and the ImportDisposition enum that corresponds to it.
1893 string str = channel_combo.get_active_text();
1894 DispositionMap::const_iterator x = disposition_map.find (str);
1896 if (x == disposition_map.end()) {
1897 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1898 abort(); /*NOTREACHED*/
1905 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
1907 selected_audio_track_cnt = selected_audio_tracks;
1908 selected_midi_track_cnt = selected_midi_tracks;
1910 if (selected_audio_track_cnt == 0 && selected_midi_track_cnt > 0) {
1911 chooser.set_filter (midi_filter);
1912 } else if (selected_midi_track_cnt == 0 && selected_audio_track_cnt > 0) {
1913 chooser.set_filter (audio_filter);
1915 chooser.set_filter (audio_and_midi_filter);
1922 SoundFileOmega::file_selection_changed ()
1924 if (resetting_ourselves) {
1928 if (!reset_options ()) {
1929 set_action_sensitive (false);
1931 if (chooser.get_filenames().size() > 0) {
1932 set_action_sensitive (true);
1934 set_action_sensitive (false);
1940 SoundFileOmega::do_something (int action)
1942 SoundFileBrowser::do_something (action);
1944 if (action == RESPONSE_CLOSE) {
1951 vector<string> paths = get_paths ();
1952 ImportPosition pos = get_position ();
1953 ImportMode mode = get_mode ();
1954 ImportDisposition chns = get_channel_disposition ();
1955 PluginInfoPtr instrument = instrument_combo.selected_instrument();
1959 case ImportAtEditPoint:
1960 where = PublicEditor::instance().get_preferred_edit_position ();
1962 case ImportAtTimestamp:
1965 case ImportAtPlayhead:
1966 where = _session->transport_frame();
1969 where = _session->current_start_frame();
1973 SrcQuality quality = get_src_quality();
1975 _import_active = true;
1977 if (copy_files_btn.get_active()) {
1978 PublicEditor::instance().do_import (paths, chns, mode, quality, where, instrument);
1980 PublicEditor::instance().do_embed (paths, chns, mode, where, instrument);
1983 _import_active = false;
1985 if (_reset_post_import) {
1986 _reset_post_import = false;