ardour
diskstream.cc
Go to the documentation of this file.
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 <fstream>
21 #include <cassert>
22 #include <cstdio>
23 #include <unistd.h>
24 #include <cmath>
25 #include <cerrno>
26 #include <string>
27 #include <climits>
28 #include <fcntl.h>
29 #include <cstdlib>
30 #include <ctime>
31 #include <sys/stat.h>
32 
33 #include <glibmm/threads.h>
34 
35 #include "pbd/error.h"
36 #include "pbd/basename.h"
37 #include "pbd/memento_command.h"
38 #include "pbd/xml++.h"
39 #include "pbd/stacktrace.h"
40 
41 #include "ardour/debug.h"
42 #include "ardour/diskstream.h"
43 #include "ardour/io.h"
44 #include "ardour/pannable.h"
45 #include "ardour/playlist.h"
46 #include "ardour/session.h"
47 #include "ardour/track.h"
48 
49 #include "i18n.h"
50 #include <locale.h>
51 
52 using namespace std;
53 using namespace ARDOUR;
54 using namespace PBD;
55 
56 ARDOUR::framecnt_t Diskstream::disk_read_chunk_frames = default_disk_read_chunk_frames ();
57 ARDOUR::framecnt_t Diskstream::disk_write_chunk_frames = default_disk_write_chunk_frames ();
58 
59 PBD::Signal0<void> Diskstream::DiskOverrun;
60 PBD::Signal0<void> Diskstream::DiskUnderrun;
61 
62 Diskstream::Diskstream (Session &sess, const string &name, Flag flag)
63  : SessionObject(sess, name)
64  , i_am_the_modifier (0)
65  , _track (0)
66  , _record_enabled (0)
67  , _visible_speed (1.0f)
68  , _actual_speed (1.0f)
69  , _buffer_reallocation_required (false)
70  , _seek_required (false)
71  , capture_start_frame (0)
72  , capture_captured (0)
73  , was_recording (false)
74  , adjust_capture_position (0)
75  , _capture_offset (0)
76  , _roll_delay (0)
77  , first_recordable_frame (max_framepos)
78  , last_recordable_frame (max_framepos)
79  , last_possibly_recording (0)
80  , _alignment_style (ExistingMaterial)
81  , _alignment_choice (Automatic)
82  , _slaved (false)
83  , loop_location (0)
84  , overwrite_frame (0)
85  , overwrite_offset (0)
86  , _pending_overwrite (false)
87  , overwrite_queued (false)
88  , wrap_buffer_size (0)
89  , speed_buffer_size (0)
90  , _speed (1.0)
91  , _target_speed (_speed)
92  , file_frame (0)
93  , playback_sample (0)
94  , in_set_state (false)
95  , _flags (flag)
96  , deprecated_io_node (0)
97 {
98 }
99 
100 Diskstream::Diskstream (Session& sess, const XMLNode& /*node*/)
101  : SessionObject(sess, "unnamed diskstream")
102  , i_am_the_modifier (0)
103  , _track (0)
104  , _record_enabled (0)
105  , _visible_speed (1.0f)
106  , _actual_speed (1.0f)
107  , _buffer_reallocation_required (false)
108  , _seek_required (false)
109  , capture_start_frame (0)
110  , capture_captured (0)
111  , was_recording (false)
112  , adjust_capture_position (0)
113  , _capture_offset (0)
114  , _roll_delay (0)
115  , first_recordable_frame (max_framepos)
116  , last_recordable_frame (max_framepos)
117  , last_possibly_recording (0)
118  , _alignment_style (ExistingMaterial)
119  , _alignment_choice (Automatic)
120  , _slaved (false)
121  , loop_location (0)
122  , overwrite_frame (0)
123  , overwrite_offset (0)
124  , _pending_overwrite (false)
125  , overwrite_queued (false)
126  , wrap_buffer_size (0)
127  , speed_buffer_size (0)
128  , _speed (1.0)
129  , _target_speed (_speed)
130  , file_frame (0)
131  , playback_sample (0)
132  , in_set_state (false)
133  , _flags (Recordable)
134  , deprecated_io_node (0)
135 {
136 }
137 
139 {
140  DEBUG_TRACE (DEBUG::Destruction, string_compose ("Diskstream %1 deleted\n", _name));
141 
142  if (_playlist) {
143  _playlist->release ();
144  }
145 
146  delete deprecated_io_node;
147 }
148 
149 void
151 {
152  _track = t;
153  _io = _track->input();
154 
156  _io->changed.connect_same_thread (ic_connection, boost::bind (&Diskstream::handle_input_change, this, _1, _2));
157 
158  if (_io->n_ports() != ChanCount::ZERO) {
161  }
162 
163  _track->Destroyed.connect_same_thread (*this, boost::bind (&Diskstream::route_going_away, this));
164 }
165 
166 void
168 {
170 
172 
173  /* rather than handle this here on a DS-by-DS basis we defer to the
174  session transport/butler thread, and let it tackle
175  as many diskstreams as need it in one shot. this avoids many repeated
176  takings of the audioengine process lock.
177  */
178 
179  if (!(input_change_pending.type & change.type)) {
182  }
183  }
184 }
185 
186 void
188 {
190  {
193 
195  }
196 
197  if (_seek_required) {
198  if (speed() != 1.0f || speed() != -1.0f) {
199  seek ((framepos_t) (_session.transport_frame() * (double) speed()), true);
200  }
201  else {
202  seek (_session.transport_frame(), true);
203  }
204 
205  _seek_required = false;
206  }
207 }
208 
209 bool
210 Diskstream::realtime_set_speed (double sp, bool global)
211 {
212  bool changed = false;
213  double new_speed = sp * _session.transport_speed();
214 
215  if (_visible_speed != sp) {
216  _visible_speed = sp;
217  changed = true;
218  }
219 
220  if (new_speed != _actual_speed) {
221 
222  framecnt_t required_wrap_size = (framecnt_t) ceil (_session.get_block_size() *
223  fabs (new_speed)) + 2;
224 
225  if (required_wrap_size > wrap_buffer_size) {
227  }
228 
229  _actual_speed = new_speed;
231  }
232 
233  if (changed) {
234  if (!global) {
235  _seek_required = true;
236  }
237  SpeedChanged (); /* EMIT SIGNAL */
238  }
239 
241 }
242 
243 void
245 {
246  if (_io == 0) {
247  /* can't capture, so forget it */
248  return;
249  }
250 
251  switch (_alignment_style) {
252  case ExistingMaterial:
254  break;
255 
256  case CaptureTime:
257  default:
258  _capture_offset = 0;
259  break;
260  }
261 
262  DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: using IO latency, capture offset set to %2 with style = %3\n", name(), _capture_offset, enum_2_string (_alignment_style)));
263 }
264 
265 
266 void
268 {
270  return;
271  }
272 
273  if ((a != _alignment_style) || force) {
274  _alignment_style = a;
277  }
278 }
279 
280 void
282 {
284  return;
285  }
286 
287  if ((a != _alignment_choice) || force) {
288  _alignment_choice = a;
289 
290  switch (_alignment_choice) {
291  case Automatic:
293  break;
294  case UseExistingMaterial:
296  break;
297  case UseCaptureTime:
299  break;
300  }
301  }
302 }
303 
304 int
306 {
307  if (location) {
308  if (location->start() >= location->end()) {
309  error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl;
310  return -1;
311  }
312  }
313 
314  loop_location = location;
315 
316  LoopSet (location); /* EMIT SIGNAL */
317  return 0;
318 }
319 
323 {
325 
326  if (capture_info.size() > n) {
327  /* this is a completed capture */
328  return capture_info[n]->start;
329  } else {
330  /* this is the currently in-progress capture */
331  return capture_start_frame;
332  }
333 }
334 
337 {
339 
340  if (capture_info.size() > n) {
341  /* this is a completed capture */
342  return capture_info[n]->frames;
343  } else {
344  /* this is the currently in-progress capture */
345  return capture_captured;
346  }
347 }
348 
349 void
351 {
352  _roll_delay = nframes;
353 }
354 
355 int
357 {
358  if (!playlist) {
359  return 0;
360  }
361 
362  bool prior_playlist = false;
363 
364  {
366 
367  if (playlist == _playlist) {
368  return 0;
369  }
370 
372 
373  if (_playlist) {
374  _playlist->release();
375  prior_playlist = true;
376  }
377 
379  _playlist->use();
380 
381  if (!in_set_state && recordable()) {
382  reset_write_sources (false);
383  }
384 
385  _playlist->ContentsChanged.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_modified, this));
387  _playlist->RangesMoved.connect_same_thread (playlist_connections, boost::bind (&Diskstream::playlist_ranges_moved, this, _1, _2));
388  }
389 
390  /* don't do this if we've already asked for it *or* if we are setting up
391  the diskstream for the very first time - the input changed handling will
392  take care of the buffer refill.
393  */
394 
395  if (!overwrite_queued && prior_playlist) {
397  overwrite_queued = true;
398  }
399 
400  PlaylistChanged (); /* EMIT SIGNAL */
401  _session.set_dirty ();
402 
403  return 0;
404 }
405 
406 void
408 {
410 }
411 
412 void
414 {
417  overwrite_queued = true;
418  }
419 }
420 
421 void
423 {
424  boost::shared_ptr<Playlist> pl (wpl.lock());
425 
426  if (pl == _playlist) {
427 
428  /* this catches an ordering issue with session destruction. playlists
429  are destroyed before diskstreams. we have to invalidate any handles
430  we have to the playlist.
431  */
432 
433  if (_playlist) {
434  _playlist.reset ();
435  }
436  }
437 }
438 
439 bool
440 Diskstream::set_name (const string& str)
441 {
442  if (_name != str) {
443  assert(playlist());
444  playlist()->set_name (str);
446  }
447  return true;
448 }
449 
450 bool
451 Diskstream::set_write_source_name (const std::string& str) {
452  _write_source_name = str;
453  return true;
454 }
455 
456 XMLNode&
458 {
459  XMLNode* node = new XMLNode ("Diskstream");
460  char buf[64];
461  LocaleGuard lg (X_("C"));
462 
463  node->add_property ("flags", enum_2_string (_flags));
464  node->add_property ("playlist", _playlist->name());
465  node->add_property("name", _name);
466  id().print (buf, sizeof (buf));
467  node->add_property("id", buf);
468  snprintf (buf, sizeof(buf), "%f", _visible_speed);
469  node->add_property ("speed", buf);
470  node->add_property ("capture-alignment", enum_2_string (_alignment_choice));
471 
472  if (_extra_xml) {
473  node->add_child_copy (*_extra_xml);
474  }
475 
476  return *node;
477 }
478 
479 int
480 Diskstream::set_state (const XMLNode& node, int /*version*/)
481 {
482  const XMLProperty* prop;
483 
484  if ((prop = node.property ("name")) != 0) {
485  _name = prop->value();
486  }
487 
488  if (deprecated_io_node) {
490  } else {
491  set_id (node);
492  }
493 
494  if ((prop = node.property ("flags")) != 0) {
495  _flags = Flag (string_2_enum (prop->value(), _flags));
496  }
497 
498  if ((prop = node.property (X_("capture-alignment"))) != 0) {
500  } else {
501  set_align_choice (Automatic, true);
502  }
503 
504  if ((prop = node.property ("playlist")) == 0) {
505  return -1;
506  }
507 
508  if (find_and_use_playlist (prop->value())) {
509  return -1;
510  }
511 
512  if ((prop = node.property ("speed")) != 0) {
513  double sp = atof (prop->value().c_str());
514 
515  if (realtime_set_speed (sp, false)) {
517  }
518  }
519 
520  return 0;
521 }
522 
523 void
524 Diskstream::playlist_ranges_moved (list< Evoral::RangeMove<framepos_t> > const & movements_frames, bool from_undo)
525 {
526  /* If we're coming from an undo, it will have handled
527  automation undo (it must, since automation-follows-regions
528  can lose automation data). Hence we can do nothing here.
529  */
530 
531  if (from_undo) {
532  return;
533  }
534 
535  if (!_track || Config->get_automation_follows_regions () == false) {
536  return;
537  }
538 
539  list< Evoral::RangeMove<double> > movements;
540 
541  for (list< Evoral::RangeMove<framepos_t> >::const_iterator i = movements_frames.begin();
542  i != movements_frames.end();
543  ++i) {
544 
545  movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
546  }
547 
548  /* move panner automation */
550  Evoral::ControlSet::Controls& c (pannable->controls());
551 
552  for (Evoral::ControlSet::Controls::iterator ci = c.begin(); ci != c.end(); ++ci) {
554  if (!ac) {
555  continue;
556  }
558 
559  XMLNode & before = alist->get_state ();
560  bool const things_moved = alist->move_ranges (movements);
561  if (things_moved) {
563  *alist.get(), &before, &alist->get_state ()));
564  }
565  }
566 
567  /* move processor automation */
568  _track->foreach_processor (boost::bind (&Diskstream::move_processor_automation, this, _1, movements_frames));
569 }
570 
571 void
573 {
574  boost::shared_ptr<Processor> processor (p.lock ());
575  if (!processor) {
576  return;
577  }
578 
579  list< Evoral::RangeMove<double> > movements;
580  for (list< Evoral::RangeMove<framepos_t> >::const_iterator i = movements_frames.begin(); i != movements_frames.end(); ++i) {
581  movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
582  }
583 
584  set<Evoral::Parameter> const a = processor->what_can_be_automated ();
585 
586  for (set<Evoral::Parameter>::const_iterator i = a.begin (); i != a.end (); ++i) {
587  boost::shared_ptr<AutomationList> al = processor->automation_control(*i)->alist();
588  XMLNode & before = al->get_state ();
589  bool const things_moved = al->move_ranges (movements);
590  if (things_moved) {
593  *al.get(), &before, &al->get_state ()
594  )
595  );
596  }
597  }
598 }
599 
600 void
601 Diskstream::check_record_status (framepos_t transport_frame, bool can_record)
602 {
603  int possibly_recording;
604  int rolling;
605  int change;
606  const int transport_rolling = 0x4;
607  const int track_rec_enabled = 0x2;
608  const int global_rec_enabled = 0x1;
609  const int fully_rec_enabled = (transport_rolling|track_rec_enabled|global_rec_enabled);
610 
611  /* merge together the 3 factors that affect record status, and compute
612  * what has changed.
613  */
614 
615  rolling = _session.transport_speed() != 0.0f;
616  possibly_recording = (rolling << 2) | ((int)record_enabled() << 1) | (int)can_record;
617  change = possibly_recording ^ last_possibly_recording;
618 
619  if (possibly_recording == last_possibly_recording) {
620  return;
621  }
622 
623  const framecnt_t existing_material_offset = _session.worst_playback_latency();
624 
625  if (possibly_recording == fully_rec_enabled) {
626 
627  if (last_possibly_recording == fully_rec_enabled) {
628  return;
629  }
630 
634 
635  DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: @ %7 (%9) FRF = %2 CSF = %4 CO = %5, EMO = %6 RD = %8 WOL %10 WTL %11\n",
637  _capture_offset,
638  existing_material_offset,
639  transport_frame,
640  _roll_delay,
644 
645 
647  first_recordable_frame += existing_material_offset;
648  DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("\tshift FRF by EMO %1\n",
650  }
651 
653 
654  } else {
655 
656  if (last_possibly_recording == fully_rec_enabled) {
657 
658  /* we were recording last time */
659 
660  if (change & transport_rolling) {
661 
662  /* transport-change (stopped rolling): last_recordable_frame was set in ::prepare_to_stop(). We
663  * had to set it there because we likely rolled past the stopping point to declick out,
664  * and then backed up.
665  */
666 
667  } else {
668  /* punch out */
669 
671 
673  last_recordable_frame += existing_material_offset;
674  }
675  }
676  }
677  }
678 
679  last_possibly_recording = possibly_recording;
680 }
681 
682 void
684 {
685  _io.reset ();
686 }
687 
688 void
690  framecnt_t & rec_nframes, framecnt_t & rec_offset)
691 {
692  switch (ot) {
693  case Evoral::OverlapNone:
694  rec_nframes = 0;
695  break;
696 
698  /* ---------- recrange
699  * |---| transrange
700  */
701  rec_nframes = nframes;
702  rec_offset = 0;
703  break;
704 
706  /* |--------| recrange
707  * -----| transrange
708  */
709  rec_nframes = transport_frame + nframes - first_recordable_frame;
710  if (rec_nframes) {
711  rec_offset = first_recordable_frame - transport_frame;
712  }
713  break;
714 
715  case Evoral::OverlapEnd:
716  /* |--------| recrange
717  * |-------- transrange
718  */
719  rec_nframes = last_recordable_frame - transport_frame;
720  rec_offset = 0;
721  break;
722 
724  /* |--------| recrange
725  * -------------- transrange
726  */
728  rec_offset = first_recordable_frame - transport_frame;
729  break;
730  }
731 
732  DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1 rec? %2 @ %3 (for %4) FRF %5 LRF %6 : rf %7 @ %8\n",
733  _name, enum_2_string (ot), transport_frame, nframes,
734  first_recordable_frame, last_recordable_frame, rec_nframes, rec_offset));
735 }
736 
737 void
738 Diskstream::prepare_to_stop (framepos_t transport_frame, framepos_t audible_frame)
739 {
740  switch (_alignment_style) {
741  case ExistingMaterial:
742  last_recordable_frame = transport_frame + _capture_offset;
743  DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose("%1: prepare to stop sets last recordable frame to %2 + %3 = %4\n", _name, transport_frame, _capture_offset, last_recordable_frame));
744  break;
745 
746  case CaptureTime:
747  last_recordable_frame = audible_frame; // note that capture_offset is zero
748  /* we may already have captured audio before the last_recordable_frame (audible frame),
749  so deal with this.
750  */
753  }
754  DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose("%1: prepare to stop sets last recordable frame to audible frame @ %2\n", _name, audible_frame));
755  break;
756  }
757 
758 }
759 
760 void
762 {
763  g_atomic_int_set (&_record_enabled, 1);
764 }
765 
766 void
768 {
769  g_atomic_int_set (&_record_enabled, 0);
770 }
771 
774 {
775  return 65536;
776 }
777 
780 {
781  return 65536;
782 }
framepos_t first_recordable_frame
Definition: diskstream.h:306
framecnt_t _capture_offset
Definition: diskstream.h:301
PBD::ScopedConnectionList playlist_connections
Definition: diskstream.h:334
void handle_input_change(IOChange, void *src)
Definition: diskstream.cc:167
framepos_t get_capture_start_frame(uint32_t n=0) const
Definition: diskstream.cc:322
ARDOUR::Session & _session
virtual void playlist_deleted(boost::weak_ptr< Playlist >)
Definition: diskstream.cc:422
void calculate_record_range(Evoral::OverlapType ot, framepos_t transport_frame, framecnt_t nframes, framecnt_t &rec_nframes, framecnt_t &rec_offset)
Definition: diskstream.cc:689
PBD::Signal0< void > SpeedChanged
Definition: diskstream.h:179
boost::shared_ptr< Playlist > _playlist
Definition: diskstream.h:287
PBD::Signal0< void > DropReferences
Definition: destructible.h:34
const std::string & value() const
Definition: xml++.h:159
framecnt_t worst_playback_latency() const
Definition: session.h:397
virtual void allocate_temporary_buffers()=0
double transport_speed() const
Definition: session.h:590
AlignStyle
Definition: types.h:163
LIBARDOUR_API uint64_t Destruction
Definition: debug.cc:38
#define enum_2_string(e)
Definition: enumwriter.h:97
PBD::Signal0< void > Destroyed
Definition: destructible.h:33
virtual void playlist_modified()
Definition: diskstream.cc:413
virtual bool set_name(const std::string &str)
Definition: diskstream.cc:440
void disengage_record_enable()
Definition: diskstream.cc:767
virtual void set_capture_offset()
Definition: diskstream.cc:244
bool actively_recording() const
Definition: session.h:280
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:396
framecnt_t latency() const
Definition: io.cc:1221
framecnt_t wrap_buffer_size
Definition: diskstream.h:318
boost::shared_ptr< Pannable > pannable() const
Definition: route.cc:4023
uint32_t i_am_the_modifier
Definition: diskstream.h:281
void add_command(Command *const cmd)
Definition: session.h:787
PBD::Signal0< void > PlaylistChanged
Definition: diskstream.h:182
framepos_t last_recordable_frame
Definition: diskstream.h:307
void set_align_choice(AlignChoice a, bool force=false)
Definition: diskstream.cc:281
tuple f
Definition: signals.py:35
XMLNode * add_child_copy(const XMLNode &)
Definition: xml++.cc:363
framepos_t end() const
Definition: location.h:72
PBD::Signal0< void > ContentsChanged
Definition: playlist.h:190
Definition: Beats.hpp:239
LIBPBD_API Transmitter error
virtual void reset_write_sources(bool, bool force=false)=0
void set_track(ARDOUR::Track *)
Definition: diskstream.cc:150
void request_input_change_handling()
LIBARDOUR_API uint64_t CaptureAlignment
Definition: debug.cc:52
virtual void set_align_style_from_io()
Definition: diskstream.h:259
AlignChoice _alignment_choice
Definition: diskstream.h:310
virtual void check_record_status(framepos_t transport_frame, bool can_record)
Definition: diskstream.cc:601
PBD::Signal0< void > AlignmentStyleChanged
Definition: diskstream.h:183
virtual bool set_write_source_name(const std::string &str)
Definition: diskstream.cc:451
virtual int seek(framepos_t which_sample, bool complete_refill=false)=0
std::string _write_source_name
Definition: diskstream.h:330
static framecnt_t default_disk_write_chunk_frames()
Definition: diskstream.cc:779
bool recordable() const
Definition: diskstream.h:115
#define _(Text)
Definition: i18n.h:11
XMLNode * _extra_xml
Definition: stateful.h:109
IOChange input_change_pending
Definition: diskstream.h:317
Location * loop_location
Definition: diskstream.h:312
const ChanCount & n_ports() const
Definition: io.h:135
Glib::Threads::Mutex state_lock
Definition: diskstream.h:332
#define X_(Text)
Definition: i18n.h:13
void engage_record_enable()
Definition: diskstream.cc:761
int64_t framecnt_t
Definition: types.h:76
XMLProperty * property(const char *)
Definition: xml++.cc:413
boost::shared_ptr< ARDOUR::IO > _io
Definition: diskstream.h:283
LIBARDOUR_API RCConfiguration * Config
Definition: globals.cc:119
int set_loop(Location *loc)
Definition: diskstream.cc:305
#define string_2_enum(str, e)
Definition: enumwriter.h:98
std::vector< CaptureInfo * > capture_info
Definition: diskstream.h:278
enum ARDOUR::IOChange::Type type
bool set_name(const std::string &str)
Definition: playlist.cc:372
framepos_t transport_frame() const
Definition: session.h:551
Definition: amp.h:29
const PBD::ID & id() const
Definition: stateful.h:68
virtual bool set_name(const std::string &str)
static framecnt_t default_disk_read_chunk_frames()
Definition: diskstream.cc:773
void print(char *buf, uint32_t bufsize) const
Definition: id.cc:73
PBD::Signal2< void, std::list< Evoral::RangeMove< framepos_t > > const &, bool > RangesMoved
Definition: playlist.h:197
bool set_id(const XMLNode &)
Definition: stateful.cc:381
virtual void playlist_changed(const PBD::PropertyChange &)
Definition: diskstream.cc:407
void foreach_processor(boost::function< void(boost::weak_ptr< Processor >)> method)
Definition: route.h:203
framecnt_t worst_track_latency() const
Definition: session.h:396
bool record_enabled() const
Definition: diskstream.h:106
PBD::Signal2< void, IOChange, void * > changed
Definition: io.h:141
framecnt_t worst_output_latency() const
Definition: session.h:394
#define DEBUG_TRACE(bits, str)
Definition: debug.h:55
void move_processor_automation(boost::weak_ptr< Processor >, std::list< Evoral::RangeMove< framepos_t > > const &)
Definition: diskstream.cc:572
int64_t framepos_t
Definition: types.h:66
PBD::Signal1< void, Location * > LoopSet
Definition: diskstream.h:184
virtual int set_state(const XMLNode &, int version)
Definition: diskstream.cc:480
PBD::Property< std::string > _name
std::map< Parameter, boost::shared_ptr< Control > > Controls
Definition: ControlSet.hpp:57
T * get() const
Definition: shared_ptr.hpp:268
framepos_t capture_start_frame
Definition: diskstream.h:297
bool changed() const
Definition: stateful.cc:325
double speed() const
Definition: diskstream.h:118
XMLProperty * add_property(const char *name, const std::string &value)
const char * name
const std::string & name() const
Definition: location.h:81
pframes_t get_block_size() const
Definition: session.h:393
virtual void playlist_ranges_moved(std::list< Evoral::RangeMove< framepos_t > > const &, bool)
Definition: diskstream.cc:524
void non_realtime_set_speed()
Definition: diskstream.cc:187
framecnt_t _roll_delay
Definition: diskstream.h:305
Definition: xml++.h:95
std::string name() const
Controls & controls()
Definition: ControlSet.hpp:58
framecnt_t capture_captured
Definition: diskstream.h:298
OverlapType
Definition: Range.hpp:31
Definition: debug.h:30
boost::shared_ptr< IO > input() const
Definition: route.h:89
bool move_ranges(std::list< RangeMove< double > > const &)
virtual bool realtime_set_speed(double, bool global_change)
Definition: diskstream.cc:210
bool _buffer_reallocation_required
Definition: diskstream.h:293
boost::shared_ptr< AutomationList > alist() const
framecnt_t get_captured_frames(uint32_t n=0) const
Definition: diskstream.cc:336
framepos_t start() const
Definition: location.h:71
static const framepos_t max_framepos
Definition: types.h:78
virtual void prepare_record_status(framepos_t)
Definition: diskstream.h:258
virtual int find_and_use_playlist(const std::string &)=0
virtual void non_realtime_input_change()=0
virtual void prepare_to_stop(framepos_t transport_pos, framepos_t audible_frame)
Definition: diskstream.cc:738
virtual ~Diskstream()
Definition: diskstream.cc:138
Glib::Threads::Mutex capture_info_lock
Definition: diskstream.h:279
void set_roll_delay(framecnt_t)
Definition: diskstream.cc:350
AlignChoice
Definition: types.h:168
static const ChanCount ZERO
Definition: chan_count.h:149
boost::shared_ptr< Playlist > playlist()
Definition: diskstream.h:127
virtual int use_playlist(boost::shared_ptr< Playlist >)
Definition: diskstream.cc:356
virtual XMLNode & get_state(void)
Definition: diskstream.cc:457
void set_align_style(AlignStyle, bool force=false)
Definition: diskstream.cc:267
XMLNode * deprecated_io_node
Definition: diskstream.h:339
PBD::ScopedConnection ic_connection
Definition: diskstream.h:336
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208
double atof(const string &s)
Definition: convert.cc:158
void request_overwrite_buffer(Track *)
AlignStyle _alignment_style
Definition: diskstream.h:309