/* Copyright (C) 2009-2016 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 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 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. */ #ifndef __ardour_disk_writer_h__ #define __ardour_disk_writer_h__ #include #include #include "pbd/i18n.h" #include "ardour/disk_io.h" #include "ardour/midi_buffer.h" namespace ARDOUR { class AudioFileSource; class SMFSource; class MidiSource; class LIBARDOUR_API DiskWriter : public DiskIOProcessor { public: DiskWriter (Session&, std::string const & name, DiskIOProcessor::Flag f = DiskIOProcessor::Flag (0)); ~DiskWriter (); bool set_name (std::string const & str); std::string display_name() const { return std::string (_("recorder")); } virtual bool set_write_source_name (const std::string& str); bool recordable() const { return _flags & Recordable; } static framecnt_t chunk_frames() { return _chunk_frames; } static framecnt_t default_chunk_frames (); static void set_chunk_frames (framecnt_t n) { _chunk_frames = n; } void run (BufferSet& /*bufs*/, framepos_t /*start_frame*/, framepos_t /*end_frame*/, double speed, pframes_t /*nframes*/, bool /*result_required*/); void non_realtime_locate (framepos_t); void realtime_handle_transport_stopped (); virtual XMLNode& state (bool full); int set_state (const XMLNode&, int version); std::string write_source_name () const { if (_write_source_name.empty()) { return name(); } else { return _write_source_name; } } boost::shared_ptr audio_write_source (uint32_t n=0) { boost::shared_ptr c = channels.reader(); if (n < c->size()) { return (*c)[n]->write_source; } return boost::shared_ptr(); } boost::shared_ptr midi_write_source () { return _midi_write_source; } virtual std::string steal_write_source_name (); int use_new_write_source (DataType, uint32_t n = 0); void reset_write_sources (bool, bool force = false); AlignStyle alignment_style() const { return _alignment_style; } AlignChoice alignment_choice() const { return _alignment_choice; } void set_align_style (AlignStyle, bool force=false); void set_align_choice (AlignChoice a, bool force=false); PBD::Signal0 AlignmentStyleChanged; void set_input_latency (framecnt_t); bool configure_io (ChanCount in, ChanCount out); std::list >& last_capture_sources () { return _last_capture_sources; } bool record_enabled() const { return g_atomic_int_get (const_cast(&_record_enabled)); } bool record_safe () const { return g_atomic_int_get (const_cast(&_record_safe)); } virtual void set_record_enabled (bool yn); virtual void set_record_safe (bool yn); bool destructive() const { return _flags & Destructive; } int set_destructive (bool yn); int set_non_layered (bool yn); bool can_become_destructive (bool& requires_bounce) const; /** @return Start position of currently-running capture (in session frames) */ framepos_t current_capture_start() const { return capture_start_frame; } framepos_t current_capture_end() const { return capture_start_frame + capture_captured; } framepos_t get_capture_start_frame (uint32_t n = 0) const; framecnt_t get_captured_frames (uint32_t n = 0) const; float buffer_load() const; virtual void request_input_monitoring (bool) {} virtual void ensure_input_monitoring (bool) {} framecnt_t capture_offset() const { return _capture_offset; } virtual void set_capture_offset (); int seek (framepos_t frame, bool complete_refill); static PBD::Signal0 Overrun; void set_note_mode (NoteMode m); /** Emitted when some MIDI data has been received for recording. * Parameter is the source that it is destined for. * A caller can get a copy of the data with get_gui_feed_buffer () */ PBD::Signal1 > DataRecorded; PBD::Signal0 RecordEnableChanged; PBD::Signal0 RecordSafeChanged; void check_record_status (framepos_t transport_frame, bool can_record); void transport_looped (framepos_t transport_frame); void transport_stopped_wallclock (struct tm&, time_t, bool abort); void adjust_buffering (); protected: friend class Track; int do_flush (RunContext context, bool force = false); void get_input_sources (); void prepare_record_status (framepos_t /*capture_start_frame*/); void set_align_style_from_io(); void setup_destructive_playlist (); void use_destructive_playlist (); void prepare_to_stop (framepos_t transport_pos, framepos_t audible_frame); void engage_record_enable (); void disengage_record_enable (); void engage_record_safe (); void disengage_record_safe (); bool prep_record_enable (); bool prep_record_disable (); void calculate_record_range ( Evoral::OverlapType ot, framepos_t transport_frame, framecnt_t nframes, framecnt_t& rec_nframes, framecnt_t& rec_offset ); mutable Glib::Threads::Mutex capture_info_lock; CaptureInfos capture_info; private: gint _record_enabled; gint _record_safe; framepos_t capture_start_frame; framecnt_t capture_captured; bool was_recording; framecnt_t adjust_capture_position; framecnt_t _capture_offset; framepos_t first_recordable_frame; framepos_t last_recordable_frame; int last_possibly_recording; AlignStyle _alignment_style; AlignChoice _alignment_choice; std::string _write_source_name; boost::shared_ptr _midi_write_source; std::list > _last_capture_sources; std::vector > capturing_sources; static framecnt_t _chunk_frames; NoteMode _note_mode; volatile gint _frames_pending_write; volatile gint _num_captured_loops; framepos_t _accumulated_capture_offset; /** A buffer that we use to put newly-arrived MIDI data in for the GUI to read (so that it can update itself). */ MidiBuffer _gui_feed_buffer; mutable Glib::Threads::Mutex _gui_feed_buffer_mutex; void finish_capture (boost::shared_ptr c); }; } // namespace #endif /* __ardour_disk_writer_h__ */