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"
32 #include <gtkmm/box.h>
33 #include <gtkmm/stock.h>
35 #include <glib/gstdio.h>
36 #include <glibmm/fileutils.h>
38 #include "pbd/convert.h"
39 #include "pbd/tokenizer.h"
40 #include "pbd/enumwriter.h"
41 #include "pbd/pthread_utils.h"
42 #include "pbd/xml++.h"
44 #include <gtkmm2ext/utils.h>
46 #include "evoral/SMF.hpp"
48 #include "ardour/audio_library.h"
49 #include "ardour/auditioner.h"
50 #include "ardour/audioregion.h"
51 #include "ardour/audiofilesource.h"
52 #include "ardour/smf_source.h"
53 #include "ardour/region_factory.h"
54 #include "ardour/source_factory.h"
55 #include "ardour/session.h"
56 #include "ardour/session_directory.h"
57 #include "ardour/srcfilesource.h"
59 #include "ardour_ui.h"
61 #include "gui_thread.h"
66 #include "gain_meter.h"
67 #include "main_clock.h"
68 #include "public_editor.h"
70 #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");
118 return _("as new tracks");
121 SoundFileBox::SoundFileBox (bool persistent)
123 length_clock ("sfboxLengthClock", !persistent, "", false, false, true, false),
124 timecode_clock ("sfboxTimecodeClock", !persistent, "", 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(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
286 preview_label.set_markup (_("<b>Sound File Information</b>"));
287 format_text.set_text ("");
288 channels_value.set_text ("");
289 samplerate_value.set_text ("");
290 tags_entry.get_buffer()->set_text ("");
292 length_clock.set (0);
293 timecode_clock.set (0);
295 tags_entry.set_sensitive (false);
296 play_btn.set_sensitive (false);
301 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::Markup::escape_text (Glib::path_get_basename (filename))));
302 std::string n = sf_info.format_name;
303 if (n.substr (0, 8) == X_("Format: ")) {
306 format_text.set_text (n);
307 channels_value.set_text (to_string (sf_info.channels, std::dec));
309 if (_session && sf_info.samplerate != _session->frame_rate()) {
310 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
311 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
312 samplerate_value.set_name ("NewSessionSR1Label");
313 samplerate.set_name ("NewSessionSR1Label");
315 samplerate.set_text (_("Sample rate:"));
316 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
317 samplerate_value.set_name ("NewSessionSR2Label");
318 samplerate.set_name ("NewSessionSR2Label");
321 framecnt_t const nfr = _session ? _session->nominal_frame_rate() : 25;
322 double src_coef = (double) nfr / sf_info.samplerate;
324 length_clock.set (sf_info.length * src_coef + 0.5, true);
325 timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
327 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
329 vector<string> tags = Library->get_tags (string ("//") + filename);
331 stringstream tag_string;
332 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
333 if (i != tags.begin()) {
338 tags_entry.get_buffer()->set_text (tag_string.str());
340 tags_entry.set_sensitive (true);
342 play_btn.set_sensitive (true);
349 SoundFileBox::autoplay() const
351 return autoplay_btn.get_active();
355 SoundFileBox::audition_oneshot()
362 SoundFileBox::audition ()
368 if (SMFSource::safe_midi_file_extension (path)) {
369 error << _("Auditioning of MIDI files is not yet supported") << endmsg;
373 _session->cancel_audition();
375 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
376 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
380 boost::shared_ptr<Region> r;
382 boost::shared_ptr<AudioFileSource> afs;
383 bool old_sbp = AudioSource::get_build_peakfiles ();
385 /* don't even think of building peakfiles for these files */
387 AudioSource::set_build_peakfiles (false);
389 for (int n = 0; n < sf_info.channels; ++n) {
391 afs = boost::dynamic_pointer_cast<AudioFileSource> (
392 SourceFactory::createExternal (DataType::AUDIO, *_session,
394 Source::Flag (0), false));
395 if (afs->sample_rate() != _session->nominal_frame_rate()) {
396 boost::shared_ptr<SrcFileSource> sfs (new SrcFileSource(*_session, afs, _src_quality));
397 srclist.push_back(sfs);
399 srclist.push_back(afs);
402 } catch (failed_constructor& err) {
403 error << _("Could not access soundfile: ") << path << endmsg;
404 AudioSource::set_build_peakfiles (old_sbp);
409 AudioSource::set_build_peakfiles (old_sbp);
411 if (srclist.empty()) {
415 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
416 string rname = region_name_from_path (afs->path(), false);
420 plist.add (ARDOUR::Properties::start, 0);
421 plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->timeline_position()));
422 plist.add (ARDOUR::Properties::name, rname);
423 plist.add (ARDOUR::Properties::layer, 0);
425 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false));
427 _session->audition_region(r);
431 SoundFileBox::stop_audition ()
434 _session->cancel_audition();
439 SoundFileBox::tags_entry_left (GdkEventFocus *)
446 SoundFileBox::tags_changed ()
448 string tag_string = tags_entry.get_buffer()->get_text ();
450 if (tag_string.empty()) {
456 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
457 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
465 SoundFileBox::save_tags (const vector<string>& tags)
467 Library->set_tags (string ("//") + path, tags);
468 Library->save_changes ();
471 SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persistent)
472 : ArdourWindow (title)
473 , found_list (ListStore::create(found_list_columns))
474 , freesound_list (ListStore::create(freesound_list_columns))
475 , chooser (FILE_CHOOSER_ACTION_OPEN)
476 , preview (persistent)
477 , found_search_btn (_("Search"))
478 , found_list_view (found_list)
479 , freesound_search_btn (_("Search"))
480 , freesound_list_view (freesound_list)
481 , resetting_ourselves (false)
485 , ok_button (Stock::OK)
486 , cancel_button (Stock::CANCEL)
487 , apply_button (Stock::APPLY)
492 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
493 chooser.add_shortcut_folder_uri("file:///Library/Audio/Apple Loops");
494 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
495 chooser.add_shortcut_folder_uri("file:///Volumes");
498 //add the file chooser
500 chooser.set_border_width (12);
502 audio_and_midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun (*this, &SoundFileBrowser::on_audio_and_midi_filter));
503 audio_and_midi_filter.set_name (_("Audio and MIDI files"));
505 audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
506 audio_filter.set_name (_("Audio files"));
508 midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
509 midi_filter.set_name (_("MIDI files"));
511 matchall_filter.add_pattern ("*.*");
512 matchall_filter.set_name (_("All files"));
514 chooser.add_filter (audio_and_midi_filter);
515 chooser.add_filter (audio_filter);
516 chooser.add_filter (midi_filter);
517 chooser.add_filter (matchall_filter);
518 chooser.set_select_multiple (true);
519 chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
520 chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
523 /* some broken redraw behaviour - this is a bandaid */
524 chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
527 if (!persistent_folder.empty()) {
528 chooser.set_current_folder (persistent_folder);
531 notebook.append_page (chooser, _("Browse Files"));
533 hpacker.set_spacing (6);
534 hpacker.pack_start (notebook, true, true);
535 hpacker.pack_start (preview, false, false);
537 vpacker.set_spacing (6);
538 vpacker.pack_start (hpacker, true, true);
548 hbox = manage(new HBox);
549 hbox->pack_start (found_entry);
550 hbox->pack_start (found_search_btn);
552 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
553 scroll->add(found_list_view);
554 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
556 vbox = manage(new VBox);
557 vbox->pack_start (*hbox, PACK_SHRINK);
558 vbox->pack_start (*scroll);
560 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
562 found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
564 found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
566 found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
567 found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
569 notebook.append_page (*vbox, _("Search Tags"));
571 //add freesound search
576 passbox = manage(new HBox);
577 passbox->set_spacing (6);
579 label = manage (new Label);
580 label->set_text (_("Tags:"));
581 passbox->pack_start (*label, false, false);
582 passbox->pack_start (freesound_entry, true, true);
584 label = manage (new Label);
585 label->set_text (_("Sort:"));
586 passbox->pack_start (*label, false, false);
587 passbox->pack_start (freesound_sort, false, false);
588 freesound_sort.clear_items();
590 // Order of the following must correspond with enum sortMethod
591 // in sfdb_freesound_mootcher.h
592 freesound_sort.append_text(_("None"));
593 freesound_sort.append_text(_("Longest"));
594 freesound_sort.append_text(_("Shortest"));
595 freesound_sort.append_text(_("Newest"));
596 freesound_sort.append_text(_("Oldest"));
597 freesound_sort.append_text(_("Most downloaded"));
598 freesound_sort.append_text(_("Least downloaded"));
599 freesound_sort.append_text(_("Highest rated"));
600 freesound_sort.append_text(_("Lowest rated"));
601 freesound_sort.set_active(0);
603 passbox->pack_start (freesound_search_btn, false, false);
604 passbox->pack_start (freesound_more_btn, false, false);
605 freesound_more_btn.set_label(_("More"));
606 freesound_more_btn.set_sensitive(false);
608 passbox->pack_start (freesound_similar_btn, false, false);
609 freesound_similar_btn.set_label(_("Similar"));
610 freesound_similar_btn.set_sensitive(false);
612 scroll = manage(new ScrolledWindow);
613 scroll->add(freesound_list_view);
614 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
616 vbox = manage(new VBox);
617 vbox->set_spacing (3);
618 vbox->pack_start (*passbox, PACK_SHRINK);
619 vbox->pack_start (*scroll);
621 freesound_list_view.append_column(_("ID") , freesound_list_columns.id);
622 freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
623 // freesound_list_view.append_column(_("URI") , freesound_list_columns.uri);
624 freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
625 freesound_list_view.append_column(_("Size"), freesound_list_columns.filesize);
626 freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
627 freesound_list_view.append_column(_("License"), freesound_list_columns.license);
628 freesound_list_view.get_column(0)->set_alignment(0.5);
629 freesound_list_view.get_column(1)->set_expand(true); // filename
630 freesound_list_view.get_column(1)->set_resizable(true); // filename
631 freesound_list_view.get_column(2)->set_alignment(0.5);
632 freesound_list_view.get_column(3)->set_alignment(0.5);
633 freesound_list_view.get_column(4)->set_alignment(0.5);
634 freesound_list_view.get_column(5)->set_alignment(0.5);
636 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
637 freesound_list_view.set_tooltip_column(1);
639 freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
640 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
641 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
642 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
643 freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
644 freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
645 notebook.append_page (*vbox, _("Search Freesound"));
647 notebook.set_size_request (500, -1);
648 notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
652 Gtk::HButtonBox* button_box = manage (new HButtonBox);
654 button_box->set_layout (BUTTONBOX_END);
655 button_box->pack_start (cancel_button, false, false);
656 cancel_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_CANCEL));
658 button_box->pack_start (apply_button, false, false);
659 apply_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_APPLY));
662 button_box->pack_start (ok_button, false, false);
663 ok_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_OK));
665 Gtkmm2ext::UI::instance()->set_tip (ok_button, _("Press to import selected files and close this window"));
666 Gtkmm2ext::UI::instance()->set_tip (apply_button, _("Press to import selected files and leave this window open"));
667 Gtkmm2ext::UI::instance()->set_tip (cancel_button, _("Press to close this window without importing any files"));
669 vpacker.pack_end (*button_box, false, false);
671 set_wmclass (X_("import"), PROGRAM_NAME);
674 SoundFileBrowser::~SoundFileBrowser ()
676 persistent_folder = chooser.get_current_folder();
680 SoundFileBrowser::run ()
689 gtk_main_iteration ();
696 SoundFileBrowser::set_action_sensitive (bool yn)
698 ok_button.set_sensitive (yn);
699 apply_button.set_sensitive (yn);
703 SoundFileBrowser::do_something (int action)
710 SoundFileBrowser::on_show ()
712 ArdourWindow::on_show ();
717 SoundFileBrowser::clear_selection ()
719 chooser.unselect_all ();
720 found_list_view.get_selection()->unselect_all ();
724 SoundFileBrowser::chooser_file_activated ()
730 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
736 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
742 SoundFileBrowser::set_session (Session* s)
744 ArdourWindow::set_session (s);
745 preview.set_session (s);
750 remove_gain_meter ();
755 SoundFileBrowser::add_gain_meter ()
759 gm = new GainMeter (_session, 250);
761 boost::shared_ptr<Route> r = _session->the_auditioner ();
763 gm->set_controls (r, r->shared_peak_meter(), r->amp());
764 gm->set_fader_name (X_("GainFader"));
766 meter_packer.set_border_width (12);
767 meter_packer.pack_start (*gm, false, true);
768 hpacker.pack_end (meter_packer, false, false);
769 meter_packer.show_all ();
774 SoundFileBrowser::remove_gain_meter ()
777 meter_packer.remove (*gm);
778 hpacker.remove (meter_packer);
785 SoundFileBrowser::start_metering ()
787 metering_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
791 SoundFileBrowser::stop_metering ()
793 metering_connection.disconnect();
797 SoundFileBrowser::meter ()
799 if (is_mapped () && _session && gm) {
800 gm->update_meters ();
805 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
807 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
811 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
813 return SMFSource::safe_midi_file_extension (filter_info.filename);
817 SoundFileBrowser::on_audio_and_midi_filter (const FileFilter::Info& filter_info)
819 return on_audio_filter (filter_info) || on_midi_filter (filter_info);
823 SoundFileBrowser::update_preview ()
825 if (preview.setup_labels (chooser.get_preview_filename())) {
826 if (preview.autoplay()) {
827 Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
833 SoundFileBrowser::found_list_view_selected ()
835 if (!reset_options ()) {
836 set_action_sensitive (false);
840 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
843 TreeIter iter = found_list->get_iter(*rows.begin());
844 file = (*iter)[found_list_columns.pathname];
845 chooser.set_filename (file);
846 set_action_sensitive (true);
848 set_action_sensitive (false);
851 preview.setup_labels (file);
856 SoundFileBrowser::found_search_clicked ()
858 string tag_string = found_entry.get_text ();
862 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
863 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
867 vector<string> results;
868 Library->search_members_and (results, tags);
871 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
872 TreeModel::iterator new_row = found_list->append();
873 TreeModel::Row row = *new_row;
874 string path = Glib::filename_from_uri (string ("file:") + *i);
875 row[found_list_columns.pathname] = path;
881 SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
884 Mootcher *mootcher = new Mootcher;
887 string id = (*iter)[freesound_list_columns.id];
888 string uri = (*iter)[freesound_list_columns.uri];
889 string ofn = (*iter)[freesound_list_columns.filename];
891 if (mootcher->checkAudioFile(ofn, id)) {
892 // file already exists, no need to download it again
893 file = mootcher->audioFileName;
895 (*iter)[freesound_list_columns.started] = false;
898 if (!(*iter)[freesound_list_columns.started]) {
899 // start downloading the sound file
900 (*iter)[freesound_list_columns.started] = true;
901 mootcher->fetchAudioFile(ofn, id, uri, this);
907 SoundFileBrowser::freesound_list_view_selected ()
910 if (!reset_options ()) {
911 set_action_sensitive (false);
914 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
915 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
916 file = freesound_get_audio_file (freesound_list->get_iter(*i));
919 switch (rows.size()) {
922 freesound_similar_btn.set_sensitive(false);
923 set_action_sensitive (false);
926 // exactly one item selected
928 // file exists on disk already
929 chooser.set_filename (file);
930 preview.setup_labels (file);
931 set_action_sensitive (true);
933 freesound_similar_btn.set_sensitive(true);
936 // multiple items selected
937 preview.setup_labels ("");
938 freesound_similar_btn.set_sensitive(false);
946 SoundFileBrowser::refresh_display(std::string ID, std::string file)
948 // called when the mootcher has finished downloading a file
949 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
950 if (rows.size() == 1) {
951 // there's a single item selected in the freesound list
952 //XXX make a function to be used to construct the actual file name both here and in the mootcher
953 Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
954 std::string selected_ID = (*row)[freesound_list_columns.id];
955 if (ID == selected_ID) {
956 // the selected item in the freesound list is the item that has just finished downloading
957 chooser.set_filename(file);
958 preview.setup_labels (file);
959 set_action_sensitive (true);
965 SoundFileBrowser::freesound_search_clicked ()
968 freesound_list->clear();
974 SoundFileBrowser::freesound_more_clicked ()
979 snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
980 freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
984 SoundFileBrowser::freesound_similar_clicked ()
986 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
987 if (rows.size() == 1) {
990 Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
991 id = (*iter)[freesound_list_columns.id];
992 freesound_list->clear();
994 GdkCursor *prev_cursor;
995 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
996 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
999 std::string theString = mootcher.searchSimilar(id);
1001 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1002 handle_freesound_results(theString);
1007 SoundFileBrowser::freesound_search()
1011 string search_string = freesound_entry.get_text ();
1012 enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
1014 GdkCursor *prev_cursor;
1015 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1016 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1019 std::string theString = mootcher.searchText(
1023 "", // OSX eats anything incl mp3
1025 "type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
1030 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1031 handle_freesound_results(theString);
1035 SoundFileBrowser::handle_freesound_results(std::string theString) {
1037 doc.read_buffer( theString );
1038 XMLNode *root = doc.root();
1041 error << "no root XML node!" << endmsg;
1045 if ( strcmp(root->name().c_str(), "response") != 0) {
1046 error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
1050 // find out how many pages are available to search
1051 int freesound_n_pages = 1;
1052 XMLNode *res = root->child("num_pages");
1054 string result = res->child("text")->content();
1055 freesound_n_pages = atoi(result);
1058 int more_pages = freesound_n_pages - freesound_page;
1060 if (more_pages > 0) {
1061 freesound_more_btn.set_sensitive(true);
1062 freesound_more_btn.set_tooltip_text(string_compose(P_(
1063 "%1 more page of 100 results available",
1064 "%1 more pages of 100 results available",
1065 more_pages), more_pages));
1067 freesound_more_btn.set_sensitive(false);
1068 freesound_more_btn.set_tooltip_text(_("No more results available"));
1071 XMLNode *sounds_root = root->child("sounds");
1073 error << "no child node \"sounds\" found!" << endmsg;
1077 XMLNodeList sounds = sounds_root->children();
1078 if (sounds.size() == 0) {
1083 XMLNodeConstIterator niter;
1085 for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
1087 if( strcmp( node->name().c_str(), "resource") != 0 ) {
1088 error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
1092 // node->dump(cerr, "node:");
1095 XMLNode *id_node = node->child ("id");
1096 XMLNode *uri_node = node->child ("serve");
1097 XMLNode *ofn_node = node->child ("original_filename");
1098 XMLNode *dur_node = node->child ("duration");
1099 XMLNode *siz_node = node->child ("filesize");
1100 XMLNode *srt_node = node->child ("samplerate");
1101 XMLNode *lic_node = node->child ("license");
1103 if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
1105 std::string id = id_node->child("text")->content();
1106 std::string uri = uri_node->child("text")->content();
1107 std::string ofn = ofn_node->child("text")->content();
1108 std::string dur = dur_node->child("text")->content();
1109 std::string siz = siz_node->child("text")->content();
1110 std::string srt = srt_node->child("text")->content();
1111 std::string lic = lic_node->child("text")->content();
1114 // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
1116 double duration_seconds = atof(dur);
1118 char duration_hhmmss[16];
1119 if (duration_seconds >= 99 * 60 * 60) {
1120 strcpy(duration_hhmmss, ">99h");
1122 s = modf(duration_seconds/60, &m) * 60;
1123 m = modf(m/60, &h) * 60;
1124 sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
1129 double size_bytes = atof(siz);
1131 if (size_bytes < 1000) {
1132 sprintf(bsize, "%.0f %s", size_bytes, _("B"));
1133 } else if (size_bytes < 1000000 ) {
1134 sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
1135 } else if (size_bytes < 10000000) {
1136 sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
1137 } else if (size_bytes < 1000000000) {
1138 sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
1140 sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
1143 /* see http://www.freesound.org/help/faq/#licenses */
1144 char shortlicense[64];
1145 if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
1146 sprintf(shortlicense, "CC-BY-NC");
1147 } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
1148 sprintf(shortlicense, "CC-BY");
1149 } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
1150 sprintf(shortlicense, "sampling+");
1151 } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
1152 sprintf(shortlicense, "PD");
1154 snprintf(shortlicense, 64, "%s", lic.c_str());
1155 shortlicense[63]= '\0';
1158 TreeModel::iterator new_row = freesound_list->append();
1159 TreeModel::Row row = *new_row;
1161 row[freesound_list_columns.id ] = id;
1162 row[freesound_list_columns.uri ] = uri;
1163 row[freesound_list_columns.filename] = ofn;
1164 row[freesound_list_columns.duration] = duration_hhmmss;
1165 row[freesound_list_columns.filesize] = bsize;
1166 row[freesound_list_columns.smplrate] = srt;
1167 row[freesound_list_columns.license ] = shortlicense;
1174 SoundFileBrowser::get_paths ()
1176 vector<string> results;
1178 int n = notebook.get_current_page ();
1181 vector<string> filenames = chooser.get_filenames();
1182 vector<string>::iterator i;
1184 for (i = filenames.begin(); i != filenames.end(); ++i) {
1186 if ((!stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
1187 results.push_back (*i);
1191 } else if (n == 1) {
1193 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1194 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1195 TreeIter iter = found_list->get_iter(*i);
1196 string str = (*iter)[found_list_columns.pathname];
1198 results.push_back (str);
1201 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1202 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1203 string str = freesound_get_audio_file (freesound_list->get_iter(*i));
1205 results.push_back (str);
1214 SoundFileOmega::reset_options_noret ()
1216 if (!resetting_ourselves) {
1217 (void) reset_options ();
1222 SoundFileOmega::reset_options ()
1224 vector<string> paths = get_paths ();
1226 if (paths.empty()) {
1228 channel_combo.set_sensitive (false);
1229 action_combo.set_sensitive (false);
1230 where_combo.set_sensitive (false);
1231 copy_files_btn.set_active (true);
1232 copy_files_btn.set_sensitive (false);
1238 channel_combo.set_sensitive (true);
1239 action_combo.set_sensitive (true);
1240 where_combo.set_sensitive (true);
1242 /* if we get through this function successfully, this may be
1243 reset at the end, once we know if we can use hard links
1244 to do embedding (or if we are importing a MIDI file).
1247 if (Config->get_only_copy_imported_files()) {
1248 copy_files_btn.set_sensitive (false);
1250 copy_files_btn.set_sensitive (false);
1256 bool selection_includes_multichannel;
1257 bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1260 /* See if we are thinking about importing any MIDI files */
1261 vector<string>::iterator i = paths.begin ();
1262 while (i != paths.end() && SMFSource::safe_midi_file_extension (*i) == false) {
1265 bool const have_a_midi_file = (i != paths.end ());
1267 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1268 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1272 string existing_choice;
1273 vector<string> action_strings;
1275 resetting_ourselves = true;
1277 if (chooser.get_filter() == &audio_filter) {
1281 if (selected_audio_track_cnt > 0) {
1282 if (channel_combo.get_active_text().length()) {
1283 ImportDisposition id = get_channel_disposition();
1286 case Editing::ImportDistinctFiles:
1287 if (selected_audio_track_cnt == paths.size()) {
1288 action_strings.push_back (importmode2string (ImportToTrack));
1292 case Editing::ImportDistinctChannels:
1293 /* XXX it would be nice to allow channel-per-selected track
1294 but its too hard we don't want to deal with all the
1295 different per-file + per-track channel configurations.
1300 action_strings.push_back (importmode2string (ImportToTrack));
1310 if (selected_midi_track_cnt > 0) {
1311 action_strings.push_back (importmode2string (ImportToTrack));
1315 action_strings.push_back (importmode2string (ImportAsTrack));
1316 action_strings.push_back (importmode2string (ImportAsRegion));
1317 action_strings.push_back (importmode2string (ImportAsTapeTrack));
1319 existing_choice = action_combo.get_active_text();
1321 set_popdown_strings (action_combo, action_strings);
1323 /* preserve any existing choice, if possible */
1326 if (existing_choice.length()) {
1327 vector<string>::iterator x;
1328 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1329 if (*x == existing_choice) {
1330 action_combo.set_active_text (existing_choice);
1334 if (x == action_strings.end()) {
1335 action_combo.set_active_text (action_strings.front());
1338 action_combo.set_active_text (action_strings.front());
1341 resetting_ourselves = false;
1343 if ((mode = get_mode()) == ImportAsRegion) {
1344 where_combo.set_sensitive (false);
1346 where_combo.set_sensitive (true);
1349 vector<string> channel_strings;
1351 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1352 channel_strings.push_back (_("one track per file"));
1354 if (selection_includes_multichannel) {
1355 channel_strings.push_back (_("one track per channel"));
1358 if (paths.size() > 1) {
1359 /* tape tracks are a single region per track, so we cannot
1360 sequence multiple files.
1362 if (mode != ImportAsTapeTrack) {
1363 channel_strings.push_back (_("sequence files"));
1366 channel_strings.push_back (_("all files in one track"));
1367 channel_strings.push_back (_("merge files"));
1373 channel_strings.push_back (_("one region per file"));
1375 if (selection_includes_multichannel) {
1376 channel_strings.push_back (_("one region per channel"));
1379 if (paths.size() > 1) {
1381 channel_strings.push_back (_("all files in one region"));
1386 resetting_ourselves = true;
1388 existing_choice = channel_combo.get_active_text();
1390 set_popdown_strings (channel_combo, channel_strings);
1392 /* preserve any existing choice, if possible */
1394 if (existing_choice.length()) {
1395 vector<string>::iterator x;
1396 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1397 if (*x == existing_choice) {
1398 channel_combo.set_active_text (existing_choice);
1402 if (x == channel_strings.end()) {
1403 channel_combo.set_active_text (channel_strings.front());
1406 channel_combo.set_active_text (channel_strings.front());
1409 resetting_ourselves = false;
1412 src_combo.set_sensitive (true);
1414 src_combo.set_sensitive (false);
1417 /* We must copy MIDI files or those from Freesound
1418 * or any file if we are under nsm control */
1419 bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
1421 if (Config->get_only_copy_imported_files()) {
1423 if (selection_can_be_embedded_with_links && !must_copy) {
1424 copy_files_btn.set_sensitive (true);
1427 copy_files_btn.set_active (true);
1429 copy_files_btn.set_sensitive (false);
1435 copy_files_btn.set_active (true);
1437 copy_files_btn.set_sensitive (!must_copy);
1445 SoundFileOmega::bad_file_message()
1447 MessageDialog msg (*this,
1448 string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1453 resetting_ourselves = true;
1454 chooser.unselect_uri (chooser.get_preview_uri());
1455 resetting_ourselves = false;
1461 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1470 multichannel = false;
1472 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1474 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1475 if (info.channels > 1) {
1476 multichannel = true;
1481 if (sz != info.length) {
1486 if (info.samplerate != _session->frame_rate()) {
1490 } else if (SMFSource::safe_midi_file_extension (*i)) {
1494 if (reader.num_tracks() > 1) {
1495 multichannel = true; // "channel" == track here...
1498 /* XXX we need err = true handling here in case
1499 we can't check the file
1512 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1514 #ifdef PLATFORM_WINDOWS
1517 std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
1520 if (mkdir (tmpdir.c_str(), 0744)) {
1521 if (errno != EEXIST) {
1526 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1528 char tmpc[PATH_MAX+1];
1530 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1534 if (link ((*i).c_str(), tmpc)) {
1544 rmdir (tmpdir.c_str());
1549 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
1550 : SoundFileBrowser (title, s, false)
1552 chooser.set_select_multiple (false);
1553 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1554 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1558 SoundFileChooser::on_hide ()
1560 ArdourWindow::on_hide();
1564 _session->cancel_audition();
1569 SoundFileChooser::get_filename ()
1571 vector<string> paths;
1573 paths = get_paths ();
1575 if (paths.empty()) {
1579 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1583 return paths.front();
1586 SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s,
1587 uint32_t selected_audio_tracks,
1588 uint32_t selected_midi_tracks,
1590 Editing::ImportMode mode_hint)
1591 : SoundFileBrowser (title, s, persistent)
1592 , copy_files_btn ( _("Copy files to session"))
1593 , selected_audio_track_cnt (selected_audio_tracks)
1594 , selected_midi_track_cnt (selected_midi_tracks)
1600 set_size_request (-1, 450);
1602 block_two.set_border_width (12);
1603 block_three.set_border_width (12);
1604 block_four.set_border_width (12);
1606 options.set_spacing (12);
1609 str.push_back (_("file timestamp"));
1610 str.push_back (_("edit point"));
1611 str.push_back (_("playhead"));
1612 str.push_back (_("session start"));
1613 set_popdown_strings (where_combo, str);
1614 where_combo.set_active_text (str.front());
1616 Label* l = manage (new Label);
1617 l->set_markup (_("<b>Add files as ...</b>"));
1619 vbox = manage (new VBox);
1620 vbox->set_border_width (12);
1621 vbox->set_spacing (6);
1622 vbox->pack_start (*l, false, false);
1623 vbox->pack_start (action_combo, false, false);
1624 hbox = manage (new HBox);
1625 hbox->pack_start (*vbox, false, false);
1626 options.pack_start (*hbox, false, false);
1628 /* dummy entry for action combo so that it doesn't look odd if we
1629 come up with no tracks selected.
1633 str.push_back (importmode2string (mode_hint));
1634 set_popdown_strings (action_combo, str);
1635 action_combo.set_active_text (str.front());
1636 action_combo.set_sensitive (false);
1638 l = manage (new Label);
1639 l->set_markup (_("<b>Insert at</b>"));
1641 vbox = manage (new VBox);
1642 vbox->set_border_width (12);
1643 vbox->set_spacing (6);
1644 vbox->pack_start (*l, false, false);
1645 vbox->pack_start (where_combo, false, false);
1646 hbox = manage (new HBox);
1647 hbox->pack_start (*vbox, false, false);
1648 options.pack_start (*hbox, false, false);
1651 l = manage (new Label);
1652 l->set_markup (_("<b>Mapping</b>"));
1654 vbox = manage (new VBox);
1655 vbox->set_border_width (12);
1656 vbox->set_spacing (6);
1657 vbox->pack_start (*l, false, false);
1658 vbox->pack_start (channel_combo, false, false);
1659 hbox = manage (new HBox);
1660 hbox->pack_start (*vbox, false, false);
1661 options.pack_start (*hbox, false, false);
1664 str.push_back (_("one track per file"));
1665 set_popdown_strings (channel_combo, str);
1666 channel_combo.set_active_text (str.front());
1667 channel_combo.set_sensitive (false);
1669 l = manage (new Label);
1670 l->set_markup (_("<b>Conversion quality</b>"));
1672 vbox = manage (new VBox);
1673 vbox->set_border_width (12);
1674 vbox->set_spacing (6);
1675 vbox->pack_start (*l, false, false);
1676 vbox->pack_start (src_combo, false, false);
1677 hbox = manage (new HBox);
1678 hbox->pack_start (*vbox, false, false);
1679 options.pack_start (*hbox, false, false);
1682 str.push_back (_("Best"));
1683 str.push_back (_("Good"));
1684 str.push_back (_("Quick"));
1685 str.push_back (_("Fast"));
1686 str.push_back (_("Fastest"));
1688 set_popdown_strings (src_combo, str);
1689 src_combo.set_active_text (str.front());
1690 src_combo.set_sensitive (false);
1691 src_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::src_combo_changed));
1695 action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1696 channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1698 copy_files_btn.set_active (true);
1700 Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1703 copy_label->set_size_request (175, -1);
1704 copy_label->set_line_wrap (true);
1707 block_four.pack_start (copy_files_btn, false, false);
1709 options.pack_start (block_four, false, false);
1711 vpacker.pack_start (options, false, false);
1713 /* setup disposition map */
1715 disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1716 disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1717 disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1718 disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1720 disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1721 disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1722 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1723 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1725 chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1727 /* set size requests for a couple of combos to allow them to display the longest text
1728 they will ever be asked to display. This prevents them being resized when the user
1729 selects a file to import, which in turn prevents the size of the dialog from jumping
1733 t.push_back (_("one track per file"));
1734 t.push_back (_("one track per channel"));
1735 t.push_back (_("sequence files"));
1736 t.push_back (_("all files in one region"));
1737 set_popdown_strings (channel_combo, t);
1740 t.push_back (importmode2string (ImportAsTrack));
1741 t.push_back (importmode2string (ImportToTrack));
1742 t.push_back (importmode2string (ImportAsRegion));
1743 t.push_back (importmode2string (ImportAsTapeTrack));
1744 set_popdown_strings (action_combo, t);
1748 SoundFileOmega::set_mode (ImportMode mode)
1750 action_combo.set_active_text (importmode2string (mode));
1754 SoundFileOmega::get_mode () const
1756 return string2importmode (action_combo.get_active_text());
1760 SoundFileOmega::on_hide ()
1762 ArdourWindow::on_hide();
1764 _session->cancel_audition();
1769 SoundFileOmega::get_position() const
1771 string str = where_combo.get_active_text();
1773 if (str == _("file timestamp")) {
1774 return ImportAtTimestamp;
1775 } else if (str == _("edit point")) {
1776 return ImportAtEditPoint;
1777 } else if (str == _("playhead")) {
1778 return ImportAtPlayhead;
1780 return ImportAtStart;
1785 SoundFileOmega::get_src_quality() const
1787 string str = src_combo.get_active_text();
1789 if (str == _("Best")) {
1791 } else if (str == _("Good")) {
1793 } else if (str == _("Quick")) {
1795 } else if (str == _("Fast")) {
1803 SoundFileOmega::src_combo_changed()
1805 preview.set_src_quality(get_src_quality());
1809 SoundFileOmega::get_channel_disposition () const
1811 /* we use a map here because the channel combo can contain different strings
1812 depending on the state of the other combos. the map contains all possible strings
1813 and the ImportDisposition enum that corresponds to it.
1816 string str = channel_combo.get_active_text();
1817 DispositionMap::const_iterator x = disposition_map.find (str);
1819 if (x == disposition_map.end()) {
1820 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1828 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
1830 selected_audio_track_cnt = selected_audio_tracks;
1831 selected_midi_track_cnt = selected_midi_tracks;
1833 if (selected_audio_track_cnt == 0 && selected_midi_track_cnt > 0) {
1834 chooser.set_filter (midi_filter);
1835 } else if (selected_midi_track_cnt == 0 && selected_audio_track_cnt > 0) {
1836 chooser.set_filter (audio_filter);
1838 chooser.set_filter (audio_and_midi_filter);
1845 SoundFileOmega::file_selection_changed ()
1847 if (resetting_ourselves) {
1851 if (!reset_options ()) {
1852 set_action_sensitive (false);
1854 if (chooser.get_filenames().size() > 0) {
1855 set_action_sensitive (true);
1857 set_action_sensitive (false);
1863 SoundFileOmega::do_something (int action)
1865 SoundFileBrowser::do_something (action);
1867 if (action == RESPONSE_CANCEL) {
1874 vector<string> paths = get_paths ();
1875 ImportPosition pos = get_position ();
1876 ImportMode mode = get_mode ();
1877 ImportDisposition chns = get_channel_disposition ();
1881 case ImportAtEditPoint:
1882 where = PublicEditor::instance().get_preferred_edit_position ();
1884 case ImportAtTimestamp:
1887 case ImportAtPlayhead:
1888 where = _session->transport_frame();
1891 where = _session->current_start_frame();
1895 SrcQuality quality = get_src_quality();
1897 if (copy_files_btn.get_active()) {
1898 PublicEditor::instance().do_import (paths, chns, mode, quality, where);
1900 PublicEditor::instance().do_embed (paths, chns, mode, where);
1903 if (action == RESPONSE_OK) {