1 /*
2  * Copyright (C) 2006-2018 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2007-2016 Tim Mayberry <mojofunk@gmail.com>
4  * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
5  * Copyright (C) 2009 David Robillard <d@drobilla.net>
6  * Copyright (C) 2015-2019 Robin Gareus <robin@gareus.org>
7  * Copyright (C) 2015 Len Ovens <len@ovenwerks.net>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 #ifndef __gm_midicontrollable_h__
25 #define __gm_midicontrollable_h__
26 
27 #include <string>
28 
29 #include "midi++/types.h"
30 
31 #include "pbd/controllable.h"
32 #include "pbd/signals.h"
33 #include "pbd/stateful.h"
34 
35 #include "ardour/types.h"
36 
37 namespace MIDI {
38 	class Channel;
39 	class Parser;
40 }
41 
42 class GenericMidiControlProtocol;
43 
44 namespace ARDOUR {
45 	class AsyncMIDIPort;
46 }
47 
48 class MIDIControllable : public PBD::Stateful
49 {
50 public:
51 	MIDIControllable (GenericMidiControlProtocol*, MIDI::Parser&, boost::shared_ptr<PBD::Controllable>, bool momentary);
52 	MIDIControllable (GenericMidiControlProtocol*, MIDI::Parser&, bool momentary = false);
53 	virtual ~MIDIControllable ();
54 
55 	int init (const std::string&);
56 
57 	void rediscover_controllable ();
bank_relative()58 	bool bank_relative() const { return _bank_relative; }
rid()59 	uint32_t rid() const { return _rid; }
what()60 	std::string what() const { return _what; }
61 
62 	enum CtlType {
63 		Ctl_Momentary,
64 		Ctl_Toggle,
65 		Ctl_Dial,
66 	};
67 
68 	enum Encoder {
69 		No_enc,
70 		Enc_R,
71 		Enc_L,
72 		Enc_2,
73 		Enc_B,
74 	};
75 
76 	MIDI::byte* write_feedback (MIDI::byte* buf, int32_t& bufsize, bool force = false);
77 
78 	void midi_rebind (MIDI::channel_t channel=-1);
79 	void midi_forget ();
80 	void learn_about_external_control ();
81 	void stop_learning ();
82 	void drop_external_control ();
83 
84 	int control_to_midi(float val);
85 	float midi_to_control(int val);
86 
learned()87 	bool learned() const { return _learned; }
88 
get_ctltype()89 	CtlType get_ctltype() const { return _ctltype; }
set_ctltype(CtlType val)90 	void set_ctltype (CtlType val) { _ctltype = val; }
91 
get_encoder()92 	Encoder get_encoder() const { return _encoder; }
set_encoder(Encoder val)93 	void set_encoder (Encoder val) { _encoder = val; }
94 
get_parser()95 	MIDI::Parser& get_parser() { return _parser; }
96 	void set_controllable (boost::shared_ptr<PBD::Controllable>);
97 	boost::shared_ptr<PBD::Controllable> get_controllable () const;
current_uri()98 	const std::string& current_uri() const { return _current_uri; }
99 
control_description()100 	std::string control_description() const { return _control_description; }
101 
102 	XMLNode& get_state (void);
103 	int set_state (const XMLNode&, int version);
104 
105 	void bind_midi (MIDI::channel_t, MIDI::eventType, MIDI::byte);
106 	void bind_rpn_value (MIDI::channel_t, uint16_t rpn);
107 	void bind_nrpn_value (MIDI::channel_t, uint16_t rpn);
108 	void bind_rpn_change (MIDI::channel_t, uint16_t rpn);
109 	void bind_nrpn_change (MIDI::channel_t, uint16_t rpn);
110 
get_control_channel()111 	MIDI::channel_t get_control_channel () { return control_channel; }
get_control_type()112 	MIDI::eventType get_control_type () { return control_type; }
get_control_additional()113 	MIDI::byte get_control_additional () { return control_additional; }
114 
115 	int lookup_controllable();
116 
117 private:
118 
119 	int max_value_for_type () const;
120 
121 	GenericMidiControlProtocol* _surface;
122 	boost::shared_ptr<PBD::Controllable> _controllable;
123 	std::string     _current_uri;
124 	MIDI::Parser&   _parser;
125 	bool             setting;
126 	int              last_value;
127 	int              last_incoming;
128 	float            last_controllable_value;
129 	bool            _momentary;
130 	bool            _is_gain_controller;
131 	bool            _learned;
132 	CtlType         _ctltype;
133 	Encoder			_encoder;
134 	int              midi_msg_id;      /* controller ID or note number */
135 	PBD::ScopedConnection midi_sense_connection[2];
136 	PBD::ScopedConnection midi_learn_connection;
137 	PBD::ScopedConnection controllable_death_connection;
138 	/** the type of MIDI message that is used for this control */
139 	MIDI::eventType  control_type;
140 	MIDI::byte       control_additional;
141 	MIDI::channel_t  control_channel;
142 	std::string     _control_description;
143 	int16_t          control_rpn;
144 	int16_t          control_nrpn;
145 	uint32_t        _rid;
146 	std::string     _what;
147 	bool            _bank_relative;
148 
149 	void drop_controllable ();
150 	Glib::Threads::Mutex controllable_lock;
151 
152 	void midi_receiver (MIDI::Parser &p, MIDI::byte *, size_t);
153 	void midi_sense_note (MIDI::Parser &, MIDI::EventTwoBytes *, bool is_on);
154 	void midi_sense_note_on (MIDI::Parser &p, MIDI::EventTwoBytes *tb);
155 	void midi_sense_note_off (MIDI::Parser &p, MIDI::EventTwoBytes *tb);
156 	void midi_sense_controller (MIDI::Parser &, MIDI::EventTwoBytes *);
157 	void midi_sense_program_change (MIDI::Parser &, MIDI::byte);
158 	void midi_sense_pitchbend (MIDI::Parser &, MIDI::pitchbend_t);
159 
160 	void nrpn_value_change (MIDI::Parser&, uint16_t nrpn, float val);
161 	void rpn_value_change (MIDI::Parser&, uint16_t nrpn, float val);
162 	void rpn_change (MIDI::Parser&, uint16_t nrpn, int direction);
163 	void nrpn_change (MIDI::Parser&, uint16_t nrpn, int direction);
164 };
165 
166 #endif // __gm_midicontrollable_h__
167