merge (with conflict fixes) with master (even against rgareus' recommendation)
This commit is contained in:
@@ -551,6 +551,7 @@
|
||||
<menuitem action='newaux'/>
|
||||
<separator/>
|
||||
<menuitem action='controls'/>
|
||||
<menuitem action='send_options'/>
|
||||
<separator/>
|
||||
<menuitem action='clear'/>
|
||||
<menuitem action='clear_pre'/>
|
||||
|
||||
@@ -1041,29 +1041,13 @@ 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;
|
||||
|
||||
uint32_t in = _route->output()->n_ports().n_audio();
|
||||
uint32_t 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);
|
||||
panners.set_available_panners(PannerManager::instance().PannerManager::get_available_panners(in, out));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1891,10 +1875,13 @@ MixerStrip::show_send (boost::shared_ptr<Send> send)
|
||||
gain_meter().set_controls (_route, send->meter(), send->amp());
|
||||
gain_meter().setup_meters ();
|
||||
|
||||
uint32_t const in = _current_delivery->pans_required();
|
||||
uint32_t const out = _current_delivery->pan_outs();
|
||||
|
||||
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().set_available_panners(PannerManager::instance().PannerManager::get_available_panners(in, out));
|
||||
panner_ui().setup_pan ();
|
||||
panners.show_all ();
|
||||
panner_ui().show_all ();
|
||||
|
||||
input_button.set_sensitive (false);
|
||||
group_button.set_sensitive (false);
|
||||
|
||||
@@ -401,7 +401,7 @@ Panner2d::on_expose_event (GdkEventExpose *event)
|
||||
{
|
||||
CartesianVector c;
|
||||
cairo_t* cr;
|
||||
bool small_size = (height <= large_size_threshold);
|
||||
bool small = (height <= large_size_threshold);
|
||||
const double diameter = radius*2.0;
|
||||
|
||||
cr = gdk_cairo_create (get_window()->gobj());
|
||||
@@ -426,14 +426,14 @@ Panner2d::on_expose_event (GdkEventExpose *event)
|
||||
/* horizontal line of "crosshairs" */
|
||||
|
||||
cairo_set_source_rgba (cr, 0.282, 0.517, 0.662, 1.0);
|
||||
cairo_move_to (cr, 0.0, rint(radius) - .5);
|
||||
cairo_line_to (cr, diameter, rint(radius) - .5);
|
||||
cairo_move_to (cr, 0.0, rint(radius) + .5);
|
||||
cairo_line_to (cr, diameter, rint(radius) + .5);
|
||||
cairo_stroke (cr);
|
||||
|
||||
/* vertical line of "crosshairs" */
|
||||
|
||||
cairo_move_to (cr, rint(radius) - .5, 0);
|
||||
cairo_line_to (cr, rint(radius) - .5, diameter);
|
||||
cairo_move_to (cr, rint(radius) + .5, 0);
|
||||
cairo_line_to (cr, rint(radius) + .5, diameter);
|
||||
cairo_stroke (cr);
|
||||
|
||||
/* the circle on which signals live */
|
||||
@@ -484,7 +484,7 @@ Panner2d::on_expose_event (GdkEventExpose *event)
|
||||
|
||||
cairo_select_font_face (cr, "sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
||||
|
||||
if (small_size) {
|
||||
if (small) {
|
||||
arc_radius = 4.0;
|
||||
} else {
|
||||
cairo_set_font_size (cr, 10);
|
||||
@@ -526,12 +526,12 @@ Panner2d::on_expose_event (GdkEventExpose *event)
|
||||
cairo_set_source_rgba (cr, 0.517, 0.772, 0.882, 0.8);
|
||||
cairo_stroke (cr);
|
||||
|
||||
if (!small_size && !signal->text.empty()) {
|
||||
if (!small && !signal->text.empty()) {
|
||||
cairo_set_source_rgba (cr, 0.517, 0.772, 0.882, .9);
|
||||
/* the +/- adjustments are a hack to try to center the text in the circle
|
||||
* TODO use pango get_pixel_size() -- see mono_panner.cc
|
||||
*/
|
||||
if (small_size) {
|
||||
if (small) {
|
||||
cairo_move_to (cr, c.x - 1, c.y + 1);
|
||||
} else {
|
||||
cairo_move_to (cr, c.x - 4, c.y + 4);
|
||||
@@ -565,7 +565,7 @@ Panner2d::on_expose_event (GdkEventExpose *event)
|
||||
cairo_move_to (cr, c.x, c.y);
|
||||
cairo_save (cr);
|
||||
cairo_rotate (cr, -(speaker->position.azi/360.0) * (2.0 * M_PI));
|
||||
if (small_size) {
|
||||
if (small) {
|
||||
cairo_scale (cr, 0.8, 0.8);
|
||||
} else {
|
||||
cairo_scale (cr, 1.2, 1.2);
|
||||
@@ -583,7 +583,7 @@ Panner2d::on_expose_event (GdkEventExpose *event)
|
||||
cairo_fill (cr);
|
||||
cairo_restore (cr);
|
||||
|
||||
if (!small_size) {
|
||||
if (!small) {
|
||||
cairo_set_font_size (cr, 16);
|
||||
|
||||
/* move the text in just a bit */
|
||||
|
||||
@@ -388,7 +388,7 @@ PannerUI::build_pan_menu ()
|
||||
items.push_back (MenuElem (_("Edit..."), sigc::mem_fun (*this, &PannerUI::pan_edit)));
|
||||
}
|
||||
|
||||
if (_route && _panner_list.size() > 1 && !_panshell->bypassed()) {
|
||||
if (_panner_list.size() > 1 && !_panshell->bypassed()) {
|
||||
RadioMenuItem::Group group;
|
||||
items.push_back (SeparatorElem());
|
||||
|
||||
@@ -444,9 +444,7 @@ PannerUI::pan_reset ()
|
||||
void
|
||||
PannerUI::pan_set_custom_type (std::string uri) {
|
||||
if (_suspend_menu_callbacks) return;
|
||||
if (_route) {
|
||||
_route->set_custom_panner_uri(uri);
|
||||
}
|
||||
_panshell->select_panner_by_uri(uri);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -644,8 +642,7 @@ PannerUI::position_adjusted ()
|
||||
}
|
||||
|
||||
void
|
||||
PannerUI::set_available_panners(boost::shared_ptr<ARDOUR::Route> r, std::map<std::string,std::string> p)
|
||||
PannerUI::set_available_panners(std::map<std::string,std::string> p)
|
||||
{
|
||||
_route = r;
|
||||
_panner_list = p;
|
||||
}
|
||||
|
||||
@@ -73,7 +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 set_available_panners(std::map<std::string,std::string>);
|
||||
|
||||
void effective_pan_display ();
|
||||
|
||||
@@ -85,6 +85,7 @@ class PannerUI : public Gtk::HBox, public ARDOUR::SessionHandlePtr
|
||||
|
||||
private:
|
||||
friend class MixerStrip;
|
||||
friend class SendUI;
|
||||
|
||||
boost::shared_ptr<ARDOUR::PannerShell> _panshell;
|
||||
boost::shared_ptr<ARDOUR::Panner> _panner;
|
||||
@@ -161,7 +162,6 @@ 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;
|
||||
};
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "ardour/audioengine.h"
|
||||
#include "ardour/internal_return.h"
|
||||
#include "ardour/internal_send.h"
|
||||
#include "ardour/panner_shell.h"
|
||||
#include "ardour/plugin_insert.h"
|
||||
#include "ardour/pannable.h"
|
||||
#include "ardour/port_insert.h"
|
||||
@@ -456,6 +457,34 @@ ProcessorEntry::toggle_control_visibility (Control* c)
|
||||
_parent->update_gui_object_state (this);
|
||||
}
|
||||
|
||||
Menu *
|
||||
ProcessorEntry::build_send_options_menu ()
|
||||
{
|
||||
using namespace Menu_Helpers;
|
||||
Menu* menu = manage (new Menu);
|
||||
MenuList& items = menu->items ();
|
||||
|
||||
boost::shared_ptr<Send> send = boost::dynamic_pointer_cast<Send> (_processor);
|
||||
if (send) {
|
||||
|
||||
items.push_back (CheckMenuElem (_("Link panner controls")));
|
||||
CheckMenuItem* c = dynamic_cast<CheckMenuItem*> (&items.back ());
|
||||
c->set_active (send->panner_shell()->is_linked_to_route());
|
||||
c->signal_toggled().connect (sigc::mem_fun (*this, &ProcessorEntry::toggle_panner_link));
|
||||
|
||||
}
|
||||
return menu;
|
||||
}
|
||||
|
||||
void
|
||||
ProcessorEntry::toggle_panner_link ()
|
||||
{
|
||||
boost::shared_ptr<Send> send = boost::dynamic_pointer_cast<Send> (_processor);
|
||||
if (send) {
|
||||
send->panner_shell()->set_linked_to_route(!send->panner_shell()->is_linked_to_route());
|
||||
}
|
||||
}
|
||||
|
||||
ProcessorEntry::Control::Control (boost::shared_ptr<AutomationControl> c, string const & n)
|
||||
: _control (c)
|
||||
, _adjustment (gain_to_slider_position_with_max (1.0, Config->get_max_gain()), 0, 1, 0.01, 0.1)
|
||||
@@ -1092,6 +1121,20 @@ ProcessorBox::show_processor_menu (int arg)
|
||||
}
|
||||
}
|
||||
|
||||
Gtk::MenuItem* send_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/ProcessorMenu/send_options"));
|
||||
if (send_menu_item) {
|
||||
if (single_selection) {
|
||||
Menu* m = single_selection->build_send_options_menu ();
|
||||
if (m && !m->items().empty()) {
|
||||
send_menu_item->set_submenu (*m);
|
||||
send_menu_item->set_sensitive (true);
|
||||
} else {
|
||||
gtk_menu_item_set_submenu (send_menu_item->gobj(), 0);
|
||||
send_menu_item->set_sensitive (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Sensitise actions as approprioate */
|
||||
|
||||
cut_action->set_sensitive (can_cut());
|
||||
@@ -2071,7 +2114,8 @@ ProcessorBox::paste_processor_state (const XMLNodeList& nlist, boost::shared_ptr
|
||||
|
||||
boost::shared_ptr<Pannable> sendpan(new Pannable (*_session));
|
||||
XMLNode n (**niter);
|
||||
Send* s = new Send (*_session, sendpan, _route->mute_master());
|
||||
|
||||
Send* s = new Send (*_session, _route->pannable(), _route->mute_master());
|
||||
|
||||
IOProcessor::prepare_for_reset (n, s->name());
|
||||
|
||||
@@ -2404,6 +2448,7 @@ ProcessorBox::register_actions ()
|
||||
ActionManager::register_action (popup_act_grp, X_("newaux"), _("New Aux Send ..."));
|
||||
|
||||
ActionManager::register_action (popup_act_grp, X_("controls"), _("Controls"));
|
||||
ActionManager::register_action (popup_act_grp, X_("send_options"), _("Send Options"));
|
||||
|
||||
ActionManager::register_action (popup_act_grp, X_("clear"), _("Clear (all)"),
|
||||
sigc::ptr_fun (ProcessorBox::rb_clear));
|
||||
|
||||
@@ -138,6 +138,7 @@ public:
|
||||
void set_control_state (XMLNode const *);
|
||||
std::string state_id () const;
|
||||
Gtk::Menu* build_controls_menu ();
|
||||
Gtk::Menu* build_send_options_menu ();
|
||||
|
||||
protected:
|
||||
ArdourButton _button;
|
||||
@@ -205,6 +206,7 @@ private:
|
||||
std::list<Control*> _controls;
|
||||
|
||||
void toggle_control_visibility (Control *);
|
||||
void toggle_panner_link ();
|
||||
|
||||
class PortIcon : public Gtk::DrawingArea {
|
||||
public:
|
||||
|
||||
@@ -1637,6 +1637,8 @@ RCOptionEditor::RCOptionEditor ()
|
||||
|
||||
/* SOLO AND MUTE */
|
||||
|
||||
add_option (_("Solo / mute"), new OptionEditorHeading (_("Solo")));
|
||||
|
||||
add_option (_("Solo / mute"),
|
||||
new FaderOption (
|
||||
"solo-mute-gain",
|
||||
@@ -1750,6 +1752,16 @@ RCOptionEditor::RCOptionEditor ()
|
||||
sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
|
||||
));
|
||||
|
||||
add_option (_("Solo / mute"), new OptionEditorHeading (_("Send Routing")));
|
||||
|
||||
add_option (_("Solo / mute"),
|
||||
new BoolOption (
|
||||
"link-send-and-route-panner",
|
||||
_("Link panners of Aux and External Sends with main panner by default"),
|
||||
sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_send_and_route_panner),
|
||||
sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_send_and_route_panner)
|
||||
));
|
||||
|
||||
add_option (_("MIDI"),
|
||||
new BoolOption (
|
||||
"send-midi-clock",
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <gtkmm2ext/doi.h>
|
||||
|
||||
#include "ardour/io.h"
|
||||
#include "ardour/panner_manager.h"
|
||||
#include "ardour/send.h"
|
||||
#include "ardour/rc_configuration.h"
|
||||
|
||||
@@ -70,7 +71,11 @@ SendUI::SendUI (Gtk::Window* parent, boost::shared_ptr<Send> s, Session* session
|
||||
|
||||
_send->output()->changed.connect (connections, invalidator (*this), boost::bind (&SendUI::outs_changed, this, _1, _2), gui_context());
|
||||
|
||||
uint32_t const in = _send->pans_required();
|
||||
uint32_t const out = _send->pan_outs();
|
||||
|
||||
_panners.set_width (Wide);
|
||||
_panners.set_available_panners(PannerManager::instance().PannerManager::get_available_panners(in, out));
|
||||
_panners.setup_pan ();
|
||||
|
||||
_gpm.setup_meters ();
|
||||
@@ -97,7 +102,14 @@ SendUI::outs_changed (IOChange change, void* /*ignored*/)
|
||||
{
|
||||
ENSURE_GUI_THREAD (*this, &SendUI::outs_changed, change, ignored)
|
||||
if (change.type & IOChange::ConfigurationChanged) {
|
||||
uint32_t const in = _send->pans_required();
|
||||
uint32_t const out = _send->pan_outs();
|
||||
if (_panners._panner == 0) {
|
||||
_panners.set_panner (_send->panner_shell(), _send->panner());
|
||||
}
|
||||
_panners.set_available_panners(PannerManager::instance().PannerManager::get_available_panners(in, out));
|
||||
_panners.setup_pan ();
|
||||
_panners.show_all ();
|
||||
_gpm.setup_meters ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#ifndef __ardour_panner_manager_h__
|
||||
#define __ardour_panner_manager_h__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <glibmm/module.h>
|
||||
|
||||
#include "ardour/panner.h"
|
||||
@@ -27,7 +29,10 @@
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
typedef std::map<std::string,std::string> PannerUriMap;
|
||||
|
||||
struct LIBARDOUR_API PannerInfo {
|
||||
|
||||
PanPluginDescriptor descriptor;
|
||||
Glib::Module* module;
|
||||
|
||||
@@ -51,7 +56,8 @@ public:
|
||||
std::list<PannerInfo*> panner_info;
|
||||
|
||||
PannerInfo* select_panner (ChanCount in, ChanCount out, std::string const uri = "");
|
||||
PannerInfo* get_by_uri (std::string uri);
|
||||
PannerInfo* get_by_uri (std::string uri) const;
|
||||
PannerUriMap get_available_panners(uint32_t const a_in, uint32_t const a_out) const;
|
||||
|
||||
private:
|
||||
PannerManager();
|
||||
|
||||
@@ -50,7 +50,7 @@ class Pannable;
|
||||
class LIBARDOUR_API PannerShell : public SessionObject
|
||||
{
|
||||
public:
|
||||
PannerShell (std::string name, Session&, boost::shared_ptr<Pannable>);
|
||||
PannerShell (std::string name, Session&, boost::shared_ptr<Pannable>, bool is_send = false);
|
||||
virtual ~PannerShell ();
|
||||
|
||||
std::string describe_parameter (Evoral::Parameter param);
|
||||
@@ -64,25 +64,38 @@ public:
|
||||
XMLNode& get_state ();
|
||||
int set_state (const XMLNode&, int version);
|
||||
|
||||
PBD::Signal0<void> PannableChanged; /* Pannable changed -- l*/
|
||||
PBD::Signal0<void> Changed; /* panner and/or outputs count and/or bypass state changed */
|
||||
|
||||
boost::shared_ptr<Panner> panner() const { return _panner; }
|
||||
boost::shared_ptr<Pannable> pannable() const { return _pannable; }
|
||||
boost::shared_ptr<Pannable> pannable() const { return _panlinked ? _pannable_route : _pannable_internal; }
|
||||
|
||||
bool bypassed () const;
|
||||
void set_bypassed (bool);
|
||||
|
||||
bool is_send () const { return (_is_send); }
|
||||
bool is_linked_to_route () const { return (_is_send && _panlinked); }
|
||||
/* this function takes the process lock: */
|
||||
void set_linked_to_route (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; }
|
||||
|
||||
/* this function takes the process lock: */
|
||||
bool select_panner_by_uri (std::string const 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;
|
||||
|
||||
boost::shared_ptr<Pannable> _pannable_internal;
|
||||
boost::shared_ptr<Pannable> _pannable_route;
|
||||
bool _is_send;
|
||||
bool _panlinked;
|
||||
bool _bypassed;
|
||||
|
||||
std::string _current_panner_uri;
|
||||
|
||||
@@ -113,6 +113,8 @@ CONFIG_VARIABLE (gain_t, solo_mute_gain, "solo-mute-gain", 0.0)
|
||||
CONFIG_VARIABLE (std::string, monitor_bus_preferred_bundle, "monitor-bus-preferred-bundle", "")
|
||||
CONFIG_VARIABLE (bool, quieten_at_speed, "quieten-at-speed", true)
|
||||
|
||||
CONFIG_VARIABLE (bool, link_send_and_route_panner, "link-send-and-route-panner", true)
|
||||
|
||||
/* click */
|
||||
|
||||
CONFIG_VARIABLE (bool, clicking, "clicking", false)
|
||||
|
||||
@@ -58,7 +58,9 @@ Delivery::Delivery (Session& s, boost::shared_ptr<IO> io, boost::shared_ptr<Pann
|
||||
, _no_panner_reset (false)
|
||||
{
|
||||
if (pannable) {
|
||||
_panshell = boost::shared_ptr<PannerShell>(new PannerShell (_name, _session, pannable));
|
||||
bool is_send = false;
|
||||
if (r & (Delivery::Send|Delivery::Aux)) is_send = true;
|
||||
_panshell = boost::shared_ptr<PannerShell>(new PannerShell (_name, _session, pannable, is_send));
|
||||
}
|
||||
|
||||
_display_to_user = false;
|
||||
@@ -80,7 +82,9 @@ Delivery::Delivery (Session& s, boost::shared_ptr<Pannable> pannable, boost::sha
|
||||
, _no_panner_reset (false)
|
||||
{
|
||||
if (pannable) {
|
||||
_panshell = boost::shared_ptr<PannerShell>(new PannerShell (_name, _session, pannable));
|
||||
bool is_send = false;
|
||||
if (r & (Delivery::Send|Delivery::Aux)) is_send = true;
|
||||
_panshell = boost::shared_ptr<PannerShell>(new PannerShell (_name, _session, pannable, is_send));
|
||||
}
|
||||
|
||||
_display_to_user = false;
|
||||
@@ -364,6 +368,7 @@ Delivery::set_state (const XMLNode& node, int version)
|
||||
XMLNode* pannnode = node.child (X_("Pannable"));
|
||||
if (_panshell && _panshell->panner() && pannnode) {
|
||||
_panshell->pannable()->set_state (*pannnode, version);
|
||||
_panshell->pannable()->set_panner(_panshell->panner());
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -222,13 +222,35 @@ PannerManager::select_panner (ChanCount in, ChanCount out, std::string const uri
|
||||
}
|
||||
|
||||
PannerInfo*
|
||||
PannerManager::get_by_uri (std::string uri)
|
||||
PannerManager::get_by_uri (std::string uri) const
|
||||
{
|
||||
PannerInfo* pi = NULL;
|
||||
for (list<PannerInfo*>::iterator p = panner_info.begin(); p != panner_info.end(); ++p) {
|
||||
for (list<PannerInfo*>::const_iterator p = panner_info.begin(); p != panner_info.end(); ++p) {
|
||||
if ((*p)->descriptor.panner_uri != uri) continue;
|
||||
pi = (*p);
|
||||
break;
|
||||
}
|
||||
return pi;
|
||||
}
|
||||
|
||||
PannerUriMap
|
||||
PannerManager::get_available_panners(uint32_t const a_in, uint32_t const a_out) const
|
||||
{
|
||||
int const in = a_in;
|
||||
int const out = a_out;
|
||||
PannerUriMap panner_list;
|
||||
|
||||
if (out < 2 || in == 0) {
|
||||
return panner_list;
|
||||
}
|
||||
|
||||
/* get available panners for current configuration. */
|
||||
for (list<PannerInfo*>::const_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));
|
||||
}
|
||||
return panner_list;
|
||||
}
|
||||
|
||||
@@ -43,8 +43,10 @@
|
||||
#include "evoral/Curve.hpp"
|
||||
|
||||
#include "ardour/audio_buffer.h"
|
||||
#include "ardour/audioengine.h"
|
||||
#include "ardour/buffer_set.h"
|
||||
#include "ardour/debug.h"
|
||||
#include "ardour/pannable.h"
|
||||
#include "ardour/panner.h"
|
||||
#include "ardour/panner_manager.h"
|
||||
#include "ardour/panner_shell.h"
|
||||
@@ -59,21 +61,31 @@ using namespace std;
|
||||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
|
||||
PannerShell::PannerShell (string name, Session& s, boost::shared_ptr<Pannable> p)
|
||||
PannerShell::PannerShell (string name, Session& s, boost::shared_ptr<Pannable> p, bool is_send)
|
||||
: SessionObject (s, name)
|
||||
, _pannable (p)
|
||||
, _pannable_route (p)
|
||||
, _is_send (is_send)
|
||||
, _panlinked (true)
|
||||
, _bypassed (false)
|
||||
, _current_panner_uri("")
|
||||
, _user_selected_panner_uri("")
|
||||
, _panner_gui_uri("")
|
||||
, _force_reselect (false)
|
||||
{
|
||||
if (is_send) {
|
||||
_pannable_internal.reset(new Pannable (s));
|
||||
if (Config->get_link_send_and_route_panner()) {
|
||||
_panlinked = true;
|
||||
} else {
|
||||
_panlinked = false;
|
||||
}
|
||||
}
|
||||
set_name (name);
|
||||
}
|
||||
|
||||
PannerShell::~PannerShell ()
|
||||
{
|
||||
DEBUG_TRACE(DEBUG::Destruction, string_compose ("panner shell %3 for %1 destructor, panner is %4, pannable is %2\n", _name, _pannable, this, _panner));
|
||||
DEBUG_TRACE(DEBUG::Destruction, string_compose ("panner shell %3 for %1 destructor, panner is %4, pannable is %2\n", _name, _pannable_route, this, _panner));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -120,7 +132,8 @@ PannerShell::configure_io (ChanCount in, ChanCount out)
|
||||
speakers.reset (s);
|
||||
}
|
||||
|
||||
Panner* p = pi->descriptor.factory (_pannable, speakers);
|
||||
/* TODO don't allow to link _is_send if internal & route panners are different types */
|
||||
Panner* p = pi->descriptor.factory (pannable(), speakers);
|
||||
// boost_debug_shared_ptr_mark_interesting (p, "Panner");
|
||||
_panner.reset (p);
|
||||
_panner->configure_io (in, out);
|
||||
@@ -137,8 +150,9 @@ PannerShell::get_state ()
|
||||
|
||||
node->add_property (X_("bypassed"), _bypassed ? X_("yes") : X_("no"));
|
||||
node->add_property (X_("user-panner"), _user_selected_panner_uri);
|
||||
node->add_property (X_("linked-to-route"), _panlinked ? X_("yes") : X_("no"));
|
||||
|
||||
if (_panner) {
|
||||
if (_panner && _is_send) {
|
||||
node->add_child_nocopy (_panner->get_state ());
|
||||
}
|
||||
|
||||
@@ -157,6 +171,10 @@ PannerShell::set_state (const XMLNode& node, int version)
|
||||
set_bypassed (string_is_affirmative (prop->value ()));
|
||||
}
|
||||
|
||||
if ((prop = node.property (X_("linked-to-route"))) != 0) {
|
||||
_panlinked = string_is_affirmative (prop->value ());
|
||||
}
|
||||
|
||||
if ((prop = node.property (X_("user-panner"))) != 0) {
|
||||
_user_selected_panner_uri = prop->value ();
|
||||
}
|
||||
@@ -170,7 +188,8 @@ PannerShell::set_state (const XMLNode& node, int version)
|
||||
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 ()));
|
||||
_panner.reset (p->descriptor.factory (
|
||||
_is_send ? _pannable_internal : _pannable_route, _session.get_speakers ()));
|
||||
_current_panner_uri = p->descriptor.panner_uri;
|
||||
_panner_gui_uri = p->descriptor.gui_uri;
|
||||
if (_panner->set_state (**niter, version) == 0) {
|
||||
@@ -193,7 +212,8 @@ PannerShell::set_state (const XMLNode& node, int version)
|
||||
assumption, but it's still an assumption.
|
||||
*/
|
||||
|
||||
_panner.reset ((*p)->descriptor.factory (_pannable, _session.get_speakers ()));
|
||||
_panner.reset ((*p)->descriptor.factory (
|
||||
_is_send ? _pannable_internal : _pannable_route, _session.get_speakers ()));
|
||||
_current_panner_uri = (*p)->descriptor.panner_uri;
|
||||
_panner_gui_uri = (*p)->descriptor.gui_uri;
|
||||
|
||||
@@ -393,3 +413,41 @@ PannerShell::set_user_selected_panner_uri (std::string const uri)
|
||||
_force_reselect = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PannerShell::select_panner_by_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;
|
||||
if (_panner) {
|
||||
Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
|
||||
ChanCount in = _panner->in();
|
||||
ChanCount out = _panner->out();
|
||||
configure_io(in, out);
|
||||
pannable()->set_panner(_panner);
|
||||
_session.set_dirty ();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PannerShell::set_linked_to_route (bool onoff)
|
||||
{
|
||||
if (!_is_send || onoff == _panlinked) {
|
||||
return;
|
||||
}
|
||||
_panlinked = onoff;
|
||||
|
||||
_force_reselect = true;
|
||||
if (_panner) {
|
||||
Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
|
||||
ChanCount in = _panner->in();
|
||||
ChanCount out = _panner->out();
|
||||
configure_io(in, out);
|
||||
pannable()->set_panner(_panner);
|
||||
_session.set_dirty ();
|
||||
}
|
||||
PannableChanged();
|
||||
}
|
||||
|
||||
@@ -1568,6 +1568,10 @@ Route::remove_processors (const ProcessorList& to_be_deleted, ProcessorStreams*
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* currently unused (again) -- but will come in handy soon (again)
|
||||
* once there is an option to link route + delivery panner settings
|
||||
*/
|
||||
void
|
||||
Route::set_custom_panner_uri (std::string const panner_uri)
|
||||
{
|
||||
@@ -1619,6 +1623,7 @@ Route::set_custom_panner_uri (std::string const panner_uri)
|
||||
processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
|
||||
_session.set_dirty ();
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
Route::reset_instrument_info ()
|
||||
@@ -2553,8 +2558,7 @@ Route::set_processor_state (const XMLNode& node)
|
||||
|
||||
if (prop->value() == "intsend") {
|
||||
|
||||
boost::shared_ptr<Pannable> sendpan (new Pannable (_session));
|
||||
processor.reset (new InternalSend (_session, sendpan, _mute_master, boost::shared_ptr<Route>(), Delivery::Role (0)));
|
||||
processor.reset (new InternalSend (_session, _pannable, _mute_master, boost::shared_ptr<Route>(), Delivery::Aux));
|
||||
|
||||
} else if (prop->value() == "ladspa" || prop->value() == "Ladspa" ||
|
||||
prop->value() == "lv2" ||
|
||||
@@ -2570,8 +2574,7 @@ Route::set_processor_state (const XMLNode& node)
|
||||
|
||||
} else if (prop->value() == "send") {
|
||||
|
||||
boost::shared_ptr<Pannable> sendpan (new Pannable (_session));
|
||||
processor.reset (new Send (_session, sendpan, _mute_master));
|
||||
processor.reset (new Send (_session, _pannable, _mute_master));
|
||||
|
||||
} else {
|
||||
error << string_compose(_("unknown Processor type \"%1\"; ignored"), prop->value()) << endmsg;
|
||||
|
||||
@@ -477,7 +477,11 @@ void
|
||||
VBAPanner::reset ()
|
||||
{
|
||||
set_position (0);
|
||||
set_width (1);
|
||||
if (_signals.size() > 1) {
|
||||
set_width (1.0 - (1.0 / (double)_signals.size()));
|
||||
} else {
|
||||
set_width (0);
|
||||
}
|
||||
set_elevation (0);
|
||||
|
||||
update ();
|
||||
|
||||
Reference in New Issue
Block a user