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