fix merge errors with master
This commit is contained in:
commit
d15fda6d75
|
@ -12,7 +12,7 @@ libs=$TOP/@LIBS@
|
|||
|
||||
export ARDOUR_PATH=$TOP/gtk2_ardour/icons:$TOP/gtk2_ardour/pixmaps:$TOP/build/gtk2_ardour:$TOP/gtk2_ardour:.
|
||||
export ARDOUR_SURFACES_PATH=$libs/surfaces/osc:$libs/surfaces/generic_midi:$libs/surfaces/tranzport:$libs/surfaces/powermate:$libs/surfaces/mackie:$libs/surfaces/wiimote
|
||||
export ARDOUR_PANNER_PATH=$libs/panners/2in2out:$libs/panners/1in2out:$libs/panners/vbap
|
||||
export ARDOUR_PANNER_PATH=$libs/panners
|
||||
export ARDOUR_DATA_PATH=$TOP:$TOP/build:$TOP/gtk2_ardour:$TOP/build/gtk2_ardour:.
|
||||
export ARDOUR_MIDIMAPS_PATH=$TOP/midi_maps:.
|
||||
export ARDOUR_MCP_PATH=$TOP/mcp:.
|
||||
|
|
25
gtk2_ardour/artest
Executable file
25
gtk2_ardour/artest
Executable file
|
@ -0,0 +1,25 @@
|
|||
#!/bin/sh
|
||||
. `dirname "$0"`/../build/gtk2_ardour/ardev_common_waf.sh
|
||||
|
||||
LIBS_DIR=$TOP/build/libs
|
||||
|
||||
run_tests () {
|
||||
echo ""
|
||||
echo "-------------------------------------------"
|
||||
echo "Running tests for $1..."
|
||||
echo "-------------------------------------------"
|
||||
echo ""
|
||||
$2 $LIBS_DIR/$1/run-tests
|
||||
echo ""
|
||||
}
|
||||
|
||||
if [ $# -gt 0 ]; then
|
||||
run_tests $1 $2
|
||||
exit
|
||||
fi
|
||||
|
||||
run_tests audiographer
|
||||
run_tests midi++2
|
||||
run_tests evoral
|
||||
run_tests pbd
|
||||
run_tests ardour
|
|
@ -41,6 +41,7 @@
|
|||
#include "ardour/pannable.h"
|
||||
#include "ardour/panner.h"
|
||||
#include "ardour/panner_shell.h"
|
||||
#include "ardour/panner_manager.h"
|
||||
#include "ardour/port.h"
|
||||
#include "ardour/profile.h"
|
||||
#include "ardour/route.h"
|
||||
|
@ -515,7 +516,10 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
|
|||
_route->output()->changed.connect (*this, invalidator (*this), boost::bind (&MixerStrip::update_output_display, this), gui_context());
|
||||
_route->route_group_changed.connect (route_connections, invalidator (*this), boost::bind (&MixerStrip::route_group_changed, this), gui_context());
|
||||
|
||||
_route->io_changed.connect (route_connections, invalidator (*this), boost::bind (&MixerStrip::io_changed_proxy, this), gui_context ());
|
||||
|
||||
if (_route->panner_shell()) {
|
||||
update_panner_choices();
|
||||
_route->panner_shell()->Changed.connect (route_connections, invalidator (*this), boost::bind (&MixerStrip::connect_to_pan, this), gui_context());
|
||||
}
|
||||
|
||||
|
@ -1019,9 +1023,48 @@ MixerStrip::connect_to_pan ()
|
|||
p->automation_state_changed.connect (panstate_connection, invalidator (*this), boost::bind (&PannerUI::pan_automation_state_changed, &panners), gui_context());
|
||||
p->automation_style_changed.connect (panstyle_connection, invalidator (*this), boost::bind (&PannerUI::pan_automation_style_changed, &panners), gui_context());
|
||||
|
||||
panners.panshell_changed ();
|
||||
/* This call reduncant, PannerUI::set_panner() connects to _panshell->Changed itself
|
||||
* However, that only works a panner was previously set.
|
||||
*
|
||||
* PannerUI must remain subscribed to _panshell->Changed() in case
|
||||
* we switch the panner eg. AUX-Send and back
|
||||
* _route->panner_shell()->Changed() vs _panshell->Changed
|
||||
*/
|
||||
if (panners._panner == 0) {
|
||||
panners.panshell_changed ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MixerStrip::update_panner_choices ()
|
||||
{
|
||||
ENSURE_GUI_THREAD (*this, &MixerStrip::update_panner_choices)
|
||||
if (!_route->panner_shell()) { return; }
|
||||
|
||||
int in = _route->output()->n_ports().n_audio();
|
||||
int out = in;
|
||||
|
||||
if (_route->panner()) {
|
||||
in = _route->panner()->in().n_audio();
|
||||
}
|
||||
|
||||
if (out < 2 || in == 0) {
|
||||
panners.set_available_panners(_route, std::map<std::string,std::string>());
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<std::string,std::string> panner_list;
|
||||
std::list<PannerInfo*> panner_info = PannerManager::instance().panner_info;
|
||||
/* get available panners for current configuration. */
|
||||
for (list<PannerInfo*>::iterator p = panner_info.begin(); p != panner_info.end(); ++p) {
|
||||
PanPluginDescriptor* d = &(*p)->descriptor;
|
||||
if (d->in != -1 && d->in != in) continue;
|
||||
if (d->out != -1 && d->out != out) continue;
|
||||
if (d->in == -1 && d->out == -1 && out <= 2) continue;
|
||||
panner_list.insert(std::pair<std::string,std::string>(d->panner_uri,d->name));
|
||||
}
|
||||
panners.set_available_panners(_route, panner_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* Output port labelling
|
||||
|
@ -1272,6 +1315,12 @@ MixerStrip::diskstream_changed ()
|
|||
Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&MixerStrip::update_diskstream_display, this));
|
||||
}
|
||||
|
||||
void
|
||||
MixerStrip::io_changed_proxy ()
|
||||
{
|
||||
Glib::signal_idle().connect_once (sigc::mem_fun (*this, &MixerStrip::update_panner_choices));
|
||||
}
|
||||
|
||||
void
|
||||
MixerStrip::port_connected_or_disconnected (boost::weak_ptr<Port> wa, boost::weak_ptr<Port> wb)
|
||||
{
|
||||
|
@ -1843,6 +1892,8 @@ MixerStrip::show_send (boost::shared_ptr<Send> send)
|
|||
gain_meter().setup_meters ();
|
||||
|
||||
panner_ui().set_panner (_current_delivery->panner_shell(), _current_delivery->panner());
|
||||
panner_ui().set_available_panners(boost::shared_ptr<ARDOUR::Route>(), std::map<std::string,std::string>());
|
||||
|
||||
panner_ui().setup_pan ();
|
||||
|
||||
/* make sure the send has audio output */
|
||||
|
@ -1884,6 +1935,7 @@ MixerStrip::revert_to_default_display ()
|
|||
gain_meter().setup_meters ();
|
||||
|
||||
panner_ui().set_panner (_route->main_outs()->panner_shell(), _route->main_outs()->panner());
|
||||
update_panner_choices();
|
||||
panner_ui().setup_pan ();
|
||||
|
||||
if (has_audio_outputs ()) {
|
||||
|
|
|
@ -226,6 +226,7 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
|
|||
void edit_output_configuration ();
|
||||
|
||||
void diskstream_changed ();
|
||||
void io_changed_proxy ();
|
||||
|
||||
Gtk::Menu *send_action_menu;
|
||||
Gtk::MenuItem* rename_menu_item;
|
||||
|
@ -237,6 +238,7 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
|
|||
PBD::ScopedConnection panstate_connection;
|
||||
PBD::ScopedConnection panstyle_connection;
|
||||
void connect_to_pan ();
|
||||
void update_panner_choices ();
|
||||
|
||||
void update_diskstream_display ();
|
||||
void update_input_display ();
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <cmath>
|
||||
|
||||
#include <gtkmm/window.h>
|
||||
#include <pangomm/layout.h>
|
||||
|
||||
#include "pbd/controllable.h"
|
||||
#include "pbd/compose.h"
|
||||
|
@ -35,6 +36,7 @@
|
|||
|
||||
#include "ardour/pannable.h"
|
||||
#include "ardour/panner.h"
|
||||
#include "ardour/panner_shell.h"
|
||||
|
||||
#include "ardour_ui.h"
|
||||
#include "global_signals.h"
|
||||
|
@ -57,23 +59,39 @@ static const int top_step = 2;
|
|||
MonoPanner::ColorScheme MonoPanner::colors;
|
||||
bool MonoPanner::have_colors = false;
|
||||
|
||||
MonoPanner::MonoPanner (boost::shared_ptr<ARDOUR::Panner> panner)
|
||||
: PannerInterface (panner)
|
||||
Pango::AttrList MonoPanner::panner_font_attributes;
|
||||
bool MonoPanner::have_font = false;
|
||||
|
||||
MonoPanner::MonoPanner (boost::shared_ptr<ARDOUR::PannerShell> p)
|
||||
: PannerInterface (p->panner())
|
||||
, _panner_shell (p)
|
||||
, position_control (_panner->pannable()->pan_azimuth_control)
|
||||
, drag_start_x (0)
|
||||
, last_drag_x (0)
|
||||
, accumulated_delta (0)
|
||||
, detented (false)
|
||||
, position_binder (position_control)
|
||||
, drag_start_x (0)
|
||||
, last_drag_x (0)
|
||||
, accumulated_delta (0)
|
||||
, detented (false)
|
||||
, position_binder (position_control)
|
||||
, _dragging (false)
|
||||
{
|
||||
if (!have_colors) {
|
||||
set_colors ();
|
||||
have_colors = true;
|
||||
}
|
||||
if (!have_colors) {
|
||||
set_colors ();
|
||||
have_colors = true;
|
||||
}
|
||||
if (!have_font) {
|
||||
Pango::FontDescription font;
|
||||
Pango::AttrFontDesc* font_attr;
|
||||
font = Pango::FontDescription ("ArdourMono");
|
||||
font.set_weight (Pango::WEIGHT_BOLD);
|
||||
font.set_size(9 * PANGO_SCALE);
|
||||
font_attr = new Pango::AttrFontDesc (Pango::Attribute::create_attr_font_desc (font));
|
||||
panner_font_attributes.change(*font_attr);
|
||||
delete font_attr;
|
||||
have_font = true;
|
||||
}
|
||||
|
||||
position_control->Changed.connect (connections, invalidator(*this), boost::bind (&MonoPanner::value_change, this), gui_context());
|
||||
position_control->Changed.connect (connections, invalidator(*this), boost::bind (&MonoPanner::value_change, this), gui_context());
|
||||
|
||||
_panner_shell->Changed.connect (connections, invalidator (*this), boost::bind (&MonoPanner::bypass_handler, this), gui_context());
|
||||
ColorsChanged.connect (sigc::mem_fun (*this, &MonoPanner::color_handler));
|
||||
|
||||
set_tooltip ();
|
||||
|
@ -87,21 +105,25 @@ MonoPanner::~MonoPanner ()
|
|||
void
|
||||
MonoPanner::set_tooltip ()
|
||||
{
|
||||
double pos = position_control->get_value(); // 0..1
|
||||
if (_panner_shell->bypassed()) {
|
||||
_tooltip.set_tip (_("bypassed"));
|
||||
return;
|
||||
}
|
||||
double pos = position_control->get_value(); // 0..1
|
||||
|
||||
/* We show the position of the center of the image relative to the left & right.
|
||||
This is expressed as a pair of percentage values that ranges from (100,0)
|
||||
(hard left) through (50,50) (hard center) to (0,100) (hard right).
|
||||
/* We show the position of the center of the image relative to the left & right.
|
||||
This is expressed as a pair of percentage values that ranges from (100,0)
|
||||
(hard left) through (50,50) (hard center) to (0,100) (hard right).
|
||||
|
||||
This is pretty wierd, but its the way audio engineers expect it. Just remember that
|
||||
the center of the USA isn't Kansas, its (50LA, 50NY) and it will all make sense.
|
||||
*/
|
||||
This is pretty wierd, but its the way audio engineers expect it. Just remember that
|
||||
the center of the USA isn't Kansas, its (50LA, 50NY) and it will all make sense.
|
||||
*/
|
||||
|
||||
char buf[64];
|
||||
snprintf (buf, sizeof (buf), _("L:%3d R:%3d"),
|
||||
(int) rint (100.0 * (1.0 - pos)),
|
||||
(int) rint (100.0 * pos));
|
||||
_tooltip.set_tip (buf);
|
||||
char buf[64];
|
||||
snprintf (buf, sizeof (buf), _("L:%3d R:%3d"),
|
||||
(int) rint (100.0 * (1.0 - pos)),
|
||||
(int) rint (100.0 * pos));
|
||||
_tooltip.set_tip (buf);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -109,137 +131,146 @@ MonoPanner::on_expose_event (GdkEventExpose*)
|
|||
{
|
||||
Glib::RefPtr<Gdk::Window> win (get_window());
|
||||
Glib::RefPtr<Gdk::GC> gc (get_style()->get_base_gc (get_state()));
|
||||
Cairo::RefPtr<Cairo::Context> context = get_window()->create_cairo_context();
|
||||
Cairo::RefPtr<Cairo::Context> context = get_window()->create_cairo_context();
|
||||
|
||||
int width, height;
|
||||
double pos = position_control->get_value (); /* 0..1 */
|
||||
uint32_t o, f, t, b, pf, po;
|
||||
const double corner_radius = 5;
|
||||
int width, height;
|
||||
double pos = position_control->get_value (); /* 0..1 */
|
||||
uint32_t o, f, t, b, pf, po;
|
||||
const double corner_radius = 5;
|
||||
|
||||
width = get_width();
|
||||
height = get_height ();
|
||||
width = get_width();
|
||||
height = get_height ();
|
||||
|
||||
o = colors.outline;
|
||||
f = colors.fill;
|
||||
t = colors.text;
|
||||
b = colors.background;
|
||||
pf = colors.pos_fill;
|
||||
po = colors.pos_outline;
|
||||
o = colors.outline;
|
||||
f = colors.fill;
|
||||
t = colors.text;
|
||||
b = colors.background;
|
||||
pf = colors.pos_fill;
|
||||
po = colors.pos_outline;
|
||||
|
||||
/* background */
|
||||
if (_panner_shell->bypassed()) {
|
||||
b = 0x20202040;
|
||||
f = 0x404040ff;
|
||||
o = 0x606060ff;
|
||||
po = 0x606060ff;
|
||||
pf = 0x404040ff;
|
||||
t = 0x606060ff;
|
||||
}
|
||||
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(b), UINT_RGBA_G_FLT(b), UINT_RGBA_B_FLT(b), UINT_RGBA_A_FLT(b));
|
||||
context->rectangle (0, 0, width, height);
|
||||
context->fill ();
|
||||
|
||||
double usable_width = width - pos_box_size;
|
||||
|
||||
/* compute the centers of the L/R boxes based on the current stereo width */
|
||||
|
||||
if (fmod (usable_width,2.0) == 0) {
|
||||
/* even width, but we need odd, so that there is an exact center.
|
||||
So, offset cairo by 1, and reduce effective width by 1
|
||||
*/
|
||||
usable_width -= 1.0;
|
||||
context->translate (1.0, 0.0);
|
||||
}
|
||||
|
||||
const double half_lr_box = lr_box_size/2.0;
|
||||
double left;
|
||||
double right;
|
||||
|
||||
left = 4 + half_lr_box; // center of left box
|
||||
right = width - 4 - half_lr_box; // center of right box
|
||||
|
||||
/* center line */
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(o), UINT_RGBA_G_FLT(o), UINT_RGBA_B_FLT(o), UINT_RGBA_A_FLT(o));
|
||||
context->set_line_width (1.0);
|
||||
context->move_to ((pos_box_size/2.0) + (usable_width/2.0), 0);
|
||||
context->line_to ((pos_box_size/2.0) + (usable_width/2.0), height);
|
||||
context->stroke ();
|
||||
|
||||
/* left box */
|
||||
|
||||
rounded_rectangle (context,
|
||||
left - half_lr_box,
|
||||
half_lr_box+step_down,
|
||||
lr_box_size, lr_box_size, corner_radius);
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(o), UINT_RGBA_G_FLT(o), UINT_RGBA_B_FLT(o), UINT_RGBA_A_FLT(o));
|
||||
context->stroke_preserve ();
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(f), UINT_RGBA_G_FLT(f), UINT_RGBA_B_FLT(f), UINT_RGBA_A_FLT(f));
|
||||
/* background */
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(b), UINT_RGBA_G_FLT(b), UINT_RGBA_B_FLT(b), UINT_RGBA_A_FLT(b));
|
||||
context->rectangle (0, 0, width, height);
|
||||
context->fill ();
|
||||
|
||||
/* add text */
|
||||
|
||||
context->move_to (
|
||||
left - half_lr_box + 3,
|
||||
(lr_box_size/2) + step_down + 13);
|
||||
context->select_font_face ("sans-serif", Cairo::FONT_SLANT_NORMAL, Cairo::FONT_WEIGHT_BOLD);
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(t), UINT_RGBA_G_FLT(t), UINT_RGBA_B_FLT(t), UINT_RGBA_A_FLT(t));
|
||||
context->show_text (_("L"));
|
||||
double usable_width = width - pos_box_size;
|
||||
|
||||
/* right box */
|
||||
/* compute the centers of the L/R boxes based on the current stereo width */
|
||||
if (fmod (usable_width,2.0) == 0) {
|
||||
usable_width -= 1.0;
|
||||
}
|
||||
const double half_lr_box = lr_box_size/2.0;
|
||||
const double left = 4 + half_lr_box; // center of left box
|
||||
const double right = width - 4 - half_lr_box; // center of right box
|
||||
|
||||
rounded_rectangle (context,
|
||||
right - half_lr_box,
|
||||
half_lr_box+step_down,
|
||||
lr_box_size, lr_box_size, corner_radius);
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(o), UINT_RGBA_G_FLT(o), UINT_RGBA_B_FLT(o), UINT_RGBA_A_FLT(o));
|
||||
context->stroke_preserve ();
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(f), UINT_RGBA_G_FLT(f), UINT_RGBA_B_FLT(f), UINT_RGBA_A_FLT(f));
|
||||
context->fill ();
|
||||
/* center line */
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(o), UINT_RGBA_G_FLT(o), UINT_RGBA_B_FLT(o), UINT_RGBA_A_FLT(o));
|
||||
context->set_line_width (1.0);
|
||||
context->move_to ((pos_box_size/2.0) + (usable_width/2.0), 0);
|
||||
context->line_to ((pos_box_size/2.0) + (usable_width/2.0), height);
|
||||
context->stroke ();
|
||||
|
||||
/* add text */
|
||||
context->set_line_width (1.0);
|
||||
/* left box */
|
||||
|
||||
context->move_to (
|
||||
right - half_lr_box + 3,
|
||||
(lr_box_size/2)+step_down + 13);
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(t), UINT_RGBA_G_FLT(t), UINT_RGBA_B_FLT(t), UINT_RGBA_A_FLT(t));
|
||||
context->show_text (_("R"));
|
||||
rounded_left_half_rectangle (context,
|
||||
left - half_lr_box + .5,
|
||||
half_lr_box + step_down,
|
||||
lr_box_size, lr_box_size, corner_radius);
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(f), UINT_RGBA_G_FLT(f), UINT_RGBA_B_FLT(f), UINT_RGBA_A_FLT(f));
|
||||
context->fill_preserve ();
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(o), UINT_RGBA_G_FLT(o), UINT_RGBA_B_FLT(o), UINT_RGBA_A_FLT(o));
|
||||
context->stroke();
|
||||
|
||||
/* 2 lines that connect them both */
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(o), UINT_RGBA_G_FLT(o), UINT_RGBA_B_FLT(o), UINT_RGBA_A_FLT(o));
|
||||
context->set_line_width (1.0);
|
||||
/* add text */
|
||||
int tw, th;
|
||||
Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(get_pango_context());
|
||||
layout->set_attributes (panner_font_attributes);
|
||||
|
||||
/* make the lines a little longer than they need to be, because the corners of
|
||||
the boxes are rounded and we don't want a gap
|
||||
*/
|
||||
context->move_to (left + half_lr_box - corner_radius, half_lr_box+step_down);
|
||||
context->line_to (right - half_lr_box + corner_radius, half_lr_box+step_down);
|
||||
context->stroke ();
|
||||
layout->set_text (_("L"));
|
||||
layout->get_pixel_size(tw, th);
|
||||
context->move_to (rint(left - tw/2), rint(lr_box_size + step_down - th/2));
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(t), UINT_RGBA_G_FLT(t), UINT_RGBA_B_FLT(t), UINT_RGBA_A_FLT(t));
|
||||
pango_cairo_show_layout (context->cobj(), layout->gobj());
|
||||
|
||||
/* right box */
|
||||
rounded_right_half_rectangle (context,
|
||||
right - half_lr_box - .5,
|
||||
half_lr_box + step_down,
|
||||
lr_box_size, lr_box_size, corner_radius);
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(f), UINT_RGBA_G_FLT(f), UINT_RGBA_B_FLT(f), UINT_RGBA_A_FLT(f));
|
||||
context->fill_preserve ();
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(o), UINT_RGBA_G_FLT(o), UINT_RGBA_B_FLT(o), UINT_RGBA_A_FLT(o));
|
||||
context->stroke();
|
||||
|
||||
context->move_to (left + half_lr_box - corner_radius, half_lr_box+step_down+lr_box_size);
|
||||
context->line_to (right - half_lr_box + corner_radius, half_lr_box+step_down+lr_box_size);
|
||||
context->stroke ();
|
||||
/* add text */
|
||||
layout->set_text (_("R"));
|
||||
layout->get_pixel_size(tw, th);
|
||||
context->move_to (rint(right - tw/2), rint(lr_box_size + step_down - th/2));
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(t), UINT_RGBA_G_FLT(t), UINT_RGBA_B_FLT(t), UINT_RGBA_A_FLT(t));
|
||||
pango_cairo_show_layout (context->cobj(), layout->gobj());
|
||||
|
||||
/* draw the position indicator */
|
||||
/* 2 lines that connect them both */
|
||||
context->set_line_width (1.0);
|
||||
|
||||
double spos = (pos_box_size/2.0) + (usable_width * pos);
|
||||
if (_panner_shell->panner_gui_uri() != "http://ardour.org/plugin/panner_balance#ui") {
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(o), UINT_RGBA_G_FLT(o), UINT_RGBA_B_FLT(o), UINT_RGBA_A_FLT(o));
|
||||
context->move_to (left + half_lr_box, half_lr_box + step_down);
|
||||
context->line_to (right - half_lr_box, half_lr_box + step_down);
|
||||
context->stroke ();
|
||||
|
||||
context->set_line_width (2.0);
|
||||
context->move_to (left + half_lr_box, half_lr_box+step_down+lr_box_size);
|
||||
context->line_to (right - half_lr_box, half_lr_box+step_down+lr_box_size);
|
||||
context->stroke ();
|
||||
} else {
|
||||
context->move_to (left + half_lr_box, half_lr_box+step_down+lr_box_size);
|
||||
context->line_to (left + half_lr_box, half_lr_box + step_down);
|
||||
context->line_to ((pos_box_size/2.0) + (usable_width/2.0), half_lr_box+step_down+lr_box_size);
|
||||
context->line_to (right - half_lr_box, half_lr_box + step_down);
|
||||
context->line_to (right - half_lr_box, half_lr_box+step_down+lr_box_size);
|
||||
context->close_path();
|
||||
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(f), UINT_RGBA_G_FLT(f), UINT_RGBA_B_FLT(f), UINT_RGBA_A_FLT(f));
|
||||
context->fill_preserve ();
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(o), UINT_RGBA_G_FLT(o), UINT_RGBA_B_FLT(o), UINT_RGBA_A_FLT(o));
|
||||
context->stroke ();
|
||||
}
|
||||
|
||||
/* draw the position indicator */
|
||||
double spos = (pos_box_size/2.0) + (usable_width * pos);
|
||||
|
||||
context->set_line_width (2.0);
|
||||
context->move_to (spos + (pos_box_size/2.0), top_step); /* top right */
|
||||
context->rel_line_to (0.0, pos_box_size); /* lower right */
|
||||
context->rel_line_to (-pos_box_size/2.0, 4.0); /* bottom point */
|
||||
context->rel_line_to (-pos_box_size/2.0, -4.0); /* lower left */
|
||||
context->rel_line_to (0.0, -pos_box_size); /* upper left */
|
||||
context->close_path ();
|
||||
context->rel_line_to (0.0, pos_box_size); /* lower right */
|
||||
context->rel_line_to (-pos_box_size/2.0, 4.0); /* bottom point */
|
||||
context->rel_line_to (-pos_box_size/2.0, -4.0); /* lower left */
|
||||
context->rel_line_to (0.0, -pos_box_size); /* upper left */
|
||||
context->close_path ();
|
||||
|
||||
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(po), UINT_RGBA_G_FLT(po), UINT_RGBA_B_FLT(po), UINT_RGBA_A_FLT(po));
|
||||
context->stroke_preserve ();
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(pf), UINT_RGBA_G_FLT(pf), UINT_RGBA_B_FLT(pf), UINT_RGBA_A_FLT(pf));
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(po), UINT_RGBA_G_FLT(po), UINT_RGBA_B_FLT(po), UINT_RGBA_A_FLT(po));
|
||||
context->stroke_preserve ();
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(pf), UINT_RGBA_G_FLT(pf), UINT_RGBA_B_FLT(pf), UINT_RGBA_A_FLT(pf));
|
||||
context->fill ();
|
||||
|
||||
/* marker line */
|
||||
/* marker line */
|
||||
context->set_line_width (1.0);
|
||||
context->move_to (spos, pos_box_size + 5);
|
||||
context->rel_line_to (0, half_lr_box+step_down);
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(po), UINT_RGBA_G_FLT(po), UINT_RGBA_B_FLT(po), UINT_RGBA_A_FLT(po));
|
||||
context->stroke ();
|
||||
|
||||
context->set_line_width (1.0);
|
||||
context->move_to (spos, pos_box_size+4);
|
||||
context->rel_line_to (0, half_lr_box+step_down);
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(po), UINT_RGBA_G_FLT(po), UINT_RGBA_B_FLT(po), UINT_RGBA_A_FLT(po));
|
||||
context->stroke ();
|
||||
|
||||
/* done */
|
||||
/* done */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -250,62 +281,65 @@ MonoPanner::on_button_press_event (GdkEventButton* ev)
|
|||
if (PannerInterface::on_button_press_event (ev)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
drag_start_x = ev->x;
|
||||
last_drag_x = ev->x;
|
||||
if (_panner_shell->bypassed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_dragging = false;
|
||||
drag_start_x = ev->x;
|
||||
last_drag_x = ev->x;
|
||||
|
||||
_dragging = false;
|
||||
_tooltip.target_stop_drag ();
|
||||
accumulated_delta = 0;
|
||||
detented = false;
|
||||
accumulated_delta = 0;
|
||||
detented = false;
|
||||
|
||||
/* Let the binding proxies get first crack at the press event
|
||||
*/
|
||||
/* Let the binding proxies get first crack at the press event
|
||||
*/
|
||||
|
||||
if (ev->y < 20) {
|
||||
if (position_binder.button_press_handler (ev)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (ev->y < 20) {
|
||||
if (position_binder.button_press_handler (ev)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ev->button != 1) {
|
||||
return false;
|
||||
}
|
||||
if (ev->button != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ev->type == GDK_2BUTTON_PRESS) {
|
||||
int width = get_width();
|
||||
if (ev->type == GDK_2BUTTON_PRESS) {
|
||||
int width = get_width();
|
||||
|
||||
if (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier)) {
|
||||
/* handled by button release */
|
||||
return true;
|
||||
}
|
||||
if (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier)) {
|
||||
/* handled by button release */
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (ev->x <= width/3) {
|
||||
/* left side dbl click */
|
||||
position_control->set_value (0);
|
||||
} else if (ev->x > 2*width/3) {
|
||||
position_control->set_value (1.0);
|
||||
} else {
|
||||
position_control->set_value (0.5);
|
||||
}
|
||||
if (ev->x <= width/3) {
|
||||
/* left side dbl click */
|
||||
position_control->set_value (0);
|
||||
} else if (ev->x > 2*width/3) {
|
||||
position_control->set_value (1.0);
|
||||
} else {
|
||||
position_control->set_value (0.5);
|
||||
}
|
||||
|
||||
_dragging = false;
|
||||
_dragging = false;
|
||||
_tooltip.target_stop_drag ();
|
||||
|
||||
} else if (ev->type == GDK_BUTTON_PRESS) {
|
||||
} else if (ev->type == GDK_BUTTON_PRESS) {
|
||||
|
||||
if (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier)) {
|
||||
/* handled by button release */
|
||||
return true;
|
||||
}
|
||||
if (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier)) {
|
||||
/* handled by button release */
|
||||
return true;
|
||||
}
|
||||
|
||||
_dragging = true;
|
||||
_dragging = true;
|
||||
_tooltip.target_start_drag ();
|
||||
StartGesture ();
|
||||
}
|
||||
StartGesture ();
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -315,121 +349,136 @@ MonoPanner::on_button_release_event (GdkEventButton* ev)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (ev->button != 1) {
|
||||
return false;
|
||||
}
|
||||
if (ev->button != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_dragging = false;
|
||||
if (_panner_shell->bypassed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_dragging = false;
|
||||
_tooltip.target_stop_drag ();
|
||||
accumulated_delta = 0;
|
||||
detented = false;
|
||||
accumulated_delta = 0;
|
||||
detented = false;
|
||||
|
||||
if (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier)) {
|
||||
if (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier)) {
|
||||
_panner->reset ();
|
||||
} else {
|
||||
StopGesture ();
|
||||
}
|
||||
} else {
|
||||
StopGesture ();
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MonoPanner::on_scroll_event (GdkEventScroll* ev)
|
||||
{
|
||||
double one_degree = 1.0/180.0; // one degree as a number from 0..1, since 180 degrees is the full L/R axis
|
||||
double pv = position_control->get_value(); // 0..1.0 ; 0 = left
|
||||
double step;
|
||||
double one_degree = 1.0/180.0; // one degree as a number from 0..1, since 180 degrees is the full L/R axis
|
||||
double pv = position_control->get_value(); // 0..1.0 ; 0 = left
|
||||
double step;
|
||||
|
||||
if (Keyboard::modifier_state_contains (ev->state, Keyboard::PrimaryModifier)) {
|
||||
step = one_degree;
|
||||
} else {
|
||||
step = one_degree * 5.0;
|
||||
}
|
||||
if (_panner_shell->bypassed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (ev->direction) {
|
||||
case GDK_SCROLL_UP:
|
||||
case GDK_SCROLL_LEFT:
|
||||
pv -= step;
|
||||
position_control->set_value (pv);
|
||||
break;
|
||||
case GDK_SCROLL_DOWN:
|
||||
case GDK_SCROLL_RIGHT:
|
||||
pv += step;
|
||||
position_control->set_value (pv);
|
||||
break;
|
||||
}
|
||||
if (Keyboard::modifier_state_contains (ev->state, Keyboard::PrimaryModifier)) {
|
||||
step = one_degree;
|
||||
} else {
|
||||
step = one_degree * 5.0;
|
||||
}
|
||||
|
||||
return true;
|
||||
switch (ev->direction) {
|
||||
case GDK_SCROLL_UP:
|
||||
case GDK_SCROLL_LEFT:
|
||||
pv -= step;
|
||||
position_control->set_value (pv);
|
||||
break;
|
||||
case GDK_SCROLL_DOWN:
|
||||
case GDK_SCROLL_RIGHT:
|
||||
pv += step;
|
||||
position_control->set_value (pv);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MonoPanner::on_motion_notify_event (GdkEventMotion* ev)
|
||||
{
|
||||
if (!_dragging) {
|
||||
return false;
|
||||
}
|
||||
if (_panner_shell->bypassed()) {
|
||||
_dragging = false;
|
||||
}
|
||||
if (!_dragging) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int w = get_width();
|
||||
double delta = (ev->x - last_drag_x) / (double) w;
|
||||
int w = get_width();
|
||||
double delta = (ev->x - last_drag_x) / (double) w;
|
||||
|
||||
/* create a detent close to the center */
|
||||
/* create a detent close to the center */
|
||||
|
||||
if (!detented && ARDOUR::Panner::equivalent (position_control->get_value(), 0.5)) {
|
||||
detented = true;
|
||||
/* snap to center */
|
||||
position_control->set_value (0.5);
|
||||
}
|
||||
if (!detented && ARDOUR::Panner::equivalent (position_control->get_value(), 0.5)) {
|
||||
detented = true;
|
||||
/* snap to center */
|
||||
position_control->set_value (0.5);
|
||||
}
|
||||
|
||||
if (detented) {
|
||||
accumulated_delta += delta;
|
||||
if (detented) {
|
||||
accumulated_delta += delta;
|
||||
|
||||
/* have we pulled far enough to escape ? */
|
||||
/* have we pulled far enough to escape ? */
|
||||
|
||||
if (fabs (accumulated_delta) >= 0.025) {
|
||||
position_control->set_value (position_control->get_value() + accumulated_delta);
|
||||
detented = false;
|
||||
accumulated_delta = false;
|
||||
}
|
||||
} else {
|
||||
double pv = position_control->get_value(); // 0..1.0 ; 0 = left
|
||||
position_control->set_value (pv + delta);
|
||||
}
|
||||
if (fabs (accumulated_delta) >= 0.025) {
|
||||
position_control->set_value (position_control->get_value() + accumulated_delta);
|
||||
detented = false;
|
||||
accumulated_delta = false;
|
||||
}
|
||||
} else {
|
||||
double pv = position_control->get_value(); // 0..1.0 ; 0 = left
|
||||
position_control->set_value (pv + delta);
|
||||
}
|
||||
|
||||
last_drag_x = ev->x;
|
||||
return true;
|
||||
last_drag_x = ev->x;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MonoPanner::on_key_press_event (GdkEventKey* ev)
|
||||
{
|
||||
double one_degree = 1.0/180.0;
|
||||
double pv = position_control->get_value(); // 0..1.0 ; 0 = left
|
||||
double step;
|
||||
double one_degree = 1.0/180.0;
|
||||
double pv = position_control->get_value(); // 0..1.0 ; 0 = left
|
||||
double step;
|
||||
|
||||
if (Keyboard::modifier_state_contains (ev->state, Keyboard::PrimaryModifier)) {
|
||||
step = one_degree;
|
||||
} else {
|
||||
step = one_degree * 5.0;
|
||||
}
|
||||
if (_panner_shell->bypassed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (ev->keyval) {
|
||||
case GDK_Left:
|
||||
pv -= step;
|
||||
position_control->set_value (pv);
|
||||
break;
|
||||
case GDK_Right:
|
||||
pv += step;
|
||||
position_control->set_value (pv);
|
||||
break;
|
||||
case GDK_0:
|
||||
case GDK_KP_0:
|
||||
position_control->set_value (0.0);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (Keyboard::modifier_state_contains (ev->state, Keyboard::PrimaryModifier)) {
|
||||
step = one_degree;
|
||||
} else {
|
||||
step = one_degree * 5.0;
|
||||
}
|
||||
|
||||
return true;
|
||||
switch (ev->keyval) {
|
||||
case GDK_Left:
|
||||
pv -= step;
|
||||
position_control->set_value (pv);
|
||||
break;
|
||||
case GDK_Right:
|
||||
pv += step;
|
||||
position_control->set_value (pv);
|
||||
break;
|
||||
case GDK_0:
|
||||
case GDK_KP_0:
|
||||
position_control->set_value (0.0);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -450,6 +499,12 @@ MonoPanner::color_handler ()
|
|||
queue_draw ();
|
||||
}
|
||||
|
||||
void
|
||||
MonoPanner::bypass_handler ()
|
||||
{
|
||||
queue_draw ();
|
||||
}
|
||||
|
||||
PannerEditor*
|
||||
MonoPanner::editor ()
|
||||
{
|
||||
|
|
|
@ -28,6 +28,10 @@
|
|||
|
||||
#include "panner_interface.h"
|
||||
|
||||
namespace ARDOUR {
|
||||
class PannerShell;
|
||||
}
|
||||
|
||||
namespace PBD {
|
||||
class Controllable;
|
||||
}
|
||||
|
@ -35,7 +39,7 @@ namespace PBD {
|
|||
class MonoPanner : public PannerInterface
|
||||
{
|
||||
public:
|
||||
MonoPanner (boost::shared_ptr<ARDOUR::Panner>);
|
||||
MonoPanner (boost::shared_ptr<ARDOUR::PannerShell>);
|
||||
~MonoPanner ();
|
||||
|
||||
boost::shared_ptr<PBD::Controllable> get_controllable() const { return position_control; }
|
||||
|
@ -53,6 +57,7 @@ class MonoPanner : public PannerInterface
|
|||
|
||||
private:
|
||||
PannerEditor* editor ();
|
||||
boost::shared_ptr<ARDOUR::PannerShell> _panner_shell;
|
||||
|
||||
boost::shared_ptr<PBD::Controllable> position_control;
|
||||
PBD::ScopedConnectionList connections;
|
||||
|
@ -76,10 +81,14 @@ class MonoPanner : public PannerInterface
|
|||
|
||||
bool _dragging;
|
||||
|
||||
static Pango::AttrList panner_font_attributes;
|
||||
static bool have_font;
|
||||
|
||||
static ColorScheme colors;
|
||||
static void set_colors ();
|
||||
static bool have_colors;
|
||||
void color_handler ();
|
||||
void bypass_handler ();
|
||||
};
|
||||
|
||||
#endif /* __gtk_ardour_mono_panner_h__ */
|
||||
|
|
|
@ -51,6 +51,7 @@ PannerUI::PannerUI (Session* s)
|
|||
, _current_nins (-1)
|
||||
, pan_automation_style_button ("")
|
||||
, pan_automation_state_button ("")
|
||||
, _panner_list()
|
||||
{
|
||||
set_session (s);
|
||||
|
||||
|
@ -203,7 +204,7 @@ PannerUI::~PannerUI ()
|
|||
void
|
||||
PannerUI::panshell_changed ()
|
||||
{
|
||||
set_panner (_panshell, _panshell->panner());
|
||||
set_panner (_panshell, _panshell->panner());
|
||||
setup_pan ();
|
||||
}
|
||||
|
||||
|
@ -233,73 +234,51 @@ PannerUI::setup_pan ()
|
|||
return;
|
||||
}
|
||||
|
||||
if (nouts == 0 || nouts == 1) {
|
||||
if (_panshell->panner_gui_uri() == "http://ardour.org/plugin/panner_2in2out#ui")
|
||||
{
|
||||
boost::shared_ptr<Pannable> pannable = _panner->pannable();
|
||||
|
||||
/* stick something into the panning viewport so that it redraws */
|
||||
_stereo_panner = new StereoPanner (_panshell);
|
||||
_stereo_panner->set_size_request (-1, pan_bar_height);
|
||||
pan_vbox.pack_start (*_stereo_panner, false, false);
|
||||
|
||||
EventBox* eb = manage (new EventBox());
|
||||
pan_vbox.pack_start (*eb, false, false);
|
||||
boost::shared_ptr<AutomationControl> ac;
|
||||
|
||||
delete big_window;
|
||||
big_window = 0;
|
||||
ac = pannable->pan_azimuth_control;
|
||||
_stereo_panner->StartPositionGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::start_touch),
|
||||
boost::weak_ptr<AutomationControl> (ac)));
|
||||
_stereo_panner->StopPositionGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::stop_touch),
|
||||
boost::weak_ptr<AutomationControl>(ac)));
|
||||
|
||||
} else if (nouts == 2) {
|
||||
ac = pannable->pan_width_control;
|
||||
_stereo_panner->StartWidthGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::start_touch),
|
||||
boost::weak_ptr<AutomationControl> (ac)));
|
||||
_stereo_panner->StopWidthGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::stop_touch),
|
||||
boost::weak_ptr<AutomationControl>(ac)));
|
||||
_stereo_panner->signal_button_release_event().connect (sigc::mem_fun(*this, &PannerUI::pan_button_event));
|
||||
}
|
||||
else if (_panshell->panner_gui_uri() == "http://ardour.org/plugin/panner_1in2out#ui"
|
||||
|| _panshell->panner_gui_uri() == "http://ardour.org/plugin/panner_balance#ui")
|
||||
{
|
||||
boost::shared_ptr<Pannable> pannable = _panner->pannable();
|
||||
boost::shared_ptr<AutomationControl> ac = pannable->pan_azimuth_control;
|
||||
|
||||
if (nins == 2) {
|
||||
_mono_panner = new MonoPanner (_panshell);
|
||||
|
||||
/* add integrated 2in/2out panner GUI */
|
||||
_mono_panner->StartGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::start_touch),
|
||||
boost::weak_ptr<AutomationControl> (ac)));
|
||||
_mono_panner->StopGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::stop_touch),
|
||||
boost::weak_ptr<AutomationControl>(ac)));
|
||||
|
||||
boost::shared_ptr<Pannable> pannable = _panner->pannable();
|
||||
_mono_panner->signal_button_release_event().connect (sigc::mem_fun(*this, &PannerUI::pan_button_event));
|
||||
|
||||
_stereo_panner = new StereoPanner (_panner);
|
||||
_stereo_panner->set_size_request (-1, pan_bar_height);
|
||||
pan_vbox.pack_start (*_stereo_panner, false, false);
|
||||
|
||||
boost::shared_ptr<AutomationControl> ac;
|
||||
|
||||
ac = pannable->pan_azimuth_control;
|
||||
_stereo_panner->StartPositionGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::start_touch),
|
||||
boost::weak_ptr<AutomationControl> (ac)));
|
||||
_stereo_panner->StopPositionGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::stop_touch),
|
||||
boost::weak_ptr<AutomationControl>(ac)));
|
||||
|
||||
ac = pannable->pan_width_control;
|
||||
_stereo_panner->StartWidthGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::start_touch),
|
||||
boost::weak_ptr<AutomationControl> (ac)));
|
||||
_stereo_panner->StopWidthGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::stop_touch),
|
||||
boost::weak_ptr<AutomationControl>(ac)));
|
||||
_stereo_panner->signal_button_release_event().connect (sigc::mem_fun(*this, &PannerUI::pan_button_event));
|
||||
|
||||
} else if (nins == 1) {
|
||||
/* 1-in/2out */
|
||||
|
||||
boost::shared_ptr<Pannable> pannable = _panner->pannable();
|
||||
boost::shared_ptr<AutomationControl> ac = pannable->pan_azimuth_control;
|
||||
|
||||
_mono_panner = new MonoPanner (_panner);
|
||||
|
||||
_mono_panner->StartGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::start_touch),
|
||||
boost::weak_ptr<AutomationControl> (ac)));
|
||||
_mono_panner->StopGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::stop_touch),
|
||||
boost::weak_ptr<AutomationControl>(ac)));
|
||||
|
||||
_mono_panner->signal_button_release_event().connect (sigc::mem_fun(*this, &PannerUI::pan_button_event));
|
||||
|
||||
_mono_panner->set_size_request (-1, pan_bar_height);
|
||||
|
||||
update_pan_sensitive ();
|
||||
pan_vbox.pack_start (*_mono_panner, false, false);
|
||||
|
||||
} else {
|
||||
warning << string_compose (_("No panner user interface is currently available for %1-in/2out tracks/busses"),
|
||||
nins) << endmsg;
|
||||
}
|
||||
|
||||
delete big_window;
|
||||
big_window = 0;
|
||||
|
||||
} else {
|
||||
_mono_panner->set_size_request (-1, pan_bar_height);
|
||||
|
||||
update_pan_sensitive ();
|
||||
pan_vbox.pack_start (*_mono_panner, false, false);
|
||||
}
|
||||
else if (_panshell->panner_gui_uri() == "http://ardour.org/plugin/panner_vbap#ui")
|
||||
{
|
||||
if (!twod_panner) {
|
||||
twod_panner = new Panner2d (_panshell, 61);
|
||||
twod_panner->set_name ("MixerPanZone");
|
||||
|
@ -309,17 +288,26 @@ PannerUI::setup_pan ()
|
|||
|
||||
update_pan_sensitive ();
|
||||
twod_panner->reset (nins);
|
||||
if (big_window) {
|
||||
big_window->reset (nins);
|
||||
}
|
||||
if (big_window) {
|
||||
big_window->reset (nins);
|
||||
}
|
||||
twod_panner->set_size_request (-1, 61);
|
||||
|
||||
/* and finally, add it to the panner frame */
|
||||
|
||||
pan_vbox.pack_start (*twod_panner, false, false);
|
||||
pan_vbox.pack_start (*twod_panner, false, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* stick something into the panning viewport so that it redraws */
|
||||
EventBox* eb = manage (new EventBox());
|
||||
pan_vbox.pack_start (*eb, false, false);
|
||||
|
||||
delete big_window;
|
||||
big_window = 0;
|
||||
}
|
||||
|
||||
pan_vbox.show_all ();
|
||||
pan_vbox.show_all ();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -388,8 +376,27 @@ PannerUI::build_pan_menu ()
|
|||
bypass_menu_item->set_active (_panshell->bypassed());
|
||||
bypass_menu_item->signal_toggled().connect (sigc::mem_fun(*this, &PannerUI::pan_bypass_toggle));
|
||||
|
||||
items.push_back (MenuElem (_("Reset"), sigc::mem_fun (*this, &PannerUI::pan_reset)));
|
||||
items.push_back (MenuElem (_("Edit..."), sigc::mem_fun (*this, &PannerUI::pan_edit)));
|
||||
if (!_panshell->bypassed()) {
|
||||
items.push_back (MenuElem (_("Reset"), sigc::mem_fun (*this, &PannerUI::pan_reset)));
|
||||
items.push_back (MenuElem (_("Edit..."), sigc::mem_fun (*this, &PannerUI::pan_edit)));
|
||||
}
|
||||
|
||||
if (_route && _panner_list.size() > 1 && !_panshell->bypassed()) {
|
||||
RadioMenuItem::Group group;
|
||||
items.push_back (SeparatorElem());
|
||||
|
||||
assert(_panshell->user_selected_panner_uri() == ""
|
||||
|| _panshell->user_selected_panner_uri() == _panshell->current_panner_uri());
|
||||
|
||||
_suspend_menu_callbacks = true;
|
||||
for (std::map<std::string,std::string>::const_iterator p = _panner_list.begin(); p != _panner_list.end(); ++p) {
|
||||
items.push_back (RadioMenuElem (group, p->second,
|
||||
sigc::bind(sigc::mem_fun (*this, &PannerUI::pan_set_custom_type), p->first)));
|
||||
RadioMenuItem* i = dynamic_cast<RadioMenuItem *> (&items.back ());
|
||||
i->set_active (_panshell->current_panner_uri() == p->first);
|
||||
}
|
||||
_suspend_menu_callbacks = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -403,6 +410,9 @@ PannerUI::pan_bypass_toggle ()
|
|||
void
|
||||
PannerUI::pan_edit ()
|
||||
{
|
||||
if (_panshell->bypassed()) {
|
||||
return;
|
||||
}
|
||||
if (_mono_panner) {
|
||||
_mono_panner->edit ();
|
||||
} else if (_stereo_panner) {
|
||||
|
@ -413,9 +423,20 @@ PannerUI::pan_edit ()
|
|||
void
|
||||
PannerUI::pan_reset ()
|
||||
{
|
||||
if (_panshell->bypassed()) {
|
||||
return;
|
||||
}
|
||||
_panner->reset ();
|
||||
}
|
||||
|
||||
void
|
||||
PannerUI::pan_set_custom_type (std::string uri) {
|
||||
if (_suspend_menu_callbacks) return;
|
||||
if (_route) {
|
||||
_route->set_custom_panner_uri(uri);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PannerUI::effective_pan_display ()
|
||||
{
|
||||
|
@ -609,3 +630,10 @@ void
|
|||
PannerUI::position_adjusted ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
PannerUI::set_available_panners(boost::shared_ptr<ARDOUR::Route> r, std::map<std::string,std::string> p)
|
||||
{
|
||||
_route = r;
|
||||
_panner_list = p;
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@ class PannerUI : public Gtk::HBox, public ARDOUR::SessionHandlePtr
|
|||
|
||||
void set_width (Width);
|
||||
void setup_pan ();
|
||||
void set_available_panners(boost::shared_ptr<ARDOUR::Route>, std::map<std::string,std::string>);
|
||||
|
||||
void effective_pan_display ();
|
||||
|
||||
|
@ -141,6 +142,7 @@ class PannerUI : public Gtk::HBox, public ARDOUR::SessionHandlePtr
|
|||
void pan_reset ();
|
||||
void pan_bypass_toggle ();
|
||||
void pan_edit ();
|
||||
void pan_set_custom_type (std::string type);
|
||||
|
||||
void pan_automation_state_changed();
|
||||
void pan_automation_style_changed();
|
||||
|
@ -158,6 +160,10 @@ class PannerUI : public Gtk::HBox, public ARDOUR::SessionHandlePtr
|
|||
|
||||
void start_touch (boost::weak_ptr<ARDOUR::AutomationControl>);
|
||||
void stop_touch (boost::weak_ptr<ARDOUR::AutomationControl>);
|
||||
|
||||
boost::shared_ptr<ARDOUR::Route> _route;
|
||||
std::map<std::string,std::string> _panner_list;
|
||||
bool _suspend_menu_callbacks;
|
||||
};
|
||||
|
||||
#endif /* __ardour_gtk_panner_ui_h__ */
|
||||
|
|
|
@ -297,12 +297,17 @@ ProcessorEntry::setup_tooltip ()
|
|||
if (_processor) {
|
||||
boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (_processor);
|
||||
if (pi) {
|
||||
std::string postfix = "";
|
||||
uint32_t replicated;
|
||||
if ((replicated = pi->get_count()) > 1) {
|
||||
postfix = string_compose(_("\nThis mono plugin has been replicated %1 times."), replicated);
|
||||
}
|
||||
if (pi->plugin()->has_editor()) {
|
||||
ARDOUR_UI::instance()->set_tip (_button,
|
||||
string_compose (_("<b>%1</b>\nDouble-click to show GUI.\nAlt+double-click to show generic GUI."), name (Wide)));
|
||||
string_compose (_("<b>%1</b>\nDouble-click to show GUI.\nAlt+double-click to show generic GUI.%2"), name (Wide), postfix));
|
||||
} else {
|
||||
ARDOUR_UI::instance()->set_tip (_button,
|
||||
string_compose (_("<b>%1</b>\nDouble-click to show generic GUI."), name (Wide)));
|
||||
string_compose (_("<b>%1</b>\nDouble-click to show generic GUI.%2"), name (Wide), postfix));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -341,6 +346,13 @@ ProcessorEntry::name (Width w) const
|
|||
}
|
||||
|
||||
} else {
|
||||
boost::shared_ptr<ARDOUR::PluginInsert> pi;
|
||||
uint32_t replicated;
|
||||
if ((pi = boost::dynamic_pointer_cast<ARDOUR::PluginInsert> (_processor)) != 0
|
||||
&& (replicated = pi->get_count()) > 1)
|
||||
{
|
||||
name_display += string_compose(_("(%1x1) "), replicated);
|
||||
}
|
||||
|
||||
switch (w) {
|
||||
case Wide:
|
||||
|
@ -706,9 +718,6 @@ ProcessorEntry::PortIcon::on_expose_event (GdkEventExpose* ev)
|
|||
cairo_rectangle (cr, ev->area.x, ev->area.y, ev->area.width, ev->area.height);
|
||||
cairo_clip (cr);
|
||||
|
||||
cairo_set_line_width (cr, 5.0);
|
||||
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
|
||||
|
||||
Gtk::Allocation a = get_allocation();
|
||||
double const width = a.get_width();
|
||||
double const height = a.get_height();
|
||||
|
@ -719,8 +728,6 @@ ProcessorEntry::PortIcon::on_expose_event (GdkEventExpose* ev)
|
|||
cairo_rectangle (cr, 0, 0, width, height);
|
||||
cairo_fill (cr);
|
||||
|
||||
const double y0 = _input ? height-.5 : .5;
|
||||
|
||||
if (_ports.n_total() > 1) {
|
||||
for (uint32_t i = 0; i < _ports.n_total(); ++i) {
|
||||
if (i < _ports.n_midi()) {
|
||||
|
@ -734,10 +741,9 @@ ProcessorEntry::PortIcon::on_expose_event (GdkEventExpose* ev)
|
|||
UINT_RGBA_G_FLT(audio_port_color),
|
||||
UINT_RGBA_B_FLT(audio_port_color));
|
||||
}
|
||||
const float x = rintf(width * (.2f + .6f * i / (_ports.n_total() - 1.f))) + .5f;
|
||||
cairo_move_to (cr, x, y0);
|
||||
cairo_close_path(cr);
|
||||
cairo_stroke(cr);
|
||||
const float x = rintf(width * (.2f + .6f * i / (_ports.n_total() - 1.f)));
|
||||
cairo_rectangle (cr, x-1, 0, 3, height);
|
||||
cairo_fill(cr);
|
||||
}
|
||||
} else if (_ports.n_total() == 1) {
|
||||
if (_ports.n_midi() == 1) {
|
||||
|
@ -751,8 +757,9 @@ ProcessorEntry::PortIcon::on_expose_event (GdkEventExpose* ev)
|
|||
UINT_RGBA_G_FLT(audio_port_color),
|
||||
UINT_RGBA_B_FLT(audio_port_color));
|
||||
}
|
||||
cairo_move_to (cr, rintf(width * .5) + .5f, y0);
|
||||
cairo_close_path(cr);
|
||||
const float x = rintf(width * .5);
|
||||
cairo_rectangle (cr, x-1, 0, 3, height);
|
||||
cairo_fill(cr);
|
||||
cairo_stroke(cr);
|
||||
}
|
||||
|
||||
|
@ -797,7 +804,7 @@ ProcessorEntry::RoutingIcon::on_expose_event (GdkEventExpose* ev)
|
|||
UINT_RGBA_B_FLT(midi_port_color));
|
||||
if (midi_sources > 0 && midi_sinks > 0 && sinks > 1 && sources > 1) {
|
||||
for (uint32_t i = 0 ; i < midi_sources; ++i) {
|
||||
const float si_x = rintf(width * (.2f + .6f * i / (sinks - 1.f))) + .5f;
|
||||
const float si_x = rintf(width * (.2f + .6f * i / (sinks - 1.f))) + .5f;
|
||||
const float si_x0 = rintf(width * (.2f + .6f * i / (sources - 1.f))) + .5f;
|
||||
cairo_move_to (cr, si_x, height);
|
||||
cairo_curve_to (cr, si_x, 0, si_x0, height, si_x0, 0);
|
||||
|
|
|
@ -211,7 +211,7 @@ private:
|
|||
PortIcon(bool input) {
|
||||
_input = input;
|
||||
_ports = ARDOUR::ChanCount(ARDOUR::DataType::AUDIO, 1);
|
||||
set_size_request (-1, 3);
|
||||
set_size_request (-1, 2);
|
||||
}
|
||||
void set_ports(ARDOUR::ChanCount const ports) { _ports = ports; }
|
||||
private:
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <cmath>
|
||||
|
||||
#include <gtkmm/window.h>
|
||||
#include <pangomm/layout.h>
|
||||
|
||||
#include "pbd/controllable.h"
|
||||
#include "pbd/compose.h"
|
||||
|
@ -34,6 +35,7 @@
|
|||
|
||||
#include "ardour/pannable.h"
|
||||
#include "ardour/panner.h"
|
||||
#include "ardour/panner_shell.h"
|
||||
|
||||
#include "ardour_ui.h"
|
||||
#include "global_signals.h"
|
||||
|
@ -56,10 +58,14 @@ static const int top_step = 2;
|
|||
StereoPanner::ColorScheme StereoPanner::colors[3];
|
||||
bool StereoPanner::have_colors = false;
|
||||
|
||||
Pango::AttrList StereoPanner::panner_font_attributes;
|
||||
bool StereoPanner::have_font = false;
|
||||
|
||||
using namespace ARDOUR;
|
||||
|
||||
StereoPanner::StereoPanner (boost::shared_ptr<Panner> panner)
|
||||
: PannerInterface (panner)
|
||||
StereoPanner::StereoPanner (boost::shared_ptr<PannerShell> p)
|
||||
: PannerInterface (p->panner())
|
||||
, _panner_shell (p)
|
||||
, position_control (_panner->pannable()->pan_azimuth_control)
|
||||
, width_control (_panner->pannable()->pan_width_control)
|
||||
, dragging_position (false)
|
||||
|
@ -77,9 +83,21 @@ StereoPanner::StereoPanner (boost::shared_ptr<Panner> panner)
|
|||
set_colors ();
|
||||
have_colors = true;
|
||||
}
|
||||
if (!have_font) {
|
||||
Pango::FontDescription font;
|
||||
Pango::AttrFontDesc* font_attr;
|
||||
font = Pango::FontDescription ("ArdourMono");
|
||||
font.set_weight (Pango::WEIGHT_BOLD);
|
||||
font.set_size(9 * PANGO_SCALE);
|
||||
font_attr = new Pango::AttrFontDesc (Pango::Attribute::create_attr_font_desc (font));
|
||||
panner_font_attributes.change(*font_attr);
|
||||
delete font_attr;
|
||||
have_font = true;
|
||||
}
|
||||
|
||||
position_control->Changed.connect (connections, invalidator(*this), boost::bind (&StereoPanner::value_change, this), gui_context());
|
||||
width_control->Changed.connect (connections, invalidator(*this), boost::bind (&StereoPanner::value_change, this), gui_context());
|
||||
_panner_shell->Changed.connect (connections, invalidator (*this), boost::bind (&StereoPanner::bypass_handler, this), gui_context());
|
||||
|
||||
ColorsChanged.connect (sigc::mem_fun (*this, &StereoPanner::color_handler));
|
||||
|
||||
|
@ -94,6 +112,10 @@ StereoPanner::~StereoPanner ()
|
|||
void
|
||||
StereoPanner::set_tooltip ()
|
||||
{
|
||||
if (_panner_shell->bypassed()) {
|
||||
_tooltip.set_tip (_("bypassed"));
|
||||
return;
|
||||
}
|
||||
double pos = position_control->get_value(); // 0..1
|
||||
|
||||
/* We show the position of the center of the image relative to the left & right.
|
||||
|
@ -117,14 +139,17 @@ StereoPanner::on_expose_event (GdkEventExpose*)
|
|||
Glib::RefPtr<Gdk::Window> win (get_window());
|
||||
Glib::RefPtr<Gdk::GC> gc (get_style()->get_base_gc (get_state()));
|
||||
Cairo::RefPtr<Cairo::Context> context = get_window()->create_cairo_context();
|
||||
Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(get_pango_context());
|
||||
layout->set_attributes (panner_font_attributes);
|
||||
|
||||
int tw, th;
|
||||
int width, height;
|
||||
double pos = position_control->get_value (); /* 0..1 */
|
||||
double swidth = width_control->get_value (); /* -1..+1 */
|
||||
double fswidth = fabs (swidth);
|
||||
const double pos = position_control->get_value (); /* 0..1 */
|
||||
const double swidth = width_control->get_value (); /* -1..+1 */
|
||||
const double fswidth = fabs (swidth);
|
||||
const double corner_radius = 5.0;
|
||||
uint32_t o, f, t, b, r;
|
||||
State state;
|
||||
const double corner_radius = 5.0;
|
||||
|
||||
width = get_width();
|
||||
height = get_height ();
|
||||
|
@ -143,11 +168,20 @@ StereoPanner::on_expose_event (GdkEventExpose*)
|
|||
b = colors[state].background;
|
||||
r = colors[state].rule;
|
||||
|
||||
if (_panner_shell->bypassed()) {
|
||||
b = 0x20202040;
|
||||
f = 0x404040ff;
|
||||
o = 0x606060ff;
|
||||
t = 0x606060ff;
|
||||
r = 0x606060ff;
|
||||
}
|
||||
|
||||
/* background */
|
||||
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(b), UINT_RGBA_G_FLT(b), UINT_RGBA_B_FLT(b), UINT_RGBA_A_FLT(b));
|
||||
cairo_rectangle (context->cobj(), 0, 0, width, height);
|
||||
context->fill ();
|
||||
context->fill_preserve ();
|
||||
context->clip();
|
||||
|
||||
/* the usable width is reduced from the real width, because we need space for
|
||||
the two halves of LR boxes that will extend past the actual left/right
|
||||
|
@ -166,17 +200,13 @@ StereoPanner::on_expose_event (GdkEventExpose*)
|
|||
context->translate (1.0, 0.0);
|
||||
}
|
||||
|
||||
double center = (lr_box_size/2.0) + (usable_width * pos);
|
||||
const double pan_spread = (fswidth * usable_width)/2.0;
|
||||
const double half_lr_box = lr_box_size/2.0;
|
||||
int left;
|
||||
int right;
|
||||
|
||||
left = center - pan_spread; // center of left box
|
||||
right = center + pan_spread; // center of right box
|
||||
const double center = rint(half_lr_box + (usable_width * pos));
|
||||
const double pan_spread = rint((fswidth * (usable_width-1.0))/2.0);
|
||||
const double left = center - pan_spread;
|
||||
const double right = center + pan_spread;
|
||||
|
||||
/* center line */
|
||||
|
||||
context->set_line_width (1.0);
|
||||
context->move_to ((usable_width + lr_box_size)/2.0, 0);
|
||||
context->rel_line_to (0, height);
|
||||
|
@ -184,67 +214,64 @@ StereoPanner::on_expose_event (GdkEventExpose*)
|
|||
context->stroke ();
|
||||
|
||||
/* compute & draw the line through the box */
|
||||
|
||||
context->set_line_width (2);
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(o), UINT_RGBA_G_FLT(o), UINT_RGBA_B_FLT(o), UINT_RGBA_A_FLT(o));
|
||||
context->move_to (left, top_step+(pos_box_size/2.0)+step_down);
|
||||
context->line_to (left, top_step+(pos_box_size/2.0));
|
||||
context->line_to (right, top_step+(pos_box_size/2.0));
|
||||
context->line_to (right, top_step+(pos_box_size/2.0) + step_down);
|
||||
context->move_to (left, top_step + (pos_box_size/2.0) + step_down + 1.0);
|
||||
context->line_to (left, top_step + (pos_box_size/2.0));
|
||||
context->line_to (right, top_step + (pos_box_size/2.0));
|
||||
context->line_to (right, top_step + (pos_box_size/2.0) + step_down + 1.0);
|
||||
context->stroke ();
|
||||
|
||||
context->set_line_width (1.0);
|
||||
|
||||
/* left box */
|
||||
|
||||
rounded_rectangle (context, left - half_lr_box,
|
||||
half_lr_box+step_down,
|
||||
lr_box_size, lr_box_size, corner_radius);
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(o), UINT_RGBA_G_FLT(o), UINT_RGBA_B_FLT(o), UINT_RGBA_A_FLT(o));
|
||||
context->stroke_preserve ();
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(f), UINT_RGBA_G_FLT(f), UINT_RGBA_B_FLT(f), UINT_RGBA_A_FLT(f));
|
||||
context->fill ();
|
||||
|
||||
/* add text */
|
||||
|
||||
context->move_to (left - half_lr_box + 3,
|
||||
(lr_box_size/2) + step_down + 13);
|
||||
context->select_font_face ("sans-serif", Cairo::FONT_SLANT_NORMAL, Cairo::FONT_WEIGHT_BOLD);
|
||||
|
||||
if (state != Mono) {
|
||||
rounded_rectangle (context, left - half_lr_box,
|
||||
half_lr_box+step_down,
|
||||
lr_box_size, lr_box_size, corner_radius);
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(f), UINT_RGBA_G_FLT(f), UINT_RGBA_B_FLT(f), UINT_RGBA_A_FLT(f));
|
||||
context->fill_preserve();
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(o), UINT_RGBA_G_FLT(o), UINT_RGBA_B_FLT(o), UINT_RGBA_A_FLT(o));
|
||||
context->stroke();
|
||||
|
||||
/* add text */
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(t), UINT_RGBA_G_FLT(t), UINT_RGBA_B_FLT(t), UINT_RGBA_A_FLT(t));
|
||||
if (swidth < 0.0) {
|
||||
context->show_text (_("R"));
|
||||
layout->set_text (_("R"));
|
||||
} else {
|
||||
context->show_text (_("L"));
|
||||
layout->set_text (_("L"));
|
||||
}
|
||||
layout->get_pixel_size(tw, th);
|
||||
context->move_to (rint(left - tw/2), rint(lr_box_size + step_down - th/2));
|
||||
pango_cairo_show_layout (context->cobj(), layout->gobj());
|
||||
}
|
||||
|
||||
/* right box */
|
||||
|
||||
rounded_rectangle (context, right - half_lr_box,
|
||||
half_lr_box+step_down,
|
||||
lr_box_size, lr_box_size, corner_radius);
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(o), UINT_RGBA_G_FLT(o), UINT_RGBA_B_FLT(o), UINT_RGBA_A_FLT(o));
|
||||
context->stroke_preserve ();
|
||||
half_lr_box+step_down,
|
||||
lr_box_size, lr_box_size, corner_radius);
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(f), UINT_RGBA_G_FLT(f), UINT_RGBA_B_FLT(f), UINT_RGBA_A_FLT(f));
|
||||
context->fill ();
|
||||
context->fill_preserve();
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(o), UINT_RGBA_G_FLT(o), UINT_RGBA_B_FLT(o), UINT_RGBA_A_FLT(o));
|
||||
context->stroke();
|
||||
|
||||
/* add text */
|
||||
|
||||
context->move_to (right - half_lr_box + 3, (lr_box_size/2)+step_down + 13);
|
||||
context->set_source_rgba (UINT_RGBA_R_FLT(t), UINT_RGBA_G_FLT(t), UINT_RGBA_B_FLT(t), UINT_RGBA_A_FLT(t));
|
||||
|
||||
if (state == Mono) {
|
||||
context->show_text (_("M"));
|
||||
layout->set_text (_("M"));
|
||||
} else {
|
||||
if (swidth < 0.0) {
|
||||
context->show_text (_("L"));
|
||||
layout->set_text (_("L"));
|
||||
} else {
|
||||
context->show_text (_("R"));
|
||||
layout->set_text (_("R"));
|
||||
}
|
||||
}
|
||||
layout->get_pixel_size(tw, th);
|
||||
context->move_to (rint(right - tw/2), rint(lr_box_size + step_down - th/2));
|
||||
pango_cairo_show_layout (context->cobj(), layout->gobj());
|
||||
|
||||
/* draw the central box */
|
||||
|
||||
context->set_line_width (2.0);
|
||||
context->move_to (center + (pos_box_size/2.0), top_step); /* top right */
|
||||
context->rel_line_to (0.0, pos_box_size); /* lower right */
|
||||
|
@ -267,6 +294,10 @@ StereoPanner::on_button_press_event (GdkEventButton* ev)
|
|||
if (PannerInterface::on_button_press_event (ev)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_panner_shell->bypassed()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
drag_start_x = ev->x;
|
||||
last_drag_x = ev->x;
|
||||
|
@ -412,6 +443,10 @@ StereoPanner::on_button_release_event (GdkEventButton* ev)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (_panner_shell->bypassed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool const dp = dragging_position;
|
||||
|
||||
_dragging = false;
|
||||
|
@ -443,6 +478,10 @@ StereoPanner::on_scroll_event (GdkEventScroll* ev)
|
|||
double wv = width_control->get_value(); // 0..1.0 ; 0 = left
|
||||
double step;
|
||||
|
||||
if (_panner_shell->bypassed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Keyboard::modifier_state_contains (ev->state, Keyboard::PrimaryModifier)) {
|
||||
step = one_degree;
|
||||
} else {
|
||||
|
@ -474,6 +513,9 @@ StereoPanner::on_scroll_event (GdkEventScroll* ev)
|
|||
bool
|
||||
StereoPanner::on_motion_notify_event (GdkEventMotion* ev)
|
||||
{
|
||||
if (_panner_shell->bypassed()) {
|
||||
_dragging = false;
|
||||
}
|
||||
if (!_dragging) {
|
||||
return false;
|
||||
}
|
||||
|
@ -566,6 +608,10 @@ StereoPanner::on_key_press_event (GdkEventKey* ev)
|
|||
double wv = width_control->get_value(); // 0..1.0 ; 0 = left
|
||||
double step;
|
||||
|
||||
if (_panner_shell->bypassed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Keyboard::modifier_state_contains (ev->state, Keyboard::PrimaryModifier)) {
|
||||
step = one_degree;
|
||||
} else {
|
||||
|
@ -641,6 +687,12 @@ StereoPanner::color_handler ()
|
|||
queue_draw ();
|
||||
}
|
||||
|
||||
void
|
||||
StereoPanner::bypass_handler ()
|
||||
{
|
||||
queue_draw ();
|
||||
}
|
||||
|
||||
PannerEditor*
|
||||
StereoPanner::editor ()
|
||||
{
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
#include "gtkmm2ext/binding_proxy.h"
|
||||
#include "panner_interface.h"
|
||||
|
||||
namespace ARDOUR {
|
||||
class PannerShell;
|
||||
}
|
||||
|
||||
namespace PBD {
|
||||
class Controllable;
|
||||
}
|
||||
|
@ -35,7 +39,7 @@ namespace ARDOUR {
|
|||
class StereoPanner : public PannerInterface
|
||||
{
|
||||
public:
|
||||
StereoPanner (boost::shared_ptr<ARDOUR::Panner>);
|
||||
StereoPanner (boost::shared_ptr<ARDOUR::PannerShell>);
|
||||
~StereoPanner ();
|
||||
|
||||
boost::shared_ptr<PBD::Controllable> get_position_controllable() const { return position_control; }
|
||||
|
@ -56,6 +60,7 @@ class StereoPanner : public PannerInterface
|
|||
|
||||
private:
|
||||
PannerEditor* editor ();
|
||||
boost::shared_ptr<ARDOUR::PannerShell> _panner_shell;
|
||||
|
||||
boost::shared_ptr<PBD::Controllable> position_control;
|
||||
boost::shared_ptr<PBD::Controllable> width_control;
|
||||
|
@ -90,10 +95,14 @@ class StereoPanner : public PannerInterface
|
|||
|
||||
bool _dragging;
|
||||
|
||||
static Pango::AttrList panner_font_attributes;
|
||||
static bool have_font;
|
||||
|
||||
static ColorScheme colors[3];
|
||||
static void set_colors ();
|
||||
static bool have_colors;
|
||||
void color_handler ();
|
||||
void bypass_handler ();
|
||||
};
|
||||
|
||||
#endif /* __gtk_ardour_stereo_panner_h__ */
|
||||
|
|
|
@ -175,8 +175,11 @@ protected:
|
|||
extern "C" {
|
||||
struct LIBARDOUR_API PanPluginDescriptor {
|
||||
std::string name;
|
||||
std::string panner_uri;
|
||||
std::string gui_uri;
|
||||
int32_t in;
|
||||
int32_t out;
|
||||
uint32_t priority;
|
||||
ARDOUR::Panner* (*factory)(boost::shared_ptr<ARDOUR::Pannable>, boost::shared_ptr<ARDOUR::Speakers>);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -49,7 +49,8 @@ public:
|
|||
void discover_panners ();
|
||||
std::list<PannerInfo*> panner_info;
|
||||
|
||||
PannerInfo* select_panner (ChanCount in, ChanCount out);
|
||||
PannerInfo* select_panner (ChanCount in, ChanCount out, std::string const uri = "");
|
||||
PannerInfo* get_by_uri (std::string uri);
|
||||
|
||||
private:
|
||||
PannerManager();
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
namespace ARDOUR {
|
||||
|
||||
class Session;
|
||||
class Route;
|
||||
class Panner;
|
||||
class BufferSet;
|
||||
class AudioBuffer;
|
||||
|
@ -71,11 +72,23 @@ public:
|
|||
bool bypassed () const;
|
||||
void set_bypassed (bool);
|
||||
|
||||
std::string current_panner_uri() const { return _current_panner_uri; }
|
||||
std::string user_selected_panner_uri() const { return _user_selected_panner_uri; }
|
||||
std::string panner_gui_uri() const { return _panner_gui_uri; }
|
||||
|
||||
private:
|
||||
friend class Route;
|
||||
void distribute_no_automation (BufferSet& src, BufferSet& dest, pframes_t nframes, gain_t gain_coeff);
|
||||
bool set_user_selected_panner_uri (std::string const uri);
|
||||
|
||||
boost::shared_ptr<Panner> _panner;
|
||||
boost::shared_ptr<Pannable> _pannable;
|
||||
bool _bypassed;
|
||||
|
||||
std::string _current_panner_uri;
|
||||
std::string _user_selected_panner_uri;
|
||||
std::string _panner_gui_uri;
|
||||
bool _force_reselect;
|
||||
};
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
|
|
@ -256,6 +256,7 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
|
|||
int remove_processor (boost::shared_ptr<Processor>, ProcessorStreams* err = 0, bool need_process_lock = true);
|
||||
int remove_processors (const ProcessorList&, ProcessorStreams* err = 0);
|
||||
int reorder_processors (const ProcessorList& new_order, ProcessorStreams* err = 0);
|
||||
void set_custom_panner_uri (std::string const panner_uri);
|
||||
void disable_processors (Placement);
|
||||
void disable_processors ();
|
||||
void disable_plugins (Placement);
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
|
||||
#include "pbd/error.h"
|
||||
#include "pbd/compose.h"
|
||||
#include "pbd/file_utils.h"
|
||||
#include "pbd/pathscanner.h"
|
||||
#include "pbd/stl_delete.h"
|
||||
|
||||
#include "ardour/debug.h"
|
||||
#include "ardour/panner_manager.h"
|
||||
|
@ -59,25 +60,30 @@ PannerManager::instance ()
|
|||
return *_instance;
|
||||
}
|
||||
|
||||
static bool panner_filter (const string& str, void */*arg*/)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
return str[0] != '.' && (str.length() > 6 && str.find (".dylib") == (str.length() - 6));
|
||||
#else
|
||||
return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
PannerManager::discover_panners ()
|
||||
{
|
||||
vector<std::string> panner_modules;
|
||||
PathScanner scanner;
|
||||
std::vector<std::string *> *panner_modules;
|
||||
std::string search_path = panner_search_path().to_string();
|
||||
|
||||
Glib::PatternSpec so_extension_pattern("*.so");
|
||||
Glib::PatternSpec dylib_extension_pattern("*.dylib");
|
||||
DEBUG_TRACE (DEBUG::Panning, string_compose (_("looking for panners in %1\n"), search_path));
|
||||
|
||||
find_matching_files_in_search_path (panner_search_path (),
|
||||
so_extension_pattern, panner_modules);
|
||||
panner_modules = scanner (search_path, panner_filter, 0, false, true, 1, true);
|
||||
|
||||
find_matching_files_in_search_path (panner_search_path (),
|
||||
dylib_extension_pattern, panner_modules);
|
||||
|
||||
DEBUG_TRACE (DEBUG::Panning, string_compose (_("looking for panners in %1"), panner_search_path().to_string()));
|
||||
|
||||
for (vector<std::string>::iterator i = panner_modules.begin(); i != panner_modules.end(); ++i) {
|
||||
panner_discover (*i);
|
||||
for (vector<std::string *>::iterator i = panner_modules->begin(); i != panner_modules->end(); ++i) {
|
||||
panner_discover (**i);
|
||||
}
|
||||
vector_delete (panner_modules);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -97,7 +103,7 @@ PannerManager::panner_discover (string path)
|
|||
|
||||
if (i == panner_info.end()) {
|
||||
panner_info.push_back (pinfo);
|
||||
DEBUG_TRACE (DEBUG::Panning, string_compose(_("Panner discovered: \"%1\" in %2"), pinfo->descriptor.name, path));
|
||||
DEBUG_TRACE (DEBUG::Panning, string_compose(_("Panner discovered: \"%1\" in %2\n"), pinfo->descriptor.name, path));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,53 +144,87 @@ PannerManager::get_descriptor (string path)
|
|||
}
|
||||
|
||||
PannerInfo*
|
||||
PannerManager::select_panner (ChanCount in, ChanCount out)
|
||||
PannerManager::select_panner (ChanCount in, ChanCount out, std::string const uri)
|
||||
{
|
||||
PannerInfo* rv = NULL;
|
||||
PanPluginDescriptor* d;
|
||||
int32_t nin = in.n_audio();
|
||||
int32_t nout = out.n_audio();
|
||||
uint32_t priority = 0;
|
||||
|
||||
/* look for user-preference -- check if channels match */
|
||||
for (list<PannerInfo*>::iterator p = panner_info.begin(); p != panner_info.end(); ++p) {
|
||||
d = &(*p)->descriptor;
|
||||
if (d->panner_uri != uri) continue;
|
||||
if (d->in != nin && d->in != -1) continue;
|
||||
if (d->out != nout && d->out != -1) continue;
|
||||
return *p;
|
||||
}
|
||||
|
||||
/* look for exact match first */
|
||||
|
||||
for (list<PannerInfo*>::iterator p = panner_info.begin(); p != panner_info.end(); ++p) {
|
||||
d = &(*p)->descriptor;
|
||||
|
||||
if (d->in == nin && d->out == nout) {
|
||||
return *p;
|
||||
if (d->in == nin && d->out == nout && d->priority > priority) {
|
||||
priority = d->priority;
|
||||
rv = *p;
|
||||
}
|
||||
}
|
||||
if (rv) { return rv; }
|
||||
|
||||
/* no exact match, look for good fit on inputs and variable on outputs */
|
||||
|
||||
priority = 0;
|
||||
for (list<PannerInfo*>::iterator p = panner_info.begin(); p != panner_info.end(); ++p) {
|
||||
d = &(*p)->descriptor;
|
||||
|
||||
if (d->in == nin && d->out == -1) {
|
||||
return *p;
|
||||
if (d->in == nin && d->out == -1 && d->priority > priority) {
|
||||
priority = d->priority;
|
||||
rv = *p;
|
||||
}
|
||||
}
|
||||
if (rv) { return rv; }
|
||||
|
||||
/* no exact match, look for good fit on outputs and variable on inputs */
|
||||
|
||||
priority = 0;
|
||||
for (list<PannerInfo*>::iterator p = panner_info.begin(); p != panner_info.end(); ++p) {
|
||||
d = &(*p)->descriptor;
|
||||
|
||||
if (d->in == -1 && d->out == nout) {
|
||||
return *p;
|
||||
if (d->in == -1 && d->out == nout && d->priority > priority) {
|
||||
priority = d->priority;
|
||||
rv = *p;
|
||||
}
|
||||
}
|
||||
if (rv) { return rv; }
|
||||
|
||||
/* no exact match, look for variable fit on inputs and outputs */
|
||||
|
||||
priority = 0;
|
||||
for (list<PannerInfo*>::iterator p = panner_info.begin(); p != panner_info.end(); ++p) {
|
||||
d = &(*p)->descriptor;
|
||||
|
||||
if (d->in == -1 && d->out == -1) {
|
||||
return *p;
|
||||
if (d->in == -1 && d->out == -1 && d->priority > priority) {
|
||||
priority = d->priority;
|
||||
rv = *p;
|
||||
}
|
||||
}
|
||||
if (rv) { return rv; }
|
||||
|
||||
warning << string_compose (_("no panner discovered for in/out = %1/%2"), nin, nout) << endmsg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PannerInfo*
|
||||
PannerManager::get_by_uri (std::string uri)
|
||||
{
|
||||
PannerInfo* pi = NULL;
|
||||
for (list<PannerInfo*>::iterator p = panner_info.begin(); p != panner_info.end(); ++p) {
|
||||
if ((*p)->descriptor.panner_uri != uri) continue;
|
||||
pi = (*p);
|
||||
break;
|
||||
}
|
||||
return pi;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@ panner_search_path ()
|
|||
SearchPath spath(user_config_directory ());
|
||||
spath += ardour_dll_directory ();
|
||||
spath.add_subdirectory_to_paths(panner_dir_name);
|
||||
|
||||
spath += SearchPath(Glib::getenv(panner_env_variable_name));
|
||||
return spath;
|
||||
}
|
||||
|
|
|
@ -63,6 +63,10 @@ PannerShell::PannerShell (string name, Session& s, boost::shared_ptr<Pannable> p
|
|||
: SessionObject (s, name)
|
||||
, _pannable (p)
|
||||
, _bypassed (false)
|
||||
, _current_panner_uri("")
|
||||
, _user_selected_panner_uri("")
|
||||
, _panner_gui_uri("")
|
||||
, _force_reselect (false)
|
||||
{
|
||||
set_name (name);
|
||||
}
|
||||
|
@ -82,7 +86,7 @@ PannerShell::configure_io (ChanCount in, ChanCount out)
|
|||
the config hasn't changed, we're done.
|
||||
*/
|
||||
|
||||
if (_panner && (_panner->in().n_audio() == nins) && (_panner->out().n_audio() == nouts)) {
|
||||
if (!_force_reselect && _panner && (_panner->in().n_audio() == nins) && (_panner->out().n_audio() == nouts)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -90,17 +94,21 @@ PannerShell::configure_io (ChanCount in, ChanCount out)
|
|||
/* no need for panning with less than 2 outputs or no inputs */
|
||||
if (_panner) {
|
||||
_panner.reset ();
|
||||
_current_panner_uri = "";
|
||||
_panner_gui_uri = "";
|
||||
Changed (); /* EMIT SIGNAL */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
PannerInfo* pi = PannerManager::instance().select_panner (in, out);
|
||||
PannerInfo* pi = PannerManager::instance().select_panner (in, out, _user_selected_panner_uri);
|
||||
if (!pi) {
|
||||
cerr << "No panner found: check that panners are being discovered correctly during startup.\n";
|
||||
assert (pi);
|
||||
}
|
||||
|
||||
DEBUG_TRACE (DEBUG::Panning, string_compose (_("select panner: %1\n"), pi->descriptor.name.c_str()));
|
||||
|
||||
boost::shared_ptr<Speakers> speakers = _session.get_speakers ();
|
||||
|
||||
if (nouts != speakers->size()) {
|
||||
|
@ -116,6 +124,8 @@ PannerShell::configure_io (ChanCount in, ChanCount out)
|
|||
// boost_debug_shared_ptr_mark_interesting (p, "Panner");
|
||||
_panner.reset (p);
|
||||
_panner->configure_io (in, out);
|
||||
_current_panner_uri = pi->descriptor.panner_uri;
|
||||
_panner_gui_uri = pi->descriptor.gui_uri;
|
||||
|
||||
Changed (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
@ -126,6 +136,7 @@ PannerShell::get_state ()
|
|||
XMLNode* node = new XMLNode ("PannerShell");
|
||||
|
||||
node->add_property (X_("bypassed"), _bypassed ? X_("yes") : X_("no"));
|
||||
node->add_property (X_("user-panner"), _user_selected_panner_uri);
|
||||
|
||||
if (_panner) {
|
||||
node->add_child_nocopy (_panner->get_state ());
|
||||
|
@ -146,12 +157,29 @@ PannerShell::set_state (const XMLNode& node, int version)
|
|||
set_bypassed (string_is_affirmative (prop->value ()));
|
||||
}
|
||||
|
||||
if ((prop = node.property (X_("user-panner"))) != 0) {
|
||||
_user_selected_panner_uri = prop->value ();
|
||||
}
|
||||
|
||||
_panner.reset ();
|
||||
|
||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||
|
||||
if ((*niter)->name() == X_("Panner")) {
|
||||
|
||||
if ((prop = (*niter)->property (X_("uri")))) {
|
||||
PannerInfo* p = PannerManager::instance().get_by_uri(prop->value());
|
||||
if (p) {
|
||||
_panner.reset (p->descriptor.factory (_pannable, _session.get_speakers ()));
|
||||
_current_panner_uri = p->descriptor.panner_uri;
|
||||
_panner_gui_uri = p->descriptor.gui_uri;
|
||||
if (_panner->set_state (**niter, version) == 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else /* backwards compatibility */
|
||||
if ((prop = (*niter)->property (X_("type")))) {
|
||||
|
||||
list<PannerInfo*>::iterator p;
|
||||
|
@ -166,6 +194,8 @@ PannerShell::set_state (const XMLNode& node, int version)
|
|||
*/
|
||||
|
||||
_panner.reset ((*p)->descriptor.factory (_pannable, _session.get_speakers ()));
|
||||
_current_panner_uri = (*p)->descriptor.panner_uri;
|
||||
_panner_gui_uri = (*p)->descriptor.gui_uri;
|
||||
|
||||
if (_panner->set_state (**niter, version) == 0) {
|
||||
return -1;
|
||||
|
@ -347,3 +377,19 @@ PannerShell::bypassed () const
|
|||
{
|
||||
return _bypassed;
|
||||
}
|
||||
|
||||
/* set custom-panner config
|
||||
*
|
||||
* This function is intended to be only called from
|
||||
* Route::set_custom_panner()
|
||||
* which will trigger IO-reconfigutaion if this fn return true
|
||||
*/
|
||||
bool
|
||||
PannerShell::set_user_selected_panner_uri (std::string const uri)
|
||||
{
|
||||
if (uri == _user_selected_panner_uri) return false;
|
||||
_user_selected_panner_uri = uri;
|
||||
if (uri == _current_panner_uri) return false;
|
||||
_force_reselect = true;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "ardour/midi_port.h"
|
||||
#include "ardour/monitor_processor.h"
|
||||
#include "ardour/pannable.h"
|
||||
#include "ardour/panner.h"
|
||||
#include "ardour/panner_shell.h"
|
||||
#include "ardour/plugin_insert.h"
|
||||
#include "ardour/port.h"
|
||||
|
@ -1573,6 +1574,58 @@ Route::remove_processors (const ProcessorList& to_be_deleted, ProcessorStreams*
|
|||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Route::set_custom_panner_uri (std::string const panner_uri)
|
||||
{
|
||||
if (_in_configure_processors) {
|
||||
DEBUG_TRACE (DEBUG::Panning, string_compose (_("Route::set_custom_panner_uri '%1' -- called while in_configure_processors\n"), name()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_main_outs->panner_shell()->set_user_selected_panner_uri(panner_uri)) {
|
||||
DEBUG_TRACE (DEBUG::Panning, string_compose (_("Route::set_custom_panner_uri '%1 '%2' -- no change needed\n"), name(), panner_uri));
|
||||
/* no change needed */
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_TRACE (DEBUG::Panning, string_compose (_("Route::set_custom_panner_uri '%1 '%2' -- reconfigure I/O\n"), name(), panner_uri));
|
||||
|
||||
/* reconfigure I/O -- re-initialize panner modules */
|
||||
{
|
||||
Glib::Threads::RWLock::WriterLock lm (_processor_lock);
|
||||
Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
|
||||
|
||||
for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p) {
|
||||
boost::shared_ptr<Delivery> dl;
|
||||
boost::shared_ptr<Panner> panner;
|
||||
if ((dl = boost::dynamic_pointer_cast<Delivery> (*p)) == 0) {
|
||||
continue;
|
||||
}
|
||||
if (!dl->panner_shell()) {
|
||||
continue;
|
||||
}
|
||||
if (!(panner = dl->panner_shell()->panner())) {
|
||||
continue;
|
||||
}
|
||||
/* _main_outs has already been set before the loop.
|
||||
* Ignore the return status here. It need reconfiguration */
|
||||
if (dl->panner_shell() != _main_outs->panner_shell()) {
|
||||
if (!dl->panner_shell()->set_user_selected_panner_uri(panner_uri)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ChanCount in = panner->in();
|
||||
ChanCount out = panner->out();
|
||||
dl->panner_shell()->configure_io(in, out);
|
||||
dl->panner_shell()->pannable()->set_panner(dl->panner_shell()->panner());
|
||||
}
|
||||
}
|
||||
|
||||
processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
|
||||
_session.set_dirty ();
|
||||
}
|
||||
|
||||
void
|
||||
Route::reset_instrument_info ()
|
||||
{
|
||||
|
|
|
@ -54,10 +54,14 @@ template <>
|
|||
void
|
||||
SampleFormatConverter<int32_t>::init (framecnt_t max_frames, int type, int data_width)
|
||||
{
|
||||
// GDither is broken with GDither32bit if the dither depth is bigger than 24
|
||||
if(throw_level (ThrowObject) && data_width > 24) {
|
||||
throw Exception (*this, "Trying to use SampleFormatConverter<int32_t> a data width > 24");
|
||||
if(throw_level (ThrowObject) && data_width > 32) {
|
||||
throw Exception (*this, "Trying to use SampleFormatConverter<int32_t> with a data width > 32");
|
||||
}
|
||||
|
||||
// GDither is broken with GDither32bit if the dither depth is bigger than 24.
|
||||
// And since floats only have 24 bits of data, we are fine with this.
|
||||
data_width = std::min(data_width, 24);
|
||||
|
||||
init_common (max_frames);
|
||||
dither = gdither_new ((GDitherType) type, channels, GDither32bit, data_width);
|
||||
}
|
||||
|
@ -68,7 +72,7 @@ SampleFormatConverter<int16_t>::init (framecnt_t max_frames, int type, int data_
|
|||
{
|
||||
if (throw_level (ThrowObject) && data_width > 16) {
|
||||
throw Exception (*this, boost::str(boost::format
|
||||
("Data width (%1) too large for int16_t")
|
||||
("Data width (%1%) too large for int16_t")
|
||||
% data_width));
|
||||
}
|
||||
init_common (max_frames);
|
||||
|
@ -81,7 +85,7 @@ SampleFormatConverter<uint8_t>::init (framecnt_t max_frames, int type, int data_
|
|||
{
|
||||
if (throw_level (ThrowObject) && data_width > 8) {
|
||||
throw Exception (*this, boost::str(boost::format
|
||||
("Data width (%1) too large for uint8_t")
|
||||
("Data width (%1%) too large for uint8_t")
|
||||
% data_width));
|
||||
}
|
||||
init_common (max_frames);
|
||||
|
|
|
@ -31,27 +31,31 @@ class SampleFormatConverterTest : public CppUnit::TestFixture
|
|||
|
||||
void testInit()
|
||||
{
|
||||
// Float never uses dithering and should always use full 32 bits of data
|
||||
boost::shared_ptr<SampleFormatConverter<float> > f_converter (new SampleFormatConverter<float>(1));
|
||||
f_converter->init (frames, D_Tri, 32); // Doesn't throw
|
||||
CPPUNIT_ASSERT_THROW (f_converter->init (frames, D_Tri, 24), Exception);
|
||||
CPPUNIT_ASSERT_THROW (f_converter->init (frames, D_Tri, 48), Exception);
|
||||
|
||||
|
||||
/* Test that too large data widths throw.
|
||||
We are fine with unnecessarily narrow data widths */
|
||||
|
||||
boost::shared_ptr<SampleFormatConverter<int32_t> > i_converter (new SampleFormatConverter<int32_t>(1));
|
||||
i_converter->init (frames, D_Tri, 32); // Doesn't throw
|
||||
i_converter->init (frames, D_Tri, 24); // Doesn't throw
|
||||
CPPUNIT_ASSERT_THROW (i_converter->init (frames, D_Tri, 8), Exception);
|
||||
CPPUNIT_ASSERT_THROW (i_converter->init (frames, D_Tri, 16), Exception);
|
||||
i_converter->init (frames, D_Tri, 8); // Doesn't throw
|
||||
i_converter->init (frames, D_Tri, 16); // Doesn't throw
|
||||
CPPUNIT_ASSERT_THROW (i_converter->init (frames, D_Tri, 48), Exception);
|
||||
|
||||
|
||||
boost::shared_ptr<SampleFormatConverter<int16_t> > i16_converter (new SampleFormatConverter<int16_t>(1));
|
||||
i16_converter->init (frames, D_Tri, 16); // Doesn't throw
|
||||
CPPUNIT_ASSERT_THROW (i16_converter->init (frames, D_Tri, 8), Exception);
|
||||
i16_converter->init (frames, D_Tri, 8); // Doesn't throw
|
||||
CPPUNIT_ASSERT_THROW (i16_converter->init (frames, D_Tri, 32), Exception);
|
||||
CPPUNIT_ASSERT_THROW (i16_converter->init (frames, D_Tri, 48), Exception);
|
||||
|
||||
|
||||
boost::shared_ptr<SampleFormatConverter<uint8_t> > ui_converter (new SampleFormatConverter<uint8_t>(1));
|
||||
ui_converter->init (frames, D_Tri, 8); // Doesn't throw
|
||||
CPPUNIT_ASSERT_THROW (ui_converter->init (frames, D_Tri, 4), Exception);
|
||||
ui_converter->init (frames, D_Tri, 4); // Doesn't throw
|
||||
CPPUNIT_ASSERT_THROW (ui_converter->init (frames, D_Tri, 16), Exception);
|
||||
}
|
||||
|
||||
|
|
|
@ -108,6 +108,7 @@ namespace Gtkmm2ext {
|
|||
LIBGTKMM2EXT_API void rounded_top_half_rectangle (Cairo::RefPtr<Cairo::Context>, double x, double y, double w, double h, double r=10);
|
||||
LIBGTKMM2EXT_API void rounded_bottom_half_rectangle (Cairo::RefPtr<Cairo::Context>, double x, double y, double w, double h, double r=10);
|
||||
LIBGTKMM2EXT_API void rounded_right_half_rectangle (Cairo::RefPtr<Cairo::Context>, double x, double y, double w, double h, double r=10);
|
||||
LIBGTKMM2EXT_API void rounded_left_half_rectangle (Cairo::RefPtr<Cairo::Context>, double x, double y, double w, double h, double r=10);
|
||||
|
||||
/* C API for rounded rectangles */
|
||||
|
||||
|
@ -118,6 +119,7 @@ namespace Gtkmm2ext {
|
|||
LIBGTKMM2EXT_API void rounded_top_half_rectangle (cairo_t*, double x, double y, double w, double h, double r=10);
|
||||
LIBGTKMM2EXT_API void rounded_bottom_half_rectangle (cairo_t*, double x, double y, double w, double h, double r=10);
|
||||
LIBGTKMM2EXT_API void rounded_right_half_rectangle (cairo_t*, double x, double y, double w, double h, double r=10);
|
||||
LIBGTKMM2EXT_API void rounded_left_half_rectangle (cairo_t* cr, double x, double y, double w, double h, double r=10);
|
||||
|
||||
LIBGTKMM2EXT_API Gtk::Label* left_aligned_label (std::string const &);
|
||||
|
||||
|
|
|
@ -415,6 +415,13 @@ Gtkmm2ext::rounded_bottom_half_rectangle (Cairo::RefPtr<Cairo::Context> context,
|
|||
{
|
||||
rounded_bottom_half_rectangle (context->cobj(), x, y, w, h, r);
|
||||
}
|
||||
|
||||
void
|
||||
Gtkmm2ext::rounded_left_half_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
|
||||
{
|
||||
rounded_left_half_rectangle (context->cobj(), x, y, w, h, r);
|
||||
}
|
||||
|
||||
void
|
||||
Gtkmm2ext::rounded_right_half_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
|
||||
{
|
||||
|
@ -434,6 +441,19 @@ Gtkmm2ext::rounded_rectangle (cairo_t* cr, double x, double y, double w, double
|
|||
cairo_close_path (cr);
|
||||
}
|
||||
|
||||
void
|
||||
Gtkmm2ext::rounded_left_half_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
|
||||
{
|
||||
double degrees = M_PI / 180.0;
|
||||
|
||||
cairo_new_sub_path (cr);
|
||||
cairo_line_to (cr, x+w, y); // tr
|
||||
cairo_line_to (cr, x+w, y + h); // br
|
||||
cairo_arc (cr, x + r, y + h - r, r, 90 * degrees, 180 * degrees); //bl
|
||||
cairo_arc (cr, x + r, y + r, r, 180 * degrees, 270 * degrees); //tl
|
||||
cairo_close_path (cr);
|
||||
}
|
||||
|
||||
void
|
||||
Gtkmm2ext::rounded_right_half_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
|
||||
{
|
||||
|
|
|
@ -63,7 +63,10 @@ using namespace PBD;
|
|||
|
||||
static PanPluginDescriptor _descriptor = {
|
||||
"Mono to Stereo Panner",
|
||||
"http://ardour.org/plugin/panner_1in2out",
|
||||
"http://ardour.org/plugin/panner_1in2out#ui",
|
||||
1, 2,
|
||||
10000,
|
||||
Panner1in2out::factory
|
||||
};
|
||||
|
||||
|
@ -332,6 +335,8 @@ XMLNode&
|
|||
Panner1in2out::get_state ()
|
||||
{
|
||||
XMLNode& root (Panner::get_state ());
|
||||
root.add_property (X_("uri"), _descriptor.panner_uri);
|
||||
/* this is needed to allow new sessions to load with old Ardour: */
|
||||
root.add_property (X_("type"), _descriptor.name);
|
||||
return root;
|
||||
}
|
||||
|
|
|
@ -63,7 +63,10 @@ using namespace PBD;
|
|||
|
||||
static PanPluginDescriptor _descriptor = {
|
||||
"Equal Power Stereo",
|
||||
"http://ardour.org/plugin/panner_2in2out",
|
||||
"http://ardour.org/plugin/panner_2in2out#ui",
|
||||
2, 2,
|
||||
10000,
|
||||
Panner2in2out::factory
|
||||
};
|
||||
|
||||
|
@ -464,6 +467,8 @@ XMLNode&
|
|||
Panner2in2out::get_state ()
|
||||
{
|
||||
XMLNode& root (Panner::get_state ());
|
||||
root.add_property (X_("uri"), _descriptor.panner_uri);
|
||||
/* this is needed to allow new sessions to load with old Ardour: */
|
||||
root.add_property (X_("type"), _descriptor.name);
|
||||
return root;
|
||||
}
|
||||
|
|
333
libs/panners/stereobalance/panner_balance.cc
Normal file
333
libs/panners/stereobalance/panner_balance.cc
Normal file
|
@ -0,0 +1,333 @@
|
|||
/*
|
||||
Copyright (C) 2004-2011 Paul Davis
|
||||
adopted from 2in2out panner by Robin Gareus <robin@gareus.org>
|
||||
|
||||
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 <inttypes.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <cerrno>
|
||||
#include <fstream>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <locale.h>
|
||||
#include <unistd.h>
|
||||
#include <float.h>
|
||||
#include <iomanip>
|
||||
|
||||
#include <glibmm.h>
|
||||
|
||||
#include "pbd/cartesian.h"
|
||||
#include "pbd/convert.h"
|
||||
#include "pbd/error.h"
|
||||
#include "pbd/failed_constructor.h"
|
||||
#include "pbd/xml++.h"
|
||||
#include "pbd/enumwriter.h"
|
||||
|
||||
#include "evoral/Curve.hpp"
|
||||
|
||||
#include "ardour/audio_buffer.h"
|
||||
#include "ardour/audio_buffer.h"
|
||||
#include "ardour/buffer_set.h"
|
||||
#include "ardour/pan_controllable.h"
|
||||
#include "ardour/pannable.h"
|
||||
#include "ardour/runtime_functions.h"
|
||||
#include "ardour/session.h"
|
||||
#include "ardour/utils.h"
|
||||
#include "ardour/mix.h"
|
||||
|
||||
#include "panner_balance.h"
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
#include "pbd/mathfix.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
|
||||
static PanPluginDescriptor _descriptor = {
|
||||
"Stereo Balance",
|
||||
"http://ardour.org/plugin/panner_balance",
|
||||
"http://ardour.org/plugin/panner_balance#ui",
|
||||
2, 2,
|
||||
2000,
|
||||
Pannerbalance::factory
|
||||
};
|
||||
|
||||
extern "C" { PanPluginDescriptor* panner_descriptor () { return &_descriptor; } }
|
||||
|
||||
Pannerbalance::Pannerbalance (boost::shared_ptr<Pannable> p)
|
||||
: Panner (p)
|
||||
{
|
||||
if (!_pannable->has_state()) {
|
||||
_pannable->pan_azimuth_control->set_value (0.5);
|
||||
}
|
||||
|
||||
update ();
|
||||
|
||||
/* LEFT SIGNAL */
|
||||
pos_interp[0] = pos[0] = desired_pos[0];
|
||||
/* RIGHT SIGNAL */
|
||||
pos_interp[1] = pos[1] = desired_pos[1];
|
||||
|
||||
_pannable->pan_azimuth_control->Changed.connect_same_thread (*this, boost::bind (&Pannerbalance::update, this));
|
||||
}
|
||||
|
||||
Pannerbalance::~Pannerbalance ()
|
||||
{
|
||||
}
|
||||
|
||||
double
|
||||
Pannerbalance::position () const
|
||||
{
|
||||
return _pannable->pan_azimuth_control->get_value();
|
||||
}
|
||||
|
||||
void
|
||||
Pannerbalance::set_position (double p)
|
||||
{
|
||||
if (clamp_position (p)) {
|
||||
_pannable->pan_azimuth_control->set_value (p);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Pannerbalance::thaw ()
|
||||
{
|
||||
Panner::thaw ();
|
||||
if (_frozen == 0) {
|
||||
update ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Pannerbalance::update ()
|
||||
{
|
||||
if (_frozen) {
|
||||
return;
|
||||
}
|
||||
|
||||
float const pos = _pannable->pan_azimuth_control->get_value();
|
||||
|
||||
if (pos == .5) {
|
||||
desired_pos[0] = 1.0;
|
||||
desired_pos[1] = 1.0;
|
||||
} else if (pos > .5) {
|
||||
desired_pos[0] = 2 - 2. * pos;
|
||||
desired_pos[1] = 1.0;
|
||||
} else {
|
||||
desired_pos[0] = 1.0;
|
||||
desired_pos[1] = 2. * pos;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Pannerbalance::clamp_position (double& p)
|
||||
{
|
||||
p = max (min (p, 1.0), 0.0);
|
||||
return true;
|
||||
}
|
||||
|
||||
pair<double, double>
|
||||
Pannerbalance::position_range () const
|
||||
{
|
||||
return make_pair (0, 1);
|
||||
}
|
||||
|
||||
void
|
||||
Pannerbalance::distribute_one (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gain_coeff, pframes_t nframes, uint32_t which)
|
||||
{
|
||||
assert (obufs.count().n_audio() == 2);
|
||||
|
||||
pan_t delta;
|
||||
Sample* dst;
|
||||
pan_t pan;
|
||||
|
||||
Sample* const src = srcbuf.data();
|
||||
|
||||
dst = obufs.get_audio(which).data();
|
||||
|
||||
if (fabsf ((delta = (pos[which] - desired_pos[which]))) > 0.002) { // about 1 degree of arc
|
||||
|
||||
/* we've moving the pan by an appreciable amount, so we must
|
||||
interpolate over 64 frames or nframes, whichever is smaller */
|
||||
|
||||
pframes_t const limit = min ((pframes_t) 64, nframes);
|
||||
pframes_t n;
|
||||
|
||||
delta = -(delta / (float) (limit));
|
||||
|
||||
for (n = 0; n < limit; n++) {
|
||||
pos_interp[which] = pos_interp[which] + delta;
|
||||
pos[which] = pos_interp[which] + 0.9 * (pos[which] - pos_interp[which]);
|
||||
dst[n] += src[n] * pos[which] * gain_coeff;
|
||||
}
|
||||
|
||||
/* then pan the rest of the buffer; no need for interpolation for this bit */
|
||||
|
||||
pan = pos[which] * gain_coeff;
|
||||
|
||||
mix_buffers_with_gain (dst+n,src+n,nframes-n,pan);
|
||||
|
||||
} else {
|
||||
|
||||
pos[which] = desired_pos[which];
|
||||
pos_interp[which] = pos[which];
|
||||
|
||||
if ((pan = (pos[which] * gain_coeff)) != 1.0f) {
|
||||
|
||||
if (pan != 0.0f) {
|
||||
|
||||
/* pan is 1 but also not 0, so we must do it "properly" */
|
||||
|
||||
//obufs.get_audio(1).read_from (srcbuf, nframes);
|
||||
mix_buffers_with_gain(dst,src,nframes,pan);
|
||||
|
||||
/* mark that we wrote into the buffer */
|
||||
|
||||
// obufs[0] = 0;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
/* pan is 1 so we can just copy the input samples straight in */
|
||||
mix_buffers_no_gain(dst,src,nframes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Pannerbalance::distribute_one_automated (AudioBuffer& srcbuf, BufferSet& obufs,
|
||||
framepos_t start, framepos_t end, pframes_t nframes,
|
||||
pan_t** buffers, uint32_t which)
|
||||
{
|
||||
assert (obufs.count().n_audio() == 2);
|
||||
|
||||
Sample* dst;
|
||||
pan_t* pbuf;
|
||||
Sample* const src = srcbuf.data();
|
||||
pan_t* const position = buffers[0];
|
||||
|
||||
/* fetch positional data */
|
||||
|
||||
if (!_pannable->pan_azimuth_control->list()->curve().rt_safe_get_vector (start, end, position, nframes)) {
|
||||
/* fallback */
|
||||
distribute_one (srcbuf, obufs, 1.0, nframes, which);
|
||||
return;
|
||||
}
|
||||
|
||||
for (pframes_t n = 0; n < nframes; ++n) {
|
||||
|
||||
float const pos = position[n];
|
||||
|
||||
if (which == 0) { // Left
|
||||
if (pos > .5) {
|
||||
buffers[which][n] = 2 - 2. * pos;
|
||||
} else {
|
||||
buffers[which][n] = 1.0;
|
||||
}
|
||||
} else { // Right
|
||||
if (pos < .5) {
|
||||
buffers[which][n] = 2. * pos;
|
||||
} else {
|
||||
buffers[which][n] = 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dst = obufs.get_audio(which).data();
|
||||
pbuf = buffers[which];
|
||||
|
||||
for (pframes_t n = 0; n < nframes; ++n) {
|
||||
dst[n] += src[n] * pbuf[n];
|
||||
}
|
||||
|
||||
/* XXX it would be nice to mark the buffer as written to */
|
||||
}
|
||||
|
||||
Panner*
|
||||
Pannerbalance::factory (boost::shared_ptr<Pannable> p, boost::shared_ptr<Speakers> /* ignored */)
|
||||
{
|
||||
return new Pannerbalance (p);
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
Pannerbalance::get_state ()
|
||||
{
|
||||
XMLNode& root (Panner::get_state ());
|
||||
root.add_property (X_("uri"), _descriptor.panner_uri);
|
||||
/* this is needed to allow new sessions to load with old Ardour: */
|
||||
root.add_property (X_("type"), _descriptor.name);
|
||||
return root;
|
||||
}
|
||||
|
||||
std::set<Evoral::Parameter>
|
||||
Pannerbalance::what_can_be_automated() const
|
||||
{
|
||||
set<Evoral::Parameter> s;
|
||||
s.insert (Evoral::Parameter (PanAzimuthAutomation));
|
||||
return s;
|
||||
}
|
||||
|
||||
string
|
||||
Pannerbalance::describe_parameter (Evoral::Parameter p)
|
||||
{
|
||||
switch (p.type()) {
|
||||
case PanAzimuthAutomation:
|
||||
return _("L/R");
|
||||
default:
|
||||
return _pannable->describe_parameter (p);
|
||||
}
|
||||
}
|
||||
|
||||
string
|
||||
Pannerbalance::value_as_string (boost::shared_ptr<AutomationControl> ac) const
|
||||
{
|
||||
/* DO NOT USE LocaleGuard HERE */
|
||||
double val = ac->get_value();
|
||||
|
||||
switch (ac->parameter().type()) {
|
||||
case PanAzimuthAutomation:
|
||||
/* We show the position of the center of the image relative to the left & right.
|
||||
This is expressed as a pair of percentage values that ranges from (100,0)
|
||||
(hard left) through (50,50) (hard center) to (0,100) (hard right).
|
||||
|
||||
This is pretty wierd, but its the way audio engineers expect it. Just remember that
|
||||
the center of the USA isn't Kansas, its (50LA, 50NY) and it will all make sense.
|
||||
|
||||
This is designed to be as narrow as possible. Dedicated
|
||||
panner GUIs can do their own version of this if they need
|
||||
something less compact.
|
||||
*/
|
||||
|
||||
return string_compose (_("L%1R%2"), (int) rint (100.0 * (1.0 - val)),
|
||||
(int) rint (100.0 * val));
|
||||
|
||||
default:
|
||||
return _pannable->value_as_string (ac);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Pannerbalance::reset ()
|
||||
{
|
||||
set_position (0.5);
|
||||
update ();
|
||||
}
|
83
libs/panners/stereobalance/panner_balance.h
Normal file
83
libs/panners/stereobalance/panner_balance.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
Copyright (C) 2004-2014 Paul Davis
|
||||
adopted from 2in2out panner by Robin Gareus <robin@gareus.org>
|
||||
|
||||
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 __ardour_panner_balance_h__
|
||||
#define __ardour_panner_balance_h__
|
||||
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include "pbd/stateful.h"
|
||||
#include "pbd/controllable.h"
|
||||
#include "pbd/cartesian.h"
|
||||
|
||||
#include "ardour/automation_control.h"
|
||||
#include "ardour/automatable.h"
|
||||
#include "ardour/panner.h"
|
||||
#include "ardour/types.h"
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
class Pannerbalance : public Panner
|
||||
{
|
||||
public:
|
||||
Pannerbalance (boost::shared_ptr<Pannable>);
|
||||
~Pannerbalance ();
|
||||
|
||||
ChanCount in() const { return ChanCount (DataType::AUDIO, 2); }
|
||||
ChanCount out() const { return ChanCount (DataType::AUDIO, 2); }
|
||||
|
||||
void set_position (double);
|
||||
bool clamp_position (double&);
|
||||
std::pair<double, double> position_range () const;
|
||||
double position () const;
|
||||
|
||||
std::set<Evoral::Parameter> what_can_be_automated() const;
|
||||
|
||||
static Panner* factory (boost::shared_ptr<Pannable>, boost::shared_ptr<Speakers>);
|
||||
|
||||
std::string describe_parameter (Evoral::Parameter);
|
||||
std::string value_as_string (boost::shared_ptr<AutomationControl>) const;
|
||||
|
||||
XMLNode& get_state ();
|
||||
|
||||
void reset ();
|
||||
void thaw ();
|
||||
|
||||
protected:
|
||||
float pos[2];
|
||||
float desired_pos[2];
|
||||
float pos_interp[2];
|
||||
|
||||
void update ();
|
||||
|
||||
private:
|
||||
void distribute_one (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gain_coeff, pframes_t nframes, uint32_t which);
|
||||
void distribute_one_automated (AudioBuffer& srcbuf, BufferSet& obufs,
|
||||
framepos_t start, framepos_t end, pframes_t nframes,
|
||||
pan_t** buffers, uint32_t which);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif /* __ardour_panner_balance_h__ */
|
34
libs/panners/stereobalance/wscript
Normal file
34
libs/panners/stereobalance/wscript
Normal file
|
@ -0,0 +1,34 @@
|
|||
#!/usr/bin/env python
|
||||
from waflib.extras import autowaf as autowaf
|
||||
import os
|
||||
|
||||
# Library version (UNIX style major, minor, micro)
|
||||
# major increment <=> incompatible changes
|
||||
# minor increment <=> compatible changes (additions)
|
||||
# micro increment <=> no interface changes
|
||||
LIBARDOUR_PAN2IN2OUT_LIB_VERSION = '1.0.0'
|
||||
|
||||
# Mandatory variables
|
||||
top = '.'
|
||||
out = 'build'
|
||||
|
||||
def options(opt):
|
||||
autowaf.set_options(opt)
|
||||
|
||||
def configure(conf):
|
||||
autowaf.configure(conf)
|
||||
|
||||
def build(bld):
|
||||
obj = bld(features = 'cxx cxxshlib')
|
||||
obj.source = [ 'panner_balance.cc' ]
|
||||
obj.export_includes = ['.']
|
||||
obj.cxxflags = '-DPACKAGE="libardour_panbalance"'
|
||||
obj.includes = ['.']
|
||||
obj.name = 'libardour_panbalance'
|
||||
obj.target = 'panbalance'
|
||||
obj.use = 'libardour libardour_cp libpbd'
|
||||
obj.vnum = LIBARDOUR_PAN2IN2OUT_LIB_VERSION
|
||||
obj.install_path = os.path.join(bld.env['LIBDIR'], 'ardour3', 'panners')
|
||||
|
||||
def shutdown():
|
||||
autowaf.shutdown()
|
|
@ -46,7 +46,10 @@ using namespace std;
|
|||
|
||||
static PanPluginDescriptor _descriptor = {
|
||||
"VBAP 2D panner",
|
||||
"http://ardour.org/plugin/panner_vbap",
|
||||
"http://ardour.org/plugin/panner_vbap#ui",
|
||||
-1, -1,
|
||||
1000,
|
||||
VBAPanner::factory
|
||||
};
|
||||
|
||||
|
@ -392,7 +395,9 @@ VBAPanner::distribute_one_automated (AudioBuffer& /*src*/, BufferSet& /*obufs*/,
|
|||
XMLNode&
|
||||
VBAPanner::get_state ()
|
||||
{
|
||||
XMLNode& node (Panner::get_state());
|
||||
XMLNode& node (Panner::get_state());
|
||||
node.add_property (X_("uri"), _descriptor.panner_uri);
|
||||
/* this is needed to allow new sessions to load with old Ardour: */
|
||||
node.add_property (X_("type"), _descriptor.name);
|
||||
return node;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import os
|
|||
top = '.'
|
||||
out = 'build'
|
||||
|
||||
panners = [ '2in2out', '1in2out', 'vbap' ]
|
||||
panners = [ '2in2out', '1in2out', 'vbap', 'stereobalance' ]
|
||||
|
||||
def options(opt):
|
||||
autowaf.set_options(opt)
|
||||
|
|
16
wscript
16
wscript
|
@ -164,8 +164,9 @@ def set_compiler_flags (conf,opt):
|
|||
conf.define("_DARWIN_C_SOURCE", 1)
|
||||
|
||||
if conf.options.asan:
|
||||
conf.check_cxx(cxxflags=["-fsanitize=address"], linkflags=["-fsanitize=address"])
|
||||
conf.check_cxx(cxxflags=["-fsanitize=address", "-fno-omit-frame-pointer"], linkflags=["-fsanitize=address"])
|
||||
cxx_flags.append('-fsanitize=address')
|
||||
cxx_flags.append('-fno-omit-frame-pointer')
|
||||
linker_flags.append('-fsanitize=address')
|
||||
|
||||
if is_clang and platform == "darwin":
|
||||
|
@ -483,6 +484,8 @@ def options(opt):
|
|||
help='Raise a floating point exception if a denormal is detected')
|
||||
opt.add_option('--test', action='store_true', default=False, dest='build_tests',
|
||||
help="Build unit tests")
|
||||
opt.add_option('--run-tests', action='store_true', default=False, dest='run_tests',
|
||||
help="Run tests after build")
|
||||
opt.add_option('--single-tests', action='store_true', default=False, dest='single_tests',
|
||||
help="Build a single executable for each unit test")
|
||||
#opt.add_option('--tranzport', action='store_true', default=False, dest='tranzport',
|
||||
|
@ -511,7 +514,7 @@ def options(opt):
|
|||
opt.add_option('--cxx11', action='store_true', default=False, dest='cxx11',
|
||||
help='Turn on c++11 compiler flags (-std=c++11)')
|
||||
opt.add_option('--address-sanitizer', action='store_true', default=False, dest='asan',
|
||||
help='Turn on AddressSanitizer (requires GCC >= 4.8 or clang)')
|
||||
help='Turn on AddressSanitizer (requires GCC >= 4.8 or clang >= 3.1)')
|
||||
for i in children:
|
||||
opt.recurse(i)
|
||||
|
||||
|
@ -683,7 +686,8 @@ def configure(conf):
|
|||
conf.define('ENABLE_NLS', 1)
|
||||
conf.env['ENABLE_NLS'] = True
|
||||
if opts.build_tests:
|
||||
conf.env['BUILD_TESTS'] = opts.build_tests
|
||||
conf.env['BUILD_TESTS'] = True
|
||||
conf.env['RUN_TESTS'] = opts.run_tests
|
||||
if opts.single_tests:
|
||||
conf.env['SINGLE_TESTS'] = opts.single_tests
|
||||
#if opts.tranzport:
|
||||
|
@ -803,6 +807,9 @@ def build(bld):
|
|||
|
||||
bld.install_files (os.path.join(bld.env['SYSCONFDIR'], 'ardour3', ), 'ardour_system.rc')
|
||||
|
||||
if bld.env['RUN_TESTS']:
|
||||
bld.add_post_fun(test)
|
||||
|
||||
def i18n(bld):
|
||||
bld.recurse (i18n_children)
|
||||
|
||||
|
@ -817,3 +824,6 @@ def i18n_mo(bld):
|
|||
|
||||
def tarball(bld):
|
||||
create_stored_revision()
|
||||
|
||||
def test(bld):
|
||||
subprocess.call("gtk2_ardour/artest")
|
||||
|
|
Loading…
Reference in New Issue
Block a user