7cd03a6311d03a12870f5eb5ea46bb60c8ee4559
[ardour.git] / libs / midi++2 / manager.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         for (PortList::iterator p = _ports.begin(); p != _ports.end(); ++p) {
51                 delete *p;
52         }
53
54         if (theManager == this) {
55                 theManager = 0;
56         }
57 }
58
59 Port *
60 Manager::add_port (const XMLNode& node)
61 {
62         Port::Descriptor desc (node);
63         PortFactory factory;
64         Port *port;
65         PortList::iterator p;
66
67         for (p = _ports.begin(); p != _ports.end(); ++p) {
68
69                 if (desc.tag == (*p)->name()) {
70                         break;
71                 } 
72
73                 if (!PortFactory::ignore_duplicate_devices (desc.type)) {
74                         if (desc.device == (*p)->device()) {
75                                 /* If the existing is duplex, and this request
76                                    is not, then fail, because most drivers won't
77                                    allow opening twice with duplex and non-duplex
78                                    operation.
79                                 */
80
81                                 if ((desc.mode == O_RDWR && port->mode() != O_RDWR) ||
82                                     (desc.mode != O_RDWR && port->mode() == O_RDWR)) {
83                                         break;
84                                 }
85                         }
86                 }
87         }
88
89         if (p != _ports.end()) {
90                 return 0;
91         }
92         
93         port = factory.create_port (node, api_data);
94         
95         if (port == 0) {
96                 return 0;
97         }
98
99         if (!port->ok()) {
100                 delete port;
101                 return 0;
102         }
103
104         _ports.push_back (port);
105
106         /* first port added becomes the default input
107            port.
108         */
109
110         if (inputPort == 0) {
111                 inputPort = port;
112         } 
113
114         if (outputPort == 0) {
115                 outputPort = port;
116         }
117
118         return port;
119 }
120
121 int 
122 Manager::remove_port (Port* port)
123 {
124         if (inputPort == port) {
125                 inputPort = 0;
126         }
127         if (outputPort == port) {
128                 outputPort = 0;
129         }
130         _ports.remove (port);
131         delete port;
132         return 0;
133 }
134
135 int
136 Manager::set_input_port (string tag)
137 {
138         for (PortList::iterator p = _ports.begin(); p != _ports.end(); ++p) {
139                 if ((*p)->name() == tag) {
140                         inputPort = (*p);
141                         return 0;
142                 }
143         }
144
145         return -1;
146 }
147
148 int
149 Manager::set_output_port (string tag)
150 {
151         PortList::iterator p;
152
153         for (p = _ports.begin(); p != _ports.end(); ++p) {
154                 if ((*p)->name() == tag) {
155                         inputPort = (*p);
156                         break;
157                 }
158         }
159
160         if (p == _ports.end()) {
161                 return -1;
162         }
163
164         // XXX send a signal to say we're about to change output ports
165
166         if (outputPort) {
167                 for (channel_t chan = 0; chan < 16; chan++) {
168                         outputPort->channel (chan)->all_notes_off (0);
169                 }
170         }
171         
172         outputPort = (*p);
173
174         // XXX send a signal to say we've changed output ports
175
176         return 0;
177 }
178
179 Port *
180 Manager::port (string name)
181 {
182         for (PortList::iterator p = _ports.begin(); p != _ports.end(); ++p) {
183                 if (name == (*p)->name()) {
184                         return (*p);
185                 }
186         }
187
188         return 0;
189 }
190
191 int
192 Manager::foreach_port (int (*func)(const Port &, size_t, void *),
193                            void *arg)
194 {
195         int n = 0;
196                 
197         for (PortList::const_iterator p = _ports.begin(); p != _ports.end(); ++p, ++n) {
198                 int retval;
199
200                 if ((retval = func (**p, n, arg)) != 0) {
201                         return retval;
202                 }
203         }
204
205         return 0;
206 }
207
208 void
209 Manager::cycle_start(nframes_t nframes)
210 {
211         for (PortList::iterator p = _ports.begin(); p != _ports.end(); ++p) {
212                 (*p)->cycle_start (nframes);
213         }
214 }
215
216 void
217 Manager::cycle_end()
218 {
219         for (PortList::iterator p = _ports.begin(); p != _ports.end(); ++p) {
220                 (*p)->cycle_end ();
221         }
222 }
223
224
225 int
226 Manager::get_known_ports (vector<PortSet>& ports)
227 {
228         return PortFactory::get_known_ports (ports);
229 }