Subversion Repositories svn.mios

Rev

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