Subversion Repositories svn.mios

Rev

Rev 642 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
213 tk 1
/*
628 adamjking 2
 * @(#)MidiDeviceRouting.java   beta8   2006/04/23
213 tk 3
 *
628 adamjking 4
 * Copyright (C) 2008    Adam King (adamjking@optusnet.com.au)
5
 *
213 tk 6
 * This application 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 application 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
17
 * along with this application; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20
 
21
package org.midibox.midi;
22
 
628 adamjking 23
import java.util.ArrayList;
213 tk 24
import java.util.Collection;
25
import java.util.Iterator;
615 tk 26
import java.util.List;
213 tk 27
import java.util.Observable;
28
import java.util.Vector;
29
 
30
import javax.sound.midi.MidiDevice;
31
import javax.sound.midi.MidiUnavailableException;
32
import javax.sound.midi.Receiver;
33
import javax.sound.midi.Transmitter;
34
 
641 adamjking 35
public class MidiDeviceRouting extends Observable {
213 tk 36
 
628 adamjking 37
    public static int DISCONNECTED = 0;
38
 
39
    public static int LOGICALLY_CONNECTED = 1;
40
 
41
    public static int PHYSICALLY_CONNECTED = 2;
42
 
213 tk 43
    private Vector midiReadDevices;
628 adamjking 44
 
213 tk 45
    private Vector midiWriteDevices;
628 adamjking 46
 
47
    private Vector logicalConnections;
48
 
49
    private boolean portsReleased;
50
 
51
    public MidiDeviceRouting() {
213 tk 52
        midiReadDevices = new Vector();
628 adamjking 53
        midiWriteDevices = new Vector();
54
 
55
        logicalConnections = new Vector();
213 tk 56
    }
57
 
58
    public Vector getMidiReadDevices() {
59
        return midiReadDevices;
60
    }
61
 
62
    public Vector getMidiWriteDevices() {
63
        return midiWriteDevices;
64
    }
628 adamjking 65
 
66
    public void addMidiReadDevice(MidiDevice midiDevice) {
67
        midiReadDevices.add(midiDevice);
68
        setChanged();
69
        notifyObservers(midiReadDevices);
70
        clearChanged();
213 tk 71
    }
628 adamjking 72
 
73
    public void addMidiWriteDevice(MidiDevice midiDevice) {
74
        midiWriteDevices.add(midiDevice);
75
        setChanged();
76
        notifyObservers(midiReadDevices);
77
        clearChanged();
213 tk 78
    }
79
 
628 adamjking 80
    public void addMidiReadDevices(Collection midiDevices) {
81
        Iterator it = midiDevices.iterator();
557 rutgerv 82
 
628 adamjking 83
        while (it.hasNext()) {
84
            MidiDevice midiDevice = (MidiDevice) it.next();
85
            addMidiReadDevice(midiDevice);
294 rutgerv 86
        }
87
    }
628 adamjking 88
 
89
    public void addMidiWriteDevices(Collection midiDevices) {
90
        Iterator it = midiDevices.iterator();
91
 
92
        while (it.hasNext()) {
93
            MidiDevice midiDevice = (MidiDevice) it.next();
94
            addMidiWriteDevice(midiDevice);
294 rutgerv 95
        }
96
    }
628 adamjking 97
 
98
    public void removeMidiReadDevice(MidiDevice midiDevice) {
99
        midiReadDevices.remove(midiDevice);
100
        setChanged();
101
        notifyObservers(midiReadDevices);
102
        clearChanged();
294 rutgerv 103
    }
628 adamjking 104
 
105
    public void removeMidiWriteDevice(MidiDevice midiDevice) {
106
        midiWriteDevices.remove(midiDevice);
107
        setChanged();
108
        notifyObservers(midiWriteDevices);
109
        clearChanged();
294 rutgerv 110
    }
628 adamjking 111
 
112
    public void removeMidiReadDevices(Collection midiDevices) {
113
        Iterator it = midiDevices.iterator();
114
 
115
        while (it.hasNext()) {
116
            MidiDevice midiDevice = (MidiDevice) it.next();
117
            removeMidiReadDevice(midiDevice);
118
        }
293 rutgerv 119
    }
628 adamjking 120
 
121
    public void removeMidiWriteDevices(Collection midiDevices) {
122
        Iterator it = midiDevices.iterator();
123
 
124
        while (it.hasNext()) {
125
            MidiDevice midiDevice = (MidiDevice) it.next();
126
            removeMidiWriteDevice(midiDevice);
557 rutgerv 127
        }
213 tk 128
    }
628 adamjking 129
 
130
    public void removeAllMidiReadDevices() {
131
        midiReadDevices.removeAllElements();
132
        setChanged();
133
        notifyObservers(midiReadDevices);
134
        clearChanged();
135
    }
136
 
137
    public void removeAllMidiWriteDevices() {
138
        midiWriteDevices.removeAllElements();
139
        setChanged();
140
        notifyObservers(midiWriteDevices);
141
        clearChanged();
142
    }
143
 
144
    public void connectDevices(MidiDevice transmittingDevice,
145
            MidiDevice receivingDevice) {
146
 
147
        if (devicesConnected(transmittingDevice, receivingDevice) == PHYSICALLY_CONNECTED) {
148
            return;
557 rutgerv 149
        }
628 adamjking 150
 
151
        logicallyConnectDevices(transmittingDevice, receivingDevice);
152
 
153
        if (!portsReleased
154
                || ((transmittingDevice instanceof VirtualMidiDevice) && (receivingDevice instanceof VirtualMidiDevice))) {
155
 
156
            physicallyConnectDevices(transmittingDevice, receivingDevice);
157
        }
158
 
159
        setChanged();
160
        notifyObservers();
161
        clearChanged();
213 tk 162
    }
628 adamjking 163
 
164
    private void physicallyConnectDevices(MidiDevice transmittingDevice,
213 tk 165
            MidiDevice receivingDevice) {
166
        try {
167
            if (!receivingDevice.isOpen()) {
168
                receivingDevice.open();
169
            }
170
 
171
            Receiver receiver = receivingDevice.getReceiver();
172
 
173
            if (!transmittingDevice.isOpen()) {
174
                transmittingDevice.open();
175
            }
176
 
177
            transmittingDevice.getTransmitter().setReceiver(receiver);
628 adamjking 178
 
213 tk 179
        } catch (MidiUnavailableException e) {
628 adamjking 180
 
213 tk 181
        } catch (NullPointerException e) {
628 adamjking 182
 
213 tk 183
        }
628 adamjking 184
 
213 tk 185
    }
628 adamjking 186
 
187
    private void logicallyConnectDevices(MidiDevice transmittingDevice,
213 tk 188
            MidiDevice receivingDevice) {
628 adamjking 189
        logicalConnections.add(new LogicalConnection(transmittingDevice,
190
                receivingDevice));
191
    }
213 tk 192
 
628 adamjking 193
    public void disconnectDevices(MidiDevice transmittingDevice,
194
            MidiDevice receivingDevice) {
195
 
196
        if (devicesConnected(transmittingDevice, receivingDevice) == DISCONNECTED) {
197
            return;
198
        }
199
 
200
        logicallyDisconnectDevices(transmittingDevice, receivingDevice);
201
        if (!portsReleased
202
                || ((transmittingDevice instanceof VirtualMidiDevice) && (receivingDevice instanceof VirtualMidiDevice))) {
203
 
204
            physicallyDisconnectDevices(transmittingDevice, receivingDevice);
205
        }
206
        setChanged();
207
        notifyObservers();
208
        clearChanged();
209
    }
210
 
211
    private void physicallyDisconnectDevices(MidiDevice transmittingDevice,
212
            MidiDevice receivingDevice) {
213
 
214
        // TK: to avoid a "java.util.ConcurrentModificationException" under
215
        // MacOS (using mmj)
216
        // when a transmitter or receiver is closed, we put them into a list and
217
        // execute close()
615 tk 218
        // after iteration
219
        List closeTransmitters = new ArrayList();
220
        List closeReceivers = new ArrayList();
221
 
213 tk 222
        Iterator it = transmittingDevice.getTransmitters().iterator();
223
        while (it.hasNext()) {
224
 
225
            Transmitter transmitter = (Transmitter) it.next();
226
 
227
            Iterator it2 = receivingDevice.getReceivers().iterator();
228
            while (it2.hasNext()) {
229
 
230
                Receiver receiver = (Receiver) it2.next();
231
 
232
                if (transmitter.getReceiver() == receiver) {
233
 
615 tk 234
                    // transmitter.close();
235
                    closeTransmitters.add(transmitter);
236
 
237
                    // receiver.close();
238
                    closeReceivers.add(receiver);
213 tk 239
                }
240
            }
241
        }
615 tk 242
 
243
        int i;
628 adamjking 244
        for (i = 0; i < closeTransmitters.size(); ++i) {
245
            Transmitter transmitter = (Transmitter) closeTransmitters.get(i);
246
            transmitter.close();
615 tk 247
        }
248
 
628 adamjking 249
        for (i = 0; i < closeReceivers.size(); ++i) {
250
            Receiver receiver = (Receiver) closeReceivers.get(i);
251
            receiver.close();
615 tk 252
        }
628 adamjking 253
 
624 adamjking 254
        int num_transmitters = (transmittingDevice.getTransmitters() != null) ? transmittingDevice
255
                .getTransmitters().size()
256
                : 0;
257
        int num_receivers = (transmittingDevice.getReceivers() != null) ? transmittingDevice
258
                .getReceivers().size()
259
                : 0;
260
 
261
        if (num_transmitters == 0 && num_receivers == 0) {
619 adamjking 262
            transmittingDevice.close();
263
        }
615 tk 264
 
624 adamjking 265
        num_transmitters = (receivingDevice.getTransmitters() != null) ? receivingDevice
266
                .getTransmitters().size()
267
                : 0;
268
        num_receivers = (receivingDevice.getReceivers() != null) ? receivingDevice
269
                .getReceivers().size()
270
                : 0;
271
 
628 adamjking 272
        if (num_transmitters == 0 && num_receivers == 0) {
619 adamjking 273
            receivingDevice.close();
274
        }
213 tk 275
    }
276
 
628 adamjking 277
    private void logicallyDisconnectDevices(MidiDevice transmittingDevice,
278
            MidiDevice receivingDevice) {
279
        logicalConnections.remove(new LogicalConnection(transmittingDevice,
280
                receivingDevice));
281
    }
213 tk 282
 
628 adamjking 283
    public void disconnectDevice(MidiDevice midiDevice) {
213 tk 284
 
628 adamjking 285
        Vector matches = new Vector();
213 tk 286
 
628 adamjking 287
        Iterator it = logicalConnections.iterator();
288
 
289
        while (it.hasNext()) {
290
            LogicalConnection logicalConnection = (LogicalConnection) it.next();
291
            if (logicalConnection.getSourceDevice() == midiDevice
292
                    || logicalConnection.getTargetDevice() == midiDevice) {
293
                matches.add(logicalConnection);
294
            }
295
        }
296
 
297
        it = matches.iterator();
298
 
299
        while (it.hasNext()) {
300
            LogicalConnection logicalConnection = (LogicalConnection) it.next();
301
            disconnectDevices(logicalConnection.getSourceDevice(),
302
                    logicalConnection.getTargetDevice());
303
        }
304
    }
305
 
306
    public void disconnectAll() {
307
 
308
        Iterator it = midiReadDevices.iterator();
309
 
310
        while (it.hasNext()) {
311
 
312
            MidiDevice transmittingDevice = (MidiDevice) it.next();
313
 
314
            Iterator it2 = midiWriteDevices.iterator();
315
            while (it2.hasNext()) {
316
 
317
                MidiDevice receivingDevice = (MidiDevice) it2.next();
318
 
319
                disconnectDevices(transmittingDevice, receivingDevice);
320
            }
321
        }
322
    }
323
 
324
    public void setPortsReleased(boolean portsReleased) {
325
 
326
        this.portsReleased = portsReleased;
327
 
328
        if (portsReleased) {
329
 
330
            Iterator it = logicalConnections.iterator();
331
 
332
            while (it.hasNext()) {
333
                LogicalConnection logicalConnection = (LogicalConnection) it
334
                        .next();
335
                MidiDevice sourceDevice = logicalConnection.getSourceDevice();
336
                MidiDevice targetDevice = logicalConnection.getTargetDevice();
337
 
338
                if (!(sourceDevice instanceof VirtualMidiDevice)
339
                        || !(targetDevice instanceof VirtualMidiDevice)) {
340
 
341
                    physicallyDisconnectDevices(sourceDevice, targetDevice);
342
                }
343
            }
344
        } else {
345
 
346
            Iterator it = logicalConnections.iterator();
347
 
348
            while (it.hasNext()) {
349
                LogicalConnection logicalConnection = (LogicalConnection) it
350
                        .next();
351
                MidiDevice sourceDevice = logicalConnection.getSourceDevice();
352
                MidiDevice targetDevice = logicalConnection.getTargetDevice();
353
 
354
                if (!(sourceDevice instanceof VirtualMidiDevice)
355
                        || !(targetDevice instanceof VirtualMidiDevice)) {
356
                    physicallyConnectDevices(sourceDevice, targetDevice);
357
                }
358
            }
359
        }
360
 
361
        setChanged();
362
        notifyObservers();
363
        clearChanged();
364
    }
365
 
721 adamjking 366
    public boolean isPortsReleased() {
628 adamjking 367
        return portsReleased;
368
    }
369
 
370
    public int devicesConnected(MidiDevice transmittingDevice,
371
            MidiDevice receivingDevice) {
372
 
373
        try {
374
 
375
            Iterator it = transmittingDevice.getTransmitters().iterator();
376
 
377
            while (it.hasNext()) {
378
                Transmitter transmitter = (Transmitter) it.next();
379
 
380
                Iterator it2 = receivingDevice.getReceivers().iterator();
381
 
382
                while (it2.hasNext()) {
383
 
384
                    Receiver receiver = (Receiver) it2.next();
385
 
386
                    if (transmitter.getReceiver() == receiver) {
387
                        return PHYSICALLY_CONNECTED;
213 tk 388
                    }
389
                }
628 adamjking 390
            }
391
        } catch (Exception e) {
392
            return DISCONNECTED;
393
        }
213 tk 394
 
628 adamjking 395
        if (logicalConnections.contains(new LogicalConnection(
396
                transmittingDevice, receivingDevice))) {
397
            return LOGICALLY_CONNECTED;
398
        }
399
 
400
        return DISCONNECTED;
401
    }
721 adamjking 402
 
403
    public Vector getLogicalConnections() {
404
        return logicalConnections;
405
    }
628 adamjking 406
 
721 adamjking 407
    public class LogicalConnection {
628 adamjking 408
 
409
        private MidiDevice sourceDevice;
410
 
411
        private MidiDevice targetDevice;
412
 
413
        public LogicalConnection(MidiDevice sourceDevice,
414
                MidiDevice targetDevice) {
415
            this.sourceDevice = sourceDevice;
416
            this.targetDevice = targetDevice;
417
        }
418
 
419
        public MidiDevice getSourceDevice() {
420
            return sourceDevice;
421
        }
422
 
423
        public MidiDevice getTargetDevice() {
424
            return targetDevice;
425
        }
426
 
427
        public boolean equals(Object object) {
428
            if (object instanceof LogicalConnection) {
429
                if (((LogicalConnection) object).getSourceDevice() == sourceDevice
430
                        && ((LogicalConnection) object).getTargetDevice() == targetDevice) {
431
                    return true;
432
                }
433
            }
434
            return false;
435
        }
436
    }
213 tk 437
}