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