mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 23:35:03 +01:00
partial patch/partial by-hand merge of 2.X commits 3169&3170 to 3.X codebase
git-svn-id: svn://localhost/ardour2/branches/3.0@4300 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
a9bb336fc4
commit
3be16e8afb
35 changed files with 1399 additions and 932 deletions
|
|
@ -194,6 +194,7 @@ lineset.cc
|
||||||
location_ui.cc
|
location_ui.cc
|
||||||
main.cc
|
main.cc
|
||||||
marker.cc
|
marker.cc
|
||||||
|
matrix.cc
|
||||||
midi_channel_selector.cc
|
midi_channel_selector.cc
|
||||||
midi_port_dialog.cc
|
midi_port_dialog.cc
|
||||||
midi_region_view.cc
|
midi_region_view.cc
|
||||||
|
|
|
||||||
|
|
@ -1736,8 +1736,8 @@ ARDOUR_UI::engine_halted ()
|
||||||
_("\
|
_("\
|
||||||
JACK has either been shutdown or it\n\
|
JACK has either been shutdown or it\n\
|
||||||
disconnected Ardour because Ardour\n\
|
disconnected Ardour because Ardour\n\
|
||||||
was not fast enough. You can save the\n\
|
was not fast enough. Try to restart\n\
|
||||||
session and/or try to reconnect to JACK ."));
|
JACK, reconnect and save the session."));
|
||||||
pop_back_splash ();
|
pop_back_splash ();
|
||||||
msg.run ();
|
msg.run ();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -196,6 +196,10 @@ AudioRegionView::init (Gdk::Color& basic_color, bool wfd)
|
||||||
|
|
||||||
setup_fade_handle_positions ();
|
setup_fade_handle_positions ();
|
||||||
|
|
||||||
|
if (!Config->get_show_region_fades()) {
|
||||||
|
set_fade_visibility (false);
|
||||||
|
}
|
||||||
|
|
||||||
string line_name = _region->name();
|
string line_name = _region->name();
|
||||||
line_name += ':';
|
line_name += ':';
|
||||||
line_name += "gain";
|
line_name += "gain";
|
||||||
|
|
@ -410,8 +414,10 @@ AudioRegionView::reset_width_dependent_items (double pixel_width)
|
||||||
fade_in_handle->hide();
|
fade_in_handle->hide();
|
||||||
fade_out_handle->hide();
|
fade_out_handle->hide();
|
||||||
} else {
|
} else {
|
||||||
fade_in_handle->show();
|
if (Config->get_show_region_fades()) {
|
||||||
fade_out_handle->show();
|
fade_in_handle->show();
|
||||||
|
fade_out_handle->show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -294,6 +294,7 @@ class Editor : public PublicEditor
|
||||||
Width editor_mixer_strip_width;
|
Width editor_mixer_strip_width;
|
||||||
void maybe_add_mixer_strip_width (XMLNode&);
|
void maybe_add_mixer_strip_width (XMLNode&);
|
||||||
void show_editor_mixer (bool yn);
|
void show_editor_mixer (bool yn);
|
||||||
|
void create_editor_mixer ();
|
||||||
void show_editor_list (bool yn);
|
void show_editor_list (bool yn);
|
||||||
void set_selected_mixer_strip (TimeAxisView&);
|
void set_selected_mixer_strip (TimeAxisView&);
|
||||||
void hide_track_in_display (TimeAxisView& tv, bool temporary = false);
|
void hide_track_in_display (TimeAxisView& tv, bool temporary = false);
|
||||||
|
|
|
||||||
|
|
@ -57,13 +57,6 @@ Editor::editor_list_button_toggled ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Editor::cms_new (boost::shared_ptr<ARDOUR::Route> r)
|
|
||||||
{
|
|
||||||
current_mixer_strip = new MixerStrip (*ARDOUR_UI::instance()->the_mixer(), *session, r);
|
|
||||||
current_mixer_strip->GoingAway.connect (mem_fun (*this, &Editor::cms_deleted));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Editor::cms_deleted ()
|
Editor::cms_deleted ()
|
||||||
{
|
{
|
||||||
|
|
@ -73,75 +66,107 @@ Editor::cms_deleted ()
|
||||||
void
|
void
|
||||||
Editor::show_editor_mixer (bool yn)
|
Editor::show_editor_mixer (bool yn)
|
||||||
{
|
{
|
||||||
|
boost::shared_ptr<ARDOUR::Route> r;
|
||||||
|
|
||||||
show_editor_mixer_when_tracks_arrive = false;
|
show_editor_mixer_when_tracks_arrive = false;
|
||||||
|
|
||||||
|
if (!session) {
|
||||||
|
show_editor_mixer_when_tracks_arrive = yn;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (yn) {
|
if (yn) {
|
||||||
|
|
||||||
if (current_mixer_strip == 0) {
|
if (selection->tracks.empty()) {
|
||||||
|
|
||||||
if (selection->tracks.empty()) {
|
|
||||||
|
|
||||||
if (track_views.empty()) {
|
|
||||||
show_editor_mixer_when_tracks_arrive = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
|
||||||
AudioTimeAxisView* atv;
|
|
||||||
|
|
||||||
if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
|
|
||||||
cms_new (atv->route ());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
sort_track_selection ();
|
|
||||||
|
|
||||||
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
|
|
||||||
AudioTimeAxisView* atv;
|
|
||||||
|
|
||||||
if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
|
|
||||||
cms_new (atv->route ());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (track_views.empty()) {
|
||||||
|
show_editor_mixer_when_tracks_arrive = true;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
||||||
|
AudioTimeAxisView* atv;
|
||||||
|
|
||||||
|
if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
|
||||||
|
r = atv->route();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
sort_track_selection ();
|
||||||
|
|
||||||
|
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
|
||||||
|
AudioTimeAxisView* atv;
|
||||||
|
|
||||||
|
if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
|
||||||
|
r = atv->route();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r) {
|
||||||
|
bool created;
|
||||||
|
|
||||||
if (current_mixer_strip == 0) {
|
if (current_mixer_strip == 0) {
|
||||||
return;
|
create_editor_mixer ();
|
||||||
|
created = true;
|
||||||
|
} else {
|
||||||
|
created = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_mixer_strip->set_route (r);
|
||||||
|
|
||||||
|
if (created) {
|
||||||
|
current_mixer_strip->set_width (editor_mixer_strip_width, (void*) this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_mixer_strip->get_parent() == 0) {
|
if (current_mixer_strip->get_parent() == 0) {
|
||||||
current_mixer_strip->set_embedded (true);
|
|
||||||
current_mixer_strip->Hiding.connect (mem_fun(*this, &Editor::current_mixer_strip_hidden));
|
|
||||||
current_mixer_strip->GoingAway.connect (mem_fun(*this, &Editor::current_mixer_strip_removed));
|
|
||||||
current_mixer_strip->set_width (editor_mixer_strip_width, (void*) this);
|
|
||||||
|
|
||||||
global_hpacker.pack_start (*current_mixer_strip, Gtk::PACK_SHRINK );
|
global_hpacker.pack_start (*current_mixer_strip, Gtk::PACK_SHRINK );
|
||||||
global_hpacker.reorder_child (*current_mixer_strip, 0);
|
global_hpacker.reorder_child (*current_mixer_strip, 0);
|
||||||
|
|
||||||
current_mixer_strip->show_all ();
|
current_mixer_strip->show_all ();
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (current_mixer_strip) {
|
if (current_mixer_strip) {
|
||||||
editor_mixer_strip_width = current_mixer_strip->get_width ();
|
|
||||||
if (current_mixer_strip->get_parent() != 0) {
|
if (current_mixer_strip->get_parent() != 0) {
|
||||||
global_hpacker.remove (*current_mixer_strip);
|
global_hpacker.remove (*current_mixer_strip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GTKOSX
|
#ifdef GTKOSX
|
||||||
/* XXX gtk problem here */
|
/* XXX gtk problem here */
|
||||||
|
ensure_all_elements_drawn();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef GTKOSX
|
||||||
|
void
|
||||||
|
Editor::ensure_all_elements_drawn ()
|
||||||
|
{
|
||||||
|
controls_layout.queue_draw ();
|
||||||
ruler_label_event_box.queue_draw ();
|
ruler_label_event_box.queue_draw ();
|
||||||
time_button_event_box.queue_draw ();
|
time_button_event_box.queue_draw ();
|
||||||
controls_layout.queue_draw ();
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
Editor::create_editor_mixer ()
|
||||||
|
{
|
||||||
|
current_mixer_strip = new MixerStrip (*ARDOUR_UI::instance()->the_mixer(),
|
||||||
|
*session,
|
||||||
|
false);
|
||||||
|
current_mixer_strip->Hiding.connect (mem_fun(*this, &Editor::current_mixer_strip_hidden));
|
||||||
|
current_mixer_strip->GoingAway.connect (mem_fun(*this, &Editor::current_mixer_strip_removed));
|
||||||
|
#ifdef GTKOSX
|
||||||
|
current_mixer_strip->WidthChanged.connect (mem_fun(*this, &Editor::ensure_all_elements_drawn));
|
||||||
|
#endif
|
||||||
|
current_mixer_strip->set_embedded (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -157,38 +182,52 @@ Editor::show_editor_list (bool yn)
|
||||||
void
|
void
|
||||||
Editor::set_selected_mixer_strip (TimeAxisView& view)
|
Editor::set_selected_mixer_strip (TimeAxisView& view)
|
||||||
{
|
{
|
||||||
RouteTimeAxisView* rt;
|
AudioTimeAxisView* at;
|
||||||
bool show = false;
|
bool show = false;
|
||||||
|
bool created;
|
||||||
|
|
||||||
if (!session || (rt = dynamic_cast<RouteTimeAxisView*>(&view)) == 0) {
|
if (!session || (at = dynamic_cast<AudioTimeAxisView*>(&view)) == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_mixer_strip) {
|
Glib::RefPtr<Gtk::Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
|
||||||
|
if (act) {
|
||||||
/* might be nothing to do */
|
Glib::RefPtr<Gtk::ToggleAction> tact = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(act);
|
||||||
|
if (!tact || !tact->get_active()) {
|
||||||
if (current_mixer_strip->route() == rt->route()) {
|
/* not showing mixer strip presently */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_mixer_strip->get_parent()) {
|
|
||||||
show = true;
|
|
||||||
}
|
|
||||||
delete current_mixer_strip;
|
|
||||||
current_mixer_strip = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
current_mixer_strip = new MixerStrip (*ARDOUR_UI::instance()->the_mixer(),
|
if (current_mixer_strip == 0) {
|
||||||
*session,
|
create_editor_mixer ();
|
||||||
rt->route(), false);
|
created = true;
|
||||||
current_mixer_strip->GoingAway.connect (mem_fun(*this, &Editor::cms_deleted));
|
} else {
|
||||||
|
created = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* might be nothing to do */
|
||||||
|
|
||||||
|
if (current_mixer_strip->route() == at->route()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_mixer_strip->get_parent()) {
|
||||||
|
show = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_mixer_strip->set_route (at->route());
|
||||||
|
|
||||||
|
if (created) {
|
||||||
|
current_mixer_strip->set_width (editor_mixer_strip_width, (void*) this);
|
||||||
|
}
|
||||||
|
|
||||||
if (show) {
|
if (show) {
|
||||||
show_editor_mixer (true);
|
show_editor_mixer (true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
double current = 0.0;
|
double current = 0.0;
|
||||||
bool currentInitialized = 0;
|
bool currentInitialized = 0;
|
||||||
|
|
||||||
|
|
@ -276,7 +315,7 @@ void
|
||||||
Editor::current_mixer_strip_removed ()
|
Editor::current_mixer_strip_removed ()
|
||||||
{
|
{
|
||||||
if (current_mixer_strip) {
|
if (current_mixer_strip) {
|
||||||
/* it is being deleted */
|
/* it is being deleted elsewhere */
|
||||||
current_mixer_strip = 0;
|
current_mixer_strip = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,17 +72,18 @@ GainMeter::setup_slider_pix ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GainMeterBase::GainMeterBase (boost::shared_ptr<IO> io, Session& s,
|
GainMeterBase::GainMeterBase (Session& s,
|
||||||
const Glib::RefPtr<Gdk::Pixbuf>& pix,
|
const Glib::RefPtr<Gdk::Pixbuf>& pix,
|
||||||
bool horizontal)
|
bool horizontal)
|
||||||
: _io (io),
|
: _session (s),
|
||||||
_session (s),
|
|
||||||
// 0.781787 is the value needed for gain to be set to 0.
|
// 0.781787 is the value needed for gain to be set to 0.
|
||||||
gain_adjustment (0.781787, 0.0, 1.0, 0.01, 0.1),
|
gain_adjustment (0.781787, 0.0, 1.0, 0.01, 0.1),
|
||||||
gain_automation_style_button (""),
|
gain_automation_style_button (""),
|
||||||
gain_automation_state_button ("")
|
gain_automation_state_button ("")
|
||||||
|
|
||||||
{
|
{
|
||||||
|
using namespace Menu_Helpers;
|
||||||
|
|
||||||
ignore_toggle = false;
|
ignore_toggle = false;
|
||||||
meter_menu = 0;
|
meter_menu = 0;
|
||||||
next_release_selects = false;
|
next_release_selects = false;
|
||||||
|
|
@ -92,16 +93,14 @@ GainMeterBase::GainMeterBase (boost::shared_ptr<IO> io, Session& s,
|
||||||
if (horizontal) {
|
if (horizontal) {
|
||||||
gain_slider = manage (new HSliderController (pix,
|
gain_slider = manage (new HSliderController (pix,
|
||||||
&gain_adjustment,
|
&gain_adjustment,
|
||||||
_io->gain_control(),
|
|
||||||
false));
|
false));
|
||||||
} else {
|
} else {
|
||||||
gain_slider = manage (new VSliderController (pix,
|
gain_slider = manage (new VSliderController (pix,
|
||||||
&gain_adjustment,
|
&gain_adjustment,
|
||||||
_io->gain_control(),
|
|
||||||
false));
|
false));
|
||||||
}
|
}
|
||||||
|
|
||||||
level_meter = new LevelMeter(_io, _session);
|
level_meter = new LevelMeter(_session);
|
||||||
|
|
||||||
gain_slider->signal_button_press_event().connect (mem_fun(*this, &GainMeter::start_gain_touch));
|
gain_slider->signal_button_press_event().connect (mem_fun(*this, &GainMeter::start_gain_touch));
|
||||||
gain_slider->signal_button_release_event().connect (mem_fun(*this, &GainMeter::end_gain_touch));
|
gain_slider->signal_button_release_event().connect (mem_fun(*this, &GainMeter::end_gain_touch));
|
||||||
|
|
@ -134,9 +133,39 @@ GainMeterBase::GainMeterBase (boost::shared_ptr<IO> io, Session& s,
|
||||||
gain_automation_state_button.set_size_request(15, 15);
|
gain_automation_state_button.set_size_request(15, 15);
|
||||||
gain_automation_style_button.set_size_request(15, 15);
|
gain_automation_style_button.set_size_request(15, 15);
|
||||||
|
|
||||||
|
gain_astyle_menu.items().push_back (MenuElem (_("Trim")));
|
||||||
|
gain_astyle_menu.items().push_back (MenuElem (_("Abs")));
|
||||||
|
|
||||||
|
gain_astate_menu.set_name ("ArdourContextMenu");
|
||||||
|
gain_astyle_menu.set_name ("ArdourContextMenu");
|
||||||
|
|
||||||
|
gain_adjustment.signal_value_changed().connect (mem_fun(*this, &GainMeterBase::gain_adjusted));
|
||||||
|
peak_display.signal_button_release_event().connect (mem_fun(*this, &GainMeterBase::peak_button_release), false);
|
||||||
|
gain_display.signal_key_press_event().connect (mem_fun(*this, &GainMeterBase::gain_key_press), false);
|
||||||
|
|
||||||
|
ResetAllPeakDisplays.connect (mem_fun(*this, &GainMeterBase::reset_peak_display));
|
||||||
|
ResetGroupPeakDisplays.connect (mem_fun(*this, &GainMeterBase::reset_group_peak_display));
|
||||||
|
|
||||||
|
UI::instance()->theme_changed.connect (mem_fun(*this, &GainMeterBase::on_theme_changed));
|
||||||
|
ColorsChanged.connect (bind(mem_fun (*this, &GainMeterBase::color_handler), false));
|
||||||
|
DPIReset.connect (bind(mem_fun (*this, &GainMeterBase::color_handler), true));
|
||||||
|
}
|
||||||
|
|
||||||
|
GainMeterBase::~GainMeterBase ()
|
||||||
|
{
|
||||||
|
delete meter_menu;
|
||||||
|
delete level_meter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GainMeterBase::set_io (boost::shared_ptr<IO> io)
|
||||||
|
{
|
||||||
|
connections.clear ();
|
||||||
|
|
||||||
|
_io = io;
|
||||||
|
|
||||||
|
level_meter->set_io (_io);
|
||||||
|
gain_slider->set_controllable (_io->gain_control());
|
||||||
|
|
||||||
boost::shared_ptr<Route> r;
|
boost::shared_ptr<Route> r;
|
||||||
|
|
||||||
|
|
@ -146,6 +175,8 @@ GainMeterBase::GainMeterBase (boost::shared_ptr<IO> io, Session& s,
|
||||||
|
|
||||||
using namespace Menu_Helpers;
|
using namespace Menu_Helpers;
|
||||||
|
|
||||||
|
gain_astate_menu.items().clear ();
|
||||||
|
|
||||||
gain_astate_menu.items().push_back (MenuElem (_("Manual"),
|
gain_astate_menu.items().push_back (MenuElem (_("Manual"),
|
||||||
bind (mem_fun (*_io, &IO::set_parameter_automation_state),
|
bind (mem_fun (*_io, &IO::set_parameter_automation_state),
|
||||||
Evoral::Parameter(GainAutomation), (AutoState) Off)));
|
Evoral::Parameter(GainAutomation), (AutoState) Off)));
|
||||||
|
|
@ -159,50 +190,21 @@ GainMeterBase::GainMeterBase (boost::shared_ptr<IO> io, Session& s,
|
||||||
bind (mem_fun (*_io, &IO::set_parameter_automation_state),
|
bind (mem_fun (*_io, &IO::set_parameter_automation_state),
|
||||||
Evoral::Parameter(GainAutomation), (AutoState) Touch)));
|
Evoral::Parameter(GainAutomation), (AutoState) Touch)));
|
||||||
|
|
||||||
gain_astyle_menu.items().push_back (MenuElem (_("Trim")));
|
connections.push_back (gain_automation_style_button.signal_button_press_event().connect (mem_fun(*this, &GainMeterBase::gain_automation_style_button_event), false));
|
||||||
gain_astyle_menu.items().push_back (MenuElem (_("Abs")));
|
connections.push_back (gain_automation_state_button.signal_button_press_event().connect (mem_fun(*this, &GainMeterBase::gain_automation_state_button_event), false));
|
||||||
|
|
||||||
gain_astate_menu.set_name ("ArdourContextMenu");
|
connections.push_back (r->gain_control()->alist()->automation_state_changed.connect (mem_fun(*this, &GainMeter::gain_automation_state_changed)));
|
||||||
gain_astyle_menu.set_name ("ArdourContextMenu");
|
connections.push_back (r->gain_control()->alist()->automation_style_changed.connect (mem_fun(*this, &GainMeter::gain_automation_style_changed)));
|
||||||
|
|
||||||
gain_automation_style_button.signal_button_press_event().connect (mem_fun(*this, &GainMeterBase::gain_automation_style_button_event), false);
|
|
||||||
gain_automation_state_button.signal_button_press_event().connect (mem_fun(*this, &GainMeterBase::gain_automation_state_button_event), false);
|
|
||||||
|
|
||||||
r->gain_control()->alist()->automation_state_changed.connect (mem_fun(*this, &GainMeter::gain_automation_state_changed));
|
|
||||||
r->gain_control()->alist()->automation_style_changed.connect (mem_fun(*this, &GainMeter::gain_automation_style_changed));
|
|
||||||
|
|
||||||
gain_automation_state_changed ();
|
gain_automation_state_changed ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_io->gain_control()->Changed.connect (mem_fun(*this, &GainMeterBase::gain_changed));
|
connections.push_back (_io->gain_control()->Changed.connect (mem_fun(*this, &GainMeterBase::gain_changed)));
|
||||||
|
|
||||||
gain_adjustment.signal_value_changed().connect (mem_fun(*this, &GainMeterBase::gain_adjusted));
|
|
||||||
peak_display.signal_button_release_event().connect (mem_fun(*this, &GainMeterBase::peak_button_release), false);
|
|
||||||
gain_display.signal_key_press_event().connect (mem_fun(*this, &GainMeterBase::gain_key_press), false);
|
|
||||||
|
|
||||||
gain_changed ();
|
gain_changed ();
|
||||||
show_gain ();
|
show_gain ();
|
||||||
|
|
||||||
update_gain_sensitive ();
|
update_gain_sensitive ();
|
||||||
|
|
||||||
ResetAllPeakDisplays.connect (mem_fun(*this, &GainMeterBase::reset_peak_display));
|
|
||||||
ResetGroupPeakDisplays.connect (mem_fun(*this, &GainMeterBase::reset_group_peak_display));
|
|
||||||
|
|
||||||
UI::instance()->theme_changed.connect (mem_fun(*this, &GainMeterBase::on_theme_changed));
|
|
||||||
ColorsChanged.connect (bind(mem_fun (*this, &GainMeterBase::color_handler), false));
|
|
||||||
DPIReset.connect (bind(mem_fun (*this, &GainMeterBase::color_handler), true));
|
|
||||||
}
|
|
||||||
|
|
||||||
GainMeterBase::~GainMeterBase ()
|
|
||||||
{
|
|
||||||
if (meter_menu) {
|
|
||||||
delete meter_menu;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (level_meter) {
|
|
||||||
delete level_meter;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -752,10 +754,9 @@ GainMeterBase::on_theme_changed()
|
||||||
style_changed = true;
|
style_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GainMeter::GainMeter (boost::shared_ptr<IO> io, Session& s)
|
GainMeter::GainMeter (Session& s)
|
||||||
: GainMeterBase (io, s, slider, false)
|
: GainMeterBase (s, slider, false)
|
||||||
{
|
{
|
||||||
|
|
||||||
gain_display_box.set_homogeneous (true);
|
gain_display_box.set_homogeneous (true);
|
||||||
gain_display_box.set_spacing (2);
|
gain_display_box.set_spacing (2);
|
||||||
gain_display_box.pack_start (gain_display, true, true);
|
gain_display_box.pack_start (gain_display, true, true);
|
||||||
|
|
@ -785,6 +786,31 @@ GainMeter::GainMeter (boost::shared_ptr<IO> io, Session& s)
|
||||||
hbox.set_spacing (2);
|
hbox.set_spacing (2);
|
||||||
hbox.pack_start (*fader_vbox, true, true);
|
hbox.pack_start (*fader_vbox, true, true);
|
||||||
|
|
||||||
|
set_spacing (2);
|
||||||
|
|
||||||
|
pack_start (gain_display_box, Gtk::PACK_SHRINK);
|
||||||
|
pack_start (hbox, Gtk::PACK_SHRINK);
|
||||||
|
|
||||||
|
meter_metric_area.signal_expose_event().connect (mem_fun(*this, &GainMeter::meter_metrics_expose));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GainMeter::set_io (boost::shared_ptr<IO> io)
|
||||||
|
{
|
||||||
|
if (level_meter->get_parent()) {
|
||||||
|
hbox.remove (*level_meter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (peak_display.get_parent()) {
|
||||||
|
gain_display_box.remove (peak_display);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gain_automation_state_button.get_parent()) {
|
||||||
|
fader_vbox->remove (gain_automation_state_button);
|
||||||
|
}
|
||||||
|
|
||||||
|
GainMeterBase::set_io (io);
|
||||||
|
|
||||||
boost::shared_ptr<Route> r;
|
boost::shared_ptr<Route> r;
|
||||||
|
|
||||||
if ((r = boost::dynamic_pointer_cast<Route> (_io)) != 0) {
|
if ((r = boost::dynamic_pointer_cast<Route> (_io)) != 0) {
|
||||||
|
|
@ -801,16 +827,8 @@ GainMeter::GainMeter (boost::shared_ptr<IO> io, Session& s)
|
||||||
fader_vbox->pack_start (gain_automation_state_button, false, false, 0);
|
fader_vbox->pack_start (gain_automation_state_button, false, false, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set_spacing (2);
|
|
||||||
|
|
||||||
pack_start (gain_display_box, Gtk::PACK_SHRINK);
|
|
||||||
pack_start (hbox, Gtk::PACK_SHRINK);
|
|
||||||
|
|
||||||
meter_metric_area.signal_expose_event().connect (mem_fun(*this, &GainMeter::meter_metrics_expose));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
GainMeter::get_gm_width ()
|
GainMeter::get_gm_width ()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -58,10 +58,12 @@ namespace Gtk {
|
||||||
class GainMeterBase : virtual public sigc::trackable
|
class GainMeterBase : virtual public sigc::trackable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GainMeterBase (boost::shared_ptr<ARDOUR::IO>, ARDOUR::Session&, const Glib::RefPtr<Gdk::Pixbuf>& pix,
|
GainMeterBase ( ARDOUR::Session&, const Glib::RefPtr<Gdk::Pixbuf>& pix,
|
||||||
bool horizontal);
|
bool horizontal);
|
||||||
virtual ~GainMeterBase ();
|
virtual ~GainMeterBase ();
|
||||||
|
|
||||||
|
virtual void set_io (boost::shared_ptr<ARDOUR::IO>);
|
||||||
|
|
||||||
void update_gain_sensitive ();
|
void update_gain_sensitive ();
|
||||||
void update_meters ();
|
void update_meters ();
|
||||||
|
|
||||||
|
|
@ -82,6 +84,7 @@ class GainMeterBase : virtual public sigc::trackable
|
||||||
friend class MixerStrip;
|
friend class MixerStrip;
|
||||||
boost::shared_ptr<ARDOUR::IO> _io;
|
boost::shared_ptr<ARDOUR::IO> _io;
|
||||||
ARDOUR::Session& _session;
|
ARDOUR::Session& _session;
|
||||||
|
std::vector<sigc::connection> connections;
|
||||||
|
|
||||||
bool ignore_toggle;
|
bool ignore_toggle;
|
||||||
bool next_release_selects;
|
bool next_release_selects;
|
||||||
|
|
@ -169,9 +172,11 @@ class GainMeterBase : virtual public sigc::trackable
|
||||||
class GainMeter : public GainMeterBase, public Gtk::VBox
|
class GainMeter : public GainMeterBase, public Gtk::VBox
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GainMeter (boost::shared_ptr<ARDOUR::IO>, ARDOUR::Session&);
|
GainMeter (ARDOUR::Session&);
|
||||||
~GainMeter () {}
|
~GainMeter () {}
|
||||||
|
|
||||||
|
void set_io (boost::shared_ptr<ARDOUR::IO>);
|
||||||
|
|
||||||
int get_gm_width ();
|
int get_gm_width ();
|
||||||
void setup_meters (int len=0);
|
void setup_meters (int len=0);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,9 +58,8 @@ using namespace std;
|
||||||
//sigc::signal<void,RouteGroup*> LevelMeter::ResetGroupPeakDisplays;
|
//sigc::signal<void,RouteGroup*> LevelMeter::ResetGroupPeakDisplays;
|
||||||
|
|
||||||
|
|
||||||
LevelMeter::LevelMeter (boost::shared_ptr<IO> io, Session& s)
|
LevelMeter::LevelMeter (Session& s)
|
||||||
: _io (io),
|
: _session (s)
|
||||||
_session (s)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
set_spacing (1);
|
set_spacing (1);
|
||||||
|
|
@ -85,6 +84,12 @@ LevelMeter::~LevelMeter ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LevelMeter::set_io (boost::shared_ptr<IO> io)
|
||||||
|
{
|
||||||
|
_io = io;
|
||||||
|
}
|
||||||
|
|
||||||
float
|
float
|
||||||
LevelMeter::update_meters ()
|
LevelMeter::update_meters ()
|
||||||
{
|
{
|
||||||
|
|
@ -144,6 +149,10 @@ LevelMeter::hide_all_meters ()
|
||||||
void
|
void
|
||||||
LevelMeter::setup_meters (int len, int initial_width)
|
LevelMeter::setup_meters (int len, int initial_width)
|
||||||
{
|
{
|
||||||
|
if (!_io) {
|
||||||
|
return; /* do it later */
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t nmeters = _io->n_outputs().n_total();
|
uint32_t nmeters = _io->n_outputs().n_total();
|
||||||
regular_meter_width = initial_width;
|
regular_meter_width = initial_width;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,9 +56,11 @@ namespace Gtk {
|
||||||
class LevelMeter : public Gtk::HBox
|
class LevelMeter : public Gtk::HBox
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LevelMeter (boost::shared_ptr<ARDOUR::IO>, ARDOUR::Session&);
|
LevelMeter (ARDOUR::Session&);
|
||||||
~LevelMeter ();
|
~LevelMeter ();
|
||||||
|
|
||||||
|
virtual void set_io (boost::shared_ptr<ARDOUR::IO> io);
|
||||||
|
|
||||||
void update_gain_sensitive ();
|
void update_gain_sensitive ();
|
||||||
|
|
||||||
float update_meters ();
|
float update_meters ();
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,10 @@ fixup_bundle_environment ()
|
||||||
Glib::ustring path;
|
Glib::ustring path;
|
||||||
const char *cstr = getenv ("PATH");
|
const char *cstr = getenv ("PATH");
|
||||||
|
|
||||||
/* ensure that we find any bundled executables (e.g. JACK) */
|
/* ensure that we find any bundled executables (e.g. JACK),
|
||||||
|
and find them before any instances of the same name
|
||||||
|
elsewhere in PATH
|
||||||
|
*/
|
||||||
|
|
||||||
path = dir_path;
|
path = dir_path;
|
||||||
if (cstr) {
|
if (cstr) {
|
||||||
|
|
@ -152,8 +155,10 @@ fixup_bundle_environment ()
|
||||||
if (cstr) {
|
if (cstr) {
|
||||||
path = cstr;
|
path = cstr;
|
||||||
path += ':';
|
path += ':';
|
||||||
|
} else {
|
||||||
|
path = "";
|
||||||
}
|
}
|
||||||
path = dir_path;
|
path += dir_path;
|
||||||
path += "/../Plugins";
|
path += "/../Plugins";
|
||||||
|
|
||||||
setenv ("LADSPA_PATH", path.c_str(), 1);
|
setenv ("LADSPA_PATH", path.c_str(), 1);
|
||||||
|
|
@ -162,8 +167,10 @@ fixup_bundle_environment ()
|
||||||
if (cstr) {
|
if (cstr) {
|
||||||
path = cstr;
|
path = cstr;
|
||||||
path += ':';
|
path += ':';
|
||||||
|
} else {
|
||||||
|
path = "";
|
||||||
}
|
}
|
||||||
path = dir_path;
|
path += dir_path;
|
||||||
path += "/../Frameworks";
|
path += "/../Frameworks";
|
||||||
|
|
||||||
setenv ("VAMP_PATH", path.c_str(), 1);
|
setenv ("VAMP_PATH", path.c_str(), 1);
|
||||||
|
|
@ -172,8 +179,10 @@ fixup_bundle_environment ()
|
||||||
if (cstr) {
|
if (cstr) {
|
||||||
path = cstr;
|
path = cstr;
|
||||||
path += ':';
|
path += ':';
|
||||||
|
} else {
|
||||||
|
path = "";
|
||||||
}
|
}
|
||||||
path = dir_path;
|
path += dir_path;
|
||||||
path += "/../Surfaces";
|
path += "/../Surfaces";
|
||||||
|
|
||||||
setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
|
setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
|
||||||
|
|
@ -182,8 +191,10 @@ fixup_bundle_environment ()
|
||||||
if (cstr) {
|
if (cstr) {
|
||||||
path = cstr;
|
path = cstr;
|
||||||
path += ':';
|
path += ':';
|
||||||
|
} else {
|
||||||
|
path = "";
|
||||||
}
|
}
|
||||||
path = dir_path;
|
path += dir_path;
|
||||||
path += "/../Plugins";
|
path += "/../Plugins";
|
||||||
|
|
||||||
setenv ("LV2_PATH", path.c_str(), 1);
|
setenv ("LV2_PATH", path.c_str(), 1);
|
||||||
|
|
|
||||||
427
gtk2_ardour/matrix.cc
Normal file
427
gtk2_ardour/matrix.cc
Normal file
|
|
@ -0,0 +1,427 @@
|
||||||
|
#include <gtkmm.h>
|
||||||
|
#include <cairo/cairo.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <cmath>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "matrix.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace Gtk;
|
||||||
|
using namespace ARDOUR;
|
||||||
|
|
||||||
|
Matrix::Matrix ()
|
||||||
|
{
|
||||||
|
alloc_width = 0;
|
||||||
|
alloc_height = 0;
|
||||||
|
line_width = 0;
|
||||||
|
line_height = 0;
|
||||||
|
labels_y_shift = 0;
|
||||||
|
labels_x_shift = 0;
|
||||||
|
arc_radius = 0;
|
||||||
|
xstep = 0;
|
||||||
|
ystep = 0;
|
||||||
|
pixmap = 0;
|
||||||
|
drawn = false;
|
||||||
|
angle_radians = M_PI/4.0;
|
||||||
|
motion_x = -1;
|
||||||
|
motion_y = -1;
|
||||||
|
|
||||||
|
add_events (Gdk::POINTER_MOTION_MASK|Gdk::LEAVE_NOTIFY_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Matrix::set_ports (const list<string>& ports)
|
||||||
|
{
|
||||||
|
ours = ports;
|
||||||
|
reset_size ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Matrix::add_group (PortGroup& pg)
|
||||||
|
{
|
||||||
|
for (vector<string>::const_iterator s = pg.ports.begin(); s != pg.ports.end(); ++s) {
|
||||||
|
others.push_back (OtherPort (*s, pg));
|
||||||
|
}
|
||||||
|
reset_size ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Matrix::remove_group (PortGroup& pg)
|
||||||
|
{
|
||||||
|
for (list<OtherPort>::iterator o = others.begin(); o != others.end(); ) {
|
||||||
|
if (&(*o).group() == &pg) {
|
||||||
|
o = others.erase (o);
|
||||||
|
} else {
|
||||||
|
++o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reset_size ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Matrix::hide_group (PortGroup& pg)
|
||||||
|
{
|
||||||
|
reset_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Matrix::show_group (PortGroup& pg)
|
||||||
|
{
|
||||||
|
reset_size ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Matrix::setup_nodes ()
|
||||||
|
{
|
||||||
|
int n, x, y;
|
||||||
|
list<string>::iterator m;
|
||||||
|
list<OtherPort>::iterator s;
|
||||||
|
|
||||||
|
for (vector<MatrixNode*>::iterator p = nodes.begin(); p != nodes.end(); ++p) {
|
||||||
|
delete *p;
|
||||||
|
}
|
||||||
|
nodes.clear ();
|
||||||
|
|
||||||
|
list<OtherPort>::size_type visible_others = 0;
|
||||||
|
|
||||||
|
for (list<OtherPort>::iterator s = others.begin(); s != others.end(); ++s) {
|
||||||
|
if ((*s).visible()) {
|
||||||
|
++visible_others;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nodes.assign (ours.size() * visible_others, 0);
|
||||||
|
|
||||||
|
for (n = 0, y = 0, m = ours.begin(); m != ours.end(); ++m, ++y) {
|
||||||
|
for (x = 0, s = others.begin(); s != others.end(); ++s) {
|
||||||
|
if ((*s).visible()) {
|
||||||
|
nodes[n] = new MatrixNode (*m, *s, x, y);
|
||||||
|
n++;
|
||||||
|
x++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Matrix::reset_size ()
|
||||||
|
{
|
||||||
|
list<OtherPort>::size_type visible_others = 0;
|
||||||
|
|
||||||
|
for (list<OtherPort>::iterator s = others.begin(); s != others.end(); ++s) {
|
||||||
|
if ((*s).visible()) {
|
||||||
|
++visible_others;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
border = 10;
|
||||||
|
|
||||||
|
if (alloc_width > line_width) {
|
||||||
|
|
||||||
|
xstep = (alloc_width - labels_x_shift - (2 * border) - (2 * arc_radius)) / visible_others;
|
||||||
|
line_width = xstep * (others.size() - 1);
|
||||||
|
|
||||||
|
ystep = (alloc_height - labels_y_shift - (2 * border) - (2 * arc_radius)) / (ours.size() - 1);
|
||||||
|
line_height = ystep * (ours.size() - 1);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
xstep = 20;
|
||||||
|
ystep = 20;
|
||||||
|
|
||||||
|
line_height = (ours.size() - 1) * ystep;
|
||||||
|
line_width = visible_others * xstep;
|
||||||
|
}
|
||||||
|
|
||||||
|
int half_step = min (ystep/2,xstep/2);
|
||||||
|
if (half_step > 3) {
|
||||||
|
arc_radius = half_step - 5;
|
||||||
|
} else {
|
||||||
|
arc_radius = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
arc_radius = min (arc_radius, 10);
|
||||||
|
|
||||||
|
/* scan all the port names that will be rotated, and compute
|
||||||
|
how much space we need for them
|
||||||
|
*/
|
||||||
|
|
||||||
|
float w = 0;
|
||||||
|
float w1;
|
||||||
|
float h = 0;
|
||||||
|
cairo_text_extents_t extents;
|
||||||
|
cairo_t* cr;
|
||||||
|
GdkPixmap* pm;
|
||||||
|
|
||||||
|
pm = gdk_pixmap_new (NULL, 1, 1, 24);
|
||||||
|
gdk_drawable_set_colormap (pm, gdk_colormap_get_system());
|
||||||
|
|
||||||
|
cr = gdk_cairo_create (pm);
|
||||||
|
|
||||||
|
for (list<OtherPort>::iterator s = others.begin(); s != others.end(); ++s) {
|
||||||
|
if ((*s).visible()) {
|
||||||
|
cairo_text_extents (cr, (*s).name().c_str(), &extents);
|
||||||
|
w = max ((float) extents.width, w);
|
||||||
|
h = max ((float) extents.height, h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_destroy (cr);
|
||||||
|
gdk_pixmap_unref (pm);
|
||||||
|
|
||||||
|
/* transform */
|
||||||
|
|
||||||
|
w = fabs (w * cos (angle_radians) + h * sin (angle_radians));
|
||||||
|
h = fabs (w * sin (angle_radians) + h * cos (angle_radians));
|
||||||
|
|
||||||
|
labels_y_shift = (int) ceil (h) + 10;
|
||||||
|
labels_x_shift = (int) ceil (w);
|
||||||
|
|
||||||
|
setup_nodes ();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Matrix::on_motion_notify_event (GdkEventMotion* ev)
|
||||||
|
{
|
||||||
|
motion_x = ev->x;
|
||||||
|
motion_y = ev->y;
|
||||||
|
queue_draw ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Matrix::on_leave_notify_event (GdkEventCrossing *ev)
|
||||||
|
{
|
||||||
|
motion_x = -1;
|
||||||
|
motion_y = -1;
|
||||||
|
queue_draw ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Matrix::on_size_request (Requisition* req)
|
||||||
|
{
|
||||||
|
req->width = labels_x_shift + line_width + (2*border) + (2*arc_radius);
|
||||||
|
req->height = labels_y_shift + line_height + (2*border) + (2*arc_radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
MatrixNode*
|
||||||
|
Matrix::get_node (int32_t x, int32_t y)
|
||||||
|
{
|
||||||
|
int half_xstep = xstep / 2;
|
||||||
|
int half_ystep = ystep / 2;
|
||||||
|
|
||||||
|
x -= labels_x_shift - border;
|
||||||
|
if (x < half_xstep) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
y -= labels_y_shift - border;
|
||||||
|
if (y < half_ystep) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
x = (x - half_xstep) / xstep;
|
||||||
|
y = (y - half_ystep) / ystep;
|
||||||
|
|
||||||
|
x = y*ours.size() + x;
|
||||||
|
|
||||||
|
if (x >= nodes.size()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodes[x];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Matrix::on_button_press_event (GdkEventButton* ev)
|
||||||
|
{
|
||||||
|
MatrixNode* node;
|
||||||
|
|
||||||
|
if ((node = get_node (ev->x, ev->y)) != 0) {
|
||||||
|
cerr << "Event in node " << node->our_name() << " x " << node->their_name () << endl;
|
||||||
|
node->set_connected (!node->connected());
|
||||||
|
drawn = false;
|
||||||
|
queue_draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Matrix::alloc_pixmap ()
|
||||||
|
{
|
||||||
|
if (pixmap) {
|
||||||
|
gdk_pixmap_unref (pixmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixmap = gdk_pixmap_new (get_window()->gobj(),
|
||||||
|
alloc_width,
|
||||||
|
alloc_height,
|
||||||
|
-1);
|
||||||
|
|
||||||
|
drawn = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Matrix::on_size_allocate (Allocation& alloc)
|
||||||
|
{
|
||||||
|
EventBox::on_size_allocate (alloc);
|
||||||
|
|
||||||
|
alloc_width = alloc.get_width();
|
||||||
|
alloc_height = alloc.get_height();
|
||||||
|
|
||||||
|
if (is_realized()) {
|
||||||
|
alloc_pixmap ();
|
||||||
|
reset_size ();
|
||||||
|
#ifdef MATRIX_USE_BACKING_PIXMAP
|
||||||
|
redraw (pixmap, 0, 0, alloc_width, alloc_height);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Matrix::on_realize ()
|
||||||
|
{
|
||||||
|
EventBox::on_realize ();
|
||||||
|
alloc_pixmap ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Matrix::redraw (GdkDrawable* drawable, GdkRectangle* rect)
|
||||||
|
{
|
||||||
|
list<string>::iterator o;
|
||||||
|
list<OtherPort>::iterator t;
|
||||||
|
int x, y;
|
||||||
|
uint32_t top_shift, bottom_shift, left_shift, right_shift;
|
||||||
|
cairo_t* cr;
|
||||||
|
|
||||||
|
cr = gdk_cairo_create (drawable);
|
||||||
|
|
||||||
|
cairo_set_source_rgb (cr, 0.83, 0.83, 0.83);
|
||||||
|
cairo_rectangle (cr, rect->x, rect->y, rect->width, rect->height);
|
||||||
|
cairo_fill (cr);
|
||||||
|
|
||||||
|
cairo_set_line_width (cr, 0.5);
|
||||||
|
|
||||||
|
top_shift = labels_y_shift + border;
|
||||||
|
left_shift = labels_x_shift + border;
|
||||||
|
bottom_shift = 0;
|
||||||
|
right_shift = 0;
|
||||||
|
|
||||||
|
/* horizontal grid lines and side labels */
|
||||||
|
|
||||||
|
for (y = top_shift, o = ours.begin(); o != ours.end(); ++o, y += ystep) {
|
||||||
|
|
||||||
|
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
|
||||||
|
cairo_move_to (cr, left_shift, y);
|
||||||
|
cairo_line_to (cr, left_shift+line_width, y);
|
||||||
|
cairo_stroke (cr);
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
cairo_text_extents_t extents;
|
||||||
|
cairo_text_extents (cr, (*o).c_str(),&extents);
|
||||||
|
cairo_move_to (cr, border, y+extents.height/2);
|
||||||
|
cairo_show_text (cr, (*o).c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vertical grid lines and rotated labels*/
|
||||||
|
|
||||||
|
for (x = left_shift, t = others.begin(); t != others.end(); ++t, x += xstep) {
|
||||||
|
|
||||||
|
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
|
||||||
|
cairo_move_to (cr, x, top_shift);
|
||||||
|
cairo_line_to (cr, x, top_shift+line_height);
|
||||||
|
cairo_stroke (cr);
|
||||||
|
|
||||||
|
cairo_move_to (cr, x-left_shift+12, border);
|
||||||
|
cairo_set_source_rgb (cr, 0, 0, 1.0);
|
||||||
|
|
||||||
|
cairo_save (cr);
|
||||||
|
cairo_rotate (cr, angle_radians);
|
||||||
|
cairo_show_text (cr, (*t).name().c_str());
|
||||||
|
cairo_restore (cr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* nodes */
|
||||||
|
|
||||||
|
for (vector<MatrixNode*>::iterator n = nodes.begin(); n != nodes.end(); ++n) {
|
||||||
|
|
||||||
|
x = (*n)->x() * xstep;
|
||||||
|
y = (*n)->y() * ystep;
|
||||||
|
|
||||||
|
cairo_new_path (cr);
|
||||||
|
|
||||||
|
if (arc_radius) {
|
||||||
|
cairo_arc (cr, left_shift+x, top_shift+y, arc_radius, 0, 2.0 * M_PI);
|
||||||
|
if ((*n)->connected()) {
|
||||||
|
cairo_set_source_rgba (cr, 1.0, 0, 0, 1.0);
|
||||||
|
cairo_stroke (cr);
|
||||||
|
} else {
|
||||||
|
cairo_set_source_rgba (cr, 1.0, 0, 0, 0.7);
|
||||||
|
cairo_fill (cr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* motion indicators */
|
||||||
|
|
||||||
|
if (motion_x >= left_shift && motion_y >= top_shift) {
|
||||||
|
|
||||||
|
int col_left = left_shift + ((motion_x - left_shift) / xstep) * xstep;
|
||||||
|
int row_top = top_shift + ((motion_y - top_shift) / ystep) * ystep;
|
||||||
|
|
||||||
|
cairo_set_line_width (cr, 5);
|
||||||
|
cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.3);
|
||||||
|
|
||||||
|
/* horizontal (row) */
|
||||||
|
|
||||||
|
cairo_line_to (cr, left_shift, row_top);
|
||||||
|
cairo_line_to (cr, left_shift + line_width, row_top);
|
||||||
|
cairo_stroke (cr);
|
||||||
|
|
||||||
|
/* vertical (col) */
|
||||||
|
|
||||||
|
cairo_move_to (cr, col_left, top_shift);
|
||||||
|
cairo_line_to (cr, col_left, top_shift + line_height);
|
||||||
|
cairo_stroke (cr);
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_destroy (cr);
|
||||||
|
|
||||||
|
#ifdef MATRIX_USE_BACKING_PIXMAP
|
||||||
|
drawn = true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Matrix::on_expose_event (GdkEventExpose* event)
|
||||||
|
{
|
||||||
|
#ifdef MATRIX_USE_BACKING_PIXMAP
|
||||||
|
if (!drawn) {
|
||||||
|
redraw (pixmap, 0, 0, alloc_width, alloc_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
gdk_draw_drawable (get_window()->gobj(),
|
||||||
|
get_style()->get_fg_gc (STATE_NORMAL)->gobj(),
|
||||||
|
pixmap,
|
||||||
|
event->area.x,
|
||||||
|
event->area.y,
|
||||||
|
event->area.x,
|
||||||
|
event->area.y,
|
||||||
|
event->area.width,
|
||||||
|
event->area.height);
|
||||||
|
#else
|
||||||
|
redraw (get_window()->gobj(), &event->area);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
106
gtk2_ardour/matrix.h
Normal file
106
gtk2_ardour/matrix.h
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
#ifndef __gtk_ardour_matrix_h__
|
||||||
|
#define __gtk_ardour_matrix_h__
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <gtkmm/eventbox.h>
|
||||||
|
#include <gtkmm/widget.h>
|
||||||
|
|
||||||
|
#include "port_group.h"
|
||||||
|
|
||||||
|
class OtherPort {
|
||||||
|
public:
|
||||||
|
OtherPort (const std::string& n, PortGroup& g)
|
||||||
|
: _name (n), _group (g) {}
|
||||||
|
|
||||||
|
std::string name() const { return _name; }
|
||||||
|
PortGroup& group() const { return _group; }
|
||||||
|
bool visible() const { return _group.visible; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::string _name;
|
||||||
|
PortGroup& _group;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MatrixNode {
|
||||||
|
public:
|
||||||
|
MatrixNode (std::string a, OtherPort o, int32_t x, int32_t y)
|
||||||
|
: _name (a), them (o), _connected (random()%3), _x(x), _y(y) {}
|
||||||
|
~MatrixNode() {}
|
||||||
|
|
||||||
|
PortGroup& get_group() const { return them.group(); }
|
||||||
|
|
||||||
|
std::string our_name() const { return _name; }
|
||||||
|
std::string their_name() const { return them.name(); }
|
||||||
|
|
||||||
|
bool connected() const { return _connected; }
|
||||||
|
void set_connected (bool yn) { _connected = yn; }
|
||||||
|
int32_t x() const { return _x; }
|
||||||
|
int32_t y() const { return _y; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string _name;
|
||||||
|
OtherPort them;
|
||||||
|
bool _connected;
|
||||||
|
int32_t _x;
|
||||||
|
int32_t _y;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Matrix : public Gtk::EventBox
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Matrix();
|
||||||
|
|
||||||
|
void set_ports (const std::list<std::string>&);
|
||||||
|
void add_group (PortGroup&);
|
||||||
|
void remove_group (PortGroup&);
|
||||||
|
void hide_group (PortGroup&);
|
||||||
|
void show_group (PortGroup&);
|
||||||
|
|
||||||
|
int row_spacing () const { return xstep; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool on_button_press_event (GdkEventButton* ev);
|
||||||
|
bool on_expose_event (GdkEventExpose* ev);
|
||||||
|
void on_size_allocate (Gtk::Allocation&);
|
||||||
|
void on_size_request (Gtk::Requisition*);
|
||||||
|
void on_realize ();
|
||||||
|
bool on_motion_notify_event (GdkEventMotion*);
|
||||||
|
bool on_leave_notify_event (GdkEventCrossing*);
|
||||||
|
|
||||||
|
MatrixNode* get_node (int32_t x, int32_t y);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int height;
|
||||||
|
int width;
|
||||||
|
int alloc_width;
|
||||||
|
int alloc_height;
|
||||||
|
bool drawn;
|
||||||
|
int labels_y_shift;
|
||||||
|
int labels_x_shift;
|
||||||
|
float angle_radians;
|
||||||
|
int border;
|
||||||
|
int ystep;
|
||||||
|
int xstep;
|
||||||
|
uint32_t line_height;
|
||||||
|
uint32_t line_width;
|
||||||
|
int arc_radius;
|
||||||
|
int32_t motion_x;
|
||||||
|
int32_t motion_y;
|
||||||
|
|
||||||
|
std::list<std::string> ours;
|
||||||
|
std::list<OtherPort> others;
|
||||||
|
std::vector<MatrixNode*> nodes;
|
||||||
|
|
||||||
|
void reset_size ();
|
||||||
|
void redraw (GdkDrawable*, GdkRectangle*);
|
||||||
|
void alloc_pixmap ();
|
||||||
|
void setup_nodes ();
|
||||||
|
|
||||||
|
GdkPixmap* pixmap;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __gtk_ardour_matrix_h__ */
|
||||||
|
|
@ -82,34 +82,56 @@ speed_printer (char buf[32], Gtk::Adjustment& adj, void* arg)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt, bool in_mixer)
|
MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, bool in_mixer)
|
||||||
: AxisView(sess),
|
: AxisView(sess)
|
||||||
RouteUI (rt, sess, _("Mute"), _("Solo"), _("Record")),
|
, RouteUI (sess, _("Mute"), _("Solo"), _("Record"))
|
||||||
_mixer(mx),
|
,_mixer(mx)
|
||||||
_mixer_owned (in_mixer),
|
, _mixer_owned (in_mixer)
|
||||||
pre_processor_box (PreFader, sess, rt, mx.plugin_selector(), mx.selection(), in_mixer),
|
, pre_processor_box (PreFader, sess, mx.plugin_selector(), mx.selection(), in_mixer)
|
||||||
post_processor_box (PostFader, sess, rt, mx.plugin_selector(), mx.selection(), in_mixer),
|
, post_processor_box (PostFader, sess, mx.plugin_selector(), mx.selection(), in_mixer)
|
||||||
gpm (_route, sess),
|
, gpm (sess)
|
||||||
panners (_route, sess),
|
, panners (sess)
|
||||||
button_table (3, 2),
|
, button_table (3, 2)
|
||||||
middle_button_table (1, 2),
|
, middle_button_table (1, 2)
|
||||||
bottom_button_table (1, 2),
|
, bottom_button_table (1, 2)
|
||||||
meter_point_label (_("pre")),
|
, meter_point_label (_("pre"))
|
||||||
comment_button (_("Comments")),
|
, comment_button (_("Comments"))
|
||||||
speed_adjustment (1.0, 0.001, 4.0, 0.001, 0.1),
|
, speed_adjustment (1.0, 0.001, 4.0, 0.001, 0.1)
|
||||||
speed_spinner (&speed_adjustment, "MixerStripSpeedBase", true)
|
, speed_spinner (&speed_adjustment, "MixerStripSpeedBase", true)
|
||||||
|
|
||||||
{
|
{
|
||||||
if (set_color_from_route()) {
|
init ();
|
||||||
set_color (unique_random_color());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt, bool in_mixer)
|
||||||
|
: AxisView(sess)
|
||||||
|
, RouteUI (sess, _("Mute"), _("Solo"), _("Record"))
|
||||||
|
,_mixer(mx)
|
||||||
|
, _mixer_owned (in_mixer)
|
||||||
|
, pre_processor_box (PreFader, sess, mx.plugin_selector(), mx.selection(), in_mixer)
|
||||||
|
, post_processor_box (PostFader, sess, mx.plugin_selector(), mx.selection(), in_mixer)
|
||||||
|
, gpm (sess)
|
||||||
|
, panners (sess)
|
||||||
|
, button_table (3, 2)
|
||||||
|
, middle_button_table (1, 2)
|
||||||
|
, bottom_button_table (1, 2)
|
||||||
|
, meter_point_label (_("pre"))
|
||||||
|
, comment_button (_("Comments"))
|
||||||
|
, speed_adjustment (1.0, 0.001, 4.0, 0.001, 0.1)
|
||||||
|
, speed_spinner (&speed_adjustment, "MixerStripSpeedBase", true)
|
||||||
|
|
||||||
|
{
|
||||||
|
init ();
|
||||||
|
set_route (rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MixerStrip::init ()
|
||||||
|
{
|
||||||
input_selector = 0;
|
input_selector = 0;
|
||||||
output_selector = 0;
|
output_selector = 0;
|
||||||
group_menu = 0;
|
group_menu = 0;
|
||||||
if (!_route->is_hidden()) {
|
_marked_for_display = false;
|
||||||
_marked_for_display = true;
|
|
||||||
}
|
|
||||||
route_ops_menu = 0;
|
route_ops_menu = 0;
|
||||||
ignore_comment_edit = false;
|
ignore_comment_edit = false;
|
||||||
ignore_toggle = false;
|
ignore_toggle = false;
|
||||||
|
|
@ -118,40 +140,26 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt
|
||||||
comment_area = 0;
|
comment_area = 0;
|
||||||
_width_owner = 0;
|
_width_owner = 0;
|
||||||
|
|
||||||
Gtk::Image *width_icon = manage (new Gtk::Image (::get_icon("strip_width")));
|
width_button.add (*(manage (new Gtk::Image (::get_icon("strip_width")))));
|
||||||
Gtk::Image *hide_icon = manage (new Gtk::Image (::get_icon("hide")));
|
hide_button.add (*(manage (new Gtk::Image (::get_icon("hide")))));
|
||||||
width_button.add (*width_icon);
|
|
||||||
hide_button.add (*hide_icon);
|
|
||||||
|
|
||||||
input_label.set_text (_("Input"));
|
input_label.set_text (_("Input"));
|
||||||
|
ARDOUR_UI::instance()->set_tip (&input_button, _("Click to choose inputs"), "");
|
||||||
input_button.add (input_label);
|
input_button.add (input_label);
|
||||||
input_button.set_name ("MixerIOButton");
|
input_button.set_name ("MixerIOButton");
|
||||||
input_label.set_name ("MixerIOButtonLabel");
|
input_label.set_name ("MixerIOButtonLabel");
|
||||||
|
|
||||||
output_label.set_text (_("Output"));
|
output_label.set_text (_("Output"));
|
||||||
|
ARDOUR_UI::instance()->set_tip (&output_button, _("Click to choose outputs"), "");
|
||||||
output_button.add (output_label);
|
output_button.add (output_label);
|
||||||
output_button.set_name ("MixerIOButton");
|
output_button.set_name ("MixerIOButton");
|
||||||
output_label.set_name ("MixerIOButtonLabel");
|
output_label.set_name ("MixerIOButtonLabel");
|
||||||
|
|
||||||
_route->meter_change.connect (mem_fun(*this, &MixerStrip::meter_changed));
|
ARDOUR_UI::instance()->set_tip (&meter_point_button, _("Select metering point"), "");
|
||||||
meter_point_button.add (meter_point_label);
|
meter_point_button.add (meter_point_label);
|
||||||
meter_point_button.set_name ("MixerStripMeterPreButton");
|
meter_point_button.set_name ("MixerStripMeterPreButton");
|
||||||
meter_point_label.set_name ("MixerStripMeterPreButton");
|
meter_point_label.set_name ("MixerStripMeterPreButton");
|
||||||
|
|
||||||
switch (_route->meter_point()) {
|
|
||||||
case MeterInput:
|
|
||||||
meter_point_label.set_text (_("input"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MeterPreFader:
|
|
||||||
meter_point_label.set_text (_("pre"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MeterPostFader:
|
|
||||||
meter_point_label.set_text (_("post"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TRANSLATORS: this string should be longest of the strings
|
/* TRANSLATORS: this string should be longest of the strings
|
||||||
used to describe meter points. In english, it's "input".
|
used to describe meter points. In english, it's "input".
|
||||||
*/
|
*/
|
||||||
|
|
@ -183,56 +191,18 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt
|
||||||
bottom_button_table.set_homogeneous (true);
|
bottom_button_table.set_homogeneous (true);
|
||||||
bottom_button_table.attach (group_button, 0, 1, 0, 1);
|
bottom_button_table.attach (group_button, 0, 1, 0, 1);
|
||||||
|
|
||||||
if (is_audio_track()) {
|
|
||||||
boost::shared_ptr<AudioTrack> at = audio_track();
|
|
||||||
|
|
||||||
at->FreezeChange.connect (mem_fun(*this, &MixerStrip::map_frozen));
|
|
||||||
|
|
||||||
#ifdef VARISPEED_IN_MIXER_STRIP
|
|
||||||
speed_adjustment.signal_value_changed().connect (mem_fun(*this, &MixerStrip::speed_adjustment_changed));
|
|
||||||
|
|
||||||
speed_frame.set_name ("BaseFrame");
|
|
||||||
speed_frame.set_shadow_type (Gtk::SHADOW_IN);
|
|
||||||
speed_frame.add (speed_spinner);
|
|
||||||
|
|
||||||
speed_spinner.set_print_func (speed_printer, 0);
|
|
||||||
|
|
||||||
ARDOUR_UI::instance()->tooltips().set_tip (speed_spinner, _("Varispeed"));
|
|
||||||
|
|
||||||
button_table.attach (speed_frame, 0, 2, 5, 6);
|
|
||||||
#endif /* VARISPEED_IN_MIXER_STRIP */
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if(rec_enable_button) {
|
|
||||||
rec_enable_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::rec_enable_press), false);
|
|
||||||
rec_enable_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::rec_enable_release));
|
|
||||||
|
|
||||||
rec_enable_button->set_name ("MixerRecordEnableButton");
|
|
||||||
button_table.attach (*rec_enable_button, 0, 2, 2, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
name_button.add (name_label);
|
name_button.add (name_label);
|
||||||
name_button.set_name ("MixerNameButton");
|
name_button.set_name ("MixerNameButton");
|
||||||
Gtkmm2ext::set_size_request_to_display_given_text (name_button, "longest label", 2, 2);
|
Gtkmm2ext::set_size_request_to_display_given_text (name_button, "longest label", 2, 2);
|
||||||
|
|
||||||
name_label.set_name ("MixerNameButtonLabel");
|
name_label.set_name ("MixerNameButtonLabel");
|
||||||
if (_route->phase_invert()) {
|
ARDOUR_UI::instance()->set_tip (&group_button, _("Mix group"), "");
|
||||||
name_label.set_text (X_("Ø ") + name_label.get_text());
|
|
||||||
} else {
|
|
||||||
name_label.set_text (_route->name());
|
|
||||||
}
|
|
||||||
|
|
||||||
group_button.add (group_label);
|
group_button.add (group_label);
|
||||||
group_button.set_name ("MixerGroupButton");
|
group_button.set_name ("MixerGroupButton");
|
||||||
group_label.set_name ("MixerGroupButtonLabel");
|
group_label.set_name ("MixerGroupButtonLabel");
|
||||||
|
|
||||||
comment_button.set_name ("MixerCommentButton");
|
comment_button.set_name ("MixerCommentButton");
|
||||||
|
|
||||||
ARDOUR_UI::instance()->tooltips().set_tip (comment_button, _route->comment()=="" ?
|
|
||||||
_("Click to Add/Edit Comments"):
|
|
||||||
_route->comment());
|
|
||||||
|
|
||||||
comment_button.signal_clicked().connect (mem_fun(*this, &MixerStrip::comment_button_clicked));
|
comment_button.signal_clicked().connect (mem_fun(*this, &MixerStrip::comment_button_clicked));
|
||||||
|
|
||||||
global_vpacker.set_border_width (0);
|
global_vpacker.set_border_width (0);
|
||||||
|
|
@ -269,19 +239,6 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt
|
||||||
global_vpacker.pack_start (output_button, Gtk::PACK_SHRINK);
|
global_vpacker.pack_start (output_button, Gtk::PACK_SHRINK);
|
||||||
global_vpacker.pack_start (comment_button, Gtk::PACK_SHRINK);
|
global_vpacker.pack_start (comment_button, Gtk::PACK_SHRINK);
|
||||||
|
|
||||||
if (route()->is_master() || route()->is_control()) {
|
|
||||||
|
|
||||||
if (scrollbar_height == 0) {
|
|
||||||
HScrollbar scrollbar;
|
|
||||||
Gtk::Requisition requisition(scrollbar.size_request ());
|
|
||||||
scrollbar_height = requisition.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
EventBox* spacer = manage (new EventBox);
|
|
||||||
spacer->set_size_request (-1, scrollbar_height);
|
|
||||||
global_vpacker.pack_start (*spacer, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
global_frame.add (global_vpacker);
|
global_frame.add (global_vpacker);
|
||||||
global_frame.set_shadow_type (Gtk::SHADOW_IN);
|
global_frame.set_shadow_type (Gtk::SHADOW_IN);
|
||||||
global_frame.set_name ("BaseFrame");
|
global_frame.set_name ("BaseFrame");
|
||||||
|
|
@ -298,22 +255,6 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt
|
||||||
|
|
||||||
_session.engine().Stopped.connect (mem_fun(*this, &MixerStrip::engine_stopped));
|
_session.engine().Stopped.connect (mem_fun(*this, &MixerStrip::engine_stopped));
|
||||||
_session.engine().Running.connect (mem_fun(*this, &MixerStrip::engine_running));
|
_session.engine().Running.connect (mem_fun(*this, &MixerStrip::engine_running));
|
||||||
_route->input_changed.connect (mem_fun(*this, &MixerStrip::input_changed));
|
|
||||||
_route->output_changed.connect (mem_fun(*this, &MixerStrip::output_changed));
|
|
||||||
_route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed));
|
|
||||||
_route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
|
|
||||||
_route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
|
|
||||||
_route->mix_group_changed.connect (mem_fun(*this, &MixerStrip::mix_group_changed));
|
|
||||||
_route->panner().Changed.connect (mem_fun(*this, &MixerStrip::connect_to_pan));
|
|
||||||
|
|
||||||
if (is_audio_track()) {
|
|
||||||
audio_track()->DiskstreamChanged.connect (mem_fun(*this, &MixerStrip::diskstream_changed));
|
|
||||||
get_diskstream()->SpeedChanged.connect (mem_fun(*this, &MixerStrip::speed_changed));
|
|
||||||
}
|
|
||||||
|
|
||||||
_route->NameChanged.connect (mem_fun(*this, &RouteUI::name_changed));
|
|
||||||
_route->comment_changed.connect (mem_fun(*this, &MixerStrip::comment_changed));
|
|
||||||
_route->gui_changed.connect (mem_fun(*this, &MixerStrip::route_gui_changed));
|
|
||||||
|
|
||||||
input_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::input_press), false);
|
input_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::input_press), false);
|
||||||
output_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::output_press), false);
|
output_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::output_press), false);
|
||||||
|
|
@ -323,11 +264,22 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt
|
||||||
mute_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::mute_press), false);
|
mute_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::mute_press), false);
|
||||||
mute_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::mute_release), false);
|
mute_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::mute_release), false);
|
||||||
|
|
||||||
|
/* we don't need this if its not an audio track, but we don't know that yet and it doesn't
|
||||||
|
hurt (much).
|
||||||
|
*/
|
||||||
|
|
||||||
|
rec_enable_button->set_name ("MixerRecordEnableButton");
|
||||||
|
rec_enable_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::rec_enable_press), false);
|
||||||
|
rec_enable_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::rec_enable_release));
|
||||||
|
|
||||||
name_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::name_button_button_press), false);
|
name_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::name_button_button_press), false);
|
||||||
group_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::select_mix_group), false);
|
group_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::select_mix_group), false);
|
||||||
|
|
||||||
_width = (Width) -1;
|
_width = (Width) -1;
|
||||||
set_stuff_from_route ();
|
|
||||||
|
/* start off as a passthru strip. we'll correct this, if necessary,
|
||||||
|
in update_diskstream_display().
|
||||||
|
*/
|
||||||
|
|
||||||
/* start off as a passthru strip. we'll correct this, if necessary,
|
/* start off as a passthru strip. we'll correct this, if necessary,
|
||||||
in update_diskstream_display().
|
in update_diskstream_display().
|
||||||
|
|
@ -338,6 +290,126 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt
|
||||||
else
|
else
|
||||||
set_name ("AudioTrackStripBase");
|
set_name ("AudioTrackStripBase");
|
||||||
|
|
||||||
|
add_events (Gdk::BUTTON_RELEASE_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
MixerStrip::~MixerStrip ()
|
||||||
|
{
|
||||||
|
GoingAway(); /* EMIT_SIGNAL */
|
||||||
|
|
||||||
|
if (input_selector) {
|
||||||
|
delete input_selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output_selector) {
|
||||||
|
delete output_selector;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MixerStrip::set_route (boost::shared_ptr<Route> rt)
|
||||||
|
{
|
||||||
|
if (rec_enable_button->get_parent()) {
|
||||||
|
button_table.remove (*rec_enable_button);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef VARISPEED_IN_MIXER_STRIP
|
||||||
|
if (speed_frame->get_parent()) {
|
||||||
|
button_table.remove (*speed_frame);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RouteUI::set_route (rt);
|
||||||
|
|
||||||
|
panners.set_io (rt);
|
||||||
|
gpm.set_io (rt);
|
||||||
|
pre_processor_box.set_route (rt);
|
||||||
|
post_processor_box.set_route (rt);
|
||||||
|
|
||||||
|
if (set_color_from_route()) {
|
||||||
|
set_color (unique_random_color());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_mixer_owned && (route()->is_master() || route()->is_control())) {
|
||||||
|
|
||||||
|
if (scrollbar_height == 0) {
|
||||||
|
HScrollbar scrollbar;
|
||||||
|
Gtk::Requisition requisition(scrollbar.size_request ());
|
||||||
|
scrollbar_height = requisition.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventBox* spacer = manage (new EventBox);
|
||||||
|
spacer->set_size_request (-1, scrollbar_height);
|
||||||
|
global_vpacker.pack_start (*spacer, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_audio_track()) {
|
||||||
|
|
||||||
|
boost::shared_ptr<AudioTrack> at = audio_track();
|
||||||
|
|
||||||
|
connections.push_back (at->FreezeChange.connect (mem_fun(*this, &MixerStrip::map_frozen)));
|
||||||
|
|
||||||
|
#ifdef VARISPEED_IN_MIXER_STRIP
|
||||||
|
speed_adjustment.signal_value_changed().connect (mem_fun(*this, &MixerStrip::speed_adjustment_changed));
|
||||||
|
|
||||||
|
speed_frame.set_name ("BaseFrame");
|
||||||
|
speed_frame.set_shadow_type (Gtk::SHADOW_IN);
|
||||||
|
speed_frame.add (speed_spinner);
|
||||||
|
|
||||||
|
speed_spinner.set_print_func (speed_printer, 0);
|
||||||
|
|
||||||
|
ARDOUR_UI::instance()->tooltips().set_tip (speed_spinner, _("Varispeed"));
|
||||||
|
|
||||||
|
button_table.attach (speed_frame, 0, 2, 5, 6);
|
||||||
|
#endif /* VARISPEED_IN_MIXER_STRIP */
|
||||||
|
|
||||||
|
button_table.attach (*rec_enable_button, 0, 2, 2, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_route->phase_invert()) {
|
||||||
|
name_label.set_text (X_("Ø ") + name_label.get_text());
|
||||||
|
} else {
|
||||||
|
name_label.set_text (_route->name());
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (_route->meter_point()) {
|
||||||
|
case MeterInput:
|
||||||
|
meter_point_label.set_text (_("input"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MeterPreFader:
|
||||||
|
meter_point_label.set_text (_("pre"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MeterPostFader:
|
||||||
|
meter_point_label.set_text (_("post"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ARDOUR_UI::instance()->tooltips().set_tip (comment_button, _route->comment().empty() ?
|
||||||
|
_("Click to Add/Edit Comments"):
|
||||||
|
_route->comment());
|
||||||
|
|
||||||
|
connections.push_back (_route->meter_change.connect (mem_fun(*this, &MixerStrip::meter_changed)));
|
||||||
|
connections.push_back (_route->input_changed.connect (mem_fun(*this, &MixerStrip::input_changed)));
|
||||||
|
connections.push_back (_route->output_changed.connect (mem_fun(*this, &MixerStrip::output_changed)));
|
||||||
|
connections.push_back (_route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed)));
|
||||||
|
connections.push_back (_route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed)));
|
||||||
|
connections.push_back (_route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed)));
|
||||||
|
connections.push_back (_route->mix_group_changed.connect (mem_fun(*this, &MixerStrip::mix_group_changed)));
|
||||||
|
connections.push_back (_route->panner().Changed.connect (mem_fun(*this, &MixerStrip::connect_to_pan)));
|
||||||
|
|
||||||
|
if (is_audio_track()) {
|
||||||
|
connections.push_back (audio_track()->DiskstreamChanged.connect (mem_fun(*this, &MixerStrip::diskstream_changed)));
|
||||||
|
connections.push_back (get_diskstream()->SpeedChanged.connect (mem_fun(*this, &MixerStrip::speed_changed)));
|
||||||
|
}
|
||||||
|
|
||||||
|
connections.push_back (_route->NameChanged.connect (mem_fun(*this, &RouteUI::name_changed)));
|
||||||
|
connections.push_back (_route->comment_changed.connect (mem_fun(*this, &MixerStrip::comment_changed)));
|
||||||
|
connections.push_back (_route->gui_changed.connect (mem_fun(*this, &MixerStrip::route_gui_changed)));
|
||||||
|
|
||||||
|
set_stuff_from_route ();
|
||||||
|
|
||||||
/* now force an update of all the various elements */
|
/* now force an update of all the various elements */
|
||||||
|
|
||||||
pre_processor_box.update();
|
pre_processor_box.update();
|
||||||
|
|
@ -362,11 +434,6 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt
|
||||||
|
|
||||||
add_events (Gdk::BUTTON_RELEASE_MASK);
|
add_events (Gdk::BUTTON_RELEASE_MASK);
|
||||||
|
|
||||||
whvbox->show();
|
|
||||||
hide_icon->show();
|
|
||||||
width_icon->show();
|
|
||||||
gain_meter_alignment->show_all();
|
|
||||||
|
|
||||||
pre_processor_box.show();
|
pre_processor_box.show();
|
||||||
|
|
||||||
if (!route()->is_master() && !route()->is_control()) {
|
if (!route()->is_master() && !route()->is_control()) {
|
||||||
|
|
@ -402,19 +469,6 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
|
|
||||||
MixerStrip::~MixerStrip ()
|
|
||||||
{
|
|
||||||
GoingAway(); /* EMIT_SIGNAL */
|
|
||||||
|
|
||||||
if (input_selector) {
|
|
||||||
delete input_selector;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (output_selector) {
|
|
||||||
delete output_selector;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MixerStrip::set_stuff_from_route ()
|
MixerStrip::set_stuff_from_route ()
|
||||||
{
|
{
|
||||||
|
|
@ -796,6 +850,7 @@ MixerStrip::update_output_display ()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gpm.setup_meters ();
|
gpm.setup_meters ();
|
||||||
panners.setup_pan ();
|
panners.setup_pan ();
|
||||||
}
|
}
|
||||||
|
|
@ -1292,22 +1347,22 @@ MixerStrip::meter_changed (void *src)
|
||||||
ENSURE_GUI_THREAD (bind (mem_fun(*this, &MixerStrip::meter_changed), src));
|
ENSURE_GUI_THREAD (bind (mem_fun(*this, &MixerStrip::meter_changed), src));
|
||||||
|
|
||||||
switch (_route->meter_point()) {
|
switch (_route->meter_point()) {
|
||||||
case MeterInput:
|
case MeterInput:
|
||||||
meter_point_label.set_text (_("input"));
|
meter_point_label.set_text (_("input"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MeterPreFader:
|
case MeterPreFader:
|
||||||
meter_point_label.set_text (_("pre"));
|
meter_point_label.set_text (_("pre"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MeterPostFader:
|
case MeterPostFader:
|
||||||
meter_point_label.set_text (_("post"));
|
meter_point_label.set_text (_("post"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
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(_width, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,7 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MixerStrip (Mixer_UI&, ARDOUR::Session&, boost::shared_ptr<ARDOUR::Route>, bool in_mixer = true);
|
MixerStrip (Mixer_UI&, ARDOUR::Session&, boost::shared_ptr<ARDOUR::Route>, bool in_mixer = true);
|
||||||
|
MixerStrip (Mixer_UI&, ARDOUR::Session&, bool in_mixer = true);
|
||||||
~MixerStrip ();
|
~MixerStrip ();
|
||||||
|
|
||||||
void set_width (Width, void* owner);
|
void set_width (Width, void* owner);
|
||||||
|
|
@ -93,6 +94,7 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
|
||||||
void set_embedded (bool);
|
void set_embedded (bool);
|
||||||
|
|
||||||
ARDOUR::RouteGroup* mix_group() const;
|
ARDOUR::RouteGroup* mix_group() const;
|
||||||
|
void set_route (boost::shared_ptr<ARDOUR::Route>);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class Mixer_UI;
|
friend class Mixer_UI;
|
||||||
|
|
@ -105,6 +107,8 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
|
||||||
private:
|
private:
|
||||||
Mixer_UI& _mixer;
|
Mixer_UI& _mixer;
|
||||||
|
|
||||||
|
void init ();
|
||||||
|
|
||||||
bool _embedded;
|
bool _embedded;
|
||||||
bool _packed;
|
bool _packed;
|
||||||
bool _mixer_owned;
|
bool _mixer_owned;
|
||||||
|
|
|
||||||
|
|
@ -1117,7 +1117,8 @@ OptionEditor::setup_click_editor ()
|
||||||
click_emphasis_path_entry.set_sensitive (true);
|
click_emphasis_path_entry.set_sensitive (true);
|
||||||
|
|
||||||
click_io_selector = new IOSelector (*session, session->click_io(), false);
|
click_io_selector = new IOSelector (*session, session->click_io(), false);
|
||||||
click_gpm = new GainMeter (session->click_io(), *session);
|
click_gpm = new GainMeter (*session);
|
||||||
|
click_gpm->set_io (session->click_io());
|
||||||
|
|
||||||
click_hpacker.pack_start (*click_io_selector, false, false);
|
click_hpacker.pack_start (*click_io_selector, false, false);
|
||||||
click_hpacker.pack_start (*click_gpm, false, false);
|
click_hpacker.pack_start (*click_gpm, false, false);
|
||||||
|
|
@ -1173,7 +1174,8 @@ void
|
||||||
OptionEditor::connect_audition_editor ()
|
OptionEditor::connect_audition_editor ()
|
||||||
{
|
{
|
||||||
auditioner_io_selector = new IOSelector (*session, session->the_auditioner(), false);
|
auditioner_io_selector = new IOSelector (*session, session->the_auditioner(), false);
|
||||||
auditioner_gpm = new GainMeter (session->the_auditioner(), *session);
|
auditioner_gpm = new GainMeter (*session);
|
||||||
|
auditioner_gpm->set_io (session->the_auditioner());
|
||||||
|
|
||||||
audition_hpacker.pack_start (*auditioner_io_selector, false, false);
|
audition_hpacker.pack_start (*auditioner_io_selector, false, false);
|
||||||
audition_hpacker.pack_start (*auditioner_gpm, false, false);
|
audition_hpacker.pack_start (*auditioner_gpm, false, false);
|
||||||
|
|
|
||||||
|
|
@ -47,9 +47,8 @@ using namespace sigc;
|
||||||
|
|
||||||
const int PannerUI::pan_bar_height = 30;
|
const int PannerUI::pan_bar_height = 30;
|
||||||
|
|
||||||
PannerUI::PannerUI (boost::shared_ptr<IO> io, Session& s)
|
PannerUI::PannerUI (Session& s)
|
||||||
: _io (io),
|
: _session (s),
|
||||||
_session (s),
|
|
||||||
hAdjustment(0.0, 0.0, 0.0),
|
hAdjustment(0.0, 0.0, 0.0),
|
||||||
vAdjustment(0.0, 0.0, 0.0),
|
vAdjustment(0.0, 0.0, 0.0),
|
||||||
panning_viewport(hAdjustment, vAdjustment),
|
panning_viewport(hAdjustment, vAdjustment),
|
||||||
|
|
@ -61,6 +60,8 @@ PannerUI::PannerUI (boost::shared_ptr<IO> io, Session& s)
|
||||||
{
|
{
|
||||||
ignore_toggle = false;
|
ignore_toggle = false;
|
||||||
pan_menu = 0;
|
pan_menu = 0;
|
||||||
|
pan_astate_menu = 0;
|
||||||
|
pan_astyle_menu = 0;
|
||||||
in_pan_update = false;
|
in_pan_update = false;
|
||||||
|
|
||||||
pan_automation_style_button.set_name ("MixerAutomationModeButton");
|
pan_automation_style_button.set_name ("MixerAutomationModeButton");
|
||||||
|
|
@ -84,22 +85,6 @@ PannerUI::PannerUI (boost::shared_ptr<IO> io, Session& s)
|
||||||
pan_automation_style_button.unset_flags (Gtk::CAN_FOCUS);
|
pan_automation_style_button.unset_flags (Gtk::CAN_FOCUS);
|
||||||
pan_automation_state_button.unset_flags (Gtk::CAN_FOCUS);
|
pan_automation_state_button.unset_flags (Gtk::CAN_FOCUS);
|
||||||
|
|
||||||
using namespace Menu_Helpers;
|
|
||||||
pan_astate_menu.items().push_back (MenuElem (_("Manual"),
|
|
||||||
bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Off)));
|
|
||||||
pan_astate_menu.items().push_back (MenuElem (_("Play"),
|
|
||||||
bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Play)));
|
|
||||||
pan_astate_menu.items().push_back (MenuElem (_("Write"),
|
|
||||||
bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Write)));
|
|
||||||
pan_astate_menu.items().push_back (MenuElem (_("Touch"),
|
|
||||||
bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Touch)));
|
|
||||||
|
|
||||||
pan_astyle_menu.items().push_back (MenuElem (_("Trim")));
|
|
||||||
pan_astyle_menu.items().push_back (MenuElem (_("Abs")));
|
|
||||||
|
|
||||||
pan_astate_menu.set_name ("ArdourContextMenu");
|
|
||||||
pan_astyle_menu.set_name ("ArdourContextMenu");
|
|
||||||
|
|
||||||
pan_automation_style_button.signal_button_press_event().connect (mem_fun(*this, &PannerUI::pan_automation_style_button_event), false);
|
pan_automation_style_button.signal_button_press_event().connect (mem_fun(*this, &PannerUI::pan_automation_style_button_event), false);
|
||||||
pan_automation_state_button.signal_button_press_event().connect (mem_fun(*this, &PannerUI::pan_automation_state_button_event), false);
|
pan_automation_state_button.signal_button_press_event().connect (mem_fun(*this, &PannerUI::pan_automation_state_button_event), false);
|
||||||
|
|
||||||
|
|
@ -141,16 +126,41 @@ PannerUI::PannerUI (boost::shared_ptr<IO> io, Session& s)
|
||||||
panner = 0;
|
panner = 0;
|
||||||
|
|
||||||
set_width(Narrow);
|
set_width(Narrow);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PannerUI::set_io (boost::shared_ptr<IO> io)
|
||||||
|
{
|
||||||
|
connections.clear ();
|
||||||
|
|
||||||
|
if (pan_astyle_menu) {
|
||||||
|
delete pan_astyle_menu;
|
||||||
|
pan_astyle_menu = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pan_astate_menu) {
|
||||||
|
delete pan_astate_menu;
|
||||||
|
pan_astate_menu = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_io = io;
|
||||||
|
|
||||||
|
connections.push_back (_io->panner().Changed.connect (mem_fun(*this, &PannerUI::panner_changed)));
|
||||||
|
connections.push_back (_io->panner().LinkStateChanged.connect (mem_fun(*this, &PannerUI::update_pan_linkage)));
|
||||||
|
connections.push_back (_io->panner().StateChanged.connect (mem_fun(*this, &PannerUI::update_pan_state)));
|
||||||
|
|
||||||
|
if (panner) {
|
||||||
|
delete panner;
|
||||||
|
panner = 0;
|
||||||
|
}
|
||||||
|
|
||||||
_io->panner().Changed.connect (mem_fun(*this, &PannerUI::panner_changed));
|
|
||||||
_io->panner().LinkStateChanged.connect (mem_fun(*this, &PannerUI::update_pan_linkage));
|
|
||||||
_io->panner().StateChanged.connect (mem_fun(*this, &PannerUI::update_pan_state));
|
|
||||||
|
|
||||||
pan_changed (0);
|
pan_changed (0);
|
||||||
update_pan_sensitive ();
|
update_pan_sensitive ();
|
||||||
update_pan_linkage ();
|
update_pan_linkage ();
|
||||||
pan_automation_state_changed ();
|
pan_automation_state_changed ();
|
||||||
|
|
||||||
|
#if WHERE_DOES_THIS_LIVE
|
||||||
pan_bar_packer.show();
|
pan_bar_packer.show();
|
||||||
panning_viewport.show();
|
panning_viewport.show();
|
||||||
panning_up.show();
|
panning_up.show();
|
||||||
|
|
@ -164,6 +174,46 @@ PannerUI::PannerUI (boost::shared_ptr<IO> io, Session& s)
|
||||||
pan_automation_style_button.show();
|
pan_automation_style_button.show();
|
||||||
pan_automation_state_button.show();
|
pan_automation_state_button.show();
|
||||||
show();
|
show();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PannerUI::build_astate_menu ()
|
||||||
|
{
|
||||||
|
using namespace Menu_Helpers;
|
||||||
|
|
||||||
|
if (pan_astate_menu == 0) {
|
||||||
|
pan_astate_menu = new Menu;
|
||||||
|
pan_astate_menu->set_name ("ArdourContextMenu");
|
||||||
|
} else {
|
||||||
|
pan_astate_menu->items().clear ();
|
||||||
|
}
|
||||||
|
|
||||||
|
pan_astate_menu->items().push_back (MenuElem (_("Manual"),
|
||||||
|
bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Off)));
|
||||||
|
pan_astate_menu->items().push_back (MenuElem (_("Play"),
|
||||||
|
bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Play)));
|
||||||
|
pan_astate_menu->items().push_back (MenuElem (_("Write"),
|
||||||
|
bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Write)));
|
||||||
|
pan_astate_menu->items().push_back (MenuElem (_("Touch"),
|
||||||
|
bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Touch)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PannerUI::build_astyle_menu ()
|
||||||
|
{
|
||||||
|
using namespace Menu_Helpers;
|
||||||
|
|
||||||
|
if (pan_astyle_menu == 0) {
|
||||||
|
pan_astyle_menu = new Menu;
|
||||||
|
pan_astyle_menu->set_name ("ArdourContextMenu");
|
||||||
|
} else {
|
||||||
|
pan_astyle_menu->items().clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
pan_astyle_menu->items().push_back (MenuElem (_("Trim")));
|
||||||
|
pan_astyle_menu->items().push_back (MenuElem (_("Abs")));
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<PBD::Controllable>
|
boost::shared_ptr<PBD::Controllable>
|
||||||
|
|
@ -263,6 +313,13 @@ PannerUI::~PannerUI ()
|
||||||
delete pan_menu;
|
delete pan_menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pan_astyle_menu) {
|
||||||
|
delete pan_astyle_menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pan_astate_menu) {
|
||||||
|
delete pan_astate_menu;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -662,7 +719,10 @@ PannerUI::pan_automation_state_button_event (GdkEventButton *ev)
|
||||||
|
|
||||||
switch (ev->button) {
|
switch (ev->button) {
|
||||||
case 1:
|
case 1:
|
||||||
pan_astate_menu.popup (1, ev->time);
|
if (pan_astate_menu == 0) {
|
||||||
|
build_astate_menu ();
|
||||||
|
}
|
||||||
|
pan_astate_menu->popup (1, ev->time);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
@ -680,7 +740,10 @@ PannerUI::pan_automation_style_button_event (GdkEventButton *ev)
|
||||||
|
|
||||||
switch (ev->button) {
|
switch (ev->button) {
|
||||||
case 1:
|
case 1:
|
||||||
pan_astyle_menu.popup (1, ev->time);
|
if (pan_astyle_menu == 0) {
|
||||||
|
build_astyle_menu ();
|
||||||
|
}
|
||||||
|
pan_astyle_menu->popup (1, ev->time);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -54,9 +54,11 @@ namespace Gtk {
|
||||||
class PannerUI : public Gtk::HBox
|
class PannerUI : public Gtk::HBox
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PannerUI (boost::shared_ptr<ARDOUR::IO>, ARDOUR::Session&);
|
PannerUI (ARDOUR::Session&);
|
||||||
~PannerUI ();
|
~PannerUI ();
|
||||||
|
|
||||||
|
virtual void set_io (boost::shared_ptr<ARDOUR::IO>);
|
||||||
|
|
||||||
void pan_changed (void *);
|
void pan_changed (void *);
|
||||||
|
|
||||||
void update_pan_sensitive ();
|
void update_pan_sensitive ();
|
||||||
|
|
@ -75,6 +77,7 @@ class PannerUI : public Gtk::HBox
|
||||||
|
|
||||||
boost::shared_ptr<ARDOUR::IO> _io;
|
boost::shared_ptr<ARDOUR::IO> _io;
|
||||||
ARDOUR::Session& _session;
|
ARDOUR::Session& _session;
|
||||||
|
std::vector<sigc::connection> connections;
|
||||||
|
|
||||||
bool ignore_toggle;
|
bool ignore_toggle;
|
||||||
bool in_pan_update;
|
bool in_pan_update;
|
||||||
|
|
@ -101,8 +104,8 @@ class PannerUI : public Gtk::HBox
|
||||||
bool panning_link_button_press (GdkEventButton*);
|
bool panning_link_button_press (GdkEventButton*);
|
||||||
bool panning_link_button_release (GdkEventButton*);
|
bool panning_link_button_release (GdkEventButton*);
|
||||||
|
|
||||||
Gtk::Menu pan_astate_menu;
|
Gtk::Menu* pan_astate_menu;
|
||||||
Gtk::Menu pan_astyle_menu;
|
Gtk::Menu* pan_astyle_menu;
|
||||||
|
|
||||||
Gtk::Button pan_automation_style_button;
|
Gtk::Button pan_automation_style_button;
|
||||||
Gtk::ToggleButton pan_automation_state_button;
|
Gtk::ToggleButton pan_automation_state_button;
|
||||||
|
|
@ -118,6 +121,8 @@ class PannerUI : public Gtk::HBox
|
||||||
void update_pan_bars (bool only_if_aplay);
|
void update_pan_bars (bool only_if_aplay);
|
||||||
void update_pan_linkage ();
|
void update_pan_linkage ();
|
||||||
void update_pan_state ();
|
void update_pan_state ();
|
||||||
|
void build_astate_menu ();
|
||||||
|
void build_astyle_menu ();
|
||||||
|
|
||||||
void panner_changed ();
|
void panner_changed ();
|
||||||
|
|
||||||
|
|
|
||||||
90
gtk2_ardour/port_group.h
Normal file
90
gtk2_ardour/port_group.h
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
#ifndef __gtk_ardour_port_group_h__
|
||||||
|
#define __gtk_ardour_port_group_h__
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <gtkmm/widget.h>
|
||||||
|
#include <gtkmm/checkbutton.h>
|
||||||
|
|
||||||
|
#include <ardour/data_type.h>
|
||||||
|
|
||||||
|
namespace ARDOUR {
|
||||||
|
class Session;
|
||||||
|
class IO;
|
||||||
|
class PortInsert;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PortMatrix;
|
||||||
|
|
||||||
|
/// A list of port names, grouped by some aspect of their type e.g. busses, tracks, system
|
||||||
|
class PortGroup
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** PortGroup constructor.
|
||||||
|
* @param n Name.
|
||||||
|
* @param p Port name prefix.
|
||||||
|
* @param v true if group should be visible in the UI, otherwise false.
|
||||||
|
*/
|
||||||
|
PortGroup (std::string const & n, std::string const & p, bool v) : name (n), prefix (p), visible (v) {}
|
||||||
|
|
||||||
|
void add (std::string const & p);
|
||||||
|
|
||||||
|
std::string name; ///< name for the group
|
||||||
|
std::string prefix; ///< prefix (before colon) e.g. "ardour:"
|
||||||
|
std::vector<std::string> ports; ///< port names
|
||||||
|
bool visible; ///< true if the group is visible in the UI
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The UI for a PortGroup
|
||||||
|
class PortGroupUI
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PortGroupUI (PortMatrix&, PortGroup&);
|
||||||
|
|
||||||
|
Gtk::Widget& get_visibility_checkbutton ();
|
||||||
|
PortGroup& port_group () { return _port_group; }
|
||||||
|
void setup_visibility ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void port_checkbutton_toggled (Gtk::CheckButton*, int, int);
|
||||||
|
bool port_checkbutton_release (GdkEventButton* ev, Gtk::CheckButton* b, int r, int c);
|
||||||
|
void visibility_checkbutton_toggled ();
|
||||||
|
|
||||||
|
PortMatrix& _port_matrix; ///< the PortMatrix that we are working for
|
||||||
|
PortGroup& _port_group; ///< the PortGroup that we are representing
|
||||||
|
bool _ignore_check_button_toggle;
|
||||||
|
Gtk::CheckButton _visibility_checkbutton;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A list of PortGroups
|
||||||
|
class PortGroupList : public std::list<PortGroup*>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Mask {
|
||||||
|
BUSS = 0x1,
|
||||||
|
TRACK = 0x2,
|
||||||
|
SYSTEM = 0x4,
|
||||||
|
OTHER = 0x8
|
||||||
|
};
|
||||||
|
|
||||||
|
PortGroupList (ARDOUR::Session &, ARDOUR::DataType, bool, Mask);
|
||||||
|
|
||||||
|
void refresh ();
|
||||||
|
int n_visible_ports () const;
|
||||||
|
std::string get_port_by_index (int, bool with_prefix = true) const;
|
||||||
|
void set_type (ARDOUR::DataType);
|
||||||
|
void set_offer_inputs (bool);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ARDOUR::Session& _session;
|
||||||
|
ARDOUR::DataType _type;
|
||||||
|
bool _offer_inputs;
|
||||||
|
|
||||||
|
PortGroup buss;
|
||||||
|
PortGroup track;
|
||||||
|
PortGroup system;
|
||||||
|
PortGroup other;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __gtk_ardour_port_group_h__ */
|
||||||
|
|
@ -69,59 +69,8 @@ PortGroupUI::PortGroupUI (PortMatrix& m, PortGroup& g)
|
||||||
, _ignore_check_button_toggle (false)
|
, _ignore_check_button_toggle (false)
|
||||||
, _visibility_checkbutton (g.name)
|
, _visibility_checkbutton (g.name)
|
||||||
{
|
{
|
||||||
int const ports = _port_group.ports.size();
|
_port_group.visible = true;
|
||||||
int const rows = _port_matrix.n_rows ();
|
|
||||||
|
|
||||||
if (rows == 0 || ports == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sort out the table and the checkbuttons inside it */
|
|
||||||
|
|
||||||
_table.resize (rows, ports);
|
|
||||||
_port_checkbuttons.resize (rows);
|
|
||||||
for (int i = 0; i < rows; ++i) {
|
|
||||||
_port_checkbuttons[i].resize (ports);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < rows; ++i) {
|
|
||||||
for (uint32_t j = 0; j < _port_group.ports.size(); ++j) {
|
|
||||||
CheckButton* b = new CheckButton;
|
|
||||||
|
|
||||||
b->signal_toggled().connect (
|
|
||||||
sigc::bind (sigc::mem_fun (*this, &PortGroupUI::port_checkbutton_toggled), b, i, j));
|
|
||||||
|
|
||||||
b->signal_button_release_event().connect (
|
|
||||||
sigc::bind (sigc::mem_fun (*this, &PortGroupUI::port_checkbutton_release), b, i, j), false);
|
|
||||||
|
|
||||||
_port_checkbuttons[i][j] = b;
|
|
||||||
|
|
||||||
cerr << this << " bind to " << &_port_checkbuttons << " via " << b
|
|
||||||
<< endl;
|
|
||||||
|
|
||||||
_table.attach (*b, j, j + 1, i, i + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_table_box.add (_table);
|
|
||||||
|
|
||||||
_ignore_check_button_toggle = true;
|
|
||||||
|
|
||||||
/* Set the state of the check boxes according to current connections */
|
|
||||||
for (int i = 0; i < rows; ++i) {
|
|
||||||
for (uint32_t j = 0; j < _port_group.ports.size(); ++j) {
|
|
||||||
std::string const t = _port_group.prefix + _port_group.ports[j];
|
|
||||||
bool const s = _port_matrix.get_state (i, t);
|
|
||||||
_port_checkbuttons[i][j]->set_active (s);
|
|
||||||
if (s) {
|
|
||||||
_port_group.visible = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_ignore_check_button_toggle = false;
|
_ignore_check_button_toggle = false;
|
||||||
|
|
||||||
_visibility_checkbutton.signal_toggled().connect (sigc::mem_fun (*this, &PortGroupUI::visibility_checkbutton_toggled));
|
_visibility_checkbutton.signal_toggled().connect (sigc::mem_fun (*this, &PortGroupUI::visibility_checkbutton_toggled));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -132,34 +81,6 @@ PortGroupUI::visibility_checkbutton_toggled ()
|
||||||
_port_group.visible = _visibility_checkbutton.get_active ();
|
_port_group.visible = _visibility_checkbutton.get_active ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return Width and height of a single checkbutton in a port group table */
|
|
||||||
std::pair<int, int>
|
|
||||||
PortGroupUI::unit_size () const
|
|
||||||
{
|
|
||||||
if (_port_checkbuttons.empty() || _port_checkbuttons[0].empty())
|
|
||||||
{
|
|
||||||
return std::pair<int, int> (0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int r = 0;
|
|
||||||
/* We can't ask for row spacing unless there >1 rows, otherwise we get a warning */
|
|
||||||
if (_table.property_n_rows() > 1) {
|
|
||||||
r = _table.get_row_spacing (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_pair (
|
|
||||||
_port_checkbuttons[0][0]->get_width() + _table.get_col_spacing (0),
|
|
||||||
_port_checkbuttons[0][0]->get_height() + r
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return Table widget containing the port checkbuttons */
|
|
||||||
Widget&
|
|
||||||
PortGroupUI::get_table ()
|
|
||||||
{
|
|
||||||
return _table_box;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return Checkbutton used to toggle visibility */
|
/** @return Checkbutton used to toggle visibility */
|
||||||
Widget&
|
Widget&
|
||||||
PortGroupUI::get_visibility_checkbutton ()
|
PortGroupUI::get_visibility_checkbutton ()
|
||||||
|
|
@ -173,293 +94,21 @@ void
|
||||||
PortGroupUI::port_checkbutton_toggled (CheckButton* b, int r, int c)
|
PortGroupUI::port_checkbutton_toggled (CheckButton* b, int r, int c)
|
||||||
{
|
{
|
||||||
if (_ignore_check_button_toggle == false) {
|
if (_ignore_check_button_toggle == false) {
|
||||||
_port_matrix.set_state (r, _port_group.prefix + _port_group.ports[c], b->get_active(), 0);
|
// _port_matrix.hide_group (_port_group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
PortGroupUI::port_checkbutton_release (GdkEventButton* ev, CheckButton* b, int r, int c)
|
|
||||||
{
|
|
||||||
cerr << this << " RELEASE on " << b << " state = " << ev->state << endl;
|
|
||||||
|
|
||||||
if (ev->state == 0) {
|
|
||||||
/* let usual toggle handler take care of it */
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The fun starts here
|
|
||||||
*/
|
|
||||||
|
|
||||||
const size_t ports = _port_group.ports.size();
|
|
||||||
const size_t rows = _port_matrix.n_rows ();
|
|
||||||
|
|
||||||
if (rows == 0 || ports == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For each port in the group, change the state of
|
|
||||||
the connection for the corresponding "connector" port.
|
|
||||||
*/
|
|
||||||
|
|
||||||
for (size_t j = c; j < ports; ++j) {
|
|
||||||
|
|
||||||
/* we've got a port to connect, now lets find the thing to
|
|
||||||
connect it too ... (search "down" the rows)
|
|
||||||
*/
|
|
||||||
|
|
||||||
cerr << "we're going to connect port " << j << " of " << ports << endl;
|
|
||||||
|
|
||||||
for (size_t i = r; i < rows; ++i) {
|
|
||||||
|
|
||||||
cerr << this << " going to connect to row " << i << " of " << rows << endl;
|
|
||||||
cerr << "access [" << i << "][" << j << "]\n";
|
|
||||||
cerr << " @ " << &_port_checkbuttons << endl;
|
|
||||||
|
|
||||||
_port_checkbuttons[i][j]->set_active (!_port_checkbuttons[i][j]->get_active());
|
|
||||||
|
|
||||||
/* next time, get at least as far as this port before looking
|
|
||||||
for more.
|
|
||||||
*/
|
|
||||||
|
|
||||||
r = i + 1;
|
|
||||||
|
|
||||||
/* changed connection state, stop looking for more */
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set up visibility of the port group according to PortGroup::visible */
|
/** Set up visibility of the port group according to PortGroup::visible */
|
||||||
void
|
void
|
||||||
PortGroupUI::setup_visibility ()
|
PortGroupUI::setup_visibility ()
|
||||||
{
|
{
|
||||||
if (!_port_group.ports.empty() && _port_group.visible) {
|
|
||||||
_table_box.show ();
|
|
||||||
} else {
|
|
||||||
_table_box.hide ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_visibility_checkbutton.get_active () != _port_group.visible) {
|
if (_visibility_checkbutton.get_active () != _port_group.visible) {
|
||||||
|
|
||||||
_visibility_checkbutton.set_active (_port_group.visible);
|
_visibility_checkbutton.set_active (_port_group.visible);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RotatedLabelSet::RotatedLabelSet (PortGroupList& g)
|
|
||||||
: Glib::ObjectBase ("RotatedLabelSet"), Widget (), _port_group_list (g), _base_width (128)
|
|
||||||
{
|
|
||||||
set_flags (NO_WINDOW);
|
|
||||||
if (getenv ("AD_ANGLE") != 0) {
|
|
||||||
set_angle (atoi (getenv ("AD_ANGLE")));
|
|
||||||
} else {
|
|
||||||
set_angle (45);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RotatedLabelSet::~RotatedLabelSet ()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Set the angle that the labels are drawn at.
|
|
||||||
* @param degrees New angle in degrees.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
RotatedLabelSet::set_angle (int degrees)
|
|
||||||
{
|
|
||||||
_angle_degrees = degrees;
|
|
||||||
_angle_radians = M_PI * _angle_degrees / 180;
|
|
||||||
|
|
||||||
queue_resize ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RotatedLabelSet::on_size_request (Requisition* requisition)
|
|
||||||
{
|
|
||||||
*requisition = Requisition ();
|
|
||||||
|
|
||||||
if (_pango_layout == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Our height is the highest label */
|
|
||||||
requisition->height = 0;
|
|
||||||
for (PortGroupList::const_iterator i = _port_group_list.begin(); i != _port_group_list.end(); ++i) {
|
|
||||||
for (std::vector<std::string>::const_iterator j = (*i)->ports.begin(); j != (*i)->ports.end(); ++j) {
|
|
||||||
std::pair<int, int> const d = setup_layout (*j);
|
|
||||||
if (d.second > requisition->height) {
|
|
||||||
requisition->height = d.second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* And our width is the base plus the width of the last label */
|
|
||||||
requisition->width = _base_width;
|
|
||||||
int const n = _port_group_list.n_visible_ports ();
|
|
||||||
if (n > 0) {
|
|
||||||
std::pair<int, int> const d = setup_layout (_port_group_list.get_port_by_index (n - 1, false));
|
|
||||||
requisition->width += d.first;
|
|
||||||
}
|
|
||||||
|
|
||||||
cerr << "Labels will be " << requisition->width << " x " << requisition->height << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RotatedLabelSet::on_size_allocate (Allocation& allocation)
|
|
||||||
{
|
|
||||||
set_allocation (allocation);
|
|
||||||
|
|
||||||
if (_gdk_window) {
|
|
||||||
_gdk_window->move_resize (allocation.get_x(), allocation.get_y(), allocation.get_width(), allocation.get_height());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RotatedLabelSet::on_realize ()
|
|
||||||
{
|
|
||||||
Widget::on_realize ();
|
|
||||||
|
|
||||||
Glib::RefPtr<Style> style = get_style ();
|
|
||||||
|
|
||||||
if (!_gdk_window) {
|
|
||||||
GdkWindowAttr attributes;
|
|
||||||
memset (&attributes, 0, sizeof (attributes));
|
|
||||||
|
|
||||||
Allocation allocation = get_allocation ();
|
|
||||||
attributes.x = allocation.get_x ();
|
|
||||||
attributes.y = allocation.get_y ();
|
|
||||||
attributes.width = allocation.get_width ();
|
|
||||||
attributes.height = allocation.get_height ();
|
|
||||||
|
|
||||||
attributes.event_mask = get_events () | Gdk::EXPOSURE_MASK;
|
|
||||||
attributes.window_type = GDK_WINDOW_CHILD;
|
|
||||||
attributes.wclass = GDK_INPUT_OUTPUT;
|
|
||||||
|
|
||||||
_gdk_window = Gdk::Window::create (get_window (), &attributes, GDK_WA_X | GDK_WA_Y);
|
|
||||||
unset_flags (NO_WINDOW);
|
|
||||||
set_window (_gdk_window);
|
|
||||||
|
|
||||||
_bg_colour = style->get_bg (STATE_NORMAL );
|
|
||||||
modify_bg (STATE_NORMAL, _bg_colour);
|
|
||||||
_fg_colour = style->get_fg (STATE_NORMAL);
|
|
||||||
|
|
||||||
_gdk_window->set_user_data (gobj ());
|
|
||||||
|
|
||||||
/* Set up Pango stuff */
|
|
||||||
_pango_context = create_pango_context ();
|
|
||||||
|
|
||||||
Pango::Matrix matrix = PANGO_MATRIX_INIT;
|
|
||||||
pango_matrix_rotate (&matrix, _angle_degrees);
|
|
||||||
_pango_context->set_matrix (matrix);
|
|
||||||
|
|
||||||
_pango_layout = Pango::Layout::create (_pango_context);
|
|
||||||
_gc = Gdk::GC::create (get_window ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RotatedLabelSet::on_unrealize()
|
|
||||||
{
|
|
||||||
_gdk_window.clear ();
|
|
||||||
|
|
||||||
Widget::on_unrealize ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Set up our Pango layout to plot a given string, and compute its dimensions once
|
|
||||||
* it has been rotated.
|
|
||||||
* @param s String to use.
|
|
||||||
* @return width and height of the rotated string, in pixels.
|
|
||||||
*/
|
|
||||||
|
|
||||||
std::pair<int, int>
|
|
||||||
RotatedLabelSet::setup_layout (std::string const & s)
|
|
||||||
{
|
|
||||||
_pango_layout->set_text (s);
|
|
||||||
|
|
||||||
/* Here's the unrotated size */
|
|
||||||
int w;
|
|
||||||
int h;
|
|
||||||
_pango_layout->get_pixel_size (w, h);
|
|
||||||
|
|
||||||
/* Rotate the width and height as appropriate. I thought Pango might be able
|
|
||||||
to do this for us, but I can't find out how...
|
|
||||||
*/
|
|
||||||
|
|
||||||
std::pair<int, int> d;
|
|
||||||
|
|
||||||
// cerr << "\"" << s << "\" was " << w << " x " << h << endl;
|
|
||||||
|
|
||||||
d.first = int (fabs (w * cos (_angle_radians) + h * sin (_angle_radians)));
|
|
||||||
d.second = int (fabs (w * sin (_angle_radians) + h * cos (_angle_radians)));
|
|
||||||
|
|
||||||
// cerr << "\trotated by " << _angle_degrees << " = " << d.first << " x " << d.second << endl;
|
|
||||||
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
RotatedLabelSet::on_expose_event (GdkEventExpose* event)
|
|
||||||
{
|
|
||||||
if (!_gdk_window) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int const height = get_allocation().get_height ();
|
|
||||||
double const spacing = double (_base_width) / _port_group_list.n_visible_ports();
|
|
||||||
|
|
||||||
/* Plot all the visible labels; really we should clip for efficiency */
|
|
||||||
int n = 0;
|
|
||||||
for (PortGroupList::const_iterator i = _port_group_list.begin(); i != _port_group_list.end(); ++i) {
|
|
||||||
if ((*i)->visible) {
|
|
||||||
for (uint32_t j = 0; j < (*i)->ports.size(); ++j) {
|
|
||||||
std::pair<int, int> const d = setup_layout ((*i)->ports[j]);
|
|
||||||
int x, y;
|
|
||||||
if (getenv ("AD_X_SHIFT") != 0) {
|
|
||||||
x = atoi (getenv ("AD_X_SHIFT"));
|
|
||||||
} else {
|
|
||||||
x = 0;
|
|
||||||
}
|
|
||||||
if (getenv ("AD_Y_SHIFT") != 0) {
|
|
||||||
y = atoi (getenv ("AD_Y_SHIFT"));
|
|
||||||
} else {
|
|
||||||
y = 0;
|
|
||||||
}
|
|
||||||
get_window()->draw_layout (_gc, int ((n + 0.25) * spacing) + x, height - d.second + y, _pango_layout, _fg_colour, _bg_colour);
|
|
||||||
++n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set the `base width'. This is the width of the base of the label set, ie:
|
|
||||||
*
|
|
||||||
* L L L L
|
|
||||||
* E E E E
|
|
||||||
* B B B B
|
|
||||||
* A A A A
|
|
||||||
* L L L L
|
|
||||||
* <--w-->
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
RotatedLabelSet::set_base_width (int w)
|
|
||||||
{
|
|
||||||
_base_width = w;
|
|
||||||
queue_resize ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PortMatrix::PortMatrix (ARDOUR::Session& session, ARDOUR::DataType type, bool offer_inputs, PortGroupList::Mask mask)
|
PortMatrix::PortMatrix (ARDOUR::Session& session, ARDOUR::DataType type, bool offer_inputs, PortGroupList::Mask mask)
|
||||||
: _offer_inputs (offer_inputs), _port_group_list (session, type, offer_inputs, mask), _type (type),
|
: _offer_inputs (offer_inputs), _port_group_list (session, type, offer_inputs, mask), _type (type)
|
||||||
_column_labels (_port_group_list)
|
|
||||||
{
|
{
|
||||||
_row_labels_vbox = 0;
|
_row_labels_vbox = 0;
|
||||||
_side_vbox_pad = 0;
|
_side_vbox_pad = 0;
|
||||||
|
|
@ -472,25 +121,10 @@ PortMatrix::PortMatrix (ARDOUR::Session& session, ARDOUR::DataType type, bool of
|
||||||
|
|
||||||
VBox* b = manage (new VBox);
|
VBox* b = manage (new VBox);
|
||||||
|
|
||||||
if (offer_inputs) {
|
b->pack_start (_port_group_hbox, false, false);
|
||||||
b->pack_start (_port_group_hbox, false, false);
|
b->pack_start (_port_group_hbox, false, false);
|
||||||
b->pack_start (_column_labels, false, false);
|
|
||||||
} else {
|
|
||||||
b->pack_start (_column_labels, false, false);
|
|
||||||
b->pack_start (_port_group_hbox, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
Alignment* a;
|
_scrolled_window.add (matrix);
|
||||||
|
|
||||||
if (offer_inputs) {
|
|
||||||
a = manage (new Alignment (1, 0, 0, 0));
|
|
||||||
} else {
|
|
||||||
a = manage (new Alignment (0, 1, 0, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
a->add (*b);
|
|
||||||
|
|
||||||
_scrolled_window.add (*a);
|
|
||||||
|
|
||||||
if (offer_inputs) {
|
if (offer_inputs) {
|
||||||
_overall_hbox.pack_start (_side_vbox, false, false, 6);
|
_overall_hbox.pack_start (_side_vbox, false, false, 6);
|
||||||
|
|
@ -535,7 +169,6 @@ PortMatrix::clear ()
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::vector<PortGroupUI*>::iterator i = _port_group_ui.begin(); i != _port_group_ui.end(); ++i) {
|
for (std::vector<PortGroupUI*>::iterator i = _port_group_ui.begin(); i != _port_group_ui.end(); ++i) {
|
||||||
_port_group_hbox.remove ((*i)->get_table());
|
|
||||||
_visibility_checkbutton_box.remove ((*i)->get_visibility_checkbutton());
|
_visibility_checkbutton_box.remove ((*i)->get_visibility_checkbutton());
|
||||||
delete *i;
|
delete *i;
|
||||||
}
|
}
|
||||||
|
|
@ -550,46 +183,16 @@ PortMatrix::clear ()
|
||||||
void
|
void
|
||||||
PortMatrix::setup_dimensions ()
|
PortMatrix::setup_dimensions ()
|
||||||
{
|
{
|
||||||
/* Get some dimensions from various places */
|
|
||||||
int const scrollbar_height = _scrolled_window.get_hscrollbar()->get_height();
|
|
||||||
|
|
||||||
std::pair<int, int> unit_size (0, 0);
|
|
||||||
int port_group_tables_height = 0;
|
|
||||||
for (std::vector<PortGroupUI*>::iterator i = _port_group_ui.begin(); i != _port_group_ui.end(); ++i) {
|
|
||||||
std::pair<int, int> const u = (*i)->unit_size ();
|
|
||||||
unit_size.first = std::max (unit_size.first, u.first);
|
|
||||||
unit_size.second = std::max (unit_size.second, u.second);
|
|
||||||
port_group_tables_height = std::max (
|
|
||||||
port_group_tables_height, (*i)->get_table().get_height()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Column labels */
|
|
||||||
_column_labels.set_base_width (_port_group_list.n_visible_ports () * unit_size.first);
|
|
||||||
|
|
||||||
/* Scrolled window */
|
|
||||||
/* XXX: really shouldn't set a minimum horizontal size here, but if we don't
|
|
||||||
the window starts up very small.
|
|
||||||
The constant value in the set_size_request() computation will control
|
|
||||||
how big the scrolled window will be if we fill the port matrix will a gajillion
|
|
||||||
ports.
|
|
||||||
*/
|
|
||||||
|
|
||||||
_scrolled_window.set_size_request (
|
|
||||||
std::min (_column_labels.get_width(), 400),
|
|
||||||
_column_labels.get_height() + port_group_tables_height + scrollbar_height + 16
|
|
||||||
);
|
|
||||||
|
|
||||||
/* Row labels */
|
/* Row labels */
|
||||||
for (std::vector<EventBox*>::iterator j = _row_labels.begin(); j != _row_labels.end(); ++j) {
|
for (std::vector<EventBox*>::iterator j = _row_labels.begin(); j != _row_labels.end(); ++j) {
|
||||||
(*j)->get_child()->set_size_request (-1, unit_size.second);
|
(*j)->get_child()->set_size_request (-1, matrix.row_spacing());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_side_vbox_pad) {
|
if (_side_vbox_pad) {
|
||||||
if (_offer_inputs) {
|
if (_offer_inputs) {
|
||||||
_side_vbox_pad->set_size_request (-1, unit_size.second / 4);
|
_side_vbox_pad->set_size_request (-1, matrix.row_spacing() / 4);
|
||||||
} else {
|
} else {
|
||||||
_side_vbox_pad->set_size_request (-1, scrollbar_height + unit_size.second / 4);
|
_side_vbox_pad->set_size_request (-1, matrix.row_spacing() / 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -647,7 +250,6 @@ PortMatrix::setup ()
|
||||||
PortGroupUI* t = new PortGroupUI (*this, **i);
|
PortGroupUI* t = new PortGroupUI (*this, **i);
|
||||||
|
|
||||||
_port_group_ui.push_back (t);
|
_port_group_ui.push_back (t);
|
||||||
_port_group_hbox.pack_start (t->get_table(), false, false);
|
|
||||||
|
|
||||||
_visibility_checkbutton_box.pack_start (t->get_visibility_checkbutton(), false, false);
|
_visibility_checkbutton_box.pack_start (t->get_visibility_checkbutton(), false, false);
|
||||||
|
|
||||||
|
|
@ -666,23 +268,14 @@ PortMatrix::setup ()
|
||||||
void
|
void
|
||||||
PortMatrix::reset_visibility ()
|
PortMatrix::reset_visibility ()
|
||||||
{
|
{
|
||||||
/* now adjust visibility and coloring */
|
|
||||||
|
|
||||||
bool even = true;
|
|
||||||
Gdk::Color odd_bg (color_from_style ("OddPortGroups", STATE_NORMAL, "fg"));
|
|
||||||
Gdk::Color even_bg (color_from_style ("EvenPortGroups", STATE_NORMAL, "fg"));
|
|
||||||
|
|
||||||
for (std::vector<PortGroupUI*>::iterator i = _port_group_ui.begin(); i != _port_group_ui.end(); ++i) {
|
for (std::vector<PortGroupUI*>::iterator i = _port_group_ui.begin(); i != _port_group_ui.end(); ++i) {
|
||||||
|
|
||||||
(*i)->setup_visibility ();
|
(*i)->setup_visibility ();
|
||||||
|
|
||||||
if ((*i)->port_group().visible) {
|
if ((*i)->port_group().visible) {
|
||||||
if (even) {
|
matrix.show_group ((*i)->port_group());
|
||||||
(*i)->get_table().modify_bg (STATE_NORMAL, even_bg);
|
} else {
|
||||||
} else {
|
matrix.hide_group ((*i)->port_group());
|
||||||
(*i)->get_table().modify_bg (STATE_NORMAL, odd_bg);
|
|
||||||
}
|
|
||||||
even = !even;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,8 @@
|
||||||
#include <gtkmm/scrolledwindow.h>
|
#include <gtkmm/scrolledwindow.h>
|
||||||
|
|
||||||
#include "ardour_dialog.h"
|
#include "ardour_dialog.h"
|
||||||
|
#include "port_group.h"
|
||||||
|
#include "matrix.h"
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
class Session;
|
class Session;
|
||||||
|
|
@ -35,118 +37,6 @@ namespace ARDOUR {
|
||||||
class PortInsert;
|
class PortInsert;
|
||||||
}
|
}
|
||||||
|
|
||||||
class PortMatrix;
|
|
||||||
|
|
||||||
/// A list of port names, grouped by some aspect of their type e.g. busses, tracks, system
|
|
||||||
class PortGroup
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/** PortGroup constructor.
|
|
||||||
* @param n Name.
|
|
||||||
* @param p Port name prefix.
|
|
||||||
* @param v true if group should be visible in the UI, otherwise false.
|
|
||||||
*/
|
|
||||||
PortGroup (std::string const & n, std::string const & p, bool v) : name (n), prefix (p), visible (v) {}
|
|
||||||
|
|
||||||
void add (std::string const & p);
|
|
||||||
|
|
||||||
std::string name; ///< name for the group
|
|
||||||
std::string prefix; ///< prefix (before colon) e.g. "ardour:"
|
|
||||||
std::vector<std::string> ports; ///< port names
|
|
||||||
bool visible; ///< true if the group is visible in the UI
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The UI for a PortGroup
|
|
||||||
class PortGroupUI
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PortGroupUI (PortMatrix&, PortGroup&);
|
|
||||||
|
|
||||||
Gtk::Widget& get_table ();
|
|
||||||
Gtk::Widget& get_visibility_checkbutton ();
|
|
||||||
std::pair<int, int> unit_size () const;
|
|
||||||
PortGroup& port_group () { return _port_group; }
|
|
||||||
void setup_visibility ();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void port_checkbutton_toggled (Gtk::CheckButton*, int, int);
|
|
||||||
bool port_checkbutton_release (GdkEventButton* ev, Gtk::CheckButton* b, int r, int c);
|
|
||||||
void visibility_checkbutton_toggled ();
|
|
||||||
|
|
||||||
PortMatrix& _port_matrix; ///< the PortMatrix that we are working for
|
|
||||||
PortGroup& _port_group; ///< the PortGroup that we are representing
|
|
||||||
bool _ignore_check_button_toggle;
|
|
||||||
Gtk::Table _table;
|
|
||||||
Gtk::EventBox _table_box;
|
|
||||||
std::vector<std::vector<Gtk::CheckButton* > > _port_checkbuttons;
|
|
||||||
Gtk::CheckButton _visibility_checkbutton;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A list of PortGroups
|
|
||||||
class PortGroupList : public std::list<PortGroup*>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum Mask {
|
|
||||||
BUSS = 0x1,
|
|
||||||
TRACK = 0x2,
|
|
||||||
SYSTEM = 0x4,
|
|
||||||
OTHER = 0x8
|
|
||||||
};
|
|
||||||
|
|
||||||
PortGroupList (ARDOUR::Session &, ARDOUR::DataType, bool, Mask);
|
|
||||||
|
|
||||||
void refresh ();
|
|
||||||
int n_visible_ports () const;
|
|
||||||
std::string get_port_by_index (int, bool with_prefix = true) const;
|
|
||||||
void set_type (ARDOUR::DataType);
|
|
||||||
void set_offer_inputs (bool);
|
|
||||||
|
|
||||||
private:
|
|
||||||
ARDOUR::Session& _session;
|
|
||||||
ARDOUR::DataType _type;
|
|
||||||
bool _offer_inputs;
|
|
||||||
|
|
||||||
PortGroup buss;
|
|
||||||
PortGroup track;
|
|
||||||
PortGroup system;
|
|
||||||
PortGroup other;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/// A widget which provides a set of rotated text labels
|
|
||||||
class RotatedLabelSet : public Gtk::Widget {
|
|
||||||
public:
|
|
||||||
RotatedLabelSet (PortGroupList&);
|
|
||||||
virtual ~RotatedLabelSet ();
|
|
||||||
|
|
||||||
void set_angle (int);
|
|
||||||
void set_base_width (int);
|
|
||||||
void update_visibility ();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void on_size_request (Gtk::Requisition*);
|
|
||||||
virtual void on_size_allocate (Gtk::Allocation&);
|
|
||||||
virtual void on_realize ();
|
|
||||||
virtual void on_unrealize ();
|
|
||||||
virtual bool on_expose_event (GdkEventExpose*);
|
|
||||||
|
|
||||||
Glib::RefPtr<Gdk::Window> _gdk_window;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::pair<int, int> setup_layout (std::string const &);
|
|
||||||
|
|
||||||
PortGroupList& _port_group_list; ///< list of ports to display
|
|
||||||
int _angle_degrees; ///< label rotation angle in degrees
|
|
||||||
double _angle_radians; ///< label rotation angle in radians
|
|
||||||
int _base_width; ///< width of labels; see set_base_width() for more details
|
|
||||||
Glib::RefPtr<Pango::Context> _pango_context;
|
|
||||||
Glib::RefPtr<Pango::Layout> _pango_layout;
|
|
||||||
Glib::RefPtr<Gdk::GC> _gc;
|
|
||||||
Gdk::Color _fg_colour;
|
|
||||||
Gdk::Color _bg_colour;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class PortMatrix : public Gtk::VBox {
|
class PortMatrix : public Gtk::VBox {
|
||||||
public:
|
public:
|
||||||
PortMatrix (ARDOUR::Session&, ARDOUR::DataType, bool, PortGroupList::Mask);
|
PortMatrix (ARDOUR::Session&, ARDOUR::DataType, bool, PortGroupList::Mask);
|
||||||
|
|
@ -184,10 +74,10 @@ class PortMatrix : public Gtk::VBox {
|
||||||
private:
|
private:
|
||||||
PortGroupList _port_group_list;
|
PortGroupList _port_group_list;
|
||||||
ARDOUR::DataType _type;
|
ARDOUR::DataType _type;
|
||||||
|
Matrix matrix;
|
||||||
std::vector<PortGroupUI*> _port_group_ui;
|
std::vector<PortGroupUI*> _port_group_ui;
|
||||||
std::vector<Gtk::EventBox*> _row_labels;
|
std::vector<Gtk::EventBox*> _row_labels;
|
||||||
Gtk::VBox* _row_labels_vbox;
|
Gtk::VBox* _row_labels_vbox;
|
||||||
RotatedLabelSet _column_labels;
|
|
||||||
Gtk::HBox _overall_hbox;
|
Gtk::HBox _overall_hbox;
|
||||||
Gtk::VBox _side_vbox;
|
Gtk::VBox _side_vbox;
|
||||||
Gtk::HBox _port_group_hbox;
|
Gtk::HBox _port_group_hbox;
|
||||||
|
|
|
||||||
|
|
@ -82,10 +82,9 @@ bool ProcessorBox::get_colors = true;
|
||||||
Gdk::Color* ProcessorBox::active_processor_color;
|
Gdk::Color* ProcessorBox::active_processor_color;
|
||||||
Gdk::Color* ProcessorBox::inactive_processor_color;
|
Gdk::Color* ProcessorBox::inactive_processor_color;
|
||||||
|
|
||||||
ProcessorBox::ProcessorBox (Placement pcmnt, Session& sess, boost::shared_ptr<Route> rt, PluginSelector &plugsel,
|
ProcessorBox::ProcessorBox (Placement pcmnt, Session& sess, PluginSelector &plugsel,
|
||||||
RouteRedirectSelection & rsel, bool owner_is_mixer)
|
RouteRedirectSelection & rsel, bool owner_is_mixer)
|
||||||
: _route(rt),
|
: _session(sess),
|
||||||
_session(sess),
|
|
||||||
_owner_is_mixer (owner_is_mixer),
|
_owner_is_mixer (owner_is_mixer),
|
||||||
_placement(pcmnt),
|
_placement(pcmnt),
|
||||||
_plugin_selector(plugsel),
|
_plugin_selector(plugsel),
|
||||||
|
|
@ -138,27 +137,29 @@ ProcessorBox::ProcessorBox (Placement pcmnt, Session& sess, boost::shared_ptr<Ro
|
||||||
|
|
||||||
pack_start (processor_eventbox, true, true);
|
pack_start (processor_eventbox, true, true);
|
||||||
|
|
||||||
_route->processors_changed.connect (mem_fun(*this, &ProcessorBox::redisplay_processors));
|
|
||||||
_route->GoingAway.connect (mem_fun (*this, &ProcessorBox::route_going_away));
|
|
||||||
|
|
||||||
processor_eventbox.signal_enter_notify_event().connect (bind (sigc::ptr_fun (ProcessorBox::enter_box), this));
|
processor_eventbox.signal_enter_notify_event().connect (bind (sigc::ptr_fun (ProcessorBox::enter_box), this));
|
||||||
|
|
||||||
processor_display.signal_button_press_event().connect (mem_fun(*this, &ProcessorBox::processor_button_press_event), false);
|
processor_display.signal_button_press_event().connect (mem_fun(*this, &ProcessorBox::processor_button_press_event), false);
|
||||||
processor_display.signal_button_release_event().connect (mem_fun(*this, &ProcessorBox::processor_button_release_event));
|
processor_display.signal_button_release_event().connect (mem_fun(*this, &ProcessorBox::processor_button_release_event));
|
||||||
|
|
||||||
/* start off as a passthru strip. we'll correct this, if necessary,
|
|
||||||
in update_diskstream_display().
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* now force an update of all the various elements */
|
|
||||||
|
|
||||||
redisplay_processors ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessorBox::~ProcessorBox ()
|
ProcessorBox::~ProcessorBox ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ProcessorBox::set_route (boost::shared_ptr<Route> r)
|
||||||
|
{
|
||||||
|
connections.clear ();
|
||||||
|
|
||||||
|
_route = r;
|
||||||
|
|
||||||
|
connections.push_back (_route->processors_changed.connect (mem_fun(*this, &ProcessorBox::redisplay_processors)));
|
||||||
|
connections.push_back (_route->GoingAway.connect (mem_fun (*this, &ProcessorBox::route_going_away)));
|
||||||
|
|
||||||
|
redisplay_processors ();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ProcessorBox::route_going_away ()
|
ProcessorBox::route_going_away ()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -68,10 +68,10 @@ namespace ARDOUR {
|
||||||
class ProcessorBox : public Gtk::HBox, public PluginInterestedObject
|
class ProcessorBox : public Gtk::HBox, public PluginInterestedObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ProcessorBox (ARDOUR::Placement, ARDOUR::Session&,
|
ProcessorBox (ARDOUR::Placement, ARDOUR::Session&, PluginSelector &, RouteRedirectSelection &, bool owner_is_mixer = false);
|
||||||
boost::shared_ptr<ARDOUR::Route>, PluginSelector &, RouteRedirectSelection &, bool owner_is_mixer = false);
|
|
||||||
~ProcessorBox ();
|
~ProcessorBox ();
|
||||||
|
|
||||||
|
void set_route (boost::shared_ptr<ARDOUR::Route>);
|
||||||
void set_width (Width);
|
void set_width (Width);
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
|
|
@ -87,14 +87,12 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject
|
||||||
|
|
||||||
static void register_actions();
|
static void register_actions();
|
||||||
|
|
||||||
protected:
|
|
||||||
void set_stuff_from_route ();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::shared_ptr<ARDOUR::Route> _route;
|
boost::shared_ptr<ARDOUR::Route> _route;
|
||||||
ARDOUR::Session & _session;
|
ARDOUR::Session & _session;
|
||||||
bool _owner_is_mixer;
|
bool _owner_is_mixer;
|
||||||
bool ab_direction;
|
bool ab_direction;
|
||||||
|
std::vector<sigc::connection> connections;
|
||||||
|
|
||||||
ARDOUR::Placement _placement;
|
ARDOUR::Placement _placement;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -229,8 +229,11 @@ RouteParams_UI::setup_processor_boxes()
|
||||||
cleanup_processor_boxes();
|
cleanup_processor_boxes();
|
||||||
|
|
||||||
// construct new redirect boxes
|
// construct new redirect boxes
|
||||||
pre_insert_box = new ProcessorBox(PreFader, *session, _route, *_plugin_selector, _rr_selection);
|
pre_insert_box = new ProcessorBox(PreFader, *session, *_plugin_selector, _rr_selection);
|
||||||
post_insert_box = new ProcessorBox(PostFader, *session, _route, *_plugin_selector, _rr_selection);
|
post_insert_box = new ProcessorBox(PostFader, *session, *_plugin_selector, _rr_selection);
|
||||||
|
|
||||||
|
pre_insert_box->set_route (_route);
|
||||||
|
post_insert_box->set_route (_route);
|
||||||
|
|
||||||
pre_redir_hpane.pack1 (*pre_insert_box);
|
pre_redir_hpane.pack1 (*pre_insert_box);
|
||||||
post_redir_hpane.pack1 (*post_insert_box);
|
post_redir_hpane.pack1 (*post_insert_box);
|
||||||
|
|
|
||||||
|
|
@ -106,9 +106,9 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
|
||||||
size_button (_("h")), // height
|
size_button (_("h")), // height
|
||||||
automation_button (_("a")),
|
automation_button (_("a")),
|
||||||
visual_button (_("v")),
|
visual_button (_("v")),
|
||||||
gm (rt, sess, slider, true)
|
gm (sess, slider, true)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
gm.set_io (rt);
|
||||||
gm.get_level_meter().set_no_show_all();
|
gm.get_level_meter().set_no_show_all();
|
||||||
gm.get_level_meter().setup_meters(50);
|
gm.get_level_meter().setup_meters(50);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,13 +54,33 @@ using namespace Gtkmm2ext;
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
using namespace PBD;
|
using namespace PBD;
|
||||||
|
|
||||||
RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, const char* m_name,
|
RouteUI::RouteUI (ARDOUR::Session& sess, const char* mute_name, const char* solo_name, const char* rec_name)
|
||||||
const char* s_name, const char* r_name)
|
: AxisView(sess)
|
||||||
: AxisView(sess),
|
{
|
||||||
_route(rt),
|
init ();
|
||||||
mute_button(0),
|
set_button_names (mute_name, solo_name, rec_name);
|
||||||
solo_button(0),
|
}
|
||||||
rec_enable_button(0)
|
|
||||||
|
RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt,
|
||||||
|
ARDOUR::Session& sess, const char* mute_name, const char* solo_name, const char* rec_name)
|
||||||
|
: AxisView(sess)
|
||||||
|
{
|
||||||
|
init ();
|
||||||
|
set_button_names (mute_name, solo_name, rec_name);
|
||||||
|
set_route (rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
RouteUI::~RouteUI()
|
||||||
|
{
|
||||||
|
GoingAway (); /* EMIT SIGNAL */
|
||||||
|
|
||||||
|
delete solo_menu;
|
||||||
|
delete mute_menu;
|
||||||
|
delete remote_control_menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RouteUI::init ()
|
||||||
{
|
{
|
||||||
xml_node = 0;
|
xml_node = 0;
|
||||||
mute_menu = 0;
|
mute_menu = 0;
|
||||||
|
|
@ -73,26 +93,86 @@ RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, co
|
||||||
polarity_menu_item = 0;
|
polarity_menu_item = 0;
|
||||||
denormal_menu_item = 0;
|
denormal_menu_item = 0;
|
||||||
|
|
||||||
|
mute_button = manage (new BindableToggleButton (""));
|
||||||
|
mute_button->set_self_managed (true);
|
||||||
|
mute_button->set_name ("MuteButton");
|
||||||
|
|
||||||
|
solo_button = manage (new BindableToggleButton (""));
|
||||||
|
solo_button->set_self_managed (true);
|
||||||
|
solo_button->set_name ("SoloButton");
|
||||||
|
|
||||||
|
rec_enable_button = manage (new BindableToggleButton (""));
|
||||||
|
rec_enable_button->set_name ("RecordEnableButton");
|
||||||
|
rec_enable_button->set_self_managed (true);
|
||||||
|
|
||||||
|
_session.SoloChanged.connect (mem_fun(*this, &RouteUI::solo_changed_so_update_mute));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RouteUI::reset ()
|
||||||
|
{
|
||||||
|
connections.clear ();
|
||||||
|
|
||||||
|
if (solo_menu) {
|
||||||
|
delete solo_menu;
|
||||||
|
solo_menu = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mute_menu) {
|
||||||
|
delete mute_menu;
|
||||||
|
mute_menu = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remote_control_menu) {
|
||||||
|
delete remote_control_menu;
|
||||||
|
remote_control_menu = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xml_node) {
|
||||||
|
/* do not delete the node - its owned by the route */
|
||||||
|
xml_node = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
route_active_menu_item = 0;
|
||||||
|
polarity_menu_item = 0;
|
||||||
|
denormal_menu_item = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RouteUI::set_button_names (const char* mute, const char* solo, const char* rec)
|
||||||
|
{
|
||||||
|
m_name = mute;
|
||||||
|
s_name = solo;
|
||||||
|
r_name = rec;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RouteUI::set_route (boost::shared_ptr<Route> rp)
|
||||||
|
{
|
||||||
|
reset ();
|
||||||
|
|
||||||
|
_route = rp;
|
||||||
|
|
||||||
if (set_color_from_route()) {
|
if (set_color_from_route()) {
|
||||||
set_color (unique_random_color());
|
set_color (unique_random_color());
|
||||||
}
|
}
|
||||||
|
|
||||||
new PairedShiva<Route,RouteUI> (*_route, *this);
|
/* no, there is no memory leak here. This object cleans itself (and other stuff)
|
||||||
|
up when the route is destroyed.
|
||||||
|
*/
|
||||||
|
|
||||||
_route->active_changed.connect (mem_fun (*this, &RouteUI::route_active_changed));
|
new PairedShiva<Route,RouteUI> (*_route, *this);
|
||||||
|
|
||||||
mute_button = manage (new BindableToggleButton (_route->mute_control(), m_name ));
|
mute_button->set_controllable (_route->mute_control());
|
||||||
mute_button->set_self_managed (true);
|
mute_button->set_label (m_name);
|
||||||
|
|
||||||
solo_button = manage (new BindableToggleButton (_route->solo_control(), s_name ));
|
solo_button->set_controllable (_route->solo_control());
|
||||||
solo_button->set_self_managed (true);
|
solo_button->set_label (s_name);
|
||||||
|
|
||||||
mute_button->set_name ("MuteButton");
|
connections.push_back (_route->active_changed.connect (mem_fun (*this, &RouteUI::route_active_changed)));
|
||||||
solo_button->set_name ("SoloButton");
|
connections.push_back (_route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed)));
|
||||||
|
connections.push_back (_route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed)));
|
||||||
_route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed));
|
connections.push_back (_route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed)));
|
||||||
_route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
|
|
||||||
_route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
|
|
||||||
|
|
||||||
/* when solo changes, update mute state too, in case the user wants us to display it */
|
/* when solo changes, update mute state too, in case the user wants us to display it */
|
||||||
|
|
||||||
|
|
@ -101,15 +181,13 @@ RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, co
|
||||||
if (is_track()) {
|
if (is_track()) {
|
||||||
boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
|
boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
|
||||||
|
|
||||||
t->diskstream()->RecordEnableChanged.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed));
|
connections.push_back (t->diskstream()->RecordEnableChanged.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed)));
|
||||||
|
connections.push_back (_session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed)));
|
||||||
_session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed));
|
|
||||||
|
|
||||||
rec_enable_button = manage (new BindableToggleButton (t->rec_enable_control(), r_name ));
|
|
||||||
rec_enable_button->set_name ("RecordEnableButton");
|
|
||||||
rec_enable_button->set_self_managed (true);
|
|
||||||
|
|
||||||
rec_enable_button->show();
|
rec_enable_button->show();
|
||||||
|
rec_enable_button->set_controllable (t->rec_enable_control());
|
||||||
|
rec_enable_button->set_label (r_name);
|
||||||
|
|
||||||
update_rec_display ();
|
update_rec_display ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,19 +197,13 @@ RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, co
|
||||||
mute_button->show();
|
mute_button->show();
|
||||||
solo_button->show();
|
solo_button->show();
|
||||||
|
|
||||||
_route->RemoteControlIDChanged.connect (mem_fun(*this, &RouteUI::refresh_remote_control_menu));
|
connections.push_back (_route->RemoteControlIDChanged.connect (mem_fun(*this, &RouteUI::refresh_remote_control_menu)));
|
||||||
|
|
||||||
/* map the current state */
|
/* map the current state */
|
||||||
|
|
||||||
map_frozen ();
|
map_frozen ();
|
||||||
}
|
}
|
||||||
|
|
||||||
RouteUI::~RouteUI()
|
|
||||||
{
|
|
||||||
GoingAway (); /* EMIT SIGNAL */
|
|
||||||
delete mute_menu;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RouteUI::mute_press(GdkEventButton* ev)
|
RouteUI::mute_press(GdkEventButton* ev)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -45,9 +45,14 @@ class BindableToggleButton;
|
||||||
class RouteUI : public virtual AxisView
|
class RouteUI : public virtual AxisView
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
RouteUI(ARDOUR::Session&, const char*, const char*, const char*);
|
||||||
RouteUI(boost::shared_ptr<ARDOUR::Route>, ARDOUR::Session&, const char*, const char*, const char*);
|
RouteUI(boost::shared_ptr<ARDOUR::Route>, ARDOUR::Session&, const char*, const char*, const char*);
|
||||||
|
|
||||||
virtual ~RouteUI();
|
virtual ~RouteUI();
|
||||||
|
|
||||||
|
virtual void set_route (boost::shared_ptr<ARDOUR::Route>);
|
||||||
|
void set_button_names (const char*, const char*, const char*);
|
||||||
|
|
||||||
bool is_track() const;
|
bool is_track() const;
|
||||||
bool is_audio_track() const;
|
bool is_audio_track() const;
|
||||||
bool is_midi_track() const;
|
bool is_midi_track() const;
|
||||||
|
|
@ -161,6 +166,15 @@ class RouteUI : public virtual AxisView
|
||||||
void reversibly_apply_track_boolean (string name, void (ARDOUR::Track::*func)(bool, void*), bool, void *);
|
void reversibly_apply_track_boolean (string name, void (ARDOUR::Track::*func)(bool, void*), bool, void *);
|
||||||
|
|
||||||
void adjust_latency ();
|
void adjust_latency ();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector<sigc::connection> connections;
|
||||||
|
std::string s_name;
|
||||||
|
std::string m_name;
|
||||||
|
std::string r_name;
|
||||||
|
|
||||||
|
void init ();
|
||||||
|
void reset ();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __ardour_route_ui__ */
|
#endif /* __ardour_route_ui__ */
|
||||||
|
|
|
||||||
|
|
@ -30,11 +30,14 @@ using namespace ARDOUR;
|
||||||
using namespace PBD;
|
using namespace PBD;
|
||||||
|
|
||||||
SendUI::SendUI (boost::shared_ptr<Send> s, Session& se)
|
SendUI::SendUI (boost::shared_ptr<Send> s, Session& se)
|
||||||
: _send (s),
|
: _send (s)
|
||||||
_session (se),
|
, _session (se)
|
||||||
gpm (s->io(), se),
|
, gpm (se)
|
||||||
panners (s->io(), se)
|
, panners (se)
|
||||||
{
|
{
|
||||||
|
panners.set_io (s->io());
|
||||||
|
gpm.set_io (s->io());
|
||||||
|
|
||||||
hbox.pack_start (gpm, true, true);
|
hbox.pack_start (gpm, true, true);
|
||||||
set_name ("SendUIFrame");
|
set_name ("SendUIFrame");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -596,7 +596,8 @@ SoundFileBrowser::add_gain_meter ()
|
||||||
delete gm;
|
delete gm;
|
||||||
}
|
}
|
||||||
|
|
||||||
gm = new GainMeter (session->the_auditioner(), *session);
|
gm = new GainMeter (*session);
|
||||||
|
gm->set_io (session->the_auditioner());
|
||||||
|
|
||||||
meter_packer.set_border_width (12);
|
meter_packer.set_border_width (12);
|
||||||
meter_packer.pack_start (*gm, false, true);
|
meter_packer.pack_start (*gm, false, true);
|
||||||
|
|
|
||||||
|
|
@ -153,11 +153,44 @@ PluginManager::refresh ()
|
||||||
void
|
void
|
||||||
PluginManager::ladspa_refresh ()
|
PluginManager::ladspa_refresh ()
|
||||||
{
|
{
|
||||||
_ladspa_plugin_info.clear ();
|
_ladspa_plugin_info.clear ();
|
||||||
|
|
||||||
if (ladspa_path.length() == 0) {
|
static const char *standard_paths[] = {
|
||||||
ladspa_path = "/usr/local/lib64/ladspa:/usr/local/lib/ladspa:/usr/lib64/ladspa:/usr/lib/ladspa:/Library/Audio/Plug-Ins/LADSPA";
|
"/usr/local/lib64/ladspa",
|
||||||
}
|
"/usr/local/lib/ladspa",
|
||||||
|
"/usr/lib64/ladspa",
|
||||||
|
"/usr/lib/ladspa",
|
||||||
|
"/Library/Audio/Plug-Ins/LADSPA",
|
||||||
|
""
|
||||||
|
};
|
||||||
|
|
||||||
|
/* allow LADSPA_PATH to augment, not override standard locations */
|
||||||
|
|
||||||
|
/* Only add standard locations to ladspa_path if it doesn't
|
||||||
|
* already contain them. Check for trailing '/'s too.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; standard_paths[i][0]; i++) {
|
||||||
|
size_t found = ladspa_path.find(standard_paths[i]);
|
||||||
|
if (found != ladspa_path.npos) {
|
||||||
|
switch (ladspa_path[found + strlen(standard_paths[i])]) {
|
||||||
|
case ':' :
|
||||||
|
case '\0':
|
||||||
|
continue;
|
||||||
|
case '/' :
|
||||||
|
if (ladspa_path[found + strlen(standard_paths[i]) + 1] == ':' ||
|
||||||
|
ladspa_path[found + strlen(standard_paths[i]) + 1] == '\0') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ladspa_path.empty())
|
||||||
|
ladspa_path += ":";
|
||||||
|
|
||||||
|
ladspa_path += standard_paths[i];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
ladspa_discover_from_path (ladspa_path);
|
ladspa_discover_from_path (ladspa_path);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,14 @@ BindingProxy::BindingProxy (boost::shared_ptr<Controllable> c)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BindingProxy::BindingProxy ()
|
||||||
|
: prompter (0),
|
||||||
|
bind_button (2),
|
||||||
|
bind_statemask (Gdk::CONTROL_MASK)
|
||||||
|
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
BindingProxy::~BindingProxy ()
|
BindingProxy::~BindingProxy ()
|
||||||
{
|
{
|
||||||
if (prompter) {
|
if (prompter) {
|
||||||
|
|
@ -47,6 +55,13 @@ BindingProxy::~BindingProxy ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BindingProxy::set_controllable (boost::shared_ptr<Controllable> c)
|
||||||
|
{
|
||||||
|
learning_finished ();
|
||||||
|
controllable = c;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BindingProxy::set_bind_button_state (guint button, guint statemask)
|
BindingProxy::set_bind_button_state (guint button, guint statemask)
|
||||||
{
|
{
|
||||||
|
|
@ -64,7 +79,7 @@ BindingProxy::get_bind_button_state (guint &button, guint &statemask)
|
||||||
bool
|
bool
|
||||||
BindingProxy::button_press_handler (GdkEventButton *ev)
|
BindingProxy::button_press_handler (GdkEventButton *ev)
|
||||||
{
|
{
|
||||||
if ((ev->state & bind_statemask) && ev->button == bind_button) {
|
if (controllable && (ev->state & bind_statemask) && ev->button == bind_button) {
|
||||||
if (Controllable::StartLearning (controllable.get())) {
|
if (Controllable::StartLearning (controllable.get())) {
|
||||||
string prompt = _("operate controller now");
|
string prompt = _("operate controller now");
|
||||||
if (prompter == 0) {
|
if (prompter == 0) {
|
||||||
|
|
@ -95,7 +110,9 @@ bool
|
||||||
BindingProxy::prompter_hiding (GdkEventAny *ev)
|
BindingProxy::prompter_hiding (GdkEventAny *ev)
|
||||||
{
|
{
|
||||||
learning_connection.disconnect ();
|
learning_connection.disconnect ();
|
||||||
Controllable::StopLearning (controllable.get());
|
if (controllable) {
|
||||||
|
Controllable::StopLearning (controllable.get());
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,9 @@ class BarController : public Gtk::Frame
|
||||||
/* export this to allow direct connection to button events */
|
/* export this to allow direct connection to button events */
|
||||||
|
|
||||||
Gtk::Widget& event_widget() { return darea; }
|
Gtk::Widget& event_widget() { return darea; }
|
||||||
|
|
||||||
boost::shared_ptr<PBD::Controllable> get_controllable() { return binding_proxy.get_controllable(); }
|
boost::shared_ptr<PBD::Controllable> get_controllable() { return binding_proxy.get_controllable(); }
|
||||||
|
void set_controllable(boost::shared_ptr<PBD::Controllable> c) { binding_proxy.set_controllable(c); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Gtk::Adjustment& adjustment;
|
Gtk::Adjustment& adjustment;
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,8 @@ namespace PBD {
|
||||||
class BindableToggleButton : public Gtkmm2ext::StatefulToggleButton
|
class BindableToggleButton : public Gtkmm2ext::StatefulToggleButton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BindableToggleButton (boost::shared_ptr<PBD::Controllable> c) : binding_proxy (c) {}
|
BindableToggleButton (const std::string &label)
|
||||||
|
: Gtkmm2ext::StatefulToggleButton (label) {}
|
||||||
explicit BindableToggleButton (boost::shared_ptr<PBD::Controllable> c, const std::string &label)
|
|
||||||
: Gtkmm2ext::StatefulToggleButton (label), binding_proxy (c) {}
|
|
||||||
|
|
||||||
virtual ~BindableToggleButton() {}
|
virtual ~BindableToggleButton() {}
|
||||||
|
|
||||||
|
|
@ -49,6 +47,7 @@ class BindableToggleButton : public Gtkmm2ext::StatefulToggleButton
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<PBD::Controllable> get_controllable() { return binding_proxy.get_controllable(); }
|
boost::shared_ptr<PBD::Controllable> get_controllable() { return binding_proxy.get_controllable(); }
|
||||||
|
void set_controllable (boost::shared_ptr<PBD::Controllable> c) { binding_proxy.set_controllable (c); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BindingProxy binding_proxy;
|
BindingProxy binding_proxy;
|
||||||
|
|
@ -58,10 +57,6 @@ class BindableButton : public Gtkmm2ext::StatefulButton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BindableButton (boost::shared_ptr<PBD::Controllable> c) : binding_proxy (c) {}
|
BindableButton (boost::shared_ptr<PBD::Controllable> c) : binding_proxy (c) {}
|
||||||
|
|
||||||
explicit BindableButton (boost::shared_ptr<PBD::Controllable> c, const std::string &label)
|
|
||||||
: Gtkmm2ext::StatefulButton (label), binding_proxy (c) {}
|
|
||||||
|
|
||||||
~BindableButton() {}
|
~BindableButton() {}
|
||||||
|
|
||||||
bool on_button_press_event (GdkEventButton *ev) {
|
bool on_button_press_event (GdkEventButton *ev) {
|
||||||
|
|
@ -74,6 +69,7 @@ class BindableButton : public Gtkmm2ext::StatefulButton
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<PBD::Controllable> get_controllable() { return binding_proxy.get_controllable(); }
|
boost::shared_ptr<PBD::Controllable> get_controllable() { return binding_proxy.get_controllable(); }
|
||||||
|
void set_controllable (boost::shared_ptr<PBD::Controllable> c) { binding_proxy.set_controllable (c); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BindingProxy binding_proxy;
|
BindingProxy binding_proxy;
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ class BindingProxy : public sigc::trackable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BindingProxy (boost::shared_ptr<PBD::Controllable>);
|
BindingProxy (boost::shared_ptr<PBD::Controllable>);
|
||||||
|
BindingProxy ();
|
||||||
virtual ~BindingProxy();
|
virtual ~BindingProxy();
|
||||||
|
|
||||||
void set_bind_button_state (guint button, guint statemask);
|
void set_bind_button_state (guint button, guint statemask);
|
||||||
|
|
@ -42,6 +43,7 @@ class BindingProxy : public sigc::trackable
|
||||||
bool button_press_handler (GdkEventButton *);
|
bool button_press_handler (GdkEventButton *);
|
||||||
|
|
||||||
boost::shared_ptr<PBD::Controllable> get_controllable() { return controllable; }
|
boost::shared_ptr<PBD::Controllable> get_controllable() { return controllable; }
|
||||||
|
void set_controllable (boost::shared_ptr<PBD::Controllable>);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Gtkmm2ext::PopUp* prompter;
|
Gtkmm2ext::PopUp* prompter;
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,6 @@ class SliderController : public Gtkmm2ext::PixFader
|
||||||
public:
|
public:
|
||||||
SliderController (Glib::RefPtr<Gdk::Pixbuf> image,
|
SliderController (Glib::RefPtr<Gdk::Pixbuf> image,
|
||||||
Gtk::Adjustment* adj, int orientation,
|
Gtk::Adjustment* adj, int orientation,
|
||||||
boost::shared_ptr<PBD::Controllable>,
|
|
||||||
bool with_numeric = true);
|
bool with_numeric = true);
|
||||||
|
|
||||||
virtual ~SliderController () {}
|
virtual ~SliderController () {}
|
||||||
|
|
@ -52,6 +51,8 @@ class SliderController : public Gtkmm2ext::PixFader
|
||||||
|
|
||||||
bool on_button_press_event (GdkEventButton *ev);
|
bool on_button_press_event (GdkEventButton *ev);
|
||||||
|
|
||||||
|
void set_controllable (boost::shared_ptr<PBD::Controllable> c) { binding_proxy.set_controllable (c); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BindingProxy binding_proxy;
|
BindingProxy binding_proxy;
|
||||||
Glib::RefPtr<Gdk::Pixbuf> slider;
|
Glib::RefPtr<Gdk::Pixbuf> slider;
|
||||||
|
|
@ -59,6 +60,8 @@ class SliderController : public Gtkmm2ext::PixFader
|
||||||
Gtk::SpinButton spin;
|
Gtk::SpinButton spin;
|
||||||
Gtk::Frame spin_frame;
|
Gtk::Frame spin_frame;
|
||||||
Gtk::HBox spin_hbox;
|
Gtk::HBox spin_hbox;
|
||||||
|
|
||||||
|
void init ();
|
||||||
};
|
};
|
||||||
|
|
||||||
class VSliderController : public SliderController
|
class VSliderController : public SliderController
|
||||||
|
|
@ -66,7 +69,6 @@ class VSliderController : public SliderController
|
||||||
public:
|
public:
|
||||||
VSliderController (Glib::RefPtr<Gdk::Pixbuf> image,
|
VSliderController (Glib::RefPtr<Gdk::Pixbuf> image,
|
||||||
Gtk::Adjustment *adj,
|
Gtk::Adjustment *adj,
|
||||||
boost::shared_ptr<PBD::Controllable>,
|
|
||||||
bool with_numeric = true);
|
bool with_numeric = true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -75,7 +77,6 @@ class HSliderController : public SliderController
|
||||||
public:
|
public:
|
||||||
HSliderController (Glib::RefPtr<Gdk::Pixbuf> image,
|
HSliderController (Glib::RefPtr<Gdk::Pixbuf> image,
|
||||||
Gtk::Adjustment *adj,
|
Gtk::Adjustment *adj,
|
||||||
boost::shared_ptr<PBD::Controllable>,
|
|
||||||
bool with_numeric = true);
|
bool with_numeric = true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,11 +30,9 @@ using namespace PBD;
|
||||||
|
|
||||||
SliderController::SliderController (Glib::RefPtr<Gdk::Pixbuf> image,
|
SliderController::SliderController (Glib::RefPtr<Gdk::Pixbuf> image,
|
||||||
Gtk::Adjustment *adj, int orientation,
|
Gtk::Adjustment *adj, int orientation,
|
||||||
boost::shared_ptr<Controllable> c,
|
|
||||||
bool with_numeric)
|
bool with_numeric)
|
||||||
|
|
||||||
: PixFader (image, *adj, orientation),
|
: PixFader (image, *adj, orientation),
|
||||||
binding_proxy (c),
|
|
||||||
spin (*adj, 0, 2)
|
spin (*adj, 0, 2)
|
||||||
{
|
{
|
||||||
spin.set_name ("SliderControllerValue");
|
spin.set_name ("SliderControllerValue");
|
||||||
|
|
@ -55,15 +53,15 @@ SliderController::on_button_press_event (GdkEventButton *ev)
|
||||||
if (binding_proxy.button_press_handler (ev)) {
|
if (binding_proxy.button_press_handler (ev)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return PixFader::on_button_press_event (ev);
|
return PixFader::on_button_press_event (ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
VSliderController::VSliderController (Glib::RefPtr<Gdk::Pixbuf> image,
|
VSliderController::VSliderController (Glib::RefPtr<Gdk::Pixbuf> image,
|
||||||
Gtk::Adjustment *adj,
|
Gtk::Adjustment *adj,
|
||||||
boost::shared_ptr<Controllable> control,
|
|
||||||
bool with_numeric)
|
bool with_numeric)
|
||||||
|
|
||||||
: SliderController (image, adj, VERT, control, with_numeric)
|
: SliderController (image, adj, VERT, with_numeric)
|
||||||
{
|
{
|
||||||
if (with_numeric) {
|
if (with_numeric) {
|
||||||
spin_frame.add (spin);
|
spin_frame.add (spin);
|
||||||
|
|
@ -76,10 +74,9 @@ VSliderController::VSliderController (Glib::RefPtr<Gdk::Pixbuf> image,
|
||||||
|
|
||||||
HSliderController::HSliderController (Glib::RefPtr<Gdk::Pixbuf> image,
|
HSliderController::HSliderController (Glib::RefPtr<Gdk::Pixbuf> image,
|
||||||
Gtk::Adjustment *adj,
|
Gtk::Adjustment *adj,
|
||||||
boost::shared_ptr<Controllable> control,
|
|
||||||
bool with_numeric)
|
bool with_numeric)
|
||||||
|
|
||||||
: SliderController (image, adj, HORIZ, control, with_numeric)
|
: SliderController (image, adj, HORIZ, with_numeric)
|
||||||
{
|
{
|
||||||
if (with_numeric) {
|
if (with_numeric) {
|
||||||
spin_frame.add (spin);
|
spin_frame.add (spin);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue