a variety of changes to finalize (?) (MIDI) SceneChange functionality
[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 (int c, int b, int p)
32         : _bank (b)
33         , _program (p)
34         , _channel (c & 0xf)
35 {
36         if (_bank > 16384) {
37                 _bank = -1;
38         }
39
40         if (_program > 128) {
41                 _program = -1;
42         }
43 }
44
45 MIDISceneChange::MIDISceneChange (const XMLNode& node, int version)
46         : _bank (-1)
47         , _program (-1)
48         , _channel (-1)
49 {
50         set_state (node, version);
51 }
52
53 MIDISceneChange::~MIDISceneChange ()
54 {
55 }
56
57 size_t
58 MIDISceneChange::get_bank_msb_message (uint8_t* buf, size_t size) const
59 {
60         if (size < 3 || _bank < 0) {
61                 return 0;
62         }
63
64         buf[0] = 0xB0 | (_channel & 0xf);
65         buf[1] = 0x0;
66         buf[2] = (_bank >> 7) & 0x7f;
67
68         return 3;
69 }
70
71 size_t
72 MIDISceneChange::get_bank_lsb_message (uint8_t* buf, size_t size) const
73 {
74         if (size < 3 || _bank < 0) {
75                 return 0;
76         }
77
78         buf[0] = 0xB0 | (_channel & 0xf);
79         buf[1] = 0x20;
80         buf[2] = _bank & 0x7f;  
81
82         return 3;
83 }
84
85 size_t
86 MIDISceneChange::get_program_message (uint8_t* buf, size_t size) const
87 {
88         if (size < 2 || _program < 0) {
89                 return 0;
90         }
91
92         buf[0] = 0xC0 | (_channel & 0xf);
93         buf[1] = _program & 0x7f;
94
95         return 2;
96 }
97
98 XMLNode&
99 MIDISceneChange::get_state ()
100 {
101         char buf[32];
102         XMLNode* node = new XMLNode (SceneChange::xml_node_name);
103
104         node->add_property (X_("type"), X_("MIDI"));
105         snprintf (buf, sizeof (buf), "%d", (int) _program);
106         node->add_property (X_("id"), id().to_s());
107         snprintf (buf, sizeof (buf), "%d", (int) _program);
108         node->add_property (X_("program"), buf);
109         snprintf (buf, sizeof (buf), "%d", (int) _bank);
110         node->add_property (X_("bank"), buf);
111         snprintf (buf, sizeof (buf), "%d", (int) _channel);
112         node->add_property (X_("channel"), buf);
113
114         return *node;
115 }
116
117 int
118 MIDISceneChange::set_state (const XMLNode& node, int /* version-ignored */)
119 {
120         if (!set_id (node)) {
121                 return -1;
122         }
123
124         const XMLProperty* prop;
125
126         if ((prop = node.property (X_("program"))) == 0) {
127                 return -1;
128         }
129         _program = atoi (prop->value());
130
131         if ((prop = node.property (X_("bank"))) == 0) {
132                 return -1;
133         }
134         _bank = atoi (prop->value());
135
136         if ((prop = node.property (X_("channel"))) == 0) {
137                 return -1;
138         }
139         _channel = atoi (prop->value());
140
141         return 0;
142 }