merge (squash) with scenechange topic branch to provide MIDI-driven scene change...
[ardour.git] / libs / ardour / midi_scene_change.cc
1 /*
2     Copyright (C) 2014 Paul Davis
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
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include "pbd/error.h"
21 #include "pbd/compose.h"
22
23 #include "ardour/midi_port.h"
24 #include "ardour/midi_scene_change.h"
25
26 #include "i18n.h"
27
28 using namespace PBD;
29 using namespace ARDOUR;
30
31 MIDISceneChange::MIDISceneChange (framepos_t time, int c, int b, int p)
32         : SceneChange (time)
33         , _bank (b)
34         , _program (p)
35         , _channel (c & 0xf)
36 {
37         if (_bank > 16384) {
38                 _bank = -1;
39         }
40
41         if (_program > 128) {
42                 _program = -1;
43         }
44 }
45
46 MIDISceneChange::MIDISceneChange (const XMLNode& node, int version)
47         : SceneChange (0)
48         , _bank (-1)
49         , _program (-1)
50         , _channel (-1)
51 {
52         set_state (node, version);
53 }
54
55 MIDISceneChange::~MIDISceneChange ()
56 {
57 }
58
59 size_t
60 MIDISceneChange::get_bank_msb_message (uint8_t* buf, size_t size) const
61 {
62         if (size < 3 || _bank < 0) {
63                 return 0;
64         }
65
66         buf[0] = 0xB0 | (_channel & 0xf);
67         buf[1] = 0x0;
68         buf[2] = (_bank & 0xf700) >> 8;
69
70         return 3;
71 }
72
73 size_t
74 MIDISceneChange::get_bank_lsb_message (uint8_t* buf, size_t size) const
75 {
76         if (size < 3 || _bank < 0) {
77                 return 0;
78         }
79
80         buf[0] = 0xB0 | (_channel & 0xf);
81         buf[1] = 0x20;
82         buf[2] = (_bank & 0xf7);        
83
84         return 3;
85 }
86
87 size_t
88 MIDISceneChange::get_program_message (uint8_t* buf, size_t size) const
89 {
90         if (size < 2 || _program < 0) {
91                 return 0;
92         }
93
94         buf[0] = 0xC0 | (_channel & 0xf);
95         buf[1] = _program & 0xf7;
96
97         return 2;
98 }
99
100 XMLNode&
101 MIDISceneChange::get_state ()
102 {
103         char buf[32];
104         XMLNode* node = new XMLNode (SceneChange::xml_node_name);
105
106         node->add_property (X_("type"), X_("MIDI"));
107         snprintf (buf, sizeof (buf), "%d", (int) _program);
108         node->add_property (X_("id"), id().to_s());
109         snprintf (buf, sizeof (buf), "%d", (int) _program);
110         node->add_property (X_("program"), buf);
111         snprintf (buf, sizeof (buf), "%d", (int) _bank);
112         node->add_property (X_("bank"), buf);
113         snprintf (buf, sizeof (buf), "%d", (int) _channel);
114         node->add_property (X_("channel"), buf);
115
116         return *node;
117 }
118
119 int
120 MIDISceneChange::set_state (const XMLNode& node, int /* version-ignored */)
121 {
122         if (!set_id (node)) {
123                 return -1;
124         }
125
126         const XMLProperty* prop;
127
128         if ((prop = node.property (X_("program"))) == 0) {
129                 return -1;
130         }
131         _program = atoi (prop->value());
132
133         if ((prop = node.property (X_("bank"))) == 0) {
134                 return -1;
135         }
136         _bank = atoi (prop->value());
137
138         if ((prop = node.property (X_("channel"))) == 0) {
139                 return -1;
140         }
141         _channel = atoi (prop->value());
142
143         return 0;
144 }