diff options
Diffstat (limited to 'gtk2_ardour')
-rw-r--r-- | gtk2_ardour/ardour3_ui_default.conf.in | 2 | ||||
-rw-r--r-- | gtk2_ardour/ardour_button.h | 2 | ||||
-rw-r--r-- | gtk2_ardour/ardour_display.cc | 149 | ||||
-rw-r--r-- | gtk2_ardour/ardour_display.h | 62 | ||||
-rw-r--r-- | gtk2_ardour/ardour_knob.cc | 458 | ||||
-rw-r--r-- | gtk2_ardour/ardour_knob.h | 97 | ||||
-rw-r--r-- | gtk2_ardour/monitor_section.cc | 125 | ||||
-rw-r--r-- | gtk2_ardour/monitor_section.h | 15 | ||||
-rw-r--r-- | gtk2_ardour/wscript | 2 |
9 files changed, 880 insertions, 32 deletions
diff --git a/gtk2_ardour/ardour3_ui_default.conf.in b/gtk2_ardour/ardour3_ui_default.conf.in index a91aec32bf..d9f3a26a52 100644 --- a/gtk2_ardour/ardour3_ui_default.conf.in +++ b/gtk2_ardour/ardour3_ui_default.conf.in @@ -180,7 +180,7 @@ <Option name="waveform fill" value="ffffffff"/> <Option name="zero line" value="7f7f7fe0"/> <Option name="zoom rect" value="c6d1b26d"/> - <Option name="monitor knob" value="329edfff"/> + <Option name="monitor knob" value="555050ff"/> <Option name="button border" value="000000f0"/> <Option name="border color" value="00000000"/> <Option name="processor prefader: fill start" value="873c3cff"/> diff --git a/gtk2_ardour/ardour_button.h b/gtk2_ardour/ardour_button.h index 7b8d2a2372..260e0b21ab 100644 --- a/gtk2_ardour/ardour_button.h +++ b/gtk2_ardour/ardour_button.h @@ -115,7 +115,7 @@ class ArdourButton : public CairoWidget , public Gtkmm2ext::Activatable void controllable_changed (); PBD::ScopedConnection watch_connection; - private: + protected: Glib::RefPtr<Pango::Layout> _layout; Glib::RefPtr<Gdk::Pixbuf> _pixbuf; std::string _text; diff --git a/gtk2_ardour/ardour_display.cc b/gtk2_ardour/ardour_display.cc new file mode 100644 index 0000000000..ef845258ac --- /dev/null +++ b/gtk2_ardour/ardour_display.cc @@ -0,0 +1,149 @@ +/* + Copyright (C) 2014 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include <iostream> +#include <cmath> +#include <algorithm> + +#include <pangomm/layout.h> + +#include "pbd/compose.h" +#include "pbd/error.h" +#include "pbd/stacktrace.h" + +#include "gtkmm2ext/utils.h" +#include "gtkmm2ext/rgb_macros.h" +#include "gtkmm2ext/gui_thread.h" +#include "gtkmm2ext/keyboard.h" + +#include "ardour/rc_configuration.h" // for widget prelight preference + +#include "ardour_display.h" +#include "ardour_ui.h" +#include "global_signals.h" + +#include "i18n.h" + +using namespace Gtkmm2ext; +using namespace Gdk; +using namespace Gtk; +using namespace Glib; +using namespace PBD; +using std::max; +using std::min; +using namespace std; + + +ArdourDisplay::ArdourDisplay (Element e) +{ + signal_button_press_event().connect (sigc::mem_fun(*this, &ArdourDisplay::on_mouse_pressed)); + + add_elements(e); + add_elements(ArdourButton::Menu); + add_elements(ArdourButton::Text); +} + +ArdourDisplay::~ArdourDisplay () +{ +} + +bool +ArdourDisplay::on_mouse_pressed (GdkEventButton*) +{ + _menu.popup (1, gtk_get_current_event_time()); + return true; +} + +bool +ArdourDisplay::on_scroll_event (GdkEventScroll* ev) +{ + /* mouse wheel */ + + float scale = 1.0; + if (ev->state & Keyboard::GainFineScaleModifier) { + if (ev->state & Keyboard::GainExtraFineScaleModifier) { + scale *= 0.01; + } else { + scale *= 0.10; + } + } + + boost::shared_ptr<PBD::Controllable> c = binding_proxy.get_controllable(); + if (c) { + float val = c->get_interface(); + + if ( ev->direction == GDK_SCROLL_UP ) + val += 0.05 * scale; //by default, we step in 1/20ths of the knob travel + else + val -= 0.05 * scale; + + c->set_interface(val); + } + + return true; +} + + +void +ArdourDisplay::add_controllable_preset (const char *txt, float val) +{ + using namespace Menu_Helpers; + + MenuList& items = _menu.items (); + + items.push_back (MenuElem (txt, sigc::bind (sigc::mem_fun(*this, &ArdourDisplay::handle_controllable_preset), val))); +} + + +void +ArdourDisplay::handle_controllable_preset (float p) +{ + boost::shared_ptr<PBD::Controllable> c = binding_proxy.get_controllable(); + + if (!c) return; + + c->set_user(p); +} + + +void +ArdourDisplay::set_controllable (boost::shared_ptr<Controllable> c) +{ + watch_connection.disconnect (); //stop watching the old controllable + + if (!c) return; + + binding_proxy.set_controllable (c); + + c->Changed.connect (watch_connection, invalidator(*this), boost::bind (&ArdourDisplay::controllable_changed, this), gui_context()); + + controllable_changed(); +} + +void +ArdourDisplay::controllable_changed () +{ + boost::shared_ptr<PBD::Controllable> c = binding_proxy.get_controllable(); + + if (!c) return; + + set_text(c->get_user_string()); + + set_dirty(); +} diff --git a/gtk2_ardour/ardour_display.h b/gtk2_ardour/ardour_display.h new file mode 100644 index 0000000000..90bd61b834 --- /dev/null +++ b/gtk2_ardour/ardour_display.h @@ -0,0 +1,62 @@ +/* + Copyright (C) 2014 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __gtk2_ardour_ardour_display_h__ +#define __gtk2_ardour_ardour_display_h__ + +#include <list> +#include <stdint.h> + +#include <gtkmm/action.h> +#include <gtkmm/menu.h> +#include <gtkmm/menuitem.h> + + +#include "ardour_button.h" + +class ArdourDisplay : public ArdourButton +{ + public: + + ArdourDisplay (Element e = default_elements); + virtual ~ArdourDisplay (); + + boost::shared_ptr<PBD::Controllable> get_controllable() { return binding_proxy.get_controllable(); } + void set_controllable (boost::shared_ptr<PBD::Controllable> c); + + bool on_mouse_pressed (GdkEventButton*); //mousedown will pop up our preset menu +// bool on_button_press_event (GdkEventButton*); +// bool on_button_release_event (GdkEventButton*); + bool on_scroll_event (GdkEventScroll* ev); +// bool on_motion_notify_event (GdkEventMotion *ev) ; + + void add_controllable_preset (const char*, float); + void handle_controllable_preset (float p); + + void controllable_changed (); + PBD::ScopedConnection watch_connection; + + private: + Gtk::Menu _menu; + + bool _hovering; + bool _grabbed; + float _grabbed_y; +}; + +#endif /* __gtk2_ardour_ardour_menu_h__ */ diff --git a/gtk2_ardour/ardour_knob.cc b/gtk2_ardour/ardour_knob.cc new file mode 100644 index 0000000000..a125588db7 --- /dev/null +++ b/gtk2_ardour/ardour_knob.cc @@ -0,0 +1,458 @@ +/* + Copyright (C) 2010 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include <iostream> +#include <cmath> +#include <algorithm> + +#include <pangomm/layout.h> + +#include "pbd/compose.h" +#include "pbd/error.h" +#include "pbd/stacktrace.h" + +#include "gtkmm2ext/utils.h" +#include "gtkmm2ext/rgb_macros.h" +#include "gtkmm2ext/gui_thread.h" +#include "gtkmm2ext/keyboard.h" + +#include "ardour/rc_configuration.h" // for widget prelight preference + +#include "ardour_knob.h" +#include "ardour_ui.h" +#include "global_signals.h" + +#include "canvas/utils.h" + +#include "i18n.h" + +using namespace Gtkmm2ext; +using namespace Gdk; +using namespace Gtk; +using namespace Glib; +using namespace PBD; +using std::max; +using std::min; +using namespace std; + +ArdourKnob::Element ArdourKnob::default_elements = ArdourKnob::Element (ArdourKnob::Arc); + +ArdourKnob::ArdourKnob (Element e) + : _elements (e) + , _hovering (false) + , _grabbed (false) +{ + ARDOUR_UI_UTILS::ColorsChanged.connect (sigc::mem_fun (*this, &ArdourKnob::color_handler)); +} + +ArdourKnob::~ArdourKnob() +{ +} + +void +ArdourKnob::render (cairo_t* cr, cairo_rectangle_t *) +{ + cairo_pattern_t* shade_pattern; + + float width = get_width(); + float height = get_height(); + + const float scale = min(width, height); + const float pointer_thickness = 3.0 * (scale/80); //(if the knob is 80 pixels wide, we want a 3-pix line on it) + + float start_angle = ((180 - 65) * G_PI) / 180; + float end_angle = ((360 + 65) * G_PI) / 180; + float value_angle = start_angle + (_val * (end_angle - start_angle)); + + float value_x = cos (value_angle); + float value_y = sin (value_angle); + + cairo_set_antialias( cr, CAIRO_ANTIALIAS_BEST ); + + float xc = 0.5 + width/ 2.0; + float yc = 0.5 + height/ 2.0; + + cairo_translate (cr, xc, yc); //after this, everything is based on the center of the knob + + //get the knob color from the theme + ArdourCanvas::Color knob_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1", get_name())); + + float center_radius = 0.48*scale; + + bool arc = (_elements & Arc)==Arc; + bool bevel = (_elements & Bevel)==Bevel; + bool flat = ARDOUR_UI::config()->get_flat_buttons(); + + if ( arc ) { + center_radius = scale*0.25; + + float inner_progress_radius = scale*0.25; + float outer_progress_radius = scale*0.48; + float progress_width = (outer_progress_radius-inner_progress_radius); + float progress_radius = inner_progress_radius + progress_width/2.0; + + float start_angle_x = cos (start_angle); + float start_angle_y = sin (start_angle); + float end_angle_x = cos (end_angle); + float end_angle_y = sin (end_angle); + + //dark arc background + cairo_set_source_rgb (cr, 0.3, 0.3, 0.3 ); + cairo_set_line_width (cr, progress_width); + cairo_arc (cr, 0, 0, progress_radius, start_angle, end_angle); + cairo_stroke (cr); + + //look up the arc colors from the config + double red_start, green_start, blue_start, unused; + ArdourCanvas::Color arc_start_color = ARDOUR_UI::config()->color_by_name ( "processor fader: fill start"); + ArdourCanvas::color_to_rgba( arc_start_color, red_start, green_start, blue_start, unused ); + double red_end, green_end, blue_end; + ArdourCanvas::Color arc_end_color = ARDOUR_UI::config()->color_by_name ( "processor fader: fill end" ); + ArdourCanvas::color_to_rgba( arc_end_color, red_end, green_end, blue_end, unused ); + + //vary the arc color over the travel of the knob + float r = (1.0-_val) * red_end + _val * red_start; + float g = (1.0-_val) * green_end + _val * green_start; + float b = (1.0-_val) * blue_end + _val * blue_start; + + //draw the arc + cairo_set_source_rgb (cr, r,g,b); + cairo_set_line_width (cr, progress_width); + cairo_arc (cr, 0, 0, progress_radius, start_angle, value_angle); + cairo_stroke (cr); + + //shade the arc + if (!flat) { + shade_pattern = cairo_pattern_create_linear (0.0, -yc, 0.0, yc); //note we have to offset the pattern from our centerpoint + cairo_pattern_add_color_stop_rgba (shade_pattern, 0.0, 1,1,1, 0.15); + cairo_pattern_add_color_stop_rgba (shade_pattern, 0.5, 1,1,1, 0.0); + cairo_pattern_add_color_stop_rgba (shade_pattern, 1.0, 1,1,1, 0.0); + cairo_set_source (cr, shade_pattern); + cairo_arc (cr, 0, 0, outer_progress_radius-1, 0, 2.0*G_PI); + cairo_fill (cr); + cairo_pattern_destroy (shade_pattern); + } + + //black border + cairo_set_source_rgb (cr, 0, 0, 0 ); + cairo_set_line_width (cr, 1.0); + cairo_move_to (cr, (outer_progress_radius * start_angle_x), (outer_progress_radius * start_angle_y)); + cairo_line_to (cr, (inner_progress_radius * start_angle_x), (inner_progress_radius * start_angle_y)); + cairo_stroke (cr); + cairo_move_to (cr, (outer_progress_radius * end_angle_x), (outer_progress_radius * end_angle_y)); + cairo_line_to (cr, (inner_progress_radius * end_angle_x), (inner_progress_radius * end_angle_y)); + cairo_stroke (cr); + cairo_arc (cr, 0, 0, outer_progress_radius, start_angle, end_angle); + cairo_stroke (cr); + } + + if (!flat) { + //knob shadow + cairo_save(cr); + cairo_translate(cr, pointer_thickness+1, pointer_thickness+1 ); + cairo_set_source_rgba (cr, 0, 0, 0, 0.1 ); + cairo_arc (cr, 0, 0, center_radius-1, 0, 2.0*G_PI); + cairo_fill (cr); + cairo_restore(cr); + + //black border + cairo_set_source_rgb (cr, 0, 0, 0 ); + cairo_arc (cr, 0, 0, center_radius, 0, 2.0*G_PI); + cairo_stroke (cr); + + //inner circle + ArdourCanvas::set_source_rgba(cr, knob_color); + cairo_arc (cr, 0, 0, center_radius, 0, 2.0*G_PI); + cairo_fill (cr); + + //gradient + if (bevel) { + //knob gradient + shade_pattern = cairo_pattern_create_linear (0.0, -yc, 0.0, yc); //note we have to offset the gradient from our centerpoint + cairo_pattern_add_color_stop_rgba (shade_pattern, 0.0, 1,1,1, 0.2); + cairo_pattern_add_color_stop_rgba (shade_pattern, 0.2, 1,1,1, 0.2); + cairo_pattern_add_color_stop_rgba (shade_pattern, 0.8, 0,0,0, 0.2); + cairo_pattern_add_color_stop_rgba (shade_pattern, 1.0, 0,0,0, 0.2); + cairo_set_source (cr, shade_pattern); + cairo_arc (cr, 0, 0, center_radius, 0, 2.0*G_PI); + cairo_fill (cr); + cairo_pattern_destroy (shade_pattern); + + //flat top over beveled edge + ArdourCanvas::set_source_rgb_a (cr, knob_color, 0.5 ); + cairo_arc (cr, 0, 0, center_radius-pointer_thickness, 0, 2.0*G_PI); + cairo_fill (cr); + } else { + //radial gradient + shade_pattern = cairo_pattern_create_radial ( -center_radius, -center_radius, 1, -center_radius, -center_radius, center_radius*2.5 ); //note we have to offset the gradient from our centerpoint + cairo_pattern_add_color_stop_rgba (shade_pattern, 0.0, 1,1,1, 0.2); + cairo_pattern_add_color_stop_rgba (shade_pattern, 1.0, 0,0,0, 0.3); + cairo_set_source (cr, shade_pattern); + cairo_arc (cr, 0, 0, center_radius, 0, 2.0*G_PI); + cairo_fill (cr); + cairo_pattern_destroy (shade_pattern); + } + + } else { + //inner circle + ArdourCanvas::set_source_rgba(cr, knob_color); + cairo_arc (cr, 0, 0, center_radius, 0, 2.0*G_PI); + cairo_fill (cr); + } + + + //black knob border + cairo_set_line_width (cr, 1); + cairo_set_source_rgba (cr, 0,0,0, 1 ); + cairo_arc (cr, 0, 0, center_radius, 0, 2.0*G_PI); + cairo_stroke (cr); + + //line shadow + if (!flat) { + cairo_save(cr); + cairo_translate(cr, 2, 2 ); + cairo_set_source_rgba (cr, 0,0,0,0.5 ); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); + cairo_set_line_width (cr, pointer_thickness); + cairo_move_to (cr, (center_radius * value_x), (center_radius * value_y)); + cairo_line_to (cr, ((center_radius*0.4) * value_x), ((center_radius*0.4) * value_y)); + cairo_stroke (cr); + cairo_restore(cr); + } + + //line + cairo_set_source_rgba (cr, 1,1,1, 1 ); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); + cairo_set_line_width (cr, pointer_thickness); + cairo_move_to (cr, (center_radius * value_x), (center_radius * value_y)); + cairo_line_to (cr, ((center_radius*0.4) * value_x), ((center_radius*0.4) * value_y)); + cairo_stroke (cr); + + //highlight if grabbed or if mouse is hovering over me + if ( _grabbed || (_hovering && ARDOUR::Config->get_widget_prelight() ) ) { + cairo_set_source_rgba (cr, 1,1,1, 0.12 ); + cairo_arc (cr, 0, 0, center_radius, 0, 2.0*G_PI); + cairo_fill (cr); + } + + cairo_identity_matrix(cr); +} + +void +ArdourKnob::on_size_request (Gtk::Requisition* req) +{ + CairoWidget::on_size_request (req); + + //perhaps render the knob base into a cached image here? +} + +bool +ArdourKnob::on_scroll_event (GdkEventScroll* ev) +{ + /* mouse wheel */ + + float scale = 0.05; //by default, we step in 1/20ths of the knob travel + if (ev->state & Keyboard::GainFineScaleModifier) { + if (ev->state & Keyboard::GainExtraFineScaleModifier) { + scale *= 0.01; + } else { + scale *= 0.10; + } + } + + boost::shared_ptr<PBD::Controllable> c = binding_proxy.get_controllable(); + if (c) { + float val = c->get_interface(); + + if ( ev->direction == GDK_SCROLL_UP ) + val += scale; + else + val -= scale; + + c->set_interface(val); + } + + return true; +} + +bool +ArdourKnob::on_motion_notify_event (GdkEventMotion *ev) +{ + //scale the adjustment based on keyboard modifiers + float scale = 0.0025; + if (ev->state & Keyboard::GainFineScaleModifier) { + if (ev->state & Keyboard::GainExtraFineScaleModifier) { + scale *= 0.01; + } else { + scale *= 0.10; + } + } + + //calculate the travel of the mouse + int y_delta = 0; + if (ev->state & Gdk::BUTTON1_MASK) { + y_delta = _grabbed_y - ev->y; + _grabbed_y = ev->y; + if (y_delta == 0) return TRUE; + } + + //step the value of the controllable + boost::shared_ptr<PBD::Controllable> c = binding_proxy.get_controllable(); + if (c) { + float val = c->get_interface(); + val += y_delta * scale; + c->set_interface(val); + } + + return true; +} + +bool +ArdourKnob::on_button_press_event (GdkEventButton *ev) +{ + _grabbed_y = ev->y; + _grabbed = true; + + set_active_state (Gtkmm2ext::ExplicitActive); + + if (binding_proxy.button_press_handler (ev)) { + return true; + } + + return false; +} + +bool +ArdourKnob::on_button_release_event (GdkEventButton *ev) +{ + _grabbed = false; + unset_active_state (); + + return false; +} + +void +ArdourKnob::color_handler () +{ + set_dirty (); +} + +void +ArdourKnob::on_size_allocate (Allocation& alloc) +{ + CairoWidget::on_size_allocate (alloc); +} + +void +ArdourKnob::set_controllable (boost::shared_ptr<Controllable> c) +{ + watch_connection.disconnect (); //stop watching the old controllable + + if (!c) return; + + binding_proxy.set_controllable (c); + + c->Changed.connect (watch_connection, invalidator(*this), boost::bind (&ArdourKnob::controllable_changed, this), gui_context()); + + controllable_changed(); +} + +void +ArdourKnob::controllable_changed () +{ + _val = binding_proxy.get_controllable()->get_interface(); //% of knob travel + + _val = min( max(0.0f, _val), 1.0f); //range check + + set_dirty(); +} + +void +ArdourKnob::on_style_changed (const RefPtr<Gtk::Style>&) +{ + set_dirty (); +} + +void +ArdourKnob::on_name_changed () +{ + set_dirty (); +} + + +void +ArdourKnob::set_active_state (Gtkmm2ext::ActiveState s) +{ + if (_active_state != s) + CairoWidget::set_active_state (s); +} + +void +ArdourKnob::set_visual_state (Gtkmm2ext::VisualState s) +{ + if (_visual_state != s) + CairoWidget::set_visual_state (s); +} + + +bool +ArdourKnob::on_focus_in_event (GdkEventFocus* ev) +{ + set_dirty (); + return CairoWidget::on_focus_in_event (ev); +} + +bool +ArdourKnob::on_focus_out_event (GdkEventFocus* ev) +{ + set_dirty (); + return CairoWidget::on_focus_out_event (ev); +} + +bool +ArdourKnob::on_enter_notify_event (GdkEventCrossing* ev) +{ + _hovering = true; + + set_dirty (); + + return CairoWidget::on_enter_notify_event (ev); +} + +bool +ArdourKnob::on_leave_notify_event (GdkEventCrossing* ev) +{ + _hovering = false; + + set_dirty (); + + return CairoWidget::on_leave_notify_event (ev); +} + +void +ArdourKnob::set_elements (Element e) +{ + _elements = e; +} + +void +ArdourKnob::add_elements (Element e) +{ + _elements = (ArdourKnob::Element) (_elements | e); +} diff --git a/gtk2_ardour/ardour_knob.h b/gtk2_ardour/ardour_knob.h new file mode 100644 index 0000000000..1a318a21dc --- /dev/null +++ b/gtk2_ardour/ardour_knob.h @@ -0,0 +1,97 @@ +/* + Copyright (C) 2014 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __gtk2_ardour_ardour_knob_h__ +#define __gtk2_ardour_ardour_knob_h__ + +#include <list> +#include <stdint.h> + +#include <gtkmm/action.h> + +#include "pbd/signals.h" +#include "gtkmm2ext/binding_proxy.h" +#include "gtkmm2ext/activatable.h" +#include "gtkmm2ext/cairo_widget.h" + +class ArdourKnob : public CairoWidget , public Gtkmm2ext::Activatable +{ +public: + + enum Element { + Arc = 0x1, + Bevel = 0x2, + unused2 = 0x4, + unused3 = 0x8, + unused4 = 0x10, + unused5 = 0x20, + }; + + ArdourKnob (Element e = default_elements); + virtual ~ArdourKnob (); + + void set_active_state (Gtkmm2ext::ActiveState); + void set_visual_state (Gtkmm2ext::VisualState); + + Element elements() const { return _elements; } + void set_elements (Element); + void add_elements (Element); + static Element default_elements; + + boost::shared_ptr<PBD::Controllable> get_controllable() { return binding_proxy.get_controllable(); } + void set_controllable (boost::shared_ptr<PBD::Controllable> c); + + bool on_button_press_event (GdkEventButton*); + bool on_button_release_event (GdkEventButton*); + bool on_scroll_event (GdkEventScroll* ev); + bool on_motion_notify_event (GdkEventMotion *ev) ; + + void color_handler (); + + protected: + void render (cairo_t *, cairo_rectangle_t *); + void on_size_request (Gtk::Requisition* req); + void on_size_allocate (Gtk::Allocation&); + void on_style_changed (const Glib::RefPtr<Gtk::Style>&); + void on_name_changed (); + bool on_enter_notify_event (GdkEventCrossing*); + bool on_leave_notify_event (GdkEventCrossing*); + bool on_focus_in_event (GdkEventFocus*); + bool on_focus_out_event (GdkEventFocus*); + + void controllable_changed (); + PBD::ScopedConnection watch_connection; + + + private: + Element _elements; + + BindingProxy binding_proxy; + + bool _hovering; + bool _grabbed; + float _grabbed_y; + + float _val; //percent of knob travel + + void action_sensitivity_changed (); + void action_visibility_changed (); + void action_tooltip_changed (); +}; + +#endif /* __gtk2_ardour_ardour_knob_h__ */ diff --git a/gtk2_ardour/monitor_section.cc b/gtk2_ardour/monitor_section.cc index a816dd397d..3f7ebfaa6e 100644 --- a/gtk2_ardour/monitor_section.cc +++ b/gtk2_ardour/monitor_section.cc @@ -27,6 +27,9 @@ #include "gtkmm2ext/actions.h" #include "gtkmm2ext/motionfeedback.h" +#include <gtkmm/menu.h> +#include <gtkmm/menuitem.h> + #include "ardour/monitor_processor.h" #include "ardour/route.h" @@ -60,6 +63,10 @@ MonitorSection::MonitorSection (Session* s) , dim_control (0) , solo_boost_control (0) , solo_cut_control (0) + , gain_display (0) + , dim_display (0) + , solo_boost_display (0) + , solo_cut_display (0) , solo_in_place_button (_("SiP"), ArdourButton::led_default_elements) , afl_button (_("AFL"), ArdourButton::led_default_elements) , pfl_button (_("PFL"), ArdourButton::led_default_elements) @@ -67,6 +74,9 @@ MonitorSection::MonitorSection (Session* s) , solo_mute_override_button (ArdourButton::led_default_elements) , _inhibit_solo_model_update (false) { + + using namespace Menu_Helpers; + Glib::RefPtr<Action> act; if (!monitor_actions) { @@ -141,9 +151,19 @@ MonitorSection::MonitorSection (Session* s) /* Solo Boost */ - solo_boost_control = new VolumeController (little_knob_pixbuf, boost::shared_ptr<Controllable>(), 0.0, 0.01, 0.1, true, 30, 30, true); - ARDOUR_UI::instance()->tooltips().set_tip (*solo_boost_control, _("Gain increase for soloed signals (0dB is normal)")); - + solo_boost_control = new ArdourKnob (); + solo_boost_control->set_name("monitor knob"); + solo_boost_control->set_size_request(40,40); + ARDOUR_UI::instance()->tooltips().set_tip (*solo_boost_control, _("Gain increase for soloed signals (0dB is normal)")); + + solo_boost_display = new ArdourDisplay (); + solo_boost_display->set_name("monitor section cut"); + solo_boost_display->set_size_request(80,20); + solo_boost_display->add_controllable_preset("0dB", 0.0); + solo_boost_display->add_controllable_preset("3 dB", 3.0); + solo_boost_display->add_controllable_preset("6 dB", 6.0); + solo_boost_display->add_controllable_preset("10 dB", 10.0); + HBox* solo_packer = manage (new HBox); solo_packer->set_spacing (6); solo_packer->show (); @@ -151,44 +171,69 @@ MonitorSection::MonitorSection (Session* s) spin_label = manage (new Label (_("Solo Boost"))); spin_packer = manage (new VBox); spin_packer->show (); - spin_packer->set_spacing (6); - spin_packer->pack_start (*solo_boost_control, false, false); + spin_packer->set_spacing (3); spin_packer->pack_start (*spin_label, false, false); + spin_packer->pack_start (*solo_boost_control, false, false); + spin_packer->pack_start (*solo_boost_display, false, false); solo_packer->pack_start (*spin_packer, true, false); /* Solo (SiP) cut */ - solo_cut_control = new VolumeController (little_knob_pixbuf, boost::shared_ptr<Controllable>(), 0.0, 0.1, 0.5, true, 30, 30, true); - ARDOUR_UI::instance()->tooltips().set_tip (*solo_cut_control, _("Gain reduction non-soloed signals\nA value above -inf dB causes \"solo-in-front\"")); - + solo_cut_control = new ArdourKnob (); + solo_cut_control->set_name ("monitor knob"); + solo_cut_control->set_size_request (40,40); + ARDOUR_UI::instance()->tooltips().set_tip (*solo_cut_control, _("Gain reduction non-soloed signals\nA value above -inf dB causes \"solo-in-front\"")); + + solo_cut_display = new ArdourDisplay (); + solo_cut_display->set_name("monitor section cut"); + solo_cut_display->set_size_request(80,20); + solo_cut_display->add_controllable_preset("0dB", 0.0); + solo_cut_display->add_controllable_preset("-6 dB", -6.0); + solo_cut_display->add_controllable_preset("-12 dB", -12.0); + solo_cut_display->add_controllable_preset("-20 dB", -20.0); + spin_label = manage (new Label (_("SiP Cut"))); spin_packer = manage (new VBox); spin_packer->show (); - spin_packer->set_spacing (6); - spin_packer->pack_start (*solo_cut_control, false, false); + spin_packer->set_spacing (3); spin_packer->pack_start (*spin_label, false, false); + spin_packer->pack_start (*solo_cut_control, false, false); + spin_packer->pack_start (*solo_cut_display, false, false); solo_packer->pack_start (*spin_packer, true, false); /* Dim */ - dim_control = new VolumeController (little_knob_pixbuf, boost::shared_ptr<Controllable>(), 0.0, 0.01, 0.1, true, 30, 30, true); - ARDOUR_UI::instance()->tooltips().set_tip (*dim_control, _("Gain reduction to use when dimming monitor outputs")); - + dim_control = new ArdourKnob (); + dim_control->set_name ("monitor knob"); + dim_control->set_size_request (40,40); + ARDOUR_UI::instance()->tooltips().set_tip (*dim_control, _("Gain reduction to use when dimming monitor outputs")); + + dim_display = new ArdourDisplay (); + dim_display->set_name("monitor section cut"); + dim_display->set_size_request(80,20); + dim_display->add_controllable_preset("0dB", 0.0); + dim_display->add_controllable_preset("-3 dB", -3.0); + dim_display->add_controllable_preset("-6 dB", -6.0); + dim_display->add_controllable_preset("-12 dB", -12.0); + dim_display->add_controllable_preset("-20 dB", -20.0); + dim_display->add_controllable_preset("-30 dB", -30.0); + HBox* dim_packer = manage (new HBox); dim_packer->show (); spin_label = manage (new Label (_("Dim"))); spin_packer = manage (new VBox); spin_packer->show (); - spin_packer->set_spacing (6); - spin_packer->pack_start (*dim_control, false, false); + spin_packer->set_spacing (3); spin_packer->pack_start (*spin_label, false, false); + spin_packer->pack_start (*dim_control, false, false); + spin_packer->pack_start (*dim_display, false, false); dim_packer->pack_start (*spin_packer, true, false); - exclusive_solo_button.set_text (_("excl. solo")); + exclusive_solo_button.set_text (_("excl. solo")); exclusive_solo_button.set_name (X_("monitor solo exclusive")); ARDOUR_UI::instance()->set_tip (&exclusive_solo_button, _("Exclusive solo means that only 1 solo is active at a time")); @@ -262,14 +307,27 @@ MonitorSection::MonitorSection (Session* s) /* Gain */ - gain_control = new VolumeController (big_knob_pixbuf, boost::shared_ptr<Controllable>(), 1.0, 0.01, 0.1, true, 80, 80, false); - - spin_label = manage (new Label (_("Monitor"))); - spin_packer = manage (new VBox); + gain_control = new ArdourKnob (); + gain_control->set_name("monitor knob"); + gain_control->set_size_request(80,80); + + gain_display = new ArdourDisplay (); + gain_display->set_name("monitor section cut"); + gain_display->set_size_request(40,20); + gain_display->add_controllable_preset("0dB", 0.0); + gain_display->add_controllable_preset("-3 dB", -3.0); + gain_display->add_controllable_preset("-6 dB", -6.0); + gain_display->add_controllable_preset("-12 dB", -12.0); + gain_display->add_controllable_preset("-20 dB", -20.0); + gain_display->add_controllable_preset("-30 dB", -30.0); + + spin_label = manage (new Label (_("Monitor"))); + spin_packer = manage (new VBox); spin_packer->show (); - spin_packer->set_spacing (6); - spin_packer->pack_start (*gain_control, false, false); + spin_packer->set_spacing (3); spin_packer->pack_start (*spin_label, false, false); + spin_packer->pack_start (*gain_control, false, false); + spin_packer->pack_start (*gain_display, false, false); lower_packer.pack_start (*spin_packer, true, true); @@ -317,8 +375,11 @@ MonitorSection::MonitorSection (Session* s) hpacker.pack_start (vpacker, true, true); gain_control->show_all (); + gain_display->show_all (); dim_control->show_all (); + dim_display->show_all(); solo_boost_control->show_all (); + solo_boost_display->show_all(); channel_table.show (); hpacker.show (); @@ -351,8 +412,13 @@ MonitorSection::~MonitorSection () _channel_buttons.clear (); delete gain_control; + delete gain_display; delete dim_control; + delete dim_display; delete solo_boost_control; + delete solo_boost_display; + delete solo_cut_control; + delete solo_cut_display; delete _tearoff; } @@ -1064,13 +1130,16 @@ MonitorSection::assign_controllables () } if (_session) { - solo_cut_control->set_controllable (_session->solo_cut_control()); + solo_cut_control->set_controllable (_session->solo_cut_control()); + solo_cut_display->set_controllable (_session->solo_cut_control()); } else { - solo_cut_control->set_controllable (none); + solo_cut_control->set_controllable (none); + solo_cut_display->set_controllable (none); } if (_route) { gain_control->set_controllable (_route->gain_control()); + gain_display->set_controllable (_route->gain_control()); } else { gain_control->set_controllable (none); } @@ -1084,8 +1153,10 @@ MonitorSection::assign_controllables () mono_button.set_controllable (_monitor->mono_control()); mono_button.watch (); - dim_control->set_controllable (_monitor->dim_level_control ()); - solo_boost_control->set_controllable (_monitor->solo_boost_control ()); + dim_control->set_controllable (_monitor->dim_level_control ()); + dim_display->set_controllable (_monitor->dim_level_control ()); + solo_boost_control->set_controllable (_monitor->solo_boost_control ()); + solo_boost_display->set_controllable (_monitor->solo_boost_control ()); } else { @@ -1094,7 +1165,9 @@ MonitorSection::assign_controllables () mono_button.set_controllable (none); dim_control->set_controllable (none); + dim_display->set_controllable (none); solo_boost_control->set_controllable (none); + solo_boost_display->set_controllable (none); } } diff --git a/gtk2_ardour/monitor_section.h b/gtk2_ardour/monitor_section.h index f7848a3f01..d1fc7d8da1 100644 --- a/gtk2_ardour/monitor_section.h +++ b/gtk2_ardour/monitor_section.h @@ -23,6 +23,8 @@ #include "gtkmm2ext/bindable_button.h" #include "ardour_button.h" +#include "ardour_knob.h" +#include "ardour_display.h" #include "axis_view.h" #include "level_meter.h" #include "route_ui.h" @@ -74,11 +76,16 @@ class MonitorSection : public RouteUI typedef std::vector<ChannelButtonSet*> ChannelButtons; ChannelButtons _channel_buttons; - VolumeController* gain_control; - VolumeController* dim_control; - VolumeController* solo_boost_control; - VolumeController* solo_cut_control; + ArdourKnob* gain_control; + ArdourKnob* dim_control; + ArdourKnob* solo_boost_control; + ArdourKnob* solo_cut_control; + ArdourDisplay* gain_display; + ArdourDisplay* dim_display; + ArdourDisplay* solo_boost_display; + ArdourDisplay* solo_cut_display; + void populate_buttons (); void map_state (); diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript index 95d359f982..e99d97b516 100644 --- a/gtk2_ardour/wscript +++ b/gtk2_ardour/wscript @@ -25,7 +25,9 @@ gtk2_ardour_sources = [ 'analysis_window.cc', 'ardour_button.cc', 'ardour_dialog.cc', + 'ardour_display.cc', 'ardour_dropdown.cc', + 'ardour_knob.cc', 'ardour_ui.cc', 'ardour_ui2.cc', 'ardour_ui_dependents.cc', |