Logo Search packages:      
Sourcecode: ardour version File versions


    Copyright (C) 2000 Paul Davis 

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    $Id: diskstream.h,v 1.74 2005/02/09 19:19:05 pauld Exp $

#ifndef __ardour_diskstream_h__
#define __ardour_diskstream_h__

#include <sigc++/signal_system.h>

#include <cmath>
#include <string>
#include <queue>
#include <map>
#include <vector>

#include <time.h>

#include <pbd/fastlog.h>
#include <pbd/ringbufferNPT.h>
#include <pbd/atomic.h>

#include <ardour/ardour.h>
#include <ardour/configuration.h>
#include <ardour/session.h>
#include <ardour/route_group.h>
#include <ardour/route.h>
#include <ardour/port.h>
#include <ardour/utils.h>
#include <ardour/stateful.h>

struct tm;

namespace ARDOUR {

class AudioEngine;
class Send;
class Session;
class AudioPlaylist;
class FileSource;
class IO;

class DiskStream : public Stateful, public SigC::Object
      enum Flag {
            Recordable = 0x1,
            Hidden = 0x2

      DiskStream (Session &, const string& name, Flag f = Recordable);
      DiskStream (Session &, const XMLNode&);

      string name() const { return _name; }

      ARDOUR::IO* io() const { return _io; }
      void set_io (ARDOUR::IO& io) { _io = &io; }
      DiskStream& ref() { _refcnt++; return *this; }
      void unref() { if (_refcnt) _refcnt--; if (_refcnt == 0) delete this; }
      uint32_t refcnt() const { return _refcnt; }

      float playback_buffer_load() const;
      float capture_buffer_load() const;

      void set_flag (Flag f) {
            _flags |= f;

      void unset_flag (Flag f) {
            _flags &= ~f;

      bool hidden() const { return _flags & Hidden; }
      bool recordable() const { return _flags & Recordable; }

      void set_name (string str, void* src);

      string input_source (uint32_t n=0) const {
            if (n < channels.size()) {
                  return channels[n].source ? channels[n].source->name() : "";
            } else {
                  return ""; 

      Port *input_source_port (uint32_t n=0) const { 
            if (n < channels.size()) return channels[n].source; return 0; 

      void set_record_enabled (bool yn, void *src);
      bool record_enabled() const { return atomic_read (&_record_enabled); }
      void punch_in ();

      bool  reversed() const { return _actual_speed < 0.0f; }
      float speed() const { return _visible_speed; }
      void set_speed (float);

      float peak_power(uint32_t n=0) { 
            float x = channels[n].peak_power;
            channels[n].peak_power = 0.0f;
            if (x > 0.0f) {
                  return 20.0f * fast_log10(x);
            } else {
                  return minus_infinity();

      int  use_playlist (AudioPlaylist *);
      int use_new_playlist ();
      int use_copy_playlist ();

      void start_scrub (jack_nframes_t where);
      void end_scrub ();

      Sample *playback_buffer (uint32_t n=0) {
            if (n < channels.size())
                  return channels[n].current_playback_buffer;
            return 0;
      Sample *capture_buffer (uint32_t n=0) {
            if (n < channels.size())
                  return channels[n].current_capture_buffer;
            return 0;

      AudioPlaylist *playlist () { return _playlist; }

      FileSource *fades_source (uint32_t n=0) {
            if (n < channels.size())
                  return channels[n].fades_source;
            return 0;
      FileSource *write_source (uint32_t n=0) {
            if (n < channels.size())
                  return channels[n].write_source;
            return 0;

      jack_nframes_t get_capture_start_frame (uint32_t n=0);
      jack_nframes_t get_captured_frames (uint32_t n=0);
      uint32_t n_channels() { return _n_channels; }

      int add_channel ();
      int remove_channel ();
      static void set_disk_io_chunk_frames (uint32_t n) {
            disk_io_chunk_frames = n;

      static jack_nframes_t disk_io_frames() { return disk_io_chunk_frames; }
      SigC::Signal1<void,void*> record_enable_changed;
      SigC::Signal0<void>       speed_changed;
      SigC::Signal1<void,void*> reverse_changed;
      SigC::Signal0<void>       PlaylistChanged;

      static SigC::Signal0<void> DiskOverrun;
      static SigC::Signal0<void> DiskUnderrun;
      static SigC::Signal1<void,DiskStream*> DiskStreamCreated;   // XXX use a ref with sigc2
      static SigC::Signal1<void,DiskStream*> CannotRecordNoInput; // XXX use a ref with sigc2
      static SigC::Signal1<void,list<Source*>*> DeleteSources;

      /* stateful */

      XMLNode& get_state(void);
      int set_state(const XMLNode& node);

      void monitor_input (bool);

      jack_nframes_t capture_offset() const { return _capture_offset; }
      void           set_capture_offset ();

      static void swap_by_ptr (Sample *first, Sample *last) {
            while (first < last) {
                  Sample tmp = *first;
                  *first++ = *last;
                  *last-- = tmp;

      static void swap_by_ptr (Sample *first, Sample *last, jack_nframes_t n) {
            while (n--) {
                  Sample tmp = *first;
                  *first++ = *last;
                  *last-- = tmp;

      bool slaved() const { return _slaved; }
      void set_slaved(bool yn) { _slaved = yn; }

      int set_loop (Location *loc);
      SigC::Signal1<void,Location *> LoopSet;

      std::list<Region*>& last_capture_regions () {
            return _last_capture_regions;

      void handle_input_change (void *src);
      void handle_input_configuration_change (void *src);

      id_t id() const { return _id; }

      XMLNode* deprecated_io_node;

      friend class Session;

      /* the Session is the only point of access for these
         because they require that the Session is "inactive"
         while they are called.

      void set_pending_overwrite (bool);
      int  overwrite_existing_buffers ();
      void reverse_scrub_buffer (bool to_forward);
      void set_block_size (jack_nframes_t);
      int  internal_playback_seek (jack_nframes_t distance);
      int  can_internal_playback_seek (jack_nframes_t distance);
      void reset_write_sources (bool);
      void non_realtime_input_configuration_change ();

      uint32_t read_data_count() const { return _read_data_count; }
      uint32_t write_data_count() const { return _write_data_count; }

      friend class Auditioner;
      int  seek (jack_nframes_t which_sample, bool complete_refill = false);

      friend class AudioTrack;

      void prepare ();
      int  process (jack_nframes_t nframes, jack_nframes_t offset, bool can_record, bool rec_monitors_input);
      bool commit  (jack_nframes_t nframes);
      void recover (); /* called if commit will not be called, but process was */


      /* use unref() to destroy a diskstream */


      struct ChannelInfo {

            Sample     *playback_wrap_buffer;
            Sample     *capture_wrap_buffer;
            Sample     *speed_buffer;

              float       peak_power;

            FileSource   *fades_source;
            FileSource   *write_source;

            Port         *source;
            Sample       *current_capture_buffer;
            Sample       *current_playback_buffer;

            RingBufferNPT<Sample> *playback_buf;
            RingBufferNPT<Sample> *capture_buf;

            Sample* scrub_buffer;
            Sample* scrub_forward_buffer;
            Sample* scrub_reverse_buffer;

            RingBufferNPT<Sample>::rw_vector playback_vector;
            RingBufferNPT<Sample>::rw_vector capture_vector;

      typedef vector<ChannelInfo> ChannelList;

      string            _name;
      ARDOUR::Session&  _session;
      ARDOUR::IO*       _io;
      ChannelList        channels;
      uint32_t      _n_channels;
      id_t              _id;

      atomic_t                 _record_enabled;
      bool                      rec_monitoring_off_for_roll;
      AudioPlaylist*           _playlist;
      float                    _visible_speed;
      float                    _actual_speed;
      /* items needed for speed change logic */
      bool                     _buffer_reallocation_required;
      bool                     _seek_required;
      bool                      force_refill;
      jack_nframes_t            capture_start_frame;
      jack_nframes_t            capture_captured;
      bool                      was_recording;
      bool                      adjust_capture_position;
      jack_nframes_t           _capture_offset;
      jack_nframes_t            legal_recording_frame;
      bool                      trim_capture_by_latency;
      bool                     _scrubbing;
      bool                     _slaved;
      bool                     _processed;
      Location*                 loop_location;
      jack_nframes_t            overwrite_frame;
      off_t                     overwrite_offset;
      bool                      pending_overwrite;
      bool                      overwrite_queued;
      bool                      input_change_pending;
      jack_nframes_t            wrap_buffer_size;
      jack_nframes_t            speed_buffer_size;

      uint64_t                   last_phase;
      uint64_t                   phi;
      jack_nframes_t            file_frame;           
      jack_nframes_t            playback_sample;
      jack_nframes_t            playback_distance;

      uint32_t            _read_data_count;
      uint32_t            _write_data_count;

      bool                      in_set_state;
      PBD::NonBlockingLock  state_lock;

      jack_nframes_t scrub_start;
      jack_nframes_t scrub_buffer_size;
      jack_nframes_t scrub_offset;
      uint32_t _refcnt;

      SigC::Connection ports_created_c;
      SigC::Connection plmod_connection;
      SigC::Connection plstate_connection;
      SigC::Connection plgone_connection;

      /* the two central butler operations */

      int do_flush (bool force = false);
      int do_refill (Sample *mixdown_buffer, float *gain_buffer);

      int read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, jack_nframes_t& start, jack_nframes_t cnt, 

              ChannelInfo& channel_info, int channel, bool reversed);

      uint32_t i_am_the_modifier;
      /* XXX fix this redundancy ... */

      void playlist_changed (Change);
      void playlist_modified ();
      void playlist_deleted (Playlist*);
      void session_controls_changed (Session::ControlType);

      void finish_capture (bool rec_monitors_input);
      void clean_up_capture (struct tm&, time_t, bool abort);
      void transport_stopped (struct tm&, time_t, bool abort);

      struct CaptureInfo {
          uint32_t start;
          uint32_t frames;

      vector<CaptureInfo*> capture_info;
      PBD::Lock  capture_info_lock;
      void init (Flag);

      void init_channel (ChannelInfo &chan);
      void destroy_channel (ChannelInfo &chan);
      void compute_peak (Sample *buf, jack_nframes_t nsamples, uint32_t n=0) {
            for (jack_nframes_t i = 0; i < nsamples; ++i) {
                  channels[n].peak_power = f_max (channels[n].peak_power, buf[i]);

      static jack_nframes_t disk_io_chunk_frames;

      int use_new_write_source (uint32_t n=0);
      int use_new_fade_source (uint32_t n=0);

      int find_and_use_playlist (const string&);

      void allocate_temporary_buffers ();

      unsigned char _flags;

      int  create_input_port ();
      int  connect_input_port ();
      int  seek_unlocked (jack_nframes_t which_sample);

      int ports_created ();

      bool realtime_set_speed (float, bool global_change);
      void non_realtime_set_speed ();

      std::list<Region*> _last_capture_regions;
      std::vector<FileSource*> capturing_sources;
      int use_pending_capture_data (XMLNode& node);

}; /* namespace ARDOUR */

#endif /* __ardour_diskstream_h__ */

Generated by  Doxygen 1.6.0   Back to index