Fix lingering references to old persist extension.
[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/amp.h"
47 #include "ardour/audio_library.h"
48 #include "ardour/auditioner.h"
49 #include "ardour/audioregion.h"
50 #include "ardour/audiofilesource.h"
51 #include "ardour/smf_source.h"
52 #include "ardour/region_factory.h"
53 #include "ardour/source_factory.h"
54 #include "ardour/session.h"
55 #include "ardour/session_directory.h"
56 #include "ardour/profile.h"
57
58 #include "ardour_ui.h"
59 #include "editing.h"
60 #include "gui_thread.h"
61 #include "prompter.h"
62 #include "sfdb_ui.h"
63 #include "editing.h"
64 #include "utils.h"
65 #include "gain_meter.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
84 static ImportMode
85 string2importmode (string str)
86 {
87         if (str == _("as new tracks")) {
88                 return ImportAsTrack;
89         } else if (str == _("to selected tracks")) {
90                 return ImportToTrack;
91         } else if (str == _("to region list")) {
92                 return ImportAsRegion;
93         } else if (str == _("as new tape tracks")) {
94                 return ImportAsTapeTrack;
95         }
96
97         warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
98
99         return ImportAsTrack;
100 }
101
102 static string
103 importmode2string (ImportMode mode)
104 {
105         switch (mode) {
106         case ImportAsTrack:
107                 return _("as new tracks");
108         case ImportToTrack:
109                 return _("to selected tracks");
110         case ImportAsRegion:
111                 return _("to region list");
112         case ImportAsTapeTrack:
113                 return _("as new tape tracks");
114         }
115         /*NOTREACHED*/
116         return _("as new tracks");
117 }
118
119 SoundFileBox::SoundFileBox (bool persistent)
120         : table (6, 2),
121           length_clock ("sfboxLengthClock", !persistent, "EditCursorClock", false, false, true, false),
122           timecode_clock ("sfboxTimecodeClock", !persistent, "EditCursorClock", false, false, false, false),
123           main_box (false, 6),
124           autoplay_btn (_("Auto-play"))
125
126 {
127         set_name (X_("SoundFileBox"));
128         set_size_request (300, -1);
129
130         preview_label.set_markup (_("<b>Sound File Information</b>"));
131
132         border_frame.set_label_widget (preview_label);
133         border_frame.add (main_box);
134
135         pack_start (border_frame, true, true);
136         set_border_width (6);
137
138         main_box.set_border_width (6);
139
140         length.set_text (_("Length:"));
141         length.set_alignment (1, 0.5);
142         timecode.set_text (_("Timestamp:"));
143         timecode.set_alignment (1, 0.5);
144         format.set_text (_("Format:"));
145         format.set_alignment (1, 0.5);
146         channels.set_text (_("Channels:"));
147         channels.set_alignment (1, 0.5);
148         samplerate.set_text (_("Sample rate:"));
149         samplerate.set_alignment (1, 0.5);
150
151         preview_label.set_max_width_chars (50);
152         preview_label.set_ellipsize (Pango::ELLIPSIZE_END);
153
154         format_text.set_max_width_chars (20);
155         format_text.set_ellipsize (Pango::ELLIPSIZE_END);
156         format_text.set_alignment (0, 1);
157
158         table.set_col_spacings (6);
159         table.set_homogeneous (false);
160         table.set_row_spacings (6);
161
162         table.attach (channels, 0, 1, 0, 1, FILL, FILL);
163         table.attach (samplerate, 0, 1, 1, 2, FILL, FILL);
164         table.attach (format, 0, 1, 2, 4, FILL, FILL);
165         table.attach (length, 0, 1, 4, 5, FILL, FILL);
166         table.attach (timecode, 0, 1, 5, 6, FILL, FILL);
167
168         table.attach (channels_value, 1, 2, 0, 1, FILL, FILL);
169         table.attach (samplerate_value, 1, 2, 1, 2, FILL, FILL);
170         table.attach (format_text, 1, 2, 2, 4, FILL, FILL);
171         table.attach (length_clock, 1, 2, 4, 5, FILL, FILL);
172         table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL);
173
174         length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock->mode());
175         timecode_clock.set_mode (AudioClock::Timecode);
176
177         main_box.pack_start (table, false, false);
178
179         tags_entry.set_editable (true);
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::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 (_("Start Downloading")),
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         //add the file chooser
442         {
443                 chooser.set_border_width (12);
444
445                 audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
446                 audio_filter.set_name (_("Audio files"));
447
448                 midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
449                 midi_filter.set_name (_("MIDI files"));
450
451                 matchall_filter.add_pattern ("*.*");
452                 matchall_filter.set_name (_("All files"));
453
454                 chooser.add_filter (audio_filter);
455                 chooser.add_filter (midi_filter);
456                 chooser.add_filter (matchall_filter);
457                 chooser.set_select_multiple (true);
458                 chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
459                 chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
460 #ifdef GTKOSX
461                 /* some broken redraw behaviour - this is a bandaid */
462                 chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
463 #endif
464
465                 if (!persistent_folder.empty()) {
466                         chooser.set_current_folder (persistent_folder);
467                 }
468                 notebook.append_page (chooser, _("Browse Files"));
469         }
470
471         hpacker.set_spacing (6);
472         hpacker.pack_start (notebook, true, true);
473         hpacker.pack_start (preview, false, false);
474
475         get_vbox()->pack_start (hpacker, true, true);
476
477         //add tag search
478         {
479                 VBox* vbox;
480                 HBox* hbox;
481
482
483                 hbox = manage(new HBox);
484                 hbox->pack_start (found_entry);
485                 hbox->pack_start (found_search_btn);
486
487                 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
488                 scroll->add(found_list_view);
489                 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
490
491                 vbox = manage(new VBox);
492                 vbox->pack_start (*hbox, PACK_SHRINK);
493                 vbox->pack_start (*scroll);
494
495                 found_list_view.append_column(_("Paths"), found_list_columns.pathname);
496
497                 found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
498
499                 found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
500
501                 found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
502                 found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
503
504                 notebook.append_page (*vbox, _("Search Tags"));
505         }
506
507         //add freesound search
508 #ifdef FREESOUND
509         {
510                 VBox* vbox;
511                 HBox* passbox;
512                 Label* label;
513
514                 passbox = manage(new HBox);
515                 passbox->set_border_width (12);
516                 passbox->set_spacing (6);
517
518                 label = manage (new Label);
519                 label->set_text (_("User:"));
520                 passbox->pack_start (*label, false, false);
521                 passbox->pack_start (freesound_name_entry);
522                 label = manage (new Label);
523                 label->set_text (_("Password:"));
524                 passbox->pack_start (*label, false, false);
525                 passbox->pack_start (freesound_pass_entry);
526                 label = manage (new Label);
527                 label->set_text (_("Tags:"));
528                 passbox->pack_start (*label, false, false);
529                 passbox->pack_start (freesound_entry, false, false);
530                 passbox->pack_start (freesound_search_btn, false, false);
531
532                 Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
533                 scroll->add(freesound_list_view);
534                 scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
535
536                 vbox = manage(new VBox);
537                 vbox->pack_start (*passbox, PACK_SHRINK);
538                 vbox->pack_start(*scroll);
539
540                 //vbox->pack_start (freesound_list_view);
541
542                 freesound_list_view.append_column(_("Paths"), freesound_list_columns.pathname);
543                 freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
544
545                 //freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
546                 freesound_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated));
547                 freesound_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
548                 freesound_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_search_clicked));
549                 notebook.append_page (*vbox, _("Search Freesound"));
550         }
551 #endif
552
553
554         notebook.set_size_request (500, -1);
555
556         set_session (s);
557
558         add_button (Stock::CANCEL, RESPONSE_CANCEL);
559         add_button (Stock::APPLY, RESPONSE_APPLY);
560         add_button (Stock::OK, RESPONSE_OK);
561
562 }
563
564 SoundFileBrowser::~SoundFileBrowser ()
565 {
566         persistent_folder = chooser.get_current_folder();
567 }
568
569
570 void
571 SoundFileBrowser::on_show ()
572 {
573         ArdourDialog::on_show ();
574         start_metering ();
575 }
576
577 void
578 SoundFileBrowser::clear_selection ()
579 {
580         chooser.unselect_all ();
581         found_list_view.get_selection()->unselect_all ();
582 }
583
584 void
585 SoundFileBrowser::chooser_file_activated ()
586 {
587         preview.audition ();
588 }
589
590 void
591 SoundFileBrowser::found_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
592 {
593         preview.audition ();
594 }
595
596 void
597 SoundFileBrowser::freesound_list_view_activated (const TreeModel::Path&, TreeViewColumn*)
598 {
599         preview.audition ();
600 }
601
602 void
603 SoundFileBrowser::set_session (Session* s)
604 {
605         ArdourDialog::set_session (s);
606         preview.set_session (s);
607
608         if (_session) {
609                 add_gain_meter ();
610         } else {
611                 remove_gain_meter ();
612         }
613 }
614
615 void
616 SoundFileBrowser::add_gain_meter ()
617 {
618         delete gm;
619
620         gm = new GainMeter (_session, 250);
621
622         boost::shared_ptr<Route> r = _session->the_auditioner ();
623
624         gm->set_controls (r, r->shared_peak_meter(), r->amp());
625
626         meter_packer.set_border_width (12);
627         meter_packer.pack_start (*gm, false, true);
628         hpacker.pack_end (meter_packer, false, false);
629         meter_packer.show_all ();
630         start_metering ();
631 }
632
633 void
634 SoundFileBrowser::remove_gain_meter ()
635 {
636         if (gm) {
637                 meter_packer.remove (*gm);
638                 hpacker.remove (meter_packer);
639                 delete gm;
640                 gm = 0;
641         }
642 }
643
644 void
645 SoundFileBrowser::start_metering ()
646 {
647         metering_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (sigc::mem_fun(*this, &SoundFileBrowser::meter));
648 }
649
650 void
651 SoundFileBrowser::stop_metering ()
652 {
653         metering_connection.disconnect();
654 }
655
656 void
657 SoundFileBrowser::meter ()
658 {
659         if (is_mapped () && _session && gm) {
660                 gm->update_meters ();
661         }
662 }
663
664 bool
665 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
666 {
667         return AudioFileSource::safe_audio_file_extension (filter_info.filename);
668 }
669
670 bool
671 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
672 {
673         return SMFSource::safe_midi_file_extension (filter_info.filename);
674 }
675
676 void
677 SoundFileBrowser::update_preview ()
678 {
679         if (preview.setup_labels (chooser.get_filename())) {
680                 if (preview.autoplay()) {
681                         Glib::signal_idle().connect (sigc::mem_fun (preview, &SoundFileBox::audition_oneshot));
682                 }
683         }
684 }
685
686 void
687 SoundFileBrowser::found_list_view_selected ()
688 {
689         if (!reset_options ()) {
690                 set_response_sensitive (RESPONSE_OK, false);
691         } else {
692                 string file;
693
694                 TreeView::Selection::ListHandle_Path rows = found_list_view.get_selection()->get_selected_rows ();
695
696                 if (!rows.empty()) {
697                         TreeIter iter = found_list->get_iter(*rows.begin());
698                         file = (*iter)[found_list_columns.pathname];
699                         chooser.set_filename (file);
700                         set_response_sensitive (RESPONSE_OK, true);
701                 } else {
702                         set_response_sensitive (RESPONSE_OK, false);
703                 }
704
705                 preview.setup_labels (file);
706         }
707 }
708
709 void
710 SoundFileBrowser::freesound_list_view_selected ()
711 {
712         if (!reset_options ()) {
713                 set_response_sensitive (RESPONSE_OK, false);
714         } else {
715                 string file;
716
717                 TreeView::Selection::ListHandle_Path rows = freesound_list_view.get_selection()->get_selected_rows ();
718
719                 if (!rows.empty()) {
720                         TreeIter iter = freesound_list->get_iter(*rows.begin());
721                         file = (*iter)[freesound_list_columns.pathname];
722                         chooser.set_filename (file);
723                         set_response_sensitive (RESPONSE_OK, true);
724                 } else {
725                         set_response_sensitive (RESPONSE_OK, false);
726                 }
727
728                 preview.setup_labels (file);
729         }
730 }
731
732 void
733 SoundFileBrowser::found_search_clicked ()
734 {
735         string tag_string = found_entry.get_text ();
736
737         vector<string> tags;
738
739         if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
740                 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
741                 return;
742         }
743
744         vector<string> results;
745         Library->search_members_and (results, tags);
746
747         found_list->clear();
748         for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
749                 TreeModel::iterator new_row = found_list->append();
750                 TreeModel::Row row = *new_row;
751                 string path = Glib::filename_from_uri (string ("file:") + *i);
752                 row[found_list_columns.pathname] = path;
753         }
754 }
755
756 void*
757 freesound_search_thread_entry (void* arg)
758 {
759         SessionEvent::create_per_thread_pool ("freesound events", 64);
760
761         static_cast<SoundFileBrowser*>(arg)->freesound_search_thread ();
762
763         return 0;
764 }
765
766 bool searching = false;
767 bool canceling = false;
768
769 void
770 SoundFileBrowser::freesound_search_clicked ()
771 {
772         if (canceling)  //already canceling, button does nothing
773                 return;
774
775         if ( searching ) {
776                 freesound_search_btn.set_label(_("Cancelling.."));
777                 canceling = true;
778         } else {
779                 searching = true;
780                 freesound_search_btn.set_label(_("Cancel"));
781                 pthread_t freesound_thr;
782                 pthread_create_and_store ("freesound_search", &freesound_thr, freesound_search_thread_entry, this);
783         }
784 }
785
786 void
787 SoundFileBrowser::freesound_search_thread()
788 {
789 #if 0
790
791         THIS IS ALL TOTALLY THREAD-ILLEGAL ... YOU CANNOT DO GTK STUFF IN THIS THREAD
792
793 #ifdef FREESOUND
794         freesound_list->clear();
795
796         string path;
797         path = Glib::get_home_dir();
798         path += "/Freesound/";
799         Mootcher theMootcher(path.c_str());
800
801         string name_string = freesound_name_entry.get_text ();
802         string pass_string = freesound_pass_entry.get_text ();
803         string search_string = freesound_entry.get_text ();
804
805         if ( theMootcher.doLogin( name_string, pass_string ) ) {
806
807                 string theString = theMootcher.searchText(search_string);
808
809                 XMLTree doc;
810                 doc.read_buffer( theString );
811                 XMLNode *root = doc.root();
812
813                 if (root==NULL) return;
814
815                 if ( strcmp(root->name().c_str(), "freesound") == 0) {
816
817                         XMLNode *node = 0;
818                         XMLNodeList children = root->children();
819                         XMLNodeConstIterator niter;
820                         for (niter = children.begin(); niter != children.end() && !canceling; ++niter) {
821                                 node = *niter;
822                                 if( strcmp( node->name().c_str(), "sample") == 0 ){
823                                         XMLProperty *prop=node->property ("id");
824                                         string filename = theMootcher.getFile( prop->value().c_str() );
825                                         if ( filename != "" ) {
826                                                 TreeModel::iterator new_row = freesound_list->append();
827                                                 TreeModel::Row row = *new_row;
828                                                 string path = Glib::filename_from_uri (string ("file:") + filename);
829                                                 row[freesound_list_columns.pathname] = path;
830                                         }
831                                 }
832                         }
833                 }
834         }
835
836         searching = false;
837         canceling = false;
838         freesound_search_btn.set_label(_("Start Downloading"));
839 #endif
840 #endif
841
842 }
843
844 vector<string>
845 SoundFileBrowser::get_paths ()
846 {
847         vector<string> results;
848
849         int n = notebook.get_current_page ();
850
851         if (n == 0) {
852                 vector<string> filenames = chooser.get_filenames();
853                 vector<string>::iterator i;
854
855                 for (i = filenames.begin(); i != filenames.end(); ++i) {
856                         struct stat buf;
857                         if ((!stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
858                                 results.push_back (*i);
859                         }
860                 }
861
862         } else if (n==1){
863
864                 typedef TreeView::Selection::ListHandle_Path ListPath;
865
866                 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
867                 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
868                         TreeIter iter = found_list->get_iter(*i);
869                         string str = (*iter)[found_list_columns.pathname];
870
871                         results.push_back (str);
872                 }
873         } else {
874
875                 typedef TreeView::Selection::ListHandle_Path ListPath;
876
877                 ListPath rows = freesound_list_view.get_selection()->get_selected_rows ();
878                 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
879                         TreeIter iter = freesound_list->get_iter(*i);
880                         string str = (*iter)[freesound_list_columns.pathname];
881
882                         results.push_back (str);
883                 }
884         }
885
886         return results;
887 }
888
889 void
890 SoundFileOmega::reset_options_noret ()
891 {
892         if (!resetting_ourselves) {
893                 (void) reset_options ();
894         }
895 }
896
897 bool
898 SoundFileOmega::reset_options ()
899 {
900         vector<string> paths = get_paths ();
901
902         if (paths.empty()) {
903
904                 channel_combo.set_sensitive (false);
905                 action_combo.set_sensitive (false);
906                 where_combo.set_sensitive (false);
907                 copy_files_btn.set_sensitive (false);
908
909                 return false;
910
911         } else {
912
913                 channel_combo.set_sensitive (true);
914                 action_combo.set_sensitive (true);
915                 where_combo.set_sensitive (true);
916
917                 /* if we get through this function successfully, this may be
918                    reset at the end, once we know if we can use hard links
919                    to do embedding
920                 */
921
922                 if (Config->get_only_copy_imported_files()) {
923                         copy_files_btn.set_sensitive (false);
924                 } else {
925                         copy_files_btn.set_sensitive (false);
926                 }
927         }
928
929         bool same_size;
930         bool src_needed;
931         bool selection_includes_multichannel;
932         bool selection_can_be_embedded_with_links = check_link_status (_session, paths);
933         ImportMode mode;
934
935         if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
936                 Glib::signal_idle().connect (sigc::mem_fun (*this, &SoundFileOmega::bad_file_message));
937                 return false;
938         }
939
940         string existing_choice;
941         vector<string> action_strings;
942
943         if (chooser.get_filter() == &audio_filter) {
944
945                 /* AUDIO */
946
947                 if (selected_audio_track_cnt > 0) {
948                         if (channel_combo.get_active_text().length()) {
949                                 ImportDisposition id = get_channel_disposition();
950                                 
951                                 switch (id) {
952                                 case Editing::ImportDistinctFiles:
953                                         if (selected_audio_track_cnt == paths.size()) {
954                                                 action_strings.push_back (importmode2string (ImportToTrack));
955                                         }
956                                         break;
957                                         
958                                 case Editing::ImportDistinctChannels:
959                                         /* XXX it would be nice to allow channel-per-selected track
960                                            but its too hard we don't want to deal with all the
961                                            different per-file + per-track channel configurations.
962                                         */
963                                         break;
964                                         
965                                 default:
966                                         action_strings.push_back (importmode2string (ImportToTrack));
967                                         break;
968                                 }
969                         }
970                 }
971
972         }  else {
973
974                 /* MIDI */
975
976                 if (selected_midi_track_cnt > 0) {
977                         action_strings.push_back (importmode2string (ImportToTrack));
978                 }
979         }
980
981         action_strings.push_back (importmode2string (ImportAsTrack));
982         action_strings.push_back (importmode2string (ImportAsRegion));
983         action_strings.push_back (importmode2string (ImportAsTapeTrack));
984
985         resetting_ourselves = true;
986
987         existing_choice = action_combo.get_active_text();
988
989         set_popdown_strings (action_combo, action_strings);
990
991         /* preserve any existing choice, if possible */
992
993
994         if (existing_choice.length()) {
995                 vector<string>::iterator x;
996                 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
997                         if (*x == existing_choice) {
998                                 action_combo.set_active_text (existing_choice);
999                                 break;
1000                         }
1001                 }
1002                 if (x == action_strings.end()) {
1003                         action_combo.set_active_text (action_strings.front());
1004                 }
1005         } else {
1006                 action_combo.set_active_text (action_strings.front());
1007         }
1008
1009         resetting_ourselves = false;
1010
1011         if ((mode = get_mode()) == ImportAsRegion) {
1012                 where_combo.set_sensitive (false);
1013         } else {
1014                 where_combo.set_sensitive (true);
1015         }
1016
1017         vector<string> channel_strings;
1018
1019         if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
1020                 channel_strings.push_back (_("one track per file"));
1021
1022                 if (selection_includes_multichannel) {
1023                         channel_strings.push_back (_("one track per channel"));
1024                 }
1025
1026                 if (paths.size() > 1) {
1027                         /* tape tracks are a single region per track, so we cannot
1028                            sequence multiple files.
1029                         */
1030                         if (mode != ImportAsTapeTrack) {
1031                                 channel_strings.push_back (_("sequence files"));
1032                         }
1033                         if (same_size) {
1034                                 channel_strings.push_back (_("all files in one track"));
1035                                 channel_strings.push_back (_("merge files"));
1036                         }
1037
1038                 }
1039
1040         } else {
1041                 channel_strings.push_back (_("one region per file"));
1042
1043                 if (selection_includes_multichannel) {
1044                         channel_strings.push_back (_("one region per channel"));
1045                 }
1046
1047                 if (paths.size() > 1) {
1048                         if (same_size) {
1049                                 channel_strings.push_back (_("all files in one region"));
1050                         }
1051                 }
1052         }
1053
1054         resetting_ourselves = true;
1055
1056         existing_choice = channel_combo.get_active_text();
1057
1058         set_popdown_strings (channel_combo, channel_strings);
1059
1060         /* preserve any existing choice, if possible */
1061
1062         if (existing_choice.length()) {
1063                 vector<string>::iterator x;
1064                 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
1065                         if (*x == existing_choice) {
1066                                 channel_combo.set_active_text (existing_choice);
1067                                 break;
1068                         }
1069                 }
1070                 if (x == channel_strings.end()) {
1071                         channel_combo.set_active_text (channel_strings.front());
1072                 }
1073         } else {
1074                 channel_combo.set_active_text (channel_strings.front());
1075         }
1076
1077         resetting_ourselves = false;
1078
1079         if (src_needed) {
1080                 src_combo.set_sensitive (true);
1081         } else {
1082                 src_combo.set_sensitive (false);
1083         }
1084
1085         if (Config->get_only_copy_imported_files()) {
1086
1087                 if (selection_can_be_embedded_with_links) {
1088                         copy_files_btn.set_sensitive (true);
1089                 } else {
1090                         copy_files_btn.set_sensitive (false);
1091                 }
1092
1093         }  else {
1094
1095                 copy_files_btn.set_sensitive (true);
1096         }
1097
1098         return true;
1099 }
1100
1101
1102 bool
1103 SoundFileOmega::bad_file_message()
1104 {
1105         MessageDialog msg (*this,
1106                            string_compose (_("One or more of the selected files\ncannot be used by %1"), PROGRAM_NAME),
1107                            true,
1108                            Gtk::MESSAGE_INFO,
1109                            Gtk::BUTTONS_OK);
1110         msg.run ();
1111         resetting_ourselves = true;
1112         chooser.unselect_uri (chooser.get_preview_uri());
1113         resetting_ourselves = false;
1114
1115         return false;
1116 }
1117
1118 bool
1119 SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool& src_needed, bool& multichannel)
1120 {
1121         SoundFileInfo info;
1122         framepos_t sz = 0;
1123         bool err = false;
1124         string errmsg;
1125
1126         same_size = true;
1127         src_needed = false;
1128         multichannel = false;
1129
1130         for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1131
1132                 if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) {
1133                         if (info.channels > 1) {
1134                                 multichannel = true;
1135                         }
1136                         if (sz == 0) {
1137                                 sz = info.length;
1138                         } else {
1139                                 if (sz != info.length) {
1140                                         same_size = false;
1141                                 }
1142                         }
1143
1144                         if (info.samplerate != _session->frame_rate()) {
1145                                 src_needed = true;
1146                         }
1147
1148                 } else if (SMFSource::safe_midi_file_extension (*i)) {
1149
1150                         Evoral::SMF reader;
1151                         reader.open(*i);
1152                         if (reader.num_tracks() > 1) {
1153                                 multichannel = true; // "channel" == track here...
1154                         }
1155
1156                         /* XXX we need err = true handling here in case
1157                            we can't check the file
1158                         */
1159
1160                 } else {
1161                         err = true;
1162                 }
1163         }
1164
1165         return err;
1166 }
1167
1168
1169 bool
1170 SoundFileOmega::check_link_status (const Session* s, const vector<string>& paths)
1171 {
1172         sys::path path = s->session_directory().sound_path() / "linktest";
1173         string tmpdir = path.to_string();
1174         bool ret = false;
1175
1176         if (mkdir (tmpdir.c_str(), 0744)) {
1177                 if (errno != EEXIST) {
1178                         return false;
1179                 }
1180         }
1181
1182         for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1183
1184                 char tmpc[MAXPATHLEN+1];
1185
1186                 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
1187
1188                 /* can we link ? */
1189
1190                 if (link ((*i).c_str(), tmpc)) {
1191                         goto out;
1192                 }
1193
1194                 unlink (tmpc);
1195         }
1196
1197         ret = true;
1198
1199   out:
1200         rmdir (tmpdir.c_str());
1201         return ret;
1202 }
1203
1204 SoundFileChooser::SoundFileChooser (Gtk::Window& parent, string title, ARDOUR::Session* s)
1205         : SoundFileBrowser (parent, title, s, false)
1206 {
1207         chooser.set_select_multiple (false);
1208         found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1209         freesound_list_view.get_selection()->set_mode (SELECTION_SINGLE);
1210 }
1211
1212 void
1213 SoundFileChooser::on_hide ()
1214 {
1215         ArdourDialog::on_hide();
1216         stop_metering ();
1217
1218         if (_session) {
1219                 _session->cancel_audition();
1220         }
1221 }
1222
1223 string
1224 SoundFileChooser::get_filename ()
1225 {
1226         vector<string> paths;
1227
1228         paths = get_paths ();
1229
1230         if (paths.empty()) {
1231                 return string ();
1232         }
1233
1234         if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
1235                 return string();
1236         }
1237
1238         return paths.front();
1239 }
1240
1241 SoundFileOmega::SoundFileOmega (Gtk::Window& parent, string title, ARDOUR::Session* s, 
1242                                 uint32_t selected_audio_tracks, 
1243                                 uint32_t selected_midi_tracks, 
1244                                 bool persistent,
1245                                 Editing::ImportMode mode_hint)
1246         : SoundFileBrowser (parent, title, s, persistent)
1247         , copy_files_btn ( _("Copy files to session"))
1248         , selected_audio_track_cnt (selected_audio_tracks)
1249         , selected_midi_track_cnt (selected_midi_tracks)
1250 {
1251         VBox* vbox;
1252         HBox* hbox;
1253         vector<string> str;
1254
1255         set_size_request (-1, 450);
1256
1257         block_two.set_border_width (12);
1258         block_three.set_border_width (12);
1259         block_four.set_border_width (12);
1260
1261         options.set_spacing (12);
1262
1263         str.clear ();
1264         str.push_back (_("file timestamp"));
1265         str.push_back (_("edit point"));
1266         str.push_back (_("playhead"));
1267         str.push_back (_("session start"));
1268         set_popdown_strings (where_combo, str);
1269         where_combo.set_active_text (str.front());
1270
1271         Label* l = manage (new Label);
1272         l->set_text (_("Add files:"));
1273
1274         hbox = manage (new HBox);
1275         hbox->set_border_width (12);
1276         hbox->set_spacing (6);
1277         hbox->pack_start (*l, false, false);
1278         hbox->pack_start (action_combo, false, false);
1279         vbox = manage (new VBox);
1280         vbox->pack_start (*hbox, false, false);
1281         options.pack_start (*vbox, false, false);
1282
1283         /* dummy entry for action combo so that it doesn't look odd if we
1284            come up with no tracks selected.
1285         */
1286
1287         str.clear ();
1288         str.push_back (importmode2string (mode_hint));
1289         set_popdown_strings (action_combo, str);
1290         action_combo.set_active_text (str.front());
1291         action_combo.set_sensitive (false);
1292
1293         l = manage (new Label);
1294         l->set_text (_("Insert at:"));
1295
1296         hbox = manage (new HBox);
1297         hbox->set_border_width (12);
1298         hbox->set_spacing (6);
1299         hbox->pack_start (*l, false, false);
1300         hbox->pack_start (where_combo, false, false);
1301         vbox = manage (new VBox);
1302         vbox->pack_start (*hbox, false, false);
1303         options.pack_start (*vbox, false, false);
1304
1305
1306         l = manage (new Label);
1307         l->set_text (_("Mapping:"));
1308
1309         hbox = manage (new HBox);
1310         hbox->set_border_width (12);
1311         hbox->set_spacing (6);
1312         hbox->pack_start (*l, false, false);
1313         hbox->pack_start (channel_combo, false, false);
1314         vbox = manage (new VBox);
1315         vbox->pack_start (*hbox, false, false);
1316         options.pack_start (*vbox, false, false);
1317
1318         str.clear ();
1319         str.push_back (_("one track per file"));
1320         set_popdown_strings (channel_combo, str);
1321         channel_combo.set_active_text (str.front());
1322         channel_combo.set_sensitive (false);
1323
1324         l = manage (new Label);
1325         l->set_text (_("Conversion quality:"));
1326
1327         hbox = manage (new HBox);
1328         hbox->set_border_width (12);
1329         hbox->set_spacing (6);
1330         hbox->pack_start (*l, false, false);
1331         hbox->pack_start (src_combo, false, false);
1332         vbox = manage (new VBox);
1333         vbox->pack_start (*hbox, false, false);
1334         options.pack_start (*vbox, false, false);
1335
1336         str.clear ();
1337         str.push_back (_("Best"));
1338         str.push_back (_("Good"));
1339         str.push_back (_("Quick"));
1340         str.push_back (_("Fast"));
1341         str.push_back (_("Fastest"));
1342
1343         set_popdown_strings (src_combo, str);
1344         src_combo.set_active_text (str.front());
1345         src_combo.set_sensitive (false);
1346
1347         reset_options ();
1348
1349         action_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1350         channel_combo.signal_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::reset_options_noret));
1351
1352         copy_files_btn.set_active (true);
1353
1354         block_four.pack_start (copy_files_btn, false, false);
1355
1356         options.pack_start (block_four, false, false);
1357
1358         get_vbox()->pack_start (options, false, false);
1359
1360         /* setup disposition map */
1361
1362         disposition_map.insert (pair<string,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1363         disposition_map.insert (pair<string,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1364         disposition_map.insert (pair<string,ImportDisposition>(_("merge files"), ImportMergeFiles));
1365         disposition_map.insert (pair<string,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1366
1367         disposition_map.insert (pair<string,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1368         disposition_map.insert (pair<string,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1369         disposition_map.insert (pair<string,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1370         disposition_map.insert (pair<string,ImportDisposition>(_("all files in one track"), ImportMergeFiles));
1371
1372         chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &SoundFileOmega::file_selection_changed));
1373
1374         /* set size requests for a couple of combos to allow them to display the longest text
1375            they will ever be asked to display.  This prevents them being resized when the user
1376            selects a file to import, which in turn prevents the size of the dialog from jumping
1377            around. */
1378
1379         vector<string> t;
1380         t.push_back (_("one track per file"));
1381         t.push_back (_("one track per channel"));
1382         t.push_back (_("sequence files"));
1383         t.push_back (_("all files in one region"));
1384         set_size_request_to_display_given_text (channel_combo, t, COMBO_FUDGE + 10, 15);
1385
1386         t.clear ();
1387         t.push_back (importmode2string (ImportAsTrack));
1388         t.push_back (importmode2string (ImportToTrack));
1389         t.push_back (importmode2string (ImportAsRegion));
1390         t.push_back (importmode2string (ImportAsTapeTrack));
1391         set_size_request_to_display_given_text (action_combo, t, COMBO_FUDGE + 10, 15);
1392 }
1393
1394 void
1395 SoundFileOmega::set_mode (ImportMode mode)
1396 {
1397         action_combo.set_active_text (importmode2string (mode));
1398 }
1399
1400 ImportMode
1401 SoundFileOmega::get_mode () const
1402 {
1403         return string2importmode (action_combo.get_active_text());
1404 }
1405
1406 void
1407 SoundFileOmega::on_hide ()
1408 {
1409         ArdourDialog::on_hide();
1410         if (_session) {
1411                 _session->cancel_audition();
1412         }
1413 }
1414
1415 ImportPosition
1416 SoundFileOmega::get_position() const
1417 {
1418         string str = where_combo.get_active_text();
1419
1420         if (str == _("file timestamp")) {
1421                 return ImportAtTimestamp;
1422         } else if (str == _("edit point")) {
1423                 return ImportAtEditPoint;
1424         } else if (str == _("playhead")) {
1425                 return ImportAtPlayhead;
1426         } else {
1427                 return ImportAtStart;
1428         }
1429 }
1430
1431 SrcQuality
1432 SoundFileOmega::get_src_quality() const
1433 {
1434         string str = where_combo.get_active_text();
1435
1436         if (str == _("Best")) {
1437                 return SrcBest;
1438         } else if (str == _("Good")) {
1439                 return SrcGood;
1440         } else if (str == _("Quick")) {
1441                 return SrcQuick;
1442         } else if (str == _("Fast")) {
1443                 return SrcFast;
1444         } else {
1445                 return SrcFastest;
1446         }
1447 }
1448
1449 ImportDisposition
1450 SoundFileOmega::get_channel_disposition () const
1451 {
1452         /* we use a map here because the channel combo can contain different strings
1453            depending on the state of the other combos. the map contains all possible strings
1454            and the ImportDisposition enum that corresponds to it.
1455         */
1456
1457         string str = channel_combo.get_active_text();
1458         DispositionMap::const_iterator x = disposition_map.find (str);
1459
1460         if (x == disposition_map.end()) {
1461                 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1462                 /*NOTREACHED*/
1463         }
1464
1465         return x->second;
1466 }
1467
1468 void
1469 SoundFileOmega::reset (uint32_t selected_audio_tracks, uint32_t selected_midi_tracks)
1470 {
1471         selected_audio_track_cnt = selected_audio_tracks;
1472         selected_midi_track_cnt = selected_midi_tracks;
1473         reset_options ();
1474 }
1475
1476 void
1477 SoundFileOmega::file_selection_changed ()
1478 {
1479         if (resetting_ourselves) {
1480                 return;
1481         }
1482
1483         if (!reset_options ()) {
1484                 set_response_sensitive (RESPONSE_OK, false);
1485         } else {
1486                 if (chooser.get_filenames().size() > 0) {
1487                         set_response_sensitive (RESPONSE_OK, true);
1488                 } else {
1489                         set_response_sensitive (RESPONSE_OK, false);
1490                 }
1491         }
1492 }
1493