2 Copyright (C) 2005-2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "gtk2ardour-config.h"
34 #include <gtkmm/box.h>
35 #include <gtkmm/stock.h>
37 #include <glib/gstdio.h>
38 #include <glibmm/fileutils.h>
40 #include "pbd/convert.h"
41 #include "pbd/tokenizer.h"
42 #include "pbd/enumwriter.h"
43 #include "pbd/pthread_utils.h"
44 #include "pbd/xml++.h"
46 #include <gtkmm2ext/utils.h>
48 #include "evoral/SMF.hpp"
50 #include "ardour/audio_library.h"
51 #include "ardour/auditioner.h"
52 #include "ardour/audioregion.h"
53 #include "ardour/audiofilesource.h"
54 #include "ardour/smf_source.h"
55 #include "ardour/region_factory.h"
56 #include "ardour/source_factory.h"
57 #include "ardour/session.h"
58 #include "ardour/session_directory.h"
59 #include "ardour/srcfilesource.h"
61 #include "ardour_ui.h"
63 #include "gui_thread.h"
67 #include "gain_meter.h"
68 #include "main_clock.h"
69 #include "public_editor.h"
71 #include "sfdb_freesound_mootcher.h"
73 using namespace ARDOUR;
77 using namespace Gtkmm2ext;
78 using namespace Editing;
82 string SoundFileBrowser::persistent_folder;
83 typedef TreeView::Selection::ListHandle_Path ListPath;
86 string2importmode (string str)
88 if (str == _("as new tracks")) {
90 } else if (str == _("to selected tracks")) {
92 } else if (str == _("to region list")) {
93 return ImportAsRegion;
94 } else if (str == _("as new tape tracks")) {
95 return ImportAsTapeTrack;
98 warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
100 return ImportAsTrack;
104 importmode2string (ImportMode mode)
108 return _("as new tracks");
110 return _("to selected tracks");
112 return _("to region list");
113 case ImportAsTapeTrack:
114 return _("as new tape tracks");
117 return _("as new tracks");
120 SoundFileBox::SoundFileBox (bool /*persistent*/)
122 length_clock ("sfboxLengthClock", true, "", false, false, true, false),
123 timecode_clock ("sfboxTimecodeClock", true, "", false, false, false, false),
125 autoplay_btn (_("Auto-play")),
126 seek_slider(0,1000,1),
130 set_name (X_("SoundFileBox"));
131 set_size_request (300, -1);
133 preview_label.set_markup (_("<b>Sound File Information</b>"));
135 border_frame.set_label_widget (preview_label);
136 border_frame.add (main_box);
138 pack_start (border_frame, true, true);
139 set_border_width (6);
141 main_box.set_border_width (6);
143 length.set_text (_("Length:"));
144 length.set_alignment (1, 0.5);
145 timecode.set_text (_("Timestamp:"));
146 timecode.set_alignment (1, 0.5);
147 format.set_text (_("Format:"));
148 format.set_alignment (1, 0.5);
149 channels.set_text (_("Channels:"));
150 channels.set_alignment (1, 0.5);
151 samplerate.set_text (_("Sample rate:"));
152 samplerate.set_alignment (1, 0.5);
154 preview_label.set_max_width_chars (50);
155 preview_label.set_ellipsize (Pango::ELLIPSIZE_END);
157 format_text.set_max_width_chars (20);
158 format_text.set_ellipsize (Pango::ELLIPSIZE_END);
159 format_text.set_alignment (0, 1);
161 table.set_col_spacings (6);
162 table.set_homogeneous (false);
163 table.set_row_spacings (6);
165 table.attach (channels, 0, 1, 0, 1, FILL, FILL);
166 table.attach (samplerate, 0, 1, 1, 2, FILL, FILL);
167 table.attach (format, 0, 1, 2, 4, FILL, FILL);
168 table.attach (length, 0, 1, 4, 5, FILL, FILL);
169 table.attach (timecode, 0, 1, 5, 6, FILL, FILL);
171 table.attach (channels_value, 1, 2, 0, 1, FILL, FILL);
172 table.attach (samplerate_value, 1, 2, 1, 2, FILL, FILL);
173 table.attach (format_text, 1, 2, 2, 4, FILL, FILL);
174 table.attach (length_clock, 1, 2, 4, 5, FILL, FILL);
175 table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL);
177 length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock->mode());
178 timecode_clock.set_mode (AudioClock::Timecode);
180 main_box.pack_start (table, false, false);
182 tags_entry.set_editable (true);
183 tags_entry.set_wrap_mode(Gtk::WRAP_WORD);
184 tags_entry.signal_focus_out_event().connect (sigc::mem_fun (*this, &SoundFileBox::tags_entry_left));
186 Label* label = manage (new Label (_("Tags:")));
187 label->set_alignment (0.0f, 0.5f);
188 main_box.pack_start (*label, false, false);
189 main_box.pack_start (tags_entry, true, true);
191 main_box.pack_start (bottom_box, false, false);
193 play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
194 // play_btn.set_label (_("Play"));
196 stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
197 // stop_btn.set_label (_("Stop"));
199 bottom_box.set_homogeneous (false);
200 bottom_box.set_spacing (6);
201 bottom_box.pack_start(play_btn, true, true);
202 bottom_box.pack_start(stop_btn, true, true);
203 bottom_box.pack_start(autoplay_btn, false, false);
205 seek_slider.set_draw_value(false);
207 seek_slider.add_events(Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
208 seek_slider.signal_button_press_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_press), false);
209 seek_slider.signal_button_release_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_release), false);
210 main_box.pack_start (seek_slider, false, false);
212 play_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::audition));
213 stop_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::stop_audition));
215 stop_btn.set_sensitive (false);
217 channels_value.set_alignment (0.0f, 0.5f);
218 samplerate_value.set_alignment (0.0f, 0.5f);
222 SoundFileBox::set_session(Session* s)
224 SessionHandlePtr::set_session (s);
226 length_clock.set_session (s);
227 timecode_clock.set_session (s);
230 play_btn.set_sensitive (false);
231 stop_btn.set_sensitive (false);
232 auditioner_connections.drop_connections();
234 auditioner_connections.drop_connections();
235 _session->AuditionActive.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_active, this, _1), gui_context());
236 _session->the_auditioner()->AuditionProgress.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_progress, this, _1, _2), gui_context());
241 SoundFileBox::audition_active(bool active) {
242 stop_btn.set_sensitive (active);
243 seek_slider.set_sensitive (active);
245 seek_slider.set_value(0);
250 SoundFileBox::audition_progress(ARDOUR::framecnt_t pos, ARDOUR::framecnt_t len) {
252 seek_slider.set_value( 1000.0 * pos / len);
253 seek_slider.set_sensitive (true);
258 SoundFileBox::seek_button_press(GdkEventButton*) {
260 return false; // pass on to slider
264 SoundFileBox::seek_button_release(GdkEventButton*) {
266 _session->the_auditioner()->seek_to_percent(seek_slider.get_value() / 10.0);
267 seek_slider.set_sensitive (false);
268 return false; // pass on to slider
272 SoundFileBox::setup_labels (const string& filename)
275 // save existing tags
283 if (SMFSource::valid_midi_file (path)) {
285 boost::shared_ptr<SMFSource> ms =
286 boost::dynamic_pointer_cast<SMFSource> (
287 SourceFactory::createExternal (DataType::MIDI, *_session,
288 path, 0, Source::Flag (0), false));
290 preview_label.set_markup (_("<b>Midi File Information</b>"));
292 format_text.set_text ("MIDI");
293 samplerate_value.set_text ("-");
294 tags_entry.get_buffer()->set_text ("");
295 timecode_clock.set (0);
296 tags_entry.set_sensitive (false);
299 channels_value.set_text (to_string(ms->num_tracks(), std::dec));
300 length_clock.set (ms->length(ms->timeline_position()));
302 channels_value.set_text ("");
303 length_clock.set (0);
306 if (_session && ms) {
307 play_btn.set_sensitive (true);
309 play_btn.set_sensitive (false);
315 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
317 preview_label.set_markup (_("<b>Sound File Information</b>"));
318 format_text.set_text ("");
319 channels_value.set_text ("");
320 samplerate_value.set_text ("");
321 tags_entry.get_buffer()->set_text ("");
323 length_clock.set (0);
324 timecode_clock.set (0);
326 tags_entry.set_sensitive (false);
327 play_btn.set_sensitive (false);
332 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::Markup::escape_text (Glib::path_get_basename (filename))));
333 std::string n = sf_info.format_name;
334 if (n.substr (0, 8) == X_("Format: ")) {
337 format_text.set_text (n);
338 channels_value.set_text (to_string (sf_info.channels, std::dec));
340 if (_session && sf_info.samplerate != _session->frame_rate()) {
341 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
342 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
343 samplerate_value.set_name ("NewSessionSR1Label");
344 samplerate.set_name ("NewSessionSR1Label");
346 samplerate.set_text (_("Sample rate:"));
347 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
348 samplerate_value.set_name ("NewSessionSR2Label");
349 samplerate.set_name ("NewSessionSR2Label");
352 framecnt_t const nfr = _session ? _session->nominal_frame_rate() : 25;
353 double src_coef = (double) nfr / sf_info.samplerate;
355 length_clock.set (sf_info.length * src_coef + 0.5, true);
356 timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
358 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
360 vector<string> tags = Library->get_tags (string ("//") + filename);
362 stringstream tag_string;
363 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
364 if (i != tags.begin()) {
369 tags_entry.get_buffer()->set_text (tag_string.str());
371 tags_entry.set_sensitive (true);
373 play_btn.set_sensitive (true);
380 SoundFileBox::autoplay() const
382 return autoplay_btn.get_active();
386 SoundFileBox::audition_oneshot()
393 SoundFileBox::audition ()
399 _session->cancel_audition();
401 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
402 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
406 boost::shared_ptr<Region> r;
408 if (SMFSource::valid_midi_file (path)) {
410 boost::shared_ptr<SMFSource> ms =
411 boost::dynamic_pointer_cast<SMFSource> (
412 SourceFactory::createExternal (DataType::MIDI, *_session,
413 path, 0, Source::Flag (0), false));
415 string rname = region_name_from_path (ms->path(), false);
419 plist.add (ARDOUR::Properties::start, 0);
420 plist.add (ARDOUR::Properties::length, ms->length(ms->timeline_position()));
421 plist.add (ARDOUR::Properties::name, rname);
422 plist.add (ARDOUR::Properties::layer, 0);
424 r = boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (boost::dynamic_pointer_cast<Source>(ms), plist, false));
430 boost::shared_ptr<AudioFileSource> afs;
431 bool old_sbp = AudioSource::get_build_peakfiles ();
433 /* don't even think of building peakfiles for these files */
435 AudioSource::set_build_peakfiles (false);
437 for (int n = 0; n < sf_info.channels; ++n) {
439 afs = boost::dynamic_pointer_cast<AudioFileSource> (
440 SourceFactory::createExternal (DataType::AUDIO, *_session,
442 Source::Flag (0), false));
443 if (afs->sample_rate() != _session->nominal_frame_rate()) {
444 boost::shared_ptr<SrcFileSource> sfs (new SrcFileSource(*_session, afs, _src_quality));
445 srclist.push_back(sfs);
447 srclist.push_back(afs);
450 } catch (failed_constructor& err) {
451 error << _("Could not access soundfile: ") << path << endmsg;
452 AudioSource::set_build_peakfiles (old_sbp);
457 AudioSource::set_build_peakfiles (old_sbp);
459 if (srclist.empty()) {
463 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
464 string rname = region_name_from_path (afs->path(), false);
468 plist.add (ARDOUR::Properties::start, 0);
469 plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->timeline_position()));
470 plist.add (ARDOUR::Properties::name, rname);
471 plist.add (ARDOUR::Properties::layer, 0);
473 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false));
476 frameoffset_t audition_position = 0;
477 switch(_import_position) {
478 case ImportAtTimestamp:
479 audition_position = 0;
481 case ImportAtPlayhead:
482 audition_position = _session->transport_frame();
485 audition_position = _session->current_start_frame();
487 case ImportAtEditPoint:
488 audition_position = PublicEditor::instance().get_preferred_edit_position ();
491 r->set_position(audition_position);
493 _session->audition_region(r);
497 SoundFileBox::stop_audition ()
500 _session->cancel_audition();
505 SoundFileBox::tags_entry_left (GdkEventFocus *)
512 SoundFileBox::tags_changed ()
514 string tag_string = tags_entry.get_buffer()->get_text ();
516 if (tag_string.empty()) {
522 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
523 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
531 SoundFileBox::save_tags (const vector<string>& tags)
533 Library->set_tags (string ("//") + path, tags);
534 Library->save_changes ();
537 SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persistent)
538 : ArdourWindow (title)
539 , found_list (ListStore::create(found_list_columns))
540 , freesound_list (ListStore::create(freesound_list_columns))
541 , chooser (FILE_CHOOSER_ACTION_OPEN)
542 , preview (persistent)
543 , found_search_btn (_("Search"))
544 , found_list_view (found_list)
545 , freesound_search_btn (_("Search"))
546 , freesound_list_view (freesound_list)
547 , resetting_ourselves (false)
551 , ok_button (Stock::OK)
552 , cancel_button (Stock::CANCEL)
553 , apply_button (Stock::APPLY)
558 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
559 chooser.add_shortcut_folder_uri("file:///Library/Audio/Apple Loops");
560 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
561 chooser.add_shortcut_folder_uri("file:///Volumes");
564 //add the file chooser
566 chooser.set_border_width (12);
568 audio_and_midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun (*this, &SoundFileBrowser::on_audio_and_midi_filter));
569 audio_and_midi_filter.set_name (_("Audio and MIDI files"));
571 audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
572 audio_filter.set_name (_("Audio files"));
574 midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
575 midi_filter.set_name (_("MIDI files"));
577 matchall_filter.add_pattern ("*.*");
578 matchall_filter.set_name (_("All files"));
580 chooser.add_filter (audio_and_midi_filter);
581 chooser.add_filter (audio_filter);
582 chooser.add_filter (midi_filter);
583 chooser.add_filter (matchall_filter);
584 chooser.set_select_multiple (true);
585 chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
586 chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
589 /* some broken redraw behaviour - this is a bandaid */
590 chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
593 if (!persistent_folder.empty()) {
594 chooser.set_current_folder (persistent_folder);
597 notebook.append_page (chooser, _("Browse Files"));
599 hpacker.set_spacing (6);
600 hpacker.pack_start (notebook, true, true);
601 hpacker.pack_start (preview, false, false);
603 vpacker.set_spacing (6);
604 vpacker.pack_start (hpacker, true, true);
614 hbox = manage(new HBox);
615 hbox->pack_start (found_entry);
616 hbox->pack_start (found_search_btn);
618 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
619 scroll->add(found_list_view);
620 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
622 vbox = manage(new VBox);
623 vbox->pack_start (*hbox, PACK_SHRINK);
624 vbox->pack_start (*scroll);
626 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
628 found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
630 found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
632 found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
633 found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
635 notebook.append_page (*vbox, _("Search Tags"));
637 //add freesound search
642 passbox = manage(new HBox);
643 passbox->set_spacing (6);
645 label = manage (new Label);
646 label->set_text (_("Tags:"));
647 passbox->pack_start (*label, false, false);
648 passbox->pack_start (freesound_entry, true, true);
650 label = manage (new Label);
651 label->set_text (_("Sort:"));
652 passbox->pack_start (*label, false, false);
653 passbox->pack_start (freesound_sort, false, false);
654 freesound_sort.clear_items();
656 // Order of the following must correspond with enum sortMethod
657 // in sfdb_freesound_mootcher.h
658 freesound_sort.append_text(_("None"));
659 freesound_sort.append_text(_("Longest"));
660 freesound_sort.append_text(_("Shortest"));
661 freesound_sort.append_text(_("Newest"));
662 freesound_sort.append_text(_("Oldest"));
663 freesound_sort.append_text(_("Most downloaded"));
664 freesound_sort.append_text(_("Least downloaded"));
665 freesound_sort.append_text(_("Highest rated"));
666 freesound_sort.append_text(_("Lowest rated"));
667 freesound_sort.set_active(0);
669 passbox->pack_start (freesound_search_btn, false, false);
670 passbox->pack_start (freesound_more_btn, false, false);
671 freesound_more_btn.set_label(_("More"));
672 freesound_more_btn.set_sensitive(false);
674 passbox->pack_start (freesound_similar_btn, false, false);
675 freesound_similar_btn.set_label(_("Similar"));
676 freesound_similar_btn.set_sensitive(false);
678 scroll = manage(new ScrolledWindow);
679 scroll->add(freesound_list_view);
680 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
682 vbox = manage(new VBox);
683 vbox->set_spacing (3);
684 vbox->pack_start (*passbox, PACK_SHRINK);
685 vbox->pack_start (*scroll);
687 freesound_list_view.append_column(_("ID") , freesound_list_columns.id);
688 freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
689 // freesound_list_view.append_column(_("URI") , freesound_list_columns.uri);
690 freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
691 freesound_list_view.append_column(_("Size"), freesound_list_columns.filesize);
692 freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
693 freesound_list_view.append_column(_("License"), freesound_list_columns.license);
694 freesound_list_view.get_column(0)->set_alignment(0.5);
695 freesound_list_view.get_column(1)->set_expand(true); // filename
696 freesound_list_view.get_column(1)->set_resizable(true); // filename
697 freesound_list_view.get_column(2)->set_alignment(0.5);
698 freesound_list_view.get_column(3)->set_alignment(0.5);
699 freesound_list_view.get_column(4)->set_alignment(0.5);
700 freesound_list_view.get_column(5)->set_alignment(0.5);
702 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
703 freesound_list_view.set_tooltip_column(1);
705 freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
706 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
707 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
708 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
709 freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
710 freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
711 notebook.append_page (*vbox, _("Search Freesound"));
713 notebook.set_size_request (500, -1);
714 notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
718 Gtk::HButtonBox* button_box = manage (new HButtonBox);
720 button_box->set_layout (BUTTONBOX_END);
721 button_box->pack_start (cancel_button, false, false);
722 cancel_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_CANCEL));
724 button_box->pack_start (apply_button, false, false);
725 apply_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_APPLY));
728 button_box->pack_start (ok_button, false, false);
729 ok_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_OK));
731 Gtkmm2ext::UI::instance()->set_tip (ok_button, _("Press to import selected files and close this window"));
732 Gtkmm2ext::UI::instance()->set_tip (apply_button, _("Press to import selected files and leave this window open"));
733 Gtkmm2ext::UI::instance()->set_tip (cancel_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 ok_button.set_sensitive (yn);
765 apply_button.set_sensitive (yn);
769 SoundFileBrowser::do_something (int action)
776 SoundFileBrowser::on_show ()
778 ArdourWindow::on_show ();
783 SoundFileBrowser::clear_selection ()
785 chooser.unselect_all ();
786 found_list_view.get_selection()->unselect_all ();
790 SoundFileBrowser::chooser_file_activated ()
796 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
802 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
808 SoundFileBrowser::set_session (Session* s)
810 ArdourWindow::set_session (s);
811 preview.set_session (s);
816 remove_gain_meter ();
821 SoundFileBrowser::add_gain_meter ()
825 gm = new GainMeter (_session, 250);
827 boost::shared_ptr<Route> r = _session->the_auditioner ();
829 gm->set_controls (r, r->shared_peak_meter(), r->amp());
830 gm->set_fader_name (X_("GainFader"));
832 meter_packer.set_border_width (12);
833 meter_packer.pack_start (*gm, false, true);
834 hpacker.pack_end (meter_packer, false, false);
835 meter_packer.show_all ();
840 SoundFileBrowser::remove_gain_meter ()
843 meter_packer.remove (*gm);
844 hpacker.remove (meter_packer);
851 SoundFileBrowser::start_metering ()
853 metering_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
857 SoundFileBrowser::stop_metering ()
859 metering_connection.disconnect();
863 SoundFileBrowser::meter ()
865 if (is_mapped () && _session && gm) {
866 gm->update_meters ();
871 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
873 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
877 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
879 return SMFSource::safe_midi_file_extension (filter_info.filename);
883 SoundFileBrowser::on_audio_and_midi_filter (const FileFilter::Info& filter_info)
885 return on_audio_filter (filter_info) || on_midi_filter (filter_info);
889 SoundFileBrowser::update_preview ()
891 if (preview.setup_labels (chooser.get_preview_filename())) {
892 if (preview.autoplay()) {
893 Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
899 SoundFileBrowser::found_list_view_selected ()
901 if (!reset_options ()) {
902 set_action_sensitive (false);
906 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
909 TreeIter iter = found_list->get_iter(*rows.begin());
910 file = (*iter)[found_list_columns.pathname];
911 chooser.set_filename (file);
912 set_action_sensitive (true);
914 set_action_sensitive (false);
917 preview.setup_labels (file);
922 SoundFileBrowser::found_search_clicked ()
924 string tag_string = found_entry.get_text ();
928 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
929 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
933 vector<string> results;
934 Library->search_members_and (results, tags);
937 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
938 TreeModel::iterator new_row = found_list->append();
939 TreeModel::Row row = *new_row;
940 string path = Glib::filename_from_uri (string ("file:") + *i);
941 row[found_list_columns.pathname] = path;
947 SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
950 Mootcher *mootcher = new Mootcher;
953 string id = (*iter)[freesound_list_columns.id];
954 string uri = (*iter)[freesound_list_columns.uri];
955 string ofn = (*iter)[freesound_list_columns.filename];
957 if (mootcher->checkAudioFile(ofn, id)) {
958 // file already exists, no need to download it again
959 file = mootcher->audioFileName;
961 (*iter)[freesound_list_columns.started] = false;
964 if (!(*iter)[freesound_list_columns.started]) {
965 // start downloading the sound file
966 (*iter)[freesound_list_columns.started] = true;
967 mootcher->fetchAudioFile(ofn, id, uri, this);
973 SoundFileBrowser::freesound_list_view_selected ()
976 if (!reset_options ()) {
977 set_action_sensitive (false);
980 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
981 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
982 file = freesound_get_audio_file (freesound_list->get_iter(*i));
985 switch (rows.size()) {
988 freesound_similar_btn.set_sensitive(false);
989 set_action_sensitive (false);
992 // exactly one item selected
994 // file exists on disk already
995 chooser.set_filename (file);
996 preview.setup_labels (file);
997 set_action_sensitive (true);
999 freesound_similar_btn.set_sensitive(true);
1002 // multiple items selected
1003 preview.setup_labels ("");
1004 freesound_similar_btn.set_sensitive(false);
1012 SoundFileBrowser::refresh_display(std::string ID, std::string file)
1014 // called when the mootcher has finished downloading a file
1015 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1016 if (rows.size() == 1) {
1017 // there's a single item selected in the freesound list
1018 //XXX make a function to be used to construct the actual file name both here and in the mootcher
1019 Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
1020 std::string selected_ID = (*row)[freesound_list_columns.id];
1021 if (ID == selected_ID) {
1022 // the selected item in the freesound list is the item that has just finished downloading
1023 chooser.set_filename(file);
1024 preview.setup_labels (file);
1025 set_action_sensitive (true);
1031 SoundFileBrowser::freesound_search_clicked ()
1034 freesound_list->clear();
1040 SoundFileBrowser::freesound_more_clicked ()
1045 snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
1046 freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
1050 SoundFileBrowser::freesound_similar_clicked ()
1052 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1053 if (rows.size() == 1) {
1056 Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
1057 id = (*iter)[freesound_list_columns.id];
1058 freesound_list->clear();
1060 GdkCursor *prev_cursor;
1061 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1062 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1065 std::string theString = mootcher.searchSimilar(id);
1067 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1068 handle_freesound_results(theString);
1073 SoundFileBrowser::freesound_search()
1077 string search_string = freesound_entry.get_text ();
1078 enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
1080 GdkCursor *prev_cursor;
1081 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1082 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1085 std::string theString = mootcher.searchText(
1089 "", // OSX eats anything incl mp3
1091 "type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
1096 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1097 handle_freesound_results(theString);
1101 SoundFileBrowser::handle_freesound_results(std::string theString) {
1103 doc.read_buffer( theString );
1104 XMLNode *root = doc.root();
1107 error << "no root XML node!" << endmsg;
1111 if ( strcmp(root->name().c_str(), "response") != 0) {
1112 error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
1116 // find out how many pages are available to search
1117 int freesound_n_pages = 1;
1118 XMLNode *res = root->child("num_pages");
1120 string result = res->child("text")->content();
1121 freesound_n_pages = atoi(result);
1124 int more_pages = freesound_n_pages - freesound_page;
1126 if (more_pages > 0) {
1127 freesound_more_btn.set_sensitive(true);
1128 freesound_more_btn.set_tooltip_text(string_compose(P_(
1129 "%1 more page of 100 results available",
1130 "%1 more pages of 100 results available",
1131 more_pages), more_pages));
1133 freesound_more_btn.set_sensitive(false);
1134 freesound_more_btn.set_tooltip_text(_("No more results available"));
1137 XMLNode *sounds_root = root->child("sounds");
1139 error << "no child node \"sounds\" found!" << endmsg;
1143 XMLNodeList sounds = sounds_root->children();
1144 if (sounds.size() == 0) {
1149 XMLNodeConstIterator niter;
1151 for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
1153 if( strcmp( node->name().c_str(), "resource") != 0 ) {
1154 error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
1158 // node->dump(cerr, "node:");
1161 XMLNode *id_node = node->child ("id");
1162 XMLNode *uri_node = node->child ("serve");
1163 XMLNode *ofn_node = node->child ("original_filename");
1164 XMLNode *dur_node = node->child ("duration");
1165 XMLNode *siz_node = node->child ("filesize");
1166 XMLNode *srt_node = node->child ("samplerate");
1167 XMLNode *lic_node = node->child ("license");
1169 if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
1171 std::string id = id_node->child("text")->content();
1172 std::string uri = uri_node->child("text")->content();
1173 std::string ofn = ofn_node->child("text")->content();
1174 std::string dur = dur_node->child("text")->content();
1175 std::string siz = siz_node->child("text")->content();
1176 std::string srt = srt_node->child("text")->content();
1177 std::string lic = lic_node->child("text")->content();
1180 // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
1182 double duration_seconds = atof(dur);
1184 char duration_hhmmss[16];
1185 if (duration_seconds >= 99 * 60 * 60) {
1186 strcpy(duration_hhmmss, ">99h");
1188 s = modf(duration_seconds/60, &m) * 60;
1189 m = modf(m/60, &h) * 60;
1190 sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
1195 double size_bytes = atof(siz);
1197 if (size_bytes < 1000) {
1198 sprintf(bsize, "%.0f %s", size_bytes, _("B"));
1199 } else if (size_bytes < 1000000 ) {
1200 sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
1201 } else if (size_bytes < 10000000) {
1202 sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
1203 } else if (size_bytes < 1000000000) {
1204 sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
1206 sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
1209 /* see http://www.freesound.org/help/faq/#licenses */
1210 char shortlicense[64];
1211 if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
1212 sprintf(shortlicense, "CC-BY-NC");
1213 } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
1214 sprintf(shortlicense, "CC-BY");
1215 } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
1216 sprintf(shortlicense, "sampling+");
1217 } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
1218 sprintf(shortlicense, "PD");
1220 snprintf(shortlicense, 64, "%s", lic.c_str());
1221 shortlicense[63]= '\0';
1224 TreeModel::iterator new_row = freesound_list->append();
1225 TreeModel::Row row = *new_row;
1227 row[freesound_list_columns.id ] = id;
1228 row[freesound_list_columns.uri ] = uri;
1229 row[freesound_list_columns.filename] = ofn;
1230 row[freesound_list_columns.duration] = duration_hhmmss;
1231 row[freesound_list_columns.filesize] = bsize;
1232 row[freesound_list_columns.smplrate] = srt;
1233 row[freesound_list_columns.license ] = shortlicense;
1240 SoundFileBrowser::get_paths ()
1242 vector<string> results;
1244 int n = notebook.get_current_page ();
1247 vector<string> filenames = chooser.get_filenames();
1248 vector<string>::iterator i;
1250 for (i = filenames.begin(); i != filenames.end(); ++i) {
1252 if ((!stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
1253 results.push_back (*i);
1257 } else if (n == 1) {
1259 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1260 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1261 TreeIter iter = found_list->get_iter(*i);
1262 string str = (*iter)[found_list_columns.pathname];
1264 results.push_back (str);
1267 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1268 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1269 string str = freesound_get_audio_file (freesound_list->get_iter(*i));
1271 results.push_back (str);
1280 SoundFileOmega::reset_options_noret ()
1282 if (!resetting_ourselves) {
1283 (void) reset_options ();
1288 SoundFileOmega::reset_options ()
1290 vector<string> paths = get_paths ();
1292 if (paths.empty()) {
1294 channel_combo.set_sensitive (false);
1295 action_combo.set_sensitive (false);
1296 where_combo.set_sensitive (false);
1297 copy_files_btn.set_active (true);
1298 copy_files_btn.set_sensitive (false);
1304 channel_combo.set_sensitive (true);
1305 action_combo.set_sensitive (true);
1306 where_combo.set_sensitive (true);
1308 /* if we get through this function successfully, this may be
1309 reset at the end, once we know if we can use hard links
1310 to do embedding (or if we are importing a MIDI file).
1313 if (Config->get_only_copy_imported_files()) {
1314 copy_files_btn.set_sensitive (false);
1316 copy_files_btn.set_sensitive (false);
1322 bool selection_includes_multichannel;
1323 bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1326 /* See if we are thinking about importing any MIDI files */
1327 vector<string>::iterator i = paths.begin ();
1328 while (i != paths.end() && SMFSource::valid_midi_file (*i) == false) {
1331 bool const have_a_midi_file = (i != paths.end ());
1333 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1334 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1338 string existing_choice;
1339 vector<string> action_strings;
1341 resetting_ourselves = true;
1343 if (chooser.get_filter() == &audio_filter) {
1347 if (selected_audio_track_cnt > 0) {
1348 if (channel_combo.get_active_text().length()) {
1349 ImportDisposition id = get_channel_disposition();
1352 case Editing::ImportDistinctFiles:
1353 if (selected_audio_track_cnt == paths.size()) {
1354 action_strings.push_back (importmode2string (ImportToTrack));
1358 case Editing::ImportDistinctChannels:
1359 /* XXX it would be nice to allow channel-per-selected track
1360 but its too hard we don't want to deal with all the
1361 different per-file + per-track channel configurations.
1366 action_strings.push_back (importmode2string (ImportToTrack));
1376 if (selected_midi_track_cnt > 0) {
1377 action_strings.push_back (importmode2string (ImportToTrack));
1381 action_strings.push_back (importmode2string (ImportAsTrack));
1382 action_strings.push_back (importmode2string (ImportAsRegion));
1383 action_strings.push_back (importmode2string (ImportAsTapeTrack));
1385 existing_choice = action_combo.get_active_text();
1387 set_popdown_strings (action_combo, action_strings);
1389 /* preserve any existing choice, if possible */
1392 if (existing_choice.length()) {
1393 vector<string>::iterator x;
1394 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1395 if (*x == existing_choice) {
1396 action_combo.set_active_text (existing_choice);
1400 if (x == action_strings.end()) {
1401 action_combo.set_active_text (action_strings.front());
1404 action_combo.set_active_text (action_strings.front());
1407 resetting_ourselves = false;
1409 if ((mode = get_mode()) == ImportAsRegion) {
1410 where_combo.set_sensitive (false);
1412 where_combo.set_sensitive (true);
1415 vector<string> channel_strings;
1417 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1418 channel_strings.push_back (_("one track per file"));
1420 if (selection_includes_multichannel) {
1421 channel_strings.push_back (_("one track per channel"));
1424 if (paths.size() > 1) {
1425 /* tape tracks are a single region per track, so we cannot
1426 sequence multiple files.
1428 if (mode != ImportAsTapeTrack) {
1429 channel_strings.push_back (_("sequence files"));
1432 channel_strings.push_back (_("all files in one track"));
1433 channel_strings.push_back (_("merge files"));
1439 channel_strings.push_back (_("one region per file"));
1441 if (selection_includes_multichannel) {
1442 channel_strings.push_back (_("one region per channel"));
1445 if (paths.size() > 1) {
1447 channel_strings.push_back (_("all files in one region"));
1452 resetting_ourselves = true;
1454 existing_choice = channel_combo.get_active_text();
1456 set_popdown_strings (channel_combo, channel_strings);
1458 /* preserve any existing choice, if possible */
1460 if (existing_choice.length()) {
1461 vector<string>::iterator x;
1462 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1463 if (*x == existing_choice) {
1464 channel_combo.set_active_text (existing_choice);
1468 if (x == channel_strings.end()) {
1469 channel_combo.set_active_text (channel_strings.front());
1472 channel_combo.set_active_text (channel_strings.front());
1475 resetting_ourselves = false;
1478 src_combo.set_sensitive (true);
1480 src_combo.set_sensitive (false);
1483 /* We must copy MIDI files or those from Freesound
1484 * or any file if we are under nsm control */
1485 bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
1487 if (Config->get_only_copy_imported_files()) {
1489 if (selection_can_be_embedded_with_links && !must_copy) {
1490 copy_files_btn.set_sensitive (true);
1493 copy_files_btn.set_active (true);
1495 copy_files_btn.set_sensitive (false);
1501 copy_files_btn.set_active (true);
1503 copy_files_btn.set_sensitive (!must_copy);
1511 SoundFileOmega::bad_file_message()
1513 MessageDialog msg (*this,
1514 string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1519 resetting_ourselves = true;
1520 chooser.unselect_uri (chooser.get_preview_uri());
1521 resetting_ourselves = false;
1527 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1536 multichannel = false;
1538 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1540 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1541 if (info.channels > 1) {
1542 multichannel = true;
1547 if (sz != info.length) {
1552 if (info.samplerate != _session->frame_rate()) {
1556 } else if (SMFSource::valid_midi_file (*i)) {
1560 if (reader.num_tracks() > 1) {
1561 multichannel = true; // "channel" == track here...
1564 /* XXX we need err = true handling here in case
1565 we can't check the file
1578 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1580 #ifdef PLATFORM_WINDOWS
1583 std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
1586 if (mkdir (tmpdir.c_str(), 0744)) {
1587 if (errno != EEXIST) {
1592 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1594 char tmpc[PATH_MAX+1];
1596 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1600 if (link ((*i).c_str(), tmpc)) {
1610 rmdir (tmpdir.c_str());
1615 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
1616 : SoundFileBrowser (title, s, false)
1618 chooser.set_select_multiple (false);
1619 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1620 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1624 SoundFileChooser::on_hide ()
1626 ArdourWindow::on_hide();
1630 _session->cancel_audition();
1635 SoundFileChooser::get_filename ()
1637 vector<string> paths;
1639 paths = get_paths ();
1641 if (paths.empty()) {
1645 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1649 return paths.front();
1652 SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s,
1653 uint32_t selected_audio_tracks,
1654 uint32_t selected_midi_tracks,
1656 Editing::ImportMode mode_hint)
1657 : SoundFileBrowser (title, s, persistent)
1658 , copy_files_btn ( _("Copy files to session"))
1659 , selected_audio_track_cnt (selected_audio_tracks)
1660 , selected_midi_track_cnt (selected_midi_tracks)
1666 set_size_request (-1, 450);
1668 block_two.set_border_width (12);
1669 block_three.set_border_width (12);
1670 block_four.set_border_width (12);
1672 options.set_spacing (12);
1675 str.push_back (_("file timestamp"));
1676 str.push_back (_("edit point"));
1677 str.push_back (_("playhead"));
1678 str.push_back (_("session start"));
1679 set_popdown_strings (where_combo, str);
1680 where_combo.set_active_text (str.front());
1681 where_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::where_combo_changed));
1683 Label* l = manage (new Label);
1684 l->set_markup (_("<b>Add files as ...</b>"));
1686 vbox = manage (new VBox);
1687 vbox->set_border_width (12);
1688 vbox->set_spacing (6);
1689 vbox->pack_start (*l, false, false);
1690 vbox->pack_start (action_combo, false, false);
1691 hbox = manage (new HBox);
1692 hbox->pack_start (*vbox, false, false);
1693 options.pack_start (*hbox, false, false);
1695 /* dummy entry for action combo so that it doesn't look odd if we
1696 come up with no tracks selected.
1700 str.push_back (importmode2string (mode_hint));
1701 set_popdown_strings (action_combo, str);
1702 action_combo.set_active_text (str.front());
1703 action_combo.set_sensitive (false);
1705 l = manage (new Label);
1706 l->set_markup (_("<b>Insert at</b>"));
1708 vbox = manage (new VBox);
1709 vbox->set_border_width (12);
1710 vbox->set_spacing (6);
1711 vbox->pack_start (*l, false, false);
1712 vbox->pack_start (where_combo, false, false);
1713 hbox = manage (new HBox);
1714 hbox->pack_start (*vbox, false, false);
1715 options.pack_start (*hbox, false, false);
1718 l = manage (new Label);
1719 l->set_markup (_("<b>Mapping</b>"));
1721 vbox = manage (new VBox);
1722 vbox->set_border_width (12);
1723 vbox->set_spacing (6);
1724 vbox->pack_start (*l, false, false);
1725 vbox->pack_start (channel_combo, false, false);
1726 hbox = manage (new HBox);
1727 hbox->pack_start (*vbox, false, false);
1728 options.pack_start (*hbox, false, false);
1731 str.push_back (_("one track per file"));
1732 set_popdown_strings (channel_combo, str);
1733 channel_combo.set_active_text (str.front());
1734 channel_combo.set_sensitive (false);
1736 l = manage (new Label);
1737 l->set_markup (_("<b>Conversion quality</b>"));
1739 vbox = manage (new VBox);
1740 vbox->set_border_width (12);
1741 vbox->set_spacing (6);
1742 vbox->pack_start (*l, false, false);
1743 vbox->pack_start (src_combo, false, false);
1744 hbox = manage (new HBox);
1745 hbox->pack_start (*vbox, false, false);
1746 options.pack_start (*hbox, false, false);
1749 str.push_back (_("Best"));
1750 str.push_back (_("Good"));
1751 str.push_back (_("Quick"));
1752 str.push_back (_("Fast"));
1753 str.push_back (_("Fastest"));
1755 set_popdown_strings (src_combo, str);
1756 src_combo.set_active_text (str.front());
1757 src_combo.set_sensitive (false);
1758 src_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::src_combo_changed));
1762 action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1763 channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1765 copy_files_btn.set_active (true);
1767 Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1770 copy_label->set_size_request (175, -1);
1771 copy_label->set_line_wrap (true);
1774 block_four.pack_start (copy_files_btn, false, false);
1776 options.pack_start (block_four, false, false);
1778 vpacker.pack_start (options, false, false);
1780 /* setup disposition map */
1782 disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1783 disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1784 disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1785 disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1787 disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1788 disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1789 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1790 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1792 chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1794 /* set size requests for a couple of combos to allow them to display the longest text
1795 they will ever be asked to display. This prevents them being resized when the user
1796 selects a file to import, which in turn prevents the size of the dialog from jumping
1800 t.push_back (_("one track per file"));
1801 t.push_back (_("one track per channel"));
1802 t.push_back (_("sequence files"));
1803 t.push_back (_("all files in one region"));
1804 set_popdown_strings (channel_combo, t);
1807 t.push_back (importmode2string (ImportAsTrack));
1808 t.push_back (importmode2string (ImportToTrack));
1809 t.push_back (importmode2string (ImportAsRegion));
1810 t.push_back (importmode2string (ImportAsTapeTrack));
1811 set_popdown_strings (action_combo, t);
1815 SoundFileOmega::set_mode (ImportMode mode)
1817 action_combo.set_active_text (importmode2string (mode));
1821 SoundFileOmega::get_mode () const
1823 return string2importmode (action_combo.get_active_text());
1827 SoundFileOmega::on_hide ()
1829 ArdourWindow::on_hide();
1831 _session->cancel_audition();
1836 SoundFileOmega::get_position() const
1838 string str = where_combo.get_active_text();
1840 if (str == _("file timestamp")) {
1841 return ImportAtTimestamp;
1842 } else if (str == _("edit point")) {
1843 return ImportAtEditPoint;
1844 } else if (str == _("playhead")) {
1845 return ImportAtPlayhead;
1847 return ImportAtStart;
1852 SoundFileOmega::get_src_quality() const
1854 string str = src_combo.get_active_text();
1856 if (str == _("Best")) {
1858 } else if (str == _("Good")) {
1860 } else if (str == _("Quick")) {
1862 } else if (str == _("Fast")) {
1870 SoundFileOmega::src_combo_changed()
1872 preview.set_src_quality(get_src_quality());
1876 SoundFileOmega::where_combo_changed()
1878 preview.set_import_position(get_position());
1882 SoundFileOmega::get_channel_disposition () const
1884 /* we use a map here because the channel combo can contain different strings
1885 depending on the state of the other combos. the map contains all possible strings
1886 and the ImportDisposition enum that corresponds to it.
1889 string str = channel_combo.get_active_text();
1890 DispositionMap::const_iterator x = disposition_map.find (str);
1892 if (x == disposition_map.end()) {
1893 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1901 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
1903 selected_audio_track_cnt = selected_audio_tracks;
1904 selected_midi_track_cnt = selected_midi_tracks;
1906 if (selected_audio_track_cnt == 0 && selected_midi_track_cnt > 0) {
1907 chooser.set_filter (midi_filter);
1908 } else if (selected_midi_track_cnt == 0 && selected_audio_track_cnt > 0) {
1909 chooser.set_filter (audio_filter);
1911 chooser.set_filter (audio_and_midi_filter);
1918 SoundFileOmega::file_selection_changed ()
1920 if (resetting_ourselves) {
1924 if (!reset_options ()) {
1925 set_action_sensitive (false);
1927 if (chooser.get_filenames().size() > 0) {
1928 set_action_sensitive (true);
1930 set_action_sensitive (false);
1936 SoundFileOmega::do_something (int action)
1938 SoundFileBrowser::do_something (action);
1940 if (action == RESPONSE_CANCEL) {
1947 vector<string> paths = get_paths ();
1948 ImportPosition pos = get_position ();
1949 ImportMode mode = get_mode ();
1950 ImportDisposition chns = get_channel_disposition ();
1954 case ImportAtEditPoint:
1955 where = PublicEditor::instance().get_preferred_edit_position ();
1957 case ImportAtTimestamp:
1960 case ImportAtPlayhead:
1961 where = _session->transport_frame();
1964 where = _session->current_start_frame();
1968 SrcQuality quality = get_src_quality();
1970 if (copy_files_btn.get_active()) {
1971 PublicEditor::instance().do_import (paths, chns, mode, quality, where);
1973 PublicEditor::instance().do_embed (paths, chns, mode, where);
1976 if (action == RESPONSE_OK) {