Subversion Repositories svn.mios

Rev

Rev 693 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
628 adamjking 1
/*
2
 * @(#)MIOSSysexSendReceive.java    beta8   2006/04/23
3
 *
4
 * Copyright (C) 2008    Adam King (adamjking@optusnet.com.au)
5
 *
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.mios;
22
 
23
import java.util.LinkedList;
24
import java.util.Observable;
25
 
26
import javax.sound.midi.MidiMessage;
27
import javax.sound.midi.Receiver;
28
import javax.sound.midi.SysexMessage;
29
 
30
import org.midibox.utils.Utils;
31
 
32
public class MIOSSysexSendReceive extends Observable implements Receiver {
33
 
34
    public final static Object DEVICE_ID = new Object();
35
 
36
    public final static Object MIOS32_MODE = new Object();
37
 
38
    public final static Object MESSAGES = new Object();
39
 
40
    public final static Object WORKER = new Object();
41
 
42
    protected Receiver receiver;
43
 
44
    protected int deviceID;
45
 
46
    protected boolean MIOS32_Mode;
47
 
48
    protected LinkedList messages;
49
 
50
    protected boolean done = true;
51
 
52
    protected boolean cancelled = true;
53
 
54
    protected static String[] _errorCodes = {
55
            "Less bytes than expected have been received", // 1
56
            "More bytes than expected have been received", // 2
57
            "Checksum mismatch", // 3
58
            "Write failed (verify error or invalid address)", // 4
59
            "Write access failed (invalid address range)", // 5
60
            "MIDI Time Out", // 6
61
            "Wrong Debug Command", // 7
62
            "Read/Write command tried to access an invalid address range", // 8
63
            "Read/Write address not correctly aligned", // 9
64
            "BankStick not available", // A
65
            "MIDI IN Overrun Error", // B
66
            "MIDI IN Frame Error", // C
67
            "Unknown Query", // D
68
            "Invalid SysEx command" // E
69
    };
70
 
71
    public MIOSSysexSendReceive(Receiver receiver) {
72
        super();
73
        this.receiver = receiver;
74
        messages = new LinkedList();
75
    }
76
 
77
    public int getDeviceID() {
78
        return deviceID;
79
    }
80
 
81
    public void setDeviceID(int deviceID) {
82
        this.deviceID = deviceID;
83
 
84
        setChanged();
85
        notifyObservers(DEVICE_ID);
86
        clearChanged();
87
    }
88
 
89
    public boolean getMIOS32_Mode() {
90
        return this.MIOS32_Mode;
91
    }
92
 
93
    public void setMIOS32_Mode(boolean enabled) {
94
        this.MIOS32_Mode = enabled;
95
 
96
        setChanged();
97
        notifyObservers(MIOS32_MODE);
98
        clearChanged();
99
    }
100
 
101
    public byte getMIOS_SysExId() {
102
        return (byte) (MIOS32_Mode ? 0x32 : 0x40); // MIOS32/MIOS8
103
    }
104
 
105
    public Receiver getReceiver() {
106
        return receiver;
107
    }
108
 
109
    protected void createWorker() {
110
 
111
        setChanged();
112
        notifyObservers(WORKER);
113
        clearChanged();
114
    }
115
 
116
    public void addMessage(String message) {
117
 
118
        messages.addLast(message);
119
 
120
        setChanged();
121
        notifyObservers(MESSAGES);
122
        clearChanged();
123
    }
124
 
125
    public LinkedList getMessages() {
126
        return messages;
127
    }
128
 
129
    public void send(MidiMessage message, long timestamp) {
130
        if (!isCancelled() && !isDone()) {
131
            decodeMessage(message, timestamp);
132
        }
133
    }
134
 
135
    public void close() {
136
 
137
    }
138
 
139
    protected byte axExpectedHeader[] = new byte[] { (byte) 0x00, (byte) 0x00,
140
            (byte) 0x7E, (byte) 0x40, (byte) (deviceID & 0x7F) }; // Note:
141
 
142
    // 0x40 will
143
    // be
144
    // changed
145
    // to 0x32
146
    // if
147
    // MIOS32_Mode
148
 
149
    public boolean isDone() {
150
        return done;
151
    }
152
 
153
    public boolean isCancelled() {
154
        return cancelled;
155
    }
156
 
157
    public void cancel() {
158
        synchronized (this) {
159
            cancelled = true;
160
            addMessage("Process stopped by user");
161
            notify(); // TK: finally the reason why threads where not informed
162
            // about a cancel request and mixed the upload blocks!
163
        }
164
    }
165
 
166
    public void decodeMessage(MidiMessage message, long timestamp) {
167
        if (message instanceof SysexMessage) {
168
 
169
            SysexMessage sysExMessage = (SysexMessage) message;
170
 
171
            byte[] axSysExData = sysExMessage.getData();
172
 
173
            axExpectedHeader[3] = getMIOS_SysExId();
174
            axExpectedHeader[4] = (byte) (deviceID & 0x7F);
175
 
176
            if ((axSysExData.length + 1) >= 8) {
177
                boolean bValid = true;
178
                if (sysExMessage.getStatus() == SysexMessage.SYSTEM_EXCLUSIVE) {
179
                    for (int n = 0; n < axExpectedHeader.length; n++) {
180
                        if (axSysExData[n] != axExpectedHeader[n]) {
181
                            bValid = false;
182
                            break;
183
                        }
184
                    }
185
 
186
                    // bValid is true if message header matches expected.
187
                    if (bValid) {
188
                        if (axSysExData[5] == 0x01) {
189
                            // Received "read" command
190
                            receivedRead(axSysExData);
191
                        } else if (axSysExData[5] == 0x02) {
192
                            // Received "write" command, probably from MIDI
193
                            // loopback cable or MIDI Yoke
194
                            receivedWrite(axSysExData);
195
                        } else if (axSysExData[5] == 0x03) {
196
                            // Received "select bankstick" command, probably
197
                            // from MIDI loopback cable or MIDI Yoke
198
                            receivedSelectBankstick(axSysExData);
199
                        } else if (axSysExData[5] == 0x08) {
200
                            // Received "lcd" command, probably from MIDI
201
                            // loopback cable or MIDI Yoke
202
                            receivedLCDCommand(axSysExData);
203
                        } else if (axSysExData[5] == 0x0D) {
204
                            // Received "debug" command, probably from MIDI
205
                            // loopback cable or MIDI Yoke
206
                            receivedDebugCommand(axSysExData);
207
                        } else if (axSysExData[5] == 0x0E) {
208
                            receivedErrorCode(axSysExData);
209
                        } else if (axSysExData[5] == 0x0F) {
210
                            receivedReturnValues(axSysExData);
211
                        } else {
212
                            receivedUnknownMIOSType(axSysExData);
213
                        }
214
                    } else {
215
                        receivedUnknownSysex(axSysExData);
216
                    }
217
                } else if (sysExMessage.getStatus() == SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE) {
218
                    // "Continued" SysEx message, currently unhandled.
219
                    receivedContinuedSysex(axSysExData);
220
                }
221
            } else {
222
                receivedSysexMessageLessThan8Bytes(axSysExData);
223
            }
224
        } else {
225
            // _progressMessages.addLast( "Received non-SysEx message" );
226
        }
227
    }
228
 
229
    protected void receivedRead(byte[] data) {
230
 
231
    }
232
 
233
    protected void receivedWrite(byte[] data) {
234
 
235
    }
236
 
237
    protected void receivedSelectBankstick(byte[] data) {
238
 
239
    }
240
 
241
    protected void receivedLCDCommand(byte[] data) {
242
 
243
    }
244
 
245
    protected void receivedDebugCommand(byte[] data) {
246
 
247
    }
248
 
249
    protected void receivedContinuedSysex(byte[] data) {
250
        addMessage("Received 'continued' SysEx message");
251
    }
252
 
253
    protected void receivedErrorCode(byte[] data) {
254
        int errorCode = data[6] - 1;
255
        if (errorCode >= _errorCodes.length) {
256
            addMessage("Received error code " + Utils.byteToHex(data[6])
257
                    + " (unknown)");
258
        } else {
259
            addMessage("Received error code " + Utils.byteToHex(data[6]) + ": "
260
                    + _errorCodes[errorCode]);
261
        }
262
    }
263
 
264
    protected void receivedReturnValues(byte[] data) {
265
        addMessage("Received acknowledgement response");
266
    }
267
 
268
    protected void receivedUnknownMIOSType(byte[] data) {
269
        addMessage("Received MIOS SysEx message of unknown type '"
270
                + Utils.bytesToString(data) + "'");
271
    }
272
 
273
    protected void receivedUnknownSysex(byte[] data) {
274
        addMessage("Received unexpected MIOS SysEx message = "
275
                + Utils.bytesToString(data) + "  expected = "
276
                + Utils.bytesToString(axExpectedHeader));
277
    }
278
 
279
    protected void receivedSysexMessageLessThan8Bytes(byte[] data) {
280
        addMessage("Received SysEx message of less than 8 bytes");
281
    }
282
 
283
}