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"
34 #include <gtkmm/box.h>
35 #include <gtkmm/stock.h>
37 #include <glib/gstdio.h>
38 #include <glibmm/fileutils.h>
40 #include "pbd/convert.h"
41 #include "pbd/tokenizer.h"
42 #include "pbd/enumwriter.h"
43 #include "pbd/pthread_utils.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"
62 #include "ardour_ui.h"
64 #include "gui_thread.h"
68 #include "gain_meter.h"
69 #include "main_clock.h"
70 #include "public_editor.h"
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 channels_value.set_text (to_string(ms->num_tracks(), std::dec));
307 length_clock.set (ms->length(ms->timeline_position()));
309 channels_value.set_text ("");
310 length_clock.set (0);
313 if (_session && ms) {
314 play_btn.set_sensitive (true);
316 play_btn.set_sensitive (false);
322 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
324 preview_label.set_markup (_("<b>Sound File Information</b>"));
325 format_text.set_text ("");
326 channels_value.set_text ("");
327 samplerate_value.set_text ("");
328 tags_entry.get_buffer()->set_text ("");
330 length_clock.set (0);
331 timecode_clock.set (0);
333 tags_entry.set_sensitive (false);
334 play_btn.set_sensitive (false);
339 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::Markup::escape_text (Glib::path_get_basename (filename))));
340 std::string n = sf_info.format_name;
341 if (n.substr (0, 8) == X_("Format: ")) {
344 format_text.set_text (n);
345 channels_value.set_text (to_string (sf_info.channels, std::dec));
347 if (_session && sf_info.samplerate != _session->frame_rate()) {
348 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
349 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
350 samplerate_value.set_name ("NewSessionSR1Label");
351 samplerate.set_name ("NewSessionSR1Label");
353 samplerate.set_text (_("Sample rate:"));
354 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
355 samplerate_value.set_name ("NewSessionSR2Label");
356 samplerate.set_name ("NewSessionSR2Label");
359 framecnt_t const nfr = _session ? _session->nominal_frame_rate() : 25;
360 double src_coef = (double) nfr / sf_info.samplerate;
362 length_clock.set (sf_info.length * src_coef + 0.5, true);
363 timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
365 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
367 vector<string> tags = Library->get_tags (string ("//") + filename);
369 stringstream tag_string;
370 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
371 if (i != tags.begin()) {
376 tags_entry.get_buffer()->set_text (tag_string.str());
378 tags_entry.set_sensitive (true);
380 play_btn.set_sensitive (true);
387 SoundFileBox::autoplay() const
389 return autoplay_btn.get_active();
393 SoundFileBox::audition_oneshot()
400 SoundFileBox::audition ()
406 _session->cancel_audition();
408 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
409 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
413 boost::shared_ptr<Region> r;
415 if (SMFSource::valid_midi_file (path)) {
417 boost::shared_ptr<SMFSource> ms =
418 boost::dynamic_pointer_cast<SMFSource> (
419 SourceFactory::createExternal (DataType::MIDI, *_session,
420 path, 0, Source::Flag (0), false));
422 string rname = region_name_from_path (ms->path(), false);
426 plist.add (ARDOUR::Properties::start, 0);
427 plist.add (ARDOUR::Properties::length, ms->length(ms->timeline_position()));
428 plist.add (ARDOUR::Properties::name, rname);
429 plist.add (ARDOUR::Properties::layer, 0);
431 r = boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (boost::dynamic_pointer_cast<Source>(ms), plist, false));
437 boost::shared_ptr<AudioFileSource> afs;
438 bool old_sbp = AudioSource::get_build_peakfiles ();
440 /* don't even think of building peakfiles for these files */
442 AudioSource::set_build_peakfiles (false);
444 for (int n = 0; n < sf_info.channels; ++n) {
446 afs = boost::dynamic_pointer_cast<AudioFileSource> (
447 SourceFactory::createExternal (DataType::AUDIO, *_session,
449 Source::Flag (ARDOUR::AudioFileSource::NoPeakFile), false));
450 if (afs->sample_rate() != _session->nominal_frame_rate()) {
451 boost::shared_ptr<SrcFileSource> sfs (new SrcFileSource(*_session, afs, _src_quality));
452 srclist.push_back(sfs);
454 srclist.push_back(afs);
457 } catch (failed_constructor& err) {
458 error << _("Could not access soundfile: ") << path << endmsg;
459 AudioSource::set_build_peakfiles (old_sbp);
464 AudioSource::set_build_peakfiles (old_sbp);
466 if (srclist.empty()) {
470 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
471 string rname = region_name_from_path (afs->path(), false);
475 plist.add (ARDOUR::Properties::start, 0);
476 plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->timeline_position()));
477 plist.add (ARDOUR::Properties::name, rname);
478 plist.add (ARDOUR::Properties::layer, 0);
480 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false));
483 frameoffset_t audition_position = 0;
484 switch(_import_position) {
485 case ImportAtTimestamp:
486 audition_position = 0;
488 case ImportAtPlayhead:
489 audition_position = _session->transport_frame();
492 audition_position = _session->current_start_frame();
494 case ImportAtEditPoint:
495 audition_position = PublicEditor::instance().get_preferred_edit_position ();
498 r->set_position(audition_position);
500 _session->audition_region(r);
504 SoundFileBox::stop_audition ()
507 _session->cancel_audition();
512 SoundFileBox::tags_entry_left (GdkEventFocus *)
519 SoundFileBox::tags_changed ()
521 string tag_string = tags_entry.get_buffer()->get_text ();
523 if (tag_string.empty()) {
529 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
530 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
538 SoundFileBox::save_tags (const vector<string>& tags)
540 Library->set_tags (string ("//") + path, tags);
541 Library->save_changes ();
544 SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persistent)
545 : ArdourWindow (title)
546 , found_list (ListStore::create(found_list_columns))
547 , freesound_list (ListStore::create(freesound_list_columns))
548 , chooser (FILE_CHOOSER_ACTION_OPEN)
549 , preview (persistent)
550 , found_search_btn (_("Search"))
551 , found_list_view (found_list)
552 , freesound_search_btn (_("Search"))
553 , freesound_list_view (freesound_list)
554 , resetting_ourselves (false)
558 , ok_button (Stock::OK)
559 , cancel_button (Stock::CANCEL)
560 , apply_button (Stock::APPLY)
565 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
566 chooser.add_shortcut_folder_uri("file:///Library/Audio/Apple Loops");
567 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
568 chooser.add_shortcut_folder_uri("file:///Volumes");
571 //add the file chooser
573 chooser.set_border_width (12);
575 audio_and_midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun (*this, &SoundFileBrowser::on_audio_and_midi_filter));
576 audio_and_midi_filter.set_name (_("Audio and MIDI files"));
578 audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
579 audio_filter.set_name (_("Audio files"));
581 midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
582 midi_filter.set_name (_("MIDI files"));
584 matchall_filter.add_pattern ("*.*");
585 matchall_filter.set_name (_("All files"));
587 chooser.add_filter (audio_and_midi_filter);
588 chooser.add_filter (audio_filter);
589 chooser.add_filter (midi_filter);
590 chooser.add_filter (matchall_filter);
591 chooser.set_select_multiple (true);
592 chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
593 chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
596 /* some broken redraw behaviour - this is a bandaid */
597 chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
600 if (!persistent_folder.empty()) {
601 chooser.set_current_folder (persistent_folder);
604 notebook.append_page (chooser, _("Browse Files"));
606 hpacker.set_spacing (6);
607 hpacker.pack_start (notebook, true, true);
608 hpacker.pack_start (preview, false, false);
610 vpacker.set_spacing (6);
611 vpacker.pack_start (hpacker, true, true);
621 hbox = manage(new HBox);
622 hbox->pack_start (found_entry);
623 hbox->pack_start (found_search_btn);
625 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
626 scroll->add(found_list_view);
627 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
629 vbox = manage(new VBox);
630 vbox->pack_start (*hbox, PACK_SHRINK);
631 vbox->pack_start (*scroll);
633 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
635 found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
637 found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
639 found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
640 found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
642 notebook.append_page (*vbox, _("Search Tags"));
644 //add freesound search
649 passbox = manage(new HBox);
650 passbox->set_spacing (6);
652 label = manage (new Label);
653 label->set_text (_("Tags:"));
654 passbox->pack_start (*label, false, false);
655 passbox->pack_start (freesound_entry, true, true);
657 label = manage (new Label);
658 label->set_text (_("Sort:"));
659 passbox->pack_start (*label, false, false);
660 passbox->pack_start (freesound_sort, false, false);
661 freesound_sort.clear_items();
663 // Order of the following must correspond with enum sortMethod
664 // in sfdb_freesound_mootcher.h
665 freesound_sort.append_text(_("None"));
666 freesound_sort.append_text(_("Longest"));
667 freesound_sort.append_text(_("Shortest"));
668 freesound_sort.append_text(_("Newest"));
669 freesound_sort.append_text(_("Oldest"));
670 freesound_sort.append_text(_("Most downloaded"));
671 freesound_sort.append_text(_("Least downloaded"));
672 freesound_sort.append_text(_("Highest rated"));
673 freesound_sort.append_text(_("Lowest rated"));
674 freesound_sort.set_active(0);
676 passbox->pack_start (freesound_search_btn, false, false);
677 passbox->pack_start (freesound_more_btn, false, false);
678 freesound_more_btn.set_label(_("More"));
679 freesound_more_btn.set_sensitive(false);
681 passbox->pack_start (freesound_similar_btn, false, false);
682 freesound_similar_btn.set_label(_("Similar"));
683 freesound_similar_btn.set_sensitive(false);
685 scroll = manage(new ScrolledWindow);
686 scroll->add(freesound_list_view);
687 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
689 vbox = manage(new VBox);
690 vbox->set_spacing (3);
691 vbox->pack_start (*passbox, PACK_SHRINK);
692 vbox->pack_start (*scroll);
694 freesound_list_view.append_column(_("ID") , freesound_list_columns.id);
695 freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
696 // freesound_list_view.append_column(_("URI") , freesound_list_columns.uri);
697 freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
698 freesound_list_view.append_column(_("Size"), freesound_list_columns.filesize);
699 freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
700 freesound_list_view.append_column(_("License"), freesound_list_columns.license);
701 freesound_list_view.get_column(0)->set_alignment(0.5);
702 freesound_list_view.get_column(1)->set_expand(true); // filename
703 freesound_list_view.get_column(1)->set_resizable(true); // filename
704 freesound_list_view.get_column(2)->set_alignment(0.5);
705 freesound_list_view.get_column(3)->set_alignment(0.5);
706 freesound_list_view.get_column(4)->set_alignment(0.5);
707 freesound_list_view.get_column(5)->set_alignment(0.5);
709 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
710 freesound_list_view.set_tooltip_column(1);
712 freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
713 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
714 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
715 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
716 freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
717 freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
718 notebook.append_page (*vbox, _("Search Freesound"));
720 notebook.set_size_request (500, -1);
721 notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
725 Gtk::HButtonBox* button_box = manage (new HButtonBox);
727 button_box->set_layout (BUTTONBOX_END);
728 button_box->pack_start (cancel_button, false, false);
729 cancel_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_CANCEL));
731 button_box->pack_start (apply_button, false, false);
732 apply_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_APPLY));
735 button_box->pack_start (ok_button, false, false);
736 ok_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_OK));
738 Gtkmm2ext::UI::instance()->set_tip (ok_button, _("Press to import selected files and close this window"));
739 Gtkmm2ext::UI::instance()->set_tip (apply_button, _("Press to import selected files and leave this window open"));
740 Gtkmm2ext::UI::instance()->set_tip (cancel_button, _("Press to close this window without importing any files"));
742 vpacker.pack_end (*button_box, false, false);
744 set_wmclass (X_("import"), PROGRAM_NAME);
747 SoundFileBrowser::~SoundFileBrowser ()
749 persistent_folder = chooser.get_current_folder();
753 SoundFileBrowser::run ()
762 gtk_main_iteration ();
769 SoundFileBrowser::set_action_sensitive (bool yn)
771 ok_button.set_sensitive (yn);
772 apply_button.set_sensitive (yn);
776 SoundFileBrowser::do_something (int action)
783 SoundFileBrowser::on_show ()
785 ArdourWindow::on_show ();
790 SoundFileBrowser::clear_selection ()
792 chooser.unselect_all ();
793 found_list_view.get_selection()->unselect_all ();
797 SoundFileBrowser::chooser_file_activated ()
803 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
809 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
815 SoundFileBrowser::set_session (Session* s)
817 ArdourWindow::set_session (s);
818 preview.set_session (s);
823 remove_gain_meter ();
828 SoundFileBrowser::add_gain_meter ()
832 gm = new GainMeter (_session, 250);
834 boost::shared_ptr<Route> r = _session->the_auditioner ();
836 gm->set_controls (r, r->shared_peak_meter(), r->amp());
837 gm->set_fader_name (X_("GainFader"));
839 meter_packer.set_border_width (12);
840 meter_packer.pack_start (*gm, false, true);
841 hpacker.pack_end (meter_packer, false, false);
842 meter_packer.show_all ();
847 SoundFileBrowser::remove_gain_meter ()
850 meter_packer.remove (*gm);
851 hpacker.remove (meter_packer);
858 SoundFileBrowser::start_metering ()
860 metering_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
864 SoundFileBrowser::stop_metering ()
866 metering_connection.disconnect();
870 SoundFileBrowser::meter ()
872 if (is_mapped () && _session && gm) {
873 gm->update_meters ();
878 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
880 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
884 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
886 return SMFSource::safe_midi_file_extension (filter_info.filename);
890 SoundFileBrowser::on_audio_and_midi_filter (const FileFilter::Info& filter_info)
892 return on_audio_filter (filter_info) || on_midi_filter (filter_info);
896 SoundFileBrowser::update_preview ()
898 if (preview.setup_labels (chooser.get_preview_filename())) {
899 if (preview.autoplay()) {
900 Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
906 SoundFileBrowser::found_list_view_selected ()
908 if (!reset_options ()) {
909 set_action_sensitive (false);
913 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
916 TreeIter iter = found_list->get_iter(*rows.begin());
917 file = (*iter)[found_list_columns.pathname];
918 chooser.set_filename (file);
919 set_action_sensitive (true);
921 set_action_sensitive (false);
924 preview.setup_labels (file);
929 SoundFileBrowser::found_search_clicked ()
931 string tag_string = found_entry.get_text ();
935 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
936 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
940 vector<string> results;
941 Library->search_members_and (results, tags);
944 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
945 TreeModel::iterator new_row = found_list->append();
946 TreeModel::Row row = *new_row;
947 string path = Glib::filename_from_uri (string ("file:") + *i);
948 row[found_list_columns.pathname] = path;
954 SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
957 Mootcher *mootcher = new Mootcher;
960 string id = (*iter)[freesound_list_columns.id];
961 string uri = (*iter)[freesound_list_columns.uri];
962 string ofn = (*iter)[freesound_list_columns.filename];
964 if (mootcher->checkAudioFile(ofn, id)) {
965 // file already exists, no need to download it again
966 file = mootcher->audioFileName;
968 (*iter)[freesound_list_columns.started] = false;
971 if (!(*iter)[freesound_list_columns.started]) {
972 // start downloading the sound file
973 (*iter)[freesound_list_columns.started] = true;
974 mootcher->fetchAudioFile(ofn, id, uri, this);
980 SoundFileBrowser::freesound_list_view_selected ()
983 if (!reset_options ()) {
984 set_action_sensitive (false);
987 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
988 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
989 file = freesound_get_audio_file (freesound_list->get_iter(*i));
992 switch (rows.size()) {
995 freesound_similar_btn.set_sensitive(false);
996 set_action_sensitive (false);
999 // exactly one item selected
1001 // file exists on disk already
1002 chooser.set_filename (file);
1003 preview.setup_labels (file);
1004 set_action_sensitive (true);
1006 freesound_similar_btn.set_sensitive(true);
1009 // multiple items selected
1010 preview.setup_labels ("");
1011 freesound_similar_btn.set_sensitive(false);
1019 SoundFileBrowser::refresh_display(std::string ID, std::string file)
1021 // called when the mootcher has finished downloading a file
1022 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1023 if (rows.size() == 1) {
1024 // there's a single item selected in the freesound list
1025 //XXX make a function to be used to construct the actual file name both here and in the mootcher
1026 Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
1027 std::string selected_ID = (*row)[freesound_list_columns.id];
1028 if (ID == selected_ID) {
1029 // the selected item in the freesound list is the item that has just finished downloading
1030 chooser.set_filename(file);
1031 preview.setup_labels (file);
1032 set_action_sensitive (true);
1038 SoundFileBrowser::freesound_search_clicked ()
1041 freesound_list->clear();
1047 SoundFileBrowser::freesound_more_clicked ()
1052 snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
1053 freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
1057 SoundFileBrowser::freesound_similar_clicked ()
1059 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1060 if (rows.size() == 1) {
1063 Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
1064 id = (*iter)[freesound_list_columns.id];
1065 freesound_list->clear();
1067 GdkCursor *prev_cursor;
1068 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1069 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1072 std::string theString = mootcher.searchSimilar(id);
1074 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1075 handle_freesound_results(theString);
1080 SoundFileBrowser::freesound_search()
1084 string search_string = freesound_entry.get_text ();
1085 enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
1087 GdkCursor *prev_cursor;
1088 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1089 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1092 std::string theString = mootcher.searchText(
1096 "", // OSX eats anything incl mp3
1098 "type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
1103 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1104 handle_freesound_results(theString);
1108 SoundFileBrowser::handle_freesound_results(std::string theString) {
1110 doc.read_buffer( theString );
1111 XMLNode *root = doc.root();
1114 error << "no root XML node!" << endmsg;
1118 if ( strcmp(root->name().c_str(), "response") != 0) {
1119 error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
1123 // find out how many pages are available to search
1124 int freesound_n_pages = 1;
1125 XMLNode *res = root->child("num_pages");
1127 string result = res->child("text")->content();
1128 freesound_n_pages = atoi(result);
1131 int more_pages = freesound_n_pages - freesound_page;
1133 if (more_pages > 0) {
1134 freesound_more_btn.set_sensitive(true);
1135 freesound_more_btn.set_tooltip_text(string_compose(P_(
1136 "%1 more page of 100 results available",
1137 "%1 more pages of 100 results available",
1138 more_pages), more_pages));
1140 freesound_more_btn.set_sensitive(false);
1141 freesound_more_btn.set_tooltip_text(_("No more results available"));
1144 XMLNode *sounds_root = root->child("sounds");
1146 error << "no child node \"sounds\" found!" << endmsg;
1150 XMLNodeList sounds = sounds_root->children();
1151 if (sounds.size() == 0) {
1156 XMLNodeConstIterator niter;
1158 for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
1160 if( strcmp( node->name().c_str(), "resource") != 0 ) {
1161 error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
1165 // node->dump(cerr, "node:");
1168 XMLNode *id_node = node->child ("id");
1169 XMLNode *uri_node = node->child ("serve");
1170 XMLNode *ofn_node = node->child ("original_filename");
1171 XMLNode *dur_node = node->child ("duration");
1172 XMLNode *siz_node = node->child ("filesize");
1173 XMLNode *srt_node = node->child ("samplerate");
1174 XMLNode *lic_node = node->child ("license");
1176 if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
1178 std::string id = id_node->child("text")->content();
1179 std::string uri = uri_node->child("text")->content();
1180 std::string ofn = ofn_node->child("text")->content();
1181 std::string dur = dur_node->child("text")->content();
1182 std::string siz = siz_node->child("text")->content();
1183 std::string srt = srt_node->child("text")->content();
1184 std::string lic = lic_node->child("text")->content();
1187 // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
1189 double duration_seconds = atof(dur);
1191 char duration_hhmmss[16];
1192 if (duration_seconds >= 99 * 60 * 60) {
1193 strcpy(duration_hhmmss, ">99h");
1195 s = modf(duration_seconds/60, &m) * 60;
1196 m = modf(m/60, &h) * 60;
1197 sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
1202 double size_bytes = atof(siz);
1204 if (size_bytes < 1000) {
1205 sprintf(bsize, "%.0f %s", size_bytes, _("B"));
1206 } else if (size_bytes < 1000000 ) {
1207 sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
1208 } else if (size_bytes < 10000000) {
1209 sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
1210 } else if (size_bytes < 1000000000) {
1211 sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
1213 sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
1216 /* see http://www.freesound.org/help/faq/#licenses */
1217 char shortlicense[64];
1218 if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
1219 sprintf(shortlicense, "CC-BY-NC");
1220 } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
1221 sprintf(shortlicense, "CC-BY");
1222 } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
1223 sprintf(shortlicense, "sampling+");
1224 } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
1225 sprintf(shortlicense, "PD");
1227 snprintf(shortlicense, 64, "%s", lic.c_str());
1228 shortlicense[63]= '\0';
1231 TreeModel::iterator new_row = freesound_list->append();
1232 TreeModel::Row row = *new_row;
1234 row[freesound_list_columns.id ] = id;
1235 row[freesound_list_columns.uri ] = uri;
1236 row[freesound_list_columns.filename] = ofn;
1237 row[freesound_list_columns.duration] = duration_hhmmss;
1238 row[freesound_list_columns.filesize] = bsize;
1239 row[freesound_list_columns.smplrate] = srt;
1240 row[freesound_list_columns.license ] = shortlicense;
1247 SoundFileBrowser::get_paths ()
1249 vector<string> results;
1251 int n = notebook.get_current_page ();
1254 vector<string> filenames = chooser.get_filenames();
1255 vector<string>::iterator i;
1257 for (i = filenames.begin(); i != filenames.end(); ++i) {
1259 if ((!stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
1260 results.push_back (*i);
1264 } else if (n == 1) {
1266 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1267 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1268 TreeIter iter = found_list->get_iter(*i);
1269 string str = (*iter)[found_list_columns.pathname];
1271 results.push_back (str);
1274 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1275 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1276 string str = freesound_get_audio_file (freesound_list->get_iter(*i));
1278 results.push_back (str);
1287 SoundFileOmega::reset_options_noret ()
1289 if (!resetting_ourselves) {
1290 (void) reset_options ();
1295 SoundFileOmega::reset_options ()
1297 vector<string> paths = get_paths ();
1299 if (paths.empty()) {
1301 channel_combo.set_sensitive (false);
1302 action_combo.set_sensitive (false);
1303 where_combo.set_sensitive (false);
1304 copy_files_btn.set_active (true);
1305 copy_files_btn.set_sensitive (false);
1311 channel_combo.set_sensitive (true);
1312 action_combo.set_sensitive (true);
1313 where_combo.set_sensitive (true);
1315 /* if we get through this function successfully, this may be
1316 reset at the end, once we know if we can use hard links
1317 to do embedding (or if we are importing a MIDI file).
1320 if (ARDOUR_UI::config()->get_only_copy_imported_files()) {
1321 copy_files_btn.set_sensitive (false);
1323 copy_files_btn.set_sensitive (false);
1329 bool selection_includes_multichannel;
1330 bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1333 /* See if we are thinking about importing any MIDI files */
1334 vector<string>::iterator i = paths.begin ();
1335 while (i != paths.end() && SMFSource::valid_midi_file (*i) == false) {
1338 bool const have_a_midi_file = (i != paths.end ());
1340 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1341 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1345 string existing_choice;
1346 vector<string> action_strings;
1348 resetting_ourselves = true;
1350 if (chooser.get_filter() == &audio_filter) {
1354 if (selected_audio_track_cnt > 0) {
1355 if (channel_combo.get_active_text().length()) {
1356 ImportDisposition id = get_channel_disposition();
1359 case Editing::ImportDistinctFiles:
1360 if (selected_audio_track_cnt == paths.size()) {
1361 action_strings.push_back (importmode2string (ImportToTrack));
1365 case Editing::ImportDistinctChannels:
1366 /* XXX it would be nice to allow channel-per-selected track
1367 but its too hard we don't want to deal with all the
1368 different per-file + per-track channel configurations.
1373 action_strings.push_back (importmode2string (ImportToTrack));
1383 if (selected_midi_track_cnt > 0) {
1384 action_strings.push_back (importmode2string (ImportToTrack));
1388 action_strings.push_back (importmode2string (ImportAsTrack));
1389 action_strings.push_back (importmode2string (ImportAsRegion));
1390 action_strings.push_back (importmode2string (ImportAsTapeTrack));
1392 existing_choice = action_combo.get_active_text();
1394 set_popdown_strings (action_combo, action_strings);
1396 /* preserve any existing choice, if possible */
1399 if (existing_choice.length()) {
1400 vector<string>::iterator x;
1401 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1402 if (*x == existing_choice) {
1403 action_combo.set_active_text (existing_choice);
1407 if (x == action_strings.end()) {
1408 action_combo.set_active_text (action_strings.front());
1411 action_combo.set_active_text (action_strings.front());
1414 resetting_ourselves = false;
1416 if ((mode = get_mode()) == ImportAsRegion) {
1417 where_combo.set_sensitive (false);
1419 where_combo.set_sensitive (true);
1422 vector<string> channel_strings;
1424 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1425 channel_strings.push_back (_("one track per file"));
1427 if (selection_includes_multichannel) {
1428 channel_strings.push_back (_("one track per channel"));
1431 if (paths.size() > 1) {
1432 /* tape tracks are a single region per track, so we cannot
1433 sequence multiple files.
1435 if (mode != ImportAsTapeTrack) {
1436 channel_strings.push_back (_("sequence files"));
1439 channel_strings.push_back (_("all files in one track"));
1440 channel_strings.push_back (_("merge files"));
1446 channel_strings.push_back (_("one region per file"));
1448 if (selection_includes_multichannel) {
1449 channel_strings.push_back (_("one region per channel"));
1452 if (paths.size() > 1) {
1454 channel_strings.push_back (_("all files in one region"));
1459 resetting_ourselves = true;
1461 existing_choice = channel_combo.get_active_text();
1463 set_popdown_strings (channel_combo, channel_strings);
1465 /* preserve any existing choice, if possible */
1467 if (existing_choice.length()) {
1468 vector<string>::iterator x;
1469 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1470 if (*x == existing_choice) {
1471 channel_combo.set_active_text (existing_choice);
1475 if (x == channel_strings.end()) {
1476 channel_combo.set_active_text (channel_strings.front());
1479 channel_combo.set_active_text (channel_strings.front());
1482 resetting_ourselves = false;
1485 src_combo.set_sensitive (true);
1487 src_combo.set_sensitive (false);
1490 /* We must copy MIDI files or those from Freesound
1491 * or any file if we are under nsm control */
1492 bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
1494 if (ARDOUR_UI::config()->get_only_copy_imported_files()) {
1496 if (selection_can_be_embedded_with_links && !must_copy) {
1497 copy_files_btn.set_sensitive (true);
1500 copy_files_btn.set_active (true);
1502 copy_files_btn.set_sensitive (false);
1508 copy_files_btn.set_active (true);
1510 copy_files_btn.set_sensitive (!must_copy);
1518 SoundFileOmega::bad_file_message()
1520 MessageDialog msg (*this,
1521 string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1526 resetting_ourselves = true;
1527 chooser.unselect_uri (chooser.get_preview_uri());
1528 resetting_ourselves = false;
1534 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1543 multichannel = false;
1545 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1547 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1548 if (info.channels > 1) {
1549 multichannel = true;
1554 if (sz != info.length) {
1559 if (info.samplerate != _session->frame_rate()) {
1563 } else if (SMFSource::valid_midi_file (*i)) {
1567 if (reader.num_tracks() > 1) {
1568 multichannel = true; // "channel" == track here...
1571 /* XXX we need err = true handling here in case
1572 we can't check the file
1585 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1587 #ifdef PLATFORM_WINDOWS
1590 std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
1593 if (mkdir (tmpdir.c_str(), 0744)) {
1594 if (errno != EEXIST) {
1599 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1601 char tmpc[PATH_MAX+1];
1603 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1607 if (link ((*i).c_str(), tmpc)) {
1617 rmdir (tmpdir.c_str());
1622 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
1623 : SoundFileBrowser (title, s, false)
1625 chooser.set_select_multiple (false);
1626 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1627 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1631 SoundFileChooser::on_hide ()
1633 ArdourWindow::on_hide();
1637 _session->cancel_audition();
1642 SoundFileChooser::get_filename ()
1644 vector<string> paths;
1646 paths = get_paths ();
1648 if (paths.empty()) {
1652 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1656 return paths.front();
1659 SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s,
1660 uint32_t selected_audio_tracks,
1661 uint32_t selected_midi_tracks,
1663 Editing::ImportMode mode_hint)
1664 : SoundFileBrowser (title, s, persistent)
1665 , copy_files_btn ( _("Copy files to session"))
1666 , selected_audio_track_cnt (selected_audio_tracks)
1667 , selected_midi_track_cnt (selected_midi_tracks)
1673 set_size_request (-1, 450);
1675 block_two.set_border_width (12);
1676 block_three.set_border_width (12);
1677 block_four.set_border_width (12);
1679 options.set_spacing (12);
1682 str.push_back (_("file timestamp"));
1683 str.push_back (_("edit point"));
1684 str.push_back (_("playhead"));
1685 str.push_back (_("session start"));
1686 set_popdown_strings (where_combo, str);
1687 where_combo.set_active_text (str.front());
1688 where_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::where_combo_changed));
1690 Label* l = manage (new Label);
1691 l->set_markup (_("<b>Add files as ...</b>"));
1693 vbox = manage (new VBox);
1694 vbox->set_border_width (12);
1695 vbox->set_spacing (6);
1696 vbox->pack_start (*l, false, false);
1697 vbox->pack_start (action_combo, false, false);
1698 hbox = manage (new HBox);
1699 hbox->pack_start (*vbox, false, false);
1700 options.pack_start (*hbox, false, false);
1702 /* dummy entry for action combo so that it doesn't look odd if we
1703 come up with no tracks selected.
1707 str.push_back (importmode2string (mode_hint));
1708 set_popdown_strings (action_combo, str);
1709 action_combo.set_active_text (str.front());
1710 action_combo.set_sensitive (false);
1712 l = manage (new Label);
1713 l->set_markup (_("<b>Insert at</b>"));
1715 vbox = manage (new VBox);
1716 vbox->set_border_width (12);
1717 vbox->set_spacing (6);
1718 vbox->pack_start (*l, false, false);
1719 vbox->pack_start (where_combo, false, false);
1720 hbox = manage (new HBox);
1721 hbox->pack_start (*vbox, false, false);
1722 options.pack_start (*hbox, false, false);
1725 l = manage (new Label);
1726 l->set_markup (_("<b>Mapping</b>"));
1728 vbox = manage (new VBox);
1729 vbox->set_border_width (12);
1730 vbox->set_spacing (6);
1731 vbox->pack_start (*l, false, false);
1732 vbox->pack_start (channel_combo, false, false);
1733 hbox = manage (new HBox);
1734 hbox->pack_start (*vbox, false, false);
1735 options.pack_start (*hbox, false, false);
1738 str.push_back (_("one track per file"));
1739 set_popdown_strings (channel_combo, str);
1740 channel_combo.set_active_text (str.front());
1741 channel_combo.set_sensitive (false);
1743 l = manage (new Label);
1744 l->set_markup (_("<b>Conversion quality</b>"));
1746 vbox = manage (new VBox);
1747 vbox->set_border_width (12);
1748 vbox->set_spacing (6);
1749 vbox->pack_start (*l, false, false);
1750 vbox->pack_start (src_combo, false, false);
1751 hbox = manage (new HBox);
1752 hbox->pack_start (*vbox, false, false);
1753 options.pack_start (*hbox, false, false);
1755 l = manage (new Label);
1756 l->set_markup (_("<b>Instrument</b>"));
1758 vbox = manage (new VBox);
1759 vbox->set_border_width (12);
1760 vbox->set_spacing (6);
1761 vbox->pack_start (*l, false, false);
1762 vbox->pack_start (instrument_combo, false, false);
1763 hbox = manage (new HBox);
1764 hbox->pack_start (*vbox, false, false);
1765 options.pack_start (*hbox, false, false);
1768 str.push_back (_("Best"));
1769 str.push_back (_("Good"));
1770 str.push_back (_("Quick"));
1771 str.push_back (_("Fast"));
1772 str.push_back (_("Fastest"));
1774 set_popdown_strings (src_combo, str);
1775 src_combo.set_active_text (str.front());
1776 src_combo.set_sensitive (false);
1777 src_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::src_combo_changed));
1781 action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1782 channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1784 copy_files_btn.set_active (true);
1786 Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1789 copy_label->set_size_request (175, -1);
1790 copy_label->set_line_wrap (true);
1793 block_four.pack_start (copy_files_btn, false, false);
1795 options.pack_start (block_four, false, false);
1797 vpacker.pack_start (options, false, false);
1799 /* setup disposition map */
1801 disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1802 disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1803 disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1804 disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1806 disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1807 disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1808 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1809 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1811 chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1813 /* set size requests for a couple of combos to allow them to display the longest text
1814 they will ever be asked to display. This prevents them being resized when the user
1815 selects a file to import, which in turn prevents the size of the dialog from jumping
1819 t.push_back (_("one track per file"));
1820 t.push_back (_("one track per channel"));
1821 t.push_back (_("sequence files"));
1822 t.push_back (_("all files in one region"));
1823 set_popdown_strings (channel_combo, t);
1826 t.push_back (importmode2string (ImportAsTrack));
1827 t.push_back (importmode2string (ImportToTrack));
1828 t.push_back (importmode2string (ImportAsRegion));
1829 t.push_back (importmode2string (ImportAsTapeTrack));
1830 set_popdown_strings (action_combo, t);
1834 SoundFileOmega::set_mode (ImportMode mode)
1836 action_combo.set_active_text (importmode2string (mode));
1840 SoundFileOmega::get_mode () const
1842 return string2importmode (action_combo.get_active_text());
1846 SoundFileOmega::on_hide ()
1848 ArdourWindow::on_hide();
1850 _session->cancel_audition();
1855 SoundFileOmega::get_position() const
1857 string str = where_combo.get_active_text();
1859 if (str == _("file timestamp")) {
1860 return ImportAtTimestamp;
1861 } else if (str == _("edit point")) {
1862 return ImportAtEditPoint;
1863 } else if (str == _("playhead")) {
1864 return ImportAtPlayhead;
1866 return ImportAtStart;
1871 SoundFileOmega::get_src_quality() const
1873 string str = src_combo.get_active_text();
1875 if (str == _("Best")) {
1877 } else if (str == _("Good")) {
1879 } else if (str == _("Quick")) {
1881 } else if (str == _("Fast")) {
1889 SoundFileOmega::src_combo_changed()
1891 preview.set_src_quality(get_src_quality());
1895 SoundFileOmega::where_combo_changed()
1897 preview.set_import_position(get_position());
1901 SoundFileOmega::get_channel_disposition () const
1903 /* we use a map here because the channel combo can contain different strings
1904 depending on the state of the other combos. the map contains all possible strings
1905 and the ImportDisposition enum that corresponds to it.
1908 string str = channel_combo.get_active_text();
1909 DispositionMap::const_iterator x = disposition_map.find (str);
1911 if (x == disposition_map.end()) {
1912 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1913 abort(); /*NOTREACHED*/
1920 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
1922 selected_audio_track_cnt = selected_audio_tracks;
1923 selected_midi_track_cnt = selected_midi_tracks;
1925 if (selected_audio_track_cnt == 0 && selected_midi_track_cnt > 0) {
1926 chooser.set_filter (midi_filter);
1927 } else if (selected_midi_track_cnt == 0 && selected_audio_track_cnt > 0) {
1928 chooser.set_filter (audio_filter);
1930 chooser.set_filter (audio_and_midi_filter);
1937 SoundFileOmega::file_selection_changed ()
1939 if (resetting_ourselves) {
1943 if (!reset_options ()) {
1944 set_action_sensitive (false);
1946 if (chooser.get_filenames().size() > 0) {
1947 set_action_sensitive (true);
1949 set_action_sensitive (false);
1955 SoundFileOmega::do_something (int action)
1957 SoundFileBrowser::do_something (action);
1959 if (action == RESPONSE_CANCEL) {
1966 vector<string> paths = get_paths ();
1967 ImportPosition pos = get_position ();
1968 ImportMode mode = get_mode ();
1969 ImportDisposition chns = get_channel_disposition ();
1970 PluginInfoPtr instrument = instrument_combo.selected_instrument();
1974 case ImportAtEditPoint:
1975 where = PublicEditor::instance().get_preferred_edit_position ();
1977 case ImportAtTimestamp:
1980 case ImportAtPlayhead:
1981 where = _session->transport_frame();
1984 where = _session->current_start_frame();
1988 SrcQuality quality = get_src_quality();
1990 if (copy_files_btn.get_active()) {
1991 PublicEditor::instance().do_import (paths, chns, mode, quality, where, instrument);
1993 PublicEditor::instance().do_embed (paths, chns, mode, where, instrument);
1996 if (action == RESPONSE_OK) {