Subversion Repositories svn.mios

Rev

Rev 624 | Rev 641 | 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
 
628 adamjking 36
public class MidiDeviceRouting extends Observable implements Observer {
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 MidiDeviceManager midiDeviceManager;
51
 
52
    private MidiRouterDeviceManager midiRouterDeviceManager;
53
 
54
    private MidiFilterDeviceManager midiFilterManager;
55
 
56
    /*
57
     * private MidiMapDeviceManager midiMapManager;
58
     */
59
 
60
    private boolean portsReleased;
61
 
62
    public MidiDeviceRouting() {
213 tk 63
        midiReadDevices = new Vector();
628 adamjking 64
        midiWriteDevices = new Vector();
65
 
66
        logicalConnections = new Vector();
67
 
68
        midiDeviceManager = new MidiDeviceManager();
69
        midiDeviceManager.addObserver(this);
70
 
71
        midiRouterDeviceManager = new MidiRouterDeviceManager();
72
        midiRouterDeviceManager.addObserver(this);
73
 
74
        midiFilterManager = new MidiFilterDeviceManager();
75
        midiFilterManager.addObserver(this);
76
 
77
        /*
78
         * midiMapManager = new MidiMapDeviceManager();
79
         * midiMapManager.addObserver(this);
80
         */
213 tk 81
    }
82
 
83
    public Vector getMidiReadDevices() {
84
        return midiReadDevices;
85
    }
86
 
87
    public Vector getMidiWriteDevices() {
88
        return midiWriteDevices;
89
    }
628 adamjking 90
 
91
    public void addMidiReadDevice(MidiDevice midiDevice) {
92
        midiReadDevices.add(midiDevice);
93
        setChanged();
94
        notifyObservers(midiReadDevices);
95
        clearChanged();
213 tk 96
    }
628 adamjking 97
 
98
    public void addMidiWriteDevice(MidiDevice midiDevice) {
99
        midiWriteDevices.add(midiDevice);
100
        setChanged();
101
        notifyObservers(midiReadDevices);
102
        clearChanged();
213 tk 103
    }
104
 
628 adamjking 105
    public void addMidiReadDevices(Collection midiDevices) {
106
        Iterator it = midiDevices.iterator();
557 rutgerv 107
 
628 adamjking 108
        while (it.hasNext()) {
109
            MidiDevice midiDevice = (MidiDevice) it.next();
110
            addMidiReadDevice(midiDevice);
294 rutgerv 111
        }
112
    }
628 adamjking 113
 
114
    public void addMidiWriteDevices(Collection midiDevices) {
115
        Iterator it = midiDevices.iterator();
116
 
117
        while (it.hasNext()) {
118
            MidiDevice midiDevice = (MidiDevice) it.next();
119
            addMidiWriteDevice(midiDevice);
294 rutgerv 120
        }
121
    }
628 adamjking 122
 
123
    public void removeMidiReadDevice(MidiDevice midiDevice) {
124
        midiReadDevices.remove(midiDevice);
125
        setChanged();
126
        notifyObservers(midiReadDevices);
127
        clearChanged();
294 rutgerv 128
    }
628 adamjking 129
 
130
    public void removeMidiWriteDevice(MidiDevice midiDevice) {
131
        midiWriteDevices.remove(midiDevice);
132
        setChanged();
133
        notifyObservers(midiWriteDevices);
134
        clearChanged();
294 rutgerv 135
    }
628 adamjking 136
 
137
    public void removeMidiReadDevices(Collection midiDevices) {
138
        Iterator it = midiDevices.iterator();
139
 
140
        while (it.hasNext()) {
141
            MidiDevice midiDevice = (MidiDevice) it.next();
142
            removeMidiReadDevice(midiDevice);
143
        }
293 rutgerv 144
    }
628 adamjking 145
 
146
    public void removeMidiWriteDevices(Collection midiDevices) {
147
        Iterator it = midiDevices.iterator();
148
 
149
        while (it.hasNext()) {
150
            MidiDevice midiDevice = (MidiDevice) it.next();
151
            removeMidiWriteDevice(midiDevice);
557 rutgerv 152
        }
213 tk 153
    }
628 adamjking 154
 
155
    public void removeAllMidiReadDevices() {
156
        midiReadDevices.removeAllElements();
157
        setChanged();
158
        notifyObservers(midiReadDevices);
159
        clearChanged();
160
    }
161
 
162
    public void removeAllMidiWriteDevices() {
163
        midiWriteDevices.removeAllElements();
164
        setChanged();
165
        notifyObservers(midiWriteDevices);
166
        clearChanged();
167
    }
168
 
169
    public MidiDeviceManager getMidiDeviceManager() {
170
        return midiDeviceManager;
171
    }
172
 
173
    public MidiRouterDeviceManager getMidiRouterDeviceManager() {
174
        return midiRouterDeviceManager;
175
    }
176
 
177
    public MidiFilterDeviceManager getMidiFilterManager() {
178
        return midiFilterManager;
179
    }
180
 
181
    /*
182
     * public MidiMapDeviceManager getMidiMapManager() { return midiMapManager;
183
     * }
184
     */
185
 
186
    public void connectDevices(MidiDevice transmittingDevice,
187
            MidiDevice receivingDevice) {
188
 
189
        if (devicesConnected(transmittingDevice, receivingDevice) == PHYSICALLY_CONNECTED) {
190
            return;
557 rutgerv 191
        }
628 adamjking 192
 
193
        logicallyConnectDevices(transmittingDevice, receivingDevice);
194
 
195
        if (!portsReleased
196
                || ((transmittingDevice instanceof VirtualMidiDevice) && (receivingDevice instanceof VirtualMidiDevice))) {
197
 
198
            physicallyConnectDevices(transmittingDevice, receivingDevice);
199
        }
200
 
201
        setChanged();
202
        notifyObservers();
203
        clearChanged();
213 tk 204
    }
628 adamjking 205
 
206
    private void physicallyConnectDevices(MidiDevice transmittingDevice,
213 tk 207
            MidiDevice receivingDevice) {
208
        try {
209
            if (!receivingDevice.isOpen()) {
210
                receivingDevice.open();
211
            }
212
 
213
            Receiver receiver = receivingDevice.getReceiver();
214
 
215
            if (!transmittingDevice.isOpen()) {
216
                transmittingDevice.open();
217
            }
218
 
219
            transmittingDevice.getTransmitter().setReceiver(receiver);
628 adamjking 220
 
213 tk 221
        } catch (MidiUnavailableException e) {
628 adamjking 222
 
213 tk 223
        } catch (NullPointerException e) {
628 adamjking 224
 
213 tk 225
        }
628 adamjking 226
 
213 tk 227
    }
628 adamjking 228
 
229
    private void logicallyConnectDevices(MidiDevice transmittingDevice,
213 tk 230
            MidiDevice receivingDevice) {
628 adamjking 231
        logicalConnections.add(new LogicalConnection(transmittingDevice,
232
                receivingDevice));
233
    }
213 tk 234
 
628 adamjking 235
    public void disconnectDevices(MidiDevice transmittingDevice,
236
            MidiDevice receivingDevice) {
237
 
238
        if (devicesConnected(transmittingDevice, receivingDevice) == DISCONNECTED) {
239
            return;
240
        }
241
 
242
        logicallyDisconnectDevices(transmittingDevice, receivingDevice);
243
        if (!portsReleased
244
                || ((transmittingDevice instanceof VirtualMidiDevice) && (receivingDevice instanceof VirtualMidiDevice))) {
245
 
246
            physicallyDisconnectDevices(transmittingDevice, receivingDevice);
247
        }
248
        setChanged();
249
        notifyObservers();
250
        clearChanged();
251
    }
252
 
253
    private void physicallyDisconnectDevices(MidiDevice transmittingDevice,
254
            MidiDevice receivingDevice) {
255
 
256
        // TK: to avoid a "java.util.ConcurrentModificationException" under
257
        // MacOS (using mmj)
258
        // when a transmitter or receiver is closed, we put them into a list and
259
        // execute close()
615 tk 260
        // after iteration
261
        List closeTransmitters = new ArrayList();
262
        List closeReceivers = new ArrayList();
263
 
213 tk 264
        Iterator it = transmittingDevice.getTransmitters().iterator();
265
        while (it.hasNext()) {
266
 
267
            Transmitter transmitter = (Transmitter) it.next();
268
 
269
            Iterator it2 = receivingDevice.getReceivers().iterator();
270
            while (it2.hasNext()) {
271
 
272
                Receiver receiver = (Receiver) it2.next();
273
 
274
                if (transmitter.getReceiver() == receiver) {
275
 
615 tk 276
                    // transmitter.close();
277
                    closeTransmitters.add(transmitter);
278
 
279
                    // receiver.close();
280
                    closeReceivers.add(receiver);
213 tk 281
                }
282
            }
283
        }
615 tk 284
 
285
        int i;
628 adamjking 286
        for (i = 0; i < closeTransmitters.size(); ++i) {
287
            Transmitter transmitter = (Transmitter) closeTransmitters.get(i);
288
            transmitter.close();
615 tk 289
        }
290
 
628 adamjking 291
        for (i = 0; i < closeReceivers.size(); ++i) {
292
            Receiver receiver = (Receiver) closeReceivers.get(i);
293
            receiver.close();
615 tk 294
        }
628 adamjking 295
 
624 adamjking 296
        int num_transmitters = (transmittingDevice.getTransmitters() != null) ? transmittingDevice
297
                .getTransmitters().size()
298
                : 0;
299
        int num_receivers = (transmittingDevice.getReceivers() != null) ? transmittingDevice
300
                .getReceivers().size()
301
                : 0;
302
 
303
        if (num_transmitters == 0 && num_receivers == 0) {
619 adamjking 304
            transmittingDevice.close();
305
        }
615 tk 306
 
624 adamjking 307
        num_transmitters = (receivingDevice.getTransmitters() != null) ? receivingDevice
308
                .getTransmitters().size()
309
                : 0;
310
        num_receivers = (receivingDevice.getReceivers() != null) ? receivingDevice
311
                .getReceivers().size()
312
                : 0;
313
 
628 adamjking 314
        if (num_transmitters == 0 && num_receivers == 0) {
619 adamjking 315
            receivingDevice.close();
316
        }
213 tk 317
    }
318
 
628 adamjking 319
    private void logicallyDisconnectDevices(MidiDevice transmittingDevice,
320
            MidiDevice receivingDevice) {
321
        logicalConnections.remove(new LogicalConnection(transmittingDevice,
322
                receivingDevice));
323
    }
213 tk 324
 
628 adamjking 325
    public void disconnectDevice(MidiDevice midiDevice) {
213 tk 326
 
628 adamjking 327
        Vector matches = new Vector();
213 tk 328
 
628 adamjking 329
        Iterator it = logicalConnections.iterator();
330
 
331
        while (it.hasNext()) {
332
            LogicalConnection logicalConnection = (LogicalConnection) it.next();
333
            if (logicalConnection.getSourceDevice() == midiDevice
334
                    || logicalConnection.getTargetDevice() == midiDevice) {
335
                matches.add(logicalConnection);
336
            }
337
        }
338
 
339
        it = matches.iterator();
340
 
341
        while (it.hasNext()) {
342
            LogicalConnection logicalConnection = (LogicalConnection) it.next();
343
            disconnectDevices(logicalConnection.getSourceDevice(),
344
                    logicalConnection.getTargetDevice());
345
        }
346
    }
347
 
348
    public void disconnectAll() {
349
 
350
        Iterator it = midiReadDevices.iterator();
351
 
352
        while (it.hasNext()) {
353
 
354
            MidiDevice transmittingDevice = (MidiDevice) it.next();
355
 
356
            Iterator it2 = midiWriteDevices.iterator();
357
            while (it2.hasNext()) {
358
 
359
                MidiDevice receivingDevice = (MidiDevice) it2.next();
360
 
361
                disconnectDevices(transmittingDevice, receivingDevice);
362
            }
363
        }
364
    }
365
 
366
    public void setPortsReleased(boolean portsReleased) {
367
 
368
        this.portsReleased = portsReleased;
369
 
370
        if (portsReleased) {
371
 
372
            Iterator it = logicalConnections.iterator();
373
 
374
            while (it.hasNext()) {
375
                LogicalConnection logicalConnection = (LogicalConnection) it
376
                        .next();
377
                MidiDevice sourceDevice = logicalConnection.getSourceDevice();
378
                MidiDevice targetDevice = logicalConnection.getTargetDevice();
379
 
380
                if (!(sourceDevice instanceof VirtualMidiDevice)
381
                        || !(targetDevice instanceof VirtualMidiDevice)) {
382
 
383
                    physicallyDisconnectDevices(sourceDevice, targetDevice);
384
                }
385
            }
386
        } else {
387
 
388
            Iterator it = logicalConnections.iterator();
389
 
390
            while (it.hasNext()) {
391
                LogicalConnection logicalConnection = (LogicalConnection) it
392
                        .next();
393
                MidiDevice sourceDevice = logicalConnection.getSourceDevice();
394
                MidiDevice targetDevice = logicalConnection.getTargetDevice();
395
 
396
                if (!(sourceDevice instanceof VirtualMidiDevice)
397
                        || !(targetDevice instanceof VirtualMidiDevice)) {
398
                    physicallyConnectDevices(sourceDevice, targetDevice);
399
                }
400
            }
401
        }
402
 
403
        setChanged();
404
        notifyObservers();
405
        clearChanged();
406
    }
407
 
408
    public boolean getPortsReleased() {
409
        return portsReleased;
410
    }
411
 
412
    public int devicesConnected(MidiDevice transmittingDevice,
413
            MidiDevice receivingDevice) {
414
 
415
        try {
416
 
417
            Iterator it = transmittingDevice.getTransmitters().iterator();
418
 
419
            while (it.hasNext()) {
420
                Transmitter transmitter = (Transmitter) it.next();
421
 
422
                Iterator it2 = receivingDevice.getReceivers().iterator();
423
 
424
                while (it2.hasNext()) {
425
 
426
                    Receiver receiver = (Receiver) it2.next();
427
 
428
                    if (transmitter.getReceiver() == receiver) {
429
                        return PHYSICALLY_CONNECTED;
213 tk 430
                    }
431
                }
628 adamjking 432
            }
433
        } catch (Exception e) {
434
            return DISCONNECTED;
435
        }
213 tk 436
 
628 adamjking 437
        if (logicalConnections.contains(new LogicalConnection(
438
                transmittingDevice, receivingDevice))) {
439
            return LOGICALLY_CONNECTED;
440
        }
441
 
442
        return DISCONNECTED;
443
    }
444
 
445
    public void reorder() {
446
        midiReadDevices.removeAll(midiDeviceManager
447
                .getSelectedMidiReadDevices());
448
        midiWriteDevices.removeAll(midiDeviceManager
449
                .getSelectedMidiWriteDevices());
450
        midiReadDevices.removeAll(midiRouterDeviceManager
451
                .getMidiRouterDevices());
452
        midiWriteDevices.removeAll(midiRouterDeviceManager
453
                .getMidiRouterDevices());
454
        midiReadDevices.removeAll(midiFilterManager.getMidiFilterDevices());
455
        midiWriteDevices.removeAll(midiFilterManager.getMidiFilterDevices());
456
 
457
        /*
458
         * midiReadDevices.removeAll(midiMapManager.getMidiMapDevices());
459
         * midiWriteDevices.removeAll(midiMapManager.getMidiMapDevices());
460
         */
461
 
462
        Iterator it = midiDeviceManager.getMidiReadDevices().iterator();
463
        while (it.hasNext()) {
464
 
465
            Object object = it.next();
466
 
467
            if (midiDeviceManager.getSelectedMidiReadDevices().contains(object)) {
468
                midiReadDevices.add(object);
213 tk 469
            }
470
        }
628 adamjking 471
 
472
        it = midiDeviceManager.getMidiWriteDevices().iterator();
473
        while (it.hasNext()) {
474
 
475
            Object object = it.next();
476
 
477
            if (midiDeviceManager.getSelectedMidiWriteDevices()
478
                    .contains(object)) {
479
                midiWriteDevices.add(object);
480
            }
481
        }
482
 
483
        midiReadDevices.addAll(midiRouterDeviceManager.getMidiRouterDevices());
484
        midiWriteDevices.addAll(midiRouterDeviceManager.getMidiRouterDevices());
485
        midiReadDevices.addAll(midiFilterManager.getMidiFilterDevices());
486
        midiWriteDevices.addAll(midiFilterManager.getMidiFilterDevices());
487
 
488
        /*
489
         * midiReadDevices.addAll(midiMapManager.getMidiMapDevices());
490
         * midiWriteDevices.addAll(midiMapManager.getMidiMapDevices());
491
         */
492
 
213 tk 493
        setChanged();
494
        notifyObservers(midiReadDevices);
495
        clearChanged();
628 adamjking 496
 
213 tk 497
        setChanged();
498
        notifyObservers(midiWriteDevices);
499
        clearChanged();
628 adamjking 500
    }
501
 
502
    public void update(Observable observable, Object object) {
503
        if (observable == midiDeviceManager
504
                || observable == midiRouterDeviceManager
505
                || observable == midiFilterManager
506
        /* || observable == midiMapManager */) {
507
 
508
            MidiDevice midiDevice = (MidiDevice) object;
509
 
510
            if (midiReadDevices.contains(midiDevice)
511
                    || midiWriteDevices.contains(midiDevice)) {
512
                disconnectDevice(midiDevice);
513
                removeMidiReadDevice(midiDevice);
514
                removeMidiWriteDevice(midiDevice);
515
            } else {
516
                reorder();
517
            }
518
        }
519
    }
520
 
521
    public static class LogicalConnection {
522
 
523
        private MidiDevice sourceDevice;
524
 
525
        private MidiDevice targetDevice;
526
 
527
        public LogicalConnection(MidiDevice sourceDevice,
528
                MidiDevice targetDevice) {
529
            this.sourceDevice = sourceDevice;
530
            this.targetDevice = targetDevice;
531
        }
532
 
533
        public MidiDevice getSourceDevice() {
534
            return sourceDevice;
535
        }
536
 
537
        public MidiDevice getTargetDevice() {
538
            return targetDevice;
539
        }
540
 
541
        public boolean equals(Object object) {
542
            if (object instanceof LogicalConnection) {
543
                if (((LogicalConnection) object).getSourceDevice() == sourceDevice
544
                        && ((LogicalConnection) object).getTargetDevice() == targetDevice) {
545
                    return true;
546
                }
547
            }
548
            return false;
549
        }
550
    }
213 tk 551
}