3bde6c98f1496bb971f6bbd73dc6a8a7a617ff16
[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 #include <map>
21 #include <cerrno>
22 #include <sstream>
23
24 #include <unistd.h>
25 #include <sys/stat.h>
26 #include <sys/param.h>
27
28 #include <gtkmm/box.h>
29 #include <gtkmm/stock.h>
30 #include <glibmm/fileutils.h>
31
32 #include <pbd/convert.h>
33 #include <pbd/tokenizer.h>
34 #include <pbd/enumwriter.h>
35
36 #include <gtkmm2ext/utils.h>
37
38 #include <ardour/audio_library.h>
39 #include <ardour/auditioner.h>
40 #include <ardour/audioregion.h>
41 #include <ardour/audiofilesource.h>
42 #include <ardour/region_factory.h>
43 #include <ardour/source_factory.h>
44 #include <ardour/session.h>
45 #include <ardour/session_directory.h>
46 #include <ardour/profile.h>
47
48 #include "ardour_ui.h"
49 #include "editing.h"
50 #include "gui_thread.h"
51 #include "prompter.h"
52 #include "sfdb_ui.h"
53 #include "editing.h"
54 #include "utils.h"
55 #include "gain_meter.h"
56
57 #include "i18n.h"
58
59 using namespace ARDOUR;
60 using namespace PBD;
61 using namespace std;
62 using namespace Gtk;
63 using namespace Gtkmm2ext;
64 using namespace Editing;
65
66 using Glib::ustring;
67
68 ustring SoundFileBrowser::persistent_folder;
69
70 static ImportMode
71 string2importmode (string str)
72 {
73         if (str == "as new tracks") {
74                 return ImportAsTrack;
75         } else if (str == "to selected tracks") {
76                 return ImportToTrack;
77         } else if (str == "to region list") {
78                 return ImportAsRegion;
79         } else if (str == "as new tape tracks") {
80                 return ImportAsTapeTrack;
81         }
82
83         warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
84         
85         return ImportAsTrack;
86 }
87
88 static string
89 importmode2string (ImportMode mode)
90 {
91         switch (mode) {
92         case ImportAsTrack:
93                 return _("as new tracks");
94         case ImportToTrack:
95                 return _("to selected tracks");
96         case ImportAsRegion:
97                 return _("to region list");
98         case ImportAsTapeTrack:
99                 return _("as new tape tracks");
100         }
101         /*NOTREACHED*/
102         return _("as new tracks");
103 }
104
105 SoundFileBox::SoundFileBox (bool persistent)
106         : _session(0),
107           table (6, 2),
108           length_clock ("sfboxLengthClock", !persistent, "EditCursorClock", false, true, false),
109           timecode_clock ("sfboxTimecodeClock", !persistent, "EditCursorClock", false, false, false),
110           main_box (false, 6),
111           autoplay_btn (_("Auto-play"))
112         
113 {
114         HBox* hbox;
115         VBox* vbox;
116
117         set_name (X_("SoundFileBox"));
118         set_size_request (300, -1);
119
120         preview_label.set_markup (_("<b>Soundfile Info</b>"));
121
122         border_frame.set_label_widget (preview_label);
123         border_frame.add (main_box);
124
125         pack_start (border_frame, true, true);
126         set_border_width (6);
127
128         main_box.set_border_width (6);
129         main_box.set_spacing (12);
130
131         length.set_text (_("Length:"));
132         timecode.set_text (_("Timestamp:"));
133         format.set_text (_("Format:"));
134         channels.set_text (_("Channels:"));
135         samplerate.set_text (_("Sample rate:"));
136
137         table.set_col_spacings (6);
138         table.set_homogeneous (false);
139         table.set_row_spacings (6);
140
141         table.attach (channels, 0, 1, 0, 1, FILL|EXPAND, (AttachOptions) 0);
142         table.attach (samplerate, 0, 1, 1, 2, FILL|EXPAND, (AttachOptions) 0);
143         table.attach (format, 0, 1, 2, 4, FILL|EXPAND, (AttachOptions) 0);
144         table.attach (length, 0, 1, 4, 5, FILL|EXPAND, (AttachOptions) 0);
145         table.attach (timecode, 0, 1, 5, 6, FILL|EXPAND, (AttachOptions) 0);
146
147         table.attach (channels_value, 1, 2, 0, 1, FILL, (AttachOptions) 0);
148         table.attach (samplerate_value, 1, 2, 1, 2, FILL, (AttachOptions) 0);
149         table.attach (format_text, 1, 2, 2, 4, FILL, AttachOptions (0));
150         table.attach (length_clock, 1, 2, 4, 5, FILL, (AttachOptions) 0);
151         table.attach (timecode_clock, 1, 2, 5, 6, FILL, (AttachOptions) 0);
152
153         length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock.mode());
154         timecode_clock.set_mode (AudioClock::SMPTE);
155
156         hbox = manage (new HBox);
157         hbox->pack_start (table, false, false);
158         main_box.pack_start (*hbox, false, false);
159
160         tags_entry.set_editable (true);
161         tags_entry.signal_focus_out_event().connect (mem_fun (*this, &SoundFileBox::tags_entry_left));
162         hbox = manage (new HBox);
163         hbox->pack_start (tags_entry, true, true);
164
165         vbox = manage (new VBox);
166
167         Label* label = manage (new Label (_("Tags:")));
168         label->set_alignment (0.0f, 0.5f);
169         vbox->set_spacing (6);
170         vbox->pack_start(*label, false, false);
171         vbox->pack_start(*hbox, true, true);
172
173         main_box.pack_start(*vbox, true, true);
174         main_box.pack_start(bottom_box, false, false);
175         
176         play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
177         play_btn.set_label (_("Play (double click)"));
178
179         stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
180         stop_btn.set_label (_("Stop"));
181         
182         bottom_box.set_homogeneous (false);
183         bottom_box.set_spacing (6);
184         bottom_box.pack_start(play_btn, true, true);
185         bottom_box.pack_start(stop_btn, true, true);
186         bottom_box.pack_start(autoplay_btn, false, false);
187
188         play_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::audition));
189         stop_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::stop_audition));
190
191         length.set_alignment (0.0f, 0.5f);
192         format.set_alignment (0.0f, 0.5f);
193         channels.set_alignment (0.0f, 0.5f);
194         samplerate.set_alignment (0.0f, 0.5f);
195         timecode.set_alignment (0.0f, 0.5f);
196
197         channels_value.set_alignment (0.0f, 0.5f);
198         samplerate_value.set_alignment (0.0f, 0.5f);
199 }
200
201 void
202 SoundFileBox::set_session(Session* s)
203 {
204         _session = s;
205
206         if (!_session) {
207                 play_btn.set_sensitive (false);
208                 stop_btn.set_sensitive (false);
209         } 
210
211
212         length_clock.set_session (s);
213         timecode_clock.set_session (s);
214 }
215
216 bool
217 SoundFileBox::setup_labels (const ustring& filename) 
218 {
219         if (!path.empty()) {
220                 // save existing tags
221                 tags_changed ();
222         }
223
224         path = filename;
225
226         string error_msg;
227
228         if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
229
230                 preview_label.set_markup (_("<b>Soundfile Info</b>"));
231                 format_text.set_text (_("n/a"));
232                 channels_value.set_text (_("n/a"));
233                 samplerate_value.set_text (_("n/a"));
234                 tags_entry.get_buffer()->set_text ("");
235
236                 length_clock.set (0);
237                 timecode_clock.set (0);
238                 
239                 tags_entry.set_sensitive (false);
240                 play_btn.set_sensitive (false);
241                 
242                 return false;
243         }
244
245         preview_label.set_markup (string_compose ("<b>%1</b>", Glib::path_get_basename (filename)));
246         format_text.set_text (sf_info.format_name);
247         channels_value.set_text (to_string (sf_info.channels, std::dec));
248
249         if (_session && sf_info.samplerate != _session->frame_rate()) {
250                 samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
251                 samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
252                 samplerate_value.set_name ("NewSessionSR1Label");
253                 samplerate.set_name ("NewSessionSR1Label");
254         } else {
255                 samplerate.set_text (_("Sample rate:"));
256                 samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
257                 samplerate_value.set_name ("NewSessionSR2Label");
258                 samplerate.set_name ("NewSessionSR2Label");
259         }
260
261         length_clock.set (sf_info.length, true);
262         timecode_clock.set (sf_info.timecode, true);
263
264         // this is a hack that is fixed in trunk, i think (august 26th, 2007)
265
266         vector<string> tags = Library->get_tags (string ("//") + filename);
267         
268         stringstream tag_string;
269         for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
270                 if (i != tags.begin()) {
271                         tag_string << ", ";
272                 }
273                 tag_string << *i;
274         }
275         tags_entry.get_buffer()->set_text (tag_string.str());
276         
277         tags_entry.set_sensitive (true);
278         if (_session) {
279                 play_btn.set_sensitive (true);
280         }
281         
282         return true;
283 }
284
285 bool
286 SoundFileBox::autoplay() const
287 {
288         return autoplay_btn.get_active();
289 }
290
291 bool
292 SoundFileBox::audition_oneshot()
293 {
294         audition ();
295         return false;
296 }
297
298 void
299 SoundFileBox::audition ()
300 {
301         if (!_session) {
302                 return;
303         }
304         
305         _session->cancel_audition();
306
307         if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
308                 warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
309                 return;
310         }
311
312         boost::shared_ptr<Region> r;
313         SourceList srclist;
314         boost::shared_ptr<AudioFileSource> afs;
315         bool old_sbp = AudioSource::get_build_peakfiles ();
316
317         /* don't even think of building peakfiles for these files */
318
319         AudioSource::set_build_peakfiles (false);
320
321         for (int n = 0; n < sf_info.channels; ++n) {
322                 try {
323                         afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, *_session, path, 
324                                                                                                            n, AudioFileSource::Flag (0), false));
325                         
326                         srclist.push_back(afs);
327                         
328                 } catch (failed_constructor& err) {
329                         error << _("Could not access soundfile: ") << path << endmsg;
330                         AudioSource::set_build_peakfiles (old_sbp);
331                         return;
332                 }
333         }
334
335         AudioSource::set_build_peakfiles (old_sbp);
336                         
337         if (srclist.empty()) {
338                 return;
339         }
340         
341         afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
342         string rname = region_name_from_path (afs->path(), false);
343         r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, 0, srclist[0]->length(), rname, 0, Region::DefaultFlags, false));
344
345         _session->audition_region(r);
346 }
347
348 void
349 SoundFileBox::stop_audition ()
350 {
351         if (_session) {
352                 _session->cancel_audition();
353         }
354 }
355
356 bool
357 SoundFileBox::tags_entry_left (GdkEventFocus *ev)
358 {
359         tags_changed ();
360         return false;
361 }
362
363 void
364 SoundFileBox::tags_changed ()
365 {
366         string tag_string = tags_entry.get_buffer()->get_text ();
367
368         if (tag_string.empty()) {
369                 return;
370         }
371
372         vector<string> tags;
373
374         if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
375                 warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
376                 return;
377         }
378
379         save_tags (tags);
380 }
381
382 void
383 SoundFileBox::save_tags (const vector<string>& tags)
384 {
385         Library->set_tags (string ("//") + path, tags);
386         Library->save_changes ();
387 }
388
389 SoundFileBrowser::SoundFileBrowser (Gtk::Window& parent, string title, ARDOUR::Session* s, bool persistent)
390         : ArdourDialog (parent, title, false, false),
391           found_list (ListStore::create(found_list_columns)),
392           chooser (FILE_CHOOSER_ACTION_OPEN),
393           found_list_view (found_list),
394           preview (persistent),
395           found_search_btn (_("Search"))
396
397 {
398         VBox* vbox;
399         HBox* hbox;
400
401         gm = 0;
402
403         set_session (s);
404         resetting_ourselves = false;
405         
406         hpacker.set_spacing (6);
407         hpacker.pack_start (notebook, true, true);
408         hpacker.pack_start (preview, false, false);
409
410         get_vbox()->pack_start (hpacker, true, true);
411
412         hbox = manage(new HBox);
413         hbox->pack_start (found_entry);
414         hbox->pack_start (found_search_btn);
415         
416         vbox = manage(new VBox);
417         vbox->pack_start (*hbox, PACK_SHRINK);
418         vbox->pack_start (found_list_view);
419         found_list_view.append_column(_("Paths"), found_list_columns.pathname);
420         
421         chooser.set_border_width (12);
422
423         notebook.append_page (chooser, _("Browse Files"));
424         notebook.append_page (*vbox, _("Search Tags"));
425
426         notebook.set_size_request (500, -1);
427
428         found_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
429         found_list_view.signal_row_activated().connect (mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
430
431         custom_filter.add_custom (FILE_FILTER_FILENAME, mem_fun(*this, &SoundFileBrowser::on_custom));
432         custom_filter.set_name (_("Audio files"));
433
434         matchall_filter.add_pattern ("*.*");
435         matchall_filter.set_name (_("All files"));
436
437         chooser.add_filter (custom_filter);
438         chooser.add_filter (matchall_filter);
439         chooser.set_select_multiple (true);
440         chooser.signal_update_preview().connect(mem_fun(*this, &SoundFileBrowser::update_preview));
441         chooser.signal_file_activated().connect (mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
442
443         if (!persistent_folder.empty()) {
444                 chooser.set_current_folder (persistent_folder);
445         }
446
447         found_list_view.get_selection()->signal_changed().connect(mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
448         
449         found_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked));
450         found_entry.signal_activate().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked));
451
452         add_button (Stock::CANCEL, RESPONSE_CANCEL);
453         add_button (Stock::APPLY, RESPONSE_APPLY);
454         add_button (Stock::OK, RESPONSE_OK);
455         
456 }
457
458 SoundFileBrowser::~SoundFileBrowser ()
459 {
460         persistent_folder = chooser.get_current_folder();
461 }
462
463
464 void
465 SoundFileBrowser::on_show ()
466 {
467         ArdourDialog::on_show ();
468         start_metering ();
469 }
470
471 void
472 SoundFileBrowser::clear_selection ()
473 {
474         chooser.unselect_all ();
475         found_list_view.get_selection()->unselect_all ();
476 }
477
478 void
479 SoundFileBrowser::chooser_file_activated ()
480 {
481         preview.audition ();
482 }
483
484 void
485 SoundFileBrowser::found_list_view_activated (const TreeModel::Path& path, TreeViewColumn* col)
486 {
487         preview.audition ();
488 }
489
490 void
491 SoundFileBrowser::set_session (Session* s)
492 {
493         ArdourDialog::set_session (s);
494         preview.set_session (s);
495         if (s) {
496                 add_gain_meter ();
497         } else {
498                 remove_gain_meter ();
499         }
500 }
501
502 void
503 SoundFileBrowser::add_gain_meter ()
504 {
505         if (gm) {
506                 delete gm;
507         }
508
509         gm = new GainMeter (session->the_auditioner(), *session);
510
511         meter_packer.set_border_width (12);
512         meter_packer.pack_start (*gm, false, true);
513         hpacker.pack_end (meter_packer, false, false);
514         meter_packer.show_all ();
515         start_metering ();
516 }
517
518 void
519 SoundFileBrowser::remove_gain_meter ()
520 {
521         if (gm) {
522                 meter_packer.remove (*gm);
523                 hpacker.remove (meter_packer);
524                 delete gm;
525                 gm = 0;
526         }
527 }
528
529 void
530 SoundFileBrowser::start_metering ()
531 {
532         metering_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun(*this, &SoundFileBrowser::meter));
533 }
534
535 void
536 SoundFileBrowser::stop_metering ()
537 {
538         metering_connection.disconnect();
539 }
540
541 void
542 SoundFileBrowser::meter ()
543 {
544         if (is_mapped () && session && gm) {
545                 gm->update_meters ();
546         }
547 }
548
549 bool
550 SoundFileBrowser::on_custom (const FileFilter::Info& filter_info)
551 {
552         return AudioFileSource::safe_file_extension (filter_info.filename);
553 }
554
555 void
556 SoundFileBrowser::update_preview ()
557 {
558         if (preview.setup_labels (chooser.get_filename())) {
559                 if (preview.autoplay()) {
560                         Glib::signal_idle().connect (mem_fun (preview, &SoundFileBox::audition_oneshot));
561                 }
562         }
563 }
564
565 void
566 SoundFileBrowser::found_list_view_selected ()
567 {
568         if (!reset_options ()) {
569                 set_response_sensitive (RESPONSE_OK, false);
570         } else {
571                 ustring file;
572
573                 TreeView::Selection::ListHandle_Path rows = found_list_view.get_selection()->get_selected_rows ();
574                 
575                 if (!rows.empty()) {
576                         TreeIter iter = found_list->get_iter(*rows.begin());
577                         file = (*iter)[found_list_columns.pathname];
578                         chooser.set_filename (file);
579                         set_response_sensitive (RESPONSE_OK, true);
580                 } else {
581                         set_response_sensitive (RESPONSE_OK, false);
582                 }
583                 
584                 preview.setup_labels (file);
585         }
586 }
587
588 void
589 SoundFileBrowser::found_search_clicked ()
590 {
591         string tag_string = found_entry.get_text ();
592
593         vector<string> tags;
594
595         if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
596                 warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
597                 return;
598         }
599         
600         vector<string> results;
601         Library->search_members_and (results, tags);
602         
603         found_list->clear();
604         for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
605                 TreeModel::iterator new_row = found_list->append();
606                 TreeModel::Row row = *new_row;
607                 string path = Glib::filename_from_uri (string ("file:") + *i);
608                 row[found_list_columns.pathname] = path;
609         }
610 }
611
612 vector<ustring>
613 SoundFileBrowser::get_paths ()
614 {
615         vector<ustring> results;
616         
617         int n = notebook.get_current_page ();
618         
619         if (n == 0) {
620                 vector<ustring> filenames = chooser.get_filenames();
621                 vector<ustring>::iterator i;
622
623                 for (i = filenames.begin(); i != filenames.end(); ++i) {
624                         struct stat buf;
625                         if ((!stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
626                                 results.push_back (*i);
627                         }
628                 }
629                 
630         } else {
631                 
632                 typedef TreeView::Selection::ListHandle_Path ListPath;
633                 
634                 ListPath rows = found_list_view.get_selection()->get_selected_rows ();
635                 for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
636                         TreeIter iter = found_list->get_iter(*i);
637                         ustring str = (*iter)[found_list_columns.pathname];
638                         
639                         results.push_back (str);
640                 }
641         }
642
643         return results;
644 }
645
646 void
647 SoundFileOmega::reset_options_noret ()
648 {
649         if (!resetting_ourselves) {
650                 (void) reset_options ();
651         }
652 }
653
654 bool
655 SoundFileOmega::reset_options ()
656 {
657         vector<ustring> paths = get_paths ();
658
659         if (paths.empty()) {
660
661                 channel_combo.set_sensitive (false);
662                 action_combo.set_sensitive (false);
663                 where_combo.set_sensitive (false);
664                 copy_files_btn.set_sensitive (false);
665
666                 return false;
667
668         } else {
669
670                 channel_combo.set_sensitive (true);
671                 action_combo.set_sensitive (true);
672                 where_combo.set_sensitive (true);
673
674                 /* if we get through this function successfully, this may be
675                    reset at the end, once we know if we can use hard links
676                    to do embedding
677                 */
678
679                 if (Config->get_only_copy_imported_files()) {
680                         copy_files_btn.set_sensitive (false);
681                 } else {
682                         copy_files_btn.set_sensitive (false);
683                 }
684         }
685
686         bool same_size;
687         bool src_needed;
688         bool selection_includes_multichannel;
689         bool selection_can_be_embedded_with_links = check_link_status (*session, paths);
690         ImportMode mode;
691
692         if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
693                 Glib::signal_idle().connect (mem_fun (*this, &SoundFileOmega::bad_file_message));
694                 return false;
695         }
696
697         ustring existing_choice;
698         vector<string> action_strings;
699
700         if (selected_track_cnt > 0) {
701                 if (channel_combo.get_active_text().length()) {
702                         ImportDisposition id = get_channel_disposition();
703                         
704                         switch (id) {
705                         case Editing::ImportDistinctFiles:
706                                 if (selected_track_cnt == paths.size()) {
707                                         action_strings.push_back (importmode2string (ImportToTrack));
708                                 }
709                                 break;
710                                 
711                         case Editing::ImportDistinctChannels:
712                                 /* XXX it would be nice to allow channel-per-selected track
713                                    but its too hard we don't want to deal with all the 
714                                    different per-file + per-track channel configurations.
715                                 */
716                                 break;
717                                 
718                         default:
719                                 action_strings.push_back (importmode2string (ImportToTrack));
720                                 break;
721                         }
722                 } 
723         }
724
725         action_strings.push_back (importmode2string (ImportAsTrack));
726         action_strings.push_back (importmode2string (ImportAsRegion));
727         action_strings.push_back (importmode2string (ImportAsTapeTrack));
728
729         resetting_ourselves = true;
730
731         existing_choice = action_combo.get_active_text();
732
733         set_popdown_strings (action_combo, action_strings);
734
735         /* preserve any existing choice, if possible */
736
737
738         if (existing_choice.length()) {
739                 vector<string>::iterator x;
740                 for (x = action_strings.begin(); x != action_strings.end(); ++x) {
741                         if (*x == existing_choice) {
742                                 action_combo.set_active_text (existing_choice);
743                                 break;
744                         }
745                 }
746                 if (x == action_strings.end()) {
747                         action_combo.set_active_text (action_strings.front());
748                 }
749         } else {
750                 action_combo.set_active_text (action_strings.front());
751         }
752
753         resetting_ourselves = false;
754
755         if ((mode = get_mode()) == ImportAsRegion) {
756                 where_combo.set_sensitive (false);
757         } else {
758                 where_combo.set_sensitive (true);
759         }
760
761         vector<string> channel_strings;
762         
763         if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
764                 channel_strings.push_back (_("one track per file"));
765
766                 if (selection_includes_multichannel) {
767                         channel_strings.push_back (_("one track per channel"));
768                 }
769
770                 if (paths.size() > 1) {
771                         /* tape tracks are a single region per track, so we cannot
772                            sequence multiple files.
773                         */
774                         if (mode != ImportAsTapeTrack) {
775                                 channel_strings.push_back (_("sequence files"));
776                         }
777                         if (same_size) {
778                                 channel_strings.push_back (_("all files in one region"));
779                         }
780                         
781                 }
782
783         } else {
784                 channel_strings.push_back (_("one region per file"));
785
786                 if (selection_includes_multichannel) {
787                         channel_strings.push_back (_("one region per channel"));
788                 }
789
790                 if (paths.size() > 1) {
791                         if (same_size) {
792                                 channel_strings.push_back (_("all files in one region"));
793                         }
794                 }
795         }
796
797         existing_choice = channel_combo.get_active_text();
798
799         set_popdown_strings (channel_combo, channel_strings);
800
801         /* preserve any existing choice, if possible */
802
803         if (existing_choice.length()) {
804                 vector<string>::iterator x;
805                 for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
806                         if (*x == existing_choice) {
807                                 channel_combo.set_active_text (existing_choice);
808                                 break;
809                         }
810                 }
811                 if (x == channel_strings.end()) {
812                         channel_combo.set_active_text (channel_strings.front());
813                 }
814         } else {
815                 channel_combo.set_active_text (channel_strings.front());
816         }
817
818         if (src_needed) {
819                 src_combo.set_sensitive (true);
820         } else {
821                 src_combo.set_sensitive (false);
822         }
823         
824         if (Config->get_only_copy_imported_files()) {
825
826                 if (selection_can_be_embedded_with_links) {
827                         copy_files_btn.set_sensitive (true);
828                 } else {
829                         copy_files_btn.set_sensitive (false);
830                 }
831
832         }  else {
833
834                 copy_files_btn.set_sensitive (true);
835         }
836         
837         return true;
838 }       
839
840
841 bool
842 SoundFileOmega::bad_file_message()
843 {
844         MessageDialog msg (*this, 
845                            _("One or more of the selected files\ncannot be used by Ardour"),
846                            true,
847                            Gtk::MESSAGE_INFO,
848                            Gtk::BUTTONS_OK);
849         msg.run ();
850         resetting_ourselves = true;
851         chooser.unselect_uri (chooser.get_preview_uri());
852         resetting_ourselves = false;
853
854         return false;
855 }
856
857 bool
858 SoundFileOmega::check_info (const vector<ustring>& paths, bool& same_size, bool& src_needed, bool& multichannel)
859 {
860         SNDFILE* sf;
861         SF_INFO info;
862         nframes64_t sz = 0;
863         bool err = false;
864
865         same_size = true;
866         src_needed = false;
867         multichannel = false;
868
869         for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
870
871                 info.format = 0; // libsndfile says to clear this before sf_open().
872                 
873                 if ((sf = sf_open ((char*) (*i).c_str(), SFM_READ, &info)) != 0) { 
874                         sf_close (sf);
875
876                         if (info.channels > 1) {
877                                 multichannel = true;
878                         }
879
880                         if (sz == 0) {
881                                 sz = info.frames;
882                         } else {
883                                 if (sz != info.frames) {
884                                         same_size = false;
885                                 }
886                         }
887
888                         if ((nframes_t) info.samplerate != session->frame_rate()) {
889                                 src_needed = true;
890                         }
891
892                 } else {
893                         err = true;
894                 }
895         }
896
897         return err;
898 }
899
900
901 bool
902 SoundFileOmega::check_link_status (const Session& s, const vector<ustring>& paths)
903 {
904         sys::path path = s.session_directory().sound_path() / "linktest";
905         string tmpdir = path.to_string();
906         bool ret = false;
907
908         if (mkdir (tmpdir.c_str(), 0744)) {
909                 if (errno != EEXIST) {
910                         return false;
911                 }
912         }
913         
914         for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
915
916                 char tmpc[MAXPATHLEN+1];
917
918                 snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
919
920                 /* can we link ? */
921
922                 if (link ((*i).c_str(), tmpc)) {
923                         goto out;
924                 }
925                 
926                 unlink (tmpc);
927         }
928
929         ret = true;
930
931   out:
932         rmdir (tmpdir.c_str());
933         return ret;
934 }
935
936 SoundFileChooser::SoundFileChooser (Gtk::Window& parent, string title, ARDOUR::Session* s)
937         : SoundFileBrowser (parent, title, s, false)
938 {
939         chooser.set_select_multiple (false);
940         found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
941 }
942
943 void
944 SoundFileChooser::on_hide ()
945 {
946         ArdourDialog::on_hide();
947         stop_metering ();
948
949         if (session) {
950                 session->cancel_audition();
951         }
952 }
953
954 ustring
955 SoundFileChooser::get_filename ()
956 {
957         vector<ustring> paths;
958
959         paths = get_paths ();
960
961         if (paths.empty()) {
962                 return ustring ();
963         }
964         
965         if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
966                 return ustring();
967         }
968
969         return paths.front();
970 }
971
972 SoundFileOmega::SoundFileOmega (Gtk::Window& parent, string title, ARDOUR::Session* s, int selected_tracks, bool persistent,
973                                 Editing::ImportMode mode_hint)
974         : SoundFileBrowser (parent, title, s, persistent),
975           copy_files_btn ( _("Copy files to session")),
976           selected_track_cnt (selected_tracks)
977 {
978         VBox* vbox;
979         HBox* hbox;
980         vector<string> str;
981
982         set_size_request (-1, 450);
983         
984         block_two.set_border_width (12);
985         block_three.set_border_width (12);
986         block_four.set_border_width (12);
987         
988         options.set_spacing (12);
989
990         str.clear ();
991         str.push_back (_("use file timestamp"));
992         str.push_back (_("at edit cursor"));
993         str.push_back (_("at playhead"));
994         str.push_back (_("at session start"));
995         set_popdown_strings (where_combo, str);
996         where_combo.set_active_text (str.front());
997
998         Label* l = manage (new Label);
999         l->set_text (_("Add files:"));
1000         
1001         hbox = manage (new HBox);
1002         hbox->set_border_width (12);
1003         hbox->set_spacing (6);
1004         hbox->pack_start (*l, false, false);
1005         hbox->pack_start (action_combo, false, false);
1006         vbox = manage (new VBox);
1007         vbox->pack_start (*hbox, false, false);
1008         options.pack_start (*vbox, false, false);
1009
1010         /* dummy entry for action combo so that it doesn't look odd if we 
1011            come up with no tracks selected.
1012         */
1013
1014         str.clear ();
1015         str.push_back (importmode2string (mode_hint));
1016         set_popdown_strings (action_combo, str);
1017         action_combo.set_active_text (str.front());
1018         action_combo.set_sensitive (false);
1019
1020         l = manage (new Label);
1021         l->set_text (_("Insert:"));
1022
1023         hbox = manage (new HBox);
1024         hbox->set_border_width (12);
1025         hbox->set_spacing (6);
1026         hbox->pack_start (*l, false, false);
1027         hbox->pack_start (where_combo, false, false);
1028         vbox = manage (new VBox);
1029         vbox->pack_start (*hbox, false, false);
1030         options.pack_start (*vbox, false, false);
1031
1032
1033         l = manage (new Label);
1034         l->set_text (_("Mapping:"));
1035
1036         hbox = manage (new HBox);
1037         hbox->set_border_width (12);
1038         hbox->set_spacing (6);
1039         hbox->pack_start (*l, false, false);
1040         hbox->pack_start (channel_combo, false, false);
1041         vbox = manage (new VBox);
1042         vbox->pack_start (*hbox, false, false);
1043         options.pack_start (*vbox, false, false);
1044
1045         str.clear ();
1046         str.push_back (_("one track per file"));
1047         set_popdown_strings (channel_combo, str);
1048         channel_combo.set_active_text (str.front());
1049         channel_combo.set_sensitive (false);
1050
1051         l = manage (new Label);
1052         l->set_text (_("Conversion Quality:"));
1053
1054         hbox = manage (new HBox);
1055         hbox->set_border_width (12);
1056         hbox->set_spacing (6);
1057         hbox->pack_start (*l, false, false);
1058         hbox->pack_start (src_combo, false, false);
1059         vbox = manage (new VBox);
1060         vbox->pack_start (*hbox, false, false);
1061         options.pack_start (*vbox, false, false);
1062
1063         str.clear ();
1064         str.push_back (_("Best"));
1065         str.push_back (_("Good"));
1066         str.push_back (_("Quick"));
1067         str.push_back (_("Fast"));
1068         str.push_back (_("Fastest"));
1069
1070         set_popdown_strings (src_combo, str);
1071         src_combo.set_active_text (str.front());
1072         src_combo.set_sensitive (false);
1073
1074         reset_options ();
1075
1076         action_combo.signal_changed().connect (mem_fun (*this, &SoundFileOmega::reset_options_noret));
1077         
1078         copy_files_btn.set_active (true);
1079
1080         block_four.pack_start (copy_files_btn, false, false);
1081
1082         options.pack_start (block_four, false, false);
1083
1084         get_vbox()->pack_start (options, false, false);
1085
1086         /* setup disposition map */
1087
1088         disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
1089         disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
1090         disposition_map.insert (pair<ustring,ImportDisposition>(_("merge files"), ImportMergeFiles));
1091         disposition_map.insert (pair<ustring,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
1092
1093         disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
1094         disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
1095         disposition_map.insert (pair<ustring,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
1096
1097         chooser.signal_selection_changed().connect (mem_fun (*this, &SoundFileOmega::file_selection_changed));
1098 }
1099
1100 void
1101 SoundFileOmega::set_mode (ImportMode mode)
1102 {
1103         action_combo.set_active_text (importmode2string (mode));
1104 }
1105
1106 ImportMode
1107 SoundFileOmega::get_mode () const
1108 {
1109         return string2importmode (action_combo.get_active_text());
1110 }
1111
1112 void
1113 SoundFileOmega::on_hide ()
1114 {
1115         ArdourDialog::on_hide();
1116         if (session) {
1117                 session->cancel_audition();
1118         }
1119 }
1120
1121 ImportPosition
1122 SoundFileOmega::get_position() const
1123 {
1124         ustring str = where_combo.get_active_text();
1125
1126         if (str == _("use file timestamp")) {
1127                 return ImportAtTimestamp;
1128         } else if (str == _("at edit cursor")) {
1129                 return ImportAtEditCursor;
1130         } else if (str == _("at playhead")) {
1131                 return ImportAtPlayhead;
1132         } else {
1133                 return ImportAtStart;
1134         }
1135 }
1136
1137 SrcQuality
1138 SoundFileOmega::get_src_quality() const
1139 {
1140         ustring str = where_combo.get_active_text();
1141
1142         if (str == _("Best")) {
1143                 return SrcBest;
1144         } else if (str == _("Good")) {
1145                 return SrcGood;
1146         } else if (str == _("Quick")) {
1147                 return SrcQuick;
1148         } else if (str == _("Fast")) {
1149                 return SrcFast;
1150         } else {
1151                 return SrcFastest;
1152         }
1153 }
1154
1155 ImportDisposition
1156 SoundFileOmega::get_channel_disposition () const
1157 {
1158         /* we use a map here because the channel combo can contain different strings
1159            depending on the state of the other combos. the map contains all possible strings
1160            and the ImportDisposition enum that corresponds to it.
1161         */
1162
1163         ustring str = channel_combo.get_active_text();
1164         DispositionMap::const_iterator x = disposition_map.find (str);
1165
1166         if (x == disposition_map.end()) {
1167                 fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
1168                 /*NOTREACHED*/
1169         }
1170
1171         return x->second;
1172 }
1173
1174 void
1175 SoundFileOmega::reset (int selected_tracks)
1176 {
1177         selected_track_cnt = selected_tracks;
1178         reset_options ();
1179 }       
1180
1181 void
1182 SoundFileOmega::file_selection_changed ()
1183 {
1184         if (resetting_ourselves) {
1185                 return;
1186         }
1187
1188         if (!reset_options ()) {
1189                 set_response_sensitive (RESPONSE_OK, false);
1190         } else {
1191                 if (chooser.get_filenames().size() > 0) {
1192                         set_response_sensitive (RESPONSE_OK, true);
1193                 } else {
1194                         set_response_sensitive (RESPONSE_OK, false);
1195                 }
1196         }
1197 }
1198