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
17package com.android.internal.midi;
18
19import android.media.midi.MidiReceiver;
20import android.media.midi.MidiSender;
21
22import java.io.IOException;
23import java.util.concurrent.CopyOnWriteArrayList;
24
25/**
26 * Utility class for dispatching MIDI data to a list of {@link android.media.midi.MidiReceiver}s.
27 * This class subclasses {@link android.media.midi.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 android.media.midi.MidiReceiver#onSend} in that case.
31 */
32public 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        @Override
39        public void onConnect(MidiReceiver receiver) {
40            mReceivers.add(receiver);
41        }
42
43        @Override
44        public void onDisconnect(MidiReceiver receiver) {
45            mReceivers.remove(receiver);
46        }
47    };
48
49    /**
50     * Returns the number of {@link android.media.midi.MidiReceiver}s this dispatcher contains.
51     * @return the number of receivers
52     */
53    public int getReceiverCount() {
54        return mReceivers.size();
55    }
56
57    /**
58     * Returns a {@link android.media.midi.MidiSender} which is used to add and remove
59     * {@link android.media.midi.MidiReceiver}s
60     * to the dispatcher's receiver list.
61     * @return the dispatcher's MidiSender
62     */
63    public MidiSender getSender() {
64        return mSender;
65    }
66
67    @Override
68    public void onSend(byte[] msg, int offset, int count, long timestamp) throws IOException {
69       for (MidiReceiver receiver : mReceivers) {
70            try {
71                receiver.send(msg, offset, count, timestamp);
72            } catch (IOException e) {
73                // if the receiver fails we remove the receiver but do not propagate the exception
74                mReceivers.remove(receiver);
75            }
76        }
77    }
78
79    @Override
80    public void onFlush() throws IOException {
81       for (MidiReceiver receiver : mReceivers) {
82            receiver.flush();
83       }
84    }
85}
86