Mix group tabs in the mixer.

git-svn-id: svn://localhost/ardour2/branches/3.0@5228 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington 2009-06-20 17:15:33 +00:00
parent 9dfa933c6e
commit be3aff4bda
15 changed files with 277 additions and 28 deletions

View file

@ -393,7 +393,7 @@
<menuitem action='ToggleMeasureVisibility'/> <menuitem action='ToggleMeasureVisibility'/>
<menuitem action='ToggleWaveformsWhileRecording'/> <menuitem action='ToggleWaveformsWhileRecording'/>
<menuitem action='ToggleSummary'/> <menuitem action='ToggleSummary'/>
<menuitem action='ToggleEditGroupTabs'/> <menuitem action='ToggleGroupTabs'/>
</menu> </menu>
<menu name='JACK' action='JACK'> <menu name='JACK' action='JACK'>
<menuitem action='JACKDisconnect'/> <menuitem action='JACKDisconnect'/>

View file

@ -345,7 +345,7 @@ class Editor : public PublicEditor
void toggle_zero_line_visibility (); void toggle_zero_line_visibility ();
void toggle_waveforms_while_recording (); void toggle_waveforms_while_recording ();
void set_summary (); void set_summary ();
void set_edit_group_tabs (); void set_group_tabs ();
void toggle_measure_visibility (); void toggle_measure_visibility ();
void toggle_logo_visibility (); void toggle_logo_visibility ();

View file

@ -810,7 +810,7 @@ Editor::register_actions ()
ActionManager::register_toggle_action (editor_actions, X_("ToggleSummary"), _("Show Summary"), mem_fun (*this, &Editor::set_summary)); ActionManager::register_toggle_action (editor_actions, X_("ToggleSummary"), _("Show Summary"), mem_fun (*this, &Editor::set_summary));
ActionManager::register_toggle_action (editor_actions, X_("ToggleEditGroupTabs"), _("Show Edit Group Tabs"), mem_fun (*this, &Editor::set_edit_group_tabs)); ActionManager::register_toggle_action (editor_actions, X_("ToggleGroupTabs"), _("Show Group Tabs"), mem_fun (*this, &Editor::set_group_tabs));
ActionManager::register_toggle_action (editor_actions, X_("ToggleMeasureVisibility"), _("Show Measures"), mem_fun (*this, &Editor::toggle_measure_visibility)); ActionManager::register_toggle_action (editor_actions, X_("ToggleMeasureVisibility"), _("Show Measures"), mem_fun (*this, &Editor::toggle_measure_visibility));
@ -899,12 +899,12 @@ Editor::set_summary ()
} }
void void
Editor::set_edit_group_tabs () Editor::set_group_tabs ()
{ {
Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleEditGroupTabs")); Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleGroupTabs"));
if (act) { if (act) {
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act); Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
session->config.set_show_edit_group_tabs (tact->get_active ()); session->config.set_show_group_tabs (tact->get_active ());
} }
} }
@ -1302,16 +1302,16 @@ Editor::parameter_changed (std::string p)
tact->set_active (s); tact->set_active (s);
} }
} }
} else if (p == "show-edit-group-tabs") { } else if (p == "show-group-tabs") {
bool const s = session->config.get_show_edit_group_tabs (); bool const s = session->config.get_show_group_tabs ();
if (s) { if (s) {
_group_tabs->show (); _group_tabs->show ();
} else { } else {
_group_tabs->hide (); _group_tabs->hide ();
} }
Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleEditGroupTabs")); Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleGroupTabs"));
if (act) { if (act) {
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act); Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
if (tact->get_active () != s) { if (tact->get_active () != s) {

View file

@ -120,7 +120,7 @@ Editor::show_editor_mixer (bool yn)
current_mixer_strip->set_route (r); current_mixer_strip->set_route (r);
if (created) { if (created) {
current_mixer_strip->set_width (editor_mixer_strip_width, (void*) this); current_mixer_strip->set_width_enum (editor_mixer_strip_width, (void*) this);
} }
} }
@ -213,7 +213,7 @@ Editor::set_selected_mixer_strip (TimeAxisView& view)
} }
if (created) { if (created) {
current_mixer_strip->set_width (editor_mixer_strip_width, (void*) this); current_mixer_strip->set_width_enum (editor_mixer_strip_width, (void*) this);
} }
current_mixer_strip->set_route (at->route()); current_mixer_strip->set_route (at->route());

View file

@ -0,0 +1,146 @@
/*
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.
*/
#include "ardour/route_group.h"
#include "ardour/session.h"
#include "mixer_group_tabs.h"
#include "mixer_strip.h"
#include "mixer_ui.h"
#include "utils.h"
using namespace std;
using namespace ARDOUR;
MixerGroupTabs::MixerGroupTabs (Mixer_UI* m)
: _mixer (m)
{
}
void
MixerGroupTabs::set_session (Session* s)
{
s->RouteMixGroupChanged.connect (mem_fun (*this, &MixerGroupTabs::set_dirty));
}
/** Handle a size request.
* @param req GTK requisition
*/
void
MixerGroupTabs::on_size_request (Gtk::Requisition *req)
{
/* Use a dummy, small width and the actual height that we want */
req->width = 16;
req->height = 16;
}
void
MixerGroupTabs::render (cairo_t* cr)
{
/* background */
cairo_set_source_rgb (cr, 0, 0, 0);
cairo_rectangle (cr, 0, 0, _width, _height);
cairo_fill (cr);
int32_t curr_start = 0;
RouteGroup* curr_group = 0;
Gdk::Color curr_colour;
int32_t x = 0;
for (list<MixerStrip*>::iterator i = _mixer->strips.begin(); i != _mixer->strips.end(); ++i) {
if ((*i)->route()->is_master() || (*i)->route()->is_control()) {
continue;
}
RouteGroup* g = (*i)->mix_group ();
if (g != curr_group) {
if (curr_group) {
draw_group (cr, curr_start, x, curr_group, curr_colour);
}
curr_start = x;
curr_group = g;
curr_colour = (*i)->color ();
}
x += (*i)->get_width ();
}
if (curr_group) {
draw_group (cr, curr_start, x, curr_group, curr_colour);
}
}
void
MixerGroupTabs::draw_group (cairo_t* cr, int32_t x1, int32_t x2, RouteGroup* g, Gdk::Color const & colour)
{
double const arc_radius = _height;
if (g->is_active()) {
cairo_set_source_rgba (cr, colour.get_red_p (), colour.get_green_p (), colour.get_blue_p (), 1);
} else {
cairo_set_source_rgba (cr, 1, 1, 1, 0.2);
}
cairo_arc (cr, x1 + arc_radius, _height, arc_radius, M_PI, 3 * M_PI / 2);
cairo_line_to (cr, x2 - arc_radius, 0);
cairo_arc (cr, x2 - arc_radius, _height, arc_radius, 3 * M_PI / 2, 2 * M_PI);
cairo_line_to (cr, x1, _height);
cairo_fill (cr);
pair<string, double> const f = fit_to_pixels (cr, g->name(), x2 - x1 - arc_radius * 2);
cairo_text_extents_t ext;
cairo_text_extents (cr, g->name().c_str(), &ext);
cairo_set_source_rgb (cr, 1, 1, 1);
cairo_move_to (cr, x1 + (x2 - x1 - f.second) / 2, _height - ext.height / 2);
cairo_save (cr);
cairo_show_text (cr, f.first.c_str());
cairo_restore (cr);
}
bool
MixerGroupTabs::on_button_press_event (GdkEventButton* ev)
{
int32_t x = 0;
list<MixerStrip*>::iterator i = _mixer->strips.begin();
while (x < ev->x && i != _mixer->strips.end()) {
x += (*i)->get_width ();
if (x < ev->x) {
++i;
}
}
if (i == _mixer->strips.end()) {
return false;
}
RouteGroup* g = (*i)->mix_group ();
if (g) {
g->set_active (!g->is_active (), this);
}
return true;
}

View file

@ -0,0 +1,38 @@
/*
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.
*/
#include "cairo_widget.h"
class Mixer_UI;
class MixerGroupTabs : public CairoWidget
{
public:
MixerGroupTabs (Mixer_UI *);
void set_session (ARDOUR::Session *);
private:
void on_size_request (Gtk::Requisition *);
bool on_button_press_event (GdkEventButton *);
void render (cairo_t *);
void draw_group (cairo_t *, int32_t, int32_t, ARDOUR::RouteGroup* , Gdk::Color const &);
Mixer_UI* _mixer;
};

View file

@ -58,6 +58,7 @@
#include "io_selector.h" #include "io_selector.h"
#include "utils.h" #include "utils.h"
#include "gui_thread.h" #include "gui_thread.h"
#include "route_group_dialog.h"
#include "i18n.h" #include "i18n.h"
@ -501,7 +502,7 @@ MixerStrip::set_stuff_from_route ()
/* if width is not set, it will be set by the MixerUI or editor */ /* if width is not set, it will be set by the MixerUI or editor */
if ((prop = xml_node->property ("strip-width")) != 0) { if ((prop = xml_node->property ("strip-width")) != 0) {
set_width (Width (string_2_enum (prop->value(), _width)), this); set_width_enum (Width (string_2_enum (prop->value(), _width)), this);
} }
if ((prop = xml_node->property ("shown-mixer")) != 0) { if ((prop = xml_node->property ("shown-mixer")) != 0) {
@ -517,7 +518,7 @@ MixerStrip::set_stuff_from_route ()
} }
void void
MixerStrip::set_width (Width w, void* owner) MixerStrip::set_width_enum (Width w, void* owner)
{ {
/* always set the gpm width again, things may be hidden */ /* always set the gpm width again, things may be hidden */
@ -952,14 +953,14 @@ void
MixerStrip::input_changed (IOChange change, void *src) MixerStrip::input_changed (IOChange change, void *src)
{ {
Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &MixerStrip::update_input_display)); Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &MixerStrip::update_input_display));
set_width(_width, this); set_width_enum (_width, this);
} }
void void
MixerStrip::output_changed (IOChange change, void *src) MixerStrip::output_changed (IOChange change, void *src)
{ {
Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &MixerStrip::update_output_display)); Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &MixerStrip::update_output_display));
set_width(_width, this); set_width_enum (_width, this);
} }
@ -1099,6 +1100,11 @@ MixerStrip::select_mix_group (GdkEventButton *ev)
case 1: case 1:
items.clear (); items.clear ();
items.push_back (MenuElem (_("New group..."), mem_fun (*this, &MixerStrip::set_mix_group_to_new)));
items.push_back (SeparatorElem ());
items.push_back (RadioMenuElem (group, _("No group"), bind (mem_fun(*this, &MixerStrip::set_mix_group), (RouteGroup *) 0))); items.push_back (RadioMenuElem (group, _("No group"), bind (mem_fun(*this, &MixerStrip::set_mix_group), (RouteGroup *) 0)));
_session.foreach_mix_group (bind (mem_fun (*this, &MixerStrip::add_mix_group_to_menu), &group)); _session.foreach_mix_group (bind (mem_fun (*this, &MixerStrip::add_mix_group_to_menu), &group));
@ -1258,10 +1264,10 @@ MixerStrip::width_clicked ()
{ {
switch (_width) { switch (_width) {
case Wide: case Wide:
set_width (Narrow, this); set_width_enum (Narrow, this);
break; break;
case Narrow: case Narrow:
set_width (Wide, this); set_width_enum (Wide, this);
break; break;
} }
} }
@ -1408,7 +1414,7 @@ MixerStrip::meter_changed (void *src)
gpm.setup_meters (); gpm.setup_meters ();
// reset peak when meter point changes // reset peak when meter point changes
gpm.reset_peak_display(); gpm.reset_peak_display();
set_width(_width, this); set_width_enum (_width, this);
} }
void void
@ -1477,3 +1483,19 @@ MixerStrip::revert_to_default_display ()
panner_ui().setup_pan (); panner_ui().setup_pan ();
} }
void
MixerStrip::set_mix_group_to_new ()
{
RouteGroup* g = new RouteGroup (_session, "", RouteGroup::Active);
g->set_active (true, this);
RouteGroupDialog d (g);
int const r = d.do_run ();
if (r == Gtk::RESPONSE_OK) {
_session.add_mix_group (g);
_route->set_mix_group (g, this);
} else {
delete g;
}
}

View file

@ -84,9 +84,9 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
MixerStrip (Mixer_UI&, ARDOUR::Session&, bool in_mixer = true); MixerStrip (Mixer_UI&, ARDOUR::Session&, bool in_mixer = true);
~MixerStrip (); ~MixerStrip ();
void set_width (Width, void* owner); void set_width_enum (Width, void* owner);
Width get_width() const { return _width; } Width get_width_enum () const { return _width; }
void* width_owner() const { return _width_owner; } void* width_owner () const { return _width_owner; }
GainMeter& gain_meter() { return gpm; } GainMeter& gain_meter() { return gpm; }
PannerUI& panner_ui() { return panners; } PannerUI& panner_ui() { return panners; }
@ -257,6 +257,8 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
boost::shared_ptr<ARDOUR::Delivery> _current_delivery; boost::shared_ptr<ARDOUR::Delivery> _current_delivery;
void revert_to_default_display (); void revert_to_default_display ();
void set_mix_group_to_new ();
static int scrollbar_height; static int scrollbar_height;
}; };

View file

@ -46,6 +46,7 @@
#include "utils.h" #include "utils.h"
#include "actions.h" #include "actions.h"
#include "gui_thread.h" #include "gui_thread.h"
#include "mixer_group_tabs.h"
#include "i18n.h" #include "i18n.h"
@ -81,7 +82,13 @@ Mixer_UI::Mixer_UI ()
// add as last item of strip packer // add as last item of strip packer
strip_packer.pack_end (scroller_base, true, true); strip_packer.pack_end (scroller_base, true, true);
scroller.add (strip_packer); _group_tabs = new MixerGroupTabs (this);
VBox* b = manage (new VBox);
b->pack_start (*_group_tabs, PACK_SHRINK);
b->pack_start (strip_packer);
b->show_all ();
scroller.add (*b);
scroller.set_policy (Gtk::POLICY_ALWAYS, Gtk::POLICY_AUTOMATIC); scroller.set_policy (Gtk::POLICY_ALWAYS, Gtk::POLICY_AUTOMATIC);
track_model = ListStore::create (track_columns); track_model = ListStore::create (track_columns);
@ -281,7 +288,7 @@ Mixer_UI::show_window ()
for (ri = rows.begin(); ri != rows.end(); ++ri) { for (ri = rows.begin(); ri != rows.end(); ++ri) {
ms = (*ri)[track_columns.strip]; ms = (*ri)[track_columns.strip];
ms->set_width (ms->get_width(), ms->width_owner()); ms->set_width_enum (ms->get_width_enum (), ms->width_owner());
} }
} }
_visible = true; _visible = true;
@ -322,7 +329,7 @@ Mixer_UI::add_strip (RouteList& routes)
Config->get_default_narrow_ms() ? _strip_width = Narrow : _strip_width = Wide; Config->get_default_narrow_ms() ? _strip_width = Narrow : _strip_width = Wide;
if (strip->width_owner() != strip) { if (strip->width_owner() != strip) {
strip->set_width (_strip_width, this); strip->set_width_enum (_strip_width, this);
} }
show_strip (strip); show_strip (strip);
@ -463,7 +470,6 @@ Mixer_UI::strip_button_release_event (GdkEventButton *ev, MixerStrip *strip)
void void
Mixer_UI::connect_to_session (Session* sess) Mixer_UI::connect_to_session (Session* sess)
{ {
session = sess; session = sess;
XMLNode* node = ARDOUR_UI::instance()->mixer_settings(); XMLNode* node = ARDOUR_UI::instance()->mixer_settings();
@ -481,6 +487,7 @@ Mixer_UI::connect_to_session (Session* sess)
session->RouteAdded.connect (mem_fun(*this, &Mixer_UI::add_strip)); session->RouteAdded.connect (mem_fun(*this, &Mixer_UI::add_strip));
session->mix_group_added.connect (mem_fun(*this, &Mixer_UI::add_mix_group)); session->mix_group_added.connect (mem_fun(*this, &Mixer_UI::add_mix_group));
session->mix_group_removed.connect (mem_fun(*this, &Mixer_UI::mix_groups_changed)); session->mix_group_removed.connect (mem_fun(*this, &Mixer_UI::mix_groups_changed));
session->config.ParameterChanged.connect (mem_fun (*this, &Mixer_UI::parameter_changed));
mix_groups_changed (); mix_groups_changed ();
@ -490,6 +497,8 @@ Mixer_UI::connect_to_session (Session* sess)
show_window(); show_window();
} }
_group_tabs->set_session (sess);
start_updating (); start_updating ();
} }
@ -768,6 +777,8 @@ Mixer_UI::redisplay_track_list ()
if (auto_rebinding) if (auto_rebinding)
auto_rebind_midi_controls (); auto_rebind_midi_controls ();
_group_tabs->set_dirty ();
} }
#ifdef GTKOSX #ifdef GTKOSX
@ -1296,7 +1307,7 @@ Mixer_UI::set_strip_width (Width w)
_strip_width = w; _strip_width = w;
for (list<MixerStrip*>::iterator i = strips.begin(); i != strips.end(); ++i) { for (list<MixerStrip*>::iterator i = strips.begin(); i != strips.end(); ++i) {
(*i)->set_width (w, this); (*i)->set_width_enum (w, this);
} }
} }
@ -1491,3 +1502,17 @@ Mixer_UI::on_key_press_event (GdkEventKey* ev)
{ {
return key_press_focus_accelerator_handler (*this, ev); return key_press_focus_accelerator_handler (*this, ev);
} }
void
Mixer_UI::parameter_changed (string const & p)
{
if (p == "show-group-tabs") {
bool const s = session->config.get_show_group_tabs ();
if (s) {
_group_tabs->show ();
} else {
_group_tabs->hide ();
}
}
}

View file

@ -48,6 +48,7 @@ namespace ARDOUR {
class MixerStrip; class MixerStrip;
class PluginSelector; class PluginSelector;
class MixerGroupTabs;
class Mixer_UI : public Gtk::Window class Mixer_UI : public Gtk::Window
{ {
@ -105,6 +106,8 @@ class Mixer_UI : public Gtk::Window
Gtk::HBox out_packer; Gtk::HBox out_packer;
Gtk::HPaned list_hpane; Gtk::HPaned list_hpane;
MixerGroupTabs* _group_tabs;
// for restoring window geometry. // for restoring window geometry.
int m_root_x, m_root_y, m_width, m_height; int m_root_x, m_root_y, m_width, m_height;
@ -249,8 +252,12 @@ class Mixer_UI : public Gtk::Window
bool strip_redisplay_does_not_sync_order_keys; bool strip_redisplay_does_not_sync_order_keys;
bool ignore_sync; bool ignore_sync;
void parameter_changed (std::string const &);
static const int32_t default_width = 478; static const int32_t default_width = 478;
static const int32_t default_height = 765; static const int32_t default_height = 765;
friend class MixerGroupTabs;
}; };
#endif /* __ardour_mixer_ui_h__ */ #endif /* __ardour_mixer_ui_h__ */

View file

@ -159,6 +159,7 @@ def build(bld):
midi_scroomer.cc midi_scroomer.cc
midi_streamview.cc midi_streamview.cc
midi_time_axis.cc midi_time_axis.cc
mixer_group_tabs.cc
mixer_strip.cc mixer_strip.cc
mixer_ui.cc mixer_ui.cc
nag.cc nag.cc

View file

@ -378,6 +378,7 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
sigc::signal<void,RouteList&> RouteAdded; sigc::signal<void,RouteList&> RouteAdded;
sigc::signal<void> RouteEditGroupChanged; sigc::signal<void> RouteEditGroupChanged;
sigc::signal<void> RouteMixGroupChanged;
void request_roll_at_and_return (nframes_t start, nframes_t return_to); void request_roll_at_and_return (nframes_t start, nframes_t return_to);
void request_bounded_roll (nframes_t start, nframes_t end); void request_bounded_roll (nframes_t start, nframes_t end);
@ -1489,6 +1490,7 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
int load_regions (const XMLNode& node); int load_regions (const XMLNode& node);
void route_edit_group_changed (); void route_edit_group_changed ();
void route_mix_group_changed ();
/* SOURCES */ /* SOURCES */

View file

@ -46,4 +46,4 @@ CONFIG_VARIABLE (bool, jack_time_master, "jack-time-master", true)
CONFIG_VARIABLE (bool, use_video_sync, "use-video-sync", false) CONFIG_VARIABLE (bool, use_video_sync, "use-video-sync", false)
CONFIG_VARIABLE (float, video_pullup, "video-pullup", 0.0f) CONFIG_VARIABLE (float, video_pullup, "video-pullup", 0.0f)
CONFIG_VARIABLE (bool, show_summary, "show-summary", true) CONFIG_VARIABLE (bool, show_summary, "show-summary", true)
CONFIG_VARIABLE (bool, show_edit_group_tabs, "show-edit-group-tabs", true) CONFIG_VARIABLE (bool, show_group_tabs, "show-group-tabs", true)

View file

@ -2004,7 +2004,6 @@ Route::drop_edit_group (void *src)
void void
Route::set_mix_group (RouteGroup *mg, void *src) Route::set_mix_group (RouteGroup *mg, void *src)
{ {
if (mg == _mix_group) { if (mg == _mix_group) {
return; return;

View file

@ -2083,6 +2083,7 @@ Session::add_routes (RouteList& new_routes, bool save)
(*x)->output()->changed.connect (mem_fun (*this, &Session::set_worst_io_latencies_x)); (*x)->output()->changed.connect (mem_fun (*this, &Session::set_worst_io_latencies_x));
(*x)->processors_changed.connect (bind (mem_fun (*this, &Session::update_latency_compensation), false, false)); (*x)->processors_changed.connect (bind (mem_fun (*this, &Session::update_latency_compensation), false, false));
(*x)->edit_group_changed.connect (hide (mem_fun (*this, &Session::route_edit_group_changed))); (*x)->edit_group_changed.connect (hide (mem_fun (*this, &Session::route_edit_group_changed)));
(*x)->mix_group_changed.connect (hide (mem_fun (*this, &Session::route_mix_group_changed)));
if ((*x)->is_master()) { if ((*x)->is_master()) {
_master_out = (*x); _master_out = (*x);
@ -4254,3 +4255,9 @@ Session::route_edit_group_changed ()
{ {
RouteEditGroupChanged (); /* EMIT SIGNAL */ RouteEditGroupChanged (); /* EMIT SIGNAL */
} }
void
Session::route_mix_group_changed ()
{
RouteMixGroupChanged (); /* EMIT SIGNAL */
}