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");
569 chooser.add_shortcut_folder_uri("file:///Volumes");
571 catch (Glib::Error & e) {
572 std::cerr << "sfdb.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
576 //add the file chooser
578 chooser.set_border_width (12);
580 audio_and_midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun (*this, &SoundFileBrowser::on_audio_and_midi_filter));
581 audio_and_midi_filter.set_name (_("Audio and MIDI files"));
583 audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
584 audio_filter.set_name (_("Audio files"));
586 midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
587 midi_filter.set_name (_("MIDI files"));
589 matchall_filter.add_pattern ("*.*");
590 matchall_filter.set_name (_("All files"));
592 chooser.add_filter (audio_and_midi_filter);
593 chooser.add_filter (audio_filter);
594 chooser.add_filter (midi_filter);
595 chooser.add_filter (matchall_filter);
596 chooser.set_select_multiple (true);
597 chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
598 chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
601 /* some broken redraw behaviour - this is a bandaid */
602 chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
605 if (!persistent_folder.empty()) {
606 chooser.set_current_folder (persistent_folder);
609 notebook.append_page (chooser, _("Browse Files"));
611 hpacker.set_spacing (6);
612 hpacker.pack_start (notebook, true, true);
613 hpacker.pack_start (preview, false, false);
615 vpacker.set_spacing (6);
616 vpacker.pack_start (hpacker, true, true);
626 hbox = manage(new HBox);
627 hbox->pack_start (found_entry);
628 hbox->pack_start (found_search_btn);
630 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
631 scroll->add(found_list_view);
632 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
634 vbox = manage(new VBox);
635 vbox->pack_start (*hbox, PACK_SHRINK);
636 vbox->pack_start (*scroll);
638 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
640 found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
642 found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
644 found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
645 found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
647 notebook.append_page (*vbox, _("Search Tags"));
649 //add freesound search
654 passbox = manage(new HBox);
655 passbox->set_spacing (6);
657 label = manage (new Label);
658 label->set_text (_("Tags:"));
659 passbox->pack_start (*label, false, false);
660 passbox->pack_start (freesound_entry, true, true);
662 label = manage (new Label);
663 label->set_text (_("Sort:"));
664 passbox->pack_start (*label, false, false);
665 passbox->pack_start (freesound_sort, false, false);
666 freesound_sort.clear_items();
668 // Order of the following must correspond with enum sortMethod
669 // in sfdb_freesound_mootcher.h
670 freesound_sort.append_text(_("None"));
671 freesound_sort.append_text(_("Longest"));
672 freesound_sort.append_text(_("Shortest"));
673 freesound_sort.append_text(_("Newest"));
674 freesound_sort.append_text(_("Oldest"));
675 freesound_sort.append_text(_("Most downloaded"));
676 freesound_sort.append_text(_("Least downloaded"));
677 freesound_sort.append_text(_("Highest rated"));
678 freesound_sort.append_text(_("Lowest rated"));
679 freesound_sort.set_active(0);
681 passbox->pack_start (freesound_search_btn, false, false);
682 passbox->pack_start (freesound_more_btn, false, false);
683 freesound_more_btn.set_label(_("More"));
684 freesound_more_btn.set_sensitive(false);
686 passbox->pack_start (freesound_similar_btn, false, false);
687 freesound_similar_btn.set_label(_("Similar"));
688 freesound_similar_btn.set_sensitive(false);
690 scroll = manage(new ScrolledWindow);
691 scroll->add(freesound_list_view);
692 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
694 vbox = manage(new VBox);
695 vbox->set_spacing (3);
696 vbox->pack_start (*passbox, PACK_SHRINK);
697 vbox->pack_start (*scroll);
699 freesound_list_view.append_column(_("ID") , freesound_list_columns.id);
700 freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
701 // freesound_list_view.append_column(_("URI") , freesound_list_columns.uri);
702 freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
703 freesound_list_view.append_column(_("Size"), freesound_list_columns.filesize);
704 freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
705 freesound_list_view.append_column(_("License"), freesound_list_columns.license);
706 freesound_list_view.get_column(0)->set_alignment(0.5);
707 freesound_list_view.get_column(1)->set_expand(true); // filename
708 freesound_list_view.get_column(1)->set_resizable(true); // filename
709 freesound_list_view.get_column(2)->set_alignment(0.5);
710 freesound_list_view.get_column(3)->set_alignment(0.5);
711 freesound_list_view.get_column(4)->set_alignment(0.5);
712 freesound_list_view.get_column(5)->set_alignment(0.5);
714 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
715 freesound_list_view.set_tooltip_column(1);
717 freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
718 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
719 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
720 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
721 freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
722 freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
723 notebook.append_page (*vbox, _("Search Freesound"));
725 notebook.set_size_request (500, -1);
726 notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
730 Gtk::HButtonBox* button_box = manage (new HButtonBox);
732 button_box->set_layout (BUTTONBOX_END);
733 button_box->pack_start (close_button, false, false);
734 close_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_CLOSE));
736 button_box->pack_start (import_button, false, false);
737 import_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_OK));
739 Gtkmm2ext::UI::instance()->set_tip (import_button, _("Press to import selected files"));
740 Gtkmm2ext::UI::instance()->set_tip (close_button, _("Press to close this window without importing any files"));
742 vpacker.pack_end (*button_box, false, false);
744 set_wmclass (X_("import"), PROGRAM_NAME);
747 SoundFileBrowser::~SoundFileBrowser ()
749 persistent_folder = chooser.get_current_folder();
753 SoundFileBrowser::run ()
762 gtk_main_iteration ();
769 SoundFileBrowser::set_action_sensitive (bool yn)
771 import_button.set_sensitive (yn);
775 SoundFileBrowser::do_something (int action)
782 SoundFileBrowser::on_show ()
784 ArdourWindow::on_show ();
789 SoundFileBrowser::clear_selection ()
791 chooser.unselect_all ();
792 found_list_view.get_selection()->unselect_all ();
796 SoundFileBrowser::chooser_file_activated ()
802 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
808 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
814 SoundFileBrowser::set_session (Session* s)
816 ArdourWindow::set_session (s);
817 preview.set_session (s);
822 remove_gain_meter ();
827 SoundFileBrowser::add_gain_meter ()
831 gm = new GainMeter (_session, 250);
833 boost::shared_ptr<Route> r = _session->the_auditioner ();
835 gm->set_controls (r, r->shared_peak_meter(), r->amp());
836 gm->set_fader_name (X_("GainFader"));
838 meter_packer.set_border_width (12);
839 meter_packer.pack_start (*gm, false, true);
840 hpacker.pack_end (meter_packer, false, false);
841 meter_packer.show_all ();
846 SoundFileBrowser::remove_gain_meter ()
849 meter_packer.remove (*gm);
850 hpacker.remove (meter_packer);
857 SoundFileBrowser::start_metering ()
859 metering_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
863 SoundFileBrowser::stop_metering ()
865 metering_connection.disconnect();
869 SoundFileBrowser::meter ()
871 if (is_mapped () && _session && gm) {
872 gm->update_meters ();
877 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
879 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
883 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
885 return SMFSource::safe_midi_file_extension (filter_info.filename);
889 SoundFileBrowser::on_audio_and_midi_filter (const FileFilter::Info& filter_info)
891 return on_audio_filter (filter_info) || on_midi_filter (filter_info);
895 SoundFileBrowser::update_preview ()
897 if (preview.setup_labels (chooser.get_preview_filename())) {
898 if (preview.autoplay()) {
899 Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
905 SoundFileBrowser::found_list_view_selected ()
907 if (!reset_options ()) {
908 set_action_sensitive (false);
912 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
915 TreeIter iter = found_list->get_iter(*rows.begin());
916 file = (*iter)[found_list_columns.pathname];
917 chooser.set_filename (file);
918 set_action_sensitive (true);
920 set_action_sensitive (false);
923 preview.setup_labels (file);
928 SoundFileBrowser::found_search_clicked ()
930 string tag_string = found_entry.get_text ();
934 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
935 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
939 vector<string> results;
940 Library->search_members_and (results, tags);
943 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
944 TreeModel::iterator new_row = found_list->append();
945 TreeModel::Row row = *new_row;
946 string path = Glib::filename_from_uri (string ("file:") + *i);
947 row[found_list_columns.pathname] = path;
953 SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
956 Mootcher *mootcher = new Mootcher;
959 string id = (*iter)[freesound_list_columns.id];
960 string uri = (*iter)[freesound_list_columns.uri];
961 string ofn = (*iter)[freesound_list_columns.filename];
963 if (mootcher->checkAudioFile(ofn, id)) {
964 // file already exists, no need to download it again
965 file = mootcher->audioFileName;
967 (*iter)[freesound_list_columns.started] = false;
970 if (!(*iter)[freesound_list_columns.started]) {
971 // start downloading the sound file
972 (*iter)[freesound_list_columns.started] = true;
973 mootcher->fetchAudioFile(ofn, id, uri, this);
979 SoundFileBrowser::freesound_list_view_selected ()
982 if (!reset_options ()) {
983 set_action_sensitive (false);
986 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
987 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
988 file = freesound_get_audio_file (freesound_list->get_iter(*i));
991 switch (rows.size()) {
994 freesound_similar_btn.set_sensitive(false);
995 set_action_sensitive (false);
998 // exactly one item selected
1000 // file exists on disk already
1001 chooser.set_filename (file);
1002 preview.setup_labels (file);
1003 set_action_sensitive (true);
1005 freesound_similar_btn.set_sensitive(true);
1008 // multiple items selected
1009 preview.setup_labels ("");
1010 freesound_similar_btn.set_sensitive(false);
1018 SoundFileBrowser::refresh_display(std::string ID, std::string file)
1020 // called when the mootcher has finished downloading a file
1021 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1022 if (rows.size() == 1) {
1023 // there's a single item selected in the freesound list
1024 //XXX make a function to be used to construct the actual file name both here and in the mootcher
1025 Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
1026 std::string selected_ID = (*row)[freesound_list_columns.id];
1027 if (ID == selected_ID) {
1028 // the selected item in the freesound list is the item that has just finished downloading
1029 chooser.set_filename(file);
1030 preview.setup_labels (file);
1031 set_action_sensitive (true);
1037 SoundFileBrowser::freesound_search_clicked ()
1040 freesound_list->clear();
1046 SoundFileBrowser::freesound_more_clicked ()
1051 snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
1052 freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
1056 SoundFileBrowser::freesound_similar_clicked ()
1058 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1059 if (rows.size() == 1) {
1062 Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
1063 id = (*iter)[freesound_list_columns.id];
1064 freesound_list->clear();
1066 GdkCursor *prev_cursor;
1067 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1068 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1071 std::string theString = mootcher.searchSimilar(id);
1073 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1074 handle_freesound_results(theString);
1079 SoundFileBrowser::freesound_search()
1083 string search_string = freesound_entry.get_text ();
1084 enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
1086 GdkCursor *prev_cursor;
1087 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1088 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1091 std::string theString = mootcher.searchText(
1095 "", // OSX eats anything incl mp3
1097 "type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
1102 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1103 handle_freesound_results(theString);
1107 SoundFileBrowser::handle_freesound_results(std::string theString) {
1109 doc.read_buffer( theString );
1110 XMLNode *root = doc.root();
1113 error << "no root XML node!" << endmsg;
1117 if ( strcmp(root->name().c_str(), "response") != 0) {
1118 error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
1122 // find out how many pages are available to search
1123 int freesound_n_pages = 1;
1124 XMLNode *res = root->child("num_pages");
1126 string result = res->child("text")->content();
1127 freesound_n_pages = atoi(result);
1130 int more_pages = freesound_n_pages - freesound_page;
1132 if (more_pages > 0) {
1133 freesound_more_btn.set_sensitive(true);
1134 freesound_more_btn.set_tooltip_text(string_compose(P_(
1135 "%1 more page of 100 results available",
1136 "%1 more pages of 100 results available",
1137 more_pages), more_pages));
1139 freesound_more_btn.set_sensitive(false);
1140 freesound_more_btn.set_tooltip_text(_("No more results available"));
1143 XMLNode *sounds_root = root->child("sounds");
1145 error << "no child node \"sounds\" found!" << endmsg;
1149 XMLNodeList sounds = sounds_root->children();
1150 if (sounds.size() == 0) {
1155 XMLNodeConstIterator niter;
1157 for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
1159 if( strcmp( node->name().c_str(), "resource") != 0 ) {
1160 error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
1164 // node->dump(cerr, "node:");
1167 XMLNode *id_node = node->child ("id");
1168 XMLNode *uri_node = node->child ("serve");
1169 XMLNode *ofn_node = node->child ("original_filename");
1170 XMLNode *dur_node = node->child ("duration");
1171 XMLNode *siz_node = node->child ("filesize");
1172 XMLNode *srt_node = node->child ("samplerate");
1173 XMLNode *lic_node = node->child ("license");
1175 if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
1177 std::string id = id_node->child("text")->content();
1178 std::string uri = uri_node->child("text")->content();
1179 std::string ofn = ofn_node->child("text")->content();
1180 std::string dur = dur_node->child("text")->content();
1181 std::string siz = siz_node->child("text")->content();
1182 std::string srt = srt_node->child("text")->content();
1183 std::string lic = lic_node->child("text")->content();
1186 // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
1188 double duration_seconds = atof(dur);
1190 char duration_hhmmss[16];
1191 if (duration_seconds >= 99 * 60 * 60) {
1192 strcpy(duration_hhmmss, ">99h");
1194 s = modf(duration_seconds/60, &m) * 60;
1195 m = modf(m/60, &h) * 60;
1196 sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
1201 double size_bytes = atof(siz);
1203 if (size_bytes < 1000) {
1204 sprintf(bsize, "%.0f %s", size_bytes, _("B"));
1205 } else if (size_bytes < 1000000 ) {
1206 sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
1207 } else if (size_bytes < 10000000) {
1208 sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
1209 } else if (size_bytes < 1000000000) {
1210 sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
1212 sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
1215 /* see http://www.freesound.org/help/faq/#licenses */
1216 char shortlicense[64];
1217 if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
1218 sprintf(shortlicense, "CC-BY-NC");
1219 } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
1220 sprintf(shortlicense, "CC-BY");
1221 } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
1222 sprintf(shortlicense, "sampling+");
1223 } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
1224 sprintf(shortlicense, "PD");
1226 snprintf(shortlicense, 64, "%s", lic.c_str());
1227 shortlicense[63]= '\0';
1230 TreeModel::iterator new_row = freesound_list->append();
1231 TreeModel::Row row = *new_row;
1233 row[freesound_list_columns.id ] = id;
1234 row[freesound_list_columns.uri ] = uri;
1235 row[freesound_list_columns.filename] = ofn;
1236 row[freesound_list_columns.duration] = duration_hhmmss;
1237 row[freesound_list_columns.filesize] = bsize;
1238 row[freesound_list_columns.smplrate] = srt;
1239 row[freesound_list_columns.license ] = shortlicense;
1246 SoundFileBrowser::get_paths ()
1248 vector<string> results;
1250 int n = notebook.get_current_page ();
1253 vector<string> filenames = chooser.get_filenames();
1254 vector<string>::iterator i;
1256 for (i = filenames.begin(); i != filenames.end(); ++i) {
1258 if ((!g_stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
1259 results.push_back (*i);
1263 } else if (n == 1) {
1265 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1266 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1267 TreeIter iter = found_list->get_iter(*i);
1268 string str = (*iter)[found_list_columns.pathname];
1270 results.push_back (str);
1273 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1274 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1275 string str = freesound_get_audio_file (freesound_list->get_iter(*i));
1277 results.push_back (str);
1286 SoundFileOmega::reset_options_noret ()
1288 if (!resetting_ourselves) {
1289 (void) reset_options ();
1294 SoundFileOmega::reset_options ()
1296 vector<string> paths = get_paths ();
1298 if (paths.empty()) {
1300 channel_combo.set_sensitive (false);
1301 action_combo.set_sensitive (false);
1302 where_combo.set_sensitive (false);
1303 copy_files_btn.set_active (true);
1304 copy_files_btn.set_sensitive (false);
1310 channel_combo.set_sensitive (true);
1311 action_combo.set_sensitive (true);
1312 where_combo.set_sensitive (true);
1314 /* if we get through this function successfully, this may be
1315 reset at the end, once we know if we can use hard links
1316 to do embedding (or if we are importing a MIDI file).
1319 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1320 copy_files_btn.set_sensitive (false);
1322 copy_files_btn.set_sensitive (false);
1328 bool selection_includes_multichannel;
1329 bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1332 /* See if we are thinking about importing any MIDI files */
1333 vector<string>::iterator i = paths.begin ();
1334 while (i != paths.end() && SMFSource::valid_midi_file (*i) == false) {
1337 bool const have_a_midi_file = (i != paths.end ());
1339 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1340 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1344 string existing_choice;
1345 vector<string> action_strings;
1347 resetting_ourselves = true;
1349 if (chooser.get_filter() == &audio_filter) {
1353 if (selected_audio_track_cnt > 0) {
1354 if (channel_combo.get_active_text().length()) {
1355 ImportDisposition id = get_channel_disposition();
1358 case Editing::ImportDistinctFiles:
1359 if (selected_audio_track_cnt == paths.size()) {
1360 action_strings.push_back (importmode2string (ImportToTrack));
1364 case Editing::ImportDistinctChannels:
1365 /* XXX it would be nice to allow channel-per-selected track
1366 but its too hard we don't want to deal with all the
1367 different per-file + per-track channel configurations.
1372 action_strings.push_back (importmode2string (ImportToTrack));
1382 if (selected_midi_track_cnt > 0) {
1383 action_strings.push_back (importmode2string (ImportToTrack));
1387 action_strings.push_back (importmode2string (ImportAsTrack));
1388 action_strings.push_back (importmode2string (ImportAsRegion));
1389 action_strings.push_back (importmode2string (ImportAsTapeTrack));
1391 existing_choice = action_combo.get_active_text();
1393 set_popdown_strings (action_combo, action_strings);
1395 /* preserve any existing choice, if possible */
1398 if (existing_choice.length()) {
1399 vector<string>::iterator x;
1400 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1401 if (*x == existing_choice) {
1402 action_combo.set_active_text (existing_choice);
1406 if (x == action_strings.end()) {
1407 action_combo.set_active_text (action_strings.front());
1410 action_combo.set_active_text (action_strings.front());
1413 resetting_ourselves = false;
1415 if ((mode = get_mode()) == ImportAsRegion) {
1416 where_combo.set_sensitive (false);
1418 where_combo.set_sensitive (true);
1421 vector<string> channel_strings;
1423 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1424 channel_strings.push_back (_("one track per file"));
1426 if (selection_includes_multichannel) {
1427 channel_strings.push_back (_("one track per channel"));
1430 if (paths.size() > 1) {
1431 /* tape tracks are a single region per track, so we cannot
1432 sequence multiple files.
1434 if (mode != ImportAsTapeTrack) {
1435 channel_strings.push_back (_("sequence files"));
1438 channel_strings.push_back (_("all files in one track"));
1439 channel_strings.push_back (_("merge files"));
1445 channel_strings.push_back (_("one region per file"));
1447 if (selection_includes_multichannel) {
1448 channel_strings.push_back (_("one region per channel"));
1451 if (paths.size() > 1) {
1453 channel_strings.push_back (_("all files in one region"));
1458 resetting_ourselves = true;
1460 existing_choice = channel_combo.get_active_text();
1462 set_popdown_strings (channel_combo, channel_strings);
1464 /* preserve any existing choice, if possible */
1466 if (existing_choice.length()) {
1467 vector<string>::iterator x;
1468 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1469 if (*x == existing_choice) {
1470 channel_combo.set_active_text (existing_choice);
1474 if (x == channel_strings.end()) {
1475 channel_combo.set_active_text (channel_strings.front());
1478 channel_combo.set_active_text (channel_strings.front());
1481 resetting_ourselves = false;
1484 src_combo.set_sensitive (true);
1486 src_combo.set_sensitive (false);
1489 /* We must copy MIDI files or those from Freesound
1490 * or any file if we are under nsm control */
1491 bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
1493 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1495 if (selection_can_be_embedded_with_links && !must_copy) {
1496 copy_files_btn.set_sensitive (true);
1499 copy_files_btn.set_active (true);
1501 copy_files_btn.set_sensitive (false);
1507 copy_files_btn.set_active (true);
1509 copy_files_btn.set_sensitive (!must_copy);
1517 SoundFileOmega::bad_file_message()
1519 MessageDialog msg (*this,
1520 string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1525 resetting_ourselves = true;
1526 chooser.unselect_uri (chooser.get_preview_uri());
1527 resetting_ourselves = false;
1533 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1542 multichannel = false;
1544 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1546 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1547 if (info.channels > 1) {
1548 multichannel = true;
1553 if (sz != info.length) {
1558 if (info.samplerate != _session->frame_rate()) {
1562 } else if (SMFSource::valid_midi_file (*i)) {
1566 if (reader.num_tracks() > 1) {
1567 multichannel = true; // "channel" == track here...
1570 /* XXX we need err = true handling here in case
1571 we can't check the file
1584 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1586 #ifdef PLATFORM_WINDOWS
1589 std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
1592 if (g_mkdir (tmpdir.c_str(), 0744)) {
1593 if (errno != EEXIST) {
1598 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1600 char tmpc[PATH_MAX+1];
1602 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1606 if (link ((*i).c_str(), tmpc)) {
1616 g_rmdir (tmpdir.c_str());
1621 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
1622 : SoundFileBrowser (title, s, false)
1624 chooser.set_select_multiple (false);
1625 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1626 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1630 SoundFileChooser::on_hide ()
1632 ArdourWindow::on_hide();
1636 _session->cancel_audition();
1641 SoundFileChooser::get_filename ()
1643 vector<string> paths;
1645 paths = get_paths ();
1647 if (paths.empty()) {
1651 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1655 return paths.front();
1658 SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s,
1659 uint32_t selected_audio_tracks,
1660 uint32_t selected_midi_tracks,
1662 Editing::ImportMode mode_hint)
1663 : SoundFileBrowser (title, s, persistent)
1664 , copy_files_btn ( _("Copy files to session"))
1665 , selected_audio_track_cnt (selected_audio_tracks)
1666 , selected_midi_track_cnt (selected_midi_tracks)
1672 set_size_request (-1, 450);
1674 block_two.set_border_width (12);
1675 block_three.set_border_width (12);
1676 block_four.set_border_width (12);
1678 options.set_spacing (12);
1681 str.push_back (_("file timestamp"));
1682 str.push_back (_("edit point"));
1683 str.push_back (_("playhead"));
1684 str.push_back (_("session start"));
1685 set_popdown_strings (where_combo, str);
1686 where_combo.set_active_text (str.front());
1687 where_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::where_combo_changed));
1689 Label* l = manage (new Label);
1690 l->set_markup (_("<b>Add files as ...</b>"));
1692 vbox = manage (new VBox);
1693 vbox->set_border_width (12);
1694 vbox->set_spacing (6);
1695 vbox->pack_start (*l, false, false);
1696 vbox->pack_start (action_combo, false, false);
1697 hbox = manage (new HBox);
1698 hbox->pack_start (*vbox, false, false);
1699 options.pack_start (*hbox, false, false);
1701 /* dummy entry for action combo so that it doesn't look odd if we
1702 come up with no tracks selected.
1706 str.push_back (importmode2string (mode_hint));
1707 set_popdown_strings (action_combo, str);
1708 action_combo.set_active_text (str.front());
1709 action_combo.set_sensitive (false);
1711 l = manage (new Label);
1712 l->set_markup (_("<b>Insert at</b>"));
1714 vbox = manage (new VBox);
1715 vbox->set_border_width (12);
1716 vbox->set_spacing (6);
1717 vbox->pack_start (*l, false, false);
1718 vbox->pack_start (where_combo, false, false);
1719 hbox = manage (new HBox);
1720 hbox->pack_start (*vbox, false, false);
1721 options.pack_start (*hbox, false, false);
1724 l = manage (new Label);
1725 l->set_markup (_("<b>Mapping</b>"));
1727 vbox = manage (new VBox);
1728 vbox->set_border_width (12);
1729 vbox->set_spacing (6);
1730 vbox->pack_start (*l, false, false);
1731 vbox->pack_start (channel_combo, false, false);
1732 hbox = manage (new HBox);
1733 hbox->pack_start (*vbox, false, false);
1734 options.pack_start (*hbox, false, false);
1737 str.push_back (_("one track per file"));
1738 set_popdown_strings (channel_combo, str);
1739 channel_combo.set_active_text (str.front());
1740 channel_combo.set_sensitive (false);
1742 l = manage (new Label);
1743 l->set_markup (_("<b>Conversion quality</b>"));
1745 vbox = manage (new VBox);
1746 vbox->set_border_width (12);
1747 vbox->set_spacing (6);
1748 vbox->pack_start (*l, false, false);
1749 vbox->pack_start (src_combo, false, false);
1750 hbox = manage (new HBox);
1751 hbox->pack_start (*vbox, false, false);
1752 options.pack_start (*hbox, false, false);
1754 l = manage (new Label);
1755 l->set_markup (_("<b>Instrument</b>"));
1757 vbox = manage (new VBox);
1758 vbox->set_border_width (12);
1759 vbox->set_spacing (6);
1760 vbox->pack_start (*l, false, false);
1761 vbox->pack_start (instrument_combo, false, false);
1762 hbox = manage (new HBox);
1763 hbox->pack_start (*vbox, false, false);
1764 options.pack_start (*hbox, false, false);
1767 str.push_back (_("Best"));
1768 str.push_back (_("Good"));
1769 str.push_back (_("Quick"));
1770 str.push_back (_("Fast"));
1771 str.push_back (_("Fastest"));
1773 set_popdown_strings (src_combo, str);
1774 src_combo.set_active_text (str.front());
1775 src_combo.set_sensitive (false);
1776 src_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::src_combo_changed));
1780 action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1781 channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1783 copy_files_btn.set_active (true);
1785 Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1788 copy_label->set_size_request (175, -1);
1789 copy_label->set_line_wrap (true);
1792 block_four.pack_start (copy_files_btn, false, false);
1794 options.pack_start (block_four, false, false);
1796 vpacker.pack_start (options, false, false);
1798 /* setup disposition map */
1800 disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1801 disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1802 disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1803 disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1805 disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1806 disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1807 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1808 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1810 chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1812 /* set size requests for a couple of combos to allow them to display the longest text
1813 they will ever be asked to display. This prevents them being resized when the user
1814 selects a file to import, which in turn prevents the size of the dialog from jumping
1818 t.push_back (_("one track per file"));
1819 t.push_back (_("one track per channel"));
1820 t.push_back (_("sequence files"));
1821 t.push_back (_("all files in one region"));
1822 set_popdown_strings (channel_combo, t);
1825 t.push_back (importmode2string (ImportAsTrack));
1826 t.push_back (importmode2string (ImportToTrack));
1827 t.push_back (importmode2string (ImportAsRegion));
1828 t.push_back (importmode2string (ImportAsTapeTrack));
1829 set_popdown_strings (action_combo, t);
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 if (copy_files_btn.get_active()) {
1990 PublicEditor::instance().do_import (paths, chns, mode, quality, where, instrument);
1992 PublicEditor::instance().do_embed (paths, chns, mode, where, instrument);