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