2 Copyright (C) 2005-2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "gtk2ardour-config.h"
33 #include <gtkmm/box.h>
34 #include <gtkmm/stock.h>
36 #include "pbd/gstdio_compat.h"
37 #include <glibmm/fileutils.h>
39 #include "pbd/convert.h"
40 #include "pbd/tokenizer.h"
41 #include "pbd/enumwriter.h"
42 #include "pbd/pthread_utils.h"
43 #include "pbd/xml++.h"
45 #include <gtkmm2ext/utils.h>
47 #include "evoral/SMF.hpp"
49 #include "ardour/audio_library.h"
50 #include "ardour/auditioner.h"
51 #include "ardour/audioregion.h"
52 #include "ardour/audiofilesource.h"
53 #include "ardour/midi_region.h"
54 #include "ardour/smf_source.h"
55 #include "ardour/region_factory.h"
56 #include "ardour/source_factory.h"
57 #include "ardour/session.h"
58 #include "ardour/session_directory.h"
59 #include "ardour/srcfilesource.h"
61 #include "ardour_ui.h"
63 #include "gui_thread.h"
67 #include "gain_meter.h"
68 #include "main_clock.h"
69 #include "public_editor.h"
71 #include "ui_config.h"
73 #include "sfdb_freesound_mootcher.h"
75 using namespace ARDOUR;
79 using namespace Gtkmm2ext;
80 using namespace Editing;
84 string SoundFileBrowser::persistent_folder;
85 typedef TreeView::Selection::ListHandle_Path ListPath;
88 string2importmode (string str)
90 if (str == _("as new tracks")) {
92 } else if (str == _("to selected tracks")) {
94 } else if (str == _("to region list")) {
95 return ImportAsRegion;
96 } else if (str == _("as new tape tracks")) {
97 return ImportAsTapeTrack;
100 warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
102 return ImportAsTrack;
106 importmode2string (ImportMode mode)
110 return _("as new tracks");
112 return _("to selected tracks");
114 return _("to region list");
115 case ImportAsTapeTrack:
116 return _("as new tape tracks");
118 abort(); /*NOTREACHED*/
119 return _("as new tracks");
122 SoundFileBox::SoundFileBox (bool /*persistent*/)
124 length_clock ("sfboxLengthClock", true, "", false, false, true, false),
125 timecode_clock ("sfboxTimecodeClock", true, "", false, false, false, false),
127 autoplay_btn (_("Auto-play")),
128 seek_slider(0,1000,1),
132 set_name (X_("SoundFileBox"));
133 set_size_request (300, -1);
135 preview_label.set_markup (_("<b>Sound File Information</b>"));
137 border_frame.set_label_widget (preview_label);
138 border_frame.add (main_box);
140 pack_start (border_frame, true, true);
141 set_border_width (6);
143 main_box.set_border_width (6);
145 length.set_text (_("Length:"));
146 length.set_alignment (1, 0.5);
147 timecode.set_text (_("Timestamp:"));
148 timecode.set_alignment (1, 0.5);
149 format.set_text (_("Format:"));
150 format.set_alignment (1, 0.5);
151 channels.set_text (_("Channels:"));
152 channels.set_alignment (1, 0.5);
153 samplerate.set_text (_("Sample rate:"));
154 samplerate.set_alignment (1, 0.5);
156 preview_label.set_max_width_chars (50);
157 preview_label.set_ellipsize (Pango::ELLIPSIZE_END);
159 format_text.set_max_width_chars (20);
160 format_text.set_ellipsize (Pango::ELLIPSIZE_END);
161 format_text.set_alignment (0, 1);
163 table.set_col_spacings (6);
164 table.set_homogeneous (false);
165 table.set_row_spacings (6);
167 table.attach (channels, 0, 1, 0, 1, FILL, FILL);
168 table.attach (samplerate, 0, 1, 1, 2, FILL, FILL);
169 table.attach (format, 0, 1, 2, 4, FILL, FILL);
170 table.attach (length, 0, 1, 4, 5, FILL, FILL);
171 table.attach (timecode, 0, 1, 5, 6, FILL, FILL);
173 table.attach (channels_value, 1, 2, 0, 1, FILL, FILL);
174 table.attach (samplerate_value, 1, 2, 1, 2, FILL, FILL);
175 table.attach (format_text, 1, 2, 2, 4, FILL, FILL);
176 table.attach (length_clock, 1, 2, 4, 5, FILL, FILL);
177 table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL);
179 length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock->mode());
180 timecode_clock.set_mode (AudioClock::Timecode);
182 main_box.pack_start (table, false, false);
184 tags_entry.set_editable (true);
185 tags_entry.set_wrap_mode(Gtk::WRAP_WORD);
186 tags_entry.signal_focus_out_event().connect (sigc::mem_fun (*this, &SoundFileBox::tags_entry_left));
188 Label* label = manage (new Label (_("Tags:")));
189 label->set_alignment (0.0f, 0.5f);
190 main_box.pack_start (*label, false, false);
191 main_box.pack_start (tags_entry, true, true);
193 main_box.pack_start (bottom_box, false, false);
195 play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
196 // play_btn.set_label (_("Play"));
198 stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
199 // stop_btn.set_label (_("Stop"));
201 bottom_box.set_homogeneous (false);
202 bottom_box.set_spacing (6);
203 bottom_box.pack_start(play_btn, true, true);
204 bottom_box.pack_start(stop_btn, true, true);
205 bottom_box.pack_start(autoplay_btn, false, false);
207 seek_slider.set_draw_value(false);
209 seek_slider.add_events(Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
210 seek_slider.signal_button_press_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_press), false);
211 seek_slider.signal_button_release_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_release), false);
212 main_box.pack_start (seek_slider, false, false);
214 play_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::audition));
215 stop_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::stop_audition));
217 stop_btn.set_sensitive (false);
219 channels_value.set_alignment (0.0f, 0.5f);
220 samplerate_value.set_alignment (0.0f, 0.5f);
224 SoundFileBox::set_session(Session* s)
226 SessionHandlePtr::set_session (s);
228 length_clock.set_session (s);
229 timecode_clock.set_session (s);
232 play_btn.set_sensitive (false);
233 stop_btn.set_sensitive (false);
234 auditioner_connections.drop_connections();
236 auditioner_connections.drop_connections();
237 _session->AuditionActive.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_active, this, _1), gui_context());
238 _session->the_auditioner()->AuditionProgress.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_progress, this, _1, _2), gui_context());
243 SoundFileBox::audition_active(bool active) {
244 stop_btn.set_sensitive (active);
245 seek_slider.set_sensitive (active);
247 seek_slider.set_value(0);
252 SoundFileBox::audition_progress(ARDOUR::framecnt_t pos, ARDOUR::framecnt_t len) {
254 seek_slider.set_value( 1000.0 * pos / len);
255 seek_slider.set_sensitive (true);
260 SoundFileBox::seek_button_press(GdkEventButton*) {
262 return false; // pass on to slider
266 SoundFileBox::seek_button_release(GdkEventButton*) {
268 _session->the_auditioner()->seek_to_percent(seek_slider.get_value() / 10.0);
269 seek_slider.set_sensitive (false);
270 return false; // pass on to slider
274 SoundFileBox::setup_labels (const string& filename)
277 // save existing tags
285 if (SMFSource::valid_midi_file (path)) {
287 boost::shared_ptr<SMFSource> ms;
289 ms = boost::dynamic_pointer_cast<SMFSource> (
290 SourceFactory::createExternal (DataType::MIDI, *_session,
291 path, 0, Source::Flag (0), false));
292 } catch (const std::exception& e) {
293 error << string_compose(_("Could not read file: %1 (%2)."),
294 path, e.what()) << endmsg;
297 preview_label.set_markup (_("<b>Midi File Information</b>"));
299 format_text.set_text ("MIDI");
300 samplerate_value.set_text ("-");
301 tags_entry.get_buffer()->set_text ("");
302 timecode_clock.set (0);
303 tags_entry.set_sensitive (false);
306 channels_value.set_text (to_string(ms->num_tracks(), std::dec));
307 length_clock.set (ms->length(ms->timeline_position()));
309 channels_value.set_text ("");
310 length_clock.set (0);
313 if (_session && ms) {
314 play_btn.set_sensitive (true);
316 play_btn.set_sensitive (false);
322 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
324 preview_label.set_markup (_("<b>Sound File Information</b>"));
325 format_text.set_text ("");
326 channels_value.set_text ("");
327 samplerate_value.set_text ("");
328 tags_entry.get_buffer()->set_text ("");
330 length_clock.set (0);
331 timecode_clock.set (0);
333 tags_entry.set_sensitive (false);
334 play_btn.set_sensitive (false);
339 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::Markup::escape_text (Glib::path_get_basename (filename))));
340 std::string n = sf_info.format_name;
341 if (n.substr (0, 8) == X_("Format: ")) {
344 format_text.set_text (n);
345 channels_value.set_text (to_string (sf_info.channels, std::dec));
347 if (_session && sf_info.samplerate != _session->frame_rate()) {
348 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
349 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
350 samplerate_value.set_name ("NewSessionSR1Label");
351 samplerate.set_name ("NewSessionSR1Label");
353 samplerate.set_text (_("Sample rate:"));
354 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
355 samplerate_value.set_name ("NewSessionSR2Label");
356 samplerate.set_name ("NewSessionSR2Label");
359 framecnt_t const nfr = _session ? _session->nominal_frame_rate() : 25;
360 double src_coef = (double) nfr / sf_info.samplerate;
362 length_clock.set (sf_info.length * src_coef + 0.5, true);
363 timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
365 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
367 vector<string> tags = Library->get_tags (string ("//") + filename);
369 stringstream tag_string;
370 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
371 if (i != tags.begin()) {
376 tags_entry.get_buffer()->set_text (tag_string.str());
378 tags_entry.set_sensitive (true);
380 play_btn.set_sensitive (true);
387 SoundFileBox::autoplay() const
389 return autoplay_btn.get_active();
393 SoundFileBox::audition_oneshot()
400 SoundFileBox::audition ()
406 _session->cancel_audition();
408 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
409 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
413 boost::shared_ptr<Region> r;
415 if (SMFSource::valid_midi_file (path)) {
417 boost::shared_ptr<SMFSource> ms =
418 boost::dynamic_pointer_cast<SMFSource> (
419 SourceFactory::createExternal (DataType::MIDI, *_session,
420 path, 0, Source::Flag (0), false));
422 string rname = region_name_from_path (ms->path(), false);
426 plist.add (ARDOUR::Properties::start, 0);
427 plist.add (ARDOUR::Properties::length, ms->length(ms->timeline_position()));
428 plist.add (ARDOUR::Properties::name, rname);
429 plist.add (ARDOUR::Properties::layer, 0);
431 r = boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (boost::dynamic_pointer_cast<Source>(ms), plist, false));
437 boost::shared_ptr<AudioFileSource> afs;
438 bool old_sbp = AudioSource::get_build_peakfiles ();
440 /* don't even think of building peakfiles for these files */
442 AudioSource::set_build_peakfiles (false);
444 for (int n = 0; n < sf_info.channels; ++n) {
446 afs = boost::dynamic_pointer_cast<AudioFileSource> (
447 SourceFactory::createExternal (DataType::AUDIO, *_session,
449 Source::Flag (ARDOUR::AudioFileSource::NoPeakFile), false));
450 if (afs->sample_rate() != _session->nominal_frame_rate()) {
451 boost::shared_ptr<SrcFileSource> sfs (new SrcFileSource(*_session, afs, _src_quality));
452 srclist.push_back(sfs);
454 srclist.push_back(afs);
457 } catch (failed_constructor& err) {
458 error << _("Could not access soundfile: ") << path << endmsg;
459 AudioSource::set_build_peakfiles (old_sbp);
464 AudioSource::set_build_peakfiles (old_sbp);
466 if (srclist.empty()) {
470 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
471 string rname = region_name_from_path (afs->path(), false);
475 plist.add (ARDOUR::Properties::start, 0);
476 plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->timeline_position()));
477 plist.add (ARDOUR::Properties::name, rname);
478 plist.add (ARDOUR::Properties::layer, 0);
480 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false));
483 frameoffset_t audition_position = 0;
484 switch(_import_position) {
485 case ImportAtTimestamp:
486 audition_position = 0;
488 case ImportAtPlayhead:
489 audition_position = _session->transport_frame();
492 audition_position = _session->current_start_frame();
494 case ImportAtEditPoint:
495 audition_position = PublicEditor::instance().get_preferred_edit_position ();
498 r->set_position(audition_position);
500 _session->audition_region(r);
504 SoundFileBox::stop_audition ()
507 _session->cancel_audition();
512 SoundFileBox::tags_entry_left (GdkEventFocus *)
519 SoundFileBox::tags_changed ()
521 string tag_string = tags_entry.get_buffer()->get_text ();
523 if (tag_string.empty()) {
529 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
530 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
538 SoundFileBox::save_tags (const vector<string>& tags)
540 Library->set_tags (string ("//") + path, tags);
541 Library->save_changes ();
544 SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persistent)
545 : ArdourWindow (title)
546 , found_list (ListStore::create(found_list_columns))
547 , freesound_list (ListStore::create(freesound_list_columns))
548 , chooser (FILE_CHOOSER_ACTION_OPEN)
549 , preview (persistent)
550 , found_search_btn (_("Search"))
551 , found_list_view (found_list)
552 , freesound_search_btn (_("Search"))
553 , freesound_list_view (freesound_list)
554 , resetting_ourselves (false)
558 , import_button (_("Import"))
559 , close_button (Stock::CLOSE)
565 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
566 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
567 chooser.add_shortcut_folder_uri("file:///Library/Audio/Apple Loops");
568 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
570 catch (Glib::Error & e) {
571 std::cerr << "sfdb.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
574 Gtkmm2ext::add_volume_shortcuts (chooser);
576 //add the file chooser
578 chooser.set_border_width (12);
580 audio_and_midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun (*this, &SoundFileBrowser::on_audio_and_midi_filter));
581 audio_and_midi_filter.set_name (_("Audio and MIDI files"));
583 audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
584 audio_filter.set_name (_("Audio files"));
586 midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
587 midi_filter.set_name (_("MIDI files"));
589 matchall_filter.add_pattern ("*.*");
590 matchall_filter.set_name (_("All files"));
592 chooser.add_filter (audio_and_midi_filter);
593 chooser.add_filter (audio_filter);
594 chooser.add_filter (midi_filter);
595 chooser.add_filter (matchall_filter);
596 chooser.set_select_multiple (true);
597 chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
598 chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
601 /* some broken redraw behaviour - this is a bandaid */
602 chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
605 if (!persistent_folder.empty()) {
606 chooser.set_current_folder (persistent_folder);
609 notebook.append_page (chooser, _("Browse Files"));
611 hpacker.set_spacing (6);
612 hpacker.pack_start (notebook, true, true);
613 hpacker.pack_start (preview, false, false);
615 vpacker.set_spacing (6);
616 vpacker.pack_start (hpacker, true, true);
626 hbox = manage(new HBox);
627 hbox->pack_start (found_entry);
628 hbox->pack_start (found_search_btn);
630 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
631 scroll->add(found_list_view);
632 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
634 vbox = manage(new VBox);
635 vbox->pack_start (*hbox, PACK_SHRINK);
636 vbox->pack_start (*scroll);
638 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
640 found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
642 found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
644 found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
645 found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
647 notebook.append_page (*vbox, _("Search Tags"));
649 //add freesound search
654 passbox = manage(new HBox);
655 passbox->set_spacing (6);
657 label = manage (new Label);
658 label->set_text (_("Tags:"));
659 passbox->pack_start (*label, false, false);
660 passbox->pack_start (freesound_entry, true, true);
662 label = manage (new Label);
663 label->set_text (_("Sort:"));
664 passbox->pack_start (*label, false, false);
665 passbox->pack_start (freesound_sort, false, false);
666 freesound_sort.clear_items();
668 // Order of the following must correspond with enum sortMethod
669 // in sfdb_freesound_mootcher.h
670 freesound_sort.append_text(_("None"));
671 freesound_sort.append_text(_("Longest"));
672 freesound_sort.append_text(_("Shortest"));
673 freesound_sort.append_text(_("Newest"));
674 freesound_sort.append_text(_("Oldest"));
675 freesound_sort.append_text(_("Most downloaded"));
676 freesound_sort.append_text(_("Least downloaded"));
677 freesound_sort.append_text(_("Highest rated"));
678 freesound_sort.append_text(_("Lowest rated"));
679 freesound_sort.set_active(0);
681 passbox->pack_start (freesound_search_btn, false, false);
682 passbox->pack_start (freesound_more_btn, false, false);
683 freesound_more_btn.set_label(_("More"));
684 freesound_more_btn.set_sensitive(false);
686 passbox->pack_start (freesound_similar_btn, false, false);
687 freesound_similar_btn.set_label(_("Similar"));
688 freesound_similar_btn.set_sensitive(false);
690 scroll = manage(new ScrolledWindow);
691 scroll->add(freesound_list_view);
692 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
694 vbox = manage(new VBox);
695 vbox->set_spacing (3);
696 vbox->pack_start (*passbox, PACK_SHRINK);
697 vbox->pack_start (*scroll);
699 freesound_list_view.append_column(_("ID") , freesound_list_columns.id);
700 freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
701 // freesound_list_view.append_column(_("URI") , freesound_list_columns.uri);
702 freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
703 freesound_list_view.append_column(_("Size"), freesound_list_columns.filesize);
704 freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
705 freesound_list_view.append_column(_("License"), freesound_list_columns.license);
706 freesound_list_view.get_column(0)->set_alignment(0.5);
707 freesound_list_view.get_column(1)->set_expand(true); // filename
708 freesound_list_view.get_column(1)->set_resizable(true); // filename
709 freesound_list_view.get_column(2)->set_alignment(0.5);
710 freesound_list_view.get_column(3)->set_alignment(0.5);
711 freesound_list_view.get_column(4)->set_alignment(0.5);
712 freesound_list_view.get_column(5)->set_alignment(0.5);
714 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
715 freesound_list_view.set_tooltip_column(1);
717 freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
718 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
719 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
720 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
721 freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
722 freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
723 notebook.append_page (*vbox, _("Search Freesound"));
725 notebook.set_size_request (500, -1);
726 notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
730 Gtk::HButtonBox* button_box = manage (new HButtonBox);
732 button_box->set_layout (BUTTONBOX_END);
733 button_box->pack_start (close_button, false, false);
734 close_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_CLOSE));
736 button_box->pack_start (import_button, false, false);
737 import_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_OK));
739 Gtkmm2ext::UI::instance()->set_tip (import_button, _("Press to import selected files"));
740 Gtkmm2ext::UI::instance()->set_tip (close_button, _("Press to close this window without importing any files"));
742 vpacker.pack_end (*button_box, false, false);
744 set_wmclass (X_("import"), PROGRAM_NAME);
747 SoundFileBrowser::~SoundFileBrowser ()
749 persistent_folder = chooser.get_current_folder();
753 SoundFileBrowser::run ()
762 gtk_main_iteration ();
769 SoundFileBrowser::set_action_sensitive (bool yn)
771 import_button.set_sensitive (yn);
775 SoundFileBrowser::do_something (int action)
782 SoundFileBrowser::on_show ()
784 ArdourWindow::on_show ();
789 SoundFileBrowser::clear_selection ()
791 chooser.unselect_all ();
792 found_list_view.get_selection()->unselect_all ();
796 SoundFileBrowser::chooser_file_activated ()
802 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
808 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
814 SoundFileBrowser::set_session (Session* s)
816 ArdourWindow::set_session (s);
817 preview.set_session (s);
822 remove_gain_meter ();
827 SoundFileBrowser::add_gain_meter ()
831 gm = new GainMeter (_session, 250);
833 boost::shared_ptr<Route> r = _session->the_auditioner ();
835 gm->set_controls (r, r->shared_peak_meter(), r->amp());
836 gm->set_fader_name (X_("GainFader"));
838 meter_packer.set_border_width (12);
839 meter_packer.pack_start (*gm, false, true);
840 hpacker.pack_end (meter_packer, false, false);
841 meter_packer.show_all ();
846 SoundFileBrowser::remove_gain_meter ()
849 meter_packer.remove (*gm);
850 hpacker.remove (meter_packer);
857 SoundFileBrowser::start_metering ()
859 metering_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
863 SoundFileBrowser::stop_metering ()
865 metering_connection.disconnect();
869 SoundFileBrowser::meter ()
871 if (is_mapped () && _session && gm) {
872 gm->update_meters ();
877 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
879 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
883 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
885 return SMFSource::safe_midi_file_extension (filter_info.filename);
889 SoundFileBrowser::on_audio_and_midi_filter (const FileFilter::Info& filter_info)
891 return on_audio_filter (filter_info) || on_midi_filter (filter_info);
895 SoundFileBrowser::update_preview ()
897 if (preview.setup_labels (chooser.get_preview_filename())) {
898 if (preview.autoplay()) {
899 Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
905 SoundFileBrowser::found_list_view_selected ()
907 if (!reset_options ()) {
908 set_action_sensitive (false);
912 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
915 TreeIter iter = found_list->get_iter(*rows.begin());
916 file = (*iter)[found_list_columns.pathname];
917 chooser.set_filename (file);
918 set_action_sensitive (true);
920 set_action_sensitive (false);
923 preview.setup_labels (file);
928 SoundFileBrowser::found_search_clicked ()
930 string tag_string = found_entry.get_text ();
934 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
935 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
939 vector<string> results;
940 Library->search_members_and (results, tags);
943 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
944 TreeModel::iterator new_row = found_list->append();
945 TreeModel::Row row = *new_row;
946 string path = Glib::filename_from_uri (string ("file:") + *i);
947 row[found_list_columns.pathname] = path;
953 SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
956 Mootcher *mootcher = new Mootcher;
959 string id = (*iter)[freesound_list_columns.id];
960 string uri = (*iter)[freesound_list_columns.uri];
961 string ofn = (*iter)[freesound_list_columns.filename];
963 if (mootcher->checkAudioFile(ofn, id)) {
964 // file already exists, no need to download it again
965 file = mootcher->audioFileName;
967 (*iter)[freesound_list_columns.started] = false;
970 if (!(*iter)[freesound_list_columns.started]) {
971 // start downloading the sound file
972 (*iter)[freesound_list_columns.started] = true;
973 mootcher->fetchAudioFile(ofn, id, uri, this);
979 SoundFileBrowser::freesound_list_view_selected ()
982 if (!reset_options ()) {
983 set_action_sensitive (false);
986 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
987 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
988 file = freesound_get_audio_file (freesound_list->get_iter(*i));
991 switch (rows.size()) {
994 freesound_similar_btn.set_sensitive(false);
995 set_action_sensitive (false);
998 // exactly one item selected
1000 // file exists on disk already
1001 chooser.set_filename (file);
1002 preview.setup_labels (file);
1003 set_action_sensitive (true);
1005 freesound_similar_btn.set_sensitive(true);
1008 // multiple items selected
1009 preview.setup_labels ("");
1010 freesound_similar_btn.set_sensitive(false);
1018 SoundFileBrowser::refresh_display(std::string ID, std::string file)
1020 // called when the mootcher has finished downloading a file
1021 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1022 if (rows.size() == 1) {
1023 // there's a single item selected in the freesound list
1024 //XXX make a function to be used to construct the actual file name both here and in the mootcher
1025 Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
1026 std::string selected_ID = (*row)[freesound_list_columns.id];
1027 if (ID == selected_ID) {
1028 // the selected item in the freesound list is the item that has just finished downloading
1029 chooser.set_filename(file);
1030 preview.setup_labels (file);
1031 set_action_sensitive (true);
1037 SoundFileBrowser::freesound_search_clicked ()
1040 freesound_list->clear();
1046 SoundFileBrowser::freesound_more_clicked ()
1051 snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
1052 freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
1056 SoundFileBrowser::freesound_similar_clicked ()
1058 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1059 if (rows.size() == 1) {
1062 Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
1063 id = (*iter)[freesound_list_columns.id];
1064 freesound_list->clear();
1066 GdkCursor *prev_cursor;
1067 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1068 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1071 std::string theString = mootcher.searchSimilar(id);
1073 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1074 handle_freesound_results(theString);
1079 SoundFileBrowser::freesound_search()
1083 string search_string = freesound_entry.get_text ();
1084 enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
1086 GdkCursor *prev_cursor;
1087 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1088 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1091 std::string theString = mootcher.searchText(
1095 "", // OSX eats anything incl mp3
1097 "type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
1102 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1103 handle_freesound_results(theString);
1107 SoundFileBrowser::handle_freesound_results(std::string theString) {
1109 doc.read_buffer( theString );
1110 XMLNode *root = doc.root();
1113 error << "no root XML node!" << endmsg;
1117 if ( strcmp(root->name().c_str(), "response") != 0) {
1118 error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
1122 // find out how many pages are available to search
1123 int freesound_n_pages = 1;
1124 XMLNode *res = root->child("num_pages");
1126 string result = res->child("text")->content();
1127 freesound_n_pages = atoi(result);
1130 int more_pages = freesound_n_pages - freesound_page;
1132 if (more_pages > 0) {
1133 freesound_more_btn.set_sensitive(true);
1134 freesound_more_btn.set_tooltip_text(string_compose(P_(
1135 "%1 more page of 100 results available",
1136 "%1 more pages of 100 results available",
1137 more_pages), more_pages));
1139 freesound_more_btn.set_sensitive(false);
1140 freesound_more_btn.set_tooltip_text(_("No more results available"));
1143 XMLNode *sounds_root = root->child("sounds");
1145 error << "no child node \"sounds\" found!" << endmsg;
1149 XMLNodeList sounds = sounds_root->children();
1150 if (sounds.size() == 0) {
1155 XMLNodeConstIterator niter;
1157 for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
1159 if( strcmp( node->name().c_str(), "resource") != 0 ) {
1160 error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
1164 // node->dump(cerr, "node:");
1167 XMLNode *id_node = node->child ("id");
1168 XMLNode *uri_node = node->child ("serve");
1169 XMLNode *ofn_node = node->child ("original_filename");
1170 XMLNode *dur_node = node->child ("duration");
1171 XMLNode *siz_node = node->child ("filesize");
1172 XMLNode *srt_node = node->child ("samplerate");
1173 XMLNode *lic_node = node->child ("license");
1175 if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
1177 std::string id = id_node->child("text")->content();
1178 std::string uri = uri_node->child("text")->content();
1179 std::string ofn = ofn_node->child("text")->content();
1180 std::string dur = dur_node->child("text")->content();
1181 std::string siz = siz_node->child("text")->content();
1182 std::string srt = srt_node->child("text")->content();
1183 std::string lic = lic_node->child("text")->content();
1186 // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
1188 double duration_seconds = atof(dur);
1190 char duration_hhmmss[16];
1191 if (duration_seconds >= 99 * 60 * 60) {
1192 strcpy(duration_hhmmss, ">99h");
1194 s = modf(duration_seconds/60, &m) * 60;
1195 m = modf(m/60, &h) * 60;
1196 sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
1201 double size_bytes = atof(siz);
1203 if (size_bytes < 1000) {
1204 sprintf(bsize, "%.0f %s", size_bytes, _("B"));
1205 } else if (size_bytes < 1000000 ) {
1206 sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
1207 } else if (size_bytes < 10000000) {
1208 sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
1209 } else if (size_bytes < 1000000000) {
1210 sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
1212 sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
1215 /* see http://www.freesound.org/help/faq/#licenses */
1216 char shortlicense[64];
1217 if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
1218 sprintf(shortlicense, "CC-BY-NC");
1219 } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
1220 sprintf(shortlicense, "CC-BY");
1221 } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
1222 sprintf(shortlicense, "sampling+");
1223 } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
1224 sprintf(shortlicense, "PD");
1226 snprintf(shortlicense, 64, "%s", lic.c_str());
1227 shortlicense[63]= '\0';
1230 TreeModel::iterator new_row = freesound_list->append();
1231 TreeModel::Row row = *new_row;
1233 row[freesound_list_columns.id ] = id;
1234 row[freesound_list_columns.uri ] = uri;
1235 row[freesound_list_columns.filename] = ofn;
1236 row[freesound_list_columns.duration] = duration_hhmmss;
1237 row[freesound_list_columns.filesize] = bsize;
1238 row[freesound_list_columns.smplrate] = srt;
1239 row[freesound_list_columns.license ] = shortlicense;
1246 SoundFileBrowser::get_paths ()
1248 vector<string> results;
1250 int n = notebook.get_current_page ();
1253 vector<string> filenames = chooser.get_filenames();
1254 vector<string>::iterator i;
1256 for (i = filenames.begin(); i != filenames.end(); ++i) {
1258 if ((!g_stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
1259 results.push_back (*i);
1263 } else if (n == 1) {
1265 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1266 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1267 TreeIter iter = found_list->get_iter(*i);
1268 string str = (*iter)[found_list_columns.pathname];
1270 results.push_back (str);
1273 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1274 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1275 string str = freesound_get_audio_file (freesound_list->get_iter(*i));
1277 results.push_back (str);
1286 SoundFileOmega::reset_options_noret ()
1288 if (!resetting_ourselves) {
1289 (void) reset_options ();
1294 SoundFileOmega::reset_options ()
1296 if (_import_active) {
1297 _reset_post_import = true;
1301 vector<string> paths = get_paths ();
1303 if (paths.empty()) {
1305 channel_combo.set_sensitive (false);
1306 action_combo.set_sensitive (false);
1307 where_combo.set_sensitive (false);
1308 copy_files_btn.set_active (true);
1309 copy_files_btn.set_sensitive (false);
1315 channel_combo.set_sensitive (true);
1316 action_combo.set_sensitive (true);
1317 where_combo.set_sensitive (true);
1319 /* if we get through this function successfully, this may be
1320 reset at the end, once we know if we can use hard links
1321 to do embedding (or if we are importing a MIDI file).
1324 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1325 copy_files_btn.set_sensitive (false);
1327 copy_files_btn.set_sensitive (false);
1333 bool selection_includes_multichannel;
1334 bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1337 /* See if we are thinking about importing any MIDI files */
1338 vector<string>::iterator i = paths.begin ();
1339 while (i != paths.end() && SMFSource::valid_midi_file (*i) == false) {
1342 bool const have_a_midi_file = (i != paths.end ());
1344 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1345 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1349 string existing_choice;
1350 vector<string> action_strings;
1352 resetting_ourselves = true;
1354 if (chooser.get_filter() == &audio_filter) {
1358 if (selected_audio_track_cnt > 0) {
1359 if (channel_combo.get_active_text().length()) {
1360 ImportDisposition id = get_channel_disposition();
1363 case Editing::ImportDistinctFiles:
1364 if (selected_audio_track_cnt == paths.size()) {
1365 action_strings.push_back (importmode2string (ImportToTrack));
1369 case Editing::ImportDistinctChannels:
1370 /* XXX it would be nice to allow channel-per-selected track
1371 but its too hard we don't want to deal with all the
1372 different per-file + per-track channel configurations.
1377 action_strings.push_back (importmode2string (ImportToTrack));
1387 if (selected_midi_track_cnt > 0) {
1388 action_strings.push_back (importmode2string (ImportToTrack));
1392 action_strings.push_back (importmode2string (ImportAsTrack));
1393 action_strings.push_back (importmode2string (ImportAsRegion));
1394 action_strings.push_back (importmode2string (ImportAsTapeTrack));
1396 existing_choice = action_combo.get_active_text();
1398 set_popdown_strings (action_combo, action_strings);
1400 /* preserve any existing choice, if possible */
1403 if (existing_choice.length()) {
1404 vector<string>::iterator x;
1405 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1406 if (*x == existing_choice) {
1407 action_combo.set_active_text (existing_choice);
1411 if (x == action_strings.end()) {
1412 action_combo.set_active_text (action_strings.front());
1415 action_combo.set_active_text (action_strings.front());
1418 resetting_ourselves = false;
1420 if ((mode = get_mode()) == ImportAsRegion) {
1421 where_combo.set_sensitive (false);
1423 where_combo.set_sensitive (true);
1426 vector<string> channel_strings;
1428 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1429 channel_strings.push_back (_("one track per file"));
1431 if (selection_includes_multichannel) {
1432 channel_strings.push_back (_("one track per channel"));
1435 if (paths.size() > 1) {
1436 /* tape tracks are a single region per track, so we cannot
1437 sequence multiple files.
1439 if (mode != ImportAsTapeTrack) {
1440 channel_strings.push_back (_("sequence files"));
1443 channel_strings.push_back (_("all files in one track"));
1444 channel_strings.push_back (_("merge files"));
1450 channel_strings.push_back (_("one region per file"));
1452 if (selection_includes_multichannel) {
1453 channel_strings.push_back (_("one region per channel"));
1456 if (paths.size() > 1) {
1458 channel_strings.push_back (_("all files in one region"));
1463 resetting_ourselves = true;
1465 existing_choice = channel_combo.get_active_text();
1467 set_popdown_strings (channel_combo, channel_strings);
1469 /* preserve any existing choice, if possible */
1471 if (existing_choice.length()) {
1472 vector<string>::iterator x;
1473 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1474 if (*x == existing_choice) {
1475 channel_combo.set_active_text (existing_choice);
1479 if (x == channel_strings.end()) {
1480 channel_combo.set_active_text (channel_strings.front());
1483 channel_combo.set_active_text (channel_strings.front());
1486 resetting_ourselves = false;
1489 src_combo.set_sensitive (true);
1491 src_combo.set_sensitive (false);
1494 /* We must copy MIDI files or those from Freesound
1495 * or any file if we are under nsm control */
1496 bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
1498 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1500 if (selection_can_be_embedded_with_links && !must_copy) {
1501 copy_files_btn.set_sensitive (true);
1504 copy_files_btn.set_active (true);
1506 copy_files_btn.set_sensitive (false);
1512 copy_files_btn.set_active (true);
1514 copy_files_btn.set_sensitive (!must_copy);
1522 SoundFileOmega::bad_file_message()
1524 MessageDialog msg (*this,
1525 string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1530 resetting_ourselves = true;
1531 chooser.unselect_uri (chooser.get_preview_uri());
1532 resetting_ourselves = false;
1538 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1547 multichannel = false;
1549 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1551 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1552 if (info.channels > 1) {
1553 multichannel = true;
1558 if (sz != info.length) {
1563 if (info.samplerate != _session->frame_rate()) {
1567 } else if (SMFSource::valid_midi_file (*i)) {
1571 if (reader.num_tracks() > 1) {
1572 multichannel = true; // "channel" == track here...
1575 /* XXX we need err = true handling here in case
1576 we can't check the file
1589 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1591 #ifdef PLATFORM_WINDOWS
1594 std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
1597 if (g_mkdir (tmpdir.c_str(), 0744)) {
1598 if (errno != EEXIST) {
1603 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1605 char tmpc[PATH_MAX+1];
1607 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1611 if (link ((*i).c_str(), tmpc)) {
1621 g_rmdir (tmpdir.c_str());
1626 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
1627 : SoundFileBrowser (title, s, false)
1629 chooser.set_select_multiple (false);
1630 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1631 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1635 SoundFileChooser::on_hide ()
1637 ArdourWindow::on_hide();
1641 _session->cancel_audition();
1646 SoundFileChooser::get_filename ()
1648 vector<string> paths;
1650 paths = get_paths ();
1652 if (paths.empty()) {
1656 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1660 return paths.front();
1663 SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s,
1664 uint32_t selected_audio_tracks,
1665 uint32_t selected_midi_tracks,
1667 Editing::ImportMode mode_hint)
1668 : SoundFileBrowser (title, s, persistent)
1669 , copy_files_btn ( _("Copy files to session"))
1670 , selected_audio_track_cnt (selected_audio_tracks)
1671 , selected_midi_track_cnt (selected_midi_tracks)
1672 , _import_active (false)
1673 , _reset_post_import (false)
1679 set_size_request (-1, 450);
1681 block_two.set_border_width (12);
1682 block_three.set_border_width (12);
1683 block_four.set_border_width (12);
1685 options.set_spacing (12);
1688 str.push_back (_("file timestamp"));
1689 str.push_back (_("edit point"));
1690 str.push_back (_("playhead"));
1691 str.push_back (_("session start"));
1692 set_popdown_strings (where_combo, str);
1693 where_combo.set_active_text (str.front());
1694 where_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::where_combo_changed));
1696 Label* l = manage (new Label);
1697 l->set_markup (_("<b>Add files ...</b>"));
1699 vbox = manage (new VBox);
1700 vbox->set_border_width (12);
1701 vbox->set_spacing (6);
1702 vbox->pack_start (*l, false, false);
1703 vbox->pack_start (action_combo, false, false);
1704 hbox = manage (new HBox);
1705 hbox->pack_start (*vbox, false, false);
1706 options.pack_start (*hbox, false, false);
1708 l = manage (new Label);
1709 l->set_markup (_("<b>Insert at</b>"));
1711 vbox = manage (new VBox);
1712 vbox->set_border_width (12);
1713 vbox->set_spacing (6);
1714 vbox->pack_start (*l, false, false);
1715 vbox->pack_start (where_combo, false, false);
1716 hbox = manage (new HBox);
1717 hbox->pack_start (*vbox, false, false);
1718 options.pack_start (*hbox, false, false);
1721 l = manage (new Label);
1722 l->set_markup (_("<b>Mapping</b>"));
1724 vbox = manage (new VBox);
1725 vbox->set_border_width (12);
1726 vbox->set_spacing (6);
1727 vbox->pack_start (*l, false, false);
1728 vbox->pack_start (channel_combo, false, false);
1729 hbox = manage (new HBox);
1730 hbox->pack_start (*vbox, false, false);
1731 options.pack_start (*hbox, false, false);
1734 str.push_back (_("one track per file"));
1735 set_popdown_strings (channel_combo, str);
1736 channel_combo.set_active_text (str.front());
1737 channel_combo.set_sensitive (false);
1739 l = manage (new Label);
1740 l->set_markup (_("<b>Conversion quality</b>"));
1742 vbox = manage (new VBox);
1743 vbox->set_border_width (12);
1744 vbox->set_spacing (6);
1745 vbox->pack_start (*l, false, false);
1746 vbox->pack_start (src_combo, false, false);
1747 hbox = manage (new HBox);
1748 hbox->pack_start (*vbox, false, false);
1749 options.pack_start (*hbox, false, false);
1751 l = manage (new Label);
1752 l->set_markup (_("<b>Instrument</b>"));
1754 vbox = manage (new VBox);
1755 vbox->set_border_width (12);
1756 vbox->set_spacing (6);
1757 vbox->pack_start (*l, false, false);
1758 vbox->pack_start (instrument_combo, false, false);
1759 hbox = manage (new HBox);
1760 hbox->pack_start (*vbox, false, false);
1761 options.pack_start (*hbox, false, false);
1764 str.push_back (_("Best"));
1765 str.push_back (_("Good"));
1766 str.push_back (_("Quick"));
1767 str.push_back (_("Fast"));
1768 str.push_back (_("Fastest"));
1770 set_popdown_strings (src_combo, str);
1771 src_combo.set_active_text (str.front());
1772 src_combo.set_sensitive (false);
1773 src_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::src_combo_changed));
1775 action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1776 channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1778 copy_files_btn.set_active (true);
1780 Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1783 copy_label->set_size_request (175, -1);
1784 copy_label->set_line_wrap (true);
1787 block_four.pack_start (copy_files_btn, false, false);
1789 options.pack_start (block_four, false, false);
1791 vpacker.pack_start (options, false, false);
1793 /* setup disposition map */
1795 disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1796 disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1797 disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1798 disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1800 disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1801 disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1802 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1803 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1805 chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1807 /* set size requests for a couple of combos to allow them to display the longest text
1808 they will ever be asked to display. This prevents them being resized when the user
1809 selects a file to import, which in turn prevents the size of the dialog from jumping
1813 str.push_back (_("one track per file"));
1814 str.push_back (_("one track per channel"));
1815 str.push_back (_("sequence files"));
1816 str.push_back (_("all files in one region"));
1817 set_popdown_strings (channel_combo, str);
1820 str.push_back (importmode2string (ImportAsTrack));
1821 str.push_back (importmode2string (ImportToTrack));
1822 str.push_back (importmode2string (ImportAsRegion));
1823 str.push_back (importmode2string (ImportAsTapeTrack));
1824 set_popdown_strings (action_combo, str);
1825 action_combo.set_active_text (importmode2string(mode_hint));
1827 reset (selected_audio_tracks, selected_midi_tracks);
1831 SoundFileOmega::set_mode (ImportMode mode)
1833 action_combo.set_active_text (importmode2string (mode));
1837 SoundFileOmega::get_mode () const
1839 return string2importmode (action_combo.get_active_text());
1843 SoundFileOmega::on_hide ()
1845 ArdourWindow::on_hide();
1847 _session->cancel_audition();
1852 SoundFileOmega::get_position() const
1854 string str = where_combo.get_active_text();
1856 if (str == _("file timestamp")) {
1857 return ImportAtTimestamp;
1858 } else if (str == _("edit point")) {
1859 return ImportAtEditPoint;
1860 } else if (str == _("playhead")) {
1861 return ImportAtPlayhead;
1863 return ImportAtStart;
1868 SoundFileOmega::get_src_quality() const
1870 string str = src_combo.get_active_text();
1872 if (str == _("Best")) {
1874 } else if (str == _("Good")) {
1876 } else if (str == _("Quick")) {
1878 } else if (str == _("Fast")) {
1886 SoundFileOmega::src_combo_changed()
1888 preview.set_src_quality(get_src_quality());
1892 SoundFileOmega::where_combo_changed()
1894 preview.set_import_position(get_position());
1898 SoundFileOmega::get_channel_disposition () const
1900 /* we use a map here because the channel combo can contain different strings
1901 depending on the state of the other combos. the map contains all possible strings
1902 and the ImportDisposition enum that corresponds to it.
1905 string str = channel_combo.get_active_text();
1906 DispositionMap::const_iterator x = disposition_map.find (str);
1908 if (x == disposition_map.end()) {
1909 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1910 abort(); /*NOTREACHED*/
1917 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
1919 selected_audio_track_cnt = selected_audio_tracks;
1920 selected_midi_track_cnt = selected_midi_tracks;
1922 if (selected_audio_track_cnt == 0 && selected_midi_track_cnt > 0) {
1923 chooser.set_filter (midi_filter);
1924 } else if (selected_midi_track_cnt == 0 && selected_audio_track_cnt > 0) {
1925 chooser.set_filter (audio_filter);
1927 chooser.set_filter (audio_and_midi_filter);
1934 SoundFileOmega::file_selection_changed ()
1936 if (resetting_ourselves) {
1940 if (!reset_options ()) {
1941 set_action_sensitive (false);
1943 if (chooser.get_filenames().size() > 0) {
1944 set_action_sensitive (true);
1946 set_action_sensitive (false);
1952 SoundFileOmega::do_something (int action)
1954 SoundFileBrowser::do_something (action);
1956 if (action == RESPONSE_CLOSE) {
1963 vector<string> paths = get_paths ();
1964 ImportPosition pos = get_position ();
1965 ImportMode mode = get_mode ();
1966 ImportDisposition chns = get_channel_disposition ();
1967 PluginInfoPtr instrument = instrument_combo.selected_instrument();
1971 case ImportAtEditPoint:
1972 where = PublicEditor::instance().get_preferred_edit_position ();
1974 case ImportAtTimestamp:
1977 case ImportAtPlayhead:
1978 where = _session->transport_frame();
1981 where = _session->current_start_frame();
1985 SrcQuality quality = get_src_quality();
1987 _import_active = true;
1989 if (copy_files_btn.get_active()) {
1990 PublicEditor::instance().do_import (paths, chns, mode, quality, where, instrument);
1992 PublicEditor::instance().do_embed (paths, chns, mode, where, instrument);
1995 _import_active = false;
1997 if (_reset_post_import) {
1998 _reset_post_import = false;