1 /*
2  * Copyright (C) 2017 Ben Loftis <ben@harrisonconsoles.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #ifndef us2400_surface_h
20 #define us2400_surface_h
21 
22 #include <stdint.h>
23 
24 #include <sigc++/trackable.h>
25 
26 #include "pbd/signals.h"
27 #include "pbd/xml++.h"
28 #include "midi++/types.h"
29 
30 #include "ardour/types.h"
31 
32 #include "control_protocol/types.h"
33 
34 #include "controls.h"
35 #include "types.h"
36 #include "jog_wheel.h"
37 
38 namespace MIDI {
39 	class Parser;
40 }
41 
42 namespace ARDOUR {
43 	class Stripable;
44 	class Port;
45 }
46 
47 class MidiByteArray;
48 
49 namespace ArdourSurface {
50 
51 class US2400Protocol;
52 
53 namespace US2400
54 {
55 
56 class MackieButtonHandler;
57 class SurfacePort;
58 class MackieMidiBuilder;
59 class Button;
60 class Meter;
61 class Fader;
62 class Jog;
63 class Pot;
64 class Led;
65 
66 class Surface : public PBD::ScopedConnectionList, public sigc::trackable
67 {
68 public:
69 	Surface (US2400Protocol&, const std::string& name, uint32_t number, surface_type_t stype);
70 	virtual ~Surface();
71 
type()72 	surface_type_t type() const { return _stype; }
number()73 	uint32_t number() const { return _number; }
name()74 	const std::string& name() { return _name; }
75 
76 	void connected ();
77 
active()78 	bool active() const { return _active; }
79 
80 	typedef std::vector<Control*> Controls;
81 	Controls controls;
82 
83 	std::map<int,Fader*> faders;
84 	std::map<int,Pot*> pots;
85 	std::map<int,Button*> buttons; // index is device-DEPENDENT
86 	std::map<int,Led*> leds;
87 	std::map<int,Meter*> meters;
88 	std::map<int,Control*> controls_by_device_independent_id;
89 
jog_wheel()90 	US2400::JogWheel* jog_wheel() const { return _jog_wheel; }
master_fader()91 	Fader* master_fader() const { return _master_fader; }
92 
93 	/// The collection of all numbered strips.
94 	typedef std::vector<Strip*> Strips;
95 	Strips strips;
96 
97 	uint32_t n_strips (bool with_locked_strips = true) const;
98 	Strip* nth_strip (uint32_t n) const;
99 
100 	bool stripable_is_locked_to_strip (boost::shared_ptr<ARDOUR::Stripable>) const;
101 	bool stripable_is_mapped (boost::shared_ptr<ARDOUR::Stripable>) const;
102 
103 	/// This collection owns the groups
104 	typedef std::map<std::string,Group*> Groups;
105 	Groups groups;
106 
port()107 	SurfacePort& port() const { return *_port; }
108 
109 	void map_stripables (const std::vector<boost::shared_ptr<ARDOUR::Stripable> >&);
110 
111 	void update_strip_selection ();
112 
113 	const MidiByteArray& sysex_hdr() const;
114 
115 	void periodic (PBD::microseconds_t now_usecs);
116 	void redisplay (PBD::microseconds_t now_usecs, bool force);
117 	void hui_heartbeat ();
118 
119 	void handle_midi_pitchbend_message (MIDI::Parser&, MIDI::pitchbend_t, uint32_t channel_id);
120 	void handle_midi_controller_message (MIDI::Parser&, MIDI::EventTwoBytes*);
121 	void handle_midi_note_on_message (MIDI::Parser&, MIDI::EventTwoBytes*);
122 
123 	/// Connect the any signal from the parser to handle_midi_any
124 	/// unless it's already connected
125 	void connect_to_signals ();
126 
127 	/// write a sysex message
128 	void write_sysex (const MidiByteArray& mba);
129 	void write_sysex (MIDI::byte msg);
130 	/// proxy write for port
131 	void write (const MidiByteArray&);
132 
133 	/// display an indicator of the first switched-in Route. Do nothing by default.
134 	void display_bank_start (uint32_t /*current_bank*/);
135 
136 	/// called from US2400Protocol::zero_all to turn things off
137 	void zero_all ();
138 	void zero_controls ();
139 
140 	/// turn off leds around the jog wheel. This is for surfaces that use a pot
141 	/// pretending to be a jog wheel.
142 	void blank_jog_ring ();
143 
144 	/// sends MCP "reset" message to surface
145 	void reset ();
146 
147 	void recalibrate_faders ();
148 	void toggle_backlight ();
149 	void set_touch_sensitivity (int);
150 
151 	/**
152 		This is used to calculate the clicks per second that define
153 		a transport speed of 1.0 for the jog wheel. 100.0 is 10 clicks
154 		per second, 50.5 is 5 clicks per second.
155 	*/
156 	float scrub_scaling_factor() const;
157 
158 	/**
159 		The scaling factor function for speed increase and decrease. At
160 		low transport speeds this should return a small value, for high transport
161 		speeds, this should return an exponentially larger value. This provides
162 		high definition control at low speeds and quick speed changes to/from
163 		higher speeds.
164 	*/
165 	float scaled_delta (float delta, float current_speed);
166 
167 	void subview_mode_changed ();
168 
mcp()169 	US2400Protocol& mcp() const { return _mcp; }
170 
171 	void next_jog_mode ();
172 	void set_jog_mode (US2400::JogWheel::Mode);
173 
174         void notify_metering_state_changed();
175 	void turn_it_on ();
176 
177 	bool connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool);
178 
179 	void master_monitor_may_have_changed ();
180 
181 	XMLNode& get_state ();
182 	int set_state (const XMLNode&, int version);
183 
184   private:
185 	US2400Protocol& _mcp;
186 	SurfacePort*           _port;
187 	surface_type_t         _stype;
188 	uint32_t               _number;
189 	std::string            _name;
190 	bool                   _active;
191 	bool                   _connected;
192 	US2400::JogWheel*      _jog_wheel;
193 	Fader*                 _master_fader;
194 	float                  _last_master_gain_written;
195 	PBD::ScopedConnection   master_connection;
196 	bool                   _joystick_active;
197 
198 	void handle_midi_sysex (MIDI::Parser&, MIDI::byte *, size_t count);
199 	MidiByteArray host_connection_query (MidiByteArray& bytes);
200 	MidiByteArray host_connection_confirmation (const MidiByteArray& bytes);
201 
202 	void say_hello ();
203 	void init_controls ();
204 	void init_strips (uint32_t n);
205 	void setup_master ();
206 	void master_gain_changed ();
207 
208 	enum ConnectionState {
209 		InputConnected = 0x1,
210 		OutputConnected = 0x2
211 	};
212 
213 	int connection_state;
214 
215   public:
216 	/* IP MIDI devices need to keep a handle on this and destroy it */
217 	GSource*    input_source;
218 };
219 
220 }
221 }
222 
223 #endif
224