tweaks for the monitor section. refactoring of some buttons, using new ArdourKnob instead of VolumeController. New ArdourDisplay shows a controllables user value, and provides support for preset values (hardcoded at present). Further refactoring to come, so that ArdourWidgets are derived from a common class. Controllable now has more responsibility for scaling between internal, user, and interface (knob percent) values. This also needs more refactoring and might have some unintended consequences. tested with audio and nothing seems amiss, yet.
This commit is contained in:
parent
ac9219a3c8
commit
b2b736d596
|
@ -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"/>
|
||||
|
|
|
@ -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;
|
||||
|
|
149
gtk2_ardour/ardour_display.cc
Normal file
149
gtk2_ardour/ardour_display.cc
Normal file
|
@ -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();
|
||||
}
|
62
gtk2_ardour/ardour_display.h
Normal file
62
gtk2_ardour/ardour_display.h
Normal file
|
@ -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__ */
|
458
gtk2_ardour/ardour_knob.cc
Normal file
458
gtk2_ardour/ardour_knob.cc
Normal file
|
@ -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);
|
||||
}
|
97
gtk2_ardour/ardour_knob.h
Normal file
97
gtk2_ardour/ardour_knob.h
Normal file
|
@ -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__ */
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -426,6 +426,19 @@ Amp::GainControl::internal_to_user (double v) const
|
|||
return accurate_coefficient_to_dB (v);
|
||||
}
|
||||
|
||||
double
|
||||
Amp::GainControl::user_to_internal (double u) const
|
||||
{
|
||||
return dB_to_coefficient (u);
|
||||
}
|
||||
|
||||
std::string
|
||||
Amp::GainControl::get_user_string () const
|
||||
{
|
||||
char theBuf[32]; sprintf( theBuf, "%3.1f dB", accurate_coefficient_to_dB (get_value()));
|
||||
return std::string(theBuf);
|
||||
}
|
||||
|
||||
/** Write gain automation for this cycle into the buffer previously passed in to
|
||||
* set_gain_automation_buffer (if we are in automation playback mode and the
|
||||
* transport is rolling).
|
||||
|
|
|
@ -90,6 +90,8 @@ public:
|
|||
double internal_to_interface (double) const;
|
||||
double interface_to_internal (double) const;
|
||||
double internal_to_user (double) const;
|
||||
double user_to_internal (double) const;
|
||||
std::string get_user_string () const;
|
||||
|
||||
Amp* _amp;
|
||||
};
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include "ardour/types.h"
|
||||
#include "ardour/processor.h"
|
||||
|
||||
#include "ardour/dB.h"
|
||||
|
||||
class XMLNode;
|
||||
|
||||
namespace ARDOUR {
|
||||
|
@ -63,6 +65,15 @@ public:
|
|||
return (float) _value;
|
||||
}
|
||||
|
||||
double internal_to_user (double i) const { return accurate_coefficient_to_dB (i);}
|
||||
double user_to_internal (double u) const { return dB_to_coefficient(u) ;}
|
||||
|
||||
std::string get_user_string () const
|
||||
{
|
||||
char theBuf[32]; sprintf( theBuf, "%3.1f dB", accurate_coefficient_to_dB (get_value()));
|
||||
return std::string(theBuf);
|
||||
}
|
||||
|
||||
double lower () const { return _lower; }
|
||||
double upper () const { return _upper; }
|
||||
|
||||
|
|
|
@ -43,6 +43,15 @@ public:
|
|||
void set_value (double v) { if (_setter (v)) { Changed(); /* EMIT SIGNAL */ } }
|
||||
double get_value () const { return _getter (); }
|
||||
|
||||
double internal_to_user (double i) const { return accurate_coefficient_to_dB (i);}
|
||||
double user_to_internal (double u) const { return dB_to_coefficient(u) ;}
|
||||
|
||||
std::string get_user_string () const
|
||||
{
|
||||
char theBuf[32]; sprintf( theBuf, "%3.1f dB", accurate_coefficient_to_dB (get_value()));
|
||||
return std::string(theBuf);
|
||||
}
|
||||
|
||||
private:
|
||||
boost::function1<bool,double> _setter;
|
||||
boost::function0<double> _getter;
|
||||
|
|
|
@ -29,6 +29,10 @@ namespace ArdourCanvas {
|
|||
extern LIBCANVAS_API Color rgba_to_color (double r, double g, double b, double a);
|
||||
|
||||
extern LIBCANVAS_API void set_source_rgba (Cairo::RefPtr<Cairo::Context>, Color);
|
||||
extern LIBCANVAS_API void set_source_rgb_a (Cairo::RefPtr<Cairo::Context>, Color, float alpha); //override the color's alpha
|
||||
|
||||
extern LIBCANVAS_API void set_source_rgba (cairo_t*, Color);
|
||||
extern LIBCANVAS_API void set_source_rgb_a (cairo_t*, Color, float alpha); //override the color's alpha
|
||||
|
||||
Distance LIBCANVAS_API distance_to_segment_squared (Duple const & p, Duple const & p1, Duple const & p2, double& t, Duple& at);
|
||||
|
||||
|
|
|
@ -154,6 +154,39 @@ ArdourCanvas::set_source_rgba (Cairo::RefPtr<Cairo::Context> context, Color colo
|
|||
);
|
||||
}
|
||||
|
||||
void
|
||||
ArdourCanvas::set_source_rgb_a (Cairo::RefPtr<Cairo::Context> context, Color color, float alpha)
|
||||
{
|
||||
context->set_source_rgba (
|
||||
((color >> 24) & 0xff) / 255.0,
|
||||
((color >> 16) & 0xff) / 255.0,
|
||||
((color >> 8) & 0xff) / 255.0,
|
||||
alpha
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
ArdourCanvas::set_source_rgba (cairo_t *cr, Color color)
|
||||
{
|
||||
cairo_set_source_rgba ( cr,
|
||||
((color >> 24) & 0xff) / 255.0,
|
||||
((color >> 16) & 0xff) / 255.0,
|
||||
((color >> 8) & 0xff) / 255.0,
|
||||
((color >> 0) & 0xff) / 255.0
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
ArdourCanvas::set_source_rgb_a (cairo_t *cr, Color color, float alpha)
|
||||
{
|
||||
cairo_set_source_rgba ( cr,
|
||||
((color >> 24) & 0xff) / 255.0,
|
||||
((color >> 16) & 0xff) / 255.0,
|
||||
((color >> 8) & 0xff) / 255.0,
|
||||
alpha
|
||||
);
|
||||
}
|
||||
|
||||
ArdourCanvas::Distance
|
||||
ArdourCanvas::distance_to_segment_squared (Duple const & p, Duple const & p1, Duple const & p2, double& t, Duple& at)
|
||||
{
|
||||
|
|
|
@ -60,11 +60,25 @@ class LIBPBD_API Controllable : public PBD::StatefulDestructible {
|
|||
* but passed to the processor as a linear quantity.
|
||||
*/
|
||||
|
||||
/** Set `internal' value */
|
||||
/** Get and Set `internal' value */
|
||||
virtual void set_value (double) = 0;
|
||||
/** @return `internal' value */
|
||||
virtual double get_value (void) const = 0;
|
||||
|
||||
/** Conversions between `internal', 'interface', and 'user' values */
|
||||
virtual double internal_to_interface (double i) const {return (i-lower())/(upper() - lower());} //by default, the interface range is just a linear interpolation between lower and upper values
|
||||
virtual double interface_to_internal (double i) const {return lower() + i*(upper() - lower());}
|
||||
virtual double internal_to_user (double i) const {return i;} //by default the internal value is the same as the user value
|
||||
virtual double user_to_internal (double i) const {return i;} //by default the internal value is the same as the user value
|
||||
|
||||
/** Get and Set `interface' value (typically, percent of knob travel) */
|
||||
virtual float get_interface() const { return (internal_to_interface(get_value())); }
|
||||
virtual void set_interface (float percent) { percent = std::min( std::max(0.0f, percent), 1.0f); set_value(interface_to_internal(percent)); }
|
||||
|
||||
/** Get and Set `user' value ( dB or milliseconds, etc. This MIGHT be the same as the internal value, but in a few cases it is not ) */
|
||||
virtual float get_user() const { return (internal_to_user(get_value())); }
|
||||
virtual void set_user (float user_v) { set_value(user_to_internal(user_v)); }
|
||||
virtual std::string get_user_string() const { return std::string(); }
|
||||
|
||||
PBD::Signal0<void> LearningFinished;
|
||||
static PBD::Signal3<void,PBD::Controllable*,int,int> CreateBinding;
|
||||
static PBD::Signal1<void,PBD::Controllable*> DeleteBinding;
|
||||
|
@ -99,6 +113,8 @@ class LIBPBD_API Controllable : public PBD::StatefulDestructible {
|
|||
private:
|
||||
std::string _name;
|
||||
|
||||
std::string _units;
|
||||
|
||||
Flag _flags;
|
||||
bool _touching;
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user