2 Copyright (C) 2000-2006 Paul Davis
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.
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.
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.
35 #include "pbd/error.h"
36 #include "pbd/basename.h"
37 #include <glibmm/thread.h>
38 #include "pbd/xml++.h"
39 #include "pbd/memento_command.h"
41 #include "ardour/ardour.h"
42 #include "ardour/audioengine.h"
43 #include "ardour/debug.h"
44 #include "ardour/diskstream.h"
45 #include "ardour/utils.h"
46 #include "ardour/configuration.h"
47 #include "ardour/audiofilesource.h"
48 #include "ardour/send.h"
49 #include "ardour/playlist.h"
50 #include "ardour/cycle_timer.h"
51 #include "ardour/region.h"
52 #include "ardour/panner.h"
53 #include "ardour/session.h"
54 #include "ardour/io.h"
55 #include "ardour/route.h"
61 using namespace ARDOUR
;
64 /* XXX This goes uninitialized when there is no ~/.config/ardour3 directory.
65 * I can't figure out why, so this will do for now (just stole the
66 * default from configuration_vars.h). 0 is not a good value for
67 * allocating buffer sizes..
69 ARDOUR::nframes_t
Diskstream::disk_io_chunk_frames
= 1024 * 256;
71 PBD::Signal0
<void> Diskstream::DiskOverrun
;
72 PBD::Signal0
<void> Diskstream::DiskUnderrun
;
74 Diskstream::Diskstream (Session
&sess
, const string
&name
, Flag flag
)
75 : SessionObject(sess
, name
)
76 , i_am_the_modifier (0)
79 , _visible_speed (1.0f
)
80 , _actual_speed (1.0f
)
81 , _buffer_reallocation_required (false)
82 , _seek_required (false)
83 , force_refill (false)
84 , capture_start_frame (0)
85 , capture_captured (0)
86 , was_recording (false)
87 , adjust_capture_position (0)
90 , first_recordable_frame (max_frames
)
91 , last_recordable_frame (max_frames
)
92 , last_possibly_recording (0)
93 , _alignment_style (ExistingMaterial
)
98 , overwrite_offset (0)
99 , pending_overwrite (false)
100 , overwrite_queued (false)
101 , input_change_pending (NoChange
)
102 , wrap_buffer_size (0)
103 , speed_buffer_size (0)
105 , _target_speed (_speed
)
107 , playback_sample (0)
108 , playback_distance (0)
109 , _read_data_count (0)
110 , _write_data_count (0)
111 , in_set_state (false)
112 , _persistent_alignment_style (ExistingMaterial
)
113 , first_input_change (true)
115 , scrub_buffer_size (0)
122 Diskstream::Diskstream (Session
& sess
, const XMLNode
& /*node*/)
123 : SessionObject(sess
, "unnamed diskstream")
124 , i_am_the_modifier (0)
126 , _record_enabled (0)
127 , _visible_speed (1.0f
)
128 , _actual_speed (1.0f
)
129 , _buffer_reallocation_required (false)
130 , _seek_required (false)
131 , force_refill (false)
132 , capture_start_frame (0)
133 , capture_captured (0)
134 , was_recording (false)
135 , adjust_capture_position (0)
136 , _capture_offset (0)
138 , first_recordable_frame (max_frames
)
139 , last_recordable_frame (max_frames
)
140 , last_possibly_recording (0)
141 , _alignment_style (ExistingMaterial
)
145 , overwrite_frame (0)
146 , overwrite_offset (0)
147 , pending_overwrite (false)
148 , overwrite_queued (false)
149 , input_change_pending (NoChange
)
150 , wrap_buffer_size (0)
151 , speed_buffer_size (0)
153 , _target_speed (_speed
)
155 , playback_sample (0)
156 , playback_distance (0)
157 , _read_data_count (0)
158 , _write_data_count (0)
159 , in_set_state (false)
160 , _persistent_alignment_style (ExistingMaterial
)
161 , first_input_change (true)
163 , scrub_buffer_size (0)
165 , _flags (Recordable
)
169 Diskstream::~Diskstream ()
171 DEBUG_TRACE (DEBUG::Destruction
, string_compose ("Diskstream %1 deleted\n", _name
));
174 _playlist
->release ();
179 Diskstream::set_route (Route
& r
)
182 _io
= _route
->input();
184 ic_connection
.disconnect();
185 _io
->changed
.connect_same_thread (ic_connection
, boost::bind (&Diskstream::handle_input_change
, this, _1
, _2
));
187 input_change_pending
= ConfigurationChanged
;
188 non_realtime_input_change ();
189 set_align_style_from_io ();
191 _route
->Destroyed
.connect_same_thread (*this, boost::bind (&Diskstream::route_going_away
, this));
195 Diskstream::handle_input_change (IOChange change
, void * /*src*/)
197 Glib::Mutex::Lock
lm (state_lock
);
199 if (!(input_change_pending
& change
)) {
200 input_change_pending
= IOChange (input_change_pending
|change
);
201 _session
.request_input_change_handling ();
206 Diskstream::non_realtime_set_speed ()
208 if (_buffer_reallocation_required
)
210 Glib::Mutex::Lock
lm (state_lock
);
211 allocate_temporary_buffers ();
213 _buffer_reallocation_required
= false;
216 if (_seek_required
) {
217 if (speed() != 1.0f
|| speed() != -1.0f
) {
218 seek ((nframes_t
) (_session
.transport_frame() * (double) speed()), true);
221 seek (_session
.transport_frame(), true);
224 _seek_required
= false;
229 Diskstream::realtime_set_speed (double sp
, bool global
)
231 bool changed
= false;
232 double new_speed
= sp
* _session
.transport_speed();
234 if (_visible_speed
!= sp
) {
239 if (new_speed
!= _actual_speed
) {
241 nframes_t required_wrap_size
= (nframes_t
) floor (_session
.get_block_size() *
242 fabs (new_speed
)) + 1;
244 if (required_wrap_size
> wrap_buffer_size
) {
245 _buffer_reallocation_required
= true;
248 _actual_speed
= new_speed
;
249 _target_speed
= fabs(_actual_speed
);
254 _seek_required
= true;
256 SpeedChanged (); /* EMIT SIGNAL */
259 return _buffer_reallocation_required
|| _seek_required
;
263 Diskstream::set_capture_offset ()
266 /* can't capture, so forget it */
270 _capture_offset
= _io
->latency();
274 Diskstream::set_align_style (AlignStyle a
)
276 if (record_enabled() && _session
.actively_recording()) {
280 if (a
!= _alignment_style
) {
281 _alignment_style
= a
;
282 AlignmentStyleChanged ();
287 Diskstream::set_loop (Location
*location
)
290 if (location
->start() >= location
->end()) {
291 error
<< string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location
->name()) << endl
;
296 loop_location
= location
;
298 LoopSet (location
); /* EMIT SIGNAL */
303 Diskstream::get_capture_start_frame (uint32_t n
)
305 Glib::Mutex::Lock
lm (capture_info_lock
);
307 if (capture_info
.size() > n
) {
308 return capture_info
[n
]->start
;
311 return capture_start_frame
;
316 Diskstream::get_captured_frames (uint32_t n
)
318 Glib::Mutex::Lock
lm (capture_info_lock
);
320 if (capture_info
.size() > n
) {
321 return capture_info
[n
]->frames
;
324 return capture_captured
;
329 Diskstream::set_roll_delay (ARDOUR::nframes_t nframes
)
331 _roll_delay
= nframes
;
335 Diskstream::set_speed (double sp
)
337 _session
.request_diskstream_speed (*this, sp
);
339 /* to force a rebuffering at the right place */
344 Diskstream::use_playlist (boost::shared_ptr
<Playlist
> playlist
)
350 bool no_prior_playlist
= true;
353 Glib::Mutex::Lock
lm (state_lock
);
355 if (playlist
== _playlist
) {
359 playlist_connections
.drop_connections ();
362 _playlist
->release();
363 no_prior_playlist
= false;
366 _playlist
= playlist
;
369 if (!in_set_state
&& recordable()) {
370 reset_write_sources (false);
373 _playlist
->ContentsChanged
.connect_same_thread (playlist_connections
, boost::bind (&Diskstream::playlist_modified
, this));
374 _playlist
->DropReferences
.connect_same_thread (playlist_connections
, boost::bind (&Diskstream::playlist_deleted
, this, boost::weak_ptr
<Playlist
>(_playlist
)));
375 _playlist
->RangesMoved
.connect_same_thread (playlist_connections
, boost::bind (&Diskstream::playlist_ranges_moved
, this, _1
));
378 /* don't do this if we've already asked for it *or* if we are setting up
379 the diskstream for the very first time - the input changed handling will
380 take care of the buffer refill.
383 if (!overwrite_queued
&& no_prior_playlist
) {
384 _session
.request_overwrite_buffer (this);
385 overwrite_queued
= true;
388 PlaylistChanged (); /* EMIT SIGNAL */
389 _session
.set_dirty ();
395 Diskstream::playlist_changed (const PropertyChange
&)
397 playlist_modified ();
401 Diskstream::playlist_modified ()
403 if (!i_am_the_modifier
&& !overwrite_queued
) {
404 _session
.request_overwrite_buffer (this);
405 overwrite_queued
= true;
410 Diskstream::playlist_deleted (boost::weak_ptr
<Playlist
> wpl
)
412 boost::shared_ptr
<Playlist
> pl (wpl
.lock());
414 if (pl
== _playlist
) {
416 /* this catches an ordering issue with session destruction. playlists
417 are destroyed before diskstreams. we have to invalidate any handles
418 we have to the playlist.
428 Diskstream::set_name (const string
& str
)
432 playlist()->set_name (str
);
434 SessionObject::set_name(str
);
436 if (!in_set_state
&& recordable()) {
437 /* rename existing capture files so that they have the correct name */
438 return rename_write_sources ();
448 Diskstream::remove_region_from_last_capture (boost::weak_ptr
<Region
> wregion
)
450 boost::shared_ptr
<Region
> region (wregion
.lock());
456 _last_capture_regions
.remove (region
);
460 Diskstream::playlist_ranges_moved (list
< Evoral::RangeMove
<framepos_t
> > const & movements_frames
)
462 if (!_route
|| Config
->get_automation_follows_regions () == false) {
466 list
< Evoral::RangeMove
<double> > movements
;
468 for (list
< Evoral::RangeMove
<framepos_t
> >::const_iterator i
= movements_frames
.begin();
469 i
!= movements_frames
.end();
472 movements
.push_back(Evoral::RangeMove
<double>(i
->from
, i
->length
, i
->to
));
475 /* move panner automation */
476 boost::shared_ptr
<Panner
> p
= _route
->main_outs()->panner ();
478 for (uint32_t i
= 0; i
< p
->npanners (); ++i
) {
479 boost::shared_ptr
<AutomationList
> pan_alist
= p
->streampanner(i
).pan_control()->alist();
480 XMLNode
& before
= pan_alist
->get_state ();
481 pan_alist
->move_ranges (movements
);
482 _session
.add_command (new MementoCommand
<AutomationList
> (
483 *pan_alist
.get(), &before
, &pan_alist
->get_state ()));
487 /* move processor automation */
488 _route
->foreach_processor (boost::bind (&Diskstream::move_processor_automation
, this, _1
, movements_frames
));
492 Diskstream::move_processor_automation (boost::weak_ptr
<Processor
> p
, list
< Evoral::RangeMove
<framepos_t
> > const & movements_frames
)
494 boost::shared_ptr
<Processor
> processor (p
.lock ());
499 list
< Evoral::RangeMove
<double> > movements
;
500 for (list
< Evoral::RangeMove
<framepos_t
> >::const_iterator i
= movements_frames
.begin();
501 i
!= movements_frames
.end(); ++i
) {
502 movements
.push_back(Evoral::RangeMove
<double>(i
->from
, i
->length
, i
->to
));
505 set
<Evoral::Parameter
> const a
= processor
->what_can_be_automated ();
507 for (set
<Evoral::Parameter
>::iterator i
= a
.begin (); i
!= a
.end (); ++i
) {
508 boost::shared_ptr
<AutomationList
> al
= processor
->automation_control(*i
)->alist();
509 XMLNode
& before
= al
->get_state ();
510 al
->move_ranges (movements
);
511 _session
.add_command (
512 new MementoCommand
<AutomationList
> (
513 *al
.get(), &before
, &al
->get_state ()
520 Diskstream::check_record_status (nframes_t transport_frame
, nframes_t
/*nframes*/, bool can_record
)
522 int possibly_recording
;
525 const int transport_rolling
= 0x4;
526 const int track_rec_enabled
= 0x2;
527 const int global_rec_enabled
= 0x1;
529 /* merge together the 3 factors that affect record status, and compute
533 rolling
= _session
.transport_speed() != 0.0f
;
534 possibly_recording
= (rolling
<< 2) | (record_enabled() << 1) | can_record
;
535 change
= possibly_recording
^ last_possibly_recording
;
537 if (possibly_recording
== last_possibly_recording
) {
543 /* if per-track or global rec-enable turned on while the other was already on, we've started recording */
545 if (((change
& track_rec_enabled
) && record_enabled() && (!(change
& global_rec_enabled
) && can_record
)) ||
546 ((change
& global_rec_enabled
) && can_record
&& (!(change
& track_rec_enabled
) && record_enabled()))) {
548 /* starting to record: compute first+last frames */
550 first_recordable_frame
= transport_frame
+ _capture_offset
;
551 last_recordable_frame
= max_frames
;
552 capture_start_frame
= transport_frame
;
554 if (!(last_possibly_recording
& transport_rolling
) && (possibly_recording
& transport_rolling
)) {
556 /* was stopped, now rolling (and recording) */
558 if (_alignment_style
== ExistingMaterial
) {
560 first_recordable_frame
+= _session
.worst_output_latency();
562 DEBUG_TRACE (DEBUG::Latency
, string_compose ("Offset rec from stop. Capture offset: %1 Worst O/P Latency: %2 Roll Delay: %3 First Recordable Frame: %4 Transport Frame: %5\n",
563 _capture_offset
, _session
.worst_output_latency(), _roll_delay
, first_recordable_frame
, transport_frame
));
565 first_recordable_frame
+= _roll_delay
;
570 /* was rolling, but record state changed */
572 if (_alignment_style
== ExistingMaterial
) {
574 /* manual punch in happens at the correct transport frame
575 because the user hit a button. but to get alignment correct
576 we have to back up the position of the new region to the
577 appropriate spot given the roll delay.
581 /* autopunch toggles recording at the precise
582 transport frame, and then the DS waits
583 to start recording for a time that depends
584 on the output latency.
587 first_recordable_frame
+= _session
.worst_output_latency();
589 DEBUG_TRACE (DEBUG::Latency
, string_compose ("Punch in manual/auto. Capture offset: %1 Worst O/P Latency: %2 Roll Delay: %3 First Recordable Frame: %4 Transport Frame: %5\n",
590 _capture_offset
, _session
.worst_output_latency(), _roll_delay
, first_recordable_frame
, transport_frame
));
593 if (_session
.config
.get_punch_in()) {
594 first_recordable_frame
+= _roll_delay
;
596 capture_start_frame
-= _roll_delay
;
602 prepare_record_status(capture_start_frame
);
604 } else if (!record_enabled() || !can_record
) {
608 last_recordable_frame
= transport_frame
+ _capture_offset
;
610 if (_alignment_style
== ExistingMaterial
) {
611 last_recordable_frame
+= _session
.worst_output_latency();
613 last_recordable_frame
+= _roll_delay
;
616 //first_recordable_frame = max_frames;
618 DEBUG_TRACE (DEBUG::Latency
, string_compose ("Stop record - %6 | %7. Capture offset: %1 Worst O/P Latency: %2 Roll Delay: %3 First Recordable Frame: %4 Transport Frame: %5\n",
619 _capture_offset
, _session
.worst_output_latency(), _roll_delay
, first_recordable_frame
, transport_frame
,
620 can_record
, record_enabled()));
623 last_possibly_recording
= possibly_recording
;
627 Diskstream::route_going_away ()
633 Diskstream::calculate_record_range(OverlapType ot
, sframes_t transport_frame
, nframes_t nframes
,
634 nframes_t
& rec_nframes
, nframes_t
& rec_offset
)
641 case OverlapInternal
:
642 /* ---------- recrange
645 rec_nframes
= nframes
;
650 /* |--------| recrange
653 rec_nframes
= transport_frame
+ nframes
- first_recordable_frame
;
655 rec_offset
= first_recordable_frame
- transport_frame
;
660 /* |--------| recrange
663 rec_nframes
= last_recordable_frame
- transport_frame
;
667 case OverlapExternal
:
668 /* |--------| recrange
669 -------------- transrange
671 rec_nframes
= last_recordable_frame
- first_recordable_frame
;
672 rec_offset
= first_recordable_frame
- transport_frame
;