1 /*
2  * Copyright (C) 2005-2014 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2005 Taybin Rutkin <taybin@taybin.com>
4  * Copyright (C) 2009-2011 Carl Hetherington <carl@carlh.net>
5  * Copyright (C) 2009-2011 David Robillard <d@drobilla.net>
6  * Copyright (C) 2014-2015 Robin Gareus <robin@gareus.org>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22 
23 #ifndef __ardour_panner_2d_h__
24 #define __ardour_panner_2d_h__
25 
26 #include <sys/types.h>
27 #include <map>
28 #include <vector>
29 
30 #include <glibmm/refptr.h>
31 #include <gtkmm/drawingarea.h>
32 #include <gtkmm/window.h>
33 #include <gtkmm/box.h>
34 #include <gtkmm/button.h>
35 #include <gtkmm/spinbutton.h>
36 #include <gtkmm/adjustment.h>
37 
38 #include "pbd/cartesian.h"
39 
40 #include "ardour_window.h"
41 
42 namespace ARDOUR {
43 	class PannerShell;
44 }
45 
46 namespace Gtk {
47 	class Menu;
48 	class CheckMenuItem;
49 }
50 
51 namespace Pango {
52 	class Container;
53 }
54 
55 class Panner2dWindow;
56 
57 class Panner2d : public Gtk::DrawingArea
58 {
59 	public:
60 	Panner2d (boost::shared_ptr<ARDOUR::PannerShell>, int32_t height);
61 	~Panner2d ();
62 
63 	void allow_target_motion (bool);
64 
65 	int  add_speaker (const PBD::AngularVector&);
66 	int  add_signal (const char* text, const PBD::AngularVector&);
67 	void move_signal (int which, const PBD::AngularVector&);
68 	void reset (uint32_t n_inputs);
69 	void set_send_drawing_mode (bool);
70 
get_panner_shell()71 	boost::shared_ptr<ARDOUR::PannerShell> get_panner_shell() const { return panner_shell; }
72 
73 	void cart_to_gtk (PBD::CartesianVector&) const;
74 	void gtk_to_cart (PBD::CartesianVector&) const;
75 
76 	protected:
77 	bool on_expose_event (GdkEventExpose *);
78 	bool on_button_press_event (GdkEventButton *);
79 	bool on_button_release_event (GdkEventButton *);
80 	bool on_motion_notify_event (GdkEventMotion *);
81 	bool on_scroll_event (GdkEventScroll *);
82 	void on_size_allocate (Gtk::Allocation& alloc);
83 
84 	private:
85 	class Target {
86 		public:
87 		PBD::AngularVector position;
88 		bool visible;
89 		std::string text;
90 
91 		Target (const PBD::AngularVector&, const char* txt = 0);
92 		~Target ();
93 
94 		void set_text (const char*);
set_selected(bool yn)95 		void set_selected (bool yn) {
96 			_selected = yn;
97 		}
selected()98 		bool selected() const {
99 			return _selected;
100 		}
101 
102 		private:
103 		bool _selected;
104 	};
105 
106 	struct ColorScheme {
107 		uint32_t background;
108 		uint32_t crosshairs;
109 		uint32_t signalcircle_border;
110 		uint32_t signalcircle;
111 		uint32_t diffusion;
112 		uint32_t diffusion_inv;
113 		uint32_t pos_outline;
114 		uint32_t pos_fill;
115 		uint32_t signal_outline;
116 		uint32_t signal_fill;
117 		uint32_t speaker_fill;
118 		uint32_t text;
119 		uint32_t send_bg;
120 		uint32_t send_pan;
121 	};
122 
123 	static ColorScheme colors;
124 	static void set_colors ();
125 	static bool have_colors;
126 	void color_handler ();
127 
128 	boost::shared_ptr<ARDOUR::PannerShell> panner_shell;
129 	Glib::RefPtr<Pango::Layout> layout;
130 
131 	typedef std::vector<Target*> Targets;
132 	Targets speakers;
133 	Targets signals;
134 	Target  position;
135 
136 	Target *drag_target;
137 	int     width;
138 	int     height;
139 	double  radius;
140 	double  border;
141 	double  hoffset;
142 	double  voffset;
143 	double  last_width;
144 	bool    did_move;
145 	bool    have_elevation;
146 	bool    _send_mode;
147 
148 	Target *find_closest_object (gdouble x, gdouble y, bool& is_signal);
149 
150 	gint handle_motion (gint, gint, GdkModifierType);
151 
152 	void toggle_bypass ();
153 	void handle_state_change ();
154 	void handle_position_change ();
155 	void label_signals ();
156 
157 	PBD::ScopedConnectionList panshell_connections;
158 	PBD::ScopedConnectionList panner_connections;
159 
160 	/* cartesian coordinates in GTK units ; adjust to same but on a circle of radius 1.0
161 	   and centered in the middle of our area
162 	*/
163 	void clamp_to_circle (double& x, double& y);
164 	void sphere_project (double& x, double& y, double& z);
165 };
166 
167 class Panner2dWindow : public ArdourWindow
168 {
169 	public:
170 	Panner2dWindow (boost::shared_ptr<ARDOUR::PannerShell>, int32_t height, uint32_t inputs);
171 
172 	void reset (uint32_t n_inputs);
173 
174 	private:
175 	Panner2d widget;
176 
177 	Gtk::HBox         hpacker;
178 	Gtk::VBox         button_box;
179 	Gtk::ToggleButton bypass_button;
180 	Gtk::VBox         spinner_box;
181 	Gtk::VBox         left_side;
182 
183 	Gtk::Adjustment   width_adjustment;
184 	Gtk::SpinButton   width_spinner;
185 
186 	PBD::ScopedConnectionList panshell_connections;
187 	PBD::ScopedConnectionList panvalue_connections;
188 	void set_bypassed();
189 	void set_width();
190 
191 	void pannable_handler ();
192 	void bypass_toggled ();
193 	void width_changed ();
194 	bool on_key_press_event (GdkEventKey*);
195 	bool on_key_release_event (GdkEventKey*);
196 };
197 
198 #endif /* __ardour_panner_2d_h__ */
199