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)
1681 set_size_request (-1, 450);
1683 block_two.set_border_width (12);
1684 block_three.set_border_width (12);
1685 block_four.set_border_width (12);
1687 options.set_spacing (12);
1690 str.push_back (_("file timestamp"));
1691 str.push_back (_("edit point"));
1692 str.push_back (_("playhead"));
1693 str.push_back (_("session start"));
1694 set_popdown_strings (where_combo, str);
1695 where_combo.set_active_text (str.back());
1696 where_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::where_combo_changed));
1698 Label* l = manage (new Label);
1699 l->set_markup (_("<b>Add files ...</b>"));
1701 vbox = manage (new VBox);
1702 vbox->set_border_width (12);
1703 vbox->set_spacing (6);
1704 vbox->pack_start (*l, false, false);
1705 vbox->pack_start (action_combo, false, false);
1706 hbox = manage (new HBox);
1707 hbox->pack_start (*vbox, false, false);
1708 options.pack_start (*hbox, false, false);
1710 l = manage (new Label);
1711 l->set_markup (_("<b>Insert at</b>"));
1713 vbox = manage (new VBox);
1714 vbox->set_border_width (12);
1715 vbox->set_spacing (6);
1716 vbox->pack_start (*l, false, false);
1717 vbox->pack_start (where_combo, false, false);
1718 hbox = manage (new HBox);
1719 hbox->pack_start (*vbox, false, false);
1720 options.pack_start (*hbox, false, false);
1723 l = manage (new Label);
1724 l->set_markup (_("<b>Mapping</b>"));
1726 vbox = manage (new VBox);
1727 vbox->set_border_width (12);
1728 vbox->set_spacing (6);
1729 vbox->pack_start (*l, false, false);
1730 vbox->pack_start (channel_combo, false, false);
1731 hbox = manage (new HBox);
1732 hbox->pack_start (*vbox, false, false);
1733 options.pack_start (*hbox, false, false);
1736 str.push_back (_("one track per file"));
1737 set_popdown_strings (channel_combo, str);
1738 channel_combo.set_active_text (str.front());
1739 channel_combo.set_sensitive (false);
1741 l = manage (new Label);
1742 l->set_markup (_("<b>Conversion quality</b>"));
1744 vbox = manage (new VBox);
1745 vbox->set_border_width (12);
1746 vbox->set_spacing (6);
1747 vbox->pack_start (*l, false, false);
1748 vbox->pack_start (src_combo, false, false);
1749 hbox = manage (new HBox);
1750 hbox->pack_start (*vbox, false, false);
1751 options.pack_start (*hbox, false, false);
1753 l = manage (new Label);
1754 l->set_markup (_("<b>Instrument</b>"));
1756 vbox = manage (new VBox);
1757 vbox->set_border_width (12);
1758 vbox->set_spacing (6);
1759 vbox->pack_start (*l, false, false);
1760 vbox->pack_start (instrument_combo, false, false);
1761 hbox = manage (new HBox);
1762 hbox->pack_start (*vbox, false, false);
1763 options.pack_start (*hbox, false, false);
1766 str.push_back (_("Best"));
1767 str.push_back (_("Good"));
1768 str.push_back (_("Quick"));
1769 str.push_back (_("Fast"));
1770 str.push_back (_("Fastest"));
1772 set_popdown_strings (src_combo, str);
1773 src_combo.set_active_text (str.front());
1774 src_combo.set_sensitive (false);
1775 src_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::src_combo_changed));
1777 action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1778 channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1780 copy_files_btn.set_active (true);
1782 Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1785 copy_label->set_size_request (175, -1);
1786 copy_label->set_line_wrap (true);
1789 block_four.pack_start (copy_files_btn, false, false);
1791 options.pack_start (block_four, false, false);
1793 vpacker.pack_start (options, false, false);
1795 /* setup disposition map */
1797 disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1798 disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1799 disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1800 disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1802 disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1803 disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1804 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1805 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1807 chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1809 /* set size requests for a couple of combos to allow them to display the longest text
1810 they will ever be asked to display. This prevents them being resized when the user
1811 selects a file to import, which in turn prevents the size of the dialog from jumping
1815 str.push_back (_("one track per file"));
1816 str.push_back (_("one track per channel"));
1817 str.push_back (_("sequence files"));
1818 str.push_back (_("all files in one region"));
1819 set_popdown_strings (channel_combo, str);
1822 str.push_back (importmode2string (ImportAsTrack));
1823 str.push_back (importmode2string (ImportToTrack));
1824 str.push_back (importmode2string (ImportAsRegion));
1825 str.push_back (importmode2string (ImportAsTapeTrack));
1826 set_popdown_strings (action_combo, str);
1827 action_combo.set_active_text (importmode2string(mode_hint));
1829 reset (selected_audio_tracks, selected_midi_tracks);
1833 SoundFileOmega::set_mode (ImportMode mode)
1835 action_combo.set_active_text (importmode2string (mode));
1839 SoundFileOmega::get_mode () const
1841 return string2importmode (action_combo.get_active_text());
1845 SoundFileOmega::on_hide ()
1847 ArdourWindow::on_hide();
1849 _session->cancel_audition();
1854 SoundFileOmega::get_position() const
1856 string str = where_combo.get_active_text();
1858 if (str == _("file timestamp")) {
1859 return ImportAtTimestamp;
1860 } else if (str == _("edit point")) {
1861 return ImportAtEditPoint;
1862 } else if (str == _("playhead")) {
1863 return ImportAtPlayhead;
1865 return ImportAtStart;
1870 SoundFileOmega::get_src_quality() const
1872 string str = src_combo.get_active_text();
1874 if (str == _("Best")) {
1876 } else if (str == _("Good")) {
1878 } else if (str == _("Quick")) {
1880 } else if (str == _("Fast")) {
1888 SoundFileOmega::src_combo_changed()
1890 preview.set_src_quality(get_src_quality());
1894 SoundFileOmega::where_combo_changed()
1896 preview.set_import_position(get_position());
1900 SoundFileOmega::get_channel_disposition () const
1902 /* we use a map here because the channel combo can contain different strings
1903 depending on the state of the other combos. the map contains all possible strings
1904 and the ImportDisposition enum that corresponds to it.
1907 string str = channel_combo.get_active_text();
1908 DispositionMap::const_iterator x = disposition_map.find (str);
1910 if (x == disposition_map.end()) {
1911 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1912 abort(); /*NOTREACHED*/
1919 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
1921 selected_audio_track_cnt = selected_audio_tracks;
1922 selected_midi_track_cnt = selected_midi_tracks;
1924 if (selected_audio_track_cnt == 0 && selected_midi_track_cnt > 0) {
1925 chooser.set_filter (midi_filter);
1926 } else if (selected_midi_track_cnt == 0 && selected_audio_track_cnt > 0) {
1927 chooser.set_filter (audio_filter);
1929 chooser.set_filter (audio_and_midi_filter);
1936 SoundFileOmega::file_selection_changed ()
1938 if (resetting_ourselves) {
1942 if (!reset_options ()) {
1943 set_action_sensitive (false);
1945 if (chooser.get_filenames().size() > 0) {
1946 set_action_sensitive (true);
1948 set_action_sensitive (false);
1954 SoundFileOmega::do_something (int action)
1956 SoundFileBrowser::do_something (action);
1958 if (action == RESPONSE_CLOSE) {
1965 vector<string> paths = get_paths ();
1966 ImportPosition pos = get_position ();
1967 ImportMode mode = get_mode ();
1968 ImportDisposition chns = get_channel_disposition ();
1969 PluginInfoPtr instrument = instrument_combo.selected_instrument();
1973 case ImportAtEditPoint:
1974 where = PublicEditor::instance().get_preferred_edit_position ();
1976 case ImportAtTimestamp:
1979 case ImportAtPlayhead:
1980 where = _session->transport_frame();
1983 where = _session->current_start_frame();
1987 SrcQuality quality = get_src_quality();
1989 _import_active = true;
1991 if (copy_files_btn.get_active()) {
1992 PublicEditor::instance().do_import (paths, chns, mode, quality, where, instrument);
1994 PublicEditor::instance().do_embed (paths, chns, mode, where, instrument);
1997 _import_active = false;
1999 if (_reset_post_import) {
2000 _reset_post_import = false;