ardour/libs/ardour/ardour/midi_track.h

208 lines
7.3 KiB
C
Raw Normal View History

/*
* Copyright (C) 2006-2015 David Robillard <d@drobilla.net>
* Copyright (C) 2007-2017 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
* Copyright (C) 2014-2019 Robin Gareus <robin@gareus.org>
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __ardour_midi_track_h__
#define __ardour_midi_track_h__
#include "ardour/midi_channel_filter.h"
#include "ardour/midi_ring_buffer.h"
#include "ardour/key.h"
#include "ardour/track.h"
namespace ARDOUR
{
namespace Properties {
LIBARDOUR_API extern PBD::PropertyDescriptor<MusicalKey::Type> musical_mode;
LIBARDOUR_API extern PBD::PropertyDescriptor<int> musical_root;
}
class InterThreadInfo;
class MidiPlaylist;
class RouteGroup;
class SMFSource;
class Session;
class LIBARDOUR_API MidiTrack : public Track
{
public:
MidiTrack (Session&, std::string name = "", TrackMode m = Normal);
~MidiTrack ();
int init ();
static void make_property_quarks ();
void realtime_locate (bool);
void non_realtime_locate (samplepos_t);
bool can_be_record_enabled ();
bool can_be_record_safe ();
void freeze_me (InterThreadInfo&);
void unfreeze ();
bool bounceable (boost::shared_ptr<Processor>, bool) const { return false; }
boost::shared_ptr<Region> bounce (InterThreadInfo&, std::string const&);
boost::shared_ptr<Region> bounce_range (samplepos_t start,
samplepos_t end,
InterThreadInfo& iti,
boost::shared_ptr<Processor> endpoint,
bool include_endpoint,
std::string const& name);
int export_stuff (BufferSet& bufs,
samplepos_t start_sample,
samplecnt_t end_sample,
boost::shared_ptr<Processor> endpoint,
bool include_endpoint,
bool for_export,
bool for_freeze,
MidiStateTracker& tracker);
int set_state (const XMLNode&, int version);
void midi_panic(void);
bool write_immediate_event (Evoral::EventType event_type, size_t size, const uint8_t* buf);
/** A control that will send "immediate" events to a MIDI track when twiddled */
struct MidiControl : public AutomationControl {
MidiControl(MidiTrack* route, const Evoral::Parameter& param,
boost::shared_ptr<AutomationList> al = boost::shared_ptr<AutomationList>())
: AutomationControl (route->session(), param, ParameterDescriptor(param), al)
, _route (route)
{}
bool writable() const { return true; }
void restore_value ();
MidiTrack* _route;
private:
void actually_set_value (double val, PBD::Controllable::GroupControlDisposition group_override);
};
virtual void set_parameter_automation_state (Evoral::Parameter param, AutoState);
NoteMode note_mode() const { return _note_mode; }
void set_note_mode (NoteMode m);
std::string describe_parameter (Evoral::Parameter param);
bool step_editing() const { return _step_editing; }
void set_step_editing (bool yn);
MidiRingBuffer<samplepos_t>& step_edit_ring_buffer() { return _step_edit_ring_buffer; }
PBD::Signal1<void,bool> StepEditStatusChange;
boost::shared_ptr<SMFSource> write_source (uint32_t n = 0);
Squashed commit of the following: commit fdbae82077db53add90df7448a06869dac89acc6 Author: Paul Davis <paul@linuxaudiosystems.com> Date: Wed Mar 27 21:45:28 2013 -0400 mammoth changes in basic signal flow, total redesign of MIDI channel filtering and more. commit 59343a8283698e02bc0f622313b29e98f449e4c8 Author: Paul Davis <paul@linuxaudiosystems.com> Date: Wed Mar 27 01:58:53 2013 -0400 initial working version after changes to MIDI channel filtering. may affect metering input too. testing not yet finished this commit merges many deep changes in ardour's internal architecture, combined with a total redesign of how MIDI channel filtering works. data in a track used to flow from JACK port buffers to diskstream's ringbuffers and was then copied from the ringbuffers into a BufferSet for use during Route::process_output_buffers(). The butler thread would handle the movement of data between the ringbuffers and disk. with this commit, data now flows from JACK port buffers into the BufferSet used for Route processing, and is copied from the BufferSet into the diskstream's ringbuffers (the butler thread continues to handle interactions with disk as usual). this change allowed a dramatic consolidation of code and simplification of most aspects of Track/Route::roll() and Track/Route::no_roll(). in particular, see Route::fill_buffers_with_input() which now concisely describes how we move data from JACK port buffers into the BufferSet for all Route types (including Tracks). this work was initially motivated by changing MIDI channel filtering so that we can process capture and playback independently. there is now a very clean pathway for this - see MidiTrack::roll() (NOTE: This needs implementing in the no-roll case too - a TODO item). the channel selector for MIDI tracks has been moved out of the track header and is now accessible via the context menu. more work is likely here, to make it (more) obvious to the user when filtering is going on.
2013-03-27 21:50:18 -04:00
/* Configure capture/playback channels (see MidiChannelFilter). */
2014-12-30 14:41:22 -05:00
void set_capture_channel_mode (ChannelMode mode, uint16_t mask);
void set_playback_channel_mode (ChannelMode mode, uint16_t mask);
void set_playback_channel_mask (uint16_t mask);
void set_capture_channel_mask (uint16_t mask);
Squashed commit of the following: commit fdbae82077db53add90df7448a06869dac89acc6 Author: Paul Davis <paul@linuxaudiosystems.com> Date: Wed Mar 27 21:45:28 2013 -0400 mammoth changes in basic signal flow, total redesign of MIDI channel filtering and more. commit 59343a8283698e02bc0f622313b29e98f449e4c8 Author: Paul Davis <paul@linuxaudiosystems.com> Date: Wed Mar 27 01:58:53 2013 -0400 initial working version after changes to MIDI channel filtering. may affect metering input too. testing not yet finished this commit merges many deep changes in ardour's internal architecture, combined with a total redesign of how MIDI channel filtering works. data in a track used to flow from JACK port buffers to diskstream's ringbuffers and was then copied from the ringbuffers into a BufferSet for use during Route::process_output_buffers(). The butler thread would handle the movement of data between the ringbuffers and disk. with this commit, data now flows from JACK port buffers into the BufferSet used for Route processing, and is copied from the BufferSet into the diskstream's ringbuffers (the butler thread continues to handle interactions with disk as usual). this change allowed a dramatic consolidation of code and simplification of most aspects of Track/Route::roll() and Track/Route::no_roll(). in particular, see Route::fill_buffers_with_input() which now concisely describes how we move data from JACK port buffers into the BufferSet for all Route types (including Tracks). this work was initially motivated by changing MIDI channel filtering so that we can process capture and playback independently. there is now a very clean pathway for this - see MidiTrack::roll() (NOTE: This needs implementing in the no-roll case too - a TODO item). the channel selector for MIDI tracks has been moved out of the track header and is now accessible via the context menu. more work is likely here, to make it (more) obvious to the user when filtering is going on.
2013-03-27 21:50:18 -04:00
ChannelMode get_playback_channel_mode() const { return _playback_filter.get_channel_mode(); }
ChannelMode get_capture_channel_mode() const { return _capture_filter.get_channel_mode(); }
uint16_t get_playback_channel_mask() const { return _playback_filter.get_channel_mask(); }
uint16_t get_capture_channel_mask() const { return _capture_filter.get_channel_mask(); }
MidiChannelFilter& playback_filter() { return _playback_filter; }
MidiChannelFilter& capture_filter() { return _capture_filter; }
Squashed commit of the following: commit fdbae82077db53add90df7448a06869dac89acc6 Author: Paul Davis <paul@linuxaudiosystems.com> Date: Wed Mar 27 21:45:28 2013 -0400 mammoth changes in basic signal flow, total redesign of MIDI channel filtering and more. commit 59343a8283698e02bc0f622313b29e98f449e4c8 Author: Paul Davis <paul@linuxaudiosystems.com> Date: Wed Mar 27 01:58:53 2013 -0400 initial working version after changes to MIDI channel filtering. may affect metering input too. testing not yet finished this commit merges many deep changes in ardour's internal architecture, combined with a total redesign of how MIDI channel filtering works. data in a track used to flow from JACK port buffers to diskstream's ringbuffers and was then copied from the ringbuffers into a BufferSet for use during Route::process_output_buffers(). The butler thread would handle the movement of data between the ringbuffers and disk. with this commit, data now flows from JACK port buffers into the BufferSet used for Route processing, and is copied from the BufferSet into the diskstream's ringbuffers (the butler thread continues to handle interactions with disk as usual). this change allowed a dramatic consolidation of code and simplification of most aspects of Track/Route::roll() and Track/Route::no_roll(). in particular, see Route::fill_buffers_with_input() which now concisely describes how we move data from JACK port buffers into the BufferSet for all Route types (including Tracks). this work was initially motivated by changing MIDI channel filtering so that we can process capture and playback independently. there is now a very clean pathway for this - see MidiTrack::roll() (NOTE: This needs implementing in the no-roll case too - a TODO item). the channel selector for MIDI tracks has been moved out of the track header and is now accessible via the context menu. more work is likely here, to make it (more) obvious to the user when filtering is going on.
2013-03-27 21:50:18 -04:00
virtual void filter_input (BufferSet& bufs);
boost::shared_ptr<MidiPlaylist> midi_playlist ();
PBD::Signal1<void, boost::weak_ptr<MidiSource> > DataRecorded;
boost::shared_ptr<MidiBuffer> get_gui_feed_buffer () const;
MonitorState monitoring_state () const;
MonitorState get_input_monitoring_state (bool recording, bool talkback) const;
MidiBuffer const& immediate_event_buffer () const { return _immediate_event_buffer; }
MidiRingBuffer<samplepos_t>& immediate_events () { return _immediate_events; }
void set_input_active (bool);
bool input_active () const;
PBD::Signal0<void> InputActiveChanged;
void set_restore_pgm_on_load (bool yn);
bool restore_pgm_on_load () const;
void realtime_handle_transport_stopped ();
void region_edited (boost::shared_ptr<Region>);
MusicalKey const & key() const { return _key; }
void set_key (MusicalKey const & key);
KeyEnforcementPolicy key_enforcment_policy () const;
void set_key_enforcement_policy (KeyEnforcementPolicy);
protected:
XMLNode& state (bool save_template);
void act_on_mute ();
void monitoring_changed (bool, PBD::Controllable::GroupControlDisposition);
void snapshot_out_of_band_data (samplecnt_t nframes);
void write_out_of_band_data (BufferSet& bufs, samplecnt_t /* nframes */) const;
private:
MidiRingBuffer<samplepos_t> _immediate_events;
MidiBuffer _immediate_event_buffer;
MidiRingBuffer<samplepos_t> _step_edit_ring_buffer;
NoteMode _note_mode;
bool _step_editing;
bool _input_active;
bool _restore_pgm_on_load;
MidiChannelFilter _playback_filter;
MidiChannelFilter _capture_filter;
MusicalKey _key;
KeyEnforcementPolicy _key_enforcement_policy;
void set_state_part_two ();
void set_state_part_three ();
int no_roll_unlocked (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool state_changing);
void push_midi_input_to_step_edit_ringbuffer (samplecnt_t nframes);
void track_input_active (IOChange, void*);
void map_input_active (bool);
Squashed commit of the following: commit fdbae82077db53add90df7448a06869dac89acc6 Author: Paul Davis <paul@linuxaudiosystems.com> Date: Wed Mar 27 21:45:28 2013 -0400 mammoth changes in basic signal flow, total redesign of MIDI channel filtering and more. commit 59343a8283698e02bc0f622313b29e98f449e4c8 Author: Paul Davis <paul@linuxaudiosystems.com> Date: Wed Mar 27 01:58:53 2013 -0400 initial working version after changes to MIDI channel filtering. may affect metering input too. testing not yet finished this commit merges many deep changes in ardour's internal architecture, combined with a total redesign of how MIDI channel filtering works. data in a track used to flow from JACK port buffers to diskstream's ringbuffers and was then copied from the ringbuffers into a BufferSet for use during Route::process_output_buffers(). The butler thread would handle the movement of data between the ringbuffers and disk. with this commit, data now flows from JACK port buffers into the BufferSet used for Route processing, and is copied from the BufferSet into the diskstream's ringbuffers (the butler thread continues to handle interactions with disk as usual). this change allowed a dramatic consolidation of code and simplification of most aspects of Track/Route::roll() and Track/Route::no_roll(). in particular, see Route::fill_buffers_with_input() which now concisely describes how we move data from JACK port buffers into the BufferSet for all Route types (including Tracks). this work was initially motivated by changing MIDI channel filtering so that we can process capture and playback independently. there is now a very clean pathway for this - see MidiTrack::roll() (NOTE: This needs implementing in the no-roll case too - a TODO item). the channel selector for MIDI tracks has been moved out of the track header and is now accessible via the context menu. more work is likely here, to make it (more) obvious to the user when filtering is going on.
2013-03-27 21:50:18 -04:00
void data_recorded (boost::weak_ptr<MidiSource> src);
/** Update automation controls to reflect any changes in buffers. */
void update_controls (BufferSet const& bufs);
void restore_controls ();
void playlist_contents_changed ();
PBD::ScopedConnection playlist_content_change_connection;
};
} /* namespace ARDOUR*/
#endif /* __ardour_midi_track_h__ */