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 <glib/gstdio.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"
72 #include "sfdb_freesound_mootcher.h"
74 using namespace ARDOUR;
78 using namespace Gtkmm2ext;
79 using namespace Editing;
83 string SoundFileBrowser::persistent_folder;
84 typedef TreeView::Selection::ListHandle_Path ListPath;
87 string2importmode (string str)
89 if (str == _("as new tracks")) {
91 } else if (str == _("to selected tracks")) {
93 } else if (str == _("to region list")) {
94 return ImportAsRegion;
95 } else if (str == _("as new tape tracks")) {
96 return ImportAsTapeTrack;
99 warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
101 return ImportAsTrack;
105 importmode2string (ImportMode mode)
109 return _("as new tracks");
111 return _("to selected tracks");
113 return _("to region list");
114 case ImportAsTapeTrack:
115 return _("as new tape tracks");
117 abort(); /*NOTREACHED*/
118 return _("as new tracks");
121 SoundFileBox::SoundFileBox (bool /*persistent*/)
123 length_clock ("sfboxLengthClock", true, "", false, false, true, false),
124 timecode_clock ("sfboxTimecodeClock", true, "", false, false, false, false),
126 autoplay_btn (_("Auto-play")),
127 seek_slider(0,1000,1),
131 set_name (X_("SoundFileBox"));
132 set_size_request (300, -1);
134 preview_label.set_markup (_("<b>Sound File Information</b>"));
136 border_frame.set_label_widget (preview_label);
137 border_frame.add (main_box);
139 pack_start (border_frame, true, true);
140 set_border_width (6);
142 main_box.set_border_width (6);
144 length.set_text (_("Length:"));
145 length.set_alignment (1, 0.5);
146 timecode.set_text (_("Timestamp:"));
147 timecode.set_alignment (1, 0.5);
148 format.set_text (_("Format:"));
149 format.set_alignment (1, 0.5);
150 channels.set_text (_("Channels:"));
151 channels.set_alignment (1, 0.5);
152 samplerate.set_text (_("Sample rate:"));
153 samplerate.set_alignment (1, 0.5);
155 preview_label.set_max_width_chars (50);
156 preview_label.set_ellipsize (Pango::ELLIPSIZE_END);
158 format_text.set_max_width_chars (20);
159 format_text.set_ellipsize (Pango::ELLIPSIZE_END);
160 format_text.set_alignment (0, 1);
162 table.set_col_spacings (6);
163 table.set_homogeneous (false);
164 table.set_row_spacings (6);
166 table.attach (channels, 0, 1, 0, 1, FILL, FILL);
167 table.attach (samplerate, 0, 1, 1, 2, FILL, FILL);
168 table.attach (format, 0, 1, 2, 4, FILL, FILL);
169 table.attach (length, 0, 1, 4, 5, FILL, FILL);
170 table.attach (timecode, 0, 1, 5, 6, FILL, FILL);
172 table.attach (channels_value, 1, 2, 0, 1, FILL, FILL);
173 table.attach (samplerate_value, 1, 2, 1, 2, FILL, FILL);
174 table.attach (format_text, 1, 2, 2, 4, FILL, FILL);
175 table.attach (length_clock, 1, 2, 4, 5, FILL, FILL);
176 table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL);
178 length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock->mode());
179 timecode_clock.set_mode (AudioClock::Timecode);
181 main_box.pack_start (table, false, false);
183 tags_entry.set_editable (true);
184 tags_entry.set_wrap_mode(Gtk::WRAP_WORD);
185 tags_entry.signal_focus_out_event().connect (sigc::mem_fun (*this, &SoundFileBox::tags_entry_left));
187 Label* label = manage (new Label (_("Tags:")));
188 label->set_alignment (0.0f, 0.5f);
189 main_box.pack_start (*label, false, false);
190 main_box.pack_start (tags_entry, true, true);
192 main_box.pack_start (bottom_box, false, false);
194 play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
195 // play_btn.set_label (_("Play"));
197 stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
198 // stop_btn.set_label (_("Stop"));
200 bottom_box.set_homogeneous (false);
201 bottom_box.set_spacing (6);
202 bottom_box.pack_start(play_btn, true, true);
203 bottom_box.pack_start(stop_btn, true, true);
204 bottom_box.pack_start(autoplay_btn, false, false);
206 seek_slider.set_draw_value(false);
208 seek_slider.add_events(Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
209 seek_slider.signal_button_press_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_press), false);
210 seek_slider.signal_button_release_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_release), false);
211 main_box.pack_start (seek_slider, false, false);
213 play_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::audition));
214 stop_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::stop_audition));
216 stop_btn.set_sensitive (false);
218 channels_value.set_alignment (0.0f, 0.5f);
219 samplerate_value.set_alignment (0.0f, 0.5f);
223 SoundFileBox::set_session(Session* s)
225 SessionHandlePtr::set_session (s);
227 length_clock.set_session (s);
228 timecode_clock.set_session (s);
231 play_btn.set_sensitive (false);
232 stop_btn.set_sensitive (false);
233 auditioner_connections.drop_connections();
235 auditioner_connections.drop_connections();
236 _session->AuditionActive.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_active, this, _1), gui_context());
237 _session->the_auditioner()->AuditionProgress.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_progress, this, _1, _2), gui_context());
242 SoundFileBox::audition_active(bool active) {
243 stop_btn.set_sensitive (active);
244 seek_slider.set_sensitive (active);
246 seek_slider.set_value(0);
251 SoundFileBox::audition_progress(ARDOUR::framecnt_t pos, ARDOUR::framecnt_t len) {
253 seek_slider.set_value( 1000.0 * pos / len);
254 seek_slider.set_sensitive (true);
259 SoundFileBox::seek_button_press(GdkEventButton*) {
261 return false; // pass on to slider
265 SoundFileBox::seek_button_release(GdkEventButton*) {
267 _session->the_auditioner()->seek_to_percent(seek_slider.get_value() / 10.0);
268 seek_slider.set_sensitive (false);
269 return false; // pass on to slider
273 SoundFileBox::setup_labels (const string& filename)
276 // save existing tags
284 if (SMFSource::valid_midi_file (path)) {
286 boost::shared_ptr<SMFSource> ms;
288 ms = boost::dynamic_pointer_cast<SMFSource> (
289 SourceFactory::createExternal (DataType::MIDI, *_session,
290 path, 0, Source::Flag (0), false));
291 } catch (const std::exception& e) {
292 error << string_compose(_("Could not read file: %1 (%2)."),
293 path, e.what()) << endmsg;
296 preview_label.set_markup (_("<b>Midi File Information</b>"));
298 format_text.set_text ("MIDI");
299 samplerate_value.set_text ("-");
300 tags_entry.get_buffer()->set_text ("");
301 timecode_clock.set (0);
302 tags_entry.set_sensitive (false);
305 channels_value.set_text (to_string(ms->num_tracks(), std::dec));
306 length_clock.set (ms->length(ms->timeline_position()));
308 channels_value.set_text ("");
309 length_clock.set (0);
312 if (_session && ms) {
313 play_btn.set_sensitive (true);
315 play_btn.set_sensitive (false);
321 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
323 preview_label.set_markup (_("<b>Sound File Information</b>"));
324 format_text.set_text ("");
325 channels_value.set_text ("");
326 samplerate_value.set_text ("");
327 tags_entry.get_buffer()->set_text ("");
329 length_clock.set (0);
330 timecode_clock.set (0);
332 tags_entry.set_sensitive (false);
333 play_btn.set_sensitive (false);
338 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::Markup::escape_text (Glib::path_get_basename (filename))));
339 std::string n = sf_info.format_name;
340 if (n.substr (0, 8) == X_("Format: ")) {
343 format_text.set_text (n);
344 channels_value.set_text (to_string (sf_info.channels, std::dec));
346 if (_session && sf_info.samplerate != _session->frame_rate()) {
347 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
348 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
349 samplerate_value.set_name ("NewSessionSR1Label");
350 samplerate.set_name ("NewSessionSR1Label");
352 samplerate.set_text (_("Sample rate:"));
353 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
354 samplerate_value.set_name ("NewSessionSR2Label");
355 samplerate.set_name ("NewSessionSR2Label");
358 framecnt_t const nfr = _session ? _session->nominal_frame_rate() : 25;
359 double src_coef = (double) nfr / sf_info.samplerate;
361 length_clock.set (sf_info.length * src_coef + 0.5, true);
362 timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
364 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
366 vector<string> tags = Library->get_tags (string ("//") + filename);
368 stringstream tag_string;
369 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
370 if (i != tags.begin()) {
375 tags_entry.get_buffer()->set_text (tag_string.str());
377 tags_entry.set_sensitive (true);
379 play_btn.set_sensitive (true);
386 SoundFileBox::autoplay() const
388 return autoplay_btn.get_active();
392 SoundFileBox::audition_oneshot()
399 SoundFileBox::audition ()
405 _session->cancel_audition();
407 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
408 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
412 boost::shared_ptr<Region> r;
414 if (SMFSource::valid_midi_file (path)) {
416 boost::shared_ptr<SMFSource> ms =
417 boost::dynamic_pointer_cast<SMFSource> (
418 SourceFactory::createExternal (DataType::MIDI, *_session,
419 path, 0, Source::Flag (0), false));
421 string rname = region_name_from_path (ms->path(), false);
425 plist.add (ARDOUR::Properties::start, 0);
426 plist.add (ARDOUR::Properties::length, ms->length(ms->timeline_position()));
427 plist.add (ARDOUR::Properties::name, rname);
428 plist.add (ARDOUR::Properties::layer, 0);
430 r = boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (boost::dynamic_pointer_cast<Source>(ms), plist, false));
436 boost::shared_ptr<AudioFileSource> afs;
437 bool old_sbp = AudioSource::get_build_peakfiles ();
439 /* don't even think of building peakfiles for these files */
441 AudioSource::set_build_peakfiles (false);
443 for (int n = 0; n < sf_info.channels; ++n) {
445 afs = boost::dynamic_pointer_cast<AudioFileSource> (
446 SourceFactory::createExternal (DataType::AUDIO, *_session,
448 Source::Flag (ARDOUR::AudioFileSource::NoPeakFile), false));
449 if (afs->sample_rate() != _session->nominal_frame_rate()) {
450 boost::shared_ptr<SrcFileSource> sfs (new SrcFileSource(*_session, afs, _src_quality));
451 srclist.push_back(sfs);
453 srclist.push_back(afs);
456 } catch (failed_constructor& err) {
457 error << _("Could not access soundfile: ") << path << endmsg;
458 AudioSource::set_build_peakfiles (old_sbp);
463 AudioSource::set_build_peakfiles (old_sbp);
465 if (srclist.empty()) {
469 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
470 string rname = region_name_from_path (afs->path(), false);
474 plist.add (ARDOUR::Properties::start, 0);
475 plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->timeline_position()));
476 plist.add (ARDOUR::Properties::name, rname);
477 plist.add (ARDOUR::Properties::layer, 0);
479 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false));
482 frameoffset_t audition_position = 0;
483 switch(_import_position) {
484 case ImportAtTimestamp:
485 audition_position = 0;
487 case ImportAtPlayhead:
488 audition_position = _session->transport_frame();
491 audition_position = _session->current_start_frame();
493 case ImportAtEditPoint:
494 audition_position = PublicEditor::instance().get_preferred_edit_position ();
497 r->set_position(audition_position);
499 _session->audition_region(r);
503 SoundFileBox::stop_audition ()
506 _session->cancel_audition();
511 SoundFileBox::tags_entry_left (GdkEventFocus *)
518 SoundFileBox::tags_changed ()
520 string tag_string = tags_entry.get_buffer()->get_text ();
522 if (tag_string.empty()) {
528 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
529 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
537 SoundFileBox::save_tags (const vector<string>& tags)
539 Library->set_tags (string ("//") + path, tags);
540 Library->save_changes ();
543 SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persistent)
544 : ArdourWindow (title)
545 , found_list (ListStore::create(found_list_columns))
546 , freesound_list (ListStore::create(freesound_list_columns))
547 , chooser (FILE_CHOOSER_ACTION_OPEN)
548 , preview (persistent)
549 , found_search_btn (_("Search"))
550 , found_list_view (found_list)
551 , freesound_search_btn (_("Search"))
552 , freesound_list_view (freesound_list)
553 , resetting_ourselves (false)
557 , ok_button (Stock::OK)
558 , close_button (Stock::CLOSE)
559 , apply_button (Stock::APPLY)
564 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
565 chooser.add_shortcut_folder_uri("file:///Library/Audio/Apple Loops");
566 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
567 chooser.add_shortcut_folder_uri("file:///Volumes");
570 //add the file chooser
572 chooser.set_border_width (12);
574 audio_and_midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun (*this, &SoundFileBrowser::on_audio_and_midi_filter));
575 audio_and_midi_filter.set_name (_("Audio and MIDI files"));
577 audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
578 audio_filter.set_name (_("Audio files"));
580 midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
581 midi_filter.set_name (_("MIDI files"));
583 matchall_filter.add_pattern ("*.*");
584 matchall_filter.set_name (_("All files"));
586 chooser.add_filter (audio_and_midi_filter);
587 chooser.add_filter (audio_filter);
588 chooser.add_filter (midi_filter);
589 chooser.add_filter (matchall_filter);
590 chooser.set_select_multiple (true);
591 chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
592 chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
595 /* some broken redraw behaviour - this is a bandaid */
596 chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
599 if (!persistent_folder.empty()) {
600 chooser.set_current_folder (persistent_folder);
603 notebook.append_page (chooser, _("Browse Files"));
605 hpacker.set_spacing (6);
606 hpacker.pack_start (notebook, true, true);
607 hpacker.pack_start (preview, false, false);
609 vpacker.set_spacing (6);
610 vpacker.pack_start (hpacker, true, true);
620 hbox = manage(new HBox);
621 hbox->pack_start (found_entry);
622 hbox->pack_start (found_search_btn);
624 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
625 scroll->add(found_list_view);
626 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
628 vbox = manage(new VBox);
629 vbox->pack_start (*hbox, PACK_SHRINK);
630 vbox->pack_start (*scroll);
632 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
634 found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
636 found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
638 found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
639 found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
641 notebook.append_page (*vbox, _("Search Tags"));
643 //add freesound search
648 passbox = manage(new HBox);
649 passbox->set_spacing (6);
651 label = manage (new Label);
652 label->set_text (_("Tags:"));
653 passbox->pack_start (*label, false, false);
654 passbox->pack_start (freesound_entry, true, true);
656 label = manage (new Label);
657 label->set_text (_("Sort:"));
658 passbox->pack_start (*label, false, false);
659 passbox->pack_start (freesound_sort, false, false);
660 freesound_sort.clear_items();
662 // Order of the following must correspond with enum sortMethod
663 // in sfdb_freesound_mootcher.h
664 freesound_sort.append_text(_("None"));
665 freesound_sort.append_text(_("Longest"));
666 freesound_sort.append_text(_("Shortest"));
667 freesound_sort.append_text(_("Newest"));
668 freesound_sort.append_text(_("Oldest"));
669 freesound_sort.append_text(_("Most downloaded"));
670 freesound_sort.append_text(_("Least downloaded"));
671 freesound_sort.append_text(_("Highest rated"));
672 freesound_sort.append_text(_("Lowest rated"));
673 freesound_sort.set_active(0);
675 passbox->pack_start (freesound_search_btn, false, false);
676 passbox->pack_start (freesound_more_btn, false, false);
677 freesound_more_btn.set_label(_("More"));
678 freesound_more_btn.set_sensitive(false);
680 passbox->pack_start (freesound_similar_btn, false, false);
681 freesound_similar_btn.set_label(_("Similar"));
682 freesound_similar_btn.set_sensitive(false);
684 scroll = manage(new ScrolledWindow);
685 scroll->add(freesound_list_view);
686 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
688 vbox = manage(new VBox);
689 vbox->set_spacing (3);
690 vbox->pack_start (*passbox, PACK_SHRINK);
691 vbox->pack_start (*scroll);
693 freesound_list_view.append_column(_("ID") , freesound_list_columns.id);
694 freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
695 // freesound_list_view.append_column(_("URI") , freesound_list_columns.uri);
696 freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
697 freesound_list_view.append_column(_("Size"), freesound_list_columns.filesize);
698 freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
699 freesound_list_view.append_column(_("License"), freesound_list_columns.license);
700 freesound_list_view.get_column(0)->set_alignment(0.5);
701 freesound_list_view.get_column(1)->set_expand(true); // filename
702 freesound_list_view.get_column(1)->set_resizable(true); // filename
703 freesound_list_view.get_column(2)->set_alignment(0.5);
704 freesound_list_view.get_column(3)->set_alignment(0.5);
705 freesound_list_view.get_column(4)->set_alignment(0.5);
706 freesound_list_view.get_column(5)->set_alignment(0.5);
708 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
709 freesound_list_view.set_tooltip_column(1);
711 freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
712 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
713 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
714 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
715 freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
716 freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
717 notebook.append_page (*vbox, _("Search Freesound"));
719 notebook.set_size_request (500, -1);
720 notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
724 Gtk::HButtonBox* button_box = manage (new HButtonBox);
726 button_box->set_layout (BUTTONBOX_END);
727 button_box->pack_start (close_button, false, false);
728 close_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_CLOSE));
730 button_box->pack_start (apply_button, false, false);
731 apply_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_APPLY));
734 button_box->pack_start (ok_button, false, false);
735 ok_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_OK));
737 Gtkmm2ext::UI::instance()->set_tip (ok_button, _("Press to import selected files and close this window"));
738 Gtkmm2ext::UI::instance()->set_tip (apply_button, _("Press to import selected files and leave this window open"));
739 Gtkmm2ext::UI::instance()->set_tip (close_button, _("Press to close this window without importing any files"));
741 vpacker.pack_end (*button_box, false, false);
743 set_wmclass (X_("import"), PROGRAM_NAME);
746 SoundFileBrowser::~SoundFileBrowser ()
748 persistent_folder = chooser.get_current_folder();
752 SoundFileBrowser::run ()
761 gtk_main_iteration ();
768 SoundFileBrowser::set_action_sensitive (bool yn)
770 ok_button.set_sensitive (yn);
771 apply_button.set_sensitive (yn);
775 SoundFileBrowser::do_something (int action)
782 SoundFileBrowser::on_show ()
784 ArdourWindow::on_show ();
789 SoundFileBrowser::clear_selection ()
791 chooser.unselect_all ();
792 found_list_view.get_selection()->unselect_all ();
796 SoundFileBrowser::chooser_file_activated ()
802 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
808 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
814 SoundFileBrowser::set_session (Session* s)
816 ArdourWindow::set_session (s);
817 preview.set_session (s);
822 remove_gain_meter ();
827 SoundFileBrowser::add_gain_meter ()
831 gm = new GainMeter (_session, 250);
833 boost::shared_ptr<Route> r = _session->the_auditioner ();
835 gm->set_controls (r, r->shared_peak_meter(), r->amp());
836 gm->set_fader_name (X_("GainFader"));
838 meter_packer.set_border_width (12);
839 meter_packer.pack_start (*gm, false, true);
840 hpacker.pack_end (meter_packer, false, false);
841 meter_packer.show_all ();
846 SoundFileBrowser::remove_gain_meter ()
849 meter_packer.remove (*gm);
850 hpacker.remove (meter_packer);
857 SoundFileBrowser::start_metering ()
859 metering_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
863 SoundFileBrowser::stop_metering ()
865 metering_connection.disconnect();
869 SoundFileBrowser::meter ()
871 if (is_mapped () && _session && gm) {
872 gm->update_meters ();
877 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
879 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
883 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
885 return SMFSource::safe_midi_file_extension (filter_info.filename);
889 SoundFileBrowser::on_audio_and_midi_filter (const FileFilter::Info& filter_info)
891 return on_audio_filter (filter_info) || on_midi_filter (filter_info);
895 SoundFileBrowser::update_preview ()
897 if (preview.setup_labels (chooser.get_preview_filename())) {
898 if (preview.autoplay()) {
899 Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
905 SoundFileBrowser::found_list_view_selected ()
907 if (!reset_options ()) {
908 set_action_sensitive (false);
912 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
915 TreeIter iter = found_list->get_iter(*rows.begin());
916 file = (*iter)[found_list_columns.pathname];
917 chooser.set_filename (file);
918 set_action_sensitive (true);
920 set_action_sensitive (false);
923 preview.setup_labels (file);
928 SoundFileBrowser::found_search_clicked ()
930 string tag_string = found_entry.get_text ();
934 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
935 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
939 vector<string> results;
940 Library->search_members_and (results, tags);
943 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
944 TreeModel::iterator new_row = found_list->append();
945 TreeModel::Row row = *new_row;
946 string path = Glib::filename_from_uri (string ("file:") + *i);
947 row[found_list_columns.pathname] = path;
953 SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
956 Mootcher *mootcher = new Mootcher;
959 string id = (*iter)[freesound_list_columns.id];
960 string uri = (*iter)[freesound_list_columns.uri];
961 string ofn = (*iter)[freesound_list_columns.filename];
963 if (mootcher->checkAudioFile(ofn, id)) {
964 // file already exists, no need to download it again
965 file = mootcher->audioFileName;
967 (*iter)[freesound_list_columns.started] = false;
970 if (!(*iter)[freesound_list_columns.started]) {
971 // start downloading the sound file
972 (*iter)[freesound_list_columns.started] = true;
973 mootcher->fetchAudioFile(ofn, id, uri, this);
979 SoundFileBrowser::freesound_list_view_selected ()
982 if (!reset_options ()) {
983 set_action_sensitive (false);
986 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
987 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
988 file = freesound_get_audio_file (freesound_list->get_iter(*i));
991 switch (rows.size()) {
994 freesound_similar_btn.set_sensitive(false);
995 set_action_sensitive (false);
998 // exactly one item selected
1000 // file exists on disk already
1001 chooser.set_filename (file);
1002 preview.setup_labels (file);
1003 set_action_sensitive (true);
1005 freesound_similar_btn.set_sensitive(true);
1008 // multiple items selected
1009 preview.setup_labels ("");
1010 freesound_similar_btn.set_sensitive(false);
1018 SoundFileBrowser::refresh_display(std::string ID, std::string file)
1020 // called when the mootcher has finished downloading a file
1021 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1022 if (rows.size() == 1) {
1023 // there's a single item selected in the freesound list
1024 //XXX make a function to be used to construct the actual file name both here and in the mootcher
1025 Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
1026 std::string selected_ID = (*row)[freesound_list_columns.id];
1027 if (ID == selected_ID) {
1028 // the selected item in the freesound list is the item that has just finished downloading
1029 chooser.set_filename(file);
1030 preview.setup_labels (file);
1031 set_action_sensitive (true);
1037 SoundFileBrowser::freesound_search_clicked ()
1040 freesound_list->clear();
1046 SoundFileBrowser::freesound_more_clicked ()
1051 snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
1052 freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
1056 SoundFileBrowser::freesound_similar_clicked ()
1058 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1059 if (rows.size() == 1) {
1062 Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
1063 id = (*iter)[freesound_list_columns.id];
1064 freesound_list->clear();
1066 GdkCursor *prev_cursor;
1067 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1068 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1071 std::string theString = mootcher.searchSimilar(id);
1073 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1074 handle_freesound_results(theString);
1079 SoundFileBrowser::freesound_search()
1083 string search_string = freesound_entry.get_text ();
1084 enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
1086 GdkCursor *prev_cursor;
1087 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1088 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1091 std::string theString = mootcher.searchText(
1095 "", // OSX eats anything incl mp3
1097 "type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
1102 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1103 handle_freesound_results(theString);
1107 SoundFileBrowser::handle_freesound_results(std::string theString) {
1109 doc.read_buffer( theString );
1110 XMLNode *root = doc.root();
1113 error << "no root XML node!" << endmsg;
1117 if ( strcmp(root->name().c_str(), "response") != 0) {
1118 error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
1122 // find out how many pages are available to search
1123 int freesound_n_pages = 1;
1124 XMLNode *res = root->child("num_pages");
1126 string result = res->child("text")->content();
1127 freesound_n_pages = atoi(result);
1130 int more_pages = freesound_n_pages - freesound_page;
1132 if (more_pages > 0) {
1133 freesound_more_btn.set_sensitive(true);
1134 freesound_more_btn.set_tooltip_text(string_compose(P_(
1135 "%1 more page of 100 results available",
1136 "%1 more pages of 100 results available",
1137 more_pages), more_pages));
1139 freesound_more_btn.set_sensitive(false);
1140 freesound_more_btn.set_tooltip_text(_("No more results available"));
1143 XMLNode *sounds_root = root->child("sounds");
1145 error << "no child node \"sounds\" found!" << endmsg;
1149 XMLNodeList sounds = sounds_root->children();
1150 if (sounds.size() == 0) {
1155 XMLNodeConstIterator niter;
1157 for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
1159 if( strcmp( node->name().c_str(), "resource") != 0 ) {
1160 error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
1164 // node->dump(cerr, "node:");
1167 XMLNode *id_node = node->child ("id");
1168 XMLNode *uri_node = node->child ("serve");
1169 XMLNode *ofn_node = node->child ("original_filename");
1170 XMLNode *dur_node = node->child ("duration");
1171 XMLNode *siz_node = node->child ("filesize");
1172 XMLNode *srt_node = node->child ("samplerate");
1173 XMLNode *lic_node = node->child ("license");
1175 if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
1177 std::string id = id_node->child("text")->content();
1178 std::string uri = uri_node->child("text")->content();
1179 std::string ofn = ofn_node->child("text")->content();
1180 std::string dur = dur_node->child("text")->content();
1181 std::string siz = siz_node->child("text")->content();
1182 std::string srt = srt_node->child("text")->content();
1183 std::string lic = lic_node->child("text")->content();
1186 // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
1188 double duration_seconds = atof(dur);
1190 char duration_hhmmss[16];
1191 if (duration_seconds >= 99 * 60 * 60) {
1192 strcpy(duration_hhmmss, ">99h");
1194 s = modf(duration_seconds/60, &m) * 60;
1195 m = modf(m/60, &h) * 60;
1196 sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
1201 double size_bytes = atof(siz);
1203 if (size_bytes < 1000) {
1204 sprintf(bsize, "%.0f %s", size_bytes, _("B"));
1205 } else if (size_bytes < 1000000 ) {
1206 sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
1207 } else if (size_bytes < 10000000) {
1208 sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
1209 } else if (size_bytes < 1000000000) {
1210 sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
1212 sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
1215 /* see http://www.freesound.org/help/faq/#licenses */
1216 char shortlicense[64];
1217 if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
1218 sprintf(shortlicense, "CC-BY-NC");
1219 } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
1220 sprintf(shortlicense, "CC-BY");
1221 } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
1222 sprintf(shortlicense, "sampling+");
1223 } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
1224 sprintf(shortlicense, "PD");
1226 snprintf(shortlicense, 64, "%s", lic.c_str());
1227 shortlicense[63]= '\0';
1230 TreeModel::iterator new_row = freesound_list->append();
1231 TreeModel::Row row = *new_row;
1233 row[freesound_list_columns.id ] = id;
1234 row[freesound_list_columns.uri ] = uri;
1235 row[freesound_list_columns.filename] = ofn;
1236 row[freesound_list_columns.duration] = duration_hhmmss;
1237 row[freesound_list_columns.filesize] = bsize;
1238 row[freesound_list_columns.smplrate] = srt;
1239 row[freesound_list_columns.license ] = shortlicense;
1246 SoundFileBrowser::get_paths ()
1248 vector<string> results;
1250 int n = notebook.get_current_page ();
1253 vector<string> filenames = chooser.get_filenames();
1254 vector<string>::iterator i;
1256 for (i = filenames.begin(); i != filenames.end(); ++i) {
1258 if ((!g_stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
1259 results.push_back (*i);
1263 } else if (n == 1) {
1265 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1266 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1267 TreeIter iter = found_list->get_iter(*i);
1268 string str = (*iter)[found_list_columns.pathname];
1270 results.push_back (str);
1273 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1274 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1275 string str = freesound_get_audio_file (freesound_list->get_iter(*i));
1277 results.push_back (str);
1286 SoundFileOmega::reset_options_noret ()
1288 if (!resetting_ourselves) {
1289 (void) reset_options ();
1294 SoundFileOmega::reset_options ()
1296 vector<string> paths = get_paths ();
1298 if (paths.empty()) {
1300 channel_combo.set_sensitive (false);
1301 action_combo.set_sensitive (false);
1302 where_combo.set_sensitive (false);
1303 copy_files_btn.set_active (true);
1304 copy_files_btn.set_sensitive (false);
1310 channel_combo.set_sensitive (true);
1311 action_combo.set_sensitive (true);
1312 where_combo.set_sensitive (true);
1314 /* if we get through this function successfully, this may be
1315 reset at the end, once we know if we can use hard links
1316 to do embedding (or if we are importing a MIDI file).
1319 if (ARDOUR_UI::config()->get_only_copy_imported_files()) {
1320 copy_files_btn.set_sensitive (false);
1322 copy_files_btn.set_sensitive (false);
1328 bool selection_includes_multichannel;
1329 bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1332 /* See if we are thinking about importing any MIDI files */
1333 vector<string>::iterator i = paths.begin ();
1334 while (i != paths.end() && SMFSource::valid_midi_file (*i) == false) {
1337 bool const have_a_midi_file = (i != paths.end ());
1339 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1340 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1344 string existing_choice;
1345 vector<string> action_strings;
1347 resetting_ourselves = true;
1349 if (chooser.get_filter() == &audio_filter) {
1353 if (selected_audio_track_cnt > 0) {
1354 if (channel_combo.get_active_text().length()) {
1355 ImportDisposition id = get_channel_disposition();
1358 case Editing::ImportDistinctFiles:
1359 if (selected_audio_track_cnt == paths.size()) {
1360 action_strings.push_back (importmode2string (ImportToTrack));
1364 case Editing::ImportDistinctChannels:
1365 /* XXX it would be nice to allow channel-per-selected track
1366 but its too hard we don't want to deal with all the
1367 different per-file + per-track channel configurations.
1372 action_strings.push_back (importmode2string (ImportToTrack));
1382 if (selected_midi_track_cnt > 0) {
1383 action_strings.push_back (importmode2string (ImportToTrack));
1387 action_strings.push_back (importmode2string (ImportAsTrack));
1388 action_strings.push_back (importmode2string (ImportAsRegion));
1389 action_strings.push_back (importmode2string (ImportAsTapeTrack));
1391 existing_choice = action_combo.get_active_text();
1393 set_popdown_strings (action_combo, action_strings);
1395 /* preserve any existing choice, if possible */
1398 if (existing_choice.length()) {
1399 vector<string>::iterator x;
1400 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1401 if (*x == existing_choice) {
1402 action_combo.set_active_text (existing_choice);
1406 if (x == action_strings.end()) {
1407 action_combo.set_active_text (action_strings.front());
1410 action_combo.set_active_text (action_strings.front());
1413 resetting_ourselves = false;
1415 if ((mode = get_mode()) == ImportAsRegion) {
1416 where_combo.set_sensitive (false);
1418 where_combo.set_sensitive (true);
1421 vector<string> channel_strings;
1423 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1424 channel_strings.push_back (_("one track per file"));
1426 if (selection_includes_multichannel) {
1427 channel_strings.push_back (_("one track per channel"));
1430 if (paths.size() > 1) {
1431 /* tape tracks are a single region per track, so we cannot
1432 sequence multiple files.
1434 if (mode != ImportAsTapeTrack) {
1435 channel_strings.push_back (_("sequence files"));
1438 channel_strings.push_back (_("all files in one track"));
1439 channel_strings.push_back (_("merge files"));
1445 channel_strings.push_back (_("one region per file"));
1447 if (selection_includes_multichannel) {
1448 channel_strings.push_back (_("one region per channel"));
1451 if (paths.size() > 1) {
1453 channel_strings.push_back (_("all files in one region"));
1458 resetting_ourselves = true;
1460 existing_choice = channel_combo.get_active_text();
1462 set_popdown_strings (channel_combo, channel_strings);
1464 /* preserve any existing choice, if possible */
1466 if (existing_choice.length()) {
1467 vector<string>::iterator x;
1468 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1469 if (*x == existing_choice) {
1470 channel_combo.set_active_text (existing_choice);
1474 if (x == channel_strings.end()) {
1475 channel_combo.set_active_text (channel_strings.front());
1478 channel_combo.set_active_text (channel_strings.front());
1481 resetting_ourselves = false;
1484 src_combo.set_sensitive (true);
1486 src_combo.set_sensitive (false);
1489 /* We must copy MIDI files or those from Freesound
1490 * or any file if we are under nsm control */
1491 bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
1493 if (ARDOUR_UI::config()->get_only_copy_imported_files()) {
1495 if (selection_can_be_embedded_with_links && !must_copy) {
1496 copy_files_btn.set_sensitive (true);
1499 copy_files_btn.set_active (true);
1501 copy_files_btn.set_sensitive (false);
1507 copy_files_btn.set_active (true);
1509 copy_files_btn.set_sensitive (!must_copy);
1517 SoundFileOmega::bad_file_message()
1519 MessageDialog msg (*this,
1520 string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1525 resetting_ourselves = true;
1526 chooser.unselect_uri (chooser.get_preview_uri());
1527 resetting_ourselves = false;
1533 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1542 multichannel = false;
1544 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1546 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1547 if (info.channels > 1) {
1548 multichannel = true;
1553 if (sz != info.length) {
1558 if (info.samplerate != _session->frame_rate()) {
1562 } else if (SMFSource::valid_midi_file (*i)) {
1566 if (reader.num_tracks() > 1) {
1567 multichannel = true; // "channel" == track here...
1570 /* XXX we need err = true handling here in case
1571 we can't check the file
1584 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1586 #ifdef PLATFORM_WINDOWS
1589 std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
1592 if (g_mkdir (tmpdir.c_str(), 0744)) {
1593 if (errno != EEXIST) {
1598 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1600 char tmpc[PATH_MAX+1];
1602 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1606 if (link ((*i).c_str(), tmpc)) {
1616 g_rmdir (tmpdir.c_str());
1621 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
1622 : SoundFileBrowser (title, s, false)
1624 chooser.set_select_multiple (false);
1625 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1626 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1630 SoundFileChooser::on_hide ()
1632 ArdourWindow::on_hide();
1636 _session->cancel_audition();
1641 SoundFileChooser::get_filename ()
1643 vector<string> paths;
1645 paths = get_paths ();
1647 if (paths.empty()) {
1651 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1655 return paths.front();
1658 SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s,
1659 uint32_t selected_audio_tracks,
1660 uint32_t selected_midi_tracks,
1662 Editing::ImportMode mode_hint)
1663 : SoundFileBrowser (title, s, persistent)
1664 , copy_files_btn ( _("Copy files to session"))
1665 , selected_audio_track_cnt (selected_audio_tracks)
1666 , selected_midi_track_cnt (selected_midi_tracks)
1672 set_size_request (-1, 450);
1674 block_two.set_border_width (12);
1675 block_three.set_border_width (12);
1676 block_four.set_border_width (12);
1678 options.set_spacing (12);
1681 str.push_back (_("file timestamp"));
1682 str.push_back (_("edit point"));
1683 str.push_back (_("playhead"));
1684 str.push_back (_("session start"));
1685 set_popdown_strings (where_combo, str);
1686 where_combo.set_active_text (str.front());
1687 where_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::where_combo_changed));
1689 Label* l = manage (new Label);
1690 l->set_markup (_("<b>Add files as ...</b>"));
1692 vbox = manage (new VBox);
1693 vbox->set_border_width (12);
1694 vbox->set_spacing (6);
1695 vbox->pack_start (*l, false, false);
1696 vbox->pack_start (action_combo, false, false);
1697 hbox = manage (new HBox);
1698 hbox->pack_start (*vbox, false, false);
1699 options.pack_start (*hbox, false, false);
1701 /* dummy entry for action combo so that it doesn't look odd if we
1702 come up with no tracks selected.
1706 str.push_back (importmode2string (mode_hint));
1707 set_popdown_strings (action_combo, str);
1708 action_combo.set_active_text (str.front());
1709 action_combo.set_sensitive (false);
1711 l = manage (new Label);
1712 l->set_markup (_("<b>Insert at</b>"));
1714 vbox = manage (new VBox);
1715 vbox->set_border_width (12);
1716 vbox->set_spacing (6);
1717 vbox->pack_start (*l, false, false);
1718 vbox->pack_start (where_combo, false, false);
1719 hbox = manage (new HBox);
1720 hbox->pack_start (*vbox, false, false);
1721 options.pack_start (*hbox, false, false);
1724 l = manage (new Label);
1725 l->set_markup (_("<b>Mapping</b>"));
1727 vbox = manage (new VBox);
1728 vbox->set_border_width (12);
1729 vbox->set_spacing (6);
1730 vbox->pack_start (*l, false, false);
1731 vbox->pack_start (channel_combo, false, false);
1732 hbox = manage (new HBox);
1733 hbox->pack_start (*vbox, false, false);
1734 options.pack_start (*hbox, false, false);
1737 str.push_back (_("one track per file"));
1738 set_popdown_strings (channel_combo, str);
1739 channel_combo.set_active_text (str.front());
1740 channel_combo.set_sensitive (false);
1742 l = manage (new Label);
1743 l->set_markup (_("<b>Conversion quality</b>"));
1745 vbox = manage (new VBox);
1746 vbox->set_border_width (12);
1747 vbox->set_spacing (6);
1748 vbox->pack_start (*l, false, false);
1749 vbox->pack_start (src_combo, false, false);
1750 hbox = manage (new HBox);
1751 hbox->pack_start (*vbox, false, false);
1752 options.pack_start (*hbox, false, false);
1754 l = manage (new Label);
1755 l->set_markup (_("<b>Instrument</b>"));
1757 vbox = manage (new VBox);
1758 vbox->set_border_width (12);
1759 vbox->set_spacing (6);
1760 vbox->pack_start (*l, false, false);
1761 vbox->pack_start (instrument_combo, false, false);
1762 hbox = manage (new HBox);
1763 hbox->pack_start (*vbox, false, false);
1764 options.pack_start (*hbox, false, false);
1767 str.push_back (_("Best"));
1768 str.push_back (_("Good"));
1769 str.push_back (_("Quick"));
1770 str.push_back (_("Fast"));
1771 str.push_back (_("Fastest"));
1773 set_popdown_strings (src_combo, str);
1774 src_combo.set_active_text (str.front());
1775 src_combo.set_sensitive (false);
1776 src_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::src_combo_changed));
1780 action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1781 channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1783 copy_files_btn.set_active (true);
1785 Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1788 copy_label->set_size_request (175, -1);
1789 copy_label->set_line_wrap (true);
1792 block_four.pack_start (copy_files_btn, false, false);
1794 options.pack_start (block_four, false, false);
1796 vpacker.pack_start (options, false, false);
1798 /* setup disposition map */
1800 disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1801 disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1802 disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1803 disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1805 disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1806 disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1807 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1808 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1810 chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1812 /* set size requests for a couple of combos to allow them to display the longest text
1813 they will ever be asked to display. This prevents them being resized when the user
1814 selects a file to import, which in turn prevents the size of the dialog from jumping
1818 t.push_back (_("one track per file"));
1819 t.push_back (_("one track per channel"));
1820 t.push_back (_("sequence files"));
1821 t.push_back (_("all files in one region"));
1822 set_popdown_strings (channel_combo, t);
1825 t.push_back (importmode2string (ImportAsTrack));
1826 t.push_back (importmode2string (ImportToTrack));
1827 t.push_back (importmode2string (ImportAsRegion));
1828 t.push_back (importmode2string (ImportAsTapeTrack));
1829 set_popdown_strings (action_combo, t);
1833 SoundFileOmega::set_mode (ImportMode mode)
1835 action_combo.set_active_text (importmode2string (mode));
1839 SoundFileOmega::get_mode () const
1841 return string2importmode (action_combo.get_active_text());
1845 SoundFileOmega::on_hide ()
1847 ArdourWindow::on_hide();
1849 _session->cancel_audition();
1854 SoundFileOmega::get_position() const
1856 string str = where_combo.get_active_text();
1858 if (str == _("file timestamp")) {
1859 return ImportAtTimestamp;
1860 } else if (str == _("edit point")) {
1861 return ImportAtEditPoint;
1862 } else if (str == _("playhead")) {
1863 return ImportAtPlayhead;
1865 return ImportAtStart;
1870 SoundFileOmega::get_src_quality() const
1872 string str = src_combo.get_active_text();
1874 if (str == _("Best")) {
1876 } else if (str == _("Good")) {
1878 } else if (str == _("Quick")) {
1880 } else if (str == _("Fast")) {
1888 SoundFileOmega::src_combo_changed()
1890 preview.set_src_quality(get_src_quality());
1894 SoundFileOmega::where_combo_changed()
1896 preview.set_import_position(get_position());
1900 SoundFileOmega::get_channel_disposition () const
1902 /* we use a map here because the channel combo can contain different strings
1903 depending on the state of the other combos. the map contains all possible strings
1904 and the ImportDisposition enum that corresponds to it.
1907 string str = channel_combo.get_active_text();
1908 DispositionMap::const_iterator x = disposition_map.find (str);
1910 if (x == disposition_map.end()) {
1911 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1912 abort(); /*NOTREACHED*/
1919 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
1921 selected_audio_track_cnt = selected_audio_tracks;
1922 selected_midi_track_cnt = selected_midi_tracks;
1924 if (selected_audio_track_cnt == 0 && selected_midi_track_cnt > 0) {
1925 chooser.set_filter (midi_filter);
1926 } else if (selected_midi_track_cnt == 0 && selected_audio_track_cnt > 0) {
1927 chooser.set_filter (audio_filter);
1929 chooser.set_filter (audio_and_midi_filter);
1936 SoundFileOmega::file_selection_changed ()
1938 if (resetting_ourselves) {
1942 if (!reset_options ()) {
1943 set_action_sensitive (false);
1945 if (chooser.get_filenames().size() > 0) {
1946 set_action_sensitive (true);
1948 set_action_sensitive (false);
1954 SoundFileOmega::do_something (int action)
1956 SoundFileBrowser::do_something (action);
1958 if (action == RESPONSE_CLOSE) {
1965 vector<string> paths = get_paths ();
1966 ImportPosition pos = get_position ();
1967 ImportMode mode = get_mode ();
1968 ImportDisposition chns = get_channel_disposition ();
1969 PluginInfoPtr instrument = instrument_combo.selected_instrument();
1973 case ImportAtEditPoint:
1974 where = PublicEditor::instance().get_preferred_edit_position ();
1976 case ImportAtTimestamp:
1979 case ImportAtPlayhead:
1980 where = _session->transport_frame();
1983 where = _session->current_start_frame();
1987 SrcQuality quality = get_src_quality();
1989 if (copy_files_btn.get_active()) {
1990 PublicEditor::instance().do_import (paths, chns, mode, quality, where, instrument);
1992 PublicEditor::instance().do_embed (paths, chns, mode, where, instrument);
1995 if (action == RESPONSE_OK) {