1*90c8c64dSAndroid Build Coastguard Worker /*
2*90c8c64dSAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*90c8c64dSAndroid Build Coastguard Worker  *
4*90c8c64dSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*90c8c64dSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*90c8c64dSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*90c8c64dSAndroid Build Coastguard Worker  *
8*90c8c64dSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*90c8c64dSAndroid Build Coastguard Worker  *
10*90c8c64dSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*90c8c64dSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*90c8c64dSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*90c8c64dSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*90c8c64dSAndroid Build Coastguard Worker  * limitations under the License.
15*90c8c64dSAndroid Build Coastguard Worker  */
16*90c8c64dSAndroid Build Coastguard Worker 
17*90c8c64dSAndroid Build Coastguard Worker package com.example.android.common.midi;
18*90c8c64dSAndroid Build Coastguard Worker 
19*90c8c64dSAndroid Build Coastguard Worker import android.media.midi.MidiReceiver;
20*90c8c64dSAndroid Build Coastguard Worker import android.media.midi.MidiSender;
21*90c8c64dSAndroid Build Coastguard Worker 
22*90c8c64dSAndroid Build Coastguard Worker import java.io.IOException;
23*90c8c64dSAndroid Build Coastguard Worker import java.util.concurrent.CopyOnWriteArrayList;
24*90c8c64dSAndroid Build Coastguard Worker 
25*90c8c64dSAndroid Build Coastguard Worker /**
26*90c8c64dSAndroid Build Coastguard Worker  * Utility class for dispatching MIDI data to a list of {@link MidiReceiver}s.
27*90c8c64dSAndroid Build Coastguard Worker  * This class subclasses {@link MidiReceiver} and dispatches any data it receives
28*90c8c64dSAndroid Build Coastguard Worker  * to its receiver list. Any receivers that throw an exception upon receiving data will
29*90c8c64dSAndroid Build Coastguard Worker  * be automatically removed from the receiver list, but no IOException will be returned
30*90c8c64dSAndroid Build Coastguard Worker  * from the dispatcher's {@link MidiReceiver#onReceive} in that case.
31*90c8c64dSAndroid Build Coastguard Worker  */
32*90c8c64dSAndroid Build Coastguard Worker public final class MidiDispatcher extends MidiReceiver {
33*90c8c64dSAndroid Build Coastguard Worker 
34*90c8c64dSAndroid Build Coastguard Worker     private final CopyOnWriteArrayList<MidiReceiver> mReceivers
35*90c8c64dSAndroid Build Coastguard Worker             = new CopyOnWriteArrayList<MidiReceiver>();
36*90c8c64dSAndroid Build Coastguard Worker 
37*90c8c64dSAndroid Build Coastguard Worker     private final MidiSender mSender = new MidiSender() {
38*90c8c64dSAndroid Build Coastguard Worker         /**
39*90c8c64dSAndroid Build Coastguard Worker          * Called to connect a {@link MidiReceiver} to the sender
40*90c8c64dSAndroid Build Coastguard Worker          *
41*90c8c64dSAndroid Build Coastguard Worker          * @param receiver the receiver to connect
42*90c8c64dSAndroid Build Coastguard Worker          */
43*90c8c64dSAndroid Build Coastguard Worker         @Override
44*90c8c64dSAndroid Build Coastguard Worker         public void onConnect(MidiReceiver receiver) {
45*90c8c64dSAndroid Build Coastguard Worker             mReceivers.add(receiver);
46*90c8c64dSAndroid Build Coastguard Worker         }
47*90c8c64dSAndroid Build Coastguard Worker 
48*90c8c64dSAndroid Build Coastguard Worker         /**
49*90c8c64dSAndroid Build Coastguard Worker          * Called to disconnect a {@link MidiReceiver} from the sender
50*90c8c64dSAndroid Build Coastguard Worker          *
51*90c8c64dSAndroid Build Coastguard Worker          * @param receiver the receiver to disconnect
52*90c8c64dSAndroid Build Coastguard Worker          */
53*90c8c64dSAndroid Build Coastguard Worker         @Override
54*90c8c64dSAndroid Build Coastguard Worker         public void onDisconnect(MidiReceiver receiver) {
55*90c8c64dSAndroid Build Coastguard Worker             mReceivers.remove(receiver);
56*90c8c64dSAndroid Build Coastguard Worker         }
57*90c8c64dSAndroid Build Coastguard Worker     };
58*90c8c64dSAndroid Build Coastguard Worker 
59*90c8c64dSAndroid Build Coastguard Worker     /**
60*90c8c64dSAndroid Build Coastguard Worker      * Returns the number of {@link MidiReceiver}s this dispatcher contains.
61*90c8c64dSAndroid Build Coastguard Worker      * @return the number of receivers
62*90c8c64dSAndroid Build Coastguard Worker      */
getReceiverCount()63*90c8c64dSAndroid Build Coastguard Worker     public int getReceiverCount() {
64*90c8c64dSAndroid Build Coastguard Worker         return mReceivers.size();
65*90c8c64dSAndroid Build Coastguard Worker     }
66*90c8c64dSAndroid Build Coastguard Worker 
67*90c8c64dSAndroid Build Coastguard Worker     /**
68*90c8c64dSAndroid Build Coastguard Worker      * Returns a {@link MidiSender} which is used to add and remove
69*90c8c64dSAndroid Build Coastguard Worker      * {@link MidiReceiver}s
70*90c8c64dSAndroid Build Coastguard Worker      * to the dispatcher's receiver list.
71*90c8c64dSAndroid Build Coastguard Worker      * @return the dispatcher's MidiSender
72*90c8c64dSAndroid Build Coastguard Worker      */
getSender()73*90c8c64dSAndroid Build Coastguard Worker     public MidiSender getSender() {
74*90c8c64dSAndroid Build Coastguard Worker         return mSender;
75*90c8c64dSAndroid Build Coastguard Worker     }
76*90c8c64dSAndroid Build Coastguard Worker 
77*90c8c64dSAndroid Build Coastguard Worker     @Override
onSend(byte[] msg, int offset, int count, long timestamp)78*90c8c64dSAndroid Build Coastguard Worker     public void onSend(byte[] msg, int offset, int count, long timestamp) throws IOException {
79*90c8c64dSAndroid Build Coastguard Worker        for (MidiReceiver receiver : mReceivers) {
80*90c8c64dSAndroid Build Coastguard Worker             try {
81*90c8c64dSAndroid Build Coastguard Worker                 receiver.send(msg, offset, count, timestamp);
82*90c8c64dSAndroid Build Coastguard Worker             } catch (IOException e) {
83*90c8c64dSAndroid Build Coastguard Worker                 // if the receiver fails we remove the receiver but do not propagate the exception
84*90c8c64dSAndroid Build Coastguard Worker                 mReceivers.remove(receiver);
85*90c8c64dSAndroid Build Coastguard Worker             }
86*90c8c64dSAndroid Build Coastguard Worker         }
87*90c8c64dSAndroid Build Coastguard Worker     }
88*90c8c64dSAndroid Build Coastguard Worker 
89*90c8c64dSAndroid Build Coastguard Worker     @Override
flush()90*90c8c64dSAndroid Build Coastguard Worker     public void flush() throws IOException {
91*90c8c64dSAndroid Build Coastguard Worker        for (MidiReceiver receiver : mReceivers) {
92*90c8c64dSAndroid Build Coastguard Worker             receiver.flush();
93*90c8c64dSAndroid Build Coastguard Worker        }
94*90c8c64dSAndroid Build Coastguard Worker     }
95*90c8c64dSAndroid Build Coastguard Worker }
96