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 <glib/gstdio.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"
72 #include "sfdb_freesound_mootcher.h"
74 using namespace ARDOUR;
78 using namespace Gtkmm2ext;
79 using namespace Editing;
83 string SoundFileBrowser::persistent_folder;
84 typedef TreeView::Selection::ListHandle_Path ListPath;
87 string2importmode (string str)
89 if (str == _("as new tracks")) {
91 } else if (str == _("to selected tracks")) {
93 } else if (str == _("to region list")) {
94 return ImportAsRegion;
95 } else if (str == _("as new tape tracks")) {
96 return ImportAsTapeTrack;
99 warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
101 return ImportAsTrack;
105 importmode2string (ImportMode mode)
109 return _("as new tracks");
111 return _("to selected tracks");
113 return _("to region list");
114 case ImportAsTapeTrack:
115 return _("as new tape tracks");
117 abort(); /*NOTREACHED*/
118 return _("as new tracks");
121 SoundFileBox::SoundFileBox (bool /*persistent*/)
123 length_clock ("sfboxLengthClock", true, "", false, false, true, false),
124 timecode_clock ("sfboxTimecodeClock", true, "", false, false, false, false),
126 autoplay_btn (_("Auto-play")),
127 seek_slider(0,1000,1),
131 set_name (X_("SoundFileBox"));
132 set_size_request (300, -1);
134 preview_label.set_markup (_("<b>Sound File Information</b>"));
136 border_frame.set_label_widget (preview_label);
137 border_frame.add (main_box);
139 pack_start (border_frame, true, true);
140 set_border_width (6);
142 main_box.set_border_width (6);
144 length.set_text (_("Length:"));
145 length.set_alignment (1, 0.5);
146 timecode.set_text (_("Timestamp:"));
147 timecode.set_alignment (1, 0.5);
148 format.set_text (_("Format:"));
149 format.set_alignment (1, 0.5);
150 channels.set_text (_("Channels:"));
151 channels.set_alignment (1, 0.5);
152 samplerate.set_text (_("Sample rate:"));
153 samplerate.set_alignment (1, 0.5);
155 preview_label.set_max_width_chars (50);
156 preview_label.set_ellipsize (Pango::ELLIPSIZE_END);
158 format_text.set_max_width_chars (20);
159 format_text.set_ellipsize (Pango::ELLIPSIZE_END);
160 format_text.set_alignment (0, 1);
162 table.set_col_spacings (6);
163 table.set_homogeneous (false);
164 table.set_row_spacings (6);
166 table.attach (channels, 0, 1, 0, 1, FILL, FILL);
167 table.attach (samplerate, 0, 1, 1, 2, FILL, FILL);
168 table.attach (format, 0, 1, 2, 4, FILL, FILL);
169 table.attach (length, 0, 1, 4, 5, FILL, FILL);
170 table.attach (timecode, 0, 1, 5, 6, FILL, FILL);
172 table.attach (channels_value, 1, 2, 0, 1, FILL, FILL);
173 table.attach (samplerate_value, 1, 2, 1, 2, FILL, FILL);
174 table.attach (format_text, 1, 2, 2, 4, FILL, FILL);
175 table.attach (length_clock, 1, 2, 4, 5, FILL, FILL);
176 table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL);
178 length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock->mode());
179 timecode_clock.set_mode (AudioClock::Timecode);
181 main_box.pack_start (table, false, false);
183 tags_entry.set_editable (true);
184 tags_entry.set_wrap_mode(Gtk::WRAP_WORD);
185 tags_entry.signal_focus_out_event().connect (sigc::mem_fun (*this, &SoundFileBox::tags_entry_left));
187 Label* label = manage (new Label (_("Tags:")));
188 label->set_alignment (0.0f, 0.5f);
189 main_box.pack_start (*label, false, false);
190 main_box.pack_start (tags_entry, true, true);
192 main_box.pack_start (bottom_box, false, false);
194 play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
195 // play_btn.set_label (_("Play"));
197 stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
198 // stop_btn.set_label (_("Stop"));
200 bottom_box.set_homogeneous (false);
201 bottom_box.set_spacing (6);
202 bottom_box.pack_start(play_btn, true, true);
203 bottom_box.pack_start(stop_btn, true, true);
204 bottom_box.pack_start(autoplay_btn, false, false);
206 seek_slider.set_draw_value(false);
208 seek_slider.add_events(Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
209 seek_slider.signal_button_press_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_press), false);
210 seek_slider.signal_button_release_event().connect(sigc::mem_fun(*this, &SoundFileBox::seek_button_release), false);
211 main_box.pack_start (seek_slider, false, false);
213 play_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::audition));
214 stop_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::stop_audition));
216 stop_btn.set_sensitive (false);
218 channels_value.set_alignment (0.0f, 0.5f);
219 samplerate_value.set_alignment (0.0f, 0.5f);
223 SoundFileBox::set_session(Session* s)
225 SessionHandlePtr::set_session (s);
227 length_clock.set_session (s);
228 timecode_clock.set_session (s);
231 play_btn.set_sensitive (false);
232 stop_btn.set_sensitive (false);
233 auditioner_connections.drop_connections();
235 auditioner_connections.drop_connections();
236 _session->AuditionActive.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_active, this, _1), gui_context());
237 _session->the_auditioner()->AuditionProgress.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_progress, this, _1, _2), gui_context());
242 SoundFileBox::audition_active(bool active) {
243 stop_btn.set_sensitive (active);
244 seek_slider.set_sensitive (active);
246 seek_slider.set_value(0);
251 SoundFileBox::audition_progress(ARDOUR::framecnt_t pos, ARDOUR::framecnt_t len) {
253 seek_slider.set_value( 1000.0 * pos / len);
254 seek_slider.set_sensitive (true);
259 SoundFileBox::seek_button_press(GdkEventButton*) {
261 return false; // pass on to slider
265 SoundFileBox::seek_button_release(GdkEventButton*) {
267 _session->the_auditioner()->seek_to_percent(seek_slider.get_value() / 10.0);
268 seek_slider.set_sensitive (false);
269 return false; // pass on to slider
273 SoundFileBox::setup_labels (const string& filename)
276 // save existing tags
284 if (SMFSource::valid_midi_file (path)) {
286 boost::shared_ptr<SMFSource> ms;
288 ms = boost::dynamic_pointer_cast<SMFSource> (
289 SourceFactory::createExternal (DataType::MIDI, *_session,
290 path, 0, Source::Flag (0), false));
291 } catch (const std::exception& e) {
292 error << string_compose(_("Could not read file: %1 (%2)."),
293 path, e.what()) << endmsg;
296 preview_label.set_markup (_("<b>Midi File Information</b>"));
298 format_text.set_text ("MIDI");
299 samplerate_value.set_text ("-");
300 tags_entry.get_buffer()->set_text ("");
301 timecode_clock.set (0);
302 tags_entry.set_sensitive (false);
305 channels_value.set_text (to_string(ms->num_tracks(), std::dec));
306 length_clock.set (ms->length(ms->timeline_position()));
308 channels_value.set_text ("");
309 length_clock.set (0);
312 if (_session && ms) {
313 play_btn.set_sensitive (true);
315 play_btn.set_sensitive (false);
321 if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
323 preview_label.set_markup (_("<b>Sound File Information</b>"));
324 format_text.set_text ("");
325 channels_value.set_text ("");
326 samplerate_value.set_text ("");
327 tags_entry.get_buffer()->set_text ("");
329 length_clock.set (0);
330 timecode_clock.set (0);
332 tags_entry.set_sensitive (false);
333 play_btn.set_sensitive (false);
338 preview_label.set_markup (string_compose ("<b>%1</b>", Glib::Markup::escape_text (Glib::path_get_basename (filename))));
339 std::string n = sf_info.format_name;
340 if (n.substr (0, 8) == X_("Format: ")) {
343 format_text.set_text (n);
344 channels_value.set_text (to_string (sf_info.channels, std::dec));
346 if (_session && sf_info.samplerate != _session->frame_rate()) {
347 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
348 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
349 samplerate_value.set_name ("NewSessionSR1Label");
350 samplerate.set_name ("NewSessionSR1Label");
352 samplerate.set_text (_("Sample rate:"));
353 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
354 samplerate_value.set_name ("NewSessionSR2Label");
355 samplerate.set_name ("NewSessionSR2Label");
358 framecnt_t const nfr = _session ? _session->nominal_frame_rate() : 25;
359 double src_coef = (double) nfr / sf_info.samplerate;
361 length_clock.set (sf_info.length * src_coef + 0.5, true);
362 timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
364 // this is a hack that is fixed in trunk, i think (august 26th, 2007)
366 vector<string> tags = Library->get_tags (string ("//") + filename);
368 stringstream tag_string;
369 for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
370 if (i != tags.begin()) {
375 tags_entry.get_buffer()->set_text (tag_string.str());
377 tags_entry.set_sensitive (true);
379 play_btn.set_sensitive (true);
386 SoundFileBox::autoplay() const
388 return autoplay_btn.get_active();
392 SoundFileBox::audition_oneshot()
399 SoundFileBox::audition ()
405 _session->cancel_audition();
407 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
408 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
412 boost::shared_ptr<Region> r;
414 if (SMFSource::valid_midi_file (path)) {
416 boost::shared_ptr<SMFSource> ms =
417 boost::dynamic_pointer_cast<SMFSource> (
418 SourceFactory::createExternal (DataType::MIDI, *_session,
419 path, 0, Source::Flag (0), false));
421 string rname = region_name_from_path (ms->path(), false);
425 plist.add (ARDOUR::Properties::start, 0);
426 plist.add (ARDOUR::Properties::length, ms->length(ms->timeline_position()));
427 plist.add (ARDOUR::Properties::name, rname);
428 plist.add (ARDOUR::Properties::layer, 0);
430 r = boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (boost::dynamic_pointer_cast<Source>(ms), plist, false));
436 boost::shared_ptr<AudioFileSource> afs;
437 bool old_sbp = AudioSource::get_build_peakfiles ();
439 /* don't even think of building peakfiles for these files */
441 AudioSource::set_build_peakfiles (false);
443 for (int n = 0; n < sf_info.channels; ++n) {
445 afs = boost::dynamic_pointer_cast<AudioFileSource> (
446 SourceFactory::createExternal (DataType::AUDIO, *_session,
448 Source::Flag (ARDOUR::AudioFileSource::NoPeakFile), false));
449 if (afs->sample_rate() != _session->nominal_frame_rate()) {
450 boost::shared_ptr<SrcFileSource> sfs (new SrcFileSource(*_session, afs, _src_quality));
451 srclist.push_back(sfs);
453 srclist.push_back(afs);
456 } catch (failed_constructor& err) {
457 error << _("Could not access soundfile: ") << path << endmsg;
458 AudioSource::set_build_peakfiles (old_sbp);
463 AudioSource::set_build_peakfiles (old_sbp);
465 if (srclist.empty()) {
469 afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
470 string rname = region_name_from_path (afs->path(), false);
474 plist.add (ARDOUR::Properties::start, 0);
475 plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->timeline_position()));
476 plist.add (ARDOUR::Properties::name, rname);
477 plist.add (ARDOUR::Properties::layer, 0);
479 r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false));
482 frameoffset_t audition_position = 0;
483 switch(_import_position) {
484 case ImportAtTimestamp:
485 audition_position = 0;
487 case ImportAtPlayhead:
488 audition_position = _session->transport_frame();
491 audition_position = _session->current_start_frame();
493 case ImportAtEditPoint:
494 audition_position = PublicEditor::instance().get_preferred_edit_position ();
497 r->set_position(audition_position);
499 _session->audition_region(r);
503 SoundFileBox::stop_audition ()
506 _session->cancel_audition();
511 SoundFileBox::tags_entry_left (GdkEventFocus *)
518 SoundFileBox::tags_changed ()
520 string tag_string = tags_entry.get_buffer()->get_text ();
522 if (tag_string.empty()) {
528 if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
529 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
537 SoundFileBox::save_tags (const vector<string>& tags)
539 Library->set_tags (string ("//") + path, tags);
540 Library->save_changes ();
543 SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persistent)
544 : ArdourWindow (title)
545 , found_list (ListStore::create(found_list_columns))
546 , freesound_list (ListStore::create(freesound_list_columns))
547 , chooser (FILE_CHOOSER_ACTION_OPEN)
548 , preview (persistent)
549 , found_search_btn (_("Search"))
550 , found_list_view (found_list)
551 , freesound_search_btn (_("Search"))
552 , freesound_list_view (freesound_list)
553 , resetting_ourselves (false)
557 , import_button (_("Import"))
558 , close_button (Stock::CLOSE)
564 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
565 chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
566 chooser.add_shortcut_folder_uri("file:///Library/Audio/Apple Loops");
567 chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
568 chooser.add_shortcut_folder_uri("file:///Volumes");
570 catch (Glib::Error & e) {
571 std::cerr << "sfdb.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
575 //add the file chooser
577 chooser.set_border_width (12);
579 audio_and_midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun (*this, &SoundFileBrowser::on_audio_and_midi_filter));
580 audio_and_midi_filter.set_name (_("Audio and MIDI files"));
582 audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
583 audio_filter.set_name (_("Audio files"));
585 midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
586 midi_filter.set_name (_("MIDI files"));
588 matchall_filter.add_pattern ("*.*");
589 matchall_filter.set_name (_("All files"));
591 chooser.add_filter (audio_and_midi_filter);
592 chooser.add_filter (audio_filter);
593 chooser.add_filter (midi_filter);
594 chooser.add_filter (matchall_filter);
595 chooser.set_select_multiple (true);
596 chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
597 chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
600 /* some broken redraw behaviour - this is a bandaid */
601 chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
604 if (!persistent_folder.empty()) {
605 chooser.set_current_folder (persistent_folder);
608 notebook.append_page (chooser, _("Browse Files"));
610 hpacker.set_spacing (6);
611 hpacker.pack_start (notebook, true, true);
612 hpacker.pack_start (preview, false, false);
614 vpacker.set_spacing (6);
615 vpacker.pack_start (hpacker, true, true);
625 hbox = manage(new HBox);
626 hbox->pack_start (found_entry);
627 hbox->pack_start (found_search_btn);
629 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
630 scroll->add(found_list_view);
631 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
633 vbox = manage(new VBox);
634 vbox->pack_start (*hbox, PACK_SHRINK);
635 vbox->pack_start (*scroll);
637 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
639 found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
641 found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
643 found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
644 found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
646 notebook.append_page (*vbox, _("Search Tags"));
648 //add freesound search
653 passbox = manage(new HBox);
654 passbox->set_spacing (6);
656 label = manage (new Label);
657 label->set_text (_("Tags:"));
658 passbox->pack_start (*label, false, false);
659 passbox->pack_start (freesound_entry, true, true);
661 label = manage (new Label);
662 label->set_text (_("Sort:"));
663 passbox->pack_start (*label, false, false);
664 passbox->pack_start (freesound_sort, false, false);
665 freesound_sort.clear_items();
667 // Order of the following must correspond with enum sortMethod
668 // in sfdb_freesound_mootcher.h
669 freesound_sort.append_text(_("None"));
670 freesound_sort.append_text(_("Longest"));
671 freesound_sort.append_text(_("Shortest"));
672 freesound_sort.append_text(_("Newest"));
673 freesound_sort.append_text(_("Oldest"));
674 freesound_sort.append_text(_("Most downloaded"));
675 freesound_sort.append_text(_("Least downloaded"));
676 freesound_sort.append_text(_("Highest rated"));
677 freesound_sort.append_text(_("Lowest rated"));
678 freesound_sort.set_active(0);
680 passbox->pack_start (freesound_search_btn, false, false);
681 passbox->pack_start (freesound_more_btn, false, false);
682 freesound_more_btn.set_label(_("More"));
683 freesound_more_btn.set_sensitive(false);
685 passbox->pack_start (freesound_similar_btn, false, false);
686 freesound_similar_btn.set_label(_("Similar"));
687 freesound_similar_btn.set_sensitive(false);
689 scroll = manage(new ScrolledWindow);
690 scroll->add(freesound_list_view);
691 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
693 vbox = manage(new VBox);
694 vbox->set_spacing (3);
695 vbox->pack_start (*passbox, PACK_SHRINK);
696 vbox->pack_start (*scroll);
698 freesound_list_view.append_column(_("ID") , freesound_list_columns.id);
699 freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
700 // freesound_list_view.append_column(_("URI") , freesound_list_columns.uri);
701 freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
702 freesound_list_view.append_column(_("Size"), freesound_list_columns.filesize);
703 freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
704 freesound_list_view.append_column(_("License"), freesound_list_columns.license);
705 freesound_list_view.get_column(0)->set_alignment(0.5);
706 freesound_list_view.get_column(1)->set_expand(true); // filename
707 freesound_list_view.get_column(1)->set_resizable(true); // filename
708 freesound_list_view.get_column(2)->set_alignment(0.5);
709 freesound_list_view.get_column(3)->set_alignment(0.5);
710 freesound_list_view.get_column(4)->set_alignment(0.5);
711 freesound_list_view.get_column(5)->set_alignment(0.5);
713 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
714 freesound_list_view.set_tooltip_column(1);
716 freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
717 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
718 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
719 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
720 freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
721 freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
722 notebook.append_page (*vbox, _("Search Freesound"));
724 notebook.set_size_request (500, -1);
725 notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
729 Gtk::HButtonBox* button_box = manage (new HButtonBox);
731 button_box->set_layout (BUTTONBOX_END);
732 button_box->pack_start (close_button, false, false);
733 close_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_CLOSE));
735 button_box->pack_start (import_button, false, false);
736 import_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_OK));
738 Gtkmm2ext::UI::instance()->set_tip (import_button, _("Press to import selected files"));
739 Gtkmm2ext::UI::instance()->set_tip (close_button, _("Press to close this window without importing any files"));
741 vpacker.pack_end (*button_box, false, false);
743 set_wmclass (X_("import"), PROGRAM_NAME);
746 SoundFileBrowser::~SoundFileBrowser ()
748 persistent_folder = chooser.get_current_folder();
752 SoundFileBrowser::run ()
761 gtk_main_iteration ();
768 SoundFileBrowser::set_action_sensitive (bool yn)
770 import_button.set_sensitive (yn);
774 SoundFileBrowser::do_something (int action)
781 SoundFileBrowser::on_show ()
783 ArdourWindow::on_show ();
788 SoundFileBrowser::clear_selection ()
790 chooser.unselect_all ();
791 found_list_view.get_selection()->unselect_all ();
795 SoundFileBrowser::chooser_file_activated ()
801 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
807 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
813 SoundFileBrowser::set_session (Session* s)
815 ArdourWindow::set_session (s);
816 preview.set_session (s);
821 remove_gain_meter ();
826 SoundFileBrowser::add_gain_meter ()
830 gm = new GainMeter (_session, 250);
832 boost::shared_ptr<Route> r = _session->the_auditioner ();
834 gm->set_controls (r, r->shared_peak_meter(), r->amp());
835 gm->set_fader_name (X_("GainFader"));
837 meter_packer.set_border_width (12);
838 meter_packer.pack_start (*gm, false, true);
839 hpacker.pack_end (meter_packer, false, false);
840 meter_packer.show_all ();
845 SoundFileBrowser::remove_gain_meter ()
848 meter_packer.remove (*gm);
849 hpacker.remove (meter_packer);
856 SoundFileBrowser::start_metering ()
858 metering_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
862 SoundFileBrowser::stop_metering ()
864 metering_connection.disconnect();
868 SoundFileBrowser::meter ()
870 if (is_mapped () && _session && gm) {
871 gm->update_meters ();
876 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
878 return AudioFileSource::safe_audio_file_extension (filter_info.filename);
882 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
884 return SMFSource::safe_midi_file_extension (filter_info.filename);
888 SoundFileBrowser::on_audio_and_midi_filter (const FileFilter::Info& filter_info)
890 return on_audio_filter (filter_info) || on_midi_filter (filter_info);
894 SoundFileBrowser::update_preview ()
896 if (preview.setup_labels (chooser.get_preview_filename())) {
897 if (preview.autoplay()) {
898 Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
904 SoundFileBrowser::found_list_view_selected ()
906 if (!reset_options ()) {
907 set_action_sensitive (false);
911 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
914 TreeIter iter = found_list->get_iter(*rows.begin());
915 file = (*iter)[found_list_columns.pathname];
916 chooser.set_filename (file);
917 set_action_sensitive (true);
919 set_action_sensitive (false);
922 preview.setup_labels (file);
927 SoundFileBrowser::found_search_clicked ()
929 string tag_string = found_entry.get_text ();
933 if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
934 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
938 vector<string> results;
939 Library->search_members_and (results, tags);
942 for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
943 TreeModel::iterator new_row = found_list->append();
944 TreeModel::Row row = *new_row;
945 string path = Glib::filename_from_uri (string ("file:") + *i);
946 row[found_list_columns.pathname] = path;
952 SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
955 Mootcher *mootcher = new Mootcher;
958 string id = (*iter)[freesound_list_columns.id];
959 string uri = (*iter)[freesound_list_columns.uri];
960 string ofn = (*iter)[freesound_list_columns.filename];
962 if (mootcher->checkAudioFile(ofn, id)) {
963 // file already exists, no need to download it again
964 file = mootcher->audioFileName;
966 (*iter)[freesound_list_columns.started] = false;
969 if (!(*iter)[freesound_list_columns.started]) {
970 // start downloading the sound file
971 (*iter)[freesound_list_columns.started] = true;
972 mootcher->fetchAudioFile(ofn, id, uri, this);
978 SoundFileBrowser::freesound_list_view_selected ()
981 if (!reset_options ()) {
982 set_action_sensitive (false);
985 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
986 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
987 file = freesound_get_audio_file (freesound_list->get_iter(*i));
990 switch (rows.size()) {
993 freesound_similar_btn.set_sensitive(false);
994 set_action_sensitive (false);
997 // exactly one item selected
999 // file exists on disk already
1000 chooser.set_filename (file);
1001 preview.setup_labels (file);
1002 set_action_sensitive (true);
1004 freesound_similar_btn.set_sensitive(true);
1007 // multiple items selected
1008 preview.setup_labels ("");
1009 freesound_similar_btn.set_sensitive(false);
1017 SoundFileBrowser::refresh_display(std::string ID, std::string file)
1019 // called when the mootcher has finished downloading a file
1020 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1021 if (rows.size() == 1) {
1022 // there's a single item selected in the freesound list
1023 //XXX make a function to be used to construct the actual file name both here and in the mootcher
1024 Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
1025 std::string selected_ID = (*row)[freesound_list_columns.id];
1026 if (ID == selected_ID) {
1027 // the selected item in the freesound list is the item that has just finished downloading
1028 chooser.set_filename(file);
1029 preview.setup_labels (file);
1030 set_action_sensitive (true);
1036 SoundFileBrowser::freesound_search_clicked ()
1039 freesound_list->clear();
1045 SoundFileBrowser::freesound_more_clicked ()
1050 snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
1051 freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
1055 SoundFileBrowser::freesound_similar_clicked ()
1057 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1058 if (rows.size() == 1) {
1061 Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
1062 id = (*iter)[freesound_list_columns.id];
1063 freesound_list->clear();
1065 GdkCursor *prev_cursor;
1066 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1067 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1070 std::string theString = mootcher.searchSimilar(id);
1072 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1073 handle_freesound_results(theString);
1078 SoundFileBrowser::freesound_search()
1082 string search_string = freesound_entry.get_text ();
1083 enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
1085 GdkCursor *prev_cursor;
1086 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
1087 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
1090 std::string theString = mootcher.searchText(
1094 "", // OSX eats anything incl mp3
1096 "type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
1101 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
1102 handle_freesound_results(theString);
1106 SoundFileBrowser::handle_freesound_results(std::string theString) {
1108 doc.read_buffer( theString );
1109 XMLNode *root = doc.root();
1112 error << "no root XML node!" << endmsg;
1116 if ( strcmp(root->name().c_str(), "response") != 0) {
1117 error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
1121 // find out how many pages are available to search
1122 int freesound_n_pages = 1;
1123 XMLNode *res = root->child("num_pages");
1125 string result = res->child("text")->content();
1126 freesound_n_pages = atoi(result);
1129 int more_pages = freesound_n_pages - freesound_page;
1131 if (more_pages > 0) {
1132 freesound_more_btn.set_sensitive(true);
1133 freesound_more_btn.set_tooltip_text(string_compose(P_(
1134 "%1 more page of 100 results available",
1135 "%1 more pages of 100 results available",
1136 more_pages), more_pages));
1138 freesound_more_btn.set_sensitive(false);
1139 freesound_more_btn.set_tooltip_text(_("No more results available"));
1142 XMLNode *sounds_root = root->child("sounds");
1144 error << "no child node \"sounds\" found!" << endmsg;
1148 XMLNodeList sounds = sounds_root->children();
1149 if (sounds.size() == 0) {
1154 XMLNodeConstIterator niter;
1156 for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
1158 if( strcmp( node->name().c_str(), "resource") != 0 ) {
1159 error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
1163 // node->dump(cerr, "node:");
1166 XMLNode *id_node = node->child ("id");
1167 XMLNode *uri_node = node->child ("serve");
1168 XMLNode *ofn_node = node->child ("original_filename");
1169 XMLNode *dur_node = node->child ("duration");
1170 XMLNode *siz_node = node->child ("filesize");
1171 XMLNode *srt_node = node->child ("samplerate");
1172 XMLNode *lic_node = node->child ("license");
1174 if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
1176 std::string id = id_node->child("text")->content();
1177 std::string uri = uri_node->child("text")->content();
1178 std::string ofn = ofn_node->child("text")->content();
1179 std::string dur = dur_node->child("text")->content();
1180 std::string siz = siz_node->child("text")->content();
1181 std::string srt = srt_node->child("text")->content();
1182 std::string lic = lic_node->child("text")->content();
1185 // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
1187 double duration_seconds = atof(dur);
1189 char duration_hhmmss[16];
1190 if (duration_seconds >= 99 * 60 * 60) {
1191 strcpy(duration_hhmmss, ">99h");
1193 s = modf(duration_seconds/60, &m) * 60;
1194 m = modf(m/60, &h) * 60;
1195 sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
1200 double size_bytes = atof(siz);
1202 if (size_bytes < 1000) {
1203 sprintf(bsize, "%.0f %s", size_bytes, _("B"));
1204 } else if (size_bytes < 1000000 ) {
1205 sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
1206 } else if (size_bytes < 10000000) {
1207 sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
1208 } else if (size_bytes < 1000000000) {
1209 sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
1211 sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
1214 /* see http://www.freesound.org/help/faq/#licenses */
1215 char shortlicense[64];
1216 if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
1217 sprintf(shortlicense, "CC-BY-NC");
1218 } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
1219 sprintf(shortlicense, "CC-BY");
1220 } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
1221 sprintf(shortlicense, "sampling+");
1222 } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
1223 sprintf(shortlicense, "PD");
1225 snprintf(shortlicense, 64, "%s", lic.c_str());
1226 shortlicense[63]= '\0';
1229 TreeModel::iterator new_row = freesound_list->append();
1230 TreeModel::Row row = *new_row;
1232 row[freesound_list_columns.id ] = id;
1233 row[freesound_list_columns.uri ] = uri;
1234 row[freesound_list_columns.filename] = ofn;
1235 row[freesound_list_columns.duration] = duration_hhmmss;
1236 row[freesound_list_columns.filesize] = bsize;
1237 row[freesound_list_columns.smplrate] = srt;
1238 row[freesound_list_columns.license ] = shortlicense;
1245 SoundFileBrowser::get_paths ()
1247 vector<string> results;
1249 int n = notebook.get_current_page ();
1252 vector<string> filenames = chooser.get_filenames();
1253 vector<string>::iterator i;
1255 for (i = filenames.begin(); i != filenames.end(); ++i) {
1257 if ((!g_stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
1258 results.push_back (*i);
1262 } else if (n == 1) {
1264 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1265 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1266 TreeIter iter = found_list->get_iter(*i);
1267 string str = (*iter)[found_list_columns.pathname];
1269 results.push_back (str);
1272 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1273 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1274 string str = freesound_get_audio_file (freesound_list->get_iter(*i));
1276 results.push_back (str);
1285 SoundFileOmega::reset_options_noret ()
1287 if (!resetting_ourselves) {
1288 (void) reset_options ();
1293 SoundFileOmega::reset_options ()
1295 vector<string> paths = get_paths ();
1297 if (paths.empty()) {
1299 channel_combo.set_sensitive (false);
1300 action_combo.set_sensitive (false);
1301 where_combo.set_sensitive (false);
1302 copy_files_btn.set_active (true);
1303 copy_files_btn.set_sensitive (false);
1309 channel_combo.set_sensitive (true);
1310 action_combo.set_sensitive (true);
1311 where_combo.set_sensitive (true);
1313 /* if we get through this function successfully, this may be
1314 reset at the end, once we know if we can use hard links
1315 to do embedding (or if we are importing a MIDI file).
1318 if (ARDOUR_UI::config()->get_only_copy_imported_files()) {
1319 copy_files_btn.set_sensitive (false);
1321 copy_files_btn.set_sensitive (false);
1327 bool selection_includes_multichannel;
1328 bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1331 /* See if we are thinking about importing any MIDI files */
1332 vector<string>::iterator i = paths.begin ();
1333 while (i != paths.end() && SMFSource::valid_midi_file (*i) == false) {
1336 bool const have_a_midi_file = (i != paths.end ());
1338 if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1339 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1343 string existing_choice;
1344 vector<string> action_strings;
1346 resetting_ourselves = true;
1348 if (chooser.get_filter() == &audio_filter) {
1352 if (selected_audio_track_cnt > 0) {
1353 if (channel_combo.get_active_text().length()) {
1354 ImportDisposition id = get_channel_disposition();
1357 case Editing::ImportDistinctFiles:
1358 if (selected_audio_track_cnt == paths.size()) {
1359 action_strings.push_back (importmode2string (ImportToTrack));
1363 case Editing::ImportDistinctChannels:
1364 /* XXX it would be nice to allow channel-per-selected track
1365 but its too hard we don't want to deal with all the
1366 different per-file + per-track channel configurations.
1371 action_strings.push_back (importmode2string (ImportToTrack));
1381 if (selected_midi_track_cnt > 0) {
1382 action_strings.push_back (importmode2string (ImportToTrack));
1386 action_strings.push_back (importmode2string (ImportAsTrack));
1387 action_strings.push_back (importmode2string (ImportAsRegion));
1388 action_strings.push_back (importmode2string (ImportAsTapeTrack));
1390 existing_choice = action_combo.get_active_text();
1392 set_popdown_strings (action_combo, action_strings);
1394 /* preserve any existing choice, if possible */
1397 if (existing_choice.length()) {
1398 vector<string>::iterator x;
1399 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1400 if (*x == existing_choice) {
1401 action_combo.set_active_text (existing_choice);
1405 if (x == action_strings.end()) {
1406 action_combo.set_active_text (action_strings.front());
1409 action_combo.set_active_text (action_strings.front());
1412 resetting_ourselves = false;
1414 if ((mode = get_mode()) == ImportAsRegion) {
1415 where_combo.set_sensitive (false);
1417 where_combo.set_sensitive (true);
1420 vector<string> channel_strings;
1422 if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1423 channel_strings.push_back (_("one track per file"));
1425 if (selection_includes_multichannel) {
1426 channel_strings.push_back (_("one track per channel"));
1429 if (paths.size() > 1) {
1430 /* tape tracks are a single region per track, so we cannot
1431 sequence multiple files.
1433 if (mode != ImportAsTapeTrack) {
1434 channel_strings.push_back (_("sequence files"));
1437 channel_strings.push_back (_("all files in one track"));
1438 channel_strings.push_back (_("merge files"));
1444 channel_strings.push_back (_("one region per file"));
1446 if (selection_includes_multichannel) {
1447 channel_strings.push_back (_("one region per channel"));
1450 if (paths.size() > 1) {
1452 channel_strings.push_back (_("all files in one region"));
1457 resetting_ourselves = true;
1459 existing_choice = channel_combo.get_active_text();
1461 set_popdown_strings (channel_combo, channel_strings);
1463 /* preserve any existing choice, if possible */
1465 if (existing_choice.length()) {
1466 vector<string>::iterator x;
1467 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1468 if (*x == existing_choice) {
1469 channel_combo.set_active_text (existing_choice);
1473 if (x == channel_strings.end()) {
1474 channel_combo.set_active_text (channel_strings.front());
1477 channel_combo.set_active_text (channel_strings.front());
1480 resetting_ourselves = false;
1483 src_combo.set_sensitive (true);
1485 src_combo.set_sensitive (false);
1488 /* We must copy MIDI files or those from Freesound
1489 * or any file if we are under nsm control */
1490 bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
1492 if (ARDOUR_UI::config()->get_only_copy_imported_files()) {
1494 if (selection_can_be_embedded_with_links && !must_copy) {
1495 copy_files_btn.set_sensitive (true);
1498 copy_files_btn.set_active (true);
1500 copy_files_btn.set_sensitive (false);
1506 copy_files_btn.set_active (true);
1508 copy_files_btn.set_sensitive (!must_copy);
1516 SoundFileOmega::bad_file_message()
1518 MessageDialog msg (*this,
1519 string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1524 resetting_ourselves = true;
1525 chooser.unselect_uri (chooser.get_preview_uri());
1526 resetting_ourselves = false;
1532 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1541 multichannel = false;
1543 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1545 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1546 if (info.channels > 1) {
1547 multichannel = true;
1552 if (sz != info.length) {
1557 if (info.samplerate != _session->frame_rate()) {
1561 } else if (SMFSource::valid_midi_file (*i)) {
1565 if (reader.num_tracks() > 1) {
1566 multichannel = true; // "channel" == track here...
1569 /* XXX we need err = true handling here in case
1570 we can't check the file
1583 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1585 #ifdef PLATFORM_WINDOWS
1588 std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
1591 if (g_mkdir (tmpdir.c_str(), 0744)) {
1592 if (errno != EEXIST) {
1597 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1599 char tmpc[PATH_MAX+1];
1601 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1605 if (link ((*i).c_str(), tmpc)) {
1615 g_rmdir (tmpdir.c_str());
1620 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
1621 : SoundFileBrowser (title, s, false)
1623 chooser.set_select_multiple (false);
1624 found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1625 freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1629 SoundFileChooser::on_hide ()
1631 ArdourWindow::on_hide();
1635 _session->cancel_audition();
1640 SoundFileChooser::get_filename ()
1642 vector<string> paths;
1644 paths = get_paths ();
1646 if (paths.empty()) {
1650 if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1654 return paths.front();
1657 SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s,
1658 uint32_t selected_audio_tracks,
1659 uint32_t selected_midi_tracks,
1661 Editing::ImportMode mode_hint)
1662 : SoundFileBrowser (title, s, persistent)
1663 , copy_files_btn ( _("Copy files to session"))
1664 , selected_audio_track_cnt (selected_audio_tracks)
1665 , selected_midi_track_cnt (selected_midi_tracks)
1671 set_size_request (-1, 450);
1673 block_two.set_border_width (12);
1674 block_three.set_border_width (12);
1675 block_four.set_border_width (12);
1677 options.set_spacing (12);
1680 str.push_back (_("file timestamp"));
1681 str.push_back (_("edit point"));
1682 str.push_back (_("playhead"));
1683 str.push_back (_("session start"));
1684 set_popdown_strings (where_combo, str);
1685 where_combo.set_active_text (str.front());
1686 where_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::where_combo_changed));
1688 Label* l = manage (new Label);
1689 l->set_markup (_("<b>Add files as ...</b>"));
1691 vbox = manage (new VBox);
1692 vbox->set_border_width (12);
1693 vbox->set_spacing (6);
1694 vbox->pack_start (*l, false, false);
1695 vbox->pack_start (action_combo, false, false);
1696 hbox = manage (new HBox);
1697 hbox->pack_start (*vbox, false, false);
1698 options.pack_start (*hbox, false, false);
1700 /* dummy entry for action combo so that it doesn't look odd if we
1701 come up with no tracks selected.
1705 str.push_back (importmode2string (mode_hint));
1706 set_popdown_strings (action_combo, str);
1707 action_combo.set_active_text (str.front());
1708 action_combo.set_sensitive (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));
1779 action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1780 channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1782 copy_files_btn.set_active (true);
1784 Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1787 copy_label->set_size_request (175, -1);
1788 copy_label->set_line_wrap (true);
1791 block_four.pack_start (copy_files_btn, false, false);
1793 options.pack_start (block_four, false, false);
1795 vpacker.pack_start (options, false, false);
1797 /* setup disposition map */
1799 disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1800 disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1801 disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1802 disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1804 disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1805 disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1806 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1807 disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1809 chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1811 /* set size requests for a couple of combos to allow them to display the longest text
1812 they will ever be asked to display. This prevents them being resized when the user
1813 selects a file to import, which in turn prevents the size of the dialog from jumping
1817 t.push_back (_("one track per file"));
1818 t.push_back (_("one track per channel"));
1819 t.push_back (_("sequence files"));
1820 t.push_back (_("all files in one region"));
1821 set_popdown_strings (channel_combo, t);
1824 t.push_back (importmode2string (ImportAsTrack));
1825 t.push_back (importmode2string (ImportToTrack));
1826 t.push_back (importmode2string (ImportAsRegion));
1827 t.push_back (importmode2string (ImportAsTapeTrack));
1828 set_popdown_strings (action_combo, t);
1832 SoundFileOmega::set_mode (ImportMode mode)
1834 action_combo.set_active_text (importmode2string (mode));
1838 SoundFileOmega::get_mode () const
1840 return string2importmode (action_combo.get_active_text());
1844 SoundFileOmega::on_hide ()
1846 ArdourWindow::on_hide();
1848 _session->cancel_audition();
1853 SoundFileOmega::get_position() const
1855 string str = where_combo.get_active_text();
1857 if (str == _("file timestamp")) {
1858 return ImportAtTimestamp;
1859 } else if (str == _("edit point")) {
1860 return ImportAtEditPoint;
1861 } else if (str == _("playhead")) {
1862 return ImportAtPlayhead;
1864 return ImportAtStart;
1869 SoundFileOmega::get_src_quality() const
1871 string str = src_combo.get_active_text();
1873 if (str == _("Best")) {
1875 } else if (str == _("Good")) {
1877 } else if (str == _("Quick")) {
1879 } else if (str == _("Fast")) {
1887 SoundFileOmega::src_combo_changed()
1889 preview.set_src_quality(get_src_quality());
1893 SoundFileOmega::where_combo_changed()
1895 preview.set_import_position(get_position());
1899 SoundFileOmega::get_channel_disposition () const
1901 /* we use a map here because the channel combo can contain different strings
1902 depending on the state of the other combos. the map contains all possible strings
1903 and the ImportDisposition enum that corresponds to it.
1906 string str = channel_combo.get_active_text();
1907 DispositionMap::const_iterator x = disposition_map.find (str);
1909 if (x == disposition_map.end()) {
1910 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1911 abort(); /*NOTREACHED*/
1918 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
1920 selected_audio_track_cnt = selected_audio_tracks;
1921 selected_midi_track_cnt = selected_midi_tracks;
1923 if (selected_audio_track_cnt == 0 && selected_midi_track_cnt > 0) {
1924 chooser.set_filter (midi_filter);
1925 } else if (selected_midi_track_cnt == 0 && selected_audio_track_cnt > 0) {
1926 chooser.set_filter (audio_filter);
1928 chooser.set_filter (audio_and_midi_filter);
1935 SoundFileOmega::file_selection_changed ()
1937 if (resetting_ourselves) {
1941 if (!reset_options ()) {
1942 set_action_sensitive (false);
1944 if (chooser.get_filenames().size() > 0) {
1945 set_action_sensitive (true);
1947 set_action_sensitive (false);
1953 SoundFileOmega::do_something (int action)
1955 SoundFileBrowser::do_something (action);
1957 if (action == RESPONSE_CLOSE) {
1964 vector<string> paths = get_paths ();
1965 ImportPosition pos = get_position ();
1966 ImportMode mode = get_mode ();
1967 ImportDisposition chns = get_channel_disposition ();
1968 PluginInfoPtr instrument = instrument_combo.selected_instrument();
1972 case ImportAtEditPoint:
1973 where = PublicEditor::instance().get_preferred_edit_position ();
1975 case ImportAtTimestamp:
1978 case ImportAtPlayhead:
1979 where = _session->transport_frame();
1982 where = _session->current_start_frame();
1986 SrcQuality quality = get_src_quality();
1988 if (copy_files_btn.get_active()) {
1989 PublicEditor::instance().do_import (paths, chns, mode, quality, where, instrument);
1991 PublicEditor::instance().do_embed (paths, chns, mode, where, instrument);