committed RWlock fixes to libardour. added hw monitoring fixes from nick_m. minor alsa midi fix and update rate settings.
git-svn-id: svn://localhost/trunk/ardour2@244 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
18844bac7a
commit
bd21c474e5
@ -1753,6 +1753,9 @@ void
|
||||
OptionEditor::hw_monitor_clicked ()
|
||||
{
|
||||
Config->set_use_hardware_monitoring (hw_monitor_button.get_active());
|
||||
if (session) {
|
||||
session->reset_input_monitor_state ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -117,6 +117,9 @@ class Configuration : public Stateful
|
||||
|
||||
string get_midi_port_name();
|
||||
void set_midi_port_name(string);
|
||||
|
||||
uint32_t get_midi_feedback_interval_ms();
|
||||
void set_midi_feedback_interval_ms (uint32_t);
|
||||
|
||||
bool get_use_hardware_monitoring();
|
||||
void set_use_hardware_monitoring(bool);
|
||||
@ -238,6 +241,8 @@ class Configuration : public Stateful
|
||||
bool use_vst; /* always per-user */
|
||||
bool quieten_at_speed;
|
||||
bool quieten_at_speed_is_user;
|
||||
uint32_t midi_feedback_interval_ms;
|
||||
bool midi_feedback_interval_ms_is_user;
|
||||
|
||||
XMLNode *key_node;
|
||||
bool user_configuration;
|
||||
|
@ -305,7 +305,6 @@ class DiskStream : public Stateful, public sigc::trackable
|
||||
id_t _id;
|
||||
|
||||
atomic_t _record_enabled;
|
||||
bool rec_monitoring_off_for_roll;
|
||||
AudioPlaylist* _playlist;
|
||||
double _visible_speed;
|
||||
double _actual_speed;
|
||||
|
@ -140,14 +140,14 @@ class Route : public IO
|
||||
void flush_redirects ();
|
||||
|
||||
template<class T> void foreach_redirect (T *obj, void (T::*func)(Redirect *)) {
|
||||
LockMonitor lm (redirect_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__);
|
||||
for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
|
||||
(obj->*func) (*i);
|
||||
}
|
||||
}
|
||||
|
||||
Redirect *nth_redirect (uint32_t n) {
|
||||
LockMonitor lm (redirect_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__);
|
||||
RedirectList::iterator i;
|
||||
for (i = _redirects.begin(); i != _redirects.end() && n; ++i, --n);
|
||||
if (i == _redirects.end()) {
|
||||
@ -288,7 +288,7 @@ class Route : public IO
|
||||
jack_nframes_t _roll_delay;
|
||||
jack_nframes_t _own_latency;
|
||||
RedirectList _redirects;
|
||||
PBD::NonBlockingLock redirect_lock;
|
||||
PBD::NonBlockingRWLock redirect_lock;
|
||||
IO *_control_outs;
|
||||
PBD::NonBlockingLock control_outs_lock;
|
||||
RouteGroup *_edit_group;
|
||||
|
@ -273,7 +273,7 @@ class Session : public sigc::trackable, public Stateful
|
||||
typedef list<DiskStream *> DiskStreamList;
|
||||
|
||||
Session::DiskStreamList disk_streams() const {
|
||||
LockMonitor lm (diskstream_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
return diskstreams; /* XXX yes, force a copy */
|
||||
}
|
||||
|
||||
@ -283,7 +283,7 @@ class Session : public sigc::trackable, public Stateful
|
||||
typedef slist<Route *> RouteList;
|
||||
|
||||
RouteList get_routes() const {
|
||||
LockMonitor rlock (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor rlock (route_lock, false, __LINE__, __FILE__);
|
||||
return routes; /* XXX yes, force a copy */
|
||||
}
|
||||
|
||||
@ -410,6 +410,7 @@ class Session : public sigc::trackable, public Stateful
|
||||
void set_auto_play (bool yn);
|
||||
void set_auto_return (bool yn);
|
||||
void set_auto_input (bool yn);
|
||||
void reset_input_monitor_state ();
|
||||
void set_input_auto_connect (bool yn);
|
||||
void set_output_auto_connect (AutoConnectOption);
|
||||
void set_punch_in (bool yn);
|
||||
@ -993,7 +994,7 @@ class Session : public sigc::trackable, public Stateful
|
||||
Location* end_location;
|
||||
Slave *_slave;
|
||||
SlaveSource _slave_type;
|
||||
float _transport_speed;
|
||||
volatile float _transport_speed;
|
||||
volatile float _desired_transport_speed;
|
||||
float _last_transport_speed;
|
||||
jack_nframes_t _last_slave_transport_frame;
|
||||
@ -1473,7 +1474,7 @@ class Session : public sigc::trackable, public Stateful
|
||||
/* disk-streams */
|
||||
|
||||
DiskStreamList diskstreams;
|
||||
mutable PBD::Lock diskstream_lock;
|
||||
mutable PBD::NonBlockingRWLock diskstream_lock;
|
||||
uint32_t dstream_buffer_size;
|
||||
void add_diskstream (DiskStream*);
|
||||
int load_diskstreams (const XMLNode&);
|
||||
@ -1481,7 +1482,7 @@ class Session : public sigc::trackable, public Stateful
|
||||
/* routes stuff */
|
||||
|
||||
RouteList routes;
|
||||
mutable PBD::NonBlockingLock route_lock;
|
||||
mutable PBD::NonBlockingRWLock route_lock;
|
||||
void add_route (Route*);
|
||||
|
||||
int load_routes (const XMLNode&);
|
||||
@ -1685,6 +1686,7 @@ class Session : public sigc::trackable, public Stateful
|
||||
Sample* click_emphasis_data;
|
||||
jack_nframes_t click_length;
|
||||
jack_nframes_t click_emphasis_length;
|
||||
mutable PBD::NonBlockingRWLock click_lock;
|
||||
|
||||
static const Sample default_click[];
|
||||
static const jack_nframes_t default_click_length;
|
||||
|
@ -29,7 +29,7 @@ namespace ARDOUR {
|
||||
template<class T> void
|
||||
Session::foreach_diskstream (T *obj, void (T::*func)(DiskStream&))
|
||||
{
|
||||
LockMonitor lm (diskstream_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); i++) {
|
||||
if (!(*i)->hidden()) {
|
||||
(obj->*func) (**i);
|
||||
|
@ -35,7 +35,7 @@ Session::foreach_route (T *obj, void (T::*func)(Route&))
|
||||
RouteList public_order;
|
||||
|
||||
{
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
public_order = routes;
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ Session::foreach_route (T *obj, void (T::*func)(Route*))
|
||||
RouteList public_order;
|
||||
|
||||
{
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
public_order = routes;
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ Session::foreach_route (T *obj, void (T::*func)(Route&, A), A arg1)
|
||||
RouteList public_order;
|
||||
|
||||
{
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
public_order = routes;
|
||||
}
|
||||
|
||||
|
@ -574,8 +574,15 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
|
||||
Sample* tmpb;
|
||||
jack_nframes_t transport_frame;
|
||||
|
||||
automation_snapshot (start_frame);
|
||||
|
||||
{
|
||||
TentativeRWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__);
|
||||
if (lm.locked()) {
|
||||
// automation snapshot can also be called from the non-rt context
|
||||
// and it uses the redirect list, so we take the lock out here
|
||||
automation_snapshot (start_frame);
|
||||
}
|
||||
}
|
||||
|
||||
if (n_outputs() == 0 && _redirects.empty()) {
|
||||
return 0;
|
||||
}
|
||||
@ -649,11 +656,12 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
|
||||
}
|
||||
}
|
||||
|
||||
/* don't waste time with automation if we're recording */
|
||||
/* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
|
||||
|
||||
if (!diskstream->record_enabled()) {
|
||||
if (!diskstream->record_enabled() && _session.transport_rolling()) {
|
||||
TentativeLockMonitor am (automation_lock, __LINE__, __FILE__);
|
||||
|
||||
if (gain_automation_playback()) {
|
||||
if (am.locked() && gain_automation_playback()) {
|
||||
apply_gain_automation = _gain_automation_curve.rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
|
||||
}
|
||||
}
|
||||
@ -683,7 +691,7 @@ AudioTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jac
|
||||
|
||||
_silent = true;
|
||||
apply_gain_automation = false;
|
||||
|
||||
|
||||
silence (nframes, offset);
|
||||
|
||||
return diskstream->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
|
||||
@ -721,7 +729,7 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes
|
||||
vector<Sample*>::iterator bi;
|
||||
Sample * b;
|
||||
|
||||
LockMonitor rlock (redirect_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor rlock (redirect_lock, false, __LINE__, __FILE__);
|
||||
|
||||
if (diskstream->playlist()->read (buffers[0], mix_buffer, gain_buffer, start, nframes) != nframes) {
|
||||
return -1;
|
||||
@ -890,7 +898,7 @@ AudioTrack::freeze (InterThreadInfo& itt)
|
||||
_freeze_record.have_mementos = true;
|
||||
|
||||
{
|
||||
LockMonitor lm (redirect_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (RedirectList::iterator r = _redirects.begin(); r != _redirects.end(); ++r) {
|
||||
|
||||
@ -947,7 +955,7 @@ AudioTrack::unfreeze ()
|
||||
|
||||
} else {
|
||||
|
||||
LockMonitor lm (redirect_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__); // should this be a write lock? jlc
|
||||
for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
|
||||
for (vector<FreezeRecordInsertInfo*>::iterator ii = _freeze_record.insert_info.begin(); ii != _freeze_record.insert_info.end(); ++ii) {
|
||||
if ((*ii)->id == (*i)->id()) {
|
||||
|
@ -207,6 +207,11 @@ Configuration::state (bool user_only)
|
||||
node->add_child_nocopy(option_node("disk-choice-space-threshold", string(buf)));
|
||||
}
|
||||
|
||||
if (!user_only || midi_feedback_interval_ms_is_user) {
|
||||
snprintf(buf, sizeof(buf), "%" PRIu32, midi_feedback_interval_ms);
|
||||
node->add_child_nocopy(option_node("midi-feedback-interval-ms", string(buf)));
|
||||
}
|
||||
|
||||
if (!user_only || mute_affects_pre_fader_is_user) {
|
||||
node->add_child_nocopy(option_node("mute-affects-pre-fader", mute_affects_pre_fader?"yes":"no"));
|
||||
}
|
||||
@ -422,6 +427,8 @@ Configuration::set_state (const XMLNode& root)
|
||||
if (sscanf (option_value.c_str(), "%f", &v) == 1) {
|
||||
set_quieten_at_speed (v);
|
||||
}
|
||||
} else if (option_name == "midi-feedback-interval-ms") {
|
||||
set_midi_feedback_interval_ms (atoi (option_value.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -472,13 +479,15 @@ Configuration::set_defaults ()
|
||||
stop_recording_on_xrun = false;
|
||||
verify_remove_last_capture = true;
|
||||
stop_at_session_end = true;
|
||||
seamless_looping = false;
|
||||
seamless_looping = true;
|
||||
auto_xfade = true;
|
||||
no_new_session_dialog = false;
|
||||
timecode_source_is_synced = true;
|
||||
use_vst = true; /* if we build with VST_SUPPORT, otherwise no effect */
|
||||
quieten_at_speed = true;
|
||||
|
||||
midi_feedback_interval_ms = 100;
|
||||
|
||||
// this is about 5 minutes at 48kHz, 4 bytes/sample
|
||||
disk_choice_space_threshold = 57600000;
|
||||
|
||||
@ -514,6 +523,7 @@ Configuration::set_defaults ()
|
||||
no_new_session_dialog_is_user = false;
|
||||
timecode_source_is_synced_is_user = false;
|
||||
quieten_at_speed_is_user = false;
|
||||
midi_feedback_interval_ms_is_user = false;
|
||||
}
|
||||
|
||||
Configuration::MidiPortDescriptor::MidiPortDescriptor (const XMLNode& node)
|
||||
@ -832,6 +842,21 @@ Configuration::set_midi_port_name (string name)
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Configuration::get_midi_feedback_interval_ms ()
|
||||
{
|
||||
return midi_feedback_interval_ms;
|
||||
}
|
||||
|
||||
void
|
||||
Configuration::set_midi_feedback_interval_ms (uint32_t val)
|
||||
{
|
||||
midi_feedback_interval_ms = val;
|
||||
if (user_configuration) {
|
||||
midi_feedback_interval_ms_is_user = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Configuration::get_use_hardware_monitoring()
|
||||
{
|
||||
|
@ -128,7 +128,6 @@ DiskStream::init (Flag f)
|
||||
_alignment_style = ExistingMaterial;
|
||||
_persistent_alignment_style = ExistingMaterial;
|
||||
first_input_change = true;
|
||||
rec_monitoring_off_for_roll = false;
|
||||
_playlist = 0;
|
||||
i_am_the_modifier = 0;
|
||||
atomic_set (&_record_enabled, 0);
|
||||
@ -735,16 +734,6 @@ DiskStream::process (jack_nframes_t transport_frame, jack_nframes_t nframes, jac
|
||||
if (can_record && !_last_capture_regions.empty()) {
|
||||
_last_capture_regions.clear ();
|
||||
}
|
||||
|
||||
if (rec_nframes) {
|
||||
|
||||
if (Config->get_use_hardware_monitoring() && re && rec_monitoring_off_for_roll && rec_monitors_input) {
|
||||
for (c = channels.begin(); c != channels.end(); ++c) {
|
||||
(*c).source->ensure_monitor_input (true);
|
||||
}
|
||||
rec_monitoring_off_for_roll = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (nominally_recording || rec_nframes) {
|
||||
|
||||
@ -807,6 +796,7 @@ DiskStream::process (jack_nframes_t transport_frame, jack_nframes_t nframes, jac
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
/* we can't use the capture buffer as the playback buffer, because
|
||||
we recorded only a part of the current process' cycle data
|
||||
for capture.
|
||||
@ -1685,24 +1675,6 @@ DiskStream::transport_stopped (struct tm& when, time_t twhen, bool abort_capture
|
||||
void
|
||||
DiskStream::finish_capture (bool rec_monitors_input)
|
||||
{
|
||||
if (Config->get_use_hardware_monitoring() && record_enabled()) {
|
||||
if (rec_monitors_input) {
|
||||
if (rec_monitoring_off_for_roll) {
|
||||
for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
|
||||
(*chan).source->ensure_monitor_input (true);
|
||||
}
|
||||
rec_monitoring_off_for_roll = false;
|
||||
}
|
||||
} else {
|
||||
if (!rec_monitoring_off_for_roll) {
|
||||
for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
|
||||
(*chan).source->ensure_monitor_input (false);
|
||||
}
|
||||
rec_monitoring_off_for_roll = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
was_recording = false;
|
||||
|
||||
if (capture_captured == 0) {
|
||||
@ -1732,6 +1704,8 @@ DiskStream::finish_capture (bool rec_monitors_input)
|
||||
void
|
||||
DiskStream::set_record_enabled (bool yn, void* src)
|
||||
{
|
||||
bool rolling = _session.transport_speed() != 0.0f;
|
||||
|
||||
if (!recordable() || !_session.record_enabling_legal()) {
|
||||
return;
|
||||
}
|
||||
@ -1765,10 +1739,10 @@ DiskStream::set_record_enabled (bool yn, void* src)
|
||||
if (yn) {
|
||||
atomic_set (&_record_enabled, 1);
|
||||
capturing_sources.clear ();
|
||||
if (Config->get_use_hardware_monitoring()) {
|
||||
if (Config->get_use_hardware_monitoring()) {
|
||||
for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
|
||||
if ((*chan).source) {
|
||||
(*chan).source->request_monitor_input (true);
|
||||
(*chan).source->request_monitor_input (!(_session.get_auto_input() && rolling));
|
||||
}
|
||||
capturing_sources.push_back ((*chan).write_source);
|
||||
}
|
||||
|
@ -2358,7 +2358,8 @@ IO::MIDIGainControl::send_feedback (gain_t gain)
|
||||
if (get_control_info (ch, ev, additional)) {
|
||||
data.controller_number = additional;
|
||||
data.value = val;
|
||||
|
||||
last_written = val;
|
||||
|
||||
io._session.send_midi_message (get_port(), ev, ch, data);
|
||||
}
|
||||
//send_midi_feedback (gain_to_midi (gain));
|
||||
|
@ -109,7 +109,8 @@ StreamPanner::MIDIControl::send_feedback (pan_t value)
|
||||
if (get_control_info (ch, ev, additional)) {
|
||||
data.controller_number = additional;
|
||||
data.value = val;
|
||||
|
||||
last_written = val;
|
||||
|
||||
sp.get_parent().session().send_midi_message (get_port(), ev, ch, data);
|
||||
}
|
||||
|
||||
|
@ -162,7 +162,8 @@ Plugin::MIDIPortControl::send_feedback (float value)
|
||||
if (get_control_info (ch, ev, additional)) {
|
||||
data.controller_number = additional;
|
||||
data.value = val;
|
||||
|
||||
last_written = val;
|
||||
|
||||
plugin.session().send_midi_message (get_port(), ev, ch, data);
|
||||
}
|
||||
}
|
||||
|
@ -314,7 +314,7 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
||||
-------------------------------------------------------------------------------------------------- */
|
||||
|
||||
if (with_redirects) {
|
||||
TentativeLockMonitor rm (redirect_lock, __LINE__, __FILE__);
|
||||
TentativeRWLockMonitor rm (redirect_lock, false, __LINE__, __FILE__);
|
||||
if (rm.locked()) {
|
||||
if (mute_gain > 0 || !_mute_affects_pre_fader) {
|
||||
for (i = _redirects.begin(); i != _redirects.end(); ++i) {
|
||||
@ -428,7 +428,7 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
||||
}
|
||||
}
|
||||
|
||||
if (apply_gain_automation) {
|
||||
if (apply_gain_automation && _session.transport_rolling()) {
|
||||
_effective_gain = gab[nframes-1];
|
||||
}
|
||||
|
||||
@ -483,7 +483,7 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
||||
|
||||
if (post_fader_work) {
|
||||
|
||||
TentativeLockMonitor rm (redirect_lock, __LINE__, __FILE__);
|
||||
TentativeRWLockMonitor rm (redirect_lock, false, __LINE__, __FILE__);
|
||||
if (rm.locked()) {
|
||||
if (mute_gain > 0 || !_mute_affects_post_fader) {
|
||||
for (i = _redirects.begin(); i != _redirects.end(); ++i) {
|
||||
@ -755,7 +755,7 @@ Route::add_redirect (Redirect *redirect, void *src, uint32_t* err_streams)
|
||||
}
|
||||
|
||||
{
|
||||
LockMonitor lm (redirect_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (redirect_lock, true, __LINE__, __FILE__);
|
||||
|
||||
PluginInsert* pi;
|
||||
PortInsert* porti;
|
||||
@ -816,7 +816,7 @@ Route::add_redirects (const RedirectList& others, void *src, uint32_t* err_strea
|
||||
}
|
||||
|
||||
{
|
||||
LockMonitor lm (redirect_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (redirect_lock, true, __LINE__, __FILE__);
|
||||
|
||||
RedirectList::iterator existing_end = _redirects.end();
|
||||
--existing_end;
|
||||
@ -861,7 +861,7 @@ Route::clear_redirects (void *src)
|
||||
}
|
||||
|
||||
{
|
||||
LockMonitor lm (redirect_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (redirect_lock, true, __LINE__, __FILE__);
|
||||
|
||||
for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
|
||||
delete *i;
|
||||
@ -891,7 +891,7 @@ Route::remove_redirect (Redirect *redirect, void *src, uint32_t* err_streams)
|
||||
redirect_max_outs = 0;
|
||||
|
||||
{
|
||||
LockMonitor lm (redirect_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (redirect_lock, true, __LINE__, __FILE__);
|
||||
RedirectList::iterator i;
|
||||
bool removed = false;
|
||||
|
||||
@ -970,7 +970,7 @@ Route::remove_redirect (Redirect *redirect, void *src, uint32_t* err_streams)
|
||||
int
|
||||
Route::reset_plugin_counts (uint32_t* lpc)
|
||||
{
|
||||
LockMonitor lm (redirect_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (redirect_lock, true, __LINE__, __FILE__);
|
||||
return _reset_plugin_counts (lpc);
|
||||
}
|
||||
|
||||
@ -1140,7 +1140,7 @@ Route::copy_redirects (const Route& other, Placement placement, uint32_t* err_st
|
||||
RedirectList to_be_deleted;
|
||||
|
||||
{
|
||||
LockMonitor lm (redirect_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (redirect_lock, true, __LINE__, __FILE__);
|
||||
RedirectList::iterator tmp;
|
||||
RedirectList the_copy;
|
||||
|
||||
@ -1219,7 +1219,7 @@ Route::copy_redirects (const Route& other, Placement placement, uint32_t* err_st
|
||||
void
|
||||
Route::all_redirects_flip ()
|
||||
{
|
||||
LockMonitor lm (redirect_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__);
|
||||
|
||||
if (_redirects.empty()) {
|
||||
return;
|
||||
@ -1235,7 +1235,7 @@ Route::all_redirects_flip ()
|
||||
void
|
||||
Route::all_redirects_active (bool state)
|
||||
{
|
||||
LockMonitor lm (redirect_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__);
|
||||
|
||||
if (_redirects.empty()) {
|
||||
return;
|
||||
@ -1257,7 +1257,7 @@ Route::sort_redirects (uint32_t* err_streams)
|
||||
{
|
||||
{
|
||||
RedirectSorter comparator;
|
||||
LockMonitor lm (redirect_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (redirect_lock, true, __LINE__, __FILE__);
|
||||
uint32_t old_rmo = redirect_max_outs;
|
||||
|
||||
/* the sweet power of C++ ... */
|
||||
@ -1736,7 +1736,7 @@ Route::silence (jack_nframes_t nframes, jack_nframes_t offset)
|
||||
}
|
||||
|
||||
{
|
||||
TentativeLockMonitor lm (redirect_lock, __LINE__, __FILE__);
|
||||
TentativeRWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__);
|
||||
|
||||
if (lm.locked()) {
|
||||
for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
|
||||
@ -1935,12 +1935,13 @@ Route::transport_stopped (bool abort_ignored, bool did_locate, bool can_flush_re
|
||||
{
|
||||
jack_nframes_t now = _session.transport_frame();
|
||||
|
||||
if (!did_locate) {
|
||||
automation_snapshot (now);
|
||||
}
|
||||
|
||||
{
|
||||
LockMonitor lm (redirect_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__);
|
||||
|
||||
if (!did_locate) {
|
||||
automation_snapshot (now);
|
||||
}
|
||||
|
||||
for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
|
||||
|
||||
if (Config->get_plugins_stop_with_transport() && can_flush_redirects) {
|
||||
@ -2014,7 +2015,7 @@ Route::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes
|
||||
}
|
||||
|
||||
apply_gain_automation = false;
|
||||
|
||||
|
||||
if (n_inputs()) {
|
||||
passthru (start_frame, end_frame, nframes, offset, 0, false);
|
||||
} else {
|
||||
@ -2053,8 +2054,15 @@ int
|
||||
Route::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, int declick,
|
||||
bool can_record, bool rec_monitors_input)
|
||||
{
|
||||
automation_snapshot (_session.transport_frame());
|
||||
|
||||
{
|
||||
TentativeRWLockMonitor lm(redirect_lock, false, __LINE__, __FILE__);
|
||||
if (lm.locked()) {
|
||||
// automation snapshot can also be called from the non-rt context
|
||||
// and it uses the redirect list, so we take the lock out here
|
||||
automation_snapshot (_session.transport_frame());
|
||||
}
|
||||
}
|
||||
|
||||
if ((n_outputs() == 0 && _redirects.empty()) || n_inputs() == 0 || !_active) {
|
||||
silence (nframes, offset);
|
||||
return 0;
|
||||
@ -2067,12 +2075,13 @@ Route::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t
|
||||
}
|
||||
|
||||
_silent = false;
|
||||
|
||||
apply_gain_automation = false;
|
||||
|
||||
{
|
||||
TentativeLockMonitor am (automation_lock, __LINE__, __FILE__);
|
||||
|
||||
if (am.locked()) {
|
||||
if (am.locked() && _session.transport_rolling()) {
|
||||
|
||||
jack_nframes_t start_frame = end_frame - nframes;
|
||||
|
||||
@ -2162,7 +2171,7 @@ Route::send_all_midi_feedback ()
|
||||
if (_session.get_midi_feedback()) {
|
||||
|
||||
{
|
||||
LockMonitor lm (redirect_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__);
|
||||
for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
|
||||
(*i)->send_all_midi_feedback ();
|
||||
}
|
||||
@ -2182,7 +2191,7 @@ Route::write_midi_feedback (MIDI::byte* buf, int32_t& bufsize)
|
||||
buf = _midi_mute_control.write_feedback (buf, bufsize, _muted);
|
||||
|
||||
{
|
||||
LockMonitor lm (redirect_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__);
|
||||
for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
|
||||
buf = (*i)->write_midi_feedback (buf, bufsize);
|
||||
}
|
||||
@ -2198,7 +2207,7 @@ Route::flush_redirects ()
|
||||
this is called from the RT audio thread.
|
||||
*/
|
||||
|
||||
LockMonitor lm (redirect_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (redirect_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
|
||||
(*i)->deactivate ();
|
||||
@ -2333,7 +2342,8 @@ Route::MIDIToggleControl::send_feedback (bool value)
|
||||
if (get_control_info (ch, ev, additional)) {
|
||||
data.controller_number = additional;
|
||||
data.value = val;
|
||||
|
||||
last_written = value;
|
||||
|
||||
route._session.send_midi_message (get_port(), ev, ch, data);
|
||||
}
|
||||
}
|
||||
|
@ -541,7 +541,7 @@ Session::set_worst_io_latencies (bool take_lock)
|
||||
}
|
||||
|
||||
if (take_lock) {
|
||||
route_lock.lock ();
|
||||
route_lock.read_lock ();
|
||||
}
|
||||
|
||||
for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
|
||||
@ -933,11 +933,51 @@ Session::set_auto_input (bool yn)
|
||||
{
|
||||
if (auto_input != yn) {
|
||||
auto_input = yn;
|
||||
|
||||
if (Config->get_use_hardware_monitoring() && transport_rolling()) {
|
||||
/* auto-input only makes a difference if we're rolling */
|
||||
|
||||
/* Even though this can called from RT context we are using
|
||||
a non-tentative rwlock here, because the action must occur.
|
||||
The rarity and short potential lock duration makes this "OK"
|
||||
*/
|
||||
RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
if ((*i)->record_enabled ()) {
|
||||
//cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
|
||||
(*i)->monitor_input (!auto_input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_dirty();
|
||||
ControlChanged (AutoInput);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Session::reset_input_monitor_state ()
|
||||
{
|
||||
if (transport_rolling()) {
|
||||
RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
if ((*i)->record_enabled ()) {
|
||||
//cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
|
||||
(*i)->monitor_input (Config->get_use_hardware_monitoring() && !auto_input);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
if ((*i)->record_enabled ()) {
|
||||
//cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
|
||||
(*i)->monitor_input (Config->get_use_hardware_monitoring());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Session::set_input_auto_connect (bool yn)
|
||||
{
|
||||
@ -1192,6 +1232,22 @@ Session::enable_record ()
|
||||
atomic_set (&_record_status, Recording);
|
||||
_last_record_location = _transport_frame;
|
||||
send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordStrobe);
|
||||
|
||||
if (Config->get_use_hardware_monitoring() && auto_input) {
|
||||
/* Even though this can be called from RT context we are using
|
||||
a non-tentative rwlock here, because the action must occur.
|
||||
The rarity and short potential lock duration makes this "OK"
|
||||
*/
|
||||
RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
if ((*i)->record_enabled ()) {
|
||||
//cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
|
||||
(*i)->monitor_input (true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RecordEnabled ();
|
||||
}
|
||||
}
|
||||
@ -1202,8 +1258,25 @@ Session::disable_record ()
|
||||
if (atomic_read (&_record_status) != Disabled) {
|
||||
atomic_set (&_record_status, Disabled);
|
||||
send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordExit);
|
||||
|
||||
if (Config->get_use_hardware_monitoring() && auto_input) {
|
||||
/* Even though this can be called from RT context we are using
|
||||
a non-tentative rwlock here, because the action must occur.
|
||||
The rarity and short potential lock duration makes this "OK"
|
||||
*/
|
||||
RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
if ((*i)->record_enabled ()) {
|
||||
//cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
|
||||
(*i)->monitor_input (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RecordDisabled ();
|
||||
remove_pending_capture_state ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1211,6 +1284,21 @@ void
|
||||
Session::step_back_from_record ()
|
||||
{
|
||||
atomic_set (&_record_status, Enabled);
|
||||
|
||||
if (Config->get_use_hardware_monitoring()) {
|
||||
/* Even though this can be called from RT context we are using
|
||||
a non-tentative rwlock here, because the action must occur.
|
||||
The rarity and short potential lock duration makes this "OK"
|
||||
*/
|
||||
RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
if (auto_input && (*i)->record_enabled ()) {
|
||||
//cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
|
||||
(*i)->monitor_input (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -1320,7 +1408,8 @@ Session::set_block_size (jack_nframes_t nframes)
|
||||
*/
|
||||
|
||||
{
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
vector<Sample*>::iterator i;
|
||||
uint32_t np;
|
||||
|
||||
@ -1381,7 +1470,8 @@ Session::set_default_fade (float steepness, float fade_msecs)
|
||||
default_fade_steepness = steepness;
|
||||
|
||||
{
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
// jlc, WTF is this!
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
AudioRegion::set_default_fade (steepness, fade_frames);
|
||||
}
|
||||
|
||||
@ -1532,7 +1622,7 @@ Session::new_audio_track (int input_channels, int output_channels)
|
||||
/* count existing audio tracks */
|
||||
|
||||
{
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
|
||||
if (dynamic_cast<AudioTrack*>(*i) != 0) {
|
||||
if (!(*i)->hidden()) {
|
||||
@ -1646,7 +1736,7 @@ Session::new_audio_route (int input_channels, int output_channels)
|
||||
/* count existing audio busses */
|
||||
|
||||
{
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
|
||||
if (dynamic_cast<AudioTrack*>(*i) == 0) {
|
||||
if (!(*i)->hidden()) {
|
||||
@ -1729,7 +1819,7 @@ void
|
||||
Session::add_route (Route* route)
|
||||
{
|
||||
{
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, true, __LINE__, __FILE__);
|
||||
routes.push_front (route);
|
||||
resort_routes(0);
|
||||
}
|
||||
@ -1756,8 +1846,11 @@ Session::add_route (Route* route)
|
||||
void
|
||||
Session::add_diskstream (DiskStream* dstream)
|
||||
{
|
||||
/* need to do this in case we're rolling at the time, to prevent false underruns */
|
||||
dstream->do_refill(0, 0);
|
||||
|
||||
{
|
||||
LockMonitor lm (diskstream_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (diskstream_lock, true, __LINE__, __FILE__);
|
||||
diskstreams.push_back (dstream);
|
||||
}
|
||||
|
||||
@ -1785,7 +1878,7 @@ void
|
||||
Session::remove_route (Route& route)
|
||||
{
|
||||
{
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, true, __LINE__, __FILE__);
|
||||
routes.remove (&route);
|
||||
|
||||
/* deleting the master out seems like a dumb
|
||||
@ -1813,7 +1906,7 @@ Session::remove_route (Route& route)
|
||||
}
|
||||
|
||||
{
|
||||
LockMonitor lm (diskstream_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (diskstream_lock, true, __LINE__, __FILE__);
|
||||
|
||||
AudioTrack* at;
|
||||
|
||||
@ -1849,7 +1942,7 @@ Session::route_solo_changed (void* src, Route* route)
|
||||
return;
|
||||
}
|
||||
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
bool is_track;
|
||||
|
||||
is_track = (dynamic_cast<AudioTrack*>(route) != 0);
|
||||
@ -2045,14 +2138,14 @@ Session::catch_up_on_solo ()
|
||||
basis, but needs the global overview that only the session
|
||||
has.
|
||||
*/
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
update_route_solo_state();
|
||||
}
|
||||
|
||||
Route *
|
||||
Session::route_by_name (string name)
|
||||
{
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
|
||||
if ((*i)->name() == name) {
|
||||
@ -2094,7 +2187,7 @@ Session::find_current_end ()
|
||||
DiskStream *
|
||||
Session::diskstream_by_name (string name)
|
||||
{
|
||||
LockMonitor lm (diskstream_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
if ((*i)->name() == name) {
|
||||
@ -2108,7 +2201,7 @@ Session::diskstream_by_name (string name)
|
||||
DiskStream *
|
||||
Session::diskstream_by_id (id_t id)
|
||||
{
|
||||
LockMonitor lm (diskstream_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
if ((*i)->id() == id) {
|
||||
@ -2433,6 +2526,8 @@ Session::remove_last_capture ()
|
||||
{
|
||||
list<Region*> r;
|
||||
|
||||
RWLockMonitor lm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
list<Region*>& l = (*i)->last_capture_regions();
|
||||
|
||||
@ -2830,19 +2925,13 @@ Session::old_peak_path_from_audio_path (string audio_path)
|
||||
void
|
||||
Session::set_all_solo (bool yn)
|
||||
{
|
||||
/* XXX this copy is not safe: the Routes within the list
|
||||
can still be deleted after the Route lock is released.
|
||||
*/
|
||||
|
||||
RouteList copy;
|
||||
{
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
copy = routes;
|
||||
}
|
||||
|
||||
for (RouteList::iterator i = copy.begin(); i != copy.end(); ++i) {
|
||||
if (!(*i)->hidden()) {
|
||||
(*i)->set_solo (yn, this);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
|
||||
if (!(*i)->hidden()) {
|
||||
(*i)->set_solo (yn, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2852,15 +2941,13 @@ Session::set_all_solo (bool yn)
|
||||
void
|
||||
Session::set_all_mute (bool yn)
|
||||
{
|
||||
RouteList copy;
|
||||
{
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
copy = routes;
|
||||
}
|
||||
|
||||
for (RouteList::iterator i = copy.begin(); i != copy.end(); ++i) {
|
||||
if (!(*i)->hidden()) {
|
||||
(*i)->set_mute (yn, this);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
|
||||
if (!(*i)->hidden()) {
|
||||
(*i)->set_mute (yn, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2870,7 +2957,7 @@ Session::set_all_mute (bool yn)
|
||||
uint32_t
|
||||
Session::n_diskstreams () const
|
||||
{
|
||||
LockMonitor lm (diskstream_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
uint32_t n = 0;
|
||||
|
||||
for (DiskStreamList::const_iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
@ -2884,7 +2971,7 @@ Session::n_diskstreams () const
|
||||
void
|
||||
Session::foreach_diskstream (void (DiskStream::*func)(void))
|
||||
{
|
||||
LockMonitor lm (diskstream_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
if (!(*i)->hidden()) {
|
||||
((*i)->*func)();
|
||||
@ -2903,8 +2990,8 @@ Session::graph_reordered ()
|
||||
return;
|
||||
}
|
||||
|
||||
LockMonitor lm1 (route_lock, __LINE__, __FILE__);
|
||||
LockMonitor lm2 (diskstream_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm1 (route_lock, true, __LINE__, __FILE__);
|
||||
RWLockMonitor lm2 (diskstream_lock, false, __LINE__, __FILE__);
|
||||
|
||||
resort_routes (0);
|
||||
|
||||
@ -2932,7 +3019,7 @@ Session::record_enable_all ()
|
||||
void
|
||||
Session::record_enable_change_all (bool yn)
|
||||
{
|
||||
LockMonitor lm1 (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm1 (route_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
|
||||
AudioTrack* at;
|
||||
@ -3181,8 +3268,9 @@ Session::remove_named_selection (NamedSelection* named_selection)
|
||||
void
|
||||
Session::reset_native_file_format ()
|
||||
{
|
||||
LockMonitor lm1 (route_lock, __LINE__, __FILE__);
|
||||
LockMonitor lm2 (diskstream_lock, __LINE__, __FILE__);
|
||||
// jlc - WHY take routelock?
|
||||
//RWLockMonitor lm1 (route_lock, true, __LINE__, __FILE__);
|
||||
RWLockMonitor lm2 (diskstream_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
(*i)->reset_write_sources (false);
|
||||
@ -3192,7 +3280,7 @@ Session::reset_native_file_format ()
|
||||
bool
|
||||
Session::route_name_unique (string n) const
|
||||
{
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (RouteList::const_iterator i = routes.begin(); i != routes.end(); ++i) {
|
||||
if ((*i)->name() == n) {
|
||||
@ -3269,7 +3357,7 @@ Session::add_instant_xml (XMLNode& node, const std::string& dir)
|
||||
int
|
||||
Session::freeze (InterThreadInfo& itt)
|
||||
{
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
|
||||
|
||||
@ -3438,7 +3526,7 @@ uint32_t
|
||||
Session::ntracks () const
|
||||
{
|
||||
uint32_t n = 0;
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (RouteList::const_iterator i = routes.begin(); i != routes.end(); ++i) {
|
||||
if (dynamic_cast<AudioTrack*> (*i)) {
|
||||
@ -3453,7 +3541,7 @@ uint32_t
|
||||
Session::nbusses () const
|
||||
{
|
||||
uint32_t n = 0;
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (RouteList::const_iterator i = routes.begin(); i != routes.end(); ++i) {
|
||||
if (dynamic_cast<AudioTrack*> (*i) == 0) {
|
||||
|
@ -254,6 +254,8 @@ Session::butler_thread_work ()
|
||||
|
||||
gettimeofday (&begin, 0);
|
||||
|
||||
RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (i = diskstreams.begin(); !transport_work_requested() && butler_should_run && i != diskstreams.end(); ++i) {
|
||||
|
||||
// cerr << "rah fondr " << (*i)->io()->name () << endl;
|
||||
@ -394,7 +396,7 @@ Session::overwrite_some_buffers (DiskStream* ds)
|
||||
|
||||
} else {
|
||||
|
||||
LockMonitor dm (diskstream_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor dm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
(*i)->set_pending_overwrite (true);
|
||||
}
|
||||
|
@ -46,8 +46,10 @@ Session::click (jack_nframes_t start, jack_nframes_t nframes, jack_nframes_t off
|
||||
if (_click_io == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
TentativeRWLockMonitor clickm (click_lock, true, __LINE__, __FILE__);
|
||||
|
||||
if (_transport_speed != 1.0 || !_clicking || click_data == 0) {
|
||||
if (!clickm.locked() || _transport_speed != 1.0 || !_clicking || click_data == 0) {
|
||||
_click_io->silence (nframes, offset);
|
||||
return;
|
||||
}
|
||||
@ -207,7 +209,7 @@ Session::setup_click_sounds (int which)
|
||||
void
|
||||
Session::clear_clicks ()
|
||||
{
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (click_lock, true, __LINE__, __FILE__);
|
||||
|
||||
for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
|
||||
delete *i;
|
||||
|
@ -342,12 +342,6 @@ Session::process_event (Event* ev)
|
||||
case Event::PunchIn:
|
||||
// cerr << "PunchIN at " << transport_frame() << endl;
|
||||
if (punch_in && record_status() == Enabled) {
|
||||
{
|
||||
LockMonitor lm (diskstream_lock, __LINE__, __FILE__);
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
(*i)->punch_in();
|
||||
}
|
||||
}
|
||||
enable_record ();
|
||||
}
|
||||
remove = false;
|
||||
|
@ -485,7 +485,7 @@ Session::prepare_to_export (AudioExportSpecification& spec)
|
||||
/* take everyone out of awrite to avoid disasters */
|
||||
|
||||
{
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
|
||||
(*i)->protect_automation ();
|
||||
}
|
||||
@ -494,7 +494,7 @@ Session::prepare_to_export (AudioExportSpecification& spec)
|
||||
/* get everyone to the right position */
|
||||
|
||||
{
|
||||
LockMonitor lm (diskstream_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
if ((*i)-> seek (spec.start_frame, true)) {
|
||||
error << string_compose (_("%1: cannot seek to %2 for export"),
|
||||
|
@ -124,7 +124,7 @@ Session::feedback_thread_work ()
|
||||
|
||||
if (active_feedback) {
|
||||
/* XXX use Config->feedback_interval_usecs()*/;
|
||||
timeout = 250;
|
||||
timeout = max (5, (int) Config->get_midi_feedback_interval_ms());
|
||||
} else {
|
||||
timeout = -1;
|
||||
}
|
||||
@ -162,7 +162,7 @@ Session::feedback_thread_work ()
|
||||
switch ((FeedbackRequest::Type) req) {
|
||||
|
||||
case FeedbackRequest::Start:
|
||||
timeout = 250;
|
||||
timeout = max (5, (int) Config->get_midi_feedback_interval_ms());
|
||||
active_feedback++;
|
||||
break;
|
||||
|
||||
@ -193,7 +193,7 @@ Session::feedback_thread_work ()
|
||||
}
|
||||
}
|
||||
|
||||
if (!active_feedback) {
|
||||
if (!active_feedback || transport_stopped()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -224,7 +224,7 @@ Session::feedback_generic_midi_function ()
|
||||
MIDI::byte* end = buf;
|
||||
|
||||
{
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
|
||||
end = (*i)->write_midi_feedback (end, bsize);
|
||||
@ -236,10 +236,11 @@ Session::feedback_generic_midi_function ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
// cerr << "MIDI feedback: write " << (int32_t) (end - buf) << " of " << buf << " to midi port\n";
|
||||
|
||||
deliver_midi (_midi_port, buf, (int32_t) (end - buf));
|
||||
|
||||
//cerr << "MIDI feedback: wrote " << (int32_t) (end - buf) << " to midi port\n";
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ using namespace MIDI;
|
||||
MachineControl::CommandSignature MMC_CommandSignature;
|
||||
MachineControl::ResponseSignature MMC_ResponseSignature;
|
||||
|
||||
MultiAllocSingleReleasePool Session::MIDIRequest::pool ("midi", sizeof (Session::MIDIRequest), 256);
|
||||
MultiAllocSingleReleasePool Session::MIDIRequest::pool ("midi", sizeof (Session::MIDIRequest), 1024);
|
||||
|
||||
int
|
||||
Session::use_config_midi_ports ()
|
||||
@ -110,7 +110,7 @@ Session::set_midi_control (bool yn)
|
||||
poke_midi_thread ();
|
||||
|
||||
if (_midi_port) {
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
|
||||
(*i)->reset_midi_control (_midi_port, midi_control);
|
||||
}
|
||||
@ -478,7 +478,7 @@ Session::send_all_midi_feedback ()
|
||||
{
|
||||
if (midi_feedback) {
|
||||
// send out current state of all routes
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
|
||||
(*i)->send_all_midi_feedback ();
|
||||
}
|
||||
|
@ -280,11 +280,13 @@ Session::process_with_events (jack_nframes_t nframes)
|
||||
end_frame = _transport_frame + nframes;
|
||||
|
||||
{
|
||||
TentativeLockMonitor rm (route_lock, __LINE__, __FILE__);
|
||||
TentativeRWLockMonitor rm (route_lock, false, __LINE__, __FILE__);
|
||||
TentativeRWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
|
||||
Event* this_event;
|
||||
Events::iterator the_next_one;
|
||||
|
||||
if (!rm.locked() || (post_transport_work & (PostTransportLocate|PostTransportStop))) {
|
||||
if (!rm.locked() || !dsm.locked() || (post_transport_work & (PostTransportLocate|PostTransportStop))) {
|
||||
no_roll (nframes, 0);
|
||||
return;
|
||||
}
|
||||
@ -543,9 +545,11 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset)
|
||||
if (slave_state == Waiting) {
|
||||
|
||||
// cerr << "waiting at " << slave_transport_frame << endl;
|
||||
|
||||
if (slave_transport_frame >= slave_wait_end) {
|
||||
TentativeRWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
|
||||
if (dsm.locked() && slave_transport_frame >= slave_wait_end) {
|
||||
// cerr << "\tstart at " << _transport_frame << endl;
|
||||
|
||||
slave_state = Running;
|
||||
|
||||
bool ok = true;
|
||||
@ -662,7 +666,13 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset)
|
||||
*/
|
||||
|
||||
bool need_butler;
|
||||
|
||||
TentativeRWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
if (!dsm.locked()) {
|
||||
goto noroll;
|
||||
}
|
||||
|
||||
|
||||
prepare_diskstreams ();
|
||||
silent_process_routes (nframes, offset);
|
||||
commit_diskstreams (nframes, need_butler);
|
||||
@ -708,9 +718,10 @@ Session::process_without_events (jack_nframes_t nframes)
|
||||
long frames_moved;
|
||||
|
||||
{
|
||||
TentativeLockMonitor rm (route_lock, __LINE__, __FILE__);
|
||||
TentativeRWLockMonitor rm (route_lock, false, __LINE__, __FILE__);
|
||||
TentativeRWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
|
||||
if (!rm.locked() || (post_transport_work & (PostTransportLocate|PostTransportStop))) {
|
||||
if (!rm.locked() || !dsm.locked() || (post_transport_work & (PostTransportLocate|PostTransportStop))) {
|
||||
no_roll (nframes, 0);
|
||||
return;
|
||||
}
|
||||
@ -779,7 +790,7 @@ Session::process_without_events (jack_nframes_t nframes)
|
||||
void
|
||||
Session::process_audition (jack_nframes_t nframes)
|
||||
{
|
||||
TentativeLockMonitor rm (route_lock, __LINE__, __FILE__);
|
||||
TentativeRWLockMonitor rm (route_lock, false, __LINE__, __FILE__);
|
||||
Event* ev;
|
||||
|
||||
if (rm.locked()) {
|
||||
|
@ -1344,7 +1344,7 @@ Session::state(bool full_state)
|
||||
child = node->add_child ("DiskStreams");
|
||||
|
||||
{
|
||||
LockMonitor dl (diskstream_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor dl (diskstream_lock, false, __LINE__, __FILE__);
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
if (!(*i)->hidden()) {
|
||||
child->add_child_nocopy ((*i)->get_state());
|
||||
@ -1366,7 +1366,7 @@ Session::state(bool full_state)
|
||||
|
||||
child = node->add_child ("Routes");
|
||||
{
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
|
||||
RoutePublicOrderSorter cmp;
|
||||
RouteList public_order(routes);
|
||||
@ -2313,7 +2313,7 @@ Session::load_route_groups (const XMLNode& node, bool edit)
|
||||
void
|
||||
Session::swap_configuration(Configuration** new_config)
|
||||
{
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, true, __LINE__, __FILE__); // jlc - WHY?
|
||||
Configuration* tmp = *new_config;
|
||||
*new_config = Config;
|
||||
Config = tmp;
|
||||
@ -2323,7 +2323,7 @@ Session::swap_configuration(Configuration** new_config)
|
||||
void
|
||||
Session::copy_configuration(Configuration* new_config)
|
||||
{
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, true, __LINE__, __FILE__);
|
||||
new_config = new Configuration(*Config);
|
||||
}
|
||||
|
||||
@ -2474,7 +2474,7 @@ Session::GlobalRouteBooleanState
|
||||
Session::get_global_route_boolean (bool (Route::*method)(void) const)
|
||||
{
|
||||
GlobalRouteBooleanState s;
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
|
||||
if (!(*i)->hidden()) {
|
||||
@ -2494,7 +2494,7 @@ Session::GlobalRouteMeterState
|
||||
Session::get_global_route_metering ()
|
||||
{
|
||||
GlobalRouteMeterState s;
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
|
||||
if (!(*i)->hidden()) {
|
||||
|
@ -192,14 +192,18 @@ Session::realtime_stop (bool abort)
|
||||
disable_record ();
|
||||
|
||||
reset_slave_state ();
|
||||
|
||||
|
||||
_transport_speed = 0;
|
||||
|
||||
transport_sub_state = (auto_return ? AutoReturning : 0);
|
||||
}
|
||||
|
||||
void
|
||||
Session::butler_transport_work ()
|
||||
{
|
||||
RWLockMonitor rm (route_lock, false, __LINE__, __FILE__);
|
||||
RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
|
||||
if (post_transport_work & PostTransportCurveRealloc) {
|
||||
for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
|
||||
(*i)->curve_reallocate();
|
||||
@ -253,7 +257,7 @@ Session::butler_transport_work ()
|
||||
void
|
||||
Session::non_realtime_set_speed ()
|
||||
{
|
||||
LockMonitor lm (diskstream_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
(*i)->non_realtime_set_speed ();
|
||||
@ -263,7 +267,7 @@ Session::non_realtime_set_speed ()
|
||||
void
|
||||
Session::non_realtime_overwrite ()
|
||||
{
|
||||
LockMonitor lm (diskstream_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
if ((*i)->pending_overwrite) {
|
||||
@ -448,7 +452,7 @@ Session::set_auto_loop (bool yn)
|
||||
{
|
||||
/* Called from event-handling context */
|
||||
|
||||
if (actively_recording() || _locations.auto_loop_location() == 0) {
|
||||
if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -603,18 +607,51 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b
|
||||
|
||||
} else {
|
||||
|
||||
/* XXX i don't know where else to put this. something has to clear the
|
||||
current clicks, and without deadlocking. clear_clicks() takes
|
||||
the route lock which would deadlock in this context.
|
||||
*/
|
||||
/* this is functionally what clear_clicks() does but with a tentative lock */
|
||||
|
||||
for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
|
||||
delete *i;
|
||||
}
|
||||
TentativeRWLockMonitor clickm (click_lock, true, __LINE__, __FILE__);
|
||||
|
||||
if (clickm.locked()) {
|
||||
|
||||
for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
|
||||
delete *i;
|
||||
}
|
||||
|
||||
clicks.clear ();
|
||||
clicks.clear ();
|
||||
}
|
||||
}
|
||||
|
||||
if (with_roll) {
|
||||
/* switch from input if we're going to roll */
|
||||
if (Config->get_use_hardware_monitoring()) {
|
||||
/* Even though this is called from RT context we are using
|
||||
a non-tentative rwlock here, because the action must occur.
|
||||
The rarity and short potential lock duration makes this "OK"
|
||||
*/
|
||||
RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
if ((*i)->record_enabled ()) {
|
||||
cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
|
||||
(*i)->monitor_input (!auto_input);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* otherwise we're going to stop, so do the opposite */
|
||||
if (Config->get_use_hardware_monitoring()) {
|
||||
/* Even though this is called from RT context we are using
|
||||
a non-tentative rwlock here, because the action must occur.
|
||||
The rarity and short potential lock duration makes this "OK"
|
||||
*/
|
||||
RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
if ((*i)->record_enabled ()) {
|
||||
cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
|
||||
(*i)->monitor_input (true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* cancel autoloop if transport pos outside of loop range */
|
||||
if (auto_loop) {
|
||||
@ -644,6 +681,21 @@ Session::set_transport_speed (float speed, bool abort)
|
||||
|
||||
if (transport_rolling() && speed == 0.0) {
|
||||
|
||||
if (Config->get_use_hardware_monitoring())
|
||||
{
|
||||
/* Even though this is called from RT context we are using
|
||||
a non-tentative rwlock here, because the action must occur.
|
||||
The rarity and short potential lock duration makes this "OK"
|
||||
*/
|
||||
RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
if ((*i)->record_enabled ()) {
|
||||
//cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
|
||||
(*i)->monitor_input (true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (synced_to_jack ()) {
|
||||
_engine.transport_stop ();
|
||||
} else {
|
||||
@ -652,6 +704,20 @@ Session::set_transport_speed (float speed, bool abort)
|
||||
|
||||
} else if (transport_stopped() && speed == 1.0) {
|
||||
|
||||
if (Config->get_use_hardware_monitoring()) {
|
||||
/* Even though this is called from RT context we are using
|
||||
a non-tentative rwlock here, because the action must occur.
|
||||
The rarity and short potential lock duration makes this "OK"
|
||||
*/
|
||||
RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
if (auto_input && (*i)->record_enabled ()) {
|
||||
//cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
|
||||
(*i)->monitor_input (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (synced_to_jack()) {
|
||||
_engine.transport_start ();
|
||||
} else {
|
||||
@ -690,7 +756,7 @@ Session::set_transport_speed (float speed, bool abort)
|
||||
|
||||
_last_transport_speed = _transport_speed;
|
||||
_transport_speed = speed;
|
||||
|
||||
|
||||
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
|
||||
if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
|
||||
post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
|
||||
@ -1102,8 +1168,8 @@ Session::update_latency_compensation (bool with_stop, bool abort)
|
||||
return;
|
||||
}
|
||||
|
||||
LockMonitor lm (route_lock, __LINE__, __FILE__);
|
||||
LockMonitor lm2 (diskstream_lock, __LINE__, __FILE__);
|
||||
RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
|
||||
RWLockMonitor lm2 (diskstream_lock, false, __LINE__, __FILE__);
|
||||
_worst_track_latency = 0;
|
||||
|
||||
for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
|
||||
|
@ -83,13 +83,15 @@ int ALSA_SequencerMidiPort::write (byte *msg, size_t msglen)
|
||||
{
|
||||
TR_FN ();
|
||||
int R;
|
||||
int totwritten = 0;
|
||||
snd_midi_event_reset_encode (encoder);
|
||||
int nwritten = snd_midi_event_encode (encoder, msg, msglen, &SEv);
|
||||
TR_VAL (nwritten);
|
||||
if (0 < nwritten) {
|
||||
while (0 < nwritten) {
|
||||
if (0 <= (R = snd_seq_event_output (seq, &SEv)) &&
|
||||
0 <= (R = snd_seq_drain_output (seq))) {
|
||||
bytes_written += nwritten;
|
||||
totwritten += nwritten;
|
||||
if (output_parser) {
|
||||
output_parser->raw_preparse (*output_parser, msg, nwritten);
|
||||
for (int i = 0; i < nwritten; i++) {
|
||||
@ -97,13 +99,23 @@ int ALSA_SequencerMidiPort::write (byte *msg, size_t msglen)
|
||||
}
|
||||
output_parser->raw_postparse (*output_parser, msg, nwritten);
|
||||
}
|
||||
return nwritten;
|
||||
} else {
|
||||
TR_VAL(R);
|
||||
return R;
|
||||
}
|
||||
} else
|
||||
return nwritten;
|
||||
|
||||
msglen -= nwritten;
|
||||
msg += nwritten;
|
||||
if (msglen > 0) {
|
||||
nwritten = snd_midi_event_encode (encoder, msg, msglen, &SEv);
|
||||
TR_VAL(nwritten);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return totwritten;
|
||||
}
|
||||
|
||||
int ALSA_SequencerMidiPort::read (byte *buf, size_t max)
|
||||
|
@ -57,6 +57,31 @@ class NonBlockingLock : public Lock {
|
||||
int unlock() { return pthread_mutex_unlock (&_mutex); }
|
||||
};
|
||||
|
||||
class RWLock {
|
||||
public:
|
||||
RWLock() { pthread_rwlock_init (&_mutex, 0); }
|
||||
virtual ~RWLock() { pthread_rwlock_destroy(&_mutex); }
|
||||
|
||||
virtual int write_lock () { return pthread_rwlock_wrlock (&_mutex); }
|
||||
virtual int read_lock () { return pthread_rwlock_rdlock (&_mutex); }
|
||||
virtual int unlock() { return pthread_rwlock_unlock (&_mutex); }
|
||||
|
||||
pthread_rwlock_t *mutex() { return &_mutex; }
|
||||
|
||||
protected:
|
||||
pthread_rwlock_t _mutex;
|
||||
};
|
||||
|
||||
class NonBlockingRWLock : public RWLock {
|
||||
public:
|
||||
NonBlockingRWLock() {}
|
||||
~NonBlockingRWLock(){}
|
||||
|
||||
int write_trylock () { return pthread_rwlock_trywrlock (&_mutex); }
|
||||
int read_trylock () { return pthread_rwlock_tryrdlock (&_mutex); }
|
||||
};
|
||||
|
||||
|
||||
class LockMonitor
|
||||
{
|
||||
public:
|
||||
@ -189,6 +214,112 @@ class SpinLockMonitor
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
class RWLockMonitor
|
||||
{
|
||||
public:
|
||||
RWLockMonitor (RWLock& lck, bool write, unsigned long l, const char *f)
|
||||
: lock (lck)
|
||||
#ifdef DEBUG_LOCK_MONITOR
|
||||
, line (l), file (f)
|
||||
#endif
|
||||
{
|
||||
|
||||
#ifdef DEBUG_LOCK_MONITOR
|
||||
unsigned long long when;
|
||||
when = get_cycles();
|
||||
cerr << when << " lock " << &lock << " at " << line << " in " << file << endl;
|
||||
#endif
|
||||
if (write) {
|
||||
lock.write_lock ();
|
||||
} else {
|
||||
lock.read_lock ();
|
||||
}
|
||||
#ifdef DEBUG_LOCK_MONITOR
|
||||
when = get_cycles();
|
||||
cerr << '\t' << when
|
||||
<< " locked: "
|
||||
<< &lock << " at "
|
||||
<< line << " in " << file << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
~RWLockMonitor () {
|
||||
lock.unlock ();
|
||||
#ifdef DEBUG_LOCK_MONITOR
|
||||
unsigned long long when;
|
||||
when = get_cycles();
|
||||
cerr << '\t' << when << ' '
|
||||
<< " UNLOCKED "
|
||||
<< &lock << " at "
|
||||
<< line << " in " << file << endl;
|
||||
#endif
|
||||
}
|
||||
private:
|
||||
RWLock& lock;
|
||||
#ifdef DEBUG_LOCK_MONITOR
|
||||
unsigned long line;
|
||||
const char * file;
|
||||
#endif
|
||||
};
|
||||
|
||||
class TentativeRWLockMonitor
|
||||
{
|
||||
public:
|
||||
TentativeRWLockMonitor (NonBlockingRWLock& lck, bool write, unsigned long l, const char *f)
|
||||
: lock (lck)
|
||||
#ifdef DEBUG_LOCK_MONITOR
|
||||
, line (l), file (f)
|
||||
#endif
|
||||
{
|
||||
|
||||
#ifdef DEBUG_LOCK_MONITOR
|
||||
unsigned long long when;
|
||||
when = get_cycles();
|
||||
cerr << when << " tentative lock " << &lock << " at " << line << " in " << file << endl;
|
||||
#endif
|
||||
if (write) {
|
||||
_locked = (lock.write_trylock() == 0);
|
||||
} else {
|
||||
_locked = (lock.read_trylock() == 0);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOCK_MONITOR
|
||||
when = get_cycles();
|
||||
cerr << '\t' << when << ' '
|
||||
<< _locked
|
||||
<< " lock: "
|
||||
<< &lock << " at "
|
||||
<< line << " in " << file << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
~TentativeRWLockMonitor () {
|
||||
if (_locked) {
|
||||
lock.unlock ();
|
||||
#ifdef DEBUG_LOCK_MONITOR
|
||||
unsigned long long when;
|
||||
when = get_cycles();
|
||||
cerr << '\t' << when << ' '
|
||||
<< " UNLOCKED "
|
||||
<< &lock << " at "
|
||||
<< line << " in " << file << endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool locked() { return _locked; }
|
||||
|
||||
private:
|
||||
NonBlockingRWLock& lock;
|
||||
bool _locked;
|
||||
#ifdef DEBUG_LOCK_MONITOR
|
||||
unsigned long line;
|
||||
const char * file;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
} /* namespace */
|
||||
|
||||
#endif /* __pbd_lockmonitor_h__*/
|
||||
|
Loading…
Reference in New Issue
Block a user