13
0

new mono panner widget; make stereo panner respond to changes in colors immediately

git-svn-id: svn://localhost/ardour2/branches/3.0@8474 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2011-01-07 17:36:01 +00:00
parent 603d07a80b
commit 7d252dbbb9
11 changed files with 655 additions and 77 deletions

View File

@ -102,10 +102,17 @@
<Option name="selected waveform outline" value="0f0f0fcc"/>
<Option name="selection rect" value="e8f4d377"/>
<Option name="selection" value="636363b2"/>
<Option name="mono panner outline" value="6a6565ff"/>
<Option name="mono panner fill" value="7e6f6fc9"/>
<Option name="mono panner text" value="000000ff"/>
<Option name="mono panner bg" value="2d2828ff"/>
<Option name="mono panner position fill" value="7a89b3ff"/>
<Option name="mono panner position outline" value="001cfeff"/>
<Option name="stereo panner outline" value="001cfeff"/>
<Option name="stereo panner fill" value="8ea2d7c9"/>
<Option name="stereo panner text" value="000000ff"/>
<Option name="stereo panner bg" value="2e2929ff"/>
<Option name="stereo panner rule" value="b5a594ff"/>
<Option name="stereo panner mono outline" value="a05600ff"/>
<Option name="stereo panner mono fill" value="e99668ca"/>
<Option name="stereo panner mono text" value="000000ff"/>

View File

@ -96,10 +96,17 @@ CANVAS_VARIABLE(canvasvar_SelectionRect, "selection rect")
CANVAS_VARIABLE(canvasvar_Selection, "selection")
CANVAS_VARIABLE(canvasvar_Silence, "silence")
CANVAS_VARIABLE(canvasvar_SilenceText, "silence text")
CANVAS_VARIABLE(canvasvar_MonoPannerOutline, "mono panner outline")
CANVAS_VARIABLE(canvasvar_MonoPannerFill, "mono panner fill")
CANVAS_VARIABLE(canvasvar_MonoPannerText, "mono panner text")
CANVAS_VARIABLE(canvasvar_MonoPannerBackground, "mono panner bg")
CANVAS_VARIABLE(canvasvar_MonoPannerPositionFill, "mono panner position fill")
CANVAS_VARIABLE(canvasvar_MonoPannerPositionOutline, "mono panner position outline")
CANVAS_VARIABLE(canvasvar_StereoPannerOutline, "stereo panner outline")
CANVAS_VARIABLE(canvasvar_StereoPannerFill, "stereo panner fill")
CANVAS_VARIABLE(canvasvar_StereoPannerText, "stereo panner text")
CANVAS_VARIABLE(canvasvar_StereoPannerBackground, "stereo panner bg")
CANVAS_VARIABLE(canvasvar_StereoPannerRule, "stereo panner rule")
CANVAS_VARIABLE(canvasvar_StereoPannerMonoOutline, "stereo panner mono outline")
CANVAS_VARIABLE(canvasvar_StereoPannerMonoFill, "stereo panner mono fill")
CANVAS_VARIABLE(canvasvar_StereoPannerMonoText, "stereo panner mono text")

484
gtk2_ardour/mono_panner.cc Normal file
View File

@ -0,0 +1,484 @@
/*
Copyright (C) 2000-2007 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cmath>
#include <gtkmm/window.h>
#include "pbd/controllable.h"
#include "pbd/compose.h"
#include "gtkmm2ext/gui_thread.h"
#include "gtkmm2ext/gtk_ui.h"
#include "gtkmm2ext/keyboard.h"
#include "ardour/panner.h"
#include "ardour_ui.h"
#include "global_signals.h"
#include "mono_panner.h"
#include "rgb_macros.h"
#include "utils.h"
#include "i18n.h"
using namespace std;
using namespace Gtk;
using namespace Gtkmm2ext;
static const int pos_box_size = 10;
static const int lr_box_size = 15;
static const int step_down = 10;
static const int top_step = 2;
MonoPanner::ColorScheme MonoPanner::colors;
bool MonoPanner::have_colors = false;
MonoPanner::MonoPanner (boost::shared_ptr<PBD::Controllable> position)
: position_control (position)
, dragging (false)
, drag_start_x (0)
, last_drag_x (0)
, accumulated_delta (0)
, detented (false)
, drag_data_window (0)
, drag_data_label (0)
, position_binder (position)
{
if (!have_colors) {
set_colors ();
have_colors = true;
}
position_control->Changed.connect (connections, invalidator(*this), boost::bind (&MonoPanner::value_change, this), gui_context());
set_flags (Gtk::CAN_FOCUS);
add_events (Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK|
Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|
Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|
Gdk::SCROLL_MASK|
Gdk::POINTER_MOTION_MASK);
ColorsChanged.connect (sigc::mem_fun (*this, &MonoPanner::color_handler));
}
MonoPanner::~MonoPanner ()
{
delete drag_data_window;
}
void
MonoPanner::set_drag_data ()
{
if (!drag_data_label) {
return;
}
double pos = position_control->get_value(); // 0..1
/* We show the position of the center of the image relative to the left & right.
This is expressed as a pair of percentage values that ranges from (100,0)
(hard left) through (50,50) (hard center) to (0,100) (hard right).
This is pretty wierd, but its the way audio engineers expect it. Just remember that
the center of the USA isn't Kansas, its (50LA, 50NY) and it will all make sense.
*/
drag_data_label->set_markup (string_compose (_("L:%1 R:%2"),
(int) rint (100.0 * (1.0 - pos)),
(int) rint (100.0 * pos)));
}
void
MonoPanner::value_change ()
{
set_drag_data ();
queue_draw ();
}
bool
MonoPanner::on_expose_event (GdkEventExpose* ev)
{
Glib::RefPtr<Gdk::Window> win (get_window());
Glib::RefPtr<Gdk::GC> gc (get_style()->get_base_gc (get_state()));
cairo_t* cr = gdk_cairo_create (win->gobj());
int width, height;
double pos = position_control->get_value (); /* 0..1 */
uint32_t o, f, t, b, pf, po;
width = get_width();
height = get_height ();
o = colors.outline;
f = colors.fill;
t = colors.text;
b = colors.background;
pf = colors.pos_fill;
po = colors.pos_outline;
/* background */
cairo_set_source_rgba (cr, UINT_RGBA_R_FLT(b), UINT_RGBA_G_FLT(b), UINT_RGBA_B_FLT(b), UINT_RGBA_A_FLT(b));
cairo_rectangle (cr, 0, 0, width, height);
cairo_fill (cr);
/* the usable width is reduced from the real width, because we need space for
the two halves of LR boxes that will extend past the actual left/right
positions (indicated by the vertical line segment above them).
*/
double usable_width = width - lr_box_size;
/* compute the centers of the L/R boxes based on the current stereo width */
if (fmod (usable_width,2.0) == 0) {
/* even width, but we need odd, so that there is an exact center.
So, offset cairo by 1, and reduce effective width by 1
*/
usable_width -= 1.0;
cairo_translate (cr, 1.0, 0.0);
}
double center = (lr_box_size/2.0) + (usable_width * pos);
const double half_lr_box = lr_box_size/2.0;
double left;
double right;
left = 4 + half_lr_box; // center of left box
right = width - 4 - half_lr_box; // center of right box
/* center line */
cairo_set_source_rgba (cr, UINT_RGBA_R_FLT(o), UINT_RGBA_G_FLT(o), UINT_RGBA_B_FLT(o), UINT_RGBA_A_FLT(o));
cairo_set_line_width (cr, 1.0);
cairo_move_to (cr, width/2.0, 0);
cairo_line_to (cr, width/2.0, height);
cairo_stroke (cr);
/* left box */
cairo_rectangle (cr,
left - half_lr_box,
half_lr_box+step_down,
lr_box_size, lr_box_size);
cairo_set_source_rgba (cr, UINT_RGBA_R_FLT(o), UINT_RGBA_G_FLT(o), UINT_RGBA_B_FLT(o), UINT_RGBA_A_FLT(o));
cairo_stroke_preserve (cr);
cairo_set_source_rgba (cr, UINT_RGBA_R_FLT(f), UINT_RGBA_G_FLT(f), UINT_RGBA_B_FLT(f), UINT_RGBA_A_FLT(f));
cairo_fill (cr);
/* add text */
cairo_move_to (cr,
left - half_lr_box + 3,
(lr_box_size/2) + step_down + 13);
cairo_select_font_face (cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_source_rgba (cr, UINT_RGBA_R_FLT(t), UINT_RGBA_G_FLT(t), UINT_RGBA_B_FLT(t), UINT_RGBA_A_FLT(t));
cairo_show_text (cr, _("L"));
/* right box */
cairo_rectangle (cr,
right - half_lr_box,
half_lr_box+step_down,
lr_box_size, lr_box_size);
cairo_set_source_rgba (cr, UINT_RGBA_R_FLT(o), UINT_RGBA_G_FLT(o), UINT_RGBA_B_FLT(o), UINT_RGBA_A_FLT(o));
cairo_stroke_preserve (cr);
cairo_set_source_rgba (cr, UINT_RGBA_R_FLT(f), UINT_RGBA_G_FLT(f), UINT_RGBA_B_FLT(f), UINT_RGBA_A_FLT(f));
cairo_fill (cr);
/* add text */
cairo_move_to (cr,
right - half_lr_box + 3,
(lr_box_size/2)+step_down + 13);
cairo_set_source_rgba (cr, UINT_RGBA_R_FLT(t), UINT_RGBA_G_FLT(t), UINT_RGBA_B_FLT(t), UINT_RGBA_A_FLT(t));
cairo_show_text (cr, _("R"));
/* 2 lines that connect them both */
cairo_set_source_rgba (cr, UINT_RGBA_R_FLT(o), UINT_RGBA_G_FLT(o), UINT_RGBA_B_FLT(o), UINT_RGBA_A_FLT(o));
cairo_set_line_width (cr, 1.0);
cairo_move_to (cr, left + half_lr_box, half_lr_box+step_down);
cairo_line_to (cr, right - half_lr_box, half_lr_box+step_down);
cairo_stroke (cr);
cairo_move_to (cr, left + half_lr_box, half_lr_box+step_down+lr_box_size);
cairo_line_to (cr, right - half_lr_box, half_lr_box+step_down+lr_box_size);
cairo_stroke (cr);
/* draw the position indicator */
cairo_set_line_width (cr, 2.0);
cairo_rectangle (cr, lrint (center - (pos_box_size/2.0)), top_step, pos_box_size, pos_box_size);
cairo_set_source_rgba (cr, UINT_RGBA_R_FLT(po), UINT_RGBA_G_FLT(po), UINT_RGBA_B_FLT(po), UINT_RGBA_A_FLT(po));
cairo_stroke_preserve (cr);
cairo_set_source_rgba (cr, UINT_RGBA_R_FLT(pf), UINT_RGBA_G_FLT(pf), UINT_RGBA_B_FLT(pf), UINT_RGBA_A_FLT(pf));
cairo_fill (cr);
/* done */
cairo_destroy (cr);
return true;
}
bool
MonoPanner::on_button_press_event (GdkEventButton* ev)
{
drag_start_x = ev->x;
last_drag_x = ev->x;
dragging = false;
accumulated_delta = 0;
detented = false;
/* Let the binding proxies get first crack at the press event
*/
if (ev->y < 20) {
if (position_binder.button_press_handler (ev)) {
return true;
}
}
if (ev->button != 1) {
return false;
}
if (ev->type == GDK_2BUTTON_PRESS) {
int width = get_width();
if (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier)) {
/* handled by button release */
return true;
}
if (ev->x <= width/3) {
/* left side dbl click */
position_control->set_value (0);
} else if (ev->x > 2*width/3) {
position_control->set_value (1.0);
} else {
position_control->set_value (0.5);
}
dragging = false;
} else if (ev->type == GDK_BUTTON_PRESS) {
if (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier)) {
/* handled by button release */
return true;
}
dragging = true;
}
return true;
}
bool
MonoPanner::on_button_release_event (GdkEventButton* ev)
{
if (ev->button != 1) {
return false;
}
dragging = false;
accumulated_delta = 0;
detented = false;
if (drag_data_window) {
drag_data_window->hide ();
}
if (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier)) {
/* reset to default */
position_control->set_value (0.5);
}
return true;
}
bool
MonoPanner::on_scroll_event (GdkEventScroll* ev)
{
double one_degree = 1.0/180.0; // one degree as a number from 0..1, since 180 degrees is the full L/R axis
double pv = position_control->get_value(); // 0..1.0 ; 0 = left
double step;
if (Keyboard::modifier_state_contains (ev->state, Keyboard::PrimaryModifier)) {
step = one_degree;
} else {
step = one_degree * 5.0;
}
switch (ev->direction) {
case GDK_SCROLL_UP:
case GDK_SCROLL_LEFT:
pv -= step;
position_control->set_value (pv);
break;
case GDK_SCROLL_DOWN:
case GDK_SCROLL_RIGHT:
pv += step;
position_control->set_value (pv);
break;
}
return true;
}
bool
MonoPanner::on_motion_notify_event (GdkEventMotion* ev)
{
if (!dragging) {
return false;
}
if (!drag_data_window) {
drag_data_window = new Window (WINDOW_POPUP);
drag_data_window->set_position (WIN_POS_MOUSE);
drag_data_window->set_decorated (false);
drag_data_label = manage (new Label);
drag_data_label->set_use_markup (true);
drag_data_window->set_border_width (6);
drag_data_window->add (*drag_data_label);
drag_data_label->show ();
Window* toplevel = dynamic_cast<Window*> (get_toplevel());
if (toplevel) {
drag_data_window->set_transient_for (*toplevel);
}
}
if (!drag_data_window->is_visible ()) {
/* move the window a little away from the mouse */
drag_data_window->move (ev->x_root+30, ev->y_root+30);
drag_data_window->present ();
}
int w = get_width();
double delta = (ev->x - last_drag_x) / (double) w;
/* create a detent close to the center */
if (!detented && ARDOUR::Panner::equivalent (position_control->get_value(), 0.5)) {
detented = true;
/* snap to center */
position_control->set_value (0.5);
}
if (detented) {
accumulated_delta += delta;
/* have we pulled far enough to escape ? */
if (fabs (accumulated_delta) >= 0.025) {
position_control->set_value (position_control->get_value() + accumulated_delta);
detented = false;
accumulated_delta = false;
}
} else {
double pv = position_control->get_value(); // 0..1.0 ; 0 = left
position_control->set_value (pv + delta);
}
last_drag_x = ev->x;
return true;
}
bool
MonoPanner::on_key_press_event (GdkEventKey* ev)
{
double one_degree = 1.0/180.0;
double pv = position_control->get_value(); // 0..1.0 ; 0 = left
double step;
if (Keyboard::modifier_state_contains (ev->state, Keyboard::PrimaryModifier)) {
step = one_degree;
} else {
step = one_degree * 5.0;
}
/* up/down control width because we consider pan position more "important"
(and thus having higher "sense" priority) than width.
*/
switch (ev->keyval) {
case GDK_Left:
pv -= step;
position_control->set_value (pv);
break;
case GDK_Right:
pv += step;
position_control->set_value (pv);
break;
default:
return false;
}
return true;
}
bool
MonoPanner::on_key_release_event (GdkEventKey* ev)
{
return false;
}
bool
MonoPanner::on_enter_notify_event (GdkEventCrossing* ev)
{
grab_focus ();
Keyboard::magic_widget_grab_focus ();
return false;
}
bool
MonoPanner::on_leave_notify_event (GdkEventCrossing*)
{
Keyboard::magic_widget_drop_focus ();
return false;
}
void
MonoPanner::set_colors ()
{
colors.fill = ARDOUR_UI::config()->canvasvar_MonoPannerFill.get();
colors.outline = ARDOUR_UI::config()->canvasvar_MonoPannerOutline.get();
colors.text = ARDOUR_UI::config()->canvasvar_MonoPannerText.get();
colors.background = ARDOUR_UI::config()->canvasvar_MonoPannerBackground.get();
colors.pos_outline = ARDOUR_UI::config()->canvasvar_MonoPannerPositionOutline.get();
colors.pos_fill = ARDOUR_UI::config()->canvasvar_MonoPannerPositionFill.get();
}
void
MonoPanner::color_handler ()
{
set_colors ();
queue_draw ();
}

85
gtk2_ardour/mono_panner.h Normal file
View File

@ -0,0 +1,85 @@
/*
Copyright (C) 2010 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __gtk_ardour_mono_panner_h__
#define __gtk_ardour_mono_panner_h__
#include "pbd/signals.h"
#include <gtkmm/drawingarea.h>
#include <boost/shared_ptr.hpp>
#include "gtkmm2ext/binding_proxy.h"
namespace PBD {
class Controllable;
}
class MonoPanner : public Gtk::DrawingArea
{
public:
MonoPanner (boost::shared_ptr<PBD::Controllable> pos);
~MonoPanner ();
boost::shared_ptr<PBD::Controllable> get_controllable() const { return position_control; }
protected:
bool on_expose_event (GdkEventExpose*);
bool on_button_press_event (GdkEventButton*);
bool on_button_release_event (GdkEventButton*);
bool on_motion_notify_event (GdkEventMotion*);
bool on_scroll_event (GdkEventScroll*);
bool on_key_press_event (GdkEventKey*);
bool on_key_release_event (GdkEventKey*);
bool on_enter_notify_event (GdkEventCrossing* ev);
bool on_leave_notify_event (GdkEventCrossing* ev);
private:
boost::shared_ptr<PBD::Controllable> position_control;
PBD::ScopedConnectionList connections;
bool dragging;
int drag_start_x;
int last_drag_x;
double accumulated_delta;
bool detented;
Gtk::Window* drag_data_window;
Gtk::Label* drag_data_label;
BindingProxy position_binder;
void value_change ();
void set_drag_data ();
struct ColorScheme {
uint32_t outline;
uint32_t fill;
uint32_t text;
uint32_t background;
uint32_t pos_outline;
uint32_t pos_fill;
};
static ColorScheme colors;
static void set_colors ();
static bool have_colors;
void color_handler ();
};
#endif /* __gtk_ardour_mono_panner_h__ */

View File

@ -29,9 +29,9 @@
#include "panner_ui.h"
#include "panner2d.h"
#include "utils.h"
#include "panner.h"
#include "gui_thread.h"
#include "stereo_panner.h"
#include "mono_panner.h"
#include "ardour/delivery.h"
#include "ardour/session.h"
@ -46,7 +46,7 @@ using namespace PBD;
using namespace Gtkmm2ext;
using namespace Gtk;
const int PannerUI::pan_bar_height = 20;
const int PannerUI::pan_bar_height = 40;
PannerUI::PannerUI (Session* s)
: _current_nouts (-1)
@ -307,7 +307,7 @@ PannerUI::~PannerUI ()
delete (*i);
}
for (vector<PannerBar*>::iterator i = pan_bars.begin(); i != pan_bars.end(); ++i) {
for (vector<MonoPanner*>::iterator i = pan_bars.begin(); i != pan_bars.end(); ++i) {
delete (*i);
}
@ -431,7 +431,7 @@ PannerUI::setup_pan ()
_stereo_panner = new StereoPanner (_panner->direction_control(),
_panner->width_control());
_stereo_panner->set_size_request (-1, 2 * pan_bar_height);
_stereo_panner->set_size_request (-1, pan_bar_height);
panning_viewport.add (*_stereo_panner);
} else {
@ -441,8 +441,8 @@ PannerUI::setup_pan ()
while ((asz = pan_adjustments.size()) < npans) {
float x, rx;
PannerBar* bc;
MonoPanner* mp;
/* initialize adjustment with 0.0 (L) or 1.0 (R) for the first and second panners,
which serves as a default, otherwise use current value */
@ -459,38 +459,29 @@ PannerUI::setup_pan ()
}
pan_adjustments.push_back (new Adjustment (x, 0, 1.0, 0.005, 0.05));
bc = new PannerBar (*pan_adjustments[asz],
boost::static_pointer_cast<PBD::Controllable>( _panner->pan_control( asz )) );
mp = new MonoPanner (_panner->pan_control (asz));
/* now set adjustment with current value of panner, then connect the signals */
pan_adjustments.back()->set_value(rx);
pan_adjustments.back()->signal_value_changed().connect (sigc::bind (sigc::mem_fun(*this, &PannerUI::pan_adjustment_changed), (uint32_t) asz));
connect_to_pan_control (asz);
bc->set_name ("PanSlider");
bc->set_shadow_type (Gtk::SHADOW_NONE);
boost::shared_ptr<AutomationControl> ac = _panner->pan_control (asz);
#if 0
if (asz) {
bc->StartGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::start_touch),
boost::weak_ptr<AutomationControl> (ac)));
bc->StopGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::stop_touch),
boost::weak_ptr<AutomationControl>(ac)));
}
char buf[64];
snprintf (buf, sizeof (buf), _("panner for channel %zu"), asz + 1);
ARDOUR_UI::instance()->set_tip (bc->event_widget(), buf);
bc->event_widget().signal_button_release_event().connect
#endif
mp->signal_button_release_event().connect
(sigc::bind (sigc::mem_fun(*this, &PannerUI::pan_button_event), (uint32_t) asz));
bc->set_size_request (-1, pan_bar_height);
bc->SpinnerActive.connect (sigc::mem_fun (*this, &PannerUI::bar_spinner_activate));
mp->set_size_request (-1, pan_bar_height);
pan_bars.push_back (bc);
pan_bar_packer.pack_start (*bc, false, false);
pan_bars.push_back (mp);
pan_bar_packer.pack_start (*mp, false, false);
}
/* now that we actually have the pan bars,
@ -703,22 +694,7 @@ PannerUI::pan_value_changed (uint32_t which)
twod_panner->move_puck (which, _panner->streampanner(which).get_position());
in_pan_update = false;
} else if (_stereo_panner) {
/* its taken care of */
} else if (_panner->npanners() > 0 && which < _panner->npanners()) {
AngularVector model = _panner->streampanner(which).get_position();
double fract = pan_adjustments[which]->get_value();
AngularVector view (BaseStereoPanner::lr_fract_to_azimuth (fract), 0.0);
if (!Panner::equivalent (model, view)) {
in_pan_update = true;
pan_adjustments[which]->set_value (BaseStereoPanner::azimuth_to_lr_fract (model.azi));
in_pan_update = false;
}
}
}
}
void
@ -765,7 +741,7 @@ PannerUI::update_pan_sensitive ()
case 1:
break;
case 2:
for (vector<PannerBar*>::iterator i = pan_bars.begin(); i != pan_bars.end(); ++i) {
for (vector<MonoPanner*>::iterator i = pan_bars.begin(); i != pan_bars.end(); ++i) {
(*i)->set_sensitive (sensitive);
}
break;

View File

@ -41,6 +41,7 @@ class Panner2d;
class PannerBar;
class Panner2dWindow;
class StereoPanner;
class MonoPanner;
namespace ARDOUR {
class Session;
@ -137,7 +138,8 @@ class PannerUI : public Gtk::HBox, public ARDOUR::SessionHandlePtr
void panning_link_direction_clicked ();
std::vector<Gtk::Adjustment*> pan_adjustments;
std::vector<PannerBar*> pan_bars;
//std::vector<PannerBar*> pan_bars;
std::vector<MonoPanner*> pan_bars;
void pan_adjustment_changed (uint32_t which);
void pan_value_changed (uint32_t which);

View File

@ -37,6 +37,7 @@
using namespace std;
using namespace ARDOUR;
using namespace PBD;
using namespace Gtk;
SessionImportDialog::SessionImportDialog (ARDOUR::Session* target) :
ArdourDialog (_("Import From Session")),
@ -65,7 +66,7 @@ SessionImportDialog::SessionImportDialog (ARDOUR::Session* target) :
get_vbox()->pack_start (file_frame, false, false);
// Session browser
session_tree = Gtk::TreeStore::create (sb_cols);
session_tree = TreeStore::create (sb_cols);
session_browser.set_model (session_tree);
session_browser.set_name ("SessionBrowser");
@ -74,23 +75,23 @@ SessionImportDialog::SessionImportDialog (ARDOUR::Session* target) :
session_browser.set_tooltip_column (3);
session_browser.get_column(0)->set_min_width (180);
session_browser.get_column(1)->set_min_width (40);
session_browser.get_column(1)->set_sizing (Gtk::TREE_VIEW_COLUMN_AUTOSIZE);
session_browser.get_column(1)->set_sizing (TREE_VIEW_COLUMN_AUTOSIZE);
session_scroll.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
session_scroll.set_policy (POLICY_AUTOMATIC, POLICY_AUTOMATIC);
session_scroll.add (session_browser);
session_scroll.set_size_request (220, 400);
// Connect signals
Gtk::CellRendererToggle *toggle = dynamic_cast<Gtk::CellRendererToggle *> (session_browser.get_column_cell_renderer (1));
CellRendererToggle *toggle = dynamic_cast<CellRendererToggle *> (session_browser.get_column_cell_renderer (1));
toggle->signal_toggled().connect(sigc::mem_fun (*this, &SessionImportDialog::update));
session_browser.signal_row_activated().connect(sigc::mem_fun (*this, &SessionImportDialog::show_info));
get_vbox()->pack_start (session_scroll, false, false);
// Buttons
cancel_button = add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
cancel_button = add_button (Stock::CANCEL, RESPONSE_CANCEL);
cancel_button->signal_clicked().connect (sigc::mem_fun (*this, &SessionImportDialog::end_dialog));
ok_button = add_button (_("Import"), Gtk::RESPONSE_ACCEPT);
ok_button = add_button (_("Import"), RESPONSE_ACCEPT);
ok_button->signal_clicked().connect (sigc::mem_fun (*this, &SessionImportDialog::do_merge));
// prompt signals XXX: problem - handlers to be in the same thread since they return values
@ -124,7 +125,7 @@ SessionImportDialog::load_session (const string& filename)
if (ElementImportHandler::dirty()) {
// Warn user
string txt = _("Some elements had errors in them. Please see the log for details");
Gtk::MessageDialog msg (txt, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK, true);
MessageDialog msg (txt, false, MESSAGE_WARNING, BUTTONS_OK, true);
msg.run();
}
}
@ -137,8 +138,8 @@ SessionImportDialog::fill_list ()
// Loop through element types
for (HandlerList::iterator handler = handlers.begin(); handler != handlers.end(); ++handler) {
Gtk::TreeModel::iterator iter = session_tree->append();
Gtk::TreeModel::Row row = *iter;
TreeModel::iterator iter = session_tree->append();
TreeModel::Row row = *iter;
row[sb_cols.name] = (*handler)->get_info();
row[sb_cols.queued] = false;
row[sb_cols.element] = ElementPtr(); // "Null" pointer
@ -147,7 +148,7 @@ SessionImportDialog::fill_list ()
ElementList &elements = (*handler)->elements;
for (ElementList::iterator element = elements.begin(); element != elements.end(); ++element) {
iter = session_tree->append(row.children());
Gtk::TreeModel::Row child = *iter;
TreeModel::Row child = *iter;
child[sb_cols.name] = (*element)->get_name();
child[sb_cols.queued] = false;
child[sb_cols.element] = *element;
@ -159,16 +160,22 @@ SessionImportDialog::fill_list ()
void
SessionImportDialog::browse ()
{
Gtk::FileChooserDialog dialog(_("Import from session"), browse_action());
FileChooserDialog dialog(_("Import from session"), browse_action());
dialog.set_transient_for(*this);
dialog.set_filename (file_entry.get_text());
dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
FileFilter session_filter;
session_filter.add_pattern ("*.ardour");
session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
dialog.add_filter (session_filter);
dialog.set_filter (session_filter);
dialog.add_button(Stock::CANCEL, RESPONSE_CANCEL);
dialog.add_button(Stock::OK, RESPONSE_OK);
int result = dialog.run();
if (result == Gtk::RESPONSE_OK) {
if (result == RESPONSE_OK) {
string filename = dialog.get_filename();
if (filename.length()) {
@ -183,12 +190,12 @@ SessionImportDialog::do_merge ()
{
// element types
Gtk::TreeModel::Children types = session_browser.get_model()->children();
Gtk::TreeModel::Children::iterator ti;
TreeModel::Children types = session_browser.get_model()->children();
TreeModel::Children::iterator ti;
for (ti = types.begin(); ti != types.end(); ++ti) {
// elements
Gtk::TreeModel::Children elements = ti->children();
Gtk::TreeModel::Children::iterator ei;
TreeModel::Children elements = ti->children();
TreeModel::Children::iterator ei;
for (ei = elements.begin(); ei != elements.end(); ++ei) {
if ((*ei)[sb_cols.queued]) {
ElementPtr element = (*ei)[sb_cols.element];
@ -202,7 +209,7 @@ SessionImportDialog::do_merge ()
if (ElementImportHandler::errors()) {
// Warn user
string txt = _("Some elements had errors in them. Please see the log for details");
Gtk::MessageDialog msg (txt, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK, true);
MessageDialog msg (txt, false, MESSAGE_WARNING, BUTTONS_OK, true);
msg.run();
}
}
@ -211,22 +218,22 @@ SessionImportDialog::do_merge ()
void
SessionImportDialog::update (string path)
{
Gtk::TreeModel::iterator cell = session_browser.get_model()->get_iter (path);
TreeModel::iterator cell = session_browser.get_model()->get_iter (path);
// Select all elements if element type is selected
if (path.size() == 1) {
{
// Prompt user for verification
string txt = _("This will select all elements of this type!");
Gtk::MessageDialog msg (txt, false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL, true);
if (msg.run() == Gtk::RESPONSE_CANCEL) {
MessageDialog msg (txt, false, MESSAGE_QUESTION, BUTTONS_OK_CANCEL, true);
if (msg.run() == RESPONSE_CANCEL) {
(*cell)[sb_cols.queued] = false;
return;
}
}
Gtk::TreeModel::Children elements = cell->children();
Gtk::TreeModel::Children::iterator ei;
TreeModel::Children elements = cell->children();
TreeModel::Children::iterator ei;
for (ei = elements.begin(); ei != elements.end(); ++ei) {
ElementPtr element = (*ei)[sb_cols.element];
if (element->prepare_move()) {
@ -249,16 +256,16 @@ SessionImportDialog::update (string path)
}
void
SessionImportDialog::show_info(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*)
SessionImportDialog::show_info(const TreeModel::Path& path, TreeViewColumn*)
{
if (path.size() == 1) {
return;
}
Gtk::TreeModel::iterator cell = session_browser.get_model()->get_iter (path);
TreeModel::iterator cell = session_browser.get_model()->get_iter (path);
string info = (*cell)[sb_cols.info];
Gtk::MessageDialog msg (info, false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_OK, true);
MessageDialog msg (info, false, MESSAGE_INFO, BUTTONS_OK, true);
msg.run();
}
@ -278,11 +285,11 @@ SessionImportDialog::open_rename_dialog (string text, string name)
string new_name;
prompter.set_name ("Prompter");
prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
prompter.add_button (Stock::SAVE, RESPONSE_ACCEPT);
prompter.set_prompt (text);
prompter.set_initial_text (name);
if (prompter.run() == Gtk::RESPONSE_ACCEPT) {
if (prompter.run() == RESPONSE_ACCEPT) {
prompter.get_result (new_name);
if (new_name.length()) {
name = new_name;
@ -295,8 +302,8 @@ SessionImportDialog::open_rename_dialog (string text, string name)
bool
SessionImportDialog::open_prompt_dialog (string text)
{
Gtk::MessageDialog msg (text, false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL, true);
if (msg.run() == Gtk::RESPONSE_OK) {
MessageDialog msg (text, false, MESSAGE_QUESTION, BUTTONS_OK_CANCEL, true);
if (msg.run() == RESPONSE_OK) {
return true;
}
return false;

View File

@ -52,7 +52,6 @@ static const int top_step = 2;
StereoPanner::ColorScheme StereoPanner::colors[3];
bool StereoPanner::have_colors = false;
PBD::Signal0<void> StereoPanner::color_change;
StereoPanner::StereoPanner (boost::shared_ptr<PBD::Controllable> position, boost::shared_ptr<PBD::Controllable> width)
: position_control (position)
@ -86,7 +85,7 @@ StereoPanner::StereoPanner (boost::shared_ptr<PBD::Controllable> position, boost
Gdk::SCROLL_MASK|
Gdk::POINTER_MOTION_MASK);
color_change.connect (connections, invalidator (*this), boost::bind (&DrawingArea::queue_draw, this), gui_context());
ColorsChanged.connect (sigc::mem_fun (*this, &StereoPanner::color_handler));
}
StereoPanner::~StereoPanner ()
@ -621,16 +620,24 @@ StereoPanner::set_colors ()
colors[Normal].outline = ARDOUR_UI::config()->canvasvar_StereoPannerOutline.get();
colors[Normal].text = ARDOUR_UI::config()->canvasvar_StereoPannerText.get();
colors[Normal].background = ARDOUR_UI::config()->canvasvar_StereoPannerBackground.get();
colors[Normal].rule = ARDOUR_UI::config()->canvasvar_StereoPannerRule.get();
colors[Mono].fill = ARDOUR_UI::config()->canvasvar_StereoPannerMonoFill.get();
colors[Mono].outline = ARDOUR_UI::config()->canvasvar_StereoPannerMonoOutline.get();
colors[Mono].text = ARDOUR_UI::config()->canvasvar_StereoPannerMonoText.get();
colors[Mono].background = ARDOUR_UI::config()->canvasvar_StereoPannerMonoBackground.get();
colors[Mono].rule = ARDOUR_UI::config()->canvasvar_StereoPannerRule.get();
colors[Inverted].fill = ARDOUR_UI::config()->canvasvar_StereoPannerInvertedFill.get();
colors[Inverted].outline = ARDOUR_UI::config()->canvasvar_StereoPannerInvertedOutline.get();
colors[Inverted].text = ARDOUR_UI::config()->canvasvar_StereoPannerInvertedText.get();
colors[Inverted].background = ARDOUR_UI::config()->canvasvar_StereoPannerInvertedBackground.get();
color_change (); /* EMIT SIGNAL */
colors[Inverted].rule = ARDOUR_UI::config()->canvasvar_StereoPannerRule.get();
}
void
StereoPanner::color_handler ()
{
set_colors ();
queue_draw ();
}

View File

@ -75,6 +75,7 @@ class StereoPanner : public Gtk::DrawingArea
uint32_t fill;
uint32_t text;
uint32_t background;
uint32_t rule;
};
enum State {
@ -86,7 +87,7 @@ class StereoPanner : public Gtk::DrawingArea
static ColorScheme colors[3];
static void set_colors ();
static bool have_colors;
static PBD::Signal0<void> color_change;
void color_handler ();
};
#endif /* __gtk_ardour_stereo_panner_h__ */

View File

@ -148,6 +148,7 @@ gtk2_ardour_sources = [
'mixer_strip.cc',
'mixer_ui.cc',
'monitor_section.cc',
'mono_panner.cc',
'mouse_cursors.cc',
'nag.cc',
'new_plugin_preset_dialog.cc',

View File

@ -130,7 +130,8 @@ StreamPanner::PanControllable::set_value (double val)
}
break;
default:
default: /* positional */
val = max (min (val, 1.0), 0.0);
streampanner->set_position (AngularVector (direct_control_to_stereo_pan (val), 0.0));
AutomationControl::set_value(val);
break;