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
650 #ifdef FREESOUND_GOT_FIXED
655 passbox = manage(new HBox);
656 passbox->set_spacing (6);
658 label = manage (new Label);
659 label->set_text (_("Tags:"));
660 passbox->pack_start (*label, false, false);
661 passbox->pack_start (freesound_entry, true, true);
663 label = manage (new Label);
664 label->set_text (_("Sort:"));
665 passbox->pack_start (*label, false, false);
666 passbox->pack_start (freesound_sort, false, false);
667 freesound_sort.clear_items();
669 // Order of the following must correspond with enum sortMethod
670 // in sfdb_freesound_mootcher.h
671 freesound_sort.append_text(_("None"));
672 freesound_sort.append_text(_("Longest"));
673 freesound_sort.append_text(_("Shortest"));
674 freesound_sort.append_text(_("Newest"));
675 freesound_sort.append_text(_("Oldest"));
676 freesound_sort.append_text(_("Most downloaded"));
677 freesound_sort.append_text(_("Least downloaded"));
678 freesound_sort.append_text(_("Highest rated"));
679 freesound_sort.append_text(_("Lowest rated"));
680 freesound_sort.set_active(0);
682 passbox->pack_start (freesound_search_btn, false, false);
683 passbox->pack_start (freesound_more_btn, false, false);
684 freesound_more_btn.set_label(_("More"));
685 freesound_more_btn.set_sensitive(false);
687 passbox->pack_start (freesound_similar_btn, false, false);
688 freesound_similar_btn.set_label(_("Similar"));
689 freesound_similar_btn.set_sensitive(false);
691 scroll = manage(new ScrolledWindow);
692 scroll->add(freesound_list_view);
693 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
695 vbox = manage(new VBox);
696 vbox->set_spacing (3);
697 vbox->pack_start (*passbox, PACK_SHRINK);
698 vbox->pack_start (*scroll);
700 freesound_list_view.append_column(_("ID") , freesound_list_columns.id);
701 freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
702 // freesound_list_view.append_column(_("URI") , freesound_list_columns.uri);
703 freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
704 freesound_list_view.append_column(_("Size"), freesound_list_columns.filesize);
705 freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
706 freesound_list_view.append_column(_("License"), freesound_list_columns.license);
707 freesound_list_view.get_column(0)->set_alignment(0.5);
708 freesound_list_view.get_column(1)->set_expand(true); // filename
709 freesound_list_view.get_column(1)->set_resizable(true); // filename
710 freesound_list_view.get_column(2)->set_alignment(0.5);
711 freesound_list_view.get_column(3)->set_alignment(0.5);
712 freesound_list_view.get_column(4)->set_alignment(0.5);
713 freesound_list_view.get_column(5)->set_alignment(0.5);
715 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
716 freesound_list_view.set_tooltip_column(1);
718 freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
719 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
720 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
721 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
722 freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
723 freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
724 notebook.append_page (*vbox, _("Search Freesound"));
727 notebook.set_size_request (500, -1);
728 notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
732 Gtk::HButtonBox* button_box = manage (new HButtonBox);
734 button_box->set_layout (BUTTONBOX_END);
735 button_box->pack_start (close_button, false, false);
736 close_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_CLOSE));
738 button_box->pack_start (import_button, false, false);
739 import_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_OK));
741 Gtkmm2ext::UI::instance()->set_tip (import_button, _("Press to import selected files"));
742 Gtkmm2ext::UI::instance()->set_tip (close_button, _("Press to close this window without importing any files"));
744 vpacker.pack_end (*button_box, false, false);
746 set_wmclass (X_("import"), PROGRAM_NAME);
749 SoundFileBrowser::~SoundFileBrowser ()
751 persistent_folder = chooser.get_current_folder();
755 SoundFileBrowser::run ()
764 gtk_main_iteration ();
771 SoundFileBrowser::set_action_sensitive (bool yn)
773 import_button.set_sensitive (yn);
777 SoundFileBrowser::do_something (int action)
784 SoundFileBrowser::on_show ()
786 ArdourWindow::on_show ();
791 SoundFileBrowser::clear_selection ()
793 chooser.unselect_all ();
794 found_list_view.get_selection()->unselect_all ();
798 SoundFileBrowser::chooser_file_activated ()
804 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
810 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
816 SoundFileBrowser::set_session (Session* s)
818 ArdourWindow::set_session (s);
819 preview.set_session (s);
824 remove_gain_meter ();
829 SoundFileBrowser::add_gain_meter ()
833 gm = new GainMeter (_session, 250);
835 boost::shared_ptr<Route> r = _session->the_auditioner ();
837 gm->set_controls (r, r->shared_peak_meter(), r->amp(), r->gain_control());
838 gm->set_fader_name (X_("GainFader"));
840 meter_packer.set_border_width (12);
841 meter_packer.pack_start (*gm, false, true);
842 hpacker.pack_end (meter_packer, false, false);
843 meter_packer.show_all ();
848 SoundFileBrowser::remove_gain_meter ()
851 meter_packer.remove (*gm);
852 hpacker.remove (meter_packer);
859 SoundFileBrowser::start_metering ()
861 metering_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
865 SoundFileBrowser::stop_metering ()
867 metering_connection.disconnect();
871 SoundFileBrowser::meter ()
873 if (is_mapped () && _session && gm) {
874 gm->update_meters ();
879 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
881 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
885 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
887 return SMFSource::safe_midi_file_extension (filter_info.filename);
891 SoundFileBrowser::on_audio_and_midi_filter (const FileFilter::Info& filter_info)
893 return on_audio_filter (filter_info) || on_midi_filter (filter_info);
897 SoundFileBrowser::update_preview ()
899 if (preview.setup_labels (chooser.get_preview_filename())) {
900 if (preview.autoplay()) {
901 Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
907 SoundFileBrowser::found_list_view_selected ()
909 if (!reset_options ()) {
910 set_action_sensitive (false);
914 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
917 TreeIter iter = found_list->get_iter(*rows.begin());
918 file = (*iter)[found_list_columns.pathname];
919 chooser.set_filename (file);
920 set_action_sensitive (true);
922 set_action_sensitive (false);
925 preview.setup_labels (file);
930 SoundFileBrowser::found_search_clicked ()
932 string tag_string = found_entry.get_text ();
936 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
937 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
941 vector<string> results;
942 Library->search_members_and (results, tags);
945 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
946 TreeModel::iterator new_row = found_list->append();
947 TreeModel::Row row = *new_row;
948 string path = Glib::filename_from_uri (string ("file:") + *i);
949 row[found_list_columns.pathname] = path;
955 SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
958 Mootcher *mootcher = new Mootcher;
961 string id = (*iter)[freesound_list_columns.id];
962 string uri = (*iter)[freesound_list_columns.uri];
963 string ofn = (*iter)[freesound_list_columns.filename];
965 if (mootcher->checkAudioFile(ofn, id)) {
966 // file already exists, no need to download it again
967 file = mootcher->audioFileName;
969 (*iter)[freesound_list_columns.started] = false;
972 if (!(*iter)[freesound_list_columns.started]) {
973 // start downloading the sound file
974 (*iter)[freesound_list_columns.started] = true;
975 mootcher->fetchAudioFile(ofn, id, uri, this);
981 SoundFileBrowser::freesound_list_view_selected ()
984 if (!reset_options ()) {
985 set_action_sensitive (false);
988 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
989 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
990 file = freesound_get_audio_file (freesound_list->get_iter(*i));
993 switch (rows.size()) {
996 freesound_similar_btn.set_sensitive(false);
997 set_action_sensitive (false);
1000 // exactly one item selected
1002 // file exists on disk already
1003 chooser.set_filename (file);
1004 preview.setup_labels (file);
1005 set_action_sensitive (true);
1007 freesound_similar_btn.set_sensitive(true);
1010 // multiple items selected
1011 preview.setup_labels ("");
1012 freesound_similar_btn.set_sensitive(false);
1020 SoundFileBrowser::refresh_display(std::string ID, std::string file)
1022 // called when the mootcher has finished downloading a file
1023 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1024 if (rows.size() == 1) {
1025 // there's a single item selected in the freesound list
1026 //XXX make a function to be used to construct the actual file name both here and in the mootcher
1027 Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
1028 std::string selected_ID = (*row)[freesound_list_columns.id];
1029 if (ID == selected_ID) {
1030 // the selected item in the freesound list is the item that has just finished downloading
1031 chooser.set_filename(file);
1032 preview.setup_labels (file);
1033 set_action_sensitive (true);
1039 SoundFileBrowser::freesound_search_clicked ()
1042 freesound_list->clear();
1048 SoundFileBrowser::freesound_more_clicked ()
1053 snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
1054 freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
1058 SoundFileBrowser::freesound_similar_clicked ()
1060 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1061 if (rows.size() == 1) {
1064 Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
1065 id = (*iter)[freesound_list_columns.id];
1066 freesound_list->clear();
1068 GdkCursor *prev_cursor;
1069 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1070 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1073 std::string theString = mootcher.searchSimilar(id);
1075 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1076 handle_freesound_results(theString);
1081 SoundFileBrowser::freesound_search()
1085 string search_string = freesound_entry.get_text ();
1086 enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
1088 GdkCursor *prev_cursor;
1089 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1090 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1093 std::string theString = mootcher.searchText(
1097 "", // OSX eats anything incl mp3
1099 "type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
1104 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1105 handle_freesound_results(theString);
1109 SoundFileBrowser::handle_freesound_results(std::string theString) {
1111 doc.read_buffer( theString );
1112 XMLNode *root = doc.root();
1115 error << "no root XML node!" << endmsg;
1119 if ( strcmp(root->name().c_str(), "response") != 0) {
1120 error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
1124 // find out how many pages are available to search
1125 int freesound_n_pages = 1;
1126 XMLNode *res = root->child("num_pages");
1128 string result = res->child("text")->content();
1129 freesound_n_pages = atoi(result);
1132 int more_pages = freesound_n_pages - freesound_page;
1134 if (more_pages > 0) {
1135 freesound_more_btn.set_sensitive(true);
1136 freesound_more_btn.set_tooltip_text(string_compose(P_(
1137 "%1 more page of 100 results available",
1138 "%1 more pages of 100 results available",
1139 more_pages), more_pages));
1141 freesound_more_btn.set_sensitive(false);
1142 freesound_more_btn.set_tooltip_text(_("No more results available"));
1145 XMLNode *sounds_root = root->child("sounds");
1147 error << "no child node \"sounds\" found!" << endmsg;
1151 XMLNodeList sounds = sounds_root->children();
1152 if (sounds.size() == 0) {
1157 XMLNodeConstIterator niter;
1159 for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
1161 if( strcmp( node->name().c_str(), "resource") != 0 ) {
1162 error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
1166 // node->dump(cerr, "node:");
1169 XMLNode *id_node = node->child ("id");
1170 XMLNode *uri_node = node->child ("serve");
1171 XMLNode *ofn_node = node->child ("original_filename");
1172 XMLNode *dur_node = node->child ("duration");
1173 XMLNode *siz_node = node->child ("filesize");
1174 XMLNode *srt_node = node->child ("samplerate");
1175 XMLNode *lic_node = node->child ("license");
1177 if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
1179 std::string id = id_node->child("text")->content();
1180 std::string uri = uri_node->child("text")->content();
1181 std::string ofn = ofn_node->child("text")->content();
1182 std::string dur = dur_node->child("text")->content();
1183 std::string siz = siz_node->child("text")->content();
1184 std::string srt = srt_node->child("text")->content();
1185 std::string lic = lic_node->child("text")->content();
1188 // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
1190 double duration_seconds = atof(dur);
1192 char duration_hhmmss[16];
1193 if (duration_seconds >= 99 * 60 * 60) {
1194 strcpy(duration_hhmmss, ">99h");
1196 s = modf(duration_seconds/60, &m) * 60;
1197 m = modf(m/60, &h) * 60;
1198 sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
1203 double size_bytes = atof(siz);
1205 if (size_bytes < 1000) {
1206 sprintf(bsize, "%.0f %s", size_bytes, _("B"));
1207 } else if (size_bytes < 1000000 ) {
1208 sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
1209 } else if (size_bytes < 10000000) {
1210 sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
1211 } else if (size_bytes < 1000000000) {
1212 sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
1214 sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
1217 /* see http://www.freesound.org/help/faq/#licenses */
1218 char shortlicense[64];
1219 if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
1220 sprintf(shortlicense, "CC-BY-NC");
1221 } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
1222 sprintf(shortlicense, "CC-BY");
1223 } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
1224 sprintf(shortlicense, "sampling+");
1225 } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
1226 sprintf(shortlicense, "PD");
1228 snprintf(shortlicense, 64, "%s", lic.c_str());
1229 shortlicense[63]= '\0';
1232 TreeModel::iterator new_row = freesound_list->append();
1233 TreeModel::Row row = *new_row;
1235 row[freesound_list_columns.id ] = id;
1236 row[freesound_list_columns.uri ] = uri;
1237 row[freesound_list_columns.filename] = ofn;
1238 row[freesound_list_columns.duration] = duration_hhmmss;
1239 row[freesound_list_columns.filesize] = bsize;
1240 row[freesound_list_columns.smplrate] = srt;
1241 row[freesound_list_columns.license ] = shortlicense;
1248 SoundFileBrowser::get_paths ()
1250 vector<string> results;
1252 int n = notebook.get_current_page ();
1255 vector<string> filenames = chooser.get_filenames();
1256 vector<string>::iterator i;
1258 for (i = filenames.begin(); i != filenames.end(); ++i) {
1260 if ((!g_stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
1261 results.push_back (*i);
1265 } else if (n == 1) {
1267 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1268 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1269 TreeIter iter = found_list->get_iter(*i);
1270 string str = (*iter)[found_list_columns.pathname];
1272 results.push_back (str);
1275 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1276 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1277 string str = freesound_get_audio_file (freesound_list->get_iter(*i));
1279 results.push_back (str);
1288 SoundFileOmega::reset_options_noret ()
1290 if (!resetting_ourselves) {
1291 (void) reset_options ();
1296 SoundFileOmega::reset_options ()
1298 if (_import_active) {
1299 _reset_post_import = true;
1303 vector<string> paths = get_paths ();
1305 if (paths.empty()) {
1307 channel_combo.set_sensitive (false);
1308 action_combo.set_sensitive (false);
1309 where_combo.set_sensitive (false);
1310 copy_files_btn.set_active (true);
1311 copy_files_btn.set_sensitive (false);
1317 channel_combo.set_sensitive (true);
1318 action_combo.set_sensitive (true);
1319 where_combo.set_sensitive (true);
1321 /* if we get through this function successfully, this may be
1322 reset at the end, once we know if we can use hard links
1323 to do embedding (or if we are importing a MIDI file).
1326 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1327 copy_files_btn.set_sensitive (false);
1329 copy_files_btn.set_sensitive (false);
1335 bool selection_includes_multichannel;
1336 bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1339 /* See if we are thinking about importing any MIDI files */
1340 vector<string>::iterator i = paths.begin ();
1341 while (i != paths.end() && SMFSource::valid_midi_file (*i) == false) {
1344 bool const have_a_midi_file = (i != paths.end ());
1346 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1347 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1351 string existing_choice;
1352 vector<string> action_strings;
1354 resetting_ourselves = true;
1356 if (chooser.get_filter() == &audio_filter) {
1360 if (selected_audio_track_cnt > 0) {
1361 if (channel_combo.get_active_text().length()) {
1362 ImportDisposition id = get_channel_disposition();
1365 case Editing::ImportDistinctFiles:
1366 if (selected_audio_track_cnt == paths.size()) {
1367 action_strings.push_back (importmode2string (ImportToTrack));
1371 case Editing::ImportDistinctChannels:
1372 /* XXX it would be nice to allow channel-per-selected track
1373 but its too hard we don't want to deal with all the
1374 different per-file + per-track channel configurations.
1379 action_strings.push_back (importmode2string (ImportToTrack));
1389 if (selected_midi_track_cnt > 0) {
1390 action_strings.push_back (importmode2string (ImportToTrack));
1394 action_strings.push_back (importmode2string (ImportAsTrack));
1395 action_strings.push_back (importmode2string (ImportAsRegion));
1396 action_strings.push_back (importmode2string (ImportAsTapeTrack));
1398 existing_choice = action_combo.get_active_text();
1400 set_popdown_strings (action_combo, action_strings);
1402 /* preserve any existing choice, if possible */
1405 if (existing_choice.length()) {
1406 vector<string>::iterator x;
1407 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1408 if (*x == existing_choice) {
1409 action_combo.set_active_text (existing_choice);
1413 if (x == action_strings.end()) {
1414 action_combo.set_active_text (action_strings.front());
1417 action_combo.set_active_text (action_strings.front());
1420 resetting_ourselves = false;
1422 if ((mode = get_mode()) == ImportAsRegion) {
1423 where_combo.set_sensitive (false);
1425 where_combo.set_sensitive (true);
1428 vector<string> channel_strings;
1430 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1431 channel_strings.push_back (_("one track per file"));
1433 if (selection_includes_multichannel) {
1434 channel_strings.push_back (_("one track per channel"));
1437 if (paths.size() > 1) {
1438 /* tape tracks are a single region per track, so we cannot
1439 sequence multiple files.
1441 if (mode != ImportAsTapeTrack) {
1442 channel_strings.push_back (_("sequence files"));
1445 channel_strings.push_back (_("all files in one track"));
1446 channel_strings.push_back (_("merge files"));
1452 channel_strings.push_back (_("one region per file"));
1454 if (selection_includes_multichannel) {
1455 channel_strings.push_back (_("one region per channel"));
1458 if (paths.size() > 1) {
1460 channel_strings.push_back (_("all files in one region"));
1465 resetting_ourselves = true;
1467 existing_choice = channel_combo.get_active_text();
1469 set_popdown_strings (channel_combo, channel_strings);
1471 /* preserve any existing choice, if possible */
1473 if (existing_choice.length()) {
1474 vector<string>::iterator x;
1475 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1476 if (*x == existing_choice) {
1477 channel_combo.set_active_text (existing_choice);
1481 if (x == channel_strings.end()) {
1482 channel_combo.set_active_text (channel_strings.front());
1485 channel_combo.set_active_text (channel_strings.front());
1488 resetting_ourselves = false;
1491 src_combo.set_sensitive (true);
1493 src_combo.set_sensitive (false);
1496 /* We must copy MIDI files or those from Freesound
1497 * or any file if we are under nsm control */
1498 bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
1500 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1502 if (selection_can_be_embedded_with_links && !must_copy) {
1503 copy_files_btn.set_sensitive (true);
1506 copy_files_btn.set_active (true);
1508 copy_files_btn.set_sensitive (false);
1514 copy_files_btn.set_active (true);
1516 copy_files_btn.set_sensitive (!must_copy);
1524 SoundFileOmega::bad_file_message()
1526 MessageDialog msg (*this,
1527 string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1532 resetting_ourselves = true;
1533 chooser.unselect_uri (chooser.get_preview_uri());
1534 resetting_ourselves = false;
1540 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1549 multichannel = false;
1551 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1553 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1554 if (info.channels > 1) {
1555 multichannel = true;
1560 if (sz != info.length) {
1565 if (info.samplerate != _session->frame_rate()) {
1569 } else if (SMFSource::valid_midi_file (*i)) {
1573 if (reader.num_tracks() > 1) {
1574 multichannel = true; // "channel" == track here...
1577 /* XXX we need err = true handling here in case
1578 we can't check the file
1591 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1593 #ifdef PLATFORM_WINDOWS
1596 std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
1599 if (g_mkdir (tmpdir.c_str(), 0744)) {
1600 if (errno != EEXIST) {
1605 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1607 char tmpc[PATH_MAX+1];
1609 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1613 if (link ((*i).c_str(), tmpc)) {
1623 g_rmdir (tmpdir.c_str());
1628 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
1629 : SoundFileBrowser (title, s, false)
1631 chooser.set_select_multiple (false);
1632 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1633 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1637 SoundFileChooser::on_hide ()
1639 ArdourWindow::on_hide();
1643 _session->cancel_audition();
1648 SoundFileChooser::get_filename ()
1650 vector<string> paths;
1652 paths = get_paths ();
1654 if (paths.empty()) {
1658 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1662 return paths.front();
1665 SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s,
1666 uint32_t selected_audio_tracks,
1667 uint32_t selected_midi_tracks,
1669 Editing::ImportMode mode_hint)
1670 : SoundFileBrowser (title, s, persistent)
1671 , copy_files_btn ( _("Copy files to session"))
1672 , selected_audio_track_cnt (selected_audio_tracks)
1673 , selected_midi_track_cnt (selected_midi_tracks)
1674 , _import_active (false)
1675 , _reset_post_import (false)
1679 set_size_request (-1, 550);
1681 block_two.set_border_width (12);
1682 block_three.set_border_width (12);
1683 block_four.set_border_width (12);
1686 str.push_back (_("file timestamp"));
1687 str.push_back (_("edit point"));
1688 str.push_back (_("playhead"));
1689 str.push_back (_("session start"));
1690 set_popdown_strings (where_combo, str);
1691 where_combo.set_active_text (str.back());
1692 where_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::where_combo_changed));
1694 Label* l = manage (new Label);
1695 l->set_markup (_("<b>Add files ...</b>"));
1696 options.attach (*l, 0, 1, 0, 1, FILL, SHRINK, 8, 0);
1697 options.attach (action_combo, 0, 1, 1, 2, FILL, SHRINK, 8, 0);
1699 l = manage (new Label);
1700 l->set_markup (_("<b>Insert at</b>"));
1701 options.attach (*l, 0, 1, 3, 4, FILL, SHRINK, 8, 0);
1702 options.attach (where_combo, 0, 1, 4, 5, FILL, SHRINK, 8, 0);
1704 l = manage (new Label);
1705 l->set_markup (_("<b>Mapping</b>"));
1706 options.attach (*l, 1, 2, 0, 1, FILL, SHRINK, 8, 0);
1707 options.attach (channel_combo, 1, 2, 1, 2, FILL, SHRINK, 8, 0);
1709 l = manage (new Label);
1710 l->set_markup (_("<b>Conversion quality</b>"));
1711 options.attach (*l, 1, 2, 3, 4, FILL, SHRINK, 8, 0);
1712 options.attach (src_combo, 1, 2, 4, 5, FILL, SHRINK, 8, 0);
1714 l = manage (new Label);
1715 l->set_markup (_("<b>Instrument</b>"));
1716 options.attach (*l, 3, 4, 0, 1, FILL, SHRINK, 8, 0);
1717 options.attach (instrument_combo, 3, 4, 1, 2, FILL, SHRINK, 8, 0);
1719 Alignment *hspace = manage (new Alignment ());
1720 hspace->set_size_request (2, 2);
1721 options.attach (*hspace, 0, 3, 2, 3, FILL, SHRINK, 0, 8);
1723 Alignment *vspace = manage (new Alignment ());
1724 vspace->set_size_request (2, 2);
1725 options.attach (*vspace, 2, 3, 0, 3, EXPAND, SHRINK, 0, 0);
1728 str.push_back (_("one track per file"));
1729 set_popdown_strings (channel_combo, str);
1730 channel_combo.set_active_text (str.front());
1731 channel_combo.set_sensitive (false);
1734 str.push_back (_("Best"));
1735 str.push_back (_("Good"));
1736 str.push_back (_("Quick"));
1737 str.push_back (_("Fast"));
1738 str.push_back (_("Fastest"));
1740 set_popdown_strings (src_combo, str);
1741 src_combo.set_active_text (str.front());
1742 src_combo.set_sensitive (false);
1743 src_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::src_combo_changed));
1745 action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1746 channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1748 copy_files_btn.set_active (true);
1750 Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1753 copy_label->set_size_request (175, -1);
1754 copy_label->set_line_wrap (true);
1757 block_four.pack_start (copy_files_btn, false, false);
1758 options.attach (block_four, 3, 4, 4, 5, FILL, SHRINK, 8, 0);
1760 vpacker.pack_start (options, false, true);
1762 /* setup disposition map */
1764 disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1765 disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1766 disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1767 disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1769 disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1770 disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1771 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1772 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1774 chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1776 /* set size requests for a couple of combos to allow them to display the longest text
1777 they will ever be asked to display. This prevents them being resized when the user
1778 selects a file to import, which in turn prevents the size of the dialog from jumping
1782 str.push_back (_("one track per file"));
1783 str.push_back (_("one track per channel"));
1784 str.push_back (_("sequence files"));
1785 str.push_back (_("all files in one region"));
1786 set_popdown_strings (channel_combo, str);
1789 str.push_back (importmode2string (ImportAsTrack));
1790 str.push_back (importmode2string (ImportToTrack));
1791 str.push_back (importmode2string (ImportAsRegion));
1792 str.push_back (importmode2string (ImportAsTapeTrack));
1793 set_popdown_strings (action_combo, str);
1794 action_combo.set_active_text (importmode2string(mode_hint));
1796 reset (selected_audio_tracks, selected_midi_tracks);
1800 SoundFileOmega::set_mode (ImportMode mode)
1802 action_combo.set_active_text (importmode2string (mode));
1806 SoundFileOmega::get_mode () const
1808 return string2importmode (action_combo.get_active_text());
1812 SoundFileOmega::on_hide ()
1814 ArdourWindow::on_hide();
1816 _session->cancel_audition();
1821 SoundFileOmega::get_position() const
1823 string str = where_combo.get_active_text();
1825 if (str == _("file timestamp")) {
1826 return ImportAtTimestamp;
1827 } else if (str == _("edit point")) {
1828 return ImportAtEditPoint;
1829 } else if (str == _("playhead")) {
1830 return ImportAtPlayhead;
1832 return ImportAtStart;
1837 SoundFileOmega::get_src_quality() const
1839 string str = src_combo.get_active_text();
1841 if (str == _("Best")) {
1843 } else if (str == _("Good")) {
1845 } else if (str == _("Quick")) {
1847 } else if (str == _("Fast")) {
1855 SoundFileOmega::src_combo_changed()
1857 preview.set_src_quality(get_src_quality());
1861 SoundFileOmega::where_combo_changed()
1863 preview.set_import_position(get_position());
1867 SoundFileOmega::get_channel_disposition () const
1869 /* we use a map here because the channel combo can contain different strings
1870 depending on the state of the other combos. the map contains all possible strings
1871 and the ImportDisposition enum that corresponds to it.
1874 string str = channel_combo.get_active_text();
1875 DispositionMap::const_iterator x = disposition_map.find (str);
1877 if (x == disposition_map.end()) {
1878 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1879 abort(); /*NOTREACHED*/
1886 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
1888 selected_audio_track_cnt = selected_audio_tracks;
1889 selected_midi_track_cnt = selected_midi_tracks;
1891 if (selected_audio_track_cnt == 0 && selected_midi_track_cnt > 0) {
1892 chooser.set_filter (midi_filter);
1893 } else if (selected_midi_track_cnt == 0 && selected_audio_track_cnt > 0) {
1894 chooser.set_filter (audio_filter);
1896 chooser.set_filter (audio_and_midi_filter);
1903 SoundFileOmega::file_selection_changed ()
1905 if (resetting_ourselves) {
1909 if (!reset_options ()) {
1910 set_action_sensitive (false);
1912 if (chooser.get_filenames().size() > 0) {
1913 set_action_sensitive (true);
1915 set_action_sensitive (false);
1921 SoundFileOmega::do_something (int action)
1923 SoundFileBrowser::do_something (action);
1925 if (action == RESPONSE_CLOSE) {
1932 vector<string> paths = get_paths ();
1933 ImportPosition pos = get_position ();
1934 ImportMode mode = get_mode ();
1935 ImportDisposition chns = get_channel_disposition ();
1936 PluginInfoPtr instrument = instrument_combo.selected_instrument();
1940 case ImportAtEditPoint:
1941 where = PublicEditor::instance().get_preferred_edit_position ();
1943 case ImportAtTimestamp:
1946 case ImportAtPlayhead:
1947 where = _session->transport_frame();
1950 where = _session->current_start_frame();
1954 SrcQuality quality = get_src_quality();
1956 _import_active = true;
1958 if (copy_files_btn.get_active()) {
1959 PublicEditor::instance().do_import (paths, chns, mode, quality, where, instrument);
1961 PublicEditor::instance().do_embed (paths, chns, mode, where, instrument);
1964 _import_active = false;
1966 if (_reset_post_import) {
1967 _reset_post_import = false;