2 /*******************************************************************************/
3 /* Copyright (C) 2008 Jonathan Moore Liles */
5 /* This program is free software; you can redistribute it and/or modify it */
6 /* under the terms of the GNU General Public License as published by the */
7 /* Free Software Foundation; either version 2 of the License, or (at your */
8 /* option) any later version. */
10 /* This program is distributed in the hope that it will be useful, but WITHOUT */
11 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
12 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
15 /* You should have received a copy of the GNU General Public License along */
16 /* with This program; see the file COPYING. If not,write to the Free Software */
17 /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /*******************************************************************************/
21 #include "../Transport.H" // for rolling
22 #include "../Control_Sequence.H"
24 #include "Playback_DS.H"
25 #include "Record_DS.H"
35 Track::capture_region ( void ) const
38 return record_ds->capture_region();
44 Track::capture ( void )
47 return record_ds->capture();
53 Track::update_port_names ( void )
55 for ( unsigned int i = 0; i < output.size(); ++i )
56 output[ i ].name( name(), i );
58 for ( unsigned int i = 0; i < input.size(); ++i )
59 input[ i ].name( name(), i );
61 /* /\* tell any attached control sequences to do the same *\/ */
62 /* for ( int i = control->children(); i-- ) */
63 /* ((Control_Sequence*)control->child( i ))->update_port_names(); */
68 Track::configure_outputs ( int n )
70 int on = output.size();
79 Playback_DS *ds = playback_ds;
87 for ( int i = on; i < n; ++i )
89 JACK::Port p( engine, JACK::Port::Output, name(), i );
93 FATAL( "could not created output port!");
97 output.push_back( p );
99 WARNING( "could not create output port!" );
104 for ( int i = on; i > n; --i )
106 output.back().shutdown();
112 playback_ds = new Playback_DS( this, engine->frame_rate(), engine->nframes(), output.size() );
120 Track::configure_inputs ( int n )
122 int on = input.size();
131 Record_DS *ds = record_ds;
139 for ( int i = on; i < n; ++i )
141 JACK::Port p( engine, JACK::Port::Input, name(), i );
145 FATAL( "could not created output port!");
149 input.push_back( p );
151 WARNING( "could not create input port!" );
156 for ( int i = on; i > n; --i )
158 input.back().shutdown();
164 record_ds = new Record_DS( this, engine->frame_rate(), engine->nframes(), input.size() );
173 Track::process_input ( nframes_t nframes )
177 if ( ! transport->rolling )
179 /* There is no work to do when we're not rolling. */
185 return record_ds->process( nframes );
192 Track::process_output ( nframes_t nframes )
196 if ( ! transport->rolling )
198 for ( int i = output.size(); i--; )
199 output[ i ].silence( nframes );
204 /* FIXME: should we blank the control output here or leave it floating? */
205 for ( int i = 0; i < control->children(); i++ )
206 ((Control_Sequence*)control->child( i ))->process( nframes );
209 return playback_ds->process( nframes );
217 Track::seek ( nframes_t frame )
222 return playback_ds->seek( frame );
226 Track::delay ( nframes_t frames )
228 // THREAD_ASSERT( RT );
231 playback_ds->delay( frames );
234 /* THREAD: RT (non-RT) */
236 Track::resize_buffers ( nframes_t nframes )
239 record_ds->resize_buffers( nframes );
241 playback_ds->resize_buffers( nframes );
246 /** very cheap UUID generator... */
250 time_t t = time( NULL );
252 return (unsigned long long) t;
255 /** create capture region and prepare to record */
257 Track::record ( Capture *c, nframes_t frame )
259 THREAD_ASSERT( Capture );
263 asprintf( &pat, "%s-%llu", name(), uuid() );
265 c->audio_file = Audio_File_SF::create( pat, engine->sample_rate(), input.size(), Track::capture_format );
269 if ( ! c->audio_file )
270 FATAL( "Could not create file for new capture!" );
272 /* open it again for reading in the GUI thread */
273 // Audio_File *af = Audio_File::from_file( c->audio_file->name() );
275 c->region = new Audio_Region( c->audio_file, sequence(), frame );
277 c->region->prepare();
280 /** write a block to the (already opened) capture file */
282 Track::write ( Capture *c, sample_t *buf, nframes_t nframes )
284 THREAD_ASSERT( Capture );
286 nframes_t l = c->audio_file->write( buf, nframes );
288 c->region->write( l );
294 Track::finalize ( Capture *c, nframes_t frame )
296 THREAD_ASSERT( Capture );
298 /* adjust region start for latency */
299 /* FIXME: is just looking at the first channel good enough? */
301 DMESSAGE( "finalizing audio file" );
302 /* must finalize audio before peaks file, otherwise another thread
303 * might think the peaks are out of date and attempt to regenerate
305 c->audio_file->finalize();
307 c->region->finalize( frame );
309 nframes_t capture_offset = 0;
311 /* Add the system latency twice. Once for the input (usually
312 * required) and again for the output latency of whatever we're
313 * playing along to (should only apply when overdubbing) */
315 /* Limitations in the JACK latency reporting API prevent us from
316 * compensating from any software latency introduced by other
317 * clients in our graph... Oh well */
319 capture_offset += engine->system_latency();
320 capture_offset += engine->system_latency();
322 DMESSAGE( "Adjusting capture by %lu frames.", (unsigned long)capture_offset );
324 c->region->offset( capture_offset );
326 // delete c->audio_file;