34 #include <glibmm/threads.h>
43 #include "ardour/debug.h"
58 #include "ardour/utils.h"
60 #include "midi++/types.h"
69 framecnt_t MidiDiskstream::midi_readahead = 4096;
76 , _frames_written_to_ringbuffer(0)
77 , _frames_read_from_ringbuffer(0)
78 , _frames_pending_write(0)
79 , _num_captured_loops(0)
80 , _accumulated_capture_offset(0)
87 use_new_write_source (0);
101 , _frames_written_to_ringbuffer(0)
102 , _frames_read_from_ringbuffer(0)
103 , _frames_pending_write(0)
104 , _num_captured_loops(0)
105 , _accumulated_capture_offset(0)
155 seek (position,
false);
173 error <<
string_compose (
_(
"%1: I/O configuration change %4 requested to use %2, but channel setup is %3"),
220 if ((playlist = boost::dynamic_pointer_cast<MidiPlaylist> (
_session.
playlists->by_name (name))) == 0) {
235 if (boost::dynamic_pointer_cast<MidiPlaylist>(playlist)) {
323 *start = location->
start();
324 *end = location->
end();
325 *length = *end - *
start;
334 bool nominally_recording;
338 playback_distance = 0;
342 nominally_recording = (can_record && re);
405 if (nominally_recording || rec_nframes) {
413 if (ev.
time() + rec_offset > rec_nframes) {
418 const uint8_t* __data = ev.
buffer();
421 for (
size_t i=0; i < ev.
size(); ++i) {
453 if (buf.
size() != 0) {
486 if (rec_nframes == nframes && rec_offset == 0) {
487 playback_distance = nframes;
492 }
else if (nominally_recording) {
498 playback_distance = nframes;
507 playback_distance = nframes;
510 if (need_disk_signal) {
526 *tme = (*tme) * nframes / playback_distance;
545 return -playback_distance;
547 return playback_distance;
554 bool need_butler =
false;
608 if (frames_read <= frames_written) {
609 if ((frames_written - frames_read) + playback_distance <
midi_readahead) {
676 if (complete_refill) {
690 return ((frames_written - frames_read) < distance);
725 if (loc && (start >= loop_end)) {
727 start = loop_start + ((start - loop_start) % loop_length);
737 if (loc && (loop_end - start <= dur)) {
738 this_read = loop_end -
start;
746 if (this_read == 0) {
750 this_read = min(dur,this_read);
754 _(
"MidiDiskstream %1: cannot read %2 from playlist at frame %3"),
755 id(), this_read, start) <<
endmsg;
799 if (write_space == 0) {
819 if ((frames_read < frames_written) && (frames_written - frames_read) >=
midi_readahead) {
829 to_read = min (to_read, (
framecnt_t) write_space);
904 bool more_work =
true;
908 MidiRegion::SourceList::iterator src;
909 vector<CaptureInfo*>::iterator ci;
917 while (more_work && !err) {
934 goto no_capture_stuff_to_do;
951 total_capture += (*ci)->frames;
970 const Evoral::Beats total_capture_beats = converter.from (total_capture);
987 string whole_file_region_name;
1036 _name, (*ci)->start, (*ci)->frames, region_name));
1055 error <<
_(
"MidiDiskstream: could not create region for captured midi!") <<
endmsg;
1094 no_capture_stuff_to_do:
1202 cs_grandchild =
new XMLNode (
X_(
"file"));
1211 snprintf (buf,
sizeof (buf),
"%" PRId64, pi->
start());
1228 XMLNode* capture_pending_node = 0;
1235 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1236 if ((*niter)->name() ==
X_(
"CapturingSources")) {
1237 capture_pending_node = *niter;
1245 if (capture_pending_node) {
1310 return our_old_name;
1410 "%1 MDS pre-read read %8 @ %4..%5 from %2 write to %3, LOOPED ? %6-%7\n",
_name,
1412 (loc ? loc->
start() : -1), (loc ? loc->
end() : -1), nframes));
1418 size_t events_read = 0;
1431 if (effective_start == loc->
start()) {
1441 if (loc->
end() >= effective_start && loc->
end() < effective_start + nframes) {
1448 first = loc->
end() - effective_start;
1449 second = nframes - first;
1452 effective_start, loc->
end(), first, second));
1456 effective_start, first));
1462 loc->
start(), second));
1468 effective_start, nframes));
1469 events_read =
_playback_buf->
read (dst, effective_start, effective_start + nframes);
1477 "%1 MDS events read %2 range %3 .. %4 rspace %5 wspace %6 r@%7 w@%8\n",
1488 if (
_name == name) {
framepos_t first_recordable_frame
void resolve_tracker(MidiBuffer &dst, framepos_t)
XMLNodeList::iterator XMLNodeIterator
framepos_t get_capture_start_frame(uint32_t n=0) const
ARDOUR::Session & _session
void calculate_record_range(Evoral::OverlapType ot, framepos_t transport_frame, framecnt_t nframes, framecnt_t &rec_nframes, framecnt_t &rec_offset)
int set_destructive(bool yn)
static int region_name(std::string &, std::string, bool new_level=false)
framecnt_t distance(framecnt_t nframes, bool roll=true)
boost::shared_ptr< Playlist > _playlist
MidiBuffer & get_midi(size_t i)
size_t get_read_ptr() const
void transport_looped(framepos_t transport_frame)
MidiDiskstream(Session &, const std::string &name, Diskstream::Flag f=Recordable)
bool get_record_enabled() const
Glib::Threads::Mutex::Lock Lock
double transport_speed() const
LIBARDOUR_API PBD::PropertyDescriptor< layer_t > layer
PBD::Signal0< void > RecordEnableChanged
void set_count(const ChanCount &count)
virtual bool set_name(const std::string &str)
void disengage_record_enable()
virtual void set_capture_offset()
bool actively_recording() const
int use_pending_capture_data(XMLNode &node)
std::list< boost::shared_ptr< Source > > _last_capture_sources
void special_set_position(framepos_t)
int process(BufferSet &, framepos_t transport_frame, pframes_t nframes, framecnt_t &, bool need_diskstream)
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r)
LIBARDOUR_API PBD::PropertyDescriptor< std::string > name
boost::shared_ptr< MidiSource > create_midi_source_for_session(std::string const &)
volatile gint _frames_pending_write
uint32_t i_am_the_modifier
bool commit(framecnt_t nframes)
int find_and_use_playlist(const std::string &)
void add_command(Command *const cmd)
void set_speed(double new_speed)
LIBARDOUR_API uint64_t MidiIO
MidiRingBuffer< framepos_t > * _capture_buf
bool set_name(std::string const &)
framepos_t last_recordable_frame
void ensure_input_monitoring(bool)
int use_playlist(boost::shared_ptr< Playlist >)
MidiBuffer _gui_feed_buffer
std::string steal_write_source_name()
LIBARDOUR_API uint64_t MidiDiskstreamIO
LIBPBD_API Transmitter error
const XMLNodeList & children(const std::string &str=std::string()) const
int use_new_write_source(uint32_t n=0)
uint32_t write(Time time, Evoral::EventType type, uint32_t size, const uint8_t *buf)
int set_state(const XMLNode &, int version)
LIBARDOUR_API uint64_t CaptureAlignment
void set_block_size(pframes_t)
std::ostream & endmsg(std::ostream &ostr)
SessionConfiguration config
AlignChoice _alignment_choice
boost::weak_ptr< MidiPort > _source_port
virtual void check_record_status(framepos_t transport_frame, bool can_record)
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > start
void non_realtime_input_change()
gint _frames_written_to_ringbuffer
static AudioEngine * instance()
virtual bool set_write_source_name(const std::string &str)
MidiChannelFilter & playback_filter()
std::string _write_source_name
void thaw(bool from_undo=false)
void set_record_enabled(bool yn)
void ensure_input_monitoring(bool)
std::list< XMLNode * > XMLNodeList
PBD::Signal1< void, boost::weak_ptr< MidiSource > > DataRecorded
void flush(framepos_t start, framepos_t end)
void add_channel_to(int, int)
void flush_playback(framepos_t, framepos_t)
Glib::Threads::Mutex _gui_feed_buffer_mutex
static framecnt_t disk_write_chunk_frames
MidiRingBuffer< framepos_t > * _playback_buf
bool prep_record_enable()
CubicMidiInterpolation interpolation
IOChange input_change_pending
void transport_stopped_wallclock(struct tm &, time_t, bool abort)
void add_region(boost::shared_ptr< Region >, framepos_t position, float times=1, bool auto_partition=false)
const ChanCount & n_ports() const
Glib::Threads::Mutex state_lock
class LIBPBD_API StatefulDiffCommand
LIBARDOUR_API PBD::PropertyDescriptor< bool > automatic
int read(framepos_t &start, framecnt_t cnt, bool reversed)
int can_internal_playback_seek(framecnt_t distance)
void engage_record_enable()
boost::shared_ptr< ARDOUR::IO > _io
LIBARDOUR_API RCConfiguration * Config
void set_note_mode(NoteMode m)
void non_realtime_locate(framepos_t location)
std::vector< CaptureInfo * > capture_info
enum ARDOUR::IOChange::Type type
bool prep_record_disable()
MidiChannelFilter & capture_filter()
size_t read(MidiBuffer &dst, framepos_t start, framepos_t end, framecnt_t offset=0, bool stop_on_overflow_in_destination=false)
XMLNode & get_state(void)
static std::string bump_name(std::string old_name, Session &)
framepos_t transport_frame() const
float playback_buffer_load() const
framecnt_t adjust_capture_position
frameoffset_t calculate_playback_distance(pframes_t nframes)
static framecnt_t disk_read_chunk_frames
boost::shared_ptr< MidiPort > midi(uint32_t n) const
std::vector< boost::shared_ptr< Source > > SourceList
std::string new_midi_source_path(const std::string &)
bool record_enabled() const
#define DEBUG_TRACE(bits, str)
MidiBuffer & get_midi_buffer(pframes_t nframes)
virtual int set_state(const XMLNode &, int version)
void filter(BufferSet &bufs)
bool set_write_source_name(const std::string &str)
static int loading_state_version
PBD::Property< std::string > _name
framepos_t capture_start_frame
static void get_location_times(const Location *location, framepos_t *start, framepos_t *end, framepos_t *length)
void allocate_temporary_buffers()
void reset_note_trackers()
int seek(framepos_t which_sample, bool complete_refill=false)
framepos_t _accumulated_capture_offset
void copy(const MidiBuffer ©)
void set_align_style_from_io()
XMLProperty * add_property(const char *name, const std::string &value)
int do_refill_with_alloc()
LIBPBD_API uint64_t debug_bits
void add_child_nocopy(XMLNode &)
pframes_t get_block_size() const
int internal_playback_seek(framecnt_t distance)
#define DEBUG_STR_APPEND(id, s)
LIBARDOUR_API PBD::PropertyDescriptor< Evoral::Beats > length_beats
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > position
const ChanCount & count() const
bool push_back(const Evoral::MIDIEvent< TimeType > &event)
void set(DataType t, uint32_t count)
void reset_write_sources(bool, bool force=false)
OverlapType coverage(T sa, T ea, T sb, T eb)
framecnt_t capture_captured
size_t skip_to(framepos_t start)
bool record_enabling_legal() const
int do_flush(RunContext context, bool force=false)
framecnt_t length() const
void request_input_monitoring(bool)
static framecnt_t midi_readahead
framepos_t playback_sample
boost::shared_ptr< SessionPlaylists > playlists
static const framepos_t max_framepos
const uint8_t * buffer() const
boost::shared_ptr< SMFSource > _write_source
gint _frames_read_from_ringbuffer
static const framecnt_t max_framecnt
std::string write_source_name() const
#define DEBUG_STR_DECL(id)
Glib::Threads::Mutex capture_info_lock
void set_pending_overwrite(bool)
boost::shared_ptr< MidiPlaylist > midi_playlist()
static boost::shared_ptr< Region > create(boost::shared_ptr< const Region > other, bool announce=false)
framepos_t overwrite_frame
void get_playback(MidiBuffer &dst, framecnt_t)
virtual int use_playlist(boost::shared_ptr< Playlist >)
boost::shared_ptr< Playlist > playlist()
uint32_t midi_diskstream_buffer_size() const
virtual XMLNode & get_state(void)
void set_align_style(AlignStyle, bool force=false)
float capture_buffer_load() const
static boost::shared_ptr< Playlist > create(Session &, const XMLNode &, bool hidden=false, bool unused=false)
LIBARDOUR_API bool init(bool with_vst, bool try_optimization, const char *localedir)
LIBARDOUR_API std::string region_name_from_path(std::string path, bool strip_channels, bool add_channel_suffix=false, uint32_t total=0, uint32_t this_one=0)
bool add(PropertyBase *prop)
boost::shared_ptr< MidiBuffer > get_gui_feed_buffer() const
LIBARDOUR_API PBD::PropertyDescriptor< bool > whole_file
std::string string_compose(const std::string &fmt, const T1 &o1)
void resolve_tracker(Evoral::EventSink< framepos_t > &buffer, framepos_t time)
size_t get_write_ptr() const
volatile gint _num_captured_loops
int overwrite_existing_buffers()
LIBARDOUR_API PBD::PropertyDescriptor< framecnt_t > length
Location * auto_punch_location() const