restore rec-enable, solo & mute functionality; remove all Global*Command cruft; reimplement momentary solo&mute; refactor session RT event stuff to be even cleaner and finally compatible with everything-is-a-UI idea ; make all UIs derive from a primitive type that pprovides only void call_slot (sigc::slot<void>) as a way to execute arbitrary code in the UI thread
git-svn-id: svn://localhost/ardour2/branches/3.0@6338 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
b5ca5713fb
commit
90d6916ca3
|
@ -113,6 +113,16 @@ sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
|
|||
sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
|
||||
sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
|
||||
|
||||
void gui_rt_cleanup (SessionEvent* ev)
|
||||
{
|
||||
/* a little helper function that makes sure we delete queued SessionEvents in the correct thread */
|
||||
ENSURE_GUI_THREAD (bind (sigc::ptr_fun (&gui_rt_cleanup), ev));
|
||||
delete ev;
|
||||
}
|
||||
|
||||
/* wrap the above as a slot so that we can pass it to the session when queuing RT events */
|
||||
const sigc::slot<void,SessionEvent*> gui_rt_cleanup_slot (sigc::ptr_fun (&gui_rt_cleanup));
|
||||
|
||||
ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
|
||||
|
||||
: Gtkmm2ext::UI (X_("gui"), argcp, argvp),
|
||||
|
|
|
@ -170,7 +170,9 @@ EditorRoutes::on_tv_rec_enable_toggled (Glib::ustring const & path_string)
|
|||
AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
|
||||
|
||||
if (atv != 0 && atv->is_audio_track()){
|
||||
atv->reversibly_apply_track_boolean ("rec-enable change", &Track::set_record_enable, !atv->track()->record_enabled(), this);
|
||||
boost::shared_ptr<RouteList> rl (new RouteList);
|
||||
rl->push_back (atv->route());
|
||||
_session->set_record_enable (rl, !atv->track()->record_enabled(), Session::rt_cleanup);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,7 +186,9 @@ EditorRoutes::on_tv_mute_enable_toggled (Glib::ustring const & path_string)
|
|||
AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
|
||||
|
||||
if (atv != 0) {
|
||||
atv->reversibly_apply_route_boolean ("mute-enable change", &Route::set_mute, !atv->route()->muted(), this);
|
||||
boost::shared_ptr<RouteList> rl (new RouteList);
|
||||
rl->push_back (atv->route());
|
||||
_session->set_mute (rl, !atv->route()->muted(), Session::rt_cleanup);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,7 +202,9 @@ EditorRoutes::on_tv_solo_enable_toggled (Glib::ustring const & path_string)
|
|||
AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
|
||||
|
||||
if (atv != 0) {
|
||||
atv->reversibly_apply_route_boolean ("solo-enable change", &Route::set_solo, !atv->route()->soloed(), this);
|
||||
boost::shared_ptr<RouteList> rl (new RouteList);
|
||||
rl->push_back (atv->route());
|
||||
_session->set_solo (rl, !atv->route()->soloed(), Session::rt_cleanup);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -519,12 +519,7 @@ GainMeterBase::meter_press(GdkEventButton* ev)
|
|||
|
||||
/* Primary+Tertiary-click applies change to all routes */
|
||||
|
||||
_session.begin_reversible_command (_("meter point change"));
|
||||
Session::GlobalMeteringStateCommand *cmd = new Session::GlobalMeteringStateCommand (_session, this);
|
||||
_session.foreach_route (this, &GainMeterBase::set_meter_point, next_meter_point (_route->meter_point()));
|
||||
cmd->mark();
|
||||
_session.add_command (cmd);
|
||||
_session.commit_reversible_command ();
|
||||
|
||||
|
||||
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
|
||||
|
@ -534,12 +529,7 @@ GainMeterBase::meter_press(GdkEventButton* ev)
|
|||
*/
|
||||
|
||||
if (ev->button == 1) {
|
||||
_session.begin_reversible_command (_("meter point change"));
|
||||
Session::GlobalMeteringStateCommand *cmd = new Session::GlobalMeteringStateCommand (_session, this);
|
||||
set_mix_group_meter_point (*_route, next_meter_point (_route->meter_point()));
|
||||
cmd->mark();
|
||||
_session.add_command (cmd);
|
||||
_session.commit_reversible_command ();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
|
@ -103,7 +103,8 @@ RouteUI::init ()
|
|||
listen_mute_check = 0;
|
||||
main_mute_check = 0;
|
||||
ignore_toggle = false;
|
||||
wait_for_release = false;
|
||||
_solo_release = 0;
|
||||
_mute_release = 0;
|
||||
route_active_menu_item = 0;
|
||||
polarity_menu_item = 0;
|
||||
denormal_menu_item = 0;
|
||||
|
@ -229,12 +230,14 @@ RouteUI::set_route (boost::shared_ptr<Route> rp)
|
|||
}
|
||||
|
||||
bool
|
||||
RouteUI::mute_press(GdkEventButton* ev)
|
||||
RouteUI::mute_press (GdkEventButton* ev)
|
||||
{
|
||||
if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
multiple_mute_change = false;
|
||||
|
||||
if (!ignore_toggle) {
|
||||
|
||||
if (Keyboard::is_context_menu_event (ev)) {
|
||||
|
@ -251,51 +254,50 @@ RouteUI::mute_press(GdkEventButton* ev)
|
|||
// Primary-button2 click is the midi binding click
|
||||
// button2-click is "momentary"
|
||||
|
||||
if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier))) {
|
||||
wait_for_release = true;
|
||||
} else {
|
||||
if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_mute_release = new SoloMuteRelease (_route->muted ());
|
||||
}
|
||||
|
||||
if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
|
||||
|
||||
if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
|
||||
|
||||
#if 0
|
||||
/* Primary-Tertiary-click applies change to all routes */
|
||||
if (_mute_release) {
|
||||
_mute_release->routes = _session.get_routes ();
|
||||
}
|
||||
|
||||
_session.begin_reversible_command (_("mute change"));
|
||||
Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand(_session, this);
|
||||
_session.set_mute (!_route->muted());
|
||||
cmd->mark();
|
||||
_session.add_command(cmd);
|
||||
_session.commit_reversible_command ();
|
||||
multiple_mute_change = true;
|
||||
#endif
|
||||
_session.set_mute (_session.get_routes(), !_route->muted());
|
||||
|
||||
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
|
||||
|
||||
#if 0
|
||||
/* Primary-button1 applies change to the mix group.
|
||||
/* Primary-button1 applies change to the mix group even if it is not active
|
||||
NOTE: Primary-button2 is MIDI learn.
|
||||
*/
|
||||
|
||||
if (ev->button == 1) {
|
||||
set_route_group_mute (_route, !_route->muted());
|
||||
if (ev->button == 1 && _route->route_group()) {
|
||||
if (_mute_release) {
|
||||
_mute_release->routes = _session.get_routes ();
|
||||
}
|
||||
|
||||
_session.set_mute (_session.get_routes(), !_route->muted(), Session::rt_cleanup, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
} else {
|
||||
|
||||
#if 0
|
||||
/* plain click applies change to this route */
|
||||
if (wait_for_release) {
|
||||
_route->set_mute (!_route->muted(), this);
|
||||
} else {
|
||||
reversibly_apply_route_boolean ("mute change", &Route::set_mute, !_route->muted(), this);
|
||||
|
||||
boost::shared_ptr<RouteList> rl (new RouteList);
|
||||
rl->push_back (_route);
|
||||
|
||||
if (_mute_release) {
|
||||
_mute_release->routes = rl;
|
||||
}
|
||||
#endif
|
||||
|
||||
_session.set_mute (rl, !_route->muted());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -306,36 +308,19 @@ RouteUI::mute_press(GdkEventButton* ev)
|
|||
}
|
||||
|
||||
bool
|
||||
RouteUI::mute_release(GdkEventButton*)
|
||||
RouteUI::mute_release (GdkEventButton*)
|
||||
{
|
||||
if (!ignore_toggle) {
|
||||
if (wait_for_release){
|
||||
wait_for_release = false;
|
||||
if (multiple_mute_change) {
|
||||
multiple_mute_change = false;
|
||||
// undo the last op
|
||||
// because the press was the last undoable thing we did
|
||||
_session.undo (1U);
|
||||
} else {
|
||||
_route->set_mute (!_route->muted(), this);
|
||||
}
|
||||
if (_mute_release){
|
||||
_session.set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, true);
|
||||
delete _mute_release;
|
||||
_mute_release = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
RouteUI::post_solo_cleanup (SessionEvent* ev, bool was_not_latched)
|
||||
{
|
||||
ENSURE_GUI_THREAD (bind (mem_fun (*this, &RouteUI::post_solo_cleanup), ev, was_not_latched));
|
||||
|
||||
delete ev;
|
||||
|
||||
if (was_not_latched) {
|
||||
Config->set_solo_latched (false);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RouteUI::solo_press(GdkEventButton* ev)
|
||||
{
|
||||
|
@ -344,106 +329,115 @@ RouteUI::solo_press(GdkEventButton* ev)
|
|||
if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
multiple_solo_change = false;
|
||||
|
||||
if (Config->get_solo_control_is_listen_control()) {
|
||||
|
||||
_route->set_listen (!_route->listening(), this);
|
||||
|
||||
} else {
|
||||
|
||||
multiple_solo_change = false;
|
||||
if (!ignore_toggle) {
|
||||
|
||||
if (Keyboard::is_context_menu_event (ev)) {
|
||||
|
||||
if (solo_menu == 0) {
|
||||
build_solo_menu ();
|
||||
if (!ignore_toggle) {
|
||||
|
||||
if (Keyboard::is_context_menu_event (ev)) {
|
||||
|
||||
if (solo_menu == 0) {
|
||||
build_solo_menu ();
|
||||
}
|
||||
|
||||
solo_menu->popup (1, ev->time);
|
||||
|
||||
} else {
|
||||
|
||||
if (Keyboard::is_button2_event (ev)) {
|
||||
|
||||
// Primary-button2 click is the midi binding click
|
||||
// button2-click is "momentary"
|
||||
|
||||
if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
solo_menu->popup (1, ev->time);
|
||||
_solo_release = new SoloMuteRelease (_route->soloed());
|
||||
}
|
||||
|
||||
if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
|
||||
|
||||
if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
|
||||
|
||||
/* Primary-Tertiary-click applies change to all routes */
|
||||
|
||||
} else {
|
||||
|
||||
if (Keyboard::is_button2_event (ev)) {
|
||||
|
||||
// Primary-button2 click is the midi binding click
|
||||
// button2-click is "momentary"
|
||||
|
||||
if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier))) {
|
||||
wait_for_release = true;
|
||||
} else {
|
||||
return false;
|
||||
if (_solo_release) {
|
||||
_solo_release->routes = _session.get_routes ();
|
||||
}
|
||||
}
|
||||
|
||||
if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
|
||||
|
||||
if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
|
||||
|
||||
/* Primary-Tertiary-click applies change to all routes */
|
||||
bool was_not_latched = false;
|
||||
|
||||
if (!Config->get_solo_latched ()) {
|
||||
was_not_latched = true;
|
||||
/*
|
||||
XXX it makes no sense to solo all tracks if we're
|
||||
not in latched mode, but doing nothing feels like a bug,
|
||||
so do it anyway
|
||||
*/
|
||||
Config->set_solo_latched (true);
|
||||
}
|
||||
|
||||
SessionEvent* ev = new SessionEvent (SessionEvent::RealTimeOperation, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
|
||||
ev->rt_slot = bind (sigc::mem_fun (_session, &Session::set_solo), _session.get_routes(), !_route->soloed());
|
||||
ev->rt_return = bind (sigc::mem_fun (*this, &RouteUI::post_solo_cleanup), was_not_latched);
|
||||
|
||||
_session.queue_event (ev);
|
||||
|
||||
} else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
|
||||
|
||||
// Primary-Secondary-click: exclusively solo this track, not a toggle */
|
||||
|
||||
//boost::shared_ptr<RouteList> rl (new RouteList);
|
||||
//rl->push_back (route());
|
||||
|
||||
//SessionEvent* ev = new SessionEvent (SessionEvent::RealTimeOperation, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
|
||||
// ev->rt_slot = bind (sigc::mem_fun (_session, &Session::set_just_one_solo), rl, true);
|
||||
//ev->rt_return = sigc::mem_fun (*this, &RouteUI::post_rtop_cleanup);
|
||||
|
||||
//_session.queue_event (ev);
|
||||
|
||||
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
|
||||
|
||||
// shift-click: toggle solo isolated status
|
||||
|
||||
_route->set_solo_isolated (!_route->solo_isolated(), this);
|
||||
wait_for_release = false;
|
||||
|
||||
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
|
||||
|
||||
#if 0
|
||||
/* Primary-button1: solo mix group.
|
||||
NOTE: Primary-button2 is MIDI learn.
|
||||
*/
|
||||
|
||||
if (ev->button == 1) {
|
||||
queue_route_group_op (RouteGroup::Solo, &Session::set_all_solo, !_route->soloed());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
if (Config->get_solo_control_is_listen_control()) {
|
||||
_session.set_listen (_session.get_routes(), !_route->listening(), Session::rt_cleanup, true);
|
||||
} else {
|
||||
_session.set_solo (_session.get_routes(), !_route->soloed(), Session::rt_cleanup, true);
|
||||
}
|
||||
|
||||
} else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
|
||||
|
||||
// Primary-Secondary-click: exclusively solo this track
|
||||
|
||||
/* click: solo this route */
|
||||
if (_solo_release) {
|
||||
_solo_release->exclusive = true;
|
||||
|
||||
boost::shared_ptr<RouteList> rl (new RouteList);
|
||||
rl->push_back (route());
|
||||
|
||||
SessionEvent* ev = new SessionEvent (SessionEvent::RealTimeOperation, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
|
||||
ev->rt_slot = bind (sigc::mem_fun (_session, &Session::set_solo), rl, !rec_enable_button->get_active());
|
||||
ev->rt_return = sigc::mem_fun (*this, &RouteUI::post_rtop_cleanup);
|
||||
|
||||
_session.queue_event (ev);
|
||||
boost::shared_ptr<RouteList> routes = _session.get_routes();
|
||||
|
||||
for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
|
||||
if ((*i)->soloed ()) {
|
||||
_solo_release->routes_on->push_back (*i);
|
||||
} else {
|
||||
_solo_release->routes_off->push_back (*i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Config->get_solo_control_is_listen_control()) {
|
||||
/* ??? we need a just_one_listen() method */
|
||||
} else {
|
||||
_session.set_just_one_solo (_route, true);
|
||||
}
|
||||
|
||||
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
|
||||
|
||||
// shift-click: toggle solo isolated status
|
||||
|
||||
_route->set_solo_isolated (!_route->solo_isolated(), this);
|
||||
delete _solo_release;
|
||||
_solo_release = 0;
|
||||
|
||||
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
|
||||
|
||||
/* Primary-button1: solo mix group.
|
||||
NOTE: Primary-button2 is MIDI learn.
|
||||
*/
|
||||
|
||||
if (ev->button == 1 && _route->route_group()) {
|
||||
|
||||
if (_solo_release) {
|
||||
_solo_release->routes = _route->route_group()->route_list();
|
||||
}
|
||||
|
||||
if (Config->get_solo_control_is_listen_control()) {
|
||||
_session.set_listen (_route->route_group()->route_list(), !_route->listening(), Session::rt_cleanup, true);
|
||||
} else {
|
||||
_session.set_solo (_route->route_group()->route_list(), !_route->soloed(), Session::rt_cleanup, true);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* click: solo this route */
|
||||
|
||||
boost::shared_ptr<RouteList> rl (new RouteList);
|
||||
rl->push_back (route());
|
||||
|
||||
if (_solo_release) {
|
||||
_solo_release->routes = rl;
|
||||
}
|
||||
|
||||
if (Config->get_solo_control_is_listen_control()) {
|
||||
_session.set_listen (rl, !_route->listening());
|
||||
} else {
|
||||
_session.set_solo (rl, !_route->soloed());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -454,73 +448,26 @@ RouteUI::solo_press(GdkEventButton* ev)
|
|||
}
|
||||
|
||||
bool
|
||||
RouteUI::solo_release(GdkEventButton*)
|
||||
RouteUI::solo_release (GdkEventButton*)
|
||||
{
|
||||
if (!ignore_toggle) {
|
||||
if (wait_for_release) {
|
||||
wait_for_release = false;
|
||||
if (multiple_solo_change) {
|
||||
multiple_solo_change = false;
|
||||
// undo the last op
|
||||
// because the press was the last undoable thing we did
|
||||
_session.undo (1U);
|
||||
|
||||
if (_solo_release) {
|
||||
|
||||
if (_solo_release->exclusive) {
|
||||
|
||||
} else {
|
||||
// we don't use "undo the last op"
|
||||
// here because its expensive for the GUI
|
||||
_route->set_solo (!_route->soloed(), this);
|
||||
_session.set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
|
||||
}
|
||||
|
||||
delete _solo_release;
|
||||
_solo_release = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
RouteUI::post_rtop_cleanup (SessionEvent* ev)
|
||||
{
|
||||
ENSURE_GUI_THREAD (bind (mem_fun (*this, &RouteUI::post_rtop_cleanup), ev));
|
||||
delete ev;
|
||||
}
|
||||
|
||||
void
|
||||
RouteUI::post_group_rtop_cleanup (SessionEvent* ev, RouteGroup* rg, RouteGroup::Property prop)
|
||||
{
|
||||
ENSURE_GUI_THREAD (bind (mem_fun (*this, &RouteUI::post_group_rtop_cleanup), ev, rg, prop));
|
||||
delete ev;
|
||||
rg->set_property (prop, false);
|
||||
}
|
||||
|
||||
void
|
||||
RouteUI::queue_route_group_op (RouteGroup::Property prop, void (Session::*session_method)(boost::shared_ptr<RouteList>, bool), bool yn)
|
||||
{
|
||||
RouteGroup* rg = _route->route_group();
|
||||
bool prop_was_active;
|
||||
|
||||
if (rg) {
|
||||
prop_was_active = rg->active_property (prop);
|
||||
rg->set_property (prop, true);
|
||||
} else {
|
||||
prop_was_active = false;
|
||||
}
|
||||
|
||||
/* we will queue the op for just this route, but because its route group now has the relevant property marked active,
|
||||
the operation will apply to the whole group (if there is a group)
|
||||
*/
|
||||
|
||||
boost::shared_ptr<RouteList> rl (new RouteList);
|
||||
rl->push_back (route());
|
||||
|
||||
SessionEvent* ev = new SessionEvent (SessionEvent::RealTimeOperation, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
|
||||
ev->rt_slot = bind (sigc::mem_fun (_session, session_method), rl, yn);
|
||||
if (rg && !prop_was_active) {
|
||||
ev->rt_return = bind (sigc::mem_fun (*this, &RouteUI::post_group_rtop_cleanup), rg, prop);
|
||||
} else {
|
||||
ev->rt_return = sigc::mem_fun (*this, &RouteUI::post_rtop_cleanup);
|
||||
}
|
||||
|
||||
_session.queue_event (ev);
|
||||
}
|
||||
|
||||
bool
|
||||
RouteUI::rec_enable_press(GdkEventButton* ev)
|
||||
{
|
||||
|
@ -543,21 +490,16 @@ RouteUI::rec_enable_press(GdkEventButton* ev)
|
|||
|
||||
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
|
||||
|
||||
#if 0
|
||||
_session.set_record_enable (_session.get_route(), !rec_enable_button->get_active(), sigc::mem_fun (*this, &RouteUI::post_rtop_cleanup));
|
||||
#endif
|
||||
_session.set_record_enable (_session.get_routes(), !rec_enable_button->get_active());
|
||||
|
||||
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
|
||||
|
||||
/* Primary-button1 applies change to the route group (even if it is not active)
|
||||
NOTE: Primary-button2 is MIDI learn.
|
||||
*/
|
||||
#if 0
|
||||
if (ev->button == 1 && _route->route_group()) {
|
||||
_session.set_record_enable (_route->route_group(), !rec_enable_button->get_active(),
|
||||
queue_route_group_op (RouteGroup::RecEnable, &Session::set_record_enable,
|
||||
_session.set_record_enable (_route->route_group()->route_list(), !rec_enable_button->get_active(), Session::rt_cleanup, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
} else if (Keyboard::is_context_menu_event (ev)) {
|
||||
|
||||
|
@ -565,11 +507,9 @@ RouteUI::rec_enable_press(GdkEventButton* ev)
|
|||
|
||||
} else {
|
||||
|
||||
#if 0
|
||||
boost::shared_ptr<RouteList> rl (new RouteList);
|
||||
rl->push_back (route());
|
||||
_session.set_record_enable (rl, !rec_enable_button->get_active(), sigc::mem_fun (*this, &RouteUI::post_rtop_cleanup));
|
||||
#endif
|
||||
_session.set_record_enable (rl, !rec_enable_button->get_active());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1018,80 +958,6 @@ RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
|
|||
_route->set_solo_safe (check->get_active(), this);
|
||||
}
|
||||
|
||||
void
|
||||
RouteUI::set_route_group_solo(boost::shared_ptr<Route> route, bool yn)
|
||||
{
|
||||
RouteGroup* route_group;
|
||||
|
||||
if((route_group = route->route_group()) != 0){
|
||||
_session.begin_reversible_command (_("mix group solo change"));
|
||||
Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
|
||||
route_group->apply(&Route::set_solo, yn, this);
|
||||
cmd->mark();
|
||||
_session.add_command (cmd);
|
||||
_session.commit_reversible_command ();
|
||||
} else {
|
||||
reversibly_apply_route_boolean ("solo change", &Route::set_solo, !route->soloed(), this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RouteUI::reversibly_apply_route_boolean (string name, void (Route::*func)(bool, void *), bool yn, void *arg)
|
||||
{
|
||||
_session.begin_reversible_command (name);
|
||||
XMLNode &before = _route->get_state();
|
||||
bind(mem_fun(*_route, func), yn, arg)();
|
||||
XMLNode &after = _route->get_state();
|
||||
_session.add_command (new MementoCommand<Route>(*_route, &before, &after));
|
||||
_session.commit_reversible_command ();
|
||||
}
|
||||
|
||||
void
|
||||
RouteUI::reversibly_apply_track_boolean (string name, void (Track::*func)(bool, void *), bool yn, void *arg)
|
||||
{
|
||||
_session.begin_reversible_command (name);
|
||||
XMLNode &before = track()->get_state();
|
||||
bind (mem_fun (*track(), func), yn, arg)();
|
||||
XMLNode &after = track()->get_state();
|
||||
_session.add_command (new MementoCommand<Track>(*track(), &before, &after));
|
||||
_session.commit_reversible_command ();
|
||||
}
|
||||
|
||||
void
|
||||
RouteUI::set_route_group_mute(boost::shared_ptr<Route> route, bool yn)
|
||||
{
|
||||
RouteGroup* route_group;
|
||||
|
||||
if((route_group = route->route_group()) != 0){
|
||||
_session.begin_reversible_command (_("mix group mute change"));
|
||||
Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand (_session, this);
|
||||
route_group->apply(&Route::set_mute, yn, this);
|
||||
cmd->mark();
|
||||
_session.add_command(cmd);
|
||||
_session.commit_reversible_command ();
|
||||
} else {
|
||||
reversibly_apply_route_boolean ("mute change", &Route::set_mute, !route->muted(), this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RouteUI::set_route_group_rec_enable(boost::shared_ptr<Route> route, bool yn)
|
||||
{
|
||||
RouteGroup* route_group;
|
||||
|
||||
if((route_group = route->route_group()) != 0){
|
||||
_session.begin_reversible_command (_("mix group rec-enable change"));
|
||||
Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
|
||||
route_group->apply (&Route::set_record_enable, yn, this);
|
||||
cmd->mark();
|
||||
_session.add_command(cmd);
|
||||
_session.commit_reversible_command ();
|
||||
} else {
|
||||
reversibly_apply_route_boolean ("rec-enable change", &Route::set_record_enable, !_route->record_enabled(), this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
RouteUI::choose_color()
|
||||
{
|
||||
|
|
|
@ -155,10 +155,6 @@ class RouteUI : public virtual AxisView
|
|||
void build_mute_menu(void);
|
||||
void init_mute_menu(ARDOUR::MuteMaster::MutePoint, Gtk::CheckMenuItem*);
|
||||
|
||||
void set_route_group_solo (boost::shared_ptr<ARDOUR::Route>, bool);
|
||||
void set_route_group_mute (boost::shared_ptr<ARDOUR::Route>, bool);
|
||||
void set_route_group_rec_enable (boost::shared_ptr<ARDOUR::Route>, bool);
|
||||
|
||||
int set_color_from_route ();
|
||||
|
||||
void remove_this_route ();
|
||||
|
@ -191,9 +187,6 @@ class RouteUI : public virtual AxisView
|
|||
|
||||
virtual void map_frozen ();
|
||||
|
||||
void reversibly_apply_route_boolean (std::string name, void (ARDOUR::Route::*func)(bool, void*), bool, void *);
|
||||
void reversibly_apply_track_boolean (std::string name, void (ARDOUR::Track::*func)(bool, void*), bool, void *);
|
||||
|
||||
void adjust_latency ();
|
||||
void save_as_template ();
|
||||
void open_remote_control_id_dialog ();
|
||||
|
@ -215,9 +208,21 @@ class RouteUI : public virtual AxisView
|
|||
void parameter_changed (std::string const &);
|
||||
void relabel_solo_button ();
|
||||
|
||||
void post_rtop_cleanup (ARDOUR::SessionEvent* ev);
|
||||
void post_group_rtop_cleanup (ARDOUR::SessionEvent* ev, ARDOUR::RouteGroup*, ARDOUR::RouteGroup::Property);
|
||||
void post_solo_cleanup (ARDOUR::SessionEvent* ev, bool was_not_latched);
|
||||
struct SoloMuteRelease {
|
||||
SoloMuteRelease (bool was_active)
|
||||
: active (was_active)
|
||||
, exclusive (false) {}
|
||||
|
||||
boost::shared_ptr<ARDOUR::RouteList> routes;
|
||||
boost::shared_ptr<ARDOUR::RouteList> routes_on;
|
||||
boost::shared_ptr<ARDOUR::RouteList> routes_off;
|
||||
boost::shared_ptr<ARDOUR::Route> route;
|
||||
bool active;
|
||||
bool exclusive;
|
||||
};
|
||||
|
||||
SoloMuteRelease* _solo_release;
|
||||
SoloMuteRelease* _mute_release;
|
||||
};
|
||||
|
||||
#endif /* __ardour_route_ui__ */
|
||||
|
|
|
@ -122,12 +122,6 @@ extern void setup_enum_writer ();
|
|||
|
||||
class Session : public PBD::StatefulDestructible, public SessionEventManager, public boost::noncopyable
|
||||
{
|
||||
private:
|
||||
typedef std::pair<boost::weak_ptr<Route>,bool> RouteBooleanState;
|
||||
typedef std::vector<RouteBooleanState> GlobalRouteBooleanState;
|
||||
typedef std::pair<boost::weak_ptr<Route>,MeterPoint> RouteMeterState;
|
||||
typedef std::vector<RouteMeterState> GlobalRouteMeterState;
|
||||
|
||||
public:
|
||||
enum RecordState {
|
||||
Disabled = 0,
|
||||
|
@ -617,14 +611,17 @@ class Session : public PBD::StatefulDestructible, public SessionEventManager, pu
|
|||
bool soloing() const { return _non_soloed_outs_muted; }
|
||||
bool listening() const { return _listen_cnt > 0; }
|
||||
|
||||
void set_solo (boost::shared_ptr<RouteList>, bool);
|
||||
void set_mute (boost::shared_ptr<RouteList>, bool);
|
||||
void set_listen (boost::shared_ptr<RouteList>, bool);
|
||||
static const sigc::slot<void,SessionEvent*> rt_cleanup;
|
||||
|
||||
void set_solo (boost::shared_ptr<RouteList>, bool, sigc::slot<void,SessionEvent*> after = rt_cleanup, bool group_override = false);
|
||||
void set_just_one_solo (boost::shared_ptr<Route>, bool, sigc::slot<void,SessionEvent*> after = rt_cleanup);
|
||||
void set_mute (boost::shared_ptr<RouteList>, bool, sigc::slot<void,SessionEvent*> after = rt_cleanup, bool group_override = false);
|
||||
void set_listen (boost::shared_ptr<RouteList>, bool, sigc::slot<void,SessionEvent*> after = rt_cleanup, bool group_override = false);
|
||||
void set_record_enable (boost::shared_ptr<RouteList>, bool, sigc::slot<void,SessionEvent*> after = rt_cleanup, bool group_override = false);
|
||||
|
||||
sigc::signal<void,bool> SoloActive;
|
||||
sigc::signal<void> SoloChanged;
|
||||
|
||||
void set_record_enable (boost::shared_ptr<RouteList>, bool);
|
||||
|
||||
/* control/master out */
|
||||
|
||||
|
@ -735,73 +732,6 @@ class Session : public PBD::StatefulDestructible, public SessionEventManager, pu
|
|||
Command* memento_command_factory(XMLNode* n);
|
||||
void register_with_memento_command_factory(PBD::ID, PBD::StatefulThingWithGoingAway*);
|
||||
|
||||
Command* global_state_command_factory (const XMLNode& n);
|
||||
|
||||
class GlobalRouteStateCommand : public Command
|
||||
{
|
||||
public:
|
||||
GlobalRouteStateCommand (Session&, void*);
|
||||
GlobalRouteStateCommand (Session&, const XMLNode& node);
|
||||
int set_state (const XMLNode&, int version);
|
||||
XMLNode& get_state ();
|
||||
|
||||
protected:
|
||||
GlobalRouteBooleanState before, after;
|
||||
Session& sess;
|
||||
void* src;
|
||||
};
|
||||
|
||||
class GlobalSoloStateCommand : public GlobalRouteStateCommand
|
||||
{
|
||||
public:
|
||||
GlobalSoloStateCommand (Session &, void *src);
|
||||
GlobalSoloStateCommand (Session&, const XMLNode&);
|
||||
void operator()(); //redo
|
||||
void undo();
|
||||
XMLNode &get_state();
|
||||
void mark();
|
||||
};
|
||||
|
||||
class GlobalMuteStateCommand : public GlobalRouteStateCommand
|
||||
{
|
||||
public:
|
||||
GlobalMuteStateCommand(Session &, void *src);
|
||||
GlobalMuteStateCommand (Session&, const XMLNode&);
|
||||
void operator()(); // redo
|
||||
void undo();
|
||||
XMLNode &get_state();
|
||||
void mark();
|
||||
};
|
||||
|
||||
class GlobalRecordEnableStateCommand : public GlobalRouteStateCommand
|
||||
{
|
||||
public:
|
||||
GlobalRecordEnableStateCommand(Session &, void *src);
|
||||
GlobalRecordEnableStateCommand (Session&, const XMLNode&);
|
||||
void operator()(); // redo
|
||||
void undo();
|
||||
XMLNode &get_state();
|
||||
void mark();
|
||||
};
|
||||
|
||||
class GlobalMeteringStateCommand : public Command
|
||||
{
|
||||
public:
|
||||
GlobalMeteringStateCommand(Session &, void *src);
|
||||
GlobalMeteringStateCommand (Session&, const XMLNode&);
|
||||
void operator()();
|
||||
void undo();
|
||||
XMLNode &get_state();
|
||||
int set_state (const XMLNode&, int version);
|
||||
void mark();
|
||||
|
||||
protected:
|
||||
Session& sess;
|
||||
void* src;
|
||||
GlobalRouteMeterState before;
|
||||
GlobalRouteMeterState after;
|
||||
};
|
||||
|
||||
/* clicking */
|
||||
|
||||
boost::shared_ptr<IO> click_io() { return _click_io; }
|
||||
|
@ -1443,16 +1373,6 @@ class Session : public PBD::StatefulDestructible, public SessionEventManager, pu
|
|||
UndoHistory _history;
|
||||
std::stack<UndoTransaction*> _current_trans;
|
||||
|
||||
GlobalRouteBooleanState get_global_route_boolean (bool (Route::*method)(void) const);
|
||||
GlobalRouteMeterState get_global_route_metering ();
|
||||
|
||||
void set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void *arg);
|
||||
void set_global_route_metering (GlobalRouteMeterState s, void *arg);
|
||||
|
||||
void set_global_mute (GlobalRouteBooleanState s, void *src);
|
||||
void set_global_solo (GlobalRouteBooleanState s, void *src);
|
||||
void set_global_record_enable (GlobalRouteBooleanState s, void *src);
|
||||
|
||||
void jack_timebase_callback (jack_transport_state_t, nframes_t, jack_position_t*, int);
|
||||
int jack_sync_callback (jack_transport_state_t, jack_position_t*);
|
||||
void reset_jack_connection (jack_client_t* jack);
|
||||
|
@ -1549,6 +1469,16 @@ class Session : public PBD::StatefulDestructible, public SessionEventManager, pu
|
|||
|
||||
void update_have_rec_enabled_diskstream ();
|
||||
gint _have_rec_enabled_diskstream;
|
||||
|
||||
/* realtime "apply to set of routes" operations */
|
||||
SessionEvent* get_rt_event (boost::shared_ptr<RouteList> rl, bool yn, sigc::slot<void,SessionEvent*> after, bool group_override,
|
||||
void (Session::*method) (boost::shared_ptr<RouteList>, bool, bool));
|
||||
|
||||
void rt_set_solo (boost::shared_ptr<RouteList>, bool yn, bool group_override);
|
||||
void rt_set_just_one_solo (boost::shared_ptr<RouteList>, bool yn, bool /* ignored*/ );
|
||||
void rt_set_mute (boost::shared_ptr<RouteList>, bool yn, bool group_override);
|
||||
void rt_set_listen (boost::shared_ptr<RouteList>, bool yn, bool group_override);
|
||||
void rt_set_record_enable (boost::shared_ptr<RouteList>, bool yn, bool group_override);
|
||||
};
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "pbd/pool.h"
|
||||
#include "pbd/ringbuffer.h"
|
||||
#include "pbd/ui_callback.h"
|
||||
|
||||
#include "ardour/types.h"
|
||||
|
||||
|
@ -68,6 +69,7 @@ struct SessionEvent {
|
|||
boost::shared_ptr<RouteList> routes;
|
||||
sigc::slot<void> rt_slot; /* what to call in RT context */
|
||||
sigc::slot<void,SessionEvent*> rt_return; /* called after rt_slot, with this event as an argument */
|
||||
PBD::UICallback* ui;
|
||||
|
||||
std::list<AudioRange> audio_range;
|
||||
std::list<MusicRange> music_range;
|
||||
|
@ -81,7 +83,8 @@ struct SessionEvent {
|
|||
, target_frame (where)
|
||||
, speed (spd)
|
||||
, yes_or_no (yn)
|
||||
, second_yes_or_no (yn2) {}
|
||||
, second_yes_or_no (yn2)
|
||||
, ui (0) {}
|
||||
|
||||
void set_ptr (void* p) {
|
||||
ptr = p;
|
||||
|
|
|
@ -117,6 +117,9 @@ sigc::signal<void> Session::AutoBindingOn;
|
|||
sigc::signal<void> Session::AutoBindingOff;
|
||||
sigc::signal<void, std::string, std::string> Session::Exported;
|
||||
|
||||
static void clean_up_session_event (SessionEvent* ev) { delete ev; }
|
||||
const sigc::slot<void,SessionEvent*> Session::rt_cleanup (sigc::ptr_fun (&clean_up_session_event));
|
||||
|
||||
Session::Session (AudioEngine &eng,
|
||||
const string& fullpath,
|
||||
const string& snapshot_name,
|
||||
|
@ -3515,42 +3518,6 @@ Session::is_auditioning () const
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Session::set_solo (boost::shared_ptr<RouteList> r, bool yn)
|
||||
{
|
||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||
if (!(*i)->is_hidden()) {
|
||||
(*i)->set_solo (yn, this);
|
||||
}
|
||||
}
|
||||
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
void
|
||||
Session::set_listen (boost::shared_ptr<RouteList> r, bool yn)
|
||||
{
|
||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||
if (!(*i)->is_hidden()) {
|
||||
(*i)->set_listen (yn, this);
|
||||
}
|
||||
}
|
||||
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
void
|
||||
Session::set_mute (boost::shared_ptr<RouteList> r, bool yn)
|
||||
{
|
||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||
if (!(*i)->is_hidden()) {
|
||||
(*i)->set_mute (yn, this);
|
||||
}
|
||||
}
|
||||
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Session::n_diskstreams () const
|
||||
{
|
||||
|
@ -3596,32 +3563,6 @@ Session::graph_reordered ()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Session::set_record_enable (boost::shared_ptr<RouteList> rl, bool yn)
|
||||
{
|
||||
if (!writable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (RouteList::iterator i = rl->begin(); i != rl->end(); ) {
|
||||
boost::shared_ptr<Track> t;
|
||||
|
||||
if ((t = boost::dynamic_pointer_cast<Track>(*i)) != 0) {
|
||||
t->set_record_enable (yn, this);
|
||||
if (t->meter_point() == MeterCustom) {
|
||||
/* don't change metering for this track */
|
||||
i = rl->erase (i);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
set_dirty ();
|
||||
}
|
||||
|
||||
void
|
||||
Session::add_processor (Processor* processor)
|
||||
{
|
||||
|
|
|
@ -124,428 +124,3 @@ Session::memento_command_factory(XMLNode *n)
|
|||
return 0 ;
|
||||
}
|
||||
|
||||
Command *
|
||||
Session::global_state_command_factory (const XMLNode& node)
|
||||
{
|
||||
const XMLProperty* prop;
|
||||
Command* command = 0;
|
||||
|
||||
if ((prop = node.property ("type")) == 0) {
|
||||
error << _("GlobalRouteStateCommand has no \"type\" node, ignoring") << endmsg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
if (prop->value() == "solo") {
|
||||
command = new GlobalSoloStateCommand (*this, node);
|
||||
} else if (prop->value() == "mute") {
|
||||
command = new GlobalMuteStateCommand (*this, node);
|
||||
} else if (prop->value() == "rec-enable") {
|
||||
command = new GlobalRecordEnableStateCommand (*this, node);
|
||||
} else if (prop->value() == "metering") {
|
||||
command = new GlobalMeteringStateCommand (*this, node);
|
||||
} else {
|
||||
error << string_compose (_("unknown type of GlobalRouteStateCommand (%1), ignored"), prop->value()) << endmsg;
|
||||
}
|
||||
}
|
||||
|
||||
catch (failed_constructor& err) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
Session::GlobalRouteStateCommand::GlobalRouteStateCommand (Session& s, void* p)
|
||||
: sess (s), src (p)
|
||||
{
|
||||
}
|
||||
|
||||
Session::GlobalRouteStateCommand::GlobalRouteStateCommand (Session& s, const XMLNode& node)
|
||||
: sess (s), src (this)
|
||||
{
|
||||
if (set_state (node, Stateful::loading_state_version)) {
|
||||
throw failed_constructor ();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
Session::GlobalRouteStateCommand::set_state (const XMLNode& node, int /*version*/)
|
||||
{
|
||||
GlobalRouteBooleanState states;
|
||||
XMLNodeList nlist;
|
||||
const XMLProperty* prop;
|
||||
XMLNode* child;
|
||||
XMLNodeConstIterator niter;
|
||||
int loop;
|
||||
|
||||
before.clear ();
|
||||
after.clear ();
|
||||
|
||||
for (loop = 0; loop < 2; ++loop) {
|
||||
|
||||
const char *str;
|
||||
|
||||
if (loop) {
|
||||
str = "after";
|
||||
} else {
|
||||
str = "before";
|
||||
}
|
||||
|
||||
if ((child = node.child (str)) == 0) {
|
||||
warning << string_compose (_("global route state command has no \"%1\" node, ignoring entire command"), str) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
nlist = child->children();
|
||||
|
||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||
|
||||
RouteBooleanState rbs;
|
||||
boost::shared_ptr<Route> route;
|
||||
ID id;
|
||||
|
||||
prop = (*niter)->property ("id");
|
||||
id = prop->value ();
|
||||
|
||||
if ((route = sess.route_by_id (id)) == 0) {
|
||||
warning << string_compose (_("cannot find track/bus \"%1\" while rebuilding a global route state command, ignored"), id.to_s()) << endmsg;
|
||||
continue;
|
||||
}
|
||||
|
||||
rbs.first = boost::weak_ptr<Route> (route);
|
||||
|
||||
prop = (*niter)->property ("yn");
|
||||
rbs.second = (prop->value() == "1");
|
||||
|
||||
if (loop) {
|
||||
after.push_back (rbs);
|
||||
} else {
|
||||
before.push_back (rbs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
Session::GlobalRouteStateCommand::get_state ()
|
||||
{
|
||||
XMLNode* node = new XMLNode (X_("GlobalRouteStateCommand"));
|
||||
XMLNode* nbefore = new XMLNode (X_("before"));
|
||||
XMLNode* nafter = new XMLNode (X_("after"));
|
||||
|
||||
for (Session::GlobalRouteBooleanState::iterator x = before.begin(); x != before.end(); ++x) {
|
||||
XMLNode* child = new XMLNode ("s");
|
||||
boost::shared_ptr<Route> r = x->first.lock();
|
||||
|
||||
if (r) {
|
||||
child->add_property (X_("id"), r->id().to_s());
|
||||
child->add_property (X_("yn"), (x->second ? "1" : "0"));
|
||||
nbefore->add_child_nocopy (*child);
|
||||
}
|
||||
}
|
||||
|
||||
for (Session::GlobalRouteBooleanState::iterator x = after.begin(); x != after.end(); ++x) {
|
||||
XMLNode* child = new XMLNode ("s");
|
||||
boost::shared_ptr<Route> r = x->first.lock();
|
||||
|
||||
if (r) {
|
||||
child->add_property (X_("id"), r->id().to_s());
|
||||
child->add_property (X_("yn"), (x->second ? "1" : "0"));
|
||||
nafter->add_child_nocopy (*child);
|
||||
}
|
||||
}
|
||||
|
||||
node->add_child_nocopy (*nbefore);
|
||||
node->add_child_nocopy (*nafter);
|
||||
|
||||
return *node;
|
||||
}
|
||||
|
||||
// solo
|
||||
|
||||
Session::GlobalSoloStateCommand::GlobalSoloStateCommand(Session &sess, void *src)
|
||||
: GlobalRouteStateCommand (sess, src)
|
||||
{
|
||||
after = before = sess.get_global_route_boolean(&Route::soloed);
|
||||
}
|
||||
|
||||
Session::GlobalSoloStateCommand::GlobalSoloStateCommand (Session& sess, const XMLNode& node)
|
||||
: Session::GlobalRouteStateCommand (sess, node)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Session::GlobalSoloStateCommand::mark()
|
||||
{
|
||||
after = sess.get_global_route_boolean(&Route::soloed);
|
||||
}
|
||||
|
||||
void
|
||||
Session::GlobalSoloStateCommand::operator()()
|
||||
{
|
||||
sess.set_global_solo(after, src);
|
||||
}
|
||||
|
||||
void
|
||||
Session::GlobalSoloStateCommand::undo()
|
||||
{
|
||||
sess.set_global_solo(before, src);
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
Session::GlobalSoloStateCommand::get_state()
|
||||
{
|
||||
XMLNode& node = GlobalRouteStateCommand::get_state();
|
||||
node.add_property ("type", "solo");
|
||||
return node;
|
||||
}
|
||||
|
||||
// mute
|
||||
Session::GlobalMuteStateCommand::GlobalMuteStateCommand(Session &sess, void *src)
|
||||
: GlobalRouteStateCommand (sess, src)
|
||||
{
|
||||
after = before = sess.get_global_route_boolean(&Route::muted);
|
||||
}
|
||||
|
||||
Session::GlobalMuteStateCommand::GlobalMuteStateCommand (Session& sess, const XMLNode& node)
|
||||
: Session::GlobalRouteStateCommand (sess, node)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Session::GlobalMuteStateCommand::mark()
|
||||
{
|
||||
after = sess.get_global_route_boolean(&Route::muted);
|
||||
}
|
||||
|
||||
void
|
||||
Session::GlobalMuteStateCommand::operator()()
|
||||
{
|
||||
sess.set_global_mute(after, src);
|
||||
}
|
||||
|
||||
void
|
||||
Session::GlobalMuteStateCommand::undo()
|
||||
{
|
||||
sess.set_global_mute(before, src);
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
Session::GlobalMuteStateCommand::get_state()
|
||||
{
|
||||
XMLNode& node = GlobalRouteStateCommand::get_state();
|
||||
node.add_property ("type", "mute");
|
||||
return node;
|
||||
}
|
||||
|
||||
// record enable
|
||||
Session::GlobalRecordEnableStateCommand::GlobalRecordEnableStateCommand(Session &sess, void *src)
|
||||
: GlobalRouteStateCommand (sess, src)
|
||||
{
|
||||
after = before = sess.get_global_route_boolean(&Route::record_enabled);
|
||||
}
|
||||
|
||||
Session::GlobalRecordEnableStateCommand::GlobalRecordEnableStateCommand (Session& sess, const XMLNode& node)
|
||||
: Session::GlobalRouteStateCommand (sess, node)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Session::GlobalRecordEnableStateCommand::mark()
|
||||
{
|
||||
after = sess.get_global_route_boolean(&Route::record_enabled);
|
||||
}
|
||||
|
||||
void
|
||||
Session::GlobalRecordEnableStateCommand::operator()()
|
||||
{
|
||||
sess.set_global_record_enable(after, src);
|
||||
}
|
||||
|
||||
void
|
||||
Session::GlobalRecordEnableStateCommand::undo()
|
||||
{
|
||||
sess.set_global_record_enable(before, src);
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
Session::GlobalRecordEnableStateCommand::get_state()
|
||||
{
|
||||
XMLNode& node = GlobalRouteStateCommand::get_state();
|
||||
node.add_property ("type", "rec-enable");
|
||||
return node;
|
||||
}
|
||||
|
||||
// metering
|
||||
Session::GlobalMeteringStateCommand::GlobalMeteringStateCommand(Session &s, void *p)
|
||||
: sess (s), src (p)
|
||||
{
|
||||
after = before = sess.get_global_route_metering();
|
||||
}
|
||||
|
||||
Session::GlobalMeteringStateCommand::GlobalMeteringStateCommand (Session& s, const XMLNode& node)
|
||||
: sess (s), src (this)
|
||||
{
|
||||
if (set_state (node, Stateful::loading_state_version)) {
|
||||
throw failed_constructor();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Session::GlobalMeteringStateCommand::mark()
|
||||
{
|
||||
after = sess.get_global_route_metering();
|
||||
}
|
||||
|
||||
void
|
||||
Session::GlobalMeteringStateCommand::operator()()
|
||||
{
|
||||
sess.set_global_route_metering(after, src);
|
||||
}
|
||||
|
||||
void
|
||||
Session::GlobalMeteringStateCommand::undo()
|
||||
{
|
||||
sess.set_global_route_metering(before, src);
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
Session::GlobalMeteringStateCommand::get_state()
|
||||
{
|
||||
XMLNode* node = new XMLNode (X_("GlobalRouteStateCommand"));
|
||||
XMLNode* nbefore = new XMLNode (X_("before"));
|
||||
XMLNode* nafter = new XMLNode (X_("after"));
|
||||
|
||||
for (Session::GlobalRouteMeterState::iterator x = before.begin(); x != before.end(); ++x) {
|
||||
XMLNode* child = new XMLNode ("s");
|
||||
boost::shared_ptr<Route> r = x->first.lock();
|
||||
|
||||
if (r) {
|
||||
child->add_property (X_("id"), r->id().to_s());
|
||||
|
||||
const char* meterstr = 0;
|
||||
|
||||
switch (x->second) {
|
||||
case MeterInput:
|
||||
meterstr = X_("input");
|
||||
break;
|
||||
case MeterPreFader:
|
||||
meterstr = X_("pre");
|
||||
break;
|
||||
case MeterPostFader:
|
||||
meterstr = X_("post");
|
||||
break;
|
||||
default:
|
||||
fatal << string_compose (_("programming error: %1") , "no meter state in Session::GlobalMeteringStateCommand::get_state") << endmsg;
|
||||
}
|
||||
|
||||
child->add_property (X_("meter"), meterstr);
|
||||
nbefore->add_child_nocopy (*child);
|
||||
}
|
||||
}
|
||||
|
||||
for (Session::GlobalRouteMeterState::iterator x = after.begin(); x != after.end(); ++x) {
|
||||
XMLNode* child = new XMLNode ("s");
|
||||
boost::shared_ptr<Route> r = x->first.lock();
|
||||
|
||||
if (r) {
|
||||
child->add_property (X_("id"), r->id().to_s());
|
||||
|
||||
const char* meterstr;
|
||||
|
||||
switch (x->second) {
|
||||
case MeterInput:
|
||||
meterstr = X_("input");
|
||||
break;
|
||||
case MeterPreFader:
|
||||
meterstr = X_("pre");
|
||||
break;
|
||||
case MeterPostFader:
|
||||
meterstr = X_("post");
|
||||
break;
|
||||
default: meterstr = "";
|
||||
}
|
||||
|
||||
child->add_property (X_("meter"), meterstr);
|
||||
nafter->add_child_nocopy (*child);
|
||||
}
|
||||
}
|
||||
|
||||
node->add_child_nocopy (*nbefore);
|
||||
node->add_child_nocopy (*nafter);
|
||||
|
||||
node->add_property ("type", "metering");
|
||||
|
||||
return *node;
|
||||
}
|
||||
|
||||
int
|
||||
Session::GlobalMeteringStateCommand::set_state (const XMLNode& node, int /*version*/)
|
||||
{
|
||||
GlobalRouteBooleanState states;
|
||||
XMLNodeList nlist;
|
||||
const XMLProperty* prop;
|
||||
XMLNode* child;
|
||||
XMLNodeConstIterator niter;
|
||||
int loop;
|
||||
|
||||
before.clear ();
|
||||
after.clear ();
|
||||
|
||||
for (loop = 0; loop < 2; ++loop) {
|
||||
|
||||
const char *str;
|
||||
|
||||
if (loop) {
|
||||
str = "after";
|
||||
} else {
|
||||
str = "before";
|
||||
}
|
||||
|
||||
if ((child = node.child (str)) == 0) {
|
||||
warning << string_compose (_("global route meter state command has no \"%1\" node, ignoring entire command"), str) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
nlist = child->children();
|
||||
|
||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||
|
||||
RouteMeterState rms;
|
||||
boost::shared_ptr<Route> route;
|
||||
ID id;
|
||||
|
||||
prop = (*niter)->property ("id");
|
||||
id = prop->value ();
|
||||
|
||||
if ((route = sess.route_by_id (id)) == 0) {
|
||||
warning << string_compose (_("cannot find track/bus \"%1\" while rebuilding a global route state command, ignored"), id.to_s()) << endmsg;
|
||||
continue;
|
||||
}
|
||||
|
||||
rms.first = boost::weak_ptr<Route> (route);
|
||||
|
||||
prop = (*niter)->property ("meter");
|
||||
|
||||
if (prop->value() == X_("pre")) {
|
||||
rms.second = MeterPreFader;
|
||||
} else if (prop->value() == X_("post")) {
|
||||
rms.second = MeterPostFader;
|
||||
} else {
|
||||
rms.second = MeterInput;
|
||||
}
|
||||
|
||||
if (loop) {
|
||||
after.push_back (rms);
|
||||
} else {
|
||||
before.push_back (rms);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -577,7 +577,7 @@ Session::follow_slave (nframes_t nframes)
|
|||
slave_speed));
|
||||
}
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
if (abs(average_slave_delta) > _slave->resolution()) {
|
||||
cerr << "average slave delta greater than slave resolution (" << _slave->resolution() << "), going to silent motion\n";
|
||||
goto silent_motion;
|
||||
|
@ -1141,9 +1141,3 @@ Session::process_event (SessionEvent* ev)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Session::process_rtop (SessionEvent* ev)
|
||||
{
|
||||
ev->rt_slot ();
|
||||
ev->rt_return (ev);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
Copyright (C) 1999-2009 Paul Davis
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "pbd/error.h"
|
||||
#include "pbd/compose.h"
|
||||
|
||||
#include "ardour/session.h"
|
||||
#include "ardour/route.h"
|
||||
#include "ardour/track.h"
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace PBD;
|
||||
using namespace ARDOUR;
|
||||
using namespace Glib;
|
||||
|
||||
SessionEvent*
|
||||
Session::get_rt_event (boost::shared_ptr<RouteList> rl, bool yn, sigc::slot<void,SessionEvent*> after, bool group_override,
|
||||
void (Session::*method) (boost::shared_ptr<RouteList>, bool, bool))
|
||||
{
|
||||
SessionEvent* ev = new SessionEvent (SessionEvent::RealTimeOperation, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
|
||||
ev->rt_slot = bind (sigc::mem_fun (*this, method), rl, yn, group_override);
|
||||
ev->rt_return = after;
|
||||
ev->ui = UICallback::get_ui_for_thread ();
|
||||
|
||||
return ev;
|
||||
}
|
||||
|
||||
void
|
||||
Session::set_solo (boost::shared_ptr<RouteList> rl, bool yn, sigc::slot<void,SessionEvent*> after, bool group_override)
|
||||
{
|
||||
queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_solo));
|
||||
}
|
||||
|
||||
void
|
||||
Session::rt_set_solo (boost::shared_ptr<RouteList> rl, bool yn, bool group_override)
|
||||
{
|
||||
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
|
||||
if (!(*i)->is_hidden()) {
|
||||
(*i)->set_solo (yn, this);
|
||||
}
|
||||
}
|
||||
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
void
|
||||
Session::set_just_one_solo (boost::shared_ptr<Route> r, bool yn, sigc::slot<void,SessionEvent*> after)
|
||||
{
|
||||
/* its a bit silly to have to do this, but it keeps the API for this public method sane (we're
|
||||
only going to solo one route) and keeps our ability to use get_rt_event() for the internal
|
||||
private method.
|
||||
*/
|
||||
|
||||
boost::shared_ptr<RouteList> rl (new RouteList);
|
||||
rl->push_back (r);
|
||||
|
||||
queue_event (get_rt_event (rl, yn, after, false, &Session::rt_set_just_one_solo));
|
||||
}
|
||||
|
||||
void
|
||||
Session::rt_set_just_one_solo (boost::shared_ptr<RouteList> just_one, bool yn, bool /*ignored*/)
|
||||
{
|
||||
boost::shared_ptr<RouteList> rl = routes.reader ();
|
||||
boost::shared_ptr<Route> r = just_one->front();
|
||||
|
||||
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
|
||||
if (!(*i)->is_hidden() && r != *i) {
|
||||
(*i)->set_solo (!yn, (*i)->route_group());
|
||||
}
|
||||
}
|
||||
|
||||
r->set_solo (yn, r->route_group());
|
||||
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
void
|
||||
Session::set_listen (boost::shared_ptr<RouteList> rl, bool yn, sigc::slot<void,SessionEvent*> after, bool group_override)
|
||||
{
|
||||
queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_listen));
|
||||
}
|
||||
|
||||
void
|
||||
Session::rt_set_listen (boost::shared_ptr<RouteList> rl, bool yn, bool group_override)
|
||||
{
|
||||
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
|
||||
if (!(*i)->is_hidden()) {
|
||||
(*i)->set_listen (yn, this);
|
||||
}
|
||||
}
|
||||
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
void
|
||||
Session::set_mute (boost::shared_ptr<RouteList> rl, bool yn, sigc::slot<void,SessionEvent*> after, bool group_override)
|
||||
{
|
||||
queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_mute));
|
||||
}
|
||||
|
||||
void
|
||||
Session::rt_set_mute (boost::shared_ptr<RouteList> rl, bool yn, bool group_override)
|
||||
{
|
||||
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
|
||||
if (!(*i)->is_hidden()) {
|
||||
(*i)->set_mute (yn, this);
|
||||
}
|
||||
}
|
||||
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
void
|
||||
Session::set_record_enable (boost::shared_ptr<RouteList> rl, bool yn, sigc::slot<void,SessionEvent*> after, bool group_override)
|
||||
{
|
||||
if (!writable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_record_enable));
|
||||
}
|
||||
|
||||
void
|
||||
Session::rt_set_record_enable (boost::shared_ptr<RouteList> rl, bool yn, bool group_override)
|
||||
{
|
||||
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
|
||||
if ((*i)->is_hidden()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Track> t;
|
||||
|
||||
if ((t = boost::dynamic_pointer_cast<Track>(*i)) != 0) {
|
||||
t->set_record_enable (yn, (group_override ? (void*) t->route_group() : (void *) this));
|
||||
}
|
||||
}
|
||||
|
||||
set_dirty ();
|
||||
}
|
||||
|
||||
void
|
||||
Session::process_rtop (SessionEvent* ev)
|
||||
{
|
||||
ev->rt_slot ();
|
||||
|
||||
if (ev->ui) {
|
||||
ev->ui->call_slot (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);
|
||||
}
|
||||
}
|
|
@ -2176,92 +2176,6 @@ Session::commit_reversible_command(Command *cmd)
|
|||
_current_trans.pop();
|
||||
}
|
||||
|
||||
Session::GlobalRouteBooleanState
|
||||
Session::get_global_route_boolean (bool (Route::*method)(void) const)
|
||||
{
|
||||
GlobalRouteBooleanState s;
|
||||
boost::shared_ptr<RouteList> r = routes.reader ();
|
||||
|
||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||
if (!(*i)->is_hidden()) {
|
||||
RouteBooleanState v;
|
||||
|
||||
v.first =* i;
|
||||
Route* r = (*i).get();
|
||||
v.second = (r->*method)();
|
||||
|
||||
s.push_back (v);
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
Session::GlobalRouteMeterState
|
||||
Session::get_global_route_metering ()
|
||||
{
|
||||
GlobalRouteMeterState s;
|
||||
boost::shared_ptr<RouteList> r = routes.reader ();
|
||||
|
||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||
if (!(*i)->is_hidden()) {
|
||||
RouteMeterState v;
|
||||
|
||||
v.first =* i;
|
||||
v.second = (*i)->meter_point();
|
||||
|
||||
s.push_back (v);
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
|
||||
{
|
||||
for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
|
||||
|
||||
boost::shared_ptr<Route> r = (i->first.lock());
|
||||
|
||||
if (r) {
|
||||
r->set_meter_point (i->second, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
|
||||
{
|
||||
for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
|
||||
|
||||
boost::shared_ptr<Route> r = (i->first.lock());
|
||||
|
||||
if (r) {
|
||||
Route* rp = r.get();
|
||||
(rp->*method) (i->second, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Session::set_global_mute (GlobalRouteBooleanState s, void* src)
|
||||
{
|
||||
set_global_route_boolean (s, &Route::set_mute, src);
|
||||
}
|
||||
|
||||
void
|
||||
Session::set_global_solo (GlobalRouteBooleanState s, void* src)
|
||||
{
|
||||
set_global_route_boolean (s, &Route::set_solo, src);
|
||||
}
|
||||
|
||||
void
|
||||
Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
|
||||
{
|
||||
set_global_route_boolean (s, &Route::set_record_enable, src);
|
||||
}
|
||||
|
||||
static bool
|
||||
accept_all_non_peak_files (const string& path, void */*arg*/)
|
||||
{
|
||||
|
@ -2892,12 +2806,6 @@ Session::restore_history (string snapshot_name)
|
|||
ut->add_command(c);
|
||||
}
|
||||
|
||||
} else if (n->name() == X_("GlobalRouteStateCommand")) {
|
||||
|
||||
if ((c = global_state_command_factory (*n))) {
|
||||
ut->add_command (c);
|
||||
}
|
||||
|
||||
} else if (n->name() == "DeltaCommand") {
|
||||
PBD::ID id(n->property("midi-source")->value());
|
||||
boost::shared_ptr<MidiSource> midi_source =
|
||||
|
|
|
@ -168,6 +168,7 @@ libardour_sources = [
|
|||
'session_midi.cc',
|
||||
'session_playlists.cc',
|
||||
'session_process.cc',
|
||||
'session_rtevents.cc',
|
||||
'session_state.cc',
|
||||
'session_state_utils.cc',
|
||||
'session_time.cc',
|
||||
|
|
|
@ -80,6 +80,12 @@ UI::UI (string namestr, int *argc, char ***argv)
|
|||
*/
|
||||
|
||||
run_loop_thread = Thread::self();
|
||||
|
||||
/* store "this" as the UI-for-thread of this thread, same argument
|
||||
as for previous line.
|
||||
*/
|
||||
|
||||
set_ui_for_thread (this);
|
||||
|
||||
/* attach our request source to the default main context */
|
||||
|
||||
|
|
|
@ -43,8 +43,6 @@ BaseUI::BaseUI (const string& str)
|
|||
: run_loop_thread (0)
|
||||
, _name (str)
|
||||
{
|
||||
cerr << "New BUI called " << _name << " @ " << this << endl;
|
||||
|
||||
base_ui_instance = this;
|
||||
|
||||
request_channel.ios()->connect (sigc::mem_fun (*this, &BaseUI::request_handler));
|
||||
|
@ -72,6 +70,7 @@ BaseUI::new_request_type ()
|
|||
void
|
||||
BaseUI::main_thread ()
|
||||
{
|
||||
set_ui_for_thread (this);
|
||||
thread_init ();
|
||||
_main_loop->run ();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2000-2007 Paul Davis
|
||||
Copyright (C) 2000-2009 Paul Davis
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -30,8 +30,10 @@
|
|||
#include <glibmm/main.h>
|
||||
|
||||
#include "pbd/crossthread.h"
|
||||
#include "pbd/ui_callback.h"
|
||||
|
||||
class BaseUI : virtual public sigc::trackable {
|
||||
class BaseUI : virtual public sigc::trackable, public PBD::UICallback
|
||||
{
|
||||
public:
|
||||
BaseUI (const std::string& name);
|
||||
virtual ~BaseUI();
|
||||
|
@ -45,7 +47,7 @@ class BaseUI : virtual public sigc::trackable {
|
|||
std::string name() const { return _name; }
|
||||
|
||||
bool ok() const { return _ok; }
|
||||
|
||||
|
||||
enum RequestType {
|
||||
range_guarantee = ~0
|
||||
};
|
||||
|
@ -62,8 +64,6 @@ class BaseUI : virtual public sigc::trackable {
|
|||
void run ();
|
||||
void quit ();
|
||||
|
||||
virtual void call_slot (sigc::slot<void> theSlot) = 0;
|
||||
|
||||
protected:
|
||||
CrossThreadChannel request_channel;
|
||||
bool _ok;
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
Copyright (C) 2009 Paul Davis
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __pbd_ui_callback_h__
|
||||
#define __pbd_ui_callback_h__
|
||||
|
||||
#include <glibmm/thread.h>
|
||||
#include <sigc++/slot.h>
|
||||
|
||||
namespace PBD
|
||||
{
|
||||
|
||||
class UICallback
|
||||
{
|
||||
public:
|
||||
UICallback() {}
|
||||
virtual ~UICallback() {}
|
||||
|
||||
virtual void call_slot (sigc::slot<void> theSlot) = 0;
|
||||
|
||||
static UICallback* get_ui_for_thread() { return thread_ui.get(); }
|
||||
static void set_ui_for_thread (UICallback* ui) { return thread_ui.set (ui); }
|
||||
|
||||
private:
|
||||
static Glib::StaticPrivate<UICallback> thread_ui;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* __pbd_ui_callback_h__ */
|
|
@ -0,0 +1,6 @@
|
|||
#include "pbd/ui_callback.h"
|
||||
|
||||
using namespace PBD;
|
||||
|
||||
Glib::StaticPrivate<UICallback> UICallback::thread_ui;
|
||||
|
|
@ -81,6 +81,7 @@ def build(bld):
|
|||
strsplit.cc
|
||||
textreceiver.cc
|
||||
transmitter.cc
|
||||
ui_callback.cc
|
||||
undo.cc
|
||||
uuid.cc
|
||||
version.cc
|
||||
|
|
Loading…
Reference in New Issue