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 , import_button (_("Import"))
558 , close_button (Stock::CLOSE)
563 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
564 chooser.add_shortcut_folder_uri("file:///Library/Audio/Apple Loops");
565 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
566 chooser.add_shortcut_folder_uri("file:///Volumes");
569 //add the file chooser
571 chooser.set_border_width (12);
573 audio_and_midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun (*this, &SoundFileBrowser::on_audio_and_midi_filter));
574 audio_and_midi_filter.set_name (_("Audio and MIDI files"));
576 audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
577 audio_filter.set_name (_("Audio files"));
579 midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
580 midi_filter.set_name (_("MIDI files"));
582 matchall_filter.add_pattern ("*.*");
583 matchall_filter.set_name (_("All files"));
585 chooser.add_filter (audio_and_midi_filter);
586 chooser.add_filter (audio_filter);
587 chooser.add_filter (midi_filter);
588 chooser.add_filter (matchall_filter);
589 chooser.set_select_multiple (true);
590 chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
591 chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
594 /* some broken redraw behaviour - this is a bandaid */
595 chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
598 if (!persistent_folder.empty()) {
599 chooser.set_current_folder (persistent_folder);
602 notebook.append_page (chooser, _("Browse Files"));
604 hpacker.set_spacing (6);
605 hpacker.pack_start (notebook, true, true);
606 hpacker.pack_start (preview, false, false);
608 vpacker.set_spacing (6);
609 vpacker.pack_start (hpacker, true, true);
619 hbox = manage(new HBox);
620 hbox->pack_start (found_entry);
621 hbox->pack_start (found_search_btn);
623 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
624 scroll->add(found_list_view);
625 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
627 vbox = manage(new VBox);
628 vbox->pack_start (*hbox, PACK_SHRINK);
629 vbox->pack_start (*scroll);
631 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
633 found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
635 found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
637 found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
638 found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
640 notebook.append_page (*vbox, _("Search Tags"));
642 //add freesound search
647 passbox = manage(new HBox);
648 passbox->set_spacing (6);
650 label = manage (new Label);
651 label->set_text (_("Tags:"));
652 passbox->pack_start (*label, false, false);
653 passbox->pack_start (freesound_entry, true, true);
655 label = manage (new Label);
656 label->set_text (_("Sort:"));
657 passbox->pack_start (*label, false, false);
658 passbox->pack_start (freesound_sort, false, false);
659 freesound_sort.clear_items();
661 // Order of the following must correspond with enum sortMethod
662 // in sfdb_freesound_mootcher.h
663 freesound_sort.append_text(_("None"));
664 freesound_sort.append_text(_("Longest"));
665 freesound_sort.append_text(_("Shortest"));
666 freesound_sort.append_text(_("Newest"));
667 freesound_sort.append_text(_("Oldest"));
668 freesound_sort.append_text(_("Most downloaded"));
669 freesound_sort.append_text(_("Least downloaded"));
670 freesound_sort.append_text(_("Highest rated"));
671 freesound_sort.append_text(_("Lowest rated"));
672 freesound_sort.set_active(0);
674 passbox->pack_start (freesound_search_btn, false, false);
675 passbox->pack_start (freesound_more_btn, false, false);
676 freesound_more_btn.set_label(_("More"));
677 freesound_more_btn.set_sensitive(false);
679 passbox->pack_start (freesound_similar_btn, false, false);
680 freesound_similar_btn.set_label(_("Similar"));
681 freesound_similar_btn.set_sensitive(false);
683 scroll = manage(new ScrolledWindow);
684 scroll->add(freesound_list_view);
685 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
687 vbox = manage(new VBox);
688 vbox->set_spacing (3);
689 vbox->pack_start (*passbox, PACK_SHRINK);
690 vbox->pack_start (*scroll);
692 freesound_list_view.append_column(_("ID") , freesound_list_columns.id);
693 freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
694 // freesound_list_view.append_column(_("URI") , freesound_list_columns.uri);
695 freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
696 freesound_list_view.append_column(_("Size"), freesound_list_columns.filesize);
697 freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
698 freesound_list_view.append_column(_("License"), freesound_list_columns.license);
699 freesound_list_view.get_column(0)->set_alignment(0.5);
700 freesound_list_view.get_column(1)->set_expand(true); // filename
701 freesound_list_view.get_column(1)->set_resizable(true); // filename
702 freesound_list_view.get_column(2)->set_alignment(0.5);
703 freesound_list_view.get_column(3)->set_alignment(0.5);
704 freesound_list_view.get_column(4)->set_alignment(0.5);
705 freesound_list_view.get_column(5)->set_alignment(0.5);
707 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
708 freesound_list_view.set_tooltip_column(1);
710 freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
711 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
712 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
713 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
714 freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
715 freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
716 notebook.append_page (*vbox, _("Search Freesound"));
718 notebook.set_size_request (500, -1);
719 notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
723 Gtk::HButtonBox* button_box = manage (new HButtonBox);
725 button_box->set_layout (BUTTONBOX_END);
726 button_box->pack_start (close_button, false, false);
727 close_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_CLOSE));
729 button_box->pack_start (import_button, false, false);
730 import_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_OK));
732 Gtkmm2ext::UI::instance()->set_tip (import_button, _("Press to import selected files"));
733 Gtkmm2ext::UI::instance()->set_tip (close_button, _("Press to close this window without importing any files"));
735 vpacker.pack_end (*button_box, false, false);
737 set_wmclass (X_("import"), PROGRAM_NAME);
740 SoundFileBrowser::~SoundFileBrowser ()
742 persistent_folder = chooser.get_current_folder();
746 SoundFileBrowser::run ()
755 gtk_main_iteration ();
762 SoundFileBrowser::set_action_sensitive (bool yn)
764 import_button.set_sensitive (yn);
768 SoundFileBrowser::do_something (int action)
775 SoundFileBrowser::on_show ()
777 ArdourWindow::on_show ();
782 SoundFileBrowser::clear_selection ()
784 chooser.unselect_all ();
785 found_list_view.get_selection()->unselect_all ();
789 SoundFileBrowser::chooser_file_activated ()
795 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
801 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
807 SoundFileBrowser::set_session (Session* s)
809 ArdourWindow::set_session (s);
810 preview.set_session (s);
815 remove_gain_meter ();
820 SoundFileBrowser::add_gain_meter ()
824 gm = new GainMeter (_session, 250);
826 boost::shared_ptr<Route> r = _session->the_auditioner ();
828 gm->set_controls (r, r->shared_peak_meter(), r->amp());
829 gm->set_fader_name (X_("GainFader"));
831 meter_packer.set_border_width (12);
832 meter_packer.pack_start (*gm, false, true);
833 hpacker.pack_end (meter_packer, false, false);
834 meter_packer.show_all ();
839 SoundFileBrowser::remove_gain_meter ()
842 meter_packer.remove (*gm);
843 hpacker.remove (meter_packer);
850 SoundFileBrowser::start_metering ()
852 metering_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
856 SoundFileBrowser::stop_metering ()
858 metering_connection.disconnect();
862 SoundFileBrowser::meter ()
864 if (is_mapped () && _session && gm) {
865 gm->update_meters ();
870 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
872 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
876 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
878 return SMFSource::safe_midi_file_extension (filter_info.filename);
882 SoundFileBrowser::on_audio_and_midi_filter (const FileFilter::Info& filter_info)
884 return on_audio_filter (filter_info) || on_midi_filter (filter_info);
888 SoundFileBrowser::update_preview ()
890 if (preview.setup_labels (chooser.get_preview_filename())) {
891 if (preview.autoplay()) {
892 Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
898 SoundFileBrowser::found_list_view_selected ()
900 if (!reset_options ()) {
901 set_action_sensitive (false);
905 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
908 TreeIter iter = found_list->get_iter(*rows.begin());
909 file = (*iter)[found_list_columns.pathname];
910 chooser.set_filename (file);
911 set_action_sensitive (true);
913 set_action_sensitive (false);
916 preview.setup_labels (file);
921 SoundFileBrowser::found_search_clicked ()
923 string tag_string = found_entry.get_text ();
927 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
928 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
932 vector<string> results;
933 Library->search_members_and (results, tags);
936 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
937 TreeModel::iterator new_row = found_list->append();
938 TreeModel::Row row = *new_row;
939 string path = Glib::filename_from_uri (string ("file:") + *i);
940 row[found_list_columns.pathname] = path;
946 SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
949 Mootcher *mootcher = new Mootcher;
952 string id = (*iter)[freesound_list_columns.id];
953 string uri = (*iter)[freesound_list_columns.uri];
954 string ofn = (*iter)[freesound_list_columns.filename];
956 if (mootcher->checkAudioFile(ofn, id)) {
957 // file already exists, no need to download it again
958 file = mootcher->audioFileName;
960 (*iter)[freesound_list_columns.started] = false;
963 if (!(*iter)[freesound_list_columns.started]) {
964 // start downloading the sound file
965 (*iter)[freesound_list_columns.started] = true;
966 mootcher->fetchAudioFile(ofn, id, uri, this);
972 SoundFileBrowser::freesound_list_view_selected ()
975 if (!reset_options ()) {
976 set_action_sensitive (false);
979 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
980 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
981 file = freesound_get_audio_file (freesound_list->get_iter(*i));
984 switch (rows.size()) {
987 freesound_similar_btn.set_sensitive(false);
988 set_action_sensitive (false);
991 // exactly one item selected
993 // file exists on disk already
994 chooser.set_filename (file);
995 preview.setup_labels (file);
996 set_action_sensitive (true);
998 freesound_similar_btn.set_sensitive(true);
1001 // multiple items selected
1002 preview.setup_labels ("");
1003 freesound_similar_btn.set_sensitive(false);
1011 SoundFileBrowser::refresh_display(std::string ID, std::string file)
1013 // called when the mootcher has finished downloading a file
1014 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1015 if (rows.size() == 1) {
1016 // there's a single item selected in the freesound list
1017 //XXX make a function to be used to construct the actual file name both here and in the mootcher
1018 Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
1019 std::string selected_ID = (*row)[freesound_list_columns.id];
1020 if (ID == selected_ID) {
1021 // the selected item in the freesound list is the item that has just finished downloading
1022 chooser.set_filename(file);
1023 preview.setup_labels (file);
1024 set_action_sensitive (true);
1030 SoundFileBrowser::freesound_search_clicked ()
1033 freesound_list->clear();
1039 SoundFileBrowser::freesound_more_clicked ()
1044 snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
1045 freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
1049 SoundFileBrowser::freesound_similar_clicked ()
1051 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1052 if (rows.size() == 1) {
1055 Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
1056 id = (*iter)[freesound_list_columns.id];
1057 freesound_list->clear();
1059 GdkCursor *prev_cursor;
1060 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1061 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1064 std::string theString = mootcher.searchSimilar(id);
1066 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1067 handle_freesound_results(theString);
1072 SoundFileBrowser::freesound_search()
1076 string search_string = freesound_entry.get_text ();
1077 enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
1079 GdkCursor *prev_cursor;
1080 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1081 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1084 std::string theString = mootcher.searchText(
1088 "", // OSX eats anything incl mp3
1090 "type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
1095 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1096 handle_freesound_results(theString);
1100 SoundFileBrowser::handle_freesound_results(std::string theString) {
1102 doc.read_buffer( theString );
1103 XMLNode *root = doc.root();
1106 error << "no root XML node!" << endmsg;
1110 if ( strcmp(root->name().c_str(), "response") != 0) {
1111 error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
1115 // find out how many pages are available to search
1116 int freesound_n_pages = 1;
1117 XMLNode *res = root->child("num_pages");
1119 string result = res->child("text")->content();
1120 freesound_n_pages = atoi(result);
1123 int more_pages = freesound_n_pages - freesound_page;
1125 if (more_pages > 0) {
1126 freesound_more_btn.set_sensitive(true);
1127 freesound_more_btn.set_tooltip_text(string_compose(P_(
1128 "%1 more page of 100 results available",
1129 "%1 more pages of 100 results available",
1130 more_pages), more_pages));
1132 freesound_more_btn.set_sensitive(false);
1133 freesound_more_btn.set_tooltip_text(_("No more results available"));
1136 XMLNode *sounds_root = root->child("sounds");
1138 error << "no child node \"sounds\" found!" << endmsg;
1142 XMLNodeList sounds = sounds_root->children();
1143 if (sounds.size() == 0) {
1148 XMLNodeConstIterator niter;
1150 for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
1152 if( strcmp( node->name().c_str(), "resource") != 0 ) {
1153 error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
1157 // node->dump(cerr, "node:");
1160 XMLNode *id_node = node->child ("id");
1161 XMLNode *uri_node = node->child ("serve");
1162 XMLNode *ofn_node = node->child ("original_filename");
1163 XMLNode *dur_node = node->child ("duration");
1164 XMLNode *siz_node = node->child ("filesize");
1165 XMLNode *srt_node = node->child ("samplerate");
1166 XMLNode *lic_node = node->child ("license");
1168 if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
1170 std::string id = id_node->child("text")->content();
1171 std::string uri = uri_node->child("text")->content();
1172 std::string ofn = ofn_node->child("text")->content();
1173 std::string dur = dur_node->child("text")->content();
1174 std::string siz = siz_node->child("text")->content();
1175 std::string srt = srt_node->child("text")->content();
1176 std::string lic = lic_node->child("text")->content();
1179 // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
1181 double duration_seconds = atof(dur);
1183 char duration_hhmmss[16];
1184 if (duration_seconds >= 99 * 60 * 60) {
1185 strcpy(duration_hhmmss, ">99h");
1187 s = modf(duration_seconds/60, &m) * 60;
1188 m = modf(m/60, &h) * 60;
1189 sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
1194 double size_bytes = atof(siz);
1196 if (size_bytes < 1000) {
1197 sprintf(bsize, "%.0f %s", size_bytes, _("B"));
1198 } else if (size_bytes < 1000000 ) {
1199 sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
1200 } else if (size_bytes < 10000000) {
1201 sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
1202 } else if (size_bytes < 1000000000) {
1203 sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
1205 sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
1208 /* see http://www.freesound.org/help/faq/#licenses */
1209 char shortlicense[64];
1210 if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
1211 sprintf(shortlicense, "CC-BY-NC");
1212 } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
1213 sprintf(shortlicense, "CC-BY");
1214 } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
1215 sprintf(shortlicense, "sampling+");
1216 } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
1217 sprintf(shortlicense, "PD");
1219 snprintf(shortlicense, 64, "%s", lic.c_str());
1220 shortlicense[63]= '\0';
1223 TreeModel::iterator new_row = freesound_list->append();
1224 TreeModel::Row row = *new_row;
1226 row[freesound_list_columns.id ] = id;
1227 row[freesound_list_columns.uri ] = uri;
1228 row[freesound_list_columns.filename] = ofn;
1229 row[freesound_list_columns.duration] = duration_hhmmss;
1230 row[freesound_list_columns.filesize] = bsize;
1231 row[freesound_list_columns.smplrate] = srt;
1232 row[freesound_list_columns.license ] = shortlicense;
1239 SoundFileBrowser::get_paths ()
1241 vector<string> results;
1243 int n = notebook.get_current_page ();
1246 vector<string> filenames = chooser.get_filenames();
1247 vector<string>::iterator i;
1249 for (i = filenames.begin(); i != filenames.end(); ++i) {
1251 if ((!g_stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
1252 results.push_back (*i);
1256 } else if (n == 1) {
1258 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1259 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1260 TreeIter iter = found_list->get_iter(*i);
1261 string str = (*iter)[found_list_columns.pathname];
1263 results.push_back (str);
1266 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1267 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1268 string str = freesound_get_audio_file (freesound_list->get_iter(*i));
1270 results.push_back (str);
1279 SoundFileOmega::reset_options_noret ()
1281 if (!resetting_ourselves) {
1282 (void) reset_options ();
1287 SoundFileOmega::reset_options ()
1289 vector<string> paths = get_paths ();
1291 if (paths.empty()) {
1293 channel_combo.set_sensitive (false);
1294 action_combo.set_sensitive (false);
1295 where_combo.set_sensitive (false);
1296 copy_files_btn.set_active (true);
1297 copy_files_btn.set_sensitive (false);
1303 channel_combo.set_sensitive (true);
1304 action_combo.set_sensitive (true);
1305 where_combo.set_sensitive (true);
1307 /* if we get through this function successfully, this may be
1308 reset at the end, once we know if we can use hard links
1309 to do embedding (or if we are importing a MIDI file).
1312 if (ARDOUR_UI::config()->get_only_copy_imported_files()) {
1313 copy_files_btn.set_sensitive (false);
1315 copy_files_btn.set_sensitive (false);
1321 bool selection_includes_multichannel;
1322 bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1325 /* See if we are thinking about importing any MIDI files */
1326 vector<string>::iterator i = paths.begin ();
1327 while (i != paths.end() && SMFSource::valid_midi_file (*i) == false) {
1330 bool const have_a_midi_file = (i != paths.end ());
1332 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1333 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1337 string existing_choice;
1338 vector<string> action_strings;
1340 resetting_ourselves = true;
1342 if (chooser.get_filter() == &audio_filter) {
1346 if (selected_audio_track_cnt > 0) {
1347 if (channel_combo.get_active_text().length()) {
1348 ImportDisposition id = get_channel_disposition();
1351 case Editing::ImportDistinctFiles:
1352 if (selected_audio_track_cnt == paths.size()) {
1353 action_strings.push_back (importmode2string (ImportToTrack));
1357 case Editing::ImportDistinctChannels:
1358 /* XXX it would be nice to allow channel-per-selected track
1359 but its too hard we don't want to deal with all the
1360 different per-file + per-track channel configurations.
1365 action_strings.push_back (importmode2string (ImportToTrack));
1375 if (selected_midi_track_cnt > 0) {
1376 action_strings.push_back (importmode2string (ImportToTrack));
1380 action_strings.push_back (importmode2string (ImportAsTrack));
1381 action_strings.push_back (importmode2string (ImportAsRegion));
1382 action_strings.push_back (importmode2string (ImportAsTapeTrack));
1384 existing_choice = action_combo.get_active_text();
1386 set_popdown_strings (action_combo, action_strings);
1388 /* preserve any existing choice, if possible */
1391 if (existing_choice.length()) {
1392 vector<string>::iterator x;
1393 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1394 if (*x == existing_choice) {
1395 action_combo.set_active_text (existing_choice);
1399 if (x == action_strings.end()) {
1400 action_combo.set_active_text (action_strings.front());
1403 action_combo.set_active_text (action_strings.front());
1406 resetting_ourselves = false;
1408 if ((mode = get_mode()) == ImportAsRegion) {
1409 where_combo.set_sensitive (false);
1411 where_combo.set_sensitive (true);
1414 vector<string> channel_strings;
1416 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1417 channel_strings.push_back (_("one track per file"));
1419 if (selection_includes_multichannel) {
1420 channel_strings.push_back (_("one track per channel"));
1423 if (paths.size() > 1) {
1424 /* tape tracks are a single region per track, so we cannot
1425 sequence multiple files.
1427 if (mode != ImportAsTapeTrack) {
1428 channel_strings.push_back (_("sequence files"));
1431 channel_strings.push_back (_("all files in one track"));
1432 channel_strings.push_back (_("merge files"));
1438 channel_strings.push_back (_("one region per file"));
1440 if (selection_includes_multichannel) {
1441 channel_strings.push_back (_("one region per channel"));
1444 if (paths.size() > 1) {
1446 channel_strings.push_back (_("all files in one region"));
1451 resetting_ourselves = true;
1453 existing_choice = channel_combo.get_active_text();
1455 set_popdown_strings (channel_combo, channel_strings);
1457 /* preserve any existing choice, if possible */
1459 if (existing_choice.length()) {
1460 vector<string>::iterator x;
1461 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1462 if (*x == existing_choice) {
1463 channel_combo.set_active_text (existing_choice);
1467 if (x == channel_strings.end()) {
1468 channel_combo.set_active_text (channel_strings.front());
1471 channel_combo.set_active_text (channel_strings.front());
1474 resetting_ourselves = false;
1477 src_combo.set_sensitive (true);
1479 src_combo.set_sensitive (false);
1482 /* We must copy MIDI files or those from Freesound
1483 * or any file if we are under nsm control */
1484 bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
1486 if (ARDOUR_UI::config()->get_only_copy_imported_files()) {
1488 if (selection_can_be_embedded_with_links && !must_copy) {
1489 copy_files_btn.set_sensitive (true);
1492 copy_files_btn.set_active (true);
1494 copy_files_btn.set_sensitive (false);
1500 copy_files_btn.set_active (true);
1502 copy_files_btn.set_sensitive (!must_copy);
1510 SoundFileOmega::bad_file_message()
1512 MessageDialog msg (*this,
1513 string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1518 resetting_ourselves = true;
1519 chooser.unselect_uri (chooser.get_preview_uri());
1520 resetting_ourselves = false;
1526 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1535 multichannel = false;
1537 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1539 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1540 if (info.channels > 1) {
1541 multichannel = true;
1546 if (sz != info.length) {
1551 if (info.samplerate != _session->frame_rate()) {
1555 } else if (SMFSource::valid_midi_file (*i)) {
1559 if (reader.num_tracks() > 1) {
1560 multichannel = true; // "channel" == track here...
1563 /* XXX we need err = true handling here in case
1564 we can't check the file
1577 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1579 #ifdef PLATFORM_WINDOWS
1582 std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
1585 if (g_mkdir (tmpdir.c_str(), 0744)) {
1586 if (errno != EEXIST) {
1591 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1593 char tmpc[PATH_MAX+1];
1595 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1599 if (link ((*i).c_str(), tmpc)) {
1609 g_rmdir (tmpdir.c_str());
1614 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
1615 : SoundFileBrowser (title, s, false)
1617 chooser.set_select_multiple (false);
1618 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1619 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1623 SoundFileChooser::on_hide ()
1625 ArdourWindow::on_hide();
1629 _session->cancel_audition();
1634 SoundFileChooser::get_filename ()
1636 vector<string> paths;
1638 paths = get_paths ();
1640 if (paths.empty()) {
1644 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1648 return paths.front();
1651 SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s,
1652 uint32_t selected_audio_tracks,
1653 uint32_t selected_midi_tracks,
1655 Editing::ImportMode mode_hint)
1656 : SoundFileBrowser (title, s, persistent)
1657 , copy_files_btn ( _("Copy files to session"))
1658 , selected_audio_track_cnt (selected_audio_tracks)
1659 , selected_midi_track_cnt (selected_midi_tracks)
1665 set_size_request (-1, 450);
1667 block_two.set_border_width (12);
1668 block_three.set_border_width (12);
1669 block_four.set_border_width (12);
1671 options.set_spacing (12);
1674 str.push_back (_("file timestamp"));
1675 str.push_back (_("edit point"));
1676 str.push_back (_("playhead"));
1677 str.push_back (_("session start"));
1678 set_popdown_strings (where_combo, str);
1679 where_combo.set_active_text (str.front());
1680 where_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::where_combo_changed));
1682 Label* l = manage (new Label);
1683 l->set_markup (_("<b>Add files as ...</b>"));
1685 vbox = manage (new VBox);
1686 vbox->set_border_width (12);
1687 vbox->set_spacing (6);
1688 vbox->pack_start (*l, false, false);
1689 vbox->pack_start (action_combo, false, false);
1690 hbox = manage (new HBox);
1691 hbox->pack_start (*vbox, false, false);
1692 options.pack_start (*hbox, false, false);
1694 /* dummy entry for action combo so that it doesn't look odd if we
1695 come up with no tracks selected.
1699 str.push_back (importmode2string (mode_hint));
1700 set_popdown_strings (action_combo, str);
1701 action_combo.set_active_text (str.front());
1702 action_combo.set_sensitive (false);
1704 l = manage (new Label);
1705 l->set_markup (_("<b>Insert at</b>"));
1707 vbox = manage (new VBox);
1708 vbox->set_border_width (12);
1709 vbox->set_spacing (6);
1710 vbox->pack_start (*l, false, false);
1711 vbox->pack_start (where_combo, false, false);
1712 hbox = manage (new HBox);
1713 hbox->pack_start (*vbox, false, false);
1714 options.pack_start (*hbox, false, false);
1717 l = manage (new Label);
1718 l->set_markup (_("<b>Mapping</b>"));
1720 vbox = manage (new VBox);
1721 vbox->set_border_width (12);
1722 vbox->set_spacing (6);
1723 vbox->pack_start (*l, false, false);
1724 vbox->pack_start (channel_combo, false, false);
1725 hbox = manage (new HBox);
1726 hbox->pack_start (*vbox, false, false);
1727 options.pack_start (*hbox, false, false);
1730 str.push_back (_("one track per file"));
1731 set_popdown_strings (channel_combo, str);
1732 channel_combo.set_active_text (str.front());
1733 channel_combo.set_sensitive (false);
1735 l = manage (new Label);
1736 l->set_markup (_("<b>Conversion quality</b>"));
1738 vbox = manage (new VBox);
1739 vbox->set_border_width (12);
1740 vbox->set_spacing (6);
1741 vbox->pack_start (*l, false, false);
1742 vbox->pack_start (src_combo, false, false);
1743 hbox = manage (new HBox);
1744 hbox->pack_start (*vbox, false, false);
1745 options.pack_start (*hbox, false, false);
1747 l = manage (new Label);
1748 l->set_markup (_("<b>Instrument</b>"));
1750 vbox = manage (new VBox);
1751 vbox->set_border_width (12);
1752 vbox->set_spacing (6);
1753 vbox->pack_start (*l, false, false);
1754 vbox->pack_start (instrument_combo, false, false);
1755 hbox = manage (new HBox);
1756 hbox->pack_start (*vbox, false, false);
1757 options.pack_start (*hbox, false, false);
1760 str.push_back (_("Best"));
1761 str.push_back (_("Good"));
1762 str.push_back (_("Quick"));
1763 str.push_back (_("Fast"));
1764 str.push_back (_("Fastest"));
1766 set_popdown_strings (src_combo, str);
1767 src_combo.set_active_text (str.front());
1768 src_combo.set_sensitive (false);
1769 src_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::src_combo_changed));
1773 action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1774 channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1776 copy_files_btn.set_active (true);
1778 Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1781 copy_label->set_size_request (175, -1);
1782 copy_label->set_line_wrap (true);
1785 block_four.pack_start (copy_files_btn, false, false);
1787 options.pack_start (block_four, false, false);
1789 vpacker.pack_start (options, false, false);
1791 /* setup disposition map */
1793 disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1794 disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1795 disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1796 disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1798 disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1799 disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1800 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1801 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1803 chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1805 /* set size requests for a couple of combos to allow them to display the longest text
1806 they will ever be asked to display. This prevents them being resized when the user
1807 selects a file to import, which in turn prevents the size of the dialog from jumping
1811 t.push_back (_("one track per file"));
1812 t.push_back (_("one track per channel"));
1813 t.push_back (_("sequence files"));
1814 t.push_back (_("all files in one region"));
1815 set_popdown_strings (channel_combo, t);
1818 t.push_back (importmode2string (ImportAsTrack));
1819 t.push_back (importmode2string (ImportToTrack));
1820 t.push_back (importmode2string (ImportAsRegion));
1821 t.push_back (importmode2string (ImportAsTapeTrack));
1822 set_popdown_strings (action_combo, t);
1826 SoundFileOmega::set_mode (ImportMode mode)
1828 action_combo.set_active_text (importmode2string (mode));
1832 SoundFileOmega::get_mode () const
1834 return string2importmode (action_combo.get_active_text());
1838 SoundFileOmega::on_hide ()
1840 ArdourWindow::on_hide();
1842 _session->cancel_audition();
1847 SoundFileOmega::get_position() const
1849 string str = where_combo.get_active_text();
1851 if (str == _("file timestamp")) {
1852 return ImportAtTimestamp;
1853 } else if (str == _("edit point")) {
1854 return ImportAtEditPoint;
1855 } else if (str == _("playhead")) {
1856 return ImportAtPlayhead;
1858 return ImportAtStart;
1863 SoundFileOmega::get_src_quality() const
1865 string str = src_combo.get_active_text();
1867 if (str == _("Best")) {
1869 } else if (str == _("Good")) {
1871 } else if (str == _("Quick")) {
1873 } else if (str == _("Fast")) {
1881 SoundFileOmega::src_combo_changed()
1883 preview.set_src_quality(get_src_quality());
1887 SoundFileOmega::where_combo_changed()
1889 preview.set_import_position(get_position());
1893 SoundFileOmega::get_channel_disposition () const
1895 /* we use a map here because the channel combo can contain different strings
1896 depending on the state of the other combos. the map contains all possible strings
1897 and the ImportDisposition enum that corresponds to it.
1900 string str = channel_combo.get_active_text();
1901 DispositionMap::const_iterator x = disposition_map.find (str);
1903 if (x == disposition_map.end()) {
1904 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1905 abort(); /*NOTREACHED*/
1912 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
1914 selected_audio_track_cnt = selected_audio_tracks;
1915 selected_midi_track_cnt = selected_midi_tracks;
1917 if (selected_audio_track_cnt == 0 && selected_midi_track_cnt > 0) {
1918 chooser.set_filter (midi_filter);
1919 } else if (selected_midi_track_cnt == 0 && selected_audio_track_cnt > 0) {
1920 chooser.set_filter (audio_filter);
1922 chooser.set_filter (audio_and_midi_filter);
1929 SoundFileOmega::file_selection_changed ()
1931 if (resetting_ourselves) {
1935 if (!reset_options ()) {
1936 set_action_sensitive (false);
1938 if (chooser.get_filenames().size() > 0) {
1939 set_action_sensitive (true);
1941 set_action_sensitive (false);
1947 SoundFileOmega::do_something (int action)
1949 SoundFileBrowser::do_something (action);
1951 if (action == RESPONSE_CLOSE) {
1958 vector<string> paths = get_paths ();
1959 ImportPosition pos = get_position ();
1960 ImportMode mode = get_mode ();
1961 ImportDisposition chns = get_channel_disposition ();
1962 PluginInfoPtr instrument = instrument_combo.selected_instrument();
1966 case ImportAtEditPoint:
1967 where = PublicEditor::instance().get_preferred_edit_position ();
1969 case ImportAtTimestamp:
1972 case ImportAtPlayhead:
1973 where = _session->transport_frame();
1976 where = _session->current_start_frame();
1980 SrcQuality quality = get_src_quality();
1982 if (copy_files_btn.get_active()) {
1983 PublicEditor::instance().do_import (paths, chns, mode, quality, where, instrument);
1985 PublicEditor::instance().do_embed (paths, chns, mode, where, instrument);