Skip to content

Most visited

Recently visited

navigation
MidiScope / src / com.example.android.common.midi /

MidiPortSelector.java

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.app.Activity;
20
import android.media.midi.MidiDeviceInfo;
21
import android.media.midi.MidiDeviceStatus;
22
import android.media.midi.MidiManager;
23
import android.media.midi.MidiManager.DeviceCallback;
24
import android.os.Handler;
25
import android.os.Looper;
26
import android.util.Log;
27
import android.view.View;
28
import android.widget.AdapterView;
29
import android.widget.ArrayAdapter;
30
import android.widget.Spinner;
31
 
32
import java.util.HashSet;
33
 
34
/**
35
 * Base class that uses a Spinner to select available MIDI ports.
36
 */
37
public abstract class MidiPortSelector extends DeviceCallback {
38
    private int mType = MidiDeviceInfo.PortInfo.TYPE_INPUT;
39
    protected ArrayAdapter<MidiPortWrapper> mAdapter;
40
    protected HashSet<MidiPortWrapper> mBusyPorts = new HashSet<MidiPortWrapper>();
41
    private Spinner mSpinner;
42
    protected MidiManager mMidiManager;
43
    protected Activity mActivity;
44
    private MidiPortWrapper mCurrentWrapper;
45
 
46
    /**
47
     * @param midiManager
48
     * @param activity
49
     * @param spinnerId
50
     *            ID from the layout resource
51
     * @param type
52
     *            TYPE_INPUT or TYPE_OUTPUT
53
     */
54
    public MidiPortSelector(MidiManager midiManager, Activity activity,
55
            int spinnerId, int type) {
56
        mMidiManager = midiManager;
57
        mActivity = activity;
58
        mType = type;
59
        mAdapter = new ArrayAdapter<MidiPortWrapper>(activity,
60
                android.R.layout.simple_spinner_item);
61
        mAdapter.setDropDownViewResource(
62
                android.R.layout.simple_spinner_dropdown_item);
63
        mAdapter.add(new MidiPortWrapper(null, 0, 0));
64
 
65
        mSpinner = (Spinner) activity.findViewById(spinnerId);
66
        mSpinner.setOnItemSelectedListener(
67
                new AdapterView.OnItemSelectedListener() {
68
 
69
                    public void onItemSelected(AdapterView<?> parent, View view,
70
                            int pos, long id) {
71
                        mCurrentWrapper = mAdapter.getItem(pos);
72
                        onPortSelected(mCurrentWrapper);
73
                    }
74
 
75
                    public void onNothingSelected(AdapterView<?> parent) {
76
                        onPortSelected(null);
77
                        mCurrentWrapper = null;
78
                    }
79
                });
80
        mSpinner.setAdapter(mAdapter);
81
 
82
        mMidiManager.registerDeviceCallback(this,
83
                new Handler(Looper.getMainLooper()));
84
 
85
        MidiDeviceInfo[] infos = mMidiManager.getDevices();
86
        for (MidiDeviceInfo info : infos) {
87
            onDeviceAdded(info);
88
        }
89
    }
90
 
91
    /**
92
     * Set to no port selected.
93
     */
94
    public void clearSelection() {
95
        mSpinner.setSelection(0);
96
    }
97
 
98
    private int getInfoPortCount(final MidiDeviceInfo info) {
99
        int portCount = (mType == MidiDeviceInfo.PortInfo.TYPE_INPUT)
100
                ? info.getInputPortCount() : info.getOutputPortCount();
101
        return portCount;
102
    }
103
 
104
    @Override
105
    public void onDeviceAdded(final MidiDeviceInfo info) {
106
        int portCount = getInfoPortCount(info);
107
        for (int i = 0; i < portCount; ++i) {
108
            MidiPortWrapper wrapper = new MidiPortWrapper(info, mType, i);
109
            mAdapter.add(wrapper);
110
            Log.i(MidiConstants.TAG, wrapper + " was added");
111
            mAdapter.notifyDataSetChanged();
112
        }
113
    }
114
 
115
    @Override
116
    public void onDeviceRemoved(final MidiDeviceInfo info) {
117
        int portCount = getInfoPortCount(info);
118
        for (int i = 0; i < portCount; ++i) {
119
            MidiPortWrapper wrapper = new MidiPortWrapper(info, mType, i);
120
            MidiPortWrapper currentWrapper = mCurrentWrapper;
121
            mAdapter.remove(wrapper);
122
            // If the currently selected port was removed then select no port.
123
            if (wrapper.equals(currentWrapper)) {
124
                clearSelection();
125
            }
126
            mAdapter.notifyDataSetChanged();
127
            Log.i(MidiConstants.TAG, wrapper + " was removed");
128
        }
129
    }
130
 
131
    @Override
132
    public void onDeviceStatusChanged(final MidiDeviceStatus status) {
133
        // If an input port becomes busy then remove it from the menu.
134
        // If it becomes free then add it back to the menu.
135
        if (mType == MidiDeviceInfo.PortInfo.TYPE_INPUT) {
136
            MidiDeviceInfo info = status.getDeviceInfo();
137
            Log.i(MidiConstants.TAG, "MidiPortSelector.onDeviceStatusChanged status = " + status
138
                    + ", mType = " + mType
139
                    + ", activity = " + mActivity.getPackageName()
140
                    + ", info = " + info);
141
            // Look for transitions from free to busy.
142
            int portCount = info.getInputPortCount();
143
            for (int i = 0; i < portCount; ++i) {
144
                MidiPortWrapper wrapper = new MidiPortWrapper(info, mType, i);
145
                if (!wrapper.equals(mCurrentWrapper)) {
146
                    if (status.isInputPortOpen(i)) { // busy?
147
                        if (!mBusyPorts.contains(wrapper)) {
148
                            // was free, now busy
149
                            mBusyPorts.add(wrapper);
150
                            mAdapter.remove(wrapper);
151
                            mAdapter.notifyDataSetChanged();
152
                        }
153
                    } else {
154
                        if (mBusyPorts.remove(wrapper)) {
155
                            // was busy, now free
156
                            mAdapter.add(wrapper);
157
                            mAdapter.notifyDataSetChanged();
158
                        }
159
                    }
160
                }
161
            }
162
        }
163
    }
164
 
165
    /**
166
     * Implement this method to handle the user selecting a port on a device.
167
     *
168
     * @param wrapper
169
     */
170
    public abstract void onPortSelected(MidiPortWrapper wrapper);
171
 
172
    /**
173
     * Implement this method to clean up any open resources.
174
     */
175
    public abstract void onClose();
176
 
177
    /**
178
     *
179
     */
180
    public void close() {
181
        onClose();
182
    }
183
}
This site uses cookies to store your preferences for site-specific language and display options.

Hooray!

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.