summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <carl@carlh.net>2011-03-04 17:35:02 +0000
committerCarl Hetherington <carl@carlh.net>2011-03-04 17:35:02 +0000
commitcbf530b6b57e391e28f148e8805da817c97c9d1d (patch)
tree41975277d82fe00fe2ad007b80626352eb102bb3
parent88ff3c0bd120090f38d7b5f8d46236c0f296dde0 (diff)
Make speaker dialogue manage the session's Speakers. Make azimuth control work. Various tweaks.
git-svn-id: svn://localhost/ardour2/branches/3.0@9073 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--gtk2_ardour/speaker_dialog.cc177
-rw-r--r--gtk2_ardour/speaker_dialog.h14
-rw-r--r--libs/ardour/ardour/speaker.h6
-rw-r--r--libs/ardour/speakers.cc30
4 files changed, 203 insertions, 24 deletions
diff --git a/gtk2_ardour/speaker_dialog.cc b/gtk2_ardour/speaker_dialog.cc
index 3b2418ec0c..e265b2ed1b 100644
--- a/gtk2_ardour/speaker_dialog.cc
+++ b/gtk2_ardour/speaker_dialog.cc
@@ -22,6 +22,7 @@
#include "gtkmm2ext/keyboard.h"
#include "speaker_dialog.h"
+#include "gui_thread.h"
#include "i18n.h"
@@ -37,15 +38,16 @@ SpeakerDialog::SpeakerDialog ()
, azimuth_adjustment (0, 0.0, 360.0, 10.0, 1.0)
, azimuth_spinner (azimuth_adjustment)
, add_speaker_button (_("Add Speaker"))
- , use_system_button (_("Use System"))
-
+ , remove_speaker_button (_("Remove Speaker"))
+ /* initialize to 0 so that set_selected works below */
+ , selected_index (0)
+ , ignore_speaker_position_change (false)
+ , ignore_azimuth_change (false)
{
side_vbox.set_homogeneous (false);
- side_vbox.set_border_width (9);
+ side_vbox.set_border_width (6);
side_vbox.set_spacing (6);
- side_vbox.pack_start (azimuth_spinner, false, false);
side_vbox.pack_start (add_speaker_button, false, false);
- side_vbox.pack_start (use_system_button, false, false);
aspect_frame.set_size_request (200, 200);
aspect_frame.set_shadow_type (SHADOW_NONE);
@@ -54,9 +56,16 @@ SpeakerDialog::SpeakerDialog ()
hbox.set_spacing (6);
hbox.set_border_width (6);
hbox.pack_start (aspect_frame, true, true);
- hbox.pack_start (side_vbox, false, false);
+ hbox.pack_start (side_vbox, true, true);
+
+ HBox* current_speaker_hbox = manage (new HBox);
+ current_speaker_hbox->set_spacing (4);
+ current_speaker_hbox->pack_start (*manage (new Label (_("Azimuth:"))), false, false);
+ current_speaker_hbox->pack_start (azimuth_spinner, true, true);
+ current_speaker_hbox->pack_start (remove_speaker_button, true, true);
get_vbox()->pack_start (hbox);
+ get_vbox()->pack_start (*current_speaker_hbox, true, true);
get_vbox()->show_all ();
darea.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
@@ -68,25 +77,37 @@ SpeakerDialog::SpeakerDialog ()
darea.signal_motion_notify_event().connect (sigc::mem_fun (*this, &SpeakerDialog::darea_motion_notify_event));
add_speaker_button.signal_clicked().connect (sigc::mem_fun (*this, &SpeakerDialog::add_speaker));
+ remove_speaker_button.signal_clicked().connect (sigc::mem_fun (*this, &SpeakerDialog::remove_speaker));
+ azimuth_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &SpeakerDialog::azimuth_changed));
drag_index = -1;
+
+ /* selected index initialised to 0 above; this will set `no selection' and
+ sensitize widgets accordingly.
+ */
+ set_selected (-1);
}
void
SpeakerDialog::set_speakers (boost::shared_ptr<Speakers> s)
{
- speakers = *s;
+ _speakers = s;
}
-Speakers
+boost::shared_ptr<Speakers>
SpeakerDialog::get_speakers () const
{
- return speakers;
+ return _speakers.lock ();
}
bool
SpeakerDialog::darea_expose_event (GdkEventExpose* event)
{
+ boost::shared_ptr<Speakers> speakers = _speakers.lock ();
+ if (!speakers) {
+ return false;
+ }
+
gint x, y;
cairo_t* cr;
@@ -131,8 +152,8 @@ SpeakerDialog::darea_expose_event (GdkEventExpose* event)
arc_radius = 4.0;
}
- uint32_t n = 0;
- for (vector<Speaker>::iterator i = speakers.speakers().begin(); i != speakers.speakers().end(); ++i) {
+ int n = 0;
+ for (vector<Speaker>::iterator i = speakers->speakers().begin(); i != speakers->speakers().end(); ++i) {
Speaker& s (*i);
CartesianVector c (s.coords());
@@ -145,7 +166,11 @@ SpeakerDialog::darea_expose_event (GdkEventExpose* event)
/* XXX need to shift circles so that they are centered on the circle */
cairo_arc (cr, x, y, arc_radius, 0, 2.0 * M_PI);
- cairo_set_source_rgb (cr, 0.8, 0.2, 0.1);
+ if (selected_index == n) {
+ cairo_set_source_rgb (cr, 0.8, 0.8, 0.2);
+ } else {
+ cairo_set_source_rgb (cr, 0.8, 0.2, 0.1);
+ }
cairo_close_path (cr);
cairo_fill (cr);
@@ -224,6 +249,11 @@ SpeakerDialog::darea_size_allocate (Gtk::Allocation& alloc)
bool
SpeakerDialog::darea_button_press_event (GdkEventButton *ev)
{
+ boost::shared_ptr<Speakers> speakers = _speakers.lock ();
+ if (!speakers) {
+ return false;
+ }
+
GdkModifierType state;
if (ev->type == GDK_2BUTTON_PRESS && ev->button == 1) {
@@ -236,14 +266,17 @@ SpeakerDialog::darea_button_press_event (GdkEventButton *ev)
case 1:
case 2:
{
- drag_index = find_closest_object (ev->x, ev->y);
+ int const index = find_closest_object (ev->x, ev->y);
+ set_selected (index);
+
+ drag_index = index;
int const drag_x = (int) floor (ev->x);
int const drag_y = (int) floor (ev->y);
state = (GdkModifierType) ev->state;
if (drag_index >= 0) {
CartesianVector c;
- speakers.speakers()[drag_index].angles().cartesian (c);
+ speakers->speakers()[drag_index].angles().cartesian (c);
cart_to_gtk (c);
drag_offset_x = drag_x - x_origin - c.x;
drag_offset_y = drag_y - y_origin - c.y;
@@ -263,6 +296,11 @@ SpeakerDialog::darea_button_press_event (GdkEventButton *ev)
bool
SpeakerDialog::darea_button_release_event (GdkEventButton *ev)
{
+ boost::shared_ptr<Speakers> speakers = _speakers.lock ();
+ if (!speakers) {
+ return false;
+ }
+
gint x, y;
GdkModifierType state;
bool ret = false;
@@ -275,7 +313,7 @@ SpeakerDialog::darea_button_release_event (GdkEventButton *ev)
if (Keyboard::modifier_state_contains (state, Keyboard::TertiaryModifier)) {
- for (vector<Speaker>::iterator i = speakers.speakers().begin(); i != speakers.speakers().end(); ++i) {
+ for (vector<Speaker>::iterator i = speakers->speakers().begin(); i != speakers->speakers().end(); ++i) {
/* XXX DO SOMETHING TO SET SPEAKER BACK TO "normal" */
}
@@ -309,12 +347,17 @@ SpeakerDialog::darea_button_release_event (GdkEventButton *ev)
int
SpeakerDialog::find_closest_object (gdouble x, gdouble y)
{
+ boost::shared_ptr<Speakers> speakers = _speakers.lock ();
+ if (!speakers) {
+ return -1;
+ }
+
float distance;
float best_distance = FLT_MAX;
int n = 0;
int which = -1;
- for (vector<Speaker>::iterator i = speakers.speakers().begin(); i != speakers.speakers().end(); ++i, ++n) {
+ for (vector<Speaker>::iterator i = speakers->speakers().begin(); i != speakers->speakers().end(); ++i, ++n) {
Speaker& candidate (*i);
CartesianVector c;
@@ -359,6 +402,11 @@ SpeakerDialog::darea_motion_notify_event (GdkEventMotion *ev)
bool
SpeakerDialog::handle_motion (gint evx, gint evy, GdkModifierType state)
{
+ boost::shared_ptr<Speakers> speakers = _speakers.lock ();
+ if (!speakers) {
+ return false;
+ }
+
if (drag_index < 0) {
return false;
}
@@ -382,7 +430,7 @@ SpeakerDialog::handle_motion (gint evx, gint evy, GdkModifierType state)
if (state & GDK_BUTTON1_MASK && !(state & GDK_BUTTON2_MASK)) {
CartesianVector c;
bool need_move = false;
- Speaker& moving (speakers.speakers()[drag_index]);
+ Speaker& moving (speakers->speakers()[drag_index]);
moving.angles().cartesian (c);
cart_to_gtk (c);
@@ -420,6 +468,99 @@ SpeakerDialog::handle_motion (gint evx, gint evy, GdkModifierType state)
void
SpeakerDialog::add_speaker ()
{
- speakers.add_speaker (PBD::AngularVector (0, 0, 0));
+ boost::shared_ptr<Speakers> speakers = _speakers.lock ();
+ if (!speakers) {
+ return;
+ }
+
+ speakers->add_speaker (PBD::AngularVector (0, 0, 0));
+ queue_draw ();
+}
+
+void
+SpeakerDialog::set_selected (int i)
+{
+ boost::shared_ptr<Speakers> speakers = _speakers.lock ();
+ if (!speakers) {
+ return;
+ }
+
+ if (i == selected_index) {
+ return;
+ }
+
+ selected_index = i;
+ queue_draw ();
+
+ selected_speaker_connection.disconnect ();
+
+ azimuth_spinner.set_sensitive (selected_index != -1);
+ remove_speaker_button.set_sensitive (selected_index != -1);
+
+ if (selected_index != -1) {
+ azimuth_adjustment.set_value (speakers->speakers()[selected_index].angles().azi);
+ speakers->speakers()[selected_index].PositionChanged.connect (
+ selected_speaker_connection, MISSING_INVALIDATOR,
+ boost::bind (&SpeakerDialog::speaker_position_changed, this),
+ gui_context ()
+ );
+ }
+}
+
+void
+SpeakerDialog::azimuth_changed ()
+{
+ boost::shared_ptr<Speakers> speakers = _speakers.lock ();
+ if (!speakers) {
+ return;
+ }
+
+ assert (selected_index != -1);
+
+ if (ignore_azimuth_change) {
+ return;
+ }
+
+ ignore_speaker_position_change = true;
+ speakers->move_speaker (speakers->speakers()[selected_index].id, PBD::AngularVector (azimuth_adjustment.get_value (), 0, 0));
+ ignore_speaker_position_change = false;
+
+ queue_draw ();
+}
+
+void
+SpeakerDialog::speaker_position_changed ()
+{
+ boost::shared_ptr<Speakers> speakers = _speakers.lock ();
+ if (!speakers) {
+ return;
+ }
+
+ assert (selected_index != -1);
+
+ if (ignore_speaker_position_change) {
+ return;
+ }
+
+ ignore_azimuth_change = true;
+ azimuth_adjustment.set_value (speakers->speakers()[selected_index].angles().azi);
+ ignore_azimuth_change = false;
+
+ queue_draw ();
+}
+
+void
+SpeakerDialog::remove_speaker ()
+{
+ boost::shared_ptr<Speakers> speakers = _speakers.lock ();
+ if (!speakers) {
+ return;
+ }
+
+ assert (selected_index != -1);
+
+ speakers->remove_speaker (speakers->speakers()[selected_index].id);
+ set_selected (-1);
+
queue_draw ();
}
diff --git a/gtk2_ardour/speaker_dialog.h b/gtk2_ardour/speaker_dialog.h
index 4922875f7f..62bcc277f2 100644
--- a/gtk2_ardour/speaker_dialog.h
+++ b/gtk2_ardour/speaker_dialog.h
@@ -35,11 +35,11 @@ class SpeakerDialog : public ArdourDialog
public:
SpeakerDialog ();
- ARDOUR::Speakers get_speakers() const;
+ boost::shared_ptr<ARDOUR::Speakers> get_speakers() const;
void set_speakers (boost::shared_ptr<ARDOUR::Speakers>);
private:
- ARDOUR::Speakers speakers;
+ boost::weak_ptr<ARDOUR::Speakers> _speakers;
Gtk::HBox hbox;
Gtk::VBox side_vbox;
Gtk::AspectFrame aspect_frame;
@@ -47,7 +47,7 @@ private:
Gtk::Adjustment azimuth_adjustment;
Gtk::SpinButton azimuth_spinner;
Gtk::Button add_speaker_button;
- Gtk::Button use_system_button;
+ Gtk::Button remove_speaker_button;
int32_t selected_speaker;
int width; ///< width of the circle
int height; ///< height of the circle
@@ -59,6 +59,10 @@ private:
double drag_offset_x;
double drag_offset_y;
int drag_index;
+ int selected_index; ///< index of any selected speaker, or -1
+ PBD::ScopedConnection selected_speaker_connection;
+ bool ignore_speaker_position_change;
+ bool ignore_azimuth_change;
bool darea_expose_event (GdkEventExpose*);
void darea_size_allocate (Gtk::Allocation& alloc);
@@ -73,6 +77,10 @@ private:
int find_closest_object (gdouble x, gdouble y);
void add_speaker ();
+ void remove_speaker ();
+ void azimuth_changed ();
+ void set_selected (int);
+ void speaker_position_changed ();
};
#endif /* __ardour_gtk_speaker_dialog_h__ */
diff --git a/libs/ardour/ardour/speaker.h b/libs/ardour/ardour/speaker.h
index 8bf1556936..7387a03c38 100644
--- a/libs/ardour/ardour/speaker.h
+++ b/libs/ardour/ardour/speaker.h
@@ -20,12 +20,15 @@
#define __libardour_speaker_h__
#include "pbd/cartesian.h"
+#include "pbd/signals.h"
namespace ARDOUR {
class Speaker {
public:
Speaker (int, const PBD::AngularVector& position);
+ Speaker (const Speaker &);
+ Speaker& operator= (const Speaker &);
void move (const PBD::AngularVector& new_position);
@@ -34,6 +37,9 @@ public:
int id;
+ /** emitted when this speaker's position has changed */
+ PBD::Signal0<void> PositionChanged;
+
private:
PBD::CartesianVector _coords;
PBD::AngularVector _angles;
diff --git a/libs/ardour/speakers.cc b/libs/ardour/speakers.cc
index 0120e56bfa..4bb843021c 100644
--- a/libs/ardour/speakers.cc
+++ b/libs/ardour/speakers.cc
@@ -35,11 +35,35 @@ Speaker::Speaker (int i, const AngularVector& position)
move (position);
}
+Speaker::Speaker (Speaker const & o)
+ : id (o.id)
+ , _coords (o._coords)
+ , _angles (o._angles)
+{
+
+}
+
+Speaker &
+Speaker::operator= (Speaker const & o)
+{
+ if (&o == this) {
+ return *this;
+ }
+
+ id = o.id;
+ _coords = o._coords;
+ _angles = o._angles;
+
+ return *this;
+}
+
void
Speaker::move (const AngularVector& new_position)
{
_angles = new_position;
_angles.cartesian (_coords);
+
+ PositionChanged (); /* EMIT SIGNAL */
}
Speakers::Speakers ()
@@ -100,12 +124,12 @@ Speakers::add_speaker (const AngularVector& position)
void
Speakers::remove_speaker (int id)
{
- for (vector<Speaker>::iterator i = _speakers.begin(); i != _speakers.end(); ) {
- if ((*i).id == id) {
+ for (vector<Speaker>::iterator i = _speakers.begin(); i != _speakers.end(); ++i) {
+ if (i->id == id) {
i = _speakers.erase (i);
update ();
break;
- }
+ }
}
}