mirror of
https://github.com/Ardour/ardour.git
synced 2026-01-04 04:39:33 +01:00
handle deletion of UI objects between the time that a callback is queued with the UI event loop and the execution of the callback (intrusive, big)
git-svn-id: svn://localhost/ardour2/branches/3.0@6807 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
10c257039d
commit
14b0ca31bc
87 changed files with 468 additions and 349 deletions
|
|
@ -2076,9 +2076,7 @@ int
|
|||
AudioDiskstream::remove_channel_from (boost::shared_ptr<ChannelList> c, uint32_t how_many)
|
||||
{
|
||||
while (how_many-- && !c->empty()) {
|
||||
// FIXME: crash (thread safe with RCU?)
|
||||
// memory leak, when disabled.... :(
|
||||
//delete c->back();
|
||||
delete c->back();
|
||||
c->pop_back();
|
||||
interpolation.remove_channel_from ();
|
||||
}
|
||||
|
|
@ -2324,9 +2322,7 @@ AudioDiskstream::ChannelInfo::ChannelInfo (nframes_t bufsize, nframes_t speed_si
|
|||
|
||||
AudioDiskstream::ChannelInfo::~ChannelInfo ()
|
||||
{
|
||||
if (write_source) {
|
||||
write_source.reset ();
|
||||
}
|
||||
write_source.reset ();
|
||||
|
||||
delete [] speed_buffer;
|
||||
speed_buffer = 0;
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ AudioSource::peaks_ready (boost::function<void()> doThisWhenReady, Connection& c
|
|||
*/
|
||||
|
||||
if (!(ret = _peaks_built)) {
|
||||
PeaksReady.connect (connect_here_if_not, doThisWhenReady, event_loop);
|
||||
PeaksReady.connect (connect_here_if_not, MISSING_INVALIDATOR, doThisWhenReady, event_loop);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ RCConfiguration::save_state()
|
|||
const string rcfile = rcfile_path.to_string();
|
||||
|
||||
// this test seems bogus?
|
||||
if (rcfile.length()) {
|
||||
if (!rcfile.empty()) {
|
||||
XMLTree tree;
|
||||
tree.set_root (&get_state());
|
||||
if (!tree.write (rcfile.c_str())){
|
||||
|
|
|
|||
|
|
@ -191,7 +191,6 @@ Session::silent_process_routes (nframes_t nframes, bool& need_butler)
|
|||
void
|
||||
Session::get_diskstream_statistics ()
|
||||
{
|
||||
int dret;
|
||||
float pworst = 1.0f;
|
||||
float cworst = 1.0f;
|
||||
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ Session::process_rtop (SessionEvent* ev)
|
|||
ev->rt_slot ();
|
||||
|
||||
if (ev->event_loop) {
|
||||
ev->event_loop->call_slot (boost::bind (ev->rt_return, ev));
|
||||
ev->event_loop->call_slot (MISSING_INVALIDATOR, boost::bind (ev->rt_return, ev));
|
||||
} else {
|
||||
warning << string_compose ("programming error: %1", X_("Session RT event queued from thread without a UI - cleanup in RT thread!")) << endmsg;
|
||||
ev->rt_return (ev);
|
||||
|
|
|
|||
|
|
@ -369,6 +369,19 @@ UI::idle_add (int (*func)(void *), void *arg)
|
|||
|
||||
/* END abstract_ui interfaces */
|
||||
|
||||
PBD::EventLoop::InvalidationRecord*
|
||||
__invalidator (sigc::trackable& trackable, const char* file, int line)
|
||||
{
|
||||
PBD::EventLoop::InvalidationRecord* ir = new PBD::EventLoop::InvalidationRecord;
|
||||
|
||||
ir->file = file;
|
||||
ir->line = line;
|
||||
|
||||
trackable.add_destroy_notify_callback (ir, PBD::EventLoop::invalidate_request);
|
||||
|
||||
return ir;
|
||||
}
|
||||
|
||||
void
|
||||
UI::do_request (UIRequest* req)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -83,13 +83,13 @@ PopUp::remove ()
|
|||
gtk_idle_add (idle_delete, this);
|
||||
}
|
||||
}
|
||||
|
||||
#define ENSURE_GUI_THREAD(slot) \
|
||||
if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {\
|
||||
Gtkmm2ext::UI::instance()->call_slot ((slot));\
|
||||
Gtkmm2ext::UI::instance()->call_slot (MISSING_INVALIDATOR, (slot)); \
|
||||
return;\
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PopUp::touch ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
#include <iostream>
|
||||
#include "pbd/event_loop.h"
|
||||
#include "pbd/stacktrace.h"
|
||||
|
||||
using namespace PBD;
|
||||
using namespace std;
|
||||
|
||||
Glib::StaticPrivate<EventLoop> EventLoop::thread_event_loop;
|
||||
|
||||
|
|
@ -17,3 +20,29 @@ EventLoop::set_event_loop_for_thread (EventLoop* loop)
|
|||
thread_event_loop.set (loop, do_not_delete_the_loop_pointer);
|
||||
}
|
||||
|
||||
void*
|
||||
EventLoop::invalidate_request (void* data)
|
||||
{
|
||||
InvalidationRecord* ir = (InvalidationRecord*) data;
|
||||
|
||||
if (ir->event_loop) {
|
||||
Glib::Mutex::Lock lm (ir->event_loop->slot_invalidation_mutex());
|
||||
if (ir->request) {
|
||||
cerr << "Object deleted had outstanding event loop request, IR created @ "
|
||||
<< ir->file << ':' << ir->line
|
||||
<< endl;
|
||||
ir->request->valid = false;
|
||||
ir->request->invalidation = 0;
|
||||
} else {
|
||||
cerr << "No queued request associated with object deletion from "
|
||||
<< ir->file << ':' << ir->line
|
||||
<< endl;
|
||||
|
||||
}
|
||||
|
||||
delete ir;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,15 +8,22 @@ using namespace PBD;
|
|||
|
||||
LocaleGuard::LocaleGuard (const char* str)
|
||||
{
|
||||
old = strdup (setlocale (LC_NUMERIC, NULL));
|
||||
if (strcmp (old, str)) {
|
||||
setlocale (LC_NUMERIC, str);
|
||||
}
|
||||
old = setlocale (LC_NUMERIC, NULL);
|
||||
|
||||
if (old) {
|
||||
old = strdup (old);
|
||||
if (strcmp (old, str)) {
|
||||
setlocale (LC_NUMERIC, str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LocaleGuard::~LocaleGuard ()
|
||||
{
|
||||
setlocale (LC_NUMERIC, old);
|
||||
free ((char*)old);
|
||||
|
||||
if (old) {
|
||||
free ((char*)old);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,11 +61,13 @@ AbstractUI<RequestObject>::get_request (RequestType rt)
|
|||
}
|
||||
|
||||
vec.buf[0]->type = rt;
|
||||
vec.buf[0]->valid = true;
|
||||
return vec.buf[0];
|
||||
}
|
||||
|
||||
RequestObject* req = new RequestObject;
|
||||
req->type = rt;
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
|
|
@ -98,10 +100,15 @@ AbstractUI<RequestObject>::handle_ui_requests ()
|
|||
if (vec.len[0] == 0) {
|
||||
break;
|
||||
} else {
|
||||
request_buffer_map_lock.unlock ();
|
||||
do_request (vec.buf[0]);
|
||||
request_buffer_map_lock.lock ();
|
||||
i->second->increment_read_ptr (1);
|
||||
if (vec.buf[0]->valid) {
|
||||
request_buffer_map_lock.unlock ();
|
||||
do_request (vec.buf[0]);
|
||||
request_buffer_map_lock.lock ();
|
||||
if (vec.buf[0]->invalidation) {
|
||||
vec.buf[0]->invalidation->request = 0;
|
||||
}
|
||||
i->second->increment_read_ptr (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -115,6 +122,30 @@ AbstractUI<RequestObject>::handle_ui_requests ()
|
|||
while (!request_list.empty()) {
|
||||
RequestObject* req = request_list.front ();
|
||||
request_list.pop_front ();
|
||||
|
||||
/* We need to use this lock, because its the one
|
||||
returned by slot_invalidation_mutex() and protects
|
||||
against request invalidation.
|
||||
*/
|
||||
|
||||
request_buffer_map_lock.lock ();
|
||||
if (!req->valid) {
|
||||
delete req;
|
||||
request_buffer_map_lock.unlock ();
|
||||
continue;
|
||||
}
|
||||
|
||||
/* we're about to execute this request, so its
|
||||
too late for any invalidation. mark
|
||||
the request as "done" before we start.
|
||||
*/
|
||||
|
||||
if (req->invalidation) {
|
||||
req->invalidation->request = 0;
|
||||
}
|
||||
|
||||
request_buffer_map_lock.unlock ();
|
||||
|
||||
lm.release ();
|
||||
|
||||
do_request (req);
|
||||
|
|
@ -152,14 +183,9 @@ AbstractUI<RequestObject>::send_request (RequestObject *req)
|
|||
}
|
||||
|
||||
template<typename RequestObject> void
|
||||
AbstractUI<RequestObject>::call_slot (const boost::function<void()>& f)
|
||||
AbstractUI<RequestObject>::call_slot (InvalidationRecord* invalidation, const boost::function<void()>& f)
|
||||
{
|
||||
if (caller_is_self()) {
|
||||
#ifndef NDEBUG
|
||||
if (getenv ("DEBUG_THREADED_SIGNALS")) {
|
||||
std::cerr << "functor called in correct thread for " << name() << " , execute ...\n";
|
||||
}
|
||||
#endif
|
||||
f ();
|
||||
return;
|
||||
}
|
||||
|
|
@ -171,11 +197,13 @@ AbstractUI<RequestObject>::call_slot (const boost::function<void()>& f)
|
|||
}
|
||||
|
||||
req->the_slot = f;
|
||||
#ifndef NDEBUG
|
||||
if (getenv ("DEBUG_THREADED_SIGNALS")) {
|
||||
std::cerr << "functor called in wrong thread for " << name() << " (from " << pthread_name() << ") send request ...\n";
|
||||
}
|
||||
#endif
|
||||
req->invalidation = invalidation;
|
||||
|
||||
if (invalidation) {
|
||||
invalidation->request = req;
|
||||
invalidation->event_loop = this;
|
||||
}
|
||||
|
||||
send_request (req);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ class AbstractUI : public BaseUI
|
|||
virtual ~AbstractUI() {}
|
||||
|
||||
void register_thread (std::string, pthread_t, std::string, uint32_t num_requests);
|
||||
void call_slot (const boost::function<void()>&);
|
||||
void call_slot (EventLoop::InvalidationRecord*, const boost::function<void()>&);
|
||||
Glib::Mutex& slot_invalidation_mutex() { return request_buffer_map_lock; }
|
||||
|
||||
protected:
|
||||
typedef RingBufferNPT<RequestObject> RequestBuffer;
|
||||
|
|
|
|||
|
|
@ -48,15 +48,6 @@ class BaseUI : virtual public sigc::trackable, public PBD::EventLoop
|
|||
|
||||
bool ok() const { return _ok; }
|
||||
|
||||
enum RequestType {
|
||||
range_guarantee = ~0
|
||||
};
|
||||
|
||||
struct BaseRequestObject {
|
||||
RequestType type;
|
||||
boost::function<void()> the_slot;
|
||||
};
|
||||
|
||||
static RequestType new_request_type();
|
||||
static RequestType CallSlot;
|
||||
static RequestType Quit;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,34 @@ class EventLoop
|
|||
EventLoop() {}
|
||||
virtual ~EventLoop() {}
|
||||
|
||||
virtual void call_slot (const boost::function<void()>&) = 0;
|
||||
enum RequestType {
|
||||
range_guarantee = ~0
|
||||
};
|
||||
|
||||
struct BaseRequestObject;
|
||||
|
||||
struct InvalidationRecord {
|
||||
BaseRequestObject* request;
|
||||
PBD::EventLoop* event_loop;
|
||||
const char* file;
|
||||
int line;
|
||||
|
||||
InvalidationRecord() : request (0), event_loop (0) {}
|
||||
};
|
||||
|
||||
static void* invalidate_request (void* data);
|
||||
|
||||
struct BaseRequestObject {
|
||||
RequestType type;
|
||||
bool valid;
|
||||
InvalidationRecord* invalidation;
|
||||
boost::function<void()> the_slot;
|
||||
|
||||
BaseRequestObject() : valid (true), invalidation (0) {}
|
||||
};
|
||||
|
||||
virtual void call_slot (InvalidationRecord*, const boost::function<void()>&) = 0;
|
||||
virtual Glib::Mutex& slot_invalidation_mutex() = 0;
|
||||
|
||||
static EventLoop* get_event_loop_for_thread();
|
||||
static void set_event_loop_for_thread (EventLoop* ui);
|
||||
|
|
@ -45,4 +72,6 @@ class EventLoop
|
|||
|
||||
}
|
||||
|
||||
#define MISSING_INVALIDATOR 0 // used to mark places where we fail to provide an invalidator
|
||||
|
||||
#endif /* __pbd_event_loop_h__ */
|
||||
|
|
|
|||
|
|
@ -88,15 +88,17 @@ public:
|
|||
}
|
||||
|
||||
void connect (ScopedConnectionList& clist,
|
||||
PBD::EventLoop::InvalidationRecord* ir,
|
||||
const typename SignalType::slot_function_type& slot,
|
||||
PBD::EventLoop* event_loop) {
|
||||
clist.add_connection (_signal.connect (boost::bind (&EventLoop::call_slot, event_loop, slot)));
|
||||
clist.add_connection (_signal.connect (boost::bind (&EventLoop::call_slot, event_loop, ir, slot)));
|
||||
}
|
||||
|
||||
void connect (Connection& c,
|
||||
PBD::EventLoop::InvalidationRecord* ir,
|
||||
const typename SignalType::slot_function_type& slot,
|
||||
PBD::EventLoop* event_loop) {
|
||||
c = _signal.connect (boost::bind (&EventLoop::call_slot, event_loop, slot));
|
||||
c = _signal.connect (boost::bind (&EventLoop::call_slot, event_loop, ir, slot));
|
||||
}
|
||||
|
||||
typename SignalType::result_type operator()() {
|
||||
|
|
@ -125,20 +127,22 @@ public:
|
|||
c = _signal.connect (slot);
|
||||
}
|
||||
|
||||
static void compositor (typename boost::function<void(A)> f, EventLoop* event_loop, A arg) {
|
||||
event_loop->call_slot (boost::bind (f, arg));
|
||||
static void compositor (typename boost::function<void(A)> f, EventLoop* event_loop, EventLoop::InvalidationRecord* ir, A arg) {
|
||||
event_loop->call_slot (ir, boost::bind (f, arg));
|
||||
}
|
||||
|
||||
void connect (ScopedConnectionList& clist,
|
||||
PBD::EventLoop::InvalidationRecord* ir,
|
||||
const typename SignalType::slot_function_type& slot,
|
||||
PBD::EventLoop* event_loop) {
|
||||
clist.add_connection (_signal.connect (boost::bind (&compositor, slot, event_loop, _1)));
|
||||
clist.add_connection (_signal.connect (boost::bind (&compositor, slot, event_loop, ir, _1)));
|
||||
}
|
||||
|
||||
void connect (Connection& c,
|
||||
PBD::EventLoop::InvalidationRecord* ir,
|
||||
const typename SignalType::slot_function_type& slot,
|
||||
PBD::EventLoop* event_loop) {
|
||||
c = _signal.connect (boost::bind (&compositor, slot, event_loop, _1));
|
||||
c = _signal.connect (boost::bind (&compositor, slot, event_loop, ir, _1));
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -168,20 +172,24 @@ public:
|
|||
c = _signal.connect (slot);
|
||||
}
|
||||
|
||||
static void compositor (typename boost::function<void(A1,A2)> f, PBD::EventLoop* event_loop, A1 arg1, A2 arg2) {
|
||||
event_loop->call_slot (boost::bind (f, arg1, arg2));
|
||||
static void compositor (typename boost::function<void(A1,A2)> f, PBD::EventLoop* event_loop,
|
||||
EventLoop::InvalidationRecord* ir,
|
||||
A1 arg1, A2 arg2) {
|
||||
event_loop->call_slot (ir, boost::bind (f, arg1, arg2));
|
||||
}
|
||||
|
||||
void connect (ScopedConnectionList& clist,
|
||||
PBD::EventLoop::InvalidationRecord* ir,
|
||||
const typename SignalType::slot_function_type& slot,
|
||||
PBD::EventLoop* event_loop) {
|
||||
clist.add_connection (_signal.connect (boost::bind (&compositor, slot, event_loop, _1, _2)));
|
||||
clist.add_connection (_signal.connect (boost::bind (&compositor, slot, event_loop, ir, _1, _2)));
|
||||
}
|
||||
|
||||
void connect (Connection& c,
|
||||
PBD::EventLoop::InvalidationRecord* ir,
|
||||
const typename SignalType::slot_function_type& slot,
|
||||
PBD::EventLoop* event_loop) {
|
||||
c = _signal.connect (boost::bind (&compositor, slot, event_loop, _1, _2));
|
||||
c = _signal.connect (boost::bind (&compositor, slot, event_loop, ir, _1, _2));
|
||||
}
|
||||
|
||||
typename SignalType::result_type operator()(A1 arg1, A2 arg2) {
|
||||
|
|
@ -210,20 +218,24 @@ public:
|
|||
c = _signal.connect (slot);
|
||||
}
|
||||
|
||||
static void compositor (typename boost::function<void(A1,A2,A3)> f, PBD::EventLoop* event_loop, A1 arg1, A2 arg2, A3 arg3) {
|
||||
event_loop->call_slot (boost::bind (f, arg1, arg2, arg3));
|
||||
static void compositor (typename boost::function<void(A1,A2,A3)> f, PBD::EventLoop* event_loop,
|
||||
EventLoop::InvalidationRecord* ir,
|
||||
A1 arg1, A2 arg2, A3 arg3) {
|
||||
event_loop->call_slot (ir, boost::bind (f, arg1, arg2, arg3));
|
||||
}
|
||||
|
||||
void connect (ScopedConnectionList& clist,
|
||||
PBD::EventLoop::InvalidationRecord* ir,
|
||||
const typename SignalType::slot_function_type& slot,
|
||||
PBD::EventLoop* event_loop) {
|
||||
clist.add_connection (_signal.connect (boost::bind (&compositor, slot, event_loop, _1, _2, _3)));
|
||||
clist.add_connection (_signal.connect (boost::bind (&compositor, slot, event_loop, ir, _1, _2, _3)));
|
||||
}
|
||||
|
||||
void connect (Connection& c,
|
||||
PBD::EventLoop::InvalidationRecord* ir,
|
||||
const typename SignalType::slot_function_type& slot,
|
||||
PBD::EventLoop* event_loop) {
|
||||
c = _signal.connect (_signal.connect (boost::bind (&compositor, slot, event_loop, _1, _2, _3)));
|
||||
c = _signal.connect (_signal.connect (boost::bind (&compositor, slot, event_loop, ir, _1, _2, _3)));
|
||||
}
|
||||
|
||||
typename SignalType::result_type operator()(A1 arg1, A2 arg2, A3 arg3) {
|
||||
|
|
@ -252,20 +264,24 @@ public:
|
|||
c = _signal.connect (slot);
|
||||
}
|
||||
|
||||
static void compositor (typename boost::function<void(A1,A2,A3)> f, PBD::EventLoop* event_loop, A1 arg1, A2 arg2, A3 arg3, A4 arg4) {
|
||||
event_loop->call_slot (boost::bind (f, arg1, arg2, arg3, arg4));
|
||||
static void compositor (typename boost::function<void(A1,A2,A3)> f, PBD::EventLoop* event_loop,
|
||||
EventLoop::InvalidationRecord* ir,
|
||||
A1 arg1, A2 arg2, A3 arg3, A4 arg4) {
|
||||
event_loop->call_slot (ir, boost::bind (f, arg1, arg2, arg3, arg4));
|
||||
}
|
||||
|
||||
void connect (ScopedConnectionList& clist,
|
||||
PBD::EventLoop::InvalidationRecord* ir,
|
||||
const typename SignalType::slot_function_type& slot,
|
||||
PBD::EventLoop* event_loop) {
|
||||
clist.add_connection (_signal.connect (boost::bind (&compositor, slot, event_loop, _1, _2, _3, _4)));
|
||||
clist.add_connection (_signal.connect (boost::bind (&compositor, slot, event_loop, ir, _1, _2, _3, _4)));
|
||||
}
|
||||
|
||||
void connect (Connection& c,
|
||||
PBD::EventLoop::InvalidationRecord* ir,
|
||||
const typename SignalType::slot_function_type& slot,
|
||||
PBD::EventLoop* event_loop) {
|
||||
c = _signal.connect (_signal.connect (boost::bind (&compositor, slot, event_loop, _1, _2, _3, _4)));
|
||||
c = _signal.connect (_signal.connect (boost::bind (&compositor, slot, event_loop, ir, _1, _2, _3, _4)));
|
||||
}
|
||||
|
||||
typename SignalType::result_type operator()(A1 arg1, A2 arg2, A3 arg3, A4 arg4) {
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ ControlProtocol::ControlProtocol (Session& s, string str, EventLoop* evloop)
|
|||
|
||||
_active = false;
|
||||
|
||||
session->RouteAdded.connect (*this, boost::protect (boost::bind (&ControlProtocol::add_strip, this, _1)), _event_loop);
|
||||
session->RouteAdded.connect (*this, MISSING_INVALIDATOR, boost::protect (boost::bind (&ControlProtocol::add_strip, this, _1)), _event_loop);
|
||||
}
|
||||
|
||||
ControlProtocol::~ControlProtocol ()
|
||||
|
|
|
|||
|
|
@ -85,8 +85,8 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
|
|||
Controllable::CreateBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::create_binding, this, _1, _2, _3));
|
||||
Controllable::DeleteBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::delete_binding, this, _1));
|
||||
|
||||
Session::SendFeedback.connect (*this, boost::bind (&GenericMidiControlProtocol::send_feedback, this), midi_ui_context());;
|
||||
Route::RemoteControlIDChange.connect (*this, boost::bind (&GenericMidiControlProtocol::reset_controllables, this), midi_ui_context());
|
||||
Session::SendFeedback.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::send_feedback, this), midi_ui_context());;
|
||||
Route::RemoteControlIDChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::reset_controllables, this), midi_ui_context());
|
||||
|
||||
reload_maps ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -540,23 +540,23 @@ void
|
|||
MackieControlProtocol::connect_session_signals()
|
||||
{
|
||||
// receive routes added
|
||||
session->RouteAdded.connect(session_connections, ui_bind (&MackieControlProtocol::notify_route_added, this, _1), midi_ui_context());
|
||||
session->RouteAdded.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_route_added, this, _1), midi_ui_context());
|
||||
// receive record state toggled
|
||||
session->RecordStateChanged.connect(session_connections, ui_bind (&MackieControlProtocol::notify_record_state_changed, this), midi_ui_context());
|
||||
session->RecordStateChanged.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_record_state_changed, this), midi_ui_context());
|
||||
// receive transport state changed
|
||||
session->TransportStateChange.connect(session_connections, ui_bind (&MackieControlProtocol::notify_transport_state_changed, this), midi_ui_context());
|
||||
session->TransportStateChange.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_transport_state_changed, this), midi_ui_context());
|
||||
// receive punch-in and punch-out
|
||||
Config->ParameterChanged.connect(session_connections, ui_bind (&MackieControlProtocol::notify_parameter_changed, this, _1), midi_ui_context());
|
||||
session->config.ParameterChanged.connect (session_connections, ui_bind (&MackieControlProtocol::notify_parameter_changed, this, _1), midi_ui_context());
|
||||
Config->ParameterChanged.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_parameter_changed, this, _1), midi_ui_context());
|
||||
session->config.ParameterChanged.connect (session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_parameter_changed, this, _1), midi_ui_context());
|
||||
// receive rude solo changed
|
||||
session->SoloActive.connect(session_connections, ui_bind (&MackieControlProtocol::notify_solo_active_changed, this, _1), midi_ui_context());
|
||||
session->SoloActive.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_solo_active_changed, this, _1), midi_ui_context());
|
||||
|
||||
// make sure remote id changed signals reach here
|
||||
// see also notify_route_added
|
||||
Sorted sorted = get_sorted_routes();
|
||||
|
||||
for (Sorted::iterator it = sorted.begin(); it != sorted.end(); ++it) {
|
||||
(*it)->RemoteControlIDChanged.connect (route_connections, ui_bind(&MackieControlProtocol::notify_remote_id_changed, this), midi_ui_context());
|
||||
(*it)->RemoteControlIDChanged.connect (route_connections, MISSING_INVALIDATOR, ui_bind(&MackieControlProtocol::notify_remote_id_changed, this), midi_ui_context());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1417,7 +1417,7 @@ MackieControlProtocol::notify_route_added (ARDOUR::RouteList & rl)
|
|||
typedef ARDOUR::RouteList ARS;
|
||||
|
||||
for (ARS::iterator it = rl.begin(); it != rl.end(); ++it) {
|
||||
(*it)->RemoteControlIDChanged.connect (route_connections, ui_bind (&MackieControlProtocol::notify_remote_id_changed, this), midi_ui_context());
|
||||
(*it)->RemoteControlIDChanged.connect (route_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_remote_id_changed, this), midi_ui_context());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,35 +37,35 @@ using namespace std;
|
|||
void RouteSignal::connect()
|
||||
{
|
||||
if (_strip.has_solo()) {
|
||||
_route->solo_control()->Changed.connect(connections, ui_bind (&MackieControlProtocol::notify_solo_changed, &_mcp, this), midi_ui_context());
|
||||
_route->solo_control()->Changed.connect(connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_solo_changed, &_mcp, this), midi_ui_context());
|
||||
}
|
||||
|
||||
if (_strip.has_mute()) {
|
||||
_route->mute_control()->Changed.connect(connections, ui_bind (&MackieControlProtocol::notify_mute_changed, &_mcp, this), midi_ui_context());
|
||||
_route->mute_control()->Changed.connect(connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_mute_changed, &_mcp, this), midi_ui_context());
|
||||
}
|
||||
|
||||
if (_strip.has_gain()) {
|
||||
_route->gain_control()->Changed.connect(connections, ui_bind (&MackieControlProtocol::notify_gain_changed, &_mcp, this, false), midi_ui_context());
|
||||
_route->gain_control()->Changed.connect(connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_gain_changed, &_mcp, this, false), midi_ui_context());
|
||||
}
|
||||
|
||||
_route->PropertyChanged.connect (connections, ui_bind (&MackieControlProtocol::notify_property_changed, &_mcp, _1, this), midi_ui_context());
|
||||
_route->PropertyChanged.connect (connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_property_changed, &_mcp, _1, this), midi_ui_context());
|
||||
|
||||
if (_route->panner()) {
|
||||
_route->panner()->Changed.connect(connections, ui_bind (&MackieControlProtocol::notify_panner_changed, &_mcp, this, false), midi_ui_context());
|
||||
_route->panner()->Changed.connect(connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_panner_changed, &_mcp, this, false), midi_ui_context());
|
||||
|
||||
for ( unsigned int i = 0; i < _route->panner()->npanners(); ++i ) {
|
||||
_route->panner()->streampanner(i).Changed.connect (connections, ui_bind (&MackieControlProtocol::notify_panner_changed, &_mcp, this, false), midi_ui_context());
|
||||
_route->panner()->streampanner(i).Changed.connect (connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_panner_changed, &_mcp, this, false), midi_ui_context());
|
||||
}
|
||||
}
|
||||
|
||||
boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<ARDOUR::Track>(_route);
|
||||
if (trk) {
|
||||
trk->rec_enable_control()->Changed .connect(connections, ui_bind (&MackieControlProtocol::notify_record_enable_changed, &_mcp, this), midi_ui_context());
|
||||
trk->rec_enable_control()->Changed .connect(connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_record_enable_changed, &_mcp, this), midi_ui_context());
|
||||
}
|
||||
|
||||
// TODO this works when a currently-banked route is made inactive, but not
|
||||
// when a route is activated which should be currently banked.
|
||||
_route->active_changed.connect (connections, ui_bind (&MackieControlProtocol::notify_active_changed, &_mcp, this), midi_ui_context());
|
||||
_route->active_changed.connect (connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_active_changed, &_mcp, this), midi_ui_context());
|
||||
|
||||
// TODO
|
||||
// SelectedChanged
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ OSC::OSC (Session& s, uint32_t port)
|
|||
|
||||
// "Application Hooks"
|
||||
session_loaded (s);
|
||||
session->Exported.connect (*this, ui_bind (&OSC::session_exported, this, _1, _2), this);
|
||||
session->Exported.connect (*this, MISSING_INVALIDATOR, ui_bind (&OSC::session_exported, this, _1, _2), this);
|
||||
}
|
||||
|
||||
OSC::~OSC()
|
||||
|
|
@ -101,7 +101,7 @@ OSC::do_request (OSCUIRequest* req)
|
|||
{
|
||||
if (req->type == CallSlot) {
|
||||
|
||||
call_slot (req->the_slot);
|
||||
call_slot (MISSING_INVALIDATOR, req->the_slot);
|
||||
|
||||
} else if (req->type == Quit) {
|
||||
|
||||
|
|
@ -586,7 +586,7 @@ OSC::listen_to_route (boost::shared_ptr<Route> route, lo_address addr)
|
|||
*/
|
||||
|
||||
if (!route_exists) {
|
||||
route->DropReferences.connect (*this, boost::bind (&OSC::drop_route, this, boost::weak_ptr<Route> (route)), this);
|
||||
route->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::drop_route, this, boost::weak_ptr<Route> (route)), this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ OSCControllable::OSCControllable (lo_address a, const std::string& p, boost::sha
|
|||
, addr (a)
|
||||
, path (p)
|
||||
{
|
||||
c->Changed.connect (changed_connection, boost::bind (&OSCControllable::send_change_message, this), OSC::instance());
|
||||
c->Changed.connect (changed_connection, MISSING_INVALIDATOR, boost::bind (&OSCControllable::send_change_message, this), OSC::instance());
|
||||
}
|
||||
|
||||
OSCControllable::~OSCControllable ()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue