fix a bad transition in the transportFSM.
[ardour.git] / libs / ardour / filter.cc
1 /*
2  * Copyright (C) 2007-2015 David Robillard <d@drobilla.net>
3  * Copyright (C) 2007-2017 Paul Davis <paul@linuxaudiosystems.com>
4  * Copyright (C) 2009-2010 Carl Hetherington <carl@carlh.net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include <time.h>
22 #include <cerrno>
23
24 #include "pbd/basename.h"
25
26 #include "ardour/analyser.h"
27 #include "ardour/audiofilesource.h"
28 #include "ardour/audioregion.h"
29 #include "ardour/filter.h"
30 #include "ardour/region.h"
31 #include "ardour/region_factory.h"
32 #include "ardour/session.h"
33 #include "ardour/smf_source.h"
34 #include "ardour/source_factory.h"
35
36 #include "pbd/i18n.h"
37
38 using namespace std;
39 using namespace ARDOUR;
40 using namespace PBD;
41
42 int
43 Filter::make_new_sources (boost::shared_ptr<Region> region, SourceList& nsrcs, std::string suffix, bool use_session_sample_rate)
44 {
45         vector<string> names = region->master_source_names();
46         assert (region->n_channels() <= names.size());
47
48         for (uint32_t i = 0; i < region->n_channels(); ++i) {
49
50                 string name = PBD::basename_nosuffix (names[i]);
51
52                 /* remove any existing version of suffix by assuming it starts
53                    with some kind of "special" character.
54                 */
55
56                 if (!suffix.empty()) {
57                         string::size_type pos = name.find (suffix[0]);
58                         if (pos != string::npos && pos > 2) {
59                                 name = name.substr (0, pos - 1);
60                         }
61                 }
62
63                 const string path = (region->data_type() == DataType::MIDI)
64                         ? session.new_midi_source_path (name)
65                         : session.new_audio_source_path (name, region->n_channels(), i, false, false);
66
67                 if (path.empty()) {
68                         error << string_compose (_("filter: error creating name for new file based on %1"), region->name())
69                               << endmsg;
70                         return -1;
71                 }
72
73                 try {
74                         samplecnt_t sample_rate;
75                         if (use_session_sample_rate) {
76                                 sample_rate = session.sample_rate();
77                         } else {
78                                 boost::shared_ptr<AudioRegion> aregion = boost::dynamic_pointer_cast<AudioRegion>(region);
79
80                                 if (aregion) {
81                                         sample_rate = aregion->audio_source()->sample_rate();
82                                 } else {
83                                         return -1;
84                                 }
85                         }
86
87                         nsrcs.push_back (boost::dynamic_pointer_cast<Source> (
88                                                  SourceFactory::createWritable (region->data_type(), session,
89                                                                                 path, false, sample_rate)));
90                 }
91
92                 catch (failed_constructor& err) {
93                         error << string_compose (_("filter: error creating new file %1 (%2)"), path, strerror (errno)) << endmsg;
94                         return -1;
95                 }
96         }
97
98         return 0;
99 }
100
101 int
102 Filter::finish (boost::shared_ptr<Region> region, SourceList& nsrcs, string region_name)
103 {
104         /* update headers on new sources */
105
106         time_t xnow;
107         struct tm* now;
108
109         time (&xnow);
110         now = localtime (&xnow);
111
112         /* this is ugly. */
113         for (SourceList::iterator si = nsrcs.begin(); si != nsrcs.end(); ++si) {
114                 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*si);
115                 if (afs) {
116                         afs->done_with_peakfile_writes ();
117                         afs->update_header (region->position(), *now, xnow);
118                         afs->mark_immutable ();
119                 }
120
121                 boost::shared_ptr<SMFSource> smfs = boost::dynamic_pointer_cast<SMFSource>(*si);
122                 if (smfs) {
123                         smfs->set_natural_position (region->position());
124                         smfs->flush ();
125                 }
126
127                 /* now that there is data there, requeue the file for analysis */
128
129                 Analyser::queue_source_for_analysis (*si, false);
130         }
131
132         /* create a new region */
133
134         if (region_name.empty()) {
135                 region_name = RegionFactory::new_region_name (region->name());
136         }
137         results.clear ();
138
139         PropertyList plist;
140
141         plist.add (Properties::start, 0);
142         plist.add (Properties::length, region->length());
143         plist.add (Properties::name, region_name);
144         plist.add (Properties::whole_file, true);
145         plist.add (Properties::position, region->position());
146
147         boost::shared_ptr<Region> r = RegionFactory::create (nsrcs, plist);
148
149         boost::shared_ptr<AudioRegion> audio_region = boost::dynamic_pointer_cast<AudioRegion> (region);
150         boost::shared_ptr<AudioRegion> audio_r = boost::dynamic_pointer_cast<AudioRegion> (r);
151         if (audio_region && audio_r) {
152                 audio_r->set_scale_amplitude (audio_region->scale_amplitude());
153                 audio_r->set_fade_in_active (audio_region->fade_in_active ());
154                 audio_r->set_fade_in (audio_region->fade_in ());
155                 audio_r->set_fade_out_active (audio_region->fade_out_active ());
156                 audio_r->set_fade_out (audio_region->fade_out ());
157                 *(audio_r->envelope()) = *(audio_region->envelope ());
158         }
159         results.push_back (r);
160
161         return 0;
162 }
163
164