Ardour  9.0-pre0-582-g084a23a80d
PatchChange.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2011 Carl Hetherington <carl@carlh.net>
3  * Copyright (C) 2011-2013 Paul Davis <paul@linuxaudiosystems.com>
4  * Copyright (C) 2011-2016 David Robillard <d@drobilla.net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #ifndef EVORAL_PATCH_CHANGE_HPP
22 #define EVORAL_PATCH_CHANGE_HPP
23 
24 #include <cassert>
25 
26 #include "evoral/visibility.h"
27 #include "evoral/Event.h"
28 #include "evoral/Event.h"
29 
30 namespace Evoral {
31 
35 template<typename Time>
36 class /*LIBEVORAL_API*/ PatchChange
37 {
38 public:
44  PatchChange (Time t, uint8_t c, uint8_t p, int b)
45  : _bank_change_msb (MIDI_EVENT, t, 3, 0, true)
46  , _bank_change_lsb (MIDI_EVENT, t, 3, 0, true)
47  , _program_change (MIDI_EVENT, t, 2, 0, true)
48  {
49  _bank_change_msb.buffer()[0] = MIDI_CMD_CONTROL | c;
50  _bank_change_msb.buffer()[1] = MIDI_CTL_MSB_BANK;
51  _bank_change_msb.buffer()[2] = (b >> 7) & 0x7f;
52 
53  _bank_change_lsb.buffer()[0] = MIDI_CMD_CONTROL | c;
54  _bank_change_lsb.buffer()[1] = MIDI_CTL_LSB_BANK;
55  _bank_change_lsb.buffer()[2] = b & 0x7f;
56 
57  _program_change.buffer()[0] = MIDI_CMD_PGM_CHANGE | c;
58  _program_change.buffer()[1] = p;
59 
60  assert (is_set());
61  }
62 
63  PatchChange (const PatchChange & other)
64  : _bank_change_msb (other._bank_change_msb, true)
65  , _bank_change_lsb (other._bank_change_lsb, true)
66  , _program_change (other._program_change, true)
67  {
68  set_id (other.id ());
69 
70  assert (is_set());
71  }
72 
74  : _bank_change_msb (MIDI_EVENT, 0, 3, 0, true)
75  , _bank_change_lsb (MIDI_EVENT, 0, 3, 0, true)
76  , _program_change (MIDI_EVENT, 0, 2, 0, true)
77  {
78  _bank_change_msb.buffer()[0] = MIDI_CMD_CONTROL;
79  _bank_change_msb.buffer()[1] = MIDI_CTL_MSB_BANK;
80  _bank_change_msb.buffer()[2] = 0;
81 
82  _bank_change_lsb.buffer()[0] = MIDI_CMD_CONTROL;
83  _bank_change_lsb.buffer()[1] = MIDI_CTL_LSB_BANK;
84  _bank_change_lsb.buffer()[2] = 0;
85 
87  _program_change.buffer()[1] = 0;
88 
89  unset ();
90  }
91 
93  /* Need to be careful with assignment here, due to buffer
94  ownership issues etc.
95  */
96  _bank_change_msb.set (other._bank_change_msb.buffer(), 3, other.time());
97  _bank_change_lsb.set (other._bank_change_lsb.buffer(), 3, other.time());
98  _program_change.set (other._program_change.buffer(), 2, other.time());
99 
100  assert (is_set());
101  return *this;
102  }
103  void unset() {
104  _bank_change_msb.buffer()[2] = 0x80; /* unset */
105  _bank_change_lsb.buffer()[2] = 0x80; /* unset */
106  _program_change.buffer()[1] = 0x80; /* unset */
107  assert (!is_set());
108  }
109 
110  bool is_set() const {
111  return ((_bank_change_msb.buffer()[2] & 0x80) == 0) &&
112  ((_bank_change_lsb.buffer()[2] & 0x80) == 0) &&
113  ((_program_change.buffer()[1] & 0x80) == 0);
114  }
115 
116  event_id_t id () const {
117  return _program_change.id ();
118  }
119 
120  void set_id (event_id_t id) {
121  _bank_change_msb.set_id (id);
122  _bank_change_lsb.set_id (id);
123  _program_change.set_id (id);
124  }
125 
126  Time time () const {
127  return _program_change.time ();
128  }
129 
130  void set_time (Time t) {
131  _bank_change_msb.set_time (t);
132  _bank_change_lsb.set_time (t);
133  _program_change.set_time (t);
134  }
135 
136  void set_channel (uint8_t c) {
137  _bank_change_msb.buffer()[0] = MIDI_CMD_CONTROL | c;
138  _bank_change_lsb.buffer()[0] = MIDI_CMD_CONTROL | c;
139  _program_change.buffer()[0] = MIDI_CMD_PGM_CHANGE | c;
140  }
141 
142  uint8_t program () const {
143  assert (is_set());
144  return _program_change.buffer()[1] & 0x7f;
145  }
146 
147  void set_program (uint8_t p) {
148  _program_change.buffer()[1] = p & 0x7f;
149  }
150 
151  int bank () const {
152  assert (is_set());
153  return (bank_msb() << 7) | bank_lsb();
154  }
155 
156  void set_bank (int b) {
157  _bank_change_msb.buffer()[2] = (b >> 7) & 0x7f;
158  _bank_change_lsb.buffer()[2] = b & 0x7f;
159  }
160 
161  uint8_t bank_msb () const {
162  assert (is_set());
163  return _bank_change_msb.buffer()[2];
164  }
165 
166  uint8_t bank_lsb () const {
167  assert (is_set());
168  return _bank_change_lsb.buffer()[2];
169  }
170 
171  uint8_t channel () const {
172  assert (is_set());
173  return _program_change.buffer()[0] & 0xf;
174  }
175 
176  inline bool operator< (const PatchChange<Time>& o) const {
177  assert (is_set());
178  if (time() != o.time()) {
179  return time() < o.time();
180  }
181 
182  if (bank() != o.bank()) {
183  return bank() < o.bank();
184  }
185 
186  return (program() < o.program());
187  }
188 
189  inline bool operator== (const PatchChange<Time>& o) const {
190  return (time() == o.time() && program() == o.program() && bank() == o.bank());
191  }
192 
196  Event<Time> const & message (int i) const {
197  assert (is_set());
198  switch (i) {
199  case 0:
200  return _bank_change_msb;
201  case 1:
202  return _bank_change_lsb;
203  case 2:
204  return _program_change;
205  default:
206  abort(); /*NOTREACHED*/
207  return _program_change;
208  }
209  }
210 
212  int messages () const {
213  return 3;
214  }
215 
216 private:
220 };
221 
222 }
223 
224 template<typename Time>
225 /*LIBEVORAL_API*/ std::ostream& operator<< (std::ostream& o, const Evoral::PatchChange<Time>& p) {
226  o << "Patch Change " << p.id() << " @ " << p.time() << " bank " << (int) p.bank() << " program " << (int) p.program();
227  return o;
228 }
229 
230 #endif
std::ostream & operator<<(std::ostream &o, const Evoral::PatchChange< Time > &p)
Definition: PatchChange.h:225
int messages() const
Definition: PatchChange.h:212
void set_program(uint8_t p)
Definition: PatchChange.h:147
Event< Time > _bank_change_msb
Definition: PatchChange.h:217
Event< Time > _program_change
Definition: PatchChange.h:219
void set_bank(int b)
Definition: PatchChange.h:156
int bank() const
Definition: PatchChange.h:151
Event< Time > const & message(int i) const
Definition: PatchChange.h:196
bool is_set() const
Definition: PatchChange.h:110
void set_time(Time t)
Definition: PatchChange.h:130
PatchChange(const PatchChange &other)
Definition: PatchChange.h:63
void set_channel(uint8_t c)
Definition: PatchChange.h:136
Event< Time > _bank_change_lsb
Definition: PatchChange.h:218
uint8_t program() const
Definition: PatchChange.h:142
PatchChange(Time t, uint8_t c, uint8_t p, int b)
Definition: PatchChange.h:44
uint8_t channel() const
Definition: PatchChange.h:171
uint8_t bank_msb() const
Definition: PatchChange.h:161
bool operator==(const PatchChange< Time > &o) const
Definition: PatchChange.h:189
bool operator<(const PatchChange< Time > &o) const
Definition: PatchChange.h:176
uint8_t bank_lsb() const
Definition: PatchChange.h:166
event_id_t id() const
Definition: PatchChange.h:116
PatchChange & operator=(PatchChange const &other)
Definition: PatchChange.h:92
Time time() const
Definition: PatchChange.h:126
void set_id(event_id_t id)
Definition: PatchChange.h:120
#define MIDI_CTL_MSB_BANK
Definition: midi_events.h:32
#define MIDI_CTL_LSB_BANK
Definition: midi_events.h:48
#define MIDI_CMD_PGM_CHANGE
Definition: midi_events.h:110
#define MIDI_CMD_CONTROL
Definition: midi_events.h:109
Definition: editor.h:86
int32_t event_id_t