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