Update NTK.
[nondaw.git] / timeline / src / Engine / Track.C
blob1c9c288bec170c2aed09f3ce41df98ff251f6e1b
2 /*******************************************************************************/
3 /* Copyright (C) 2008 Jonathan Moore Liles                                     */
4 /*                                                                             */
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.                                                  */
9 /*                                                                             */
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   */
13 /* more details.                                                               */
14 /*                                                                             */
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 /*******************************************************************************/
20 #include "../Track.H"
21 #include "../Transport.H" // for rolling
22 #include "../Control_Sequence.H"
24 #include "Playback_DS.H"
25 #include "Record_DS.H"
26 #include "Engine.H"
30 /**********/
31 /* Engine */
32 /**********/
34 const Audio_Region *
35 Track::capture_region ( void ) const
37     if ( record_ds )
38         return record_ds->capture_region();
39     else
40         return NULL;
43 Track::Capture *
44 Track::capture ( void )
46     if ( record_ds )
47         return record_ds->capture();
48     else
49         return NULL;
52 void
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(); */
67 bool
68 Track::configure_outputs ( int n )
70     int on = output.size();
72     if ( n == on )
73         return true;
75 //    engine->lock();
77     if ( playback_ds )
78     {
79         Playback_DS *ds = playback_ds;
80         playback_ds = NULL;
82         delete ds;
83     }
85     if ( n > on )
86     {
87         for ( int i = on; i < n; ++i )
88         {
89             JACK::Port p( engine, JACK::Port::Output, name(), i );
91             if ( !p.activate() )
92             {
93                 FATAL( "could not created output port!");
94             }
96             if ( p.valid() )
97                 output.push_back( p );
98             else
99                 WARNING( "could not create output port!" );
100         }
101     }
102     else
103     {
104         for ( int i = on; i > n; --i )
105         {
106             output.back().shutdown();
107             output.pop_back();
108         }
109     }
111     if ( output.size() )
112         playback_ds = new Playback_DS( this, engine->frame_rate(), engine->nframes(), output.size() );
114 //    engine->unlock();
115     /* FIXME: bogus */
116     return true;
119 bool
120 Track::configure_inputs ( int n )
122     int on = input.size();
124     if ( n == on )
125         return true;
127 //    engine->lock();
129     if ( record_ds )
130     {
131         Record_DS *ds = record_ds;
132         record_ds = NULL;
134         delete ds;
135     }
137     if ( n > on )
138     {
139         for ( int i = on; i < n; ++i )
140         {
141             JACK::Port p( engine, JACK::Port::Input, name(), i );
143             if ( !p.activate() )
144             {
145                 FATAL( "could not created output port!");
146             }
148             if ( p.valid() )
149                 input.push_back( p );
150             else
151                 WARNING( "could not create input port!" );
152         }
153     }
154     else
155     {
156         for ( int i = on; i > n; --i )
157         {
158             input.back().shutdown();
159             input.pop_back();
160         }
161     }
163     if ( input.size() )
164         record_ds = new Record_DS( this, engine->frame_rate(), engine->nframes(), input.size() );
166 //    engine->unlock();
168     /* FIXME: bogus */
169     return true;
172 nframes_t
173 Track::process_input ( nframes_t nframes )
175     THREAD_ASSERT( RT );
177     if ( ! transport->rolling )
178     {
179         /* There is no work to do when we're not rolling. */
181         return 0;
182     }
184     if ( record_ds )
185         return record_ds->process( nframes );
186     else
187         return 0;
191 nframes_t
192 Track::process_output ( nframes_t nframes )
194     THREAD_ASSERT( RT );
196     if ( ! transport->rolling )
197     {
198         for ( int i = output.size(); i--; )
199             output[ i ].silence( nframes );
201         return 0;
202     }
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 );
208     if ( playback_ds )
209         return playback_ds->process( nframes );
210     else
211         return 0;
216 void
217 Track::seek ( nframes_t frame )
219     THREAD_ASSERT( RT );
221     if ( playback_ds )
222         return playback_ds->seek( frame );
225 void
226 Track::delay ( nframes_t frames )
228 //    THREAD_ASSERT( RT );
230     if ( playback_ds )
231         playback_ds->delay( frames );
234 /* THREAD: RT (non-RT) */
235 void
236 Track::resize_buffers ( nframes_t nframes )
238     if ( record_ds )
239         record_ds->resize_buffers( nframes );
240     if ( playback_ds )
241         playback_ds->resize_buffers( nframes );
244 #include <time.h>
246 /** very cheap UUID generator... */
247 unsigned long long
248 uuid ( void )
250     time_t t = time( NULL );
252     return (unsigned long long) t;
255 /** create capture region and prepare to record */
256 void
257 Track::record ( Capture *c, nframes_t frame )
259     THREAD_ASSERT( Capture );
261     char *pat;
263     asprintf( &pat, "%s-%llu", name(), uuid() );
265     c->audio_file = Audio_File_SF::create( pat, engine->sample_rate(), input.size(), Track::capture_format );
267     free( pat );
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 */
281 void
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 );
291 #include <stdio.h>
293 void
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
304      * them */
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;