fix #5609 (import with 1 track per channel mis-associates tracks + channels)
[ardour.git] / gtk2_ardour / sfdb_ui.cc
1 /*
2     Copyright (C) 2005-2006 Paul Davis
3
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.
8
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.
13
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.
17
18 */
19
20 #ifdef WAF_BUILD
21 #include "gtk2ardour-config.h"
22 #endif
23
24 #include <map>
25 #include <cerrno>
26 #include <sstream>
27
28 #include <unistd.h>
29 #include <sys/stat.h>
30 #include <sys/param.h>
31
32 #include <gtkmm/box.h>
33 #include <gtkmm/stock.h>
34 #include <glibmm/fileutils.h>
35
36 #include "pbd/convert.h"
37 #include "pbd/tokenizer.h"
38 #include "pbd/enumwriter.h"
39 #include "pbd/pthread_utils.h"
40 #include "pbd/xml++.h"
41
42 #include <gtkmm2ext/utils.h>
43
44 #include "evoral/SMF.hpp"
45
46 #include "ardour/audio_library.h"
47 #include "ardour/auditioner.h"
48 #include "ardour/audioregion.h"
49 #include "ardour/audiofilesource.h"
50 #include "ardour/smf_source.h"
51 #include "ardour/region_factory.h"
52 #include "ardour/source_factory.h"
53 #include "ardour/session.h"
54 #include "ardour/session_directory.h"
55
56 #include "ardour_ui.h"
57 #include "editing.h"
58 #include "gui_thread.h"
59 #include "prompter.h"
60 #include "sfdb_ui.h"
61 #include "editing.h"
62 #include "utils.h"
63 #include "gain_meter.h"
64 #include "main_clock.h"
65 #include "public_editor.h"
66
67 #ifdef FREESOUND
68 #include "sfdb_freesound_mootcher.h"
69 #endif
70
71 #include "i18n.h"
72
73 using namespace ARDOUR;
74 using namespace PBD;
75 using namespace std;
76 using namespace Gtk;
77 using namespace Gtkmm2ext;
78 using namespace Editing;
79
80 using std::string;
81
82 string SoundFileBrowser::persistent_folder;
83 typedef TreeView::Selection::ListHandle_Path ListPath;
84
85 static ImportMode
86 string2importmode (string str)
87 {
88         if (str == _("as new tracks")) {
89                 return ImportAsTrack;
90         } else if (str == _("to selected tracks")) {
91                 return ImportToTrack;
92         } else if (str == _("to region list")) {
93                 return ImportAsRegion;
94         } else if (str == _("as new tape tracks")) {
95                 return ImportAsTapeTrack;
96         }
97
98         warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
99
100         return ImportAsTrack;
101 }
102
103 static string
104 importmode2string (ImportMode mode)
105 {
106         switch (mode) {
107         case ImportAsTrack:
108                 return _("as new tracks");
109         case ImportToTrack:
110                 return _("to selected tracks");
111         case ImportAsRegion:
112                 return _("to region list");
113         case ImportAsTapeTrack:
114                 return _("as new tape tracks");
115         }
116         /*NOTREACHED*/
117         return _("as new tracks");
118 }
119
120 SoundFileBox::SoundFileBox (bool persistent)
121         : table (6, 2),
122           length_clock ("sfboxLengthClock", !persistent, "", false, false, true, false),
123           timecode_clock ("sfboxTimecodeClock", !persistent, "", false, false, false, false),
124           main_box (false, 6),
125           autoplay_btn (_("Auto-play"))
126
127 {
128         set_name (X_("SoundFileBox"));
129         set_size_request (300, -1);
130
131         preview_label.set_markup (_("<b>Sound File Information</b>"));
132
133         border_frame.set_label_widget (preview_label);
134         border_frame.add (main_box);
135
136         pack_start (border_frame, true, true);
137         set_border_width (6);
138
139         main_box.set_border_width (6);
140
141         length.set_text (_("Length:"));
142         length.set_alignment (1, 0.5);
143         timecode.set_text (_("Timestamp:"));
144         timecode.set_alignment (1, 0.5);
145         format.set_text (_("Format:"));
146         format.set_alignment (1, 0.5);
147         channels.set_text (_("Channels:"));
148         channels.set_alignment (1, 0.5);
149         samplerate.set_text (_("Sample rate:"));
150         samplerate.set_alignment (1, 0.5);
151
152         preview_label.set_max_width_chars (50);
153         preview_label.set_ellipsize (Pango::ELLIPSIZE_END);
154
155         format_text.set_max_width_chars (20);
156         format_text.set_ellipsize (Pango::ELLIPSIZE_END);
157         format_text.set_alignment (0, 1);
158
159         table.set_col_spacings (6);
160         table.set_homogeneous (false);
161         table.set_row_spacings (6);
162
163         table.attach (channels, 0, 1, 0, 1, FILL, FILL);
164         table.attach (samplerate, 0, 1, 1, 2, FILL, FILL);
165         table.attach (format, 0, 1, 2, 4, FILL, FILL);
166         table.attach (length, 0, 1, 4, 5, FILL, FILL);
167         table.attach (timecode, 0, 1, 5, 6, FILL, FILL);
168
169         table.attach (channels_value, 1, 2, 0, 1, FILL, FILL);
170         table.attach (samplerate_value, 1, 2, 1, 2, FILL, FILL);
171         table.attach (format_text, 1, 2, 2, 4, FILL, FILL);
172         table.attach (length_clock, 1, 2, 4, 5, FILL, FILL);
173         table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL);
174
175         length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock->mode());
176         timecode_clock.set_mode (AudioClock::Timecode);
177
178         main_box.pack_start (table, false, false);
179
180         tags_entry.set_editable (true);
181         tags_entry.set_wrap_mode(Gtk::WRAP_WORD);
182         tags_entry.signal_focus_out_event().connect (sigc::mem_fun (*this, &SoundFileBox::tags_entry_left));
183
184         Label* label = manage (new Label (_("Tags:")));
185         label->set_alignment (0.0f, 0.5f);
186         main_box.pack_start (*label, false, false);
187         main_box.pack_start (tags_entry, true, true);
188
189         main_box.pack_start (bottom_box, false, false);
190
191         play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
192 //      play_btn.set_label (_("Play"));
193
194         stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
195 //      stop_btn.set_label (_("Stop"));
196
197         bottom_box.set_homogeneous (false);
198         bottom_box.set_spacing (6);
199         bottom_box.pack_start(play_btn, true, true);
200         bottom_box.pack_start(stop_btn, true, true);
201         bottom_box.pack_start(autoplay_btn, false, false);
202
203         play_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::audition));
204         stop_btn.signal_clicked().connect (sigc::mem_fun (*this, &SoundFileBox::stop_audition));
205
206         channels_value.set_alignment (0.0f, 0.5f);
207         samplerate_value.set_alignment (0.0f, 0.5f);
208 }
209
210 void
211 SoundFileBox::set_session(Session* s)
212 {
213         SessionHandlePtr::set_session (s);
214
215         length_clock.set_session (s);
216         timecode_clock.set_session (s);
217
218         if (!_session) {
219                 play_btn.set_sensitive (false);
220                 stop_btn.set_sensitive (false);
221         }
222 }
223
224 bool
225 SoundFileBox::setup_labels (const string& filename)
226 {
227         if (!path.empty()) {
228                 // save existing tags
229                 tags_changed ();
230         }
231
232         path = filename;
233
234         string error_msg;
235
236         if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
237
238                 preview_label.set_markup (_("<b>Sound File Information</b>"));
239                 format_text.set_text ("");
240                 channels_value.set_text ("");
241                 samplerate_value.set_text ("");
242                 tags_entry.get_buffer()->set_text ("");
243
244                 length_clock.set (0);
245                 timecode_clock.set (0);
246
247                 tags_entry.set_sensitive (false);
248                 play_btn.set_sensitive (false);
249
250                 return false;
251         }
252
253         preview_label.set_markup (string_compose ("<b>%1</b>", Glib::Markup::escape_text (Glib::path_get_basename (filename))));
254         std::string n = sf_info.format_name;
255         if (n.substr (0, 8) == X_("Format: ")) {
256                 n = n.substr (8);
257         }
258         format_text.set_text (n);
259         channels_value.set_text (to_string (sf_info.channels, std::dec));
260
261         if (_session && sf_info.samplerate != _session->frame_rate()) {
262                 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
263                 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
264                 samplerate_value.set_name ("NewSessionSR1Label");
265                 samplerate.set_name ("NewSessionSR1Label");
266         } else {
267                 samplerate.set_text (_("Sample rate:"));
268                 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
269                 samplerate_value.set_name ("NewSessionSR2Label");
270                 samplerate.set_name ("NewSessionSR2Label");
271         }
272
273         framecnt_t const nfr = _session ? _session->nominal_frame_rate() : 25;
274         double src_coef = (double) nfr / sf_info.samplerate;
275
276         length_clock.set (sf_info.length * src_coef + 0.5, true);
277         timecode_clock.set (sf_info.timecode * src_coef + 0.5, true);
278
279         // this is a hack that is fixed in trunk, i think (august 26th, 2007)
280
281         vector<string> tags = Library->get_tags (string ("//") + filename);
282
283         stringstream tag_string;
284         for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
285                 if (i != tags.begin()) {
286                         tag_string << ", ";
287                 }
288                 tag_string << *i;
289         }
290         tags_entry.get_buffer()->set_text (tag_string.str());
291
292         tags_entry.set_sensitive (true);
293         if (_session) {
294                 play_btn.set_sensitive (true);
295         }
296
297         return true;
298 }
299
300 bool
301 SoundFileBox::autoplay() const
302 {
303         return autoplay_btn.get_active();
304 }
305
306 bool
307 SoundFileBox::audition_oneshot()
308 {
309         audition ();
310         return false;
311 }
312
313 void
314 SoundFileBox::audition ()
315 {
316         if (!_session) {
317                 return;
318         }
319
320         if (SMFSource::safe_midi_file_extension (path)) {
321                 error << _("Auditioning of MIDI files is not yet supported") << endmsg;
322                 return;
323         }
324
325         _session->cancel_audition();
326
327         if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
328                 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
329                 return;
330         }
331
332         boost::shared_ptr<Region> r;
333         SourceList srclist;
334         boost::shared_ptr<AudioFileSource> afs;
335         bool old_sbp = AudioSource::get_build_peakfiles ();
336
337         /* don't even think of building peakfiles for these files */
338
339         AudioSource::set_build_peakfiles (false);
340
341         for (int n = 0; n < sf_info.channels; ++n) {
342                 try {
343                         afs = boost::dynamic_pointer_cast<AudioFileSource> (
344                                 SourceFactory::createExternal (DataType::AUDIO, *_session,
345                                                                path, n,
346                                                                Source::Flag (0), false));
347                         
348                         srclist.push_back(afs);
349
350                 } catch (failed_constructor& err) {
351                         error << _("Could not access soundfile: ") << path << endmsg;
352                         AudioSource::set_build_peakfiles (old_sbp);
353                         return;
354                 }
355         }
356
357         AudioSource::set_build_peakfiles (old_sbp);
358
359         if (srclist.empty()) {
360                 return;
361         }
362
363         afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
364         string rname = region_name_from_path (afs->path(), false);
365
366         PropertyList plist;
367
368         plist.add (ARDOUR::Properties::start, 0);
369         plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->timeline_position()));
370         plist.add (ARDOUR::Properties::name, rname);
371         plist.add (ARDOUR::Properties::layer, 0);
372
373         r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false));
374
375         _session->audition_region(r);
376 }
377
378 void
379 SoundFileBox::stop_audition ()
380 {
381         if (_session) {
382                 _session->cancel_audition();
383         }
384 }
385
386 bool
387 SoundFileBox::tags_entry_left (GdkEventFocus *)
388 {
389         tags_changed ();
390         return false;
391 }
392
393 void
394 SoundFileBox::tags_changed ()
395 {
396         string tag_string = tags_entry.get_buffer()->get_text ();
397
398         if (tag_string.empty()) {
399                 return;
400         }
401
402         vector<string> tags;
403
404         if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
405                 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
406                 return;
407         }
408
409         save_tags (tags);
410 }
411
412 void
413 SoundFileBox::save_tags (const vector<string>& tags)
414 {
415         Library->set_tags (string ("//") + path, tags);
416         Library->save_changes ();
417 }
418
419 SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persistent)
420         : ArdourWindow (title)
421         , found_list (ListStore::create(found_list_columns))
422         , freesound_list (ListStore::create(freesound_list_columns))
423         , chooser (FILE_CHOOSER_ACTION_OPEN)
424         , preview (persistent)
425         , found_search_btn (_("Search"))
426         , found_list_view (found_list)
427         , freesound_search_btn (_("Search"))
428         , freesound_list_view (freesound_list)
429         , resetting_ourselves (false)
430         , matches (0)
431         , _status (0)
432         , _done (false)
433         , ok_button (Stock::OK)
434         , cancel_button (Stock::CANCEL)
435         , apply_button (Stock::APPLY)
436         , gm (0)
437 {
438
439 #ifdef GTKOSX
440         chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
441         chooser.add_shortcut_folder_uri("file:///Library/Audio/Apple Loops");
442         chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
443         chooser.add_shortcut_folder_uri("file:///Volumes");
444 #endif
445
446         //add the file chooser
447
448         chooser.set_border_width (12);
449         
450         audio_and_midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun (*this, &SoundFileBrowser::on_audio_and_midi_filter));
451         audio_and_midi_filter.set_name (_("Audio and MIDI files"));
452         
453         audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
454         audio_filter.set_name (_("Audio files"));
455         
456         midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
457         midi_filter.set_name (_("MIDI files"));
458         
459         matchall_filter.add_pattern ("*.*");
460         matchall_filter.set_name (_("All files"));
461         
462         chooser.add_filter (audio_and_midi_filter);
463         chooser.add_filter (audio_filter);
464         chooser.add_filter (midi_filter);
465         chooser.add_filter (matchall_filter);
466         chooser.set_select_multiple (true);
467         chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
468         chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
469
470 #ifdef GTKOSX
471         /* some broken redraw behaviour - this is a bandaid */
472         chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
473 #endif
474         
475         if (!persistent_folder.empty()) {
476                 chooser.set_current_folder (persistent_folder);
477         }
478
479         notebook.append_page (chooser, _("Browse Files"));
480         
481         hpacker.set_spacing (6);
482         hpacker.pack_start (notebook, true, true);
483         hpacker.pack_start (preview, false, false);
484
485         vpacker.set_spacing (6);
486         vpacker.pack_start (hpacker, true, true);
487
488         add (vpacker);
489
490         //add tag search
491
492         VBox* vbox;
493         HBox* hbox;
494         
495         
496         hbox = manage(new HBox);
497         hbox->pack_start (found_entry);
498         hbox->pack_start (found_search_btn);
499         
500         Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
501         scroll->add(found_list_view);
502         scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
503         
504         vbox = manage(new VBox);
505         vbox->pack_start (*hbox, PACK_SHRINK);
506         vbox->pack_start (*scroll);
507         
508         found_list_view.append_column(_("Paths"), found_list_columns.pathname);
509         
510         found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
511         
512         found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
513         
514         found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
515         found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
516         
517         notebook.append_page (*vbox, _("Search Tags"));
518
519 #ifdef FREESOUND
520
521         //add freesound search
522
523         HBox* passbox;
524         Label* label;
525         
526         passbox = manage(new HBox);
527         passbox->set_spacing (6);
528         
529         label = manage (new Label);
530         label->set_text (_("Tags:"));
531         passbox->pack_start (*label, false, false);
532         passbox->pack_start (freesound_entry, true, true);
533         
534         label = manage (new Label);
535         label->set_text (_("Sort:"));
536         passbox->pack_start (*label, false, false);
537         passbox->pack_start (freesound_sort, false, false);
538         freesound_sort.clear_items();
539         
540         // Order of the following must correspond with enum sortMethod
541         // in sfdb_freesound_mootcher.h 
542         freesound_sort.append_text(_("None"));
543         freesound_sort.append_text(_("Longest"));
544         freesound_sort.append_text(_("Shortest"));
545         freesound_sort.append_text(_("Newest"));
546         freesound_sort.append_text(_("Oldest"));
547         freesound_sort.append_text(_("Most downloaded"));
548         freesound_sort.append_text(_("Least downloaded"));
549         freesound_sort.append_text(_("Highest rated"));
550         freesound_sort.append_text(_("Lowest rated"));
551         freesound_sort.set_active(0);
552         
553         passbox->pack_start (freesound_search_btn, false, false);
554         passbox->pack_start (freesound_more_btn, false, false);
555         freesound_more_btn.set_label(_("More"));
556         freesound_more_btn.set_sensitive(false);
557
558         passbox->pack_start (freesound_similar_btn, false, false);
559         freesound_similar_btn.set_label(_("Similar"));
560         freesound_similar_btn.set_sensitive(false);
561         
562         scroll = manage(new ScrolledWindow);
563         scroll->add(freesound_list_view);
564         scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
565         
566         vbox = manage(new VBox);
567         vbox->set_spacing (3);
568         vbox->pack_start (*passbox, PACK_SHRINK);
569         vbox->pack_start (*scroll);
570
571         freesound_list_view.append_column(_("ID")      , freesound_list_columns.id);
572         freesound_list_view.append_column(_("Filename"), freesound_list_columns.filename);
573         // freesound_list_view.append_column(_("URI")     , freesound_list_columns.uri);
574         freesound_list_view.append_column(_("Duration"), freesound_list_columns.duration);
575         freesound_list_view.append_column(_("Size"), freesound_list_columns.filesize);
576         freesound_list_view.append_column(_("Samplerate"), freesound_list_columns.smplrate);
577         freesound_list_view.append_column(_("License"), freesound_list_columns.license);
578         freesound_list_view.get_column(0)->set_alignment(0.5);
579         freesound_list_view.get_column(1)->set_expand(true); // filename
580         freesound_list_view.get_column(1)->set_resizable(true); // filename
581         freesound_list_view.get_column(2)->set_alignment(0.5);
582         freesound_list_view.get_column(3)->set_alignment(0.5);
583         freesound_list_view.get_column(4)->set_alignment(0.5);
584         freesound_list_view.get_column(5)->set_alignment(0.5);
585         
586         freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
587         freesound_list_view.set_tooltip_column(1);
588
589         freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
590         freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
591         freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
592         freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
593         freesound_more_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_more_clicked));
594         freesound_similar_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_similar_clicked));
595         notebook.append_page (*vbox, _("Search Freesound"));
596 #endif
597
598         notebook.set_size_request (500, -1);
599         notebook.signal_switch_page().connect (sigc::hide_return (sigc::hide (sigc::hide (sigc::mem_fun (*this, &SoundFileBrowser::reset_options)))));
600
601         set_session (s);
602
603         Gtk::HButtonBox* button_box = manage (new HButtonBox);
604
605         button_box->set_layout (BUTTONBOX_END);
606         button_box->pack_start (cancel_button, false, false);
607         cancel_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_CANCEL));
608         if (persistent) {
609                 button_box->pack_start (apply_button, false, false);
610                 apply_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_APPLY));
611         }
612
613         button_box->pack_start (ok_button, false, false);
614         ok_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &SoundFileBrowser::do_something), RESPONSE_OK));
615
616         Gtkmm2ext::UI::instance()->set_tip (ok_button, _("Press to import selected files and close this window"));
617         Gtkmm2ext::UI::instance()->set_tip (apply_button, _("Press to import selected files and leave this window open"));
618         Gtkmm2ext::UI::instance()->set_tip (cancel_button, _("Press to close this window without importing any files"));
619
620         vpacker.pack_end (*button_box, false, false);
621
622         set_wmclass (X_("import"), PROGRAM_NAME);
623 }
624
625 SoundFileBrowser::~SoundFileBrowser ()
626 {
627         persistent_folder = chooser.get_current_folder();
628 }
629
630 int
631 SoundFileBrowser::run ()
632 {
633         set_modal (true);
634         show_all ();
635         present ();
636
637         _done = false;
638
639         while (!_done) {
640                 gtk_main_iteration ();
641         }
642
643         return _status;
644 }
645
646 void
647 SoundFileBrowser::set_action_sensitive (bool yn)
648 {
649         ok_button.set_sensitive (yn);
650         apply_button.set_sensitive (yn);
651 }
652
653 void
654 SoundFileBrowser::do_something (int action)
655 {
656         _done = true;
657         _status = action;
658 }
659
660 void
661 SoundFileBrowser::on_show ()
662 {
663         ArdourWindow::on_show ();
664         start_metering ();
665 }
666
667 void
668 SoundFileBrowser::clear_selection ()
669 {
670         chooser.unselect_all ();
671         found_list_view.get_selection()->unselect_all ();
672 }
673
674 void
675 SoundFileBrowser::chooser_file_activated ()
676 {
677         preview.audition ();
678 }
679
680 void
681 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
682 {
683         preview.audition ();
684 }
685
686 void
687 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
688 {
689         preview.audition ();
690 }
691
692 void
693 SoundFileBrowser::set_session (Session* s)
694 {
695         ArdourWindow::set_session (s);
696         preview.set_session (s);
697
698         if (_session) {
699                 add_gain_meter ();
700         } else {
701                 remove_gain_meter ();
702         }
703 }
704
705 void
706 SoundFileBrowser::add_gain_meter ()
707 {
708         delete gm;
709
710         gm = new GainMeter (_session, 250);
711
712         boost::shared_ptr<Route> r = _session->the_auditioner ();
713
714         gm->set_controls (r, r->shared_peak_meter(), r->amp());
715         gm->set_fader_name (X_("AudioTrackFader"));
716
717         meter_packer.set_border_width (12);
718         meter_packer.pack_start (*gm, false, true);
719         hpacker.pack_end (meter_packer, false, false);
720         meter_packer.show_all ();
721         start_metering ();
722 }
723
724 void
725 SoundFileBrowser::remove_gain_meter ()
726 {
727         if (gm) {
728                 meter_packer.remove (*gm);
729                 hpacker.remove (meter_packer);
730                 delete gm;
731                 gm = 0;
732         }
733 }
734
735 void
736 SoundFileBrowser::start_metering ()
737 {
738         metering_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
739 }
740
741 void
742 SoundFileBrowser::stop_metering ()
743 {
744         metering_connection.disconnect();
745 }
746
747 void
748 SoundFileBrowser::meter ()
749 {
750         if (is_mapped () && _session && gm) {
751                 gm->update_meters ();
752         }
753 }
754
755 bool
756 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
757 {
758         return AudioFileSource::safe_audio_file_extension (filter_info.filename);
759 }
760
761 bool
762 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
763 {
764         return SMFSource::safe_midi_file_extension (filter_info.filename);
765 }
766
767 bool
768 SoundFileBrowser::on_audio_and_midi_filter (const FileFilter::Info& filter_info)
769 {
770         return on_audio_filter (filter_info) || on_midi_filter (filter_info);
771 }
772
773 void
774 SoundFileBrowser::update_preview ()
775 {
776         if (preview.setup_labels (chooser.get_preview_filename())) {
777                 if (preview.autoplay()) {
778                         Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
779                 }
780         }
781 }
782
783 void
784 SoundFileBrowser::found_list_view_selected ()
785 {
786         if (!reset_options ()) {
787                 set_action_sensitive (false);
788         } else {
789                 string file;
790
791                 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
792
793                 if (!rows.empty()) {
794                         TreeIter iter = found_list->get_iter(*rows.begin());
795                         file = (*iter)[found_list_columns.pathname];
796                         chooser.set_filename (file);
797                         set_action_sensitive (true);
798                 } else {
799                         set_action_sensitive (false);
800                 }
801
802                 preview.setup_labels (file);
803         }
804 }
805
806 void
807 SoundFileBrowser::found_search_clicked ()
808 {
809         string tag_string = found_entry.get_text ();
810
811         vector<string> tags;
812
813         if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
814                 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
815                 return;
816         }
817
818         vector<string> results;
819         Library->search_members_and (results, tags);
820
821         found_list->clear();
822         for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
823                 TreeModel::iterator new_row = found_list->append();
824                 TreeModel::Row row = *new_row;
825                 string path = Glib::filename_from_uri (string ("file:") + *i);
826                 row[found_list_columns.pathname] = path;
827         }
828 }
829
830
831 std::string
832 SoundFileBrowser::freesound_get_audio_file(Gtk::TreeIter iter)
833 {
834
835         Mootcher *mootcher = new Mootcher;
836         std::string file;
837
838         string id  = (*iter)[freesound_list_columns.id];
839         string uri = (*iter)[freesound_list_columns.uri];
840         string ofn = (*iter)[freesound_list_columns.filename];
841
842         if (mootcher->checkAudioFile(ofn, id)) {
843                 // file already exists, no need to download it again
844                 file = mootcher->audioFileName;
845                 delete mootcher;
846                 (*iter)[freesound_list_columns.started] = false;
847                 return file;
848         }
849         if (!(*iter)[freesound_list_columns.started]) {
850                 // start downloading the sound file
851                 (*iter)[freesound_list_columns.started] = true;
852                 mootcher->fetchAudioFile(ofn, id, uri, this);
853         }
854         return "";
855 }
856
857 void
858 SoundFileBrowser::freesound_list_view_selected ()
859 {
860
861         if (!reset_options ()) {
862                 set_action_sensitive (false);
863         } else {
864                 std::string file;
865                 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
866                 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
867                         file = freesound_get_audio_file (freesound_list->get_iter(*i));
868                 }
869
870                 switch (rows.size()) {
871                         case 0:
872                                 // nothing selected
873                                 freesound_similar_btn.set_sensitive(false);
874                                 set_action_sensitive (false);
875                                 break;
876                         case 1:
877                                 // exactly one item selected
878                                 if (file != "") {
879                                         // file exists on disk already
880                                         chooser.set_filename (file);
881                                         preview.setup_labels (file);
882                                         set_action_sensitive (true);
883                                 }
884                                 freesound_similar_btn.set_sensitive(true);
885                                 break;
886                         default:
887                                 // multiple items selected
888                                 preview.setup_labels ("");
889                                 freesound_similar_btn.set_sensitive(false);
890                                 break;
891                 }
892
893         }
894 }
895
896 void
897 SoundFileBrowser::refresh_display(std::string ID, std::string file)
898 {
899         // called when the mootcher has finished downloading a file
900         ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
901         if (rows.size() == 1) {
902                 // there's a single item selected in the freesound list
903                 //XXX make a function to be used to construct the actual file name both here and in the mootcher
904                 Gtk::TreeIter row = freesound_list->get_iter(*rows.begin());
905                 std::string selected_ID = (*row)[freesound_list_columns.id]; 
906                 if (ID == selected_ID) {
907                         // the selected item in the freesound list is the item that has just finished downloading
908                         chooser.set_filename(file);
909                         preview.setup_labels (file);
910                         set_action_sensitive (true);
911                 }
912         }
913 }
914
915 void
916 SoundFileBrowser::freesound_search_clicked ()
917 {
918         freesound_page = 1;
919         freesound_list->clear();
920         matches = 0;
921         freesound_search();
922 }
923
924 void
925 SoundFileBrowser::freesound_more_clicked ()
926 {
927         char row_path[21];
928         freesound_page++;
929         freesound_search();
930         snprintf(row_path, 21, "%d", (freesound_page - 1) * 100);
931         freesound_list_view.scroll_to_row(Gtk::TreePath(row_path), 0);
932 }
933
934 void
935 SoundFileBrowser::freesound_similar_clicked ()
936 {
937         ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
938         if (rows.size() == 1) {
939                 Mootcher mootcher;
940                 string id;
941                 Gtk::TreeIter iter = freesound_list->get_iter(*rows.begin());
942                 id = (*iter)[freesound_list_columns.id];
943                 freesound_list->clear();
944
945                 GdkCursor *prev_cursor;
946                 prev_cursor = gdk_window_get_cursor (get_window()->gobj());
947                 gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
948                 gdk_flush();
949                 
950                 std::string theString = mootcher.searchSimilar(id);
951                 
952                 gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
953                 handle_freesound_results(theString);
954         }
955 }
956
957 void
958 SoundFileBrowser::freesound_search()
959 {
960         Mootcher mootcher;
961
962         string search_string = freesound_entry.get_text ();
963         enum sortMethod sort_method = (enum sortMethod) freesound_sort.get_active_row_number();
964
965         GdkCursor *prev_cursor;
966         prev_cursor = gdk_window_get_cursor (get_window()->gobj());
967         gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
968         gdk_flush();
969
970         std::string theString = mootcher.searchText(
971                         search_string, 
972                         freesound_page,
973 #ifdef GTKOSX
974                         "", // OSX eats anything incl mp3
975 #else
976                         "type:wav OR type:aiff OR type:flac OR type:aif OR type:ogg OR type:oga",
977 #endif
978                         sort_method
979                         );
980
981         gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
982         handle_freesound_results(theString);
983 }
984
985 void
986 SoundFileBrowser::handle_freesound_results(std::string theString) {
987         XMLTree doc;
988         doc.read_buffer( theString );
989         XMLNode *root = doc.root();
990
991         if (!root) {
992                 error << "no root XML node!" << endmsg;
993                 return;
994         }
995
996         if ( strcmp(root->name().c_str(), "response") != 0) {
997                 error << string_compose ("root node name == %1 != \"response\"", root->name()) << endmsg;
998                 return;
999         }
1000
1001         // find out how many pages are available to search
1002         int freesound_n_pages = 1;
1003         XMLNode *res = root->child("num_pages");
1004         if (res) {
1005                 string result = res->child("text")->content();
1006                 freesound_n_pages = atoi(result);
1007         }
1008
1009         int more_pages = freesound_n_pages - freesound_page;
1010
1011         if (more_pages > 0) {
1012                 freesound_more_btn.set_sensitive(true);
1013                 freesound_more_btn.set_tooltip_text(string_compose(P_(
1014                                                 "%1 more page of 100 results available",
1015                                                 "%1 more pages of 100 results available",
1016                                                 more_pages), more_pages));
1017         } else {
1018                 freesound_more_btn.set_sensitive(false);
1019                 freesound_more_btn.set_tooltip_text(_("No more results available"));
1020         }
1021
1022         XMLNode *sounds_root = root->child("sounds");
1023         if (!sounds_root) {
1024                 error << "no child node \"sounds\" found!" << endmsg;
1025                 return;
1026         }
1027
1028         XMLNodeList sounds = sounds_root->children();
1029         if (sounds.size() == 0) {
1030                 /* nothing found */
1031                 return;
1032         }
1033
1034         XMLNodeConstIterator niter;
1035         XMLNode *node;
1036         for (niter = sounds.begin(); niter != sounds.end(); ++niter) {
1037                 node = *niter;
1038                 if( strcmp( node->name().c_str(), "resource") != 0 ) {
1039                         error << string_compose ("node->name()=%1 != \"resource\"", node->name()) << endmsg;
1040                         break;
1041                 }
1042
1043                 // node->dump(cerr, "node:");
1044
1045
1046                 XMLNode *id_node  = node->child ("id");
1047                 XMLNode *uri_node = node->child ("serve");
1048                 XMLNode *ofn_node = node->child ("original_filename");
1049                 XMLNode *dur_node = node->child ("duration");
1050                 XMLNode *siz_node = node->child ("filesize");
1051                 XMLNode *srt_node = node->child ("samplerate");
1052                 XMLNode *lic_node = node->child ("license");
1053
1054                 if (id_node && uri_node && ofn_node && dur_node && siz_node && srt_node) {
1055
1056                         std::string  id =  id_node->child("text")->content();
1057                         std::string uri = uri_node->child("text")->content();
1058                         std::string ofn = ofn_node->child("text")->content();
1059                         std::string dur = dur_node->child("text")->content();
1060                         std::string siz = siz_node->child("text")->content();
1061                         std::string srt = srt_node->child("text")->content();
1062                         std::string lic = lic_node->child("text")->content();
1063
1064                         std::string r;
1065                         // cerr << "id=" << id << ",uri=" << uri << ",ofn=" << ofn << ",dur=" << dur << endl;
1066
1067                         double duration_seconds = atof(dur);
1068                         double h, m, s;
1069                         char duration_hhmmss[16];
1070                         if (duration_seconds >= 99 * 60 * 60) {
1071                                 strcpy(duration_hhmmss, ">99h");
1072                         } else {
1073                                 s = modf(duration_seconds/60, &m) * 60;
1074                                 m = modf(m/60, &h) * 60;
1075                                 sprintf(duration_hhmmss, "%02.fh:%02.fm:%04.1fs",
1076                                                 h, m, s
1077                                        );
1078                         }
1079
1080                         double size_bytes = atof(siz);
1081                         char bsize[32];
1082                         if (size_bytes < 1000) {
1083                                 sprintf(bsize, "%.0f %s", size_bytes, _("B"));
1084                         } else if (size_bytes < 1000000 ) {
1085                                 sprintf(bsize, "%.1f %s", size_bytes / 1000.0, _("kB"));
1086                         } else if (size_bytes < 10000000) {
1087                                 sprintf(bsize, "%.1f %s", size_bytes / 1000000.0, _("MB"));
1088                         } else if (size_bytes < 1000000000) {
1089                                 sprintf(bsize, "%.2f %s", size_bytes / 1000000.0, _("MB"));
1090                         } else {
1091                                 sprintf(bsize, "%.2f %s", size_bytes / 1000000000.0, _("GB"));
1092                         }
1093
1094                         /* see http://www.freesound.org/help/faq/#licenses */
1095                         char shortlicense[64];
1096                         if(!lic.compare(0, 42, "http://creativecommons.org/licenses/by-nc/")){
1097                                 sprintf(shortlicense, "CC-BY-NC");
1098                         } else if(!lic.compare(0, 39, "http://creativecommons.org/licenses/by/")) {
1099                                 sprintf(shortlicense, "CC-BY");
1100                         } else if(!lic.compare("http://creativecommons.org/licenses/sampling+/1.0/")) {
1101                                 sprintf(shortlicense, "sampling+");
1102                         } else if(!lic.compare(0, 40, "http://creativecommons.org/publicdomain/")) {
1103                                 sprintf(shortlicense, "PD");
1104                         } else {
1105                                 snprintf(shortlicense, 64, "%s", lic.c_str());
1106                                 shortlicense[63]= '\0';
1107                         }
1108
1109                         TreeModel::iterator new_row = freesound_list->append();
1110                         TreeModel::Row row = *new_row;
1111
1112                         row[freesound_list_columns.id      ] = id;
1113                         row[freesound_list_columns.uri     ] = uri;
1114                         row[freesound_list_columns.filename] = ofn;
1115                         row[freesound_list_columns.duration] = duration_hhmmss;
1116                         row[freesound_list_columns.filesize] = bsize;
1117                         row[freesound_list_columns.smplrate] = srt;
1118                         row[freesound_list_columns.license ] = shortlicense;
1119                         matches++;
1120                 }
1121         }
1122 }
1123
1124 vector<string>
1125 SoundFileBrowser::get_paths ()
1126 {
1127         vector<string> results;
1128
1129         int n = notebook.get_current_page ();
1130
1131         if (n == 0) {
1132                 vector<string> filenames = chooser.get_filenames();
1133                 vector<string>::iterator i;
1134
1135                 for (i = filenames.begin(); i != filenames.end(); ++i) {
1136                         struct stat buf;
1137                         if ((!stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
1138                                 results.push_back (*i);
1139                         }
1140                 }
1141
1142         } else if (n == 1) {
1143
1144                 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
1145                 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1146                         TreeIter iter = found_list->get_iter(*i);
1147                         string str = (*iter)[found_list_columns.pathname];
1148
1149                         results.push_back (str);
1150                 }
1151         } else {
1152 #ifdef FREESOUND
1153                 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
1154                 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
1155                         string str = freesound_get_audio_file (freesound_list->get_iter(*i));
1156                         if (str != "") {
1157                                 results.push_back (str);
1158                         }
1159                 }
1160 #endif
1161         }
1162
1163         return results;
1164 }
1165
1166 void
1167 SoundFileOmega::reset_options_noret ()
1168 {
1169         if (!resetting_ourselves) {
1170                 (void) reset_options ();
1171         }
1172 }
1173
1174 bool
1175 SoundFileOmega::reset_options ()
1176 {
1177         vector<string> paths = get_paths ();
1178
1179         if (paths.empty()) {
1180
1181                 channel_combo.set_sensitive (false);
1182                 action_combo.set_sensitive (false);
1183                 where_combo.set_sensitive (false);
1184                 copy_files_btn.set_active (true);
1185                 copy_files_btn.set_sensitive (false);
1186
1187                 return false;
1188
1189         } else {
1190
1191                 channel_combo.set_sensitive (true);
1192                 action_combo.set_sensitive (true);
1193                 where_combo.set_sensitive (true);
1194
1195                 /* if we get through this function successfully, this may be
1196                    reset at the end, once we know if we can use hard links
1197                    to do embedding (or if we are importing a MIDI file).
1198                 */
1199
1200                 if (Config->get_only_copy_imported_files()) {
1201                         copy_files_btn.set_sensitive (false);
1202                 } else {
1203                         copy_files_btn.set_sensitive (false);
1204                 }
1205         }
1206
1207         bool same_size;
1208         bool src_needed;
1209         bool selection_includes_multichannel;
1210         bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
1211         ImportMode mode;
1212
1213         /* See if we are thinking about importing any MIDI files */
1214         vector<string>::iterator i = paths.begin ();
1215         while (i != paths.end() && SMFSource::safe_midi_file_extension (*i) == false) {
1216                 ++i;
1217         }
1218         bool const have_a_midi_file = (i != paths.end ());
1219
1220         if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
1221                 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
1222                 return false;
1223         }
1224
1225         string existing_choice;
1226         vector<string> action_strings;
1227
1228         resetting_ourselves = true;
1229
1230         if (chooser.get_filter() == &audio_filter) {
1231
1232                 /* AUDIO */
1233
1234                 if (selected_audio_track_cnt > 0) {
1235                         if (channel_combo.get_active_text().length()) {
1236                                 ImportDisposition id = get_channel_disposition();
1237                                 
1238                                 switch (id) {
1239                                 case Editing::ImportDistinctFiles:
1240                                         if (selected_audio_track_cnt == paths.size()) {
1241                                                 action_strings.push_back (importmode2string (ImportToTrack));
1242                                         }
1243                                         break;
1244                                         
1245                                 case Editing::ImportDistinctChannels:
1246                                         /* XXX it would be nice to allow channel-per-selected track
1247                                            but its too hard we don't want to deal with all the
1248                                            different per-file + per-track channel configurations.
1249                                         */
1250                                         break;
1251                                         
1252                                 default:
1253                                         action_strings.push_back (importmode2string (ImportToTrack));
1254                                         break;
1255                                 }
1256                         }
1257                 }
1258                 
1259         }  else {
1260
1261                 /* MIDI ONLY */
1262
1263                 if (selected_midi_track_cnt > 0) {
1264                         action_strings.push_back (importmode2string (ImportToTrack));
1265                 }
1266         }
1267
1268         action_strings.push_back (importmode2string (ImportAsTrack));
1269         action_strings.push_back (importmode2string (ImportAsRegion));
1270         action_strings.push_back (importmode2string (ImportAsTapeTrack));
1271
1272         existing_choice = action_combo.get_active_text();
1273
1274         set_popdown_strings (action_combo, action_strings);
1275
1276         /* preserve any existing choice, if possible */
1277
1278
1279         if (existing_choice.length()) {
1280                 vector<string>::iterator x;
1281                 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
1282                         if (*x == existing_choice) {
1283                                 action_combo.set_active_text (existing_choice);
1284                                 break;
1285                         }
1286                 }
1287                 if (x == action_strings.end()) {
1288                         action_combo.set_active_text (action_strings.front());
1289                 }
1290         } else {
1291                 action_combo.set_active_text (action_strings.front());
1292         }
1293
1294         resetting_ourselves = false;
1295
1296         if ((mode = get_mode()) == ImportAsRegion) {
1297                 where_combo.set_sensitive (false);
1298         } else {
1299                 where_combo.set_sensitive (true);
1300         }
1301
1302         vector<string> channel_strings;
1303
1304         if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1305                 channel_strings.push_back (_("one track per file"));
1306
1307                 if (selection_includes_multichannel) {
1308                         channel_strings.push_back (_("one track per channel"));
1309                 }
1310
1311                 if (paths.size() > 1) {
1312                         /* tape tracks are a single region per track, so we cannot
1313                            sequence multiple files.
1314                         */
1315                         if (mode != ImportAsTapeTrack) {
1316                                 channel_strings.push_back (_("sequence files"));
1317                         }
1318                         if (same_size) {
1319                                 channel_strings.push_back (_("all files in one track"));
1320                                 channel_strings.push_back (_("merge files"));
1321                         }
1322
1323                 }
1324
1325         } else {
1326                 channel_strings.push_back (_("one region per file"));
1327
1328                 if (selection_includes_multichannel) {
1329                         channel_strings.push_back (_("one region per channel"));
1330                 }
1331
1332                 if (paths.size() > 1) {
1333                         if (same_size) {
1334                                 channel_strings.push_back (_("all files in one region"));
1335                         }
1336                 }
1337         }
1338
1339         resetting_ourselves = true;
1340
1341         existing_choice = channel_combo.get_active_text();
1342
1343         set_popdown_strings (channel_combo, channel_strings);
1344
1345         /* preserve any existing choice, if possible */
1346
1347         if (existing_choice.length()) {
1348                 vector<string>::iterator x;
1349                 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1350                         if (*x == existing_choice) {
1351                                 channel_combo.set_active_text (existing_choice);
1352                                 break;
1353                         }
1354                 }
1355                 if (x == channel_strings.end()) {
1356                         channel_combo.set_active_text (channel_strings.front());
1357                 }
1358         } else {
1359                 channel_combo.set_active_text (channel_strings.front());
1360         }
1361
1362         resetting_ourselves = false;
1363
1364         if (src_needed) {
1365                 src_combo.set_sensitive (true);
1366         } else {
1367                 src_combo.set_sensitive (false);
1368         }
1369
1370         /* We must copy MIDI files or those from Freesound
1371          * or any file if we are under nsm control */
1372         bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
1373         
1374         if (Config->get_only_copy_imported_files()) {
1375
1376                 if (selection_can_be_embedded_with_links && !must_copy) {
1377                         copy_files_btn.set_sensitive (true);
1378                 } else {
1379                         if (must_copy) {
1380                                 copy_files_btn.set_active (true);
1381                         }
1382                         copy_files_btn.set_sensitive (false);
1383                 }
1384
1385         }  else {
1386
1387                 if (must_copy) {
1388                         copy_files_btn.set_active (true);
1389                 }                       
1390                 copy_files_btn.set_sensitive (!must_copy);
1391         }
1392
1393         return true;
1394 }
1395
1396
1397 bool
1398 SoundFileOmega::bad_file_message()
1399 {
1400         MessageDialog msg (*this,
1401                            string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1402                            true,
1403                            Gtk::MESSAGE_INFO,
1404                            Gtk::BUTTONS_OK);
1405         msg.run ();
1406         resetting_ourselves = true;
1407         chooser.unselect_uri (chooser.get_preview_uri());
1408         resetting_ourselves = false;
1409
1410         return false;
1411 }
1412
1413 bool
1414 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1415 {
1416         SoundFileInfo info;
1417         framepos_t sz = 0;
1418         bool err = false;
1419         string errmsg;
1420
1421         same_size = true;
1422         src_needed = false;
1423         multichannel = false;
1424
1425         for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1426
1427                 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1428                         if (info.channels > 1) {
1429                                 multichannel = true;
1430                         }
1431                         if (sz == 0) {
1432                                 sz = info.length;
1433                         } else {
1434                                 if (sz != info.length) {
1435                                         same_size = false;
1436                                 }
1437                         }
1438
1439                         if (info.samplerate != _session->frame_rate()) {
1440                                 src_needed = true;
1441                         }
1442
1443                 } else if (SMFSource::safe_midi_file_extension (*i)) {
1444
1445                         Evoral::SMF reader;
1446                         reader.open(*i);
1447                         if (reader.num_tracks() > 1) {
1448                                 multichannel = true; // "channel" == track here...
1449                         }
1450
1451                         /* XXX we need err = true handling here in case
1452                            we can't check the file
1453                         */
1454
1455                 } else {
1456                         err = true;
1457                 }
1458         }
1459
1460         return err;
1461 }
1462
1463
1464 bool
1465 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1466 {
1467         std::string tmpdir(Glib::build_filename (s->session_directory().sound_path(), "linktest"));
1468         bool ret = false;
1469
1470         if (mkdir (tmpdir.c_str(), 0744)) {
1471                 if (errno != EEXIST) {
1472                         return false;
1473                 }
1474         }
1475
1476         for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1477
1478                 char tmpc[MAXPATHLEN+1];
1479
1480                 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1481
1482                 /* can we link ? */
1483
1484                 if (link ((*i).c_str(), tmpc)) {
1485                         goto out;
1486                 }
1487
1488                 unlink (tmpc);
1489         }
1490
1491         ret = true;
1492
1493   out:
1494         rmdir (tmpdir.c_str());
1495         return ret;
1496 }
1497
1498 SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
1499         : SoundFileBrowser (title, s, false)
1500 {
1501         chooser.set_select_multiple (false);
1502         found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1503         freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1504 }
1505
1506 void
1507 SoundFileChooser::on_hide ()
1508 {
1509         ArdourWindow::on_hide();
1510         stop_metering ();
1511
1512         if (_session) {
1513                 _session->cancel_audition();
1514         }
1515 }
1516
1517 string
1518 SoundFileChooser::get_filename ()
1519 {
1520         vector<string> paths;
1521
1522         paths = get_paths ();
1523
1524         if (paths.empty()) {
1525                 return string ();
1526         }
1527
1528         if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1529                 return string();
1530         }
1531
1532         return paths.front();
1533 }
1534
1535 SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s, 
1536                                 uint32_t selected_audio_tracks, 
1537                                 uint32_t selected_midi_tracks, 
1538                                 bool persistent,
1539                                 Editing::ImportMode mode_hint)
1540         : SoundFileBrowser (title, s, persistent)
1541         , copy_files_btn ( _("Copy files to session"))
1542         , selected_audio_track_cnt (selected_audio_tracks)
1543         , selected_midi_track_cnt (selected_midi_tracks)
1544 {
1545         VBox* vbox;
1546         HBox* hbox;
1547         vector<string> str;
1548
1549         set_size_request (-1, 450);
1550
1551         block_two.set_border_width (12);
1552         block_three.set_border_width (12);
1553         block_four.set_border_width (12);
1554
1555         options.set_spacing (12);
1556
1557         str.clear ();
1558         str.push_back (_("file timestamp"));
1559         str.push_back (_("edit point"));
1560         str.push_back (_("playhead"));
1561         str.push_back (_("session start"));
1562         set_popdown_strings (where_combo, str);
1563         where_combo.set_active_text (str.front());
1564
1565         Label* l = manage (new Label);
1566         l->set_markup (_("<b>Add files as ...</b>"));
1567
1568         vbox = manage (new VBox);
1569         vbox->set_border_width (12);
1570         vbox->set_spacing (6);
1571         vbox->pack_start (*l, false, false);
1572         vbox->pack_start (action_combo, false, false);
1573         hbox = manage (new HBox);
1574         hbox->pack_start (*vbox, false, false);
1575         options.pack_start (*hbox, false, false);
1576
1577         /* dummy entry for action combo so that it doesn't look odd if we
1578            come up with no tracks selected.
1579         */
1580
1581         str.clear ();
1582         str.push_back (importmode2string (mode_hint));
1583         set_popdown_strings (action_combo, str);
1584         action_combo.set_active_text (str.front());
1585         action_combo.set_sensitive (false);
1586
1587         l = manage (new Label);
1588         l->set_markup (_("<b>Insert at</b>"));
1589
1590         vbox = manage (new VBox);
1591         vbox->set_border_width (12);
1592         vbox->set_spacing (6);
1593         vbox->pack_start (*l, false, false);
1594         vbox->pack_start (where_combo, false, false);
1595         hbox = manage (new HBox);
1596         hbox->pack_start (*vbox, false, false);
1597         options.pack_start (*hbox, false, false);
1598
1599
1600         l = manage (new Label);
1601         l->set_markup (_("<b>Mapping</b>"));
1602
1603         vbox = manage (new VBox);
1604         vbox->set_border_width (12);
1605         vbox->set_spacing (6);
1606         vbox->pack_start (*l, false, false);
1607         vbox->pack_start (channel_combo, false, false);
1608         hbox = manage (new HBox);
1609         hbox->pack_start (*vbox, false, false);
1610         options.pack_start (*hbox, false, false);
1611
1612         str.clear ();
1613         str.push_back (_("one track per file"));
1614         set_popdown_strings (channel_combo, str);
1615         channel_combo.set_active_text (str.front());
1616         channel_combo.set_sensitive (false);
1617
1618         l = manage (new Label);
1619         l->set_markup (_("<b>Conversion quality</b>"));
1620
1621         vbox = manage (new VBox);
1622         vbox->set_border_width (12);
1623         vbox->set_spacing (6);
1624         vbox->pack_start (*l, false, false);
1625         vbox->pack_start (src_combo, false, false);
1626         hbox = manage (new HBox);
1627         hbox->pack_start (*vbox, false, false);
1628         options.pack_start (*hbox, false, false);
1629
1630         str.clear ();
1631         str.push_back (_("Best"));
1632         str.push_back (_("Good"));
1633         str.push_back (_("Quick"));
1634         str.push_back (_("Fast"));
1635         str.push_back (_("Fastest"));
1636
1637         set_popdown_strings (src_combo, str);
1638         src_combo.set_active_text (str.front());
1639         src_combo.set_sensitive (false);
1640
1641         reset_options ();
1642
1643         action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1644         channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1645
1646         copy_files_btn.set_active (true);
1647
1648         Gtk::Label* copy_label = dynamic_cast<Gtk::Label*>(copy_files_btn.get_child());
1649
1650         if (copy_label) {
1651                 copy_label->set_size_request (175, -1);
1652                 copy_label->set_line_wrap (true);
1653         }
1654
1655         block_four.pack_start (copy_files_btn, false, false);
1656
1657         options.pack_start (block_four, false, false);
1658
1659         vpacker.pack_start (options, false, false);
1660
1661         /* setup disposition map */
1662
1663         disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1664         disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1665         disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1666         disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1667
1668         disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1669         disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1670         disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1671         disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1672
1673         chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1674
1675         /* set size requests for a couple of combos to allow them to display the longest text
1676            they will ever be asked to display.  This prevents them being resized when the user
1677            selects a file to import, which in turn prevents the size of the dialog from jumping
1678            around. */
1679
1680         vector<string> t;
1681         t.push_back (_("one track per file"));
1682         t.push_back (_("one track per channel"));
1683         t.push_back (_("sequence files"));
1684         t.push_back (_("all files in one region"));
1685         set_popdown_strings (channel_combo, t);
1686
1687         t.clear ();
1688         t.push_back (importmode2string (ImportAsTrack));
1689         t.push_back (importmode2string (ImportToTrack));
1690         t.push_back (importmode2string (ImportAsRegion));
1691         t.push_back (importmode2string (ImportAsTapeTrack));
1692         set_popdown_strings (action_combo, t);
1693 }
1694
1695 void
1696 SoundFileOmega::set_mode (ImportMode mode)
1697 {
1698         action_combo.set_active_text (importmode2string (mode));
1699 }
1700
1701 ImportMode
1702 SoundFileOmega::get_mode () const
1703 {
1704         return string2importmode (action_combo.get_active_text());
1705 }
1706
1707 void
1708 SoundFileOmega::on_hide ()
1709 {
1710         ArdourWindow::on_hide();
1711         if (_session) {
1712                 _session->cancel_audition();
1713         }
1714 }
1715
1716 ImportPosition
1717 SoundFileOmega::get_position() const
1718 {
1719         string str = where_combo.get_active_text();
1720
1721         if (str == _("file timestamp")) {
1722                 return ImportAtTimestamp;
1723         } else if (str == _("edit point")) {
1724                 return ImportAtEditPoint;
1725         } else if (str == _("playhead")) {
1726                 return ImportAtPlayhead;
1727         } else {
1728                 return ImportAtStart;
1729         }
1730 }
1731
1732 SrcQuality
1733 SoundFileOmega::get_src_quality() const
1734 {
1735         string str = src_combo.get_active_text();
1736
1737         if (str == _("Best")) {
1738                 return SrcBest;
1739         } else if (str == _("Good")) {
1740                 return SrcGood;
1741         } else if (str == _("Quick")) {
1742                 return SrcQuick;
1743         } else if (str == _("Fast")) {
1744                 return SrcFast;
1745         } else {
1746                 return SrcFastest;
1747         }
1748 }
1749
1750 ImportDisposition
1751 SoundFileOmega::get_channel_disposition () const
1752 {
1753         /* we use a map here because the channel combo can contain different strings
1754            depending on the state of the other combos. the map contains all possible strings
1755            and the ImportDisposition enum that corresponds to it.
1756         */
1757
1758         string str = channel_combo.get_active_text();
1759         DispositionMap::const_iterator x = disposition_map.find (str);
1760
1761         if (x == disposition_map.end()) {
1762                 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1763                 /*NOTREACHED*/
1764         }
1765
1766         return x->second;
1767 }
1768
1769 void
1770 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
1771 {
1772         selected_audio_track_cnt = selected_audio_tracks;
1773         selected_midi_track_cnt = selected_midi_tracks;
1774
1775         if (selected_audio_track_cnt == 0 && selected_midi_track_cnt > 0) {
1776                 chooser.set_filter (midi_filter);
1777         } else if (selected_midi_track_cnt == 0 && selected_audio_track_cnt > 0) {
1778                 chooser.set_filter (audio_filter);
1779         } else {
1780                 chooser.set_filter (audio_and_midi_filter);
1781         }
1782
1783         reset_options ();
1784 }
1785
1786 void
1787 SoundFileOmega::file_selection_changed ()
1788 {
1789         if (resetting_ourselves) {
1790                 return;
1791         }
1792
1793         if (!reset_options ()) {
1794                 set_action_sensitive (false);
1795         } else {
1796                 if (chooser.get_filenames().size() > 0) {
1797                         set_action_sensitive (true);
1798                 } else {
1799                         set_action_sensitive (false);
1800                 }
1801         }
1802 }
1803
1804 void
1805 SoundFileOmega::do_something (int action)
1806 {
1807         SoundFileBrowser::do_something (action);
1808
1809         if (action == RESPONSE_CANCEL) {
1810                 hide ();
1811                 return;
1812         }
1813
1814         /* lets do it */
1815         
1816         vector<string> paths = get_paths ();
1817         ImportPosition pos = get_position ();
1818         ImportMode mode = get_mode ();
1819         ImportDisposition chns = get_channel_disposition ();
1820         framepos_t where;
1821         
1822         switch (pos) {
1823         case ImportAtEditPoint:
1824                 where = PublicEditor::instance().get_preferred_edit_position ();
1825                 break;
1826         case ImportAtTimestamp:
1827                 where = -1;
1828                 break;
1829         case ImportAtPlayhead:
1830                 where = _session->transport_frame();
1831                 break;
1832         case ImportAtStart:
1833                 where = _session->current_start_frame();
1834                 break;
1835         }
1836         
1837         SrcQuality quality = get_src_quality();
1838         
1839         if (copy_files_btn.get_active()) {
1840                 PublicEditor::instance().do_import (paths, chns, mode, quality, where);
1841         } else {
1842                 PublicEditor::instance().do_embed (paths, chns, mode, where);
1843         }
1844         
1845         if (action == RESPONSE_OK) {
1846                 hide ();
1847         }
1848 }
1849