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