Fix sigc building.
[ardour.git] / libs / midi++2 / midimanager.cc
1 /*
2     Copyright (C) 1998-99 Paul Barton-Davis 
3     This program is free software; you can redistribute it and/or modify
4     it under the terms of the GNU General Public License as published by
5     the Free Software Foundation; either version 2 of the License, or
6     (at your option) any later version.
7
8     This program is distributed in the hope that it will be useful,
9     but WITHOUT ANY WARRANTY; without even the implied warranty of
10     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11     GNU General Public License for more details.
12
13     You should have received a copy of the GNU General Public License
14     along with this program; if not, write to the Free Software
15     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16
17     $Id$
18 */
19
20 #include <fcntl.h>
21
22 #include <glib.h>
23
24 #include <pbd/error.h>
25
26 #include <midi++/types.h>
27 #include <midi++/manager.h>
28 #include <midi++/factory.h>
29 #include <midi++/channel.h>
30
31 using namespace std;
32 using namespace MIDI;
33 using namespace PBD;
34
35 /* XXX check for strdup leaks */
36
37 Manager *Manager::theManager = 0;
38
39 Manager::Manager () 
40 {
41         inputPort = 0;
42         outputPort = 0;
43         inputChannelNumber = 0;
44         outputChannelNumber = 0;
45         api_data = 0;
46 }
47
48 Manager::~Manager ()
49 {
50         PortMap::iterator i;
51
52         for (i = ports_by_device.begin(); i != ports_by_device.end(); i++) {
53                 delete (*i).second;
54         }
55
56         ports_by_device.erase (ports_by_device.begin(), ports_by_device.end());
57         ports_by_tag.erase (ports_by_tag.begin(), ports_by_tag.end());
58
59         if (theManager == this) {
60                 theManager = 0;
61         }
62 }
63
64 Port *
65 Manager::add_port (const XMLNode& node)
66 {
67         Port::Descriptor desc (node);
68         PortFactory factory;
69         Port *port;
70         PortMap::iterator existing;
71         pair<string, Port *> newpair;
72
73         if (!PortFactory::ignore_duplicate_devices (desc.type)) {
74
75                 if ((existing = ports_by_device.find (desc.device)) != ports_by_device.end()) {
76                         
77                         port = (*existing).second;
78                         
79                         if (port->mode() == desc.mode) {
80                                 
81                                 /* Same mode - reuse the port, and just
82                                    create a new tag entry.
83                                 */
84                                 
85                                 newpair.first = desc.tag;
86                                 newpair.second = port;
87                                 
88                                 ports_by_tag.insert (newpair);
89                                 return port;
90                         }
91                         
92                         /* If the existing is duplex, and this request
93                            is not, then fail, because most drivers won't
94                            allow opening twice with duplex and non-duplex
95                            operation.
96                         */
97                         
98                         if ((desc.mode == O_RDWR && port->mode() != O_RDWR) ||
99                             (desc.mode != O_RDWR && port->mode() == O_RDWR)) {
100                                 error << "MIDIManager: port tagged \""
101                                       << desc.tag
102                                       << "\" cannot be opened duplex and non-duplex"
103                                       << endmsg;
104                                 return 0;
105                         }
106                         
107                         /* modes must be different or complementary */
108                 }
109         }
110         
111         port = factory.create_port (node, api_data);
112         
113         if (port == 0) {
114                 return 0;
115         }
116
117         if (!port->ok()) {
118                 delete port;
119                 return 0;
120         }
121
122         newpair.first = port->name();
123         newpair.second = port;
124         ports_by_tag.insert (newpair);
125
126         newpair.first = port->device();
127         newpair.second = port;
128         ports_by_device.insert (newpair);
129
130         /* first port added becomes the default input
131            port.
132         */
133
134         if (inputPort == 0) {
135                 inputPort = port;
136         } 
137
138         if (outputPort == 0) {
139                 outputPort = port;
140         }
141
142         return port;
143 }
144
145 int 
146 Manager::remove_port (Port* port)
147 {
148         PortMap::iterator res;
149
150         for (res = ports_by_device.begin(); res != ports_by_device.end(); ) {
151                 PortMap::iterator tmp;
152                 tmp = res;
153                 ++tmp;
154                 if (res->second == port) {
155                         ports_by_device.erase (res);
156                 } 
157                 res = tmp;
158         }
159
160
161         for (res = ports_by_tag.begin(); res != ports_by_tag.end(); ) {
162                 PortMap::iterator tmp;
163                 tmp = res;
164                 ++tmp;
165                 if (res->second == port) {
166                         ports_by_tag.erase (res);
167                 } 
168                 res = tmp;
169         }
170         
171         delete port;
172
173         return 0;
174 }
175
176 int
177 Manager::set_input_port (string tag)
178 {
179         PortMap::iterator res;
180         bool found = false;
181
182         for (res = ports_by_tag.begin(); res != ports_by_tag.end(); res++) {
183                 if (tag == (*res).first) {
184                         found = true;
185                         break;
186                 }
187         }
188         
189         if (!found) {
190                 return -1;
191         }
192
193         inputPort = (*res).second;
194
195         return 0;
196 }
197
198 int
199 Manager::set_output_port (string tag)
200
201 {
202         PortMap::iterator res;
203         bool found = false;
204
205         for (res = ports_by_tag.begin(); res != ports_by_tag.end(); res++) {
206                 if (tag == (*res).first) {
207                         found = true;
208                         break;
209                 }
210         }
211         
212         if (!found) {
213                 return -1;
214         }
215
216         // XXX send a signal to say we're about to change output ports
217
218         if (outputPort) {
219                 for (channel_t chan = 0; chan < 16; chan++) {
220                         outputPort->channel (chan)->all_notes_off (0);
221                 }
222         }
223         outputPort = (*res).second;
224
225         // XXX send a signal to say we've changed output ports
226
227         return 0;
228 }
229
230 Port *
231 Manager::port (string name)
232 {
233         PortMap::iterator res;
234
235         for (res = ports_by_tag.begin(); res != ports_by_tag.end(); res++) {
236                 if (name == (*res).first) {
237                         return (*res).second;
238                 }
239         }
240
241         return 0;
242 }
243
244 int
245 Manager::foreach_port (int (*func)(const Port &, size_t, void *),
246                            void *arg)
247 {
248         PortMap::const_iterator i;
249         int retval;
250         int n;
251                 
252         for (n = 0, i = ports_by_device.begin(); 
253                     i != ports_by_device.end(); i++, n++) {
254
255                 if ((retval = func (*((*i).second), n, arg)) != 0) {
256                         return retval;
257                 }
258         }
259
260         return 0;
261 }
262
263 void
264 Manager::cycle_start(nframes_t nframes)
265 {
266         for (PortMap::iterator i = ports_by_device.begin(); i != ports_by_device.end(); i++) {
267                 (*i).second->cycle_start (nframes);
268         }
269 }
270
271 void
272 Manager::cycle_end()
273 {
274         for (PortMap::iterator i = ports_by_device.begin(); i != ports_by_device.end(); i++) {
275                 (*i).second->cycle_end ();
276         }
277 }
278
279
280 int
281 Manager::get_known_ports (vector<PortSet>& ports)
282 {
283         return PortFactory::get_known_ports (ports);
284 }