add SRC quality to import dialog; fix instances of missing waveforms where new source...
[ardour.git] / gtk2_ardour / editor_audio_import.cc
1 /*
2     Copyright (C) 2000-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 <sys/types.h>
21 #include <sys/stat.h>
22 #include <errno.h>
23 #include <unistd.h>
24
25 #include <sndfile.h>
26
27 #include <pbd/pthread_utils.h>
28 #include <pbd/basename.h>
29 #include <pbd/shortpath.h>
30
31 #include <gtkmm2ext/choice.h>
32 #include <gtkmm2ext/window_title.h>
33
34 #include <ardour/session.h>
35 #include <ardour/audioplaylist.h>
36 #include <ardour/audioregion.h>
37 #include <ardour/audio_diskstream.h>
38 #include <ardour/utils.h>
39 #include <ardour/audio_track.h>
40 #include <ardour/audioplaylist.h>
41 #include <ardour/audiofilesource.h>
42 #include <ardour/region_factory.h>
43 #include <ardour/source_factory.h>
44 #include <pbd/memento_command.h>
45
46 #include "ardour_ui.h"
47 #include "editor.h"
48 #include "sfdb_ui.h"
49 #include "editing.h"
50 #include "audio_time_axis.h"
51 #include "utils.h"
52
53 #include "i18n.h"
54
55 using namespace std;
56 using namespace ARDOUR;
57 using namespace PBD;
58 using namespace sigc;
59 using namespace Gtk;
60 using namespace Gtkmm2ext;
61 using namespace Editing;
62 using Glib::ustring;
63
64 /* Functions supporting the incorporation of external (non-captured) audio material into ardour */
65
66 void
67 Editor::add_external_audio_action (ImportMode mode)
68 {
69 }
70
71 void
72 Editor::external_audio_dialog ()
73 {
74         vector<Glib::ustring> paths;
75
76         if (session == 0) {
77                 MessageDialog msg (0, _("You can't import or embed an audiofile until you have a session loaded."));
78                 msg.run ();
79                 return;
80         }
81         
82         if (sfbrowser == 0) {
83                 sfbrowser = new SoundFileOmega (*this, _("Add existing audio"), session, selection->tracks.size());
84         } else {
85                 sfbrowser->reset (selection->tracks.size());
86         }
87
88         sfbrowser->show_all ();
89
90   again:
91         int response = sfbrowser->run ();
92
93         switch (response) {
94         case RESPONSE_APPLY:
95                 // leave the dialog open
96                 break;
97
98         case RESPONSE_OK:
99                 sfbrowser->hide ();
100                 break;
101         default:
102                 // cancel from the browser - we are done
103                 sfbrowser->hide ();
104                 return;
105         }
106
107         /* lets do it */
108         
109         paths = sfbrowser->get_paths ();
110
111         ImportPosition pos = sfbrowser->get_position ();
112         ImportMode mode = sfbrowser->get_mode ();
113         ImportDisposition chns = sfbrowser->get_channel_disposition ();
114         nframes64_t where;
115
116         switch (pos) {
117         case ImportAtEditCursor:
118                 where = edit_cursor->current_frame;
119                 break;
120         case ImportAtTimestamp:
121                 where = -1;
122                 break;
123         case ImportAtPlayhead:
124                 where = playhead_cursor->current_frame;
125                 break;
126         case ImportAtStart:
127                 where = session->current_start_frame();
128                 break;
129         }
130
131         SrcQuality quality = sfbrowser->get_src_quality();
132
133         if (sfbrowser->copy_files_btn.get_active()) {
134                 do_import (paths, chns, mode, quality, where);
135         } else {
136                 do_embed (paths, chns, mode, where);
137         }
138
139         if (response == RESPONSE_APPLY) {
140                 sfbrowser->clear_selection ();
141                 goto again;
142         }
143 }
144
145 boost::shared_ptr<AudioTrack>
146 Editor::get_nth_selected_audio_track (int nth) const
147 {
148         AudioTimeAxisView* atv;
149         TrackSelection::iterator x;
150         
151         for (x = selection->tracks.begin(); nth > 0 && x != selection->tracks.end(); ++x) {
152                 if (dynamic_cast<AudioTimeAxisView*>(*x)) {
153                         --nth;
154                 }
155         }
156         
157         if (x == selection->tracks.end()) {
158                 atv = dynamic_cast<AudioTimeAxisView*>(selection->tracks.back());
159         } else {
160                 atv = dynamic_cast<AudioTimeAxisView*>(*x);
161         }
162         
163         if (!atv) {
164                 return boost::shared_ptr<AudioTrack>();
165         }
166         
167         return atv->audio_track();
168 }       
169
170 void
171 Editor::do_import (vector<ustring> paths, ImportDisposition chns, ImportMode mode, SrcQuality quality, nframes64_t& pos)
172 {
173         boost::shared_ptr<AudioTrack> track;
174         vector<ustring> to_import;
175         bool ok = false;
176         int nth = 0;
177
178         if (interthread_progress_window == 0) {
179                 build_interthread_progress_window ();
180         }
181
182         switch (chns) {
183         case Editing::ImportDistinctFiles:
184                 for (vector<ustring>::iterator a = paths.begin(); a != paths.end(); ++a) {
185
186                         to_import.clear ();
187                         to_import.push_back (*a);
188
189                         if (mode == Editing::ImportToTrack) {
190                                 track = get_nth_selected_audio_track (nth++);
191                         }
192                         
193                         if (import_sndfiles (to_import, mode, quality, pos, 1, -1, track)) {
194                                 goto out;
195                         }
196
197                 }
198                 break;
199
200         case Editing::ImportDistinctChannels:
201                 for (vector<ustring>::iterator a = paths.begin(); a != paths.end(); ++a) {
202
203                         to_import.clear ();
204                         to_import.push_back (*a);
205
206                         if (import_sndfiles (to_import, mode, quality, pos, -1, -1, track)) {
207                                 goto out;
208                         }
209
210                 }
211                 break;
212
213         case Editing::ImportMergeFiles:
214                 /* create 1 region from all paths, add to 1 track,
215                    ignore "track"
216                 */
217                 if (import_sndfiles (paths, mode, quality, pos, 1, 1, track)) {
218                         goto out;
219                 }
220                 break;
221
222         case Editing::ImportSerializeFiles:
223                 for (vector<ustring>::iterator a = paths.begin(); a != paths.end(); ++a) {
224
225                         to_import.clear ();
226                         to_import.push_back (*a);
227                         
228                         /* create 1 region from this path, add to 1 track,
229                            reuse "track" across paths
230                         */
231
232                         if (import_sndfiles (to_import, mode, quality, pos, 1, 1, track)) {
233                                 goto out;
234                         }
235
236                 }
237                 break;
238         }
239
240         ok = true;
241         
242   out:  
243         if (ok) {
244                 session->save_state ("");
245         }
246
247         interthread_progress_window->hide_all ();
248 }
249
250 bool
251 Editor::idle_do_embed (vector<ustring> paths, ImportDisposition chns, ImportMode mode, nframes64_t& pos)
252 {
253         _do_embed (paths, chns, mode, pos);
254         return false;
255 }
256
257 void
258 Editor::do_embed (vector<ustring> paths, ImportDisposition chns, ImportMode mode, nframes64_t& pos)
259 {
260 #ifdef GTKOSX
261         Glib::signal_idle().connect (bind (mem_fun (*this, &Editor::idle_do_embed), paths, chns, mode, pos));
262 #else
263         _do_embed (paths, chns, mode, pos);
264 #endif
265 }
266
267 void
268 Editor::_do_embed (vector<ustring> paths, ImportDisposition chns, ImportMode mode, nframes64_t& pos)
269 {
270         boost::shared_ptr<AudioTrack> track;
271         bool check_sample_rate = true;
272         bool ok = false;
273         vector<ustring> to_embed;
274         bool multi = paths.size() > 1;
275         int nth = 0;
276
277         switch (chns) {
278         case Editing::ImportDistinctFiles:
279                 for (vector<ustring>::iterator a = paths.begin(); a != paths.end(); ++a) {
280
281                         to_embed.clear ();
282                         to_embed.push_back (*a);
283
284                         if (mode == Editing::ImportToTrack) {
285                                 track = get_nth_selected_audio_track (nth++);
286                         }
287
288                         if (embed_sndfiles (to_embed, multi, check_sample_rate, mode, pos, 1, -1, track) < -1) {
289                                 goto out;
290                         }
291                 }
292                 break;
293                 
294         case Editing::ImportDistinctChannels:
295                 for (vector<ustring>::iterator a = paths.begin(); a != paths.end(); ++a) {
296
297                         to_embed.clear ();
298                         to_embed.push_back (*a);
299
300                         if (embed_sndfiles (to_embed, multi, check_sample_rate, mode, pos, -1, -1, track) < -1) {
301                                 goto out;
302                         }
303                 }
304                 break;
305
306         case Editing::ImportMergeFiles:
307                 if (embed_sndfiles (paths, multi, check_sample_rate, mode, pos, 1, 1, track) < -1) {
308                         goto out;
309                 }
310         break;
311
312         case Editing::ImportSerializeFiles:
313                 for (vector<ustring>::iterator a = paths.begin(); a != paths.end(); ++a) {
314
315                         to_embed.clear ();
316                         to_embed.push_back (*a);
317
318                         if (embed_sndfiles (to_embed, multi, check_sample_rate, mode, pos, 1, 1, track) < -1) {
319                                 goto out;
320                         }
321                 }
322                 break;
323         }
324
325         ok = true;
326         
327   out:  
328         if (ok) {
329                 session->save_state ("");
330         }
331 }
332
333 int
334 Editor::import_sndfiles (vector<ustring> paths, ImportMode mode, SrcQuality quality, nframes64_t& pos, 
335                          int target_regions, int target_tracks, boost::shared_ptr<AudioTrack>& track)
336 {
337         WindowTitle title = string_compose (_("importing %1"), paths.front());
338
339         interthread_progress_window->set_title (title.get_string());
340         interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
341         interthread_progress_window->show_all ();
342         interthread_progress_bar.set_fraction (0.0f);
343         interthread_cancel_label.set_text (_("Cancel Import"));
344         current_interthread_info = &import_status;
345
346         import_status.paths = paths;
347         import_status.done = false;
348         import_status.cancel = false;
349         import_status.freeze = false;
350         import_status.done = 0.0;
351         import_status.quality = quality;
352
353         interthread_progress_connection = Glib::signal_timeout().connect 
354                 (bind (mem_fun(*this, &Editor::import_progress_timeout), (gpointer) 0), 100);
355         
356         track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
357         ARDOUR_UI::instance()->flush_pending ();
358
359         /* start import thread for this spec. this will ultimately call Session::import_audiofile()
360            and if successful will add the file(s) as a region to the session region list.
361         */
362         
363         pthread_create_and_store ("import", &import_status.thread, 0, _import_thread, this);
364         pthread_detach (import_status.thread);
365         
366         while (!(import_status.done || import_status.cancel)) {
367                 gtk_main_iteration ();
368         }
369
370         interthread_progress_window->hide ();
371         
372         import_status.done = true;
373         interthread_progress_connection.disconnect ();
374         
375         /* import thread finished - see if we should build a new track */
376
377         boost::shared_ptr<AudioRegion> r;
378         
379         if (import_status.cancel || import_status.sources.empty()) {
380                 goto out;
381         }
382
383         if (add_sources (paths, import_status.sources, pos, mode, target_regions, target_tracks, track, false) == 0) {
384                 session->save_state ("");
385         }
386
387   out:
388         track_canvas.get_window()->set_cursor (*current_canvas_cursor);
389         return 0;
390 }
391
392 int
393 Editor::embed_sndfiles (vector<Glib::ustring> paths, bool multifile,
394                         bool& check_sample_rate, ImportMode mode, nframes64_t& pos, int target_regions, int target_tracks,
395                         boost::shared_ptr<AudioTrack>& track)
396 {
397         boost::shared_ptr<AudioFileSource> source;
398         SourceList sources;
399         string linked_path;
400         SoundFileInfo finfo;
401         int ret = 0;
402
403         track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
404         ARDOUR_UI::instance()->flush_pending ();
405
406         for (vector<Glib::ustring>::iterator p = paths.begin(); p != paths.end(); ++p) {
407
408                 ustring path = *p;
409
410                 /* lets see if we can link it into the session */
411                 
412                 linked_path = session->sound_dir();
413                 linked_path += '/';
414                 linked_path += Glib::path_get_basename (path);
415                 
416                 if (link (path.c_str(), linked_path.c_str()) == 0) {
417
418                         /* there are many reasons why link(2) might have failed.
419                            but if it succeeds, we now have a link in the
420                            session sound dir that will protect against
421                            unlinking of the original path. nice.
422                         */
423                         
424                         path = linked_path;
425
426                 } else {
427
428                         /* one possible reason is that its already linked */
429
430                         if (errno == EEXIST) {
431                                 struct stat sb;
432
433                                 if (stat (linked_path.c_str(), &sb) == 0) {
434                                         if (sb.st_nlink > 1) { // its a hard link, assume its the one we want
435                                                 path = linked_path;
436                                         }
437                                 }
438                         }
439                 }
440                 
441                 /* note that we temporarily truncated _id at the colon */
442                 
443                 string error_msg;
444
445                 if (!AudioFileSource::get_soundfile_info (path, finfo, error_msg)) {
446                         error << string_compose(_("Editor: cannot open file \"%1\", (%2)"), path, error_msg ) << endmsg;
447                         goto out;
448                 }
449                 
450                 if (check_sample_rate  && (finfo.samplerate != (int) session->frame_rate())) {
451                         vector<string> choices;
452                         
453                         if (multifile) {
454                                 choices.push_back (_("Cancel entire import"));
455                                 choices.push_back (_("Don't embed it"));
456                                 choices.push_back (_("Embed all without questions"));
457                         
458                                 Gtkmm2ext::Choice rate_choice (
459                                         string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"), 
460                                                         short_path (path, 40)),
461                                         choices, false);
462                                 
463                                 int resx = rate_choice.run ();
464                                 
465                                 switch (resx) {
466                                 case 0: /* stop a multi-file import */
467                                         ret = -2;
468                                         goto out;
469                                 case 1: /* don't embed this one */
470                                         ret = -1;
471                                         goto out;
472                                 case 2: /* do it, and the rest without asking */
473                                         check_sample_rate = false;
474                                         break;
475                                 case 3: /* do it */
476                                         break;
477                                 default:
478                                         ret = -2;
479                                         goto out;
480                                 }
481                         } else {
482                                 choices.push_back (_("Cancel"));
483                                 choices.push_back (_("Embed it anyway"));
484                         
485                                 Gtkmm2ext::Choice rate_choice (
486                                         string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"), path),
487                                         choices, false);
488                                 
489                                 int resx = rate_choice.run ();
490                                 
491                                 switch (resx) {
492                                 case 0: /* don't import */
493                                         ret = -1;
494                                         goto out;
495                                 case 1: /* do it */
496                                         break;
497                                 default:
498                                         ret = -2;
499                                         goto out;
500                                 }
501                         }
502                 }
503                 
504                 track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
505
506                 for (int n = 0; n < finfo.channels; ++n) {
507                         try {
508
509                                 /* check if we have this thing embedded already */
510
511                                 boost::shared_ptr<Source> s;
512
513                                 if ((s = session->source_by_path_and_channel (path, n)) == 0) {
514                                         source = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable 
515                                                                                                (*session, path,  n,
516                                                                                                 (mode == ImportAsTapeTrack ? 
517                                                                                                  AudioFileSource::Destructive : 
518                                                                                                  AudioFileSource::Flag (0)),
519                                                                                                 true, true));
520                                 } else {
521                                         source = boost::dynamic_pointer_cast<AudioFileSource> (s);
522                                 }
523
524                                 sources.push_back(source);
525                         } 
526                         
527                         catch (failed_constructor& err) {
528                                 error << string_compose(_("could not open %1"), path) << endmsg;
529                                 goto out;
530                         }
531                         
532                         ARDOUR_UI::instance()->flush_pending ();
533                 }
534         }
535
536         if (sources.empty()) {
537                 goto out;
538         }
539
540         ret = add_sources (paths, sources, pos, mode, target_regions, target_tracks, track, true);
541
542   out:
543         track_canvas.get_window()->set_cursor (*current_canvas_cursor);
544         return ret;
545 }
546
547 int
548 Editor::add_sources (vector<Glib::ustring> paths, SourceList& sources, nframes64_t& pos, ImportMode mode, 
549                      int target_regions, int target_tracks, boost::shared_ptr<AudioTrack>& track, bool add_channel_suffix)
550 {
551         vector<boost::shared_ptr<AudioRegion> > regions;
552         ustring region_name;
553         uint32_t input_chan = 0;
554         uint32_t output_chan = 0;
555
556         if (pos == -1) { // "use timestamp"
557                 if (sources[0]->natural_position() != 0) {
558                         pos = sources[0]->natural_position();
559                 } else {
560                         // XXX is this the best alternative ?
561                         pos = edit_cursor->current_frame;
562                 }
563         }
564
565         if (target_regions == 1) {
566
567                 /* take all the sources we have and package them up as a region */
568
569                 region_name = region_name_from_path (paths.front(), (sources.size() > 1), false);
570                 
571                 regions.push_back (boost::dynamic_pointer_cast<AudioRegion> 
572                                    (RegionFactory::create (sources, 0, sources[0]->length(), region_name, 0,
573                                                            Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External))));
574                 
575         } else if (target_regions == -1) {
576
577                 /* take each source and create a region for each one */
578
579                 SourceList just_one;
580                 SourceList::iterator x;
581                 uint32_t n;
582
583                 for (n = 0, x = sources.begin(); x != sources.end(); ++x, ++n) {
584
585                         just_one.clear ();
586                         just_one.push_back (*x);
587                         
588                         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (*x);
589
590                         region_name = region_name_from_path (afs->path(), false, true, sources.size(), n);
591
592                         cerr << "got region name " << region_name << endl;
593                         
594                         regions.push_back (boost::dynamic_pointer_cast<AudioRegion> 
595                                            (RegionFactory::create (just_one, 0, (*x)->length(), region_name, 0,
596                                                                    Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External))));
597
598                 }
599         }
600
601         if (target_regions == 1) {
602                 input_chan = regions.front()->n_channels();
603         } else {
604                 if (target_tracks == 1) {
605                         input_chan = regions.size();
606                 } else {
607                         input_chan = 1;
608                 }
609         }
610
611         if (Config->get_output_auto_connect() & AutoConnectMaster) {
612                 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
613         } else {
614                 output_chan = input_chan;
615         }
616
617         int n = 0;
618
619         for (vector<boost::shared_ptr<AudioRegion> >::iterator r = regions.begin(); r != regions.end(); ++r, ++n) {
620
621                 finish_bringing_in_audio (*r, input_chan, output_chan, pos, mode, track);
622                 
623                 if (target_tracks != 1) {
624                         track.reset ();
625                 } else {
626                         pos += (*r)->length();
627                 } 
628         }
629
630         return 0;
631 }
632         
633 int
634 Editor::finish_bringing_in_audio (boost::shared_ptr<AudioRegion> region, uint32_t in_chans, uint32_t out_chans, nframes64_t& pos, 
635                                   ImportMode mode, boost::shared_ptr<AudioTrack>& existing_track)
636 {
637
638         switch (mode) {
639         case ImportAsRegion:
640                 /* relax, its been done */
641                 break;
642                 
643         case ImportToTrack:
644         {
645                 if (!existing_track) {
646
647                         if (selection->tracks.empty()) {
648                                 return -1;
649                         }
650                         
651                         AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(selection->tracks.front());
652                         
653                         if (!atv) {
654                                 return -1;
655                         }
656                         
657                         existing_track = atv->audio_track();
658                 }
659
660                 boost::shared_ptr<Playlist> playlist = existing_track->diskstream()->playlist();
661                 boost::shared_ptr<AudioRegion> copy (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (region)));
662                 begin_reversible_command (_("insert sndfile"));
663                 XMLNode &before = playlist->get_state();
664                 playlist->add_region (copy, pos);
665                 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
666                 commit_reversible_command ();
667                 break;
668         }
669
670         case ImportAsTrack:
671         { 
672                 if (!existing_track) {
673                         list<boost::shared_ptr<AudioTrack> > at (session->new_audio_track (in_chans, out_chans, Normal, 1));
674
675                         if (at.empty()) {
676                                 return -1;
677                         }
678
679                         existing_track = at.front();
680                         existing_track->set_name (region->name(), this);
681                 }
682
683                 boost::shared_ptr<AudioRegion> copy (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (region)));
684                 existing_track->diskstream()->playlist()->add_region (copy, pos);
685                 break;
686         }
687
688
689         case ImportAsTapeTrack:
690         {
691                 list<boost::shared_ptr<AudioTrack> > at (session->new_audio_track (in_chans, out_chans, Destructive));
692                 if (!at.empty()) {
693                         boost::shared_ptr<AudioRegion> copy (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (region)));
694                         at.front()->set_name (basename_nosuffix (copy->name()), this);
695                         at.front()->diskstream()->playlist()->add_region (copy, pos);
696                 }
697                 break;
698         }
699         }
700
701         return 0;
702 }
703
704 void *
705 Editor::_import_thread (void *arg)
706 {
707         PBD::ThreadCreated (pthread_self(), X_("Import"));
708
709         Editor *ed = (Editor *) arg;
710         return ed->import_thread ();
711 }
712
713 void *
714 Editor::import_thread ()
715 {
716         session->import_audiofile (import_status);
717         pthread_exit_pbd (0);
718         /*NOTREACHED*/
719         return 0;
720 }
721
722 gint
723 Editor::import_progress_timeout (void *arg)
724 {
725         interthread_progress_label.set_text (import_status.doing_what);
726
727         if (import_status.freeze) {
728                 interthread_cancel_button.set_sensitive(false);
729         } else {
730                 interthread_cancel_button.set_sensitive(true);
731         }
732
733         if (import_status.doing_what == "building peak files") {
734                 interthread_progress_bar.pulse ();
735                 return FALSE;
736         } else {
737                 interthread_progress_bar.set_fraction (import_status.progress);
738         }
739
740         return !(import_status.done || import_status.cancel);
741 }
742