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