Subversion Repositories svn.mios

Rev

Rev 693 | Rev 723 | Go to most recent revision | Details | Compare with Previous | 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
 
721 adamjking 46
    protected boolean mios32Mode;
628 adamjking 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
 
721 adamjking 89
    public boolean isMIOS32Mode() {
90
        return this.mios32Mode;
628 adamjking 91
    }
92
 
721 adamjking 93
    public void setMIOS32Mode(boolean enabled) {
94
        this.mios32Mode = enabled;
628 adamjking 95
 
96
        setChanged();
97
        notifyObservers(MIOS32_MODE);
98
        clearChanged();
99
    }
100
 
101
    public byte getMIOS_SysExId() {
721 adamjking 102
        return (byte) (mios32Mode ? 0x32 : 0x40); // MIOS32/MIOS8
628 adamjking 103
    }
104
 
105
    public Receiver getReceiver() {
106
        return receiver;
107
    }
108
 
109
    public void addMessage(String message) {
110
 
111
        messages.addLast(message);
693 adamjking 112
 
628 adamjking 113
        setChanged();
114
        notifyObservers(MESSAGES);
115
        clearChanged();
116
    }
117
 
118
    public LinkedList getMessages() {
119
        return messages;
120
    }
121
 
122
    public void send(MidiMessage message, long timestamp) {
123
        if (!isCancelled() && !isDone()) {
124
            decodeMessage(message, timestamp);
125
        }
126
    }
127
 
128
    public void close() {
129
 
130
    }
131
 
132
    protected byte axExpectedHeader[] = new byte[] { (byte) 0x00, (byte) 0x00,
133
            (byte) 0x7E, (byte) 0x40, (byte) (deviceID & 0x7F) }; // Note:
134
 
135
    // 0x40 will
136
    // be
137
    // changed
138
    // to 0x32
139
    // if
140
    // MIOS32_Mode
141
 
142
    public boolean isDone() {
143
        return done;
144
    }
145
 
146
    public boolean isCancelled() {
147
        return cancelled;
148
    }
149
 
150
    public void cancel() {
151
        synchronized (this) {
152
            cancelled = true;
153
            addMessage("Process stopped by user");
154
            notify(); // TK: finally the reason why threads where not informed
155
            // about a cancel request and mixed the upload blocks!
156
        }
157
    }
158
 
159
    public void decodeMessage(MidiMessage message, long timestamp) {
160
        if (message instanceof SysexMessage) {
161
 
162
            SysexMessage sysExMessage = (SysexMessage) message;
163
 
164
            byte[] axSysExData = sysExMessage.getData();
165
 
166
            axExpectedHeader[3] = getMIOS_SysExId();
167
            axExpectedHeader[4] = (byte) (deviceID & 0x7F);
168
 
169
            if ((axSysExData.length + 1) >= 8) {
170
                boolean bValid = true;
171
                if (sysExMessage.getStatus() == SysexMessage.SYSTEM_EXCLUSIVE) {
172
                    for (int n = 0; n < axExpectedHeader.length; n++) {
173
                        if (axSysExData[n] != axExpectedHeader[n]) {
174
                            bValid = false;
175
                            break;
176
                        }
177
                    }
178
 
179
                    // bValid is true if message header matches expected.
180
                    if (bValid) {
181
                        if (axSysExData[5] == 0x01) {
182
                            // Received "read" command
183
                            receivedRead(axSysExData);
184
                        } else if (axSysExData[5] == 0x02) {
185
                            // Received "write" command, probably from MIDI
186
                            // loopback cable or MIDI Yoke
187
                            receivedWrite(axSysExData);
188
                        } else if (axSysExData[5] == 0x03) {
189
                            // Received "select bankstick" command, probably
190
                            // from MIDI loopback cable or MIDI Yoke
191
                            receivedSelectBankstick(axSysExData);
192
                        } else if (axSysExData[5] == 0x08) {
193
                            // Received "lcd" command, probably from MIDI
194
                            // loopback cable or MIDI Yoke
195
                            receivedLCDCommand(axSysExData);
196
                        } else if (axSysExData[5] == 0x0D) {
197
                            // Received "debug" command, probably from MIDI
198
                            // loopback cable or MIDI Yoke
199
                            receivedDebugCommand(axSysExData);
200
                        } else if (axSysExData[5] == 0x0E) {
201
                            receivedErrorCode(axSysExData);
202
                        } else if (axSysExData[5] == 0x0F) {
203
                            receivedReturnValues(axSysExData);
204
                        } else {
205
                            receivedUnknownMIOSType(axSysExData);
206
                        }
207
                    } else {
208
                        receivedUnknownSysex(axSysExData);
209
                    }
210
                } else if (sysExMessage.getStatus() == SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE) {
211
                    // "Continued" SysEx message, currently unhandled.
212
                    receivedContinuedSysex(axSysExData);
213
                }
214
            } else {
215
                receivedSysexMessageLessThan8Bytes(axSysExData);
216
            }
217
        } else {
218
            // _progressMessages.addLast( "Received non-SysEx message" );
219
        }
220
    }
221
 
222
    protected void receivedRead(byte[] data) {
223
 
224
    }
225
 
226
    protected void receivedWrite(byte[] data) {
227
 
228
    }
229
 
230
    protected void receivedSelectBankstick(byte[] data) {
231
 
232
    }
233
 
234
    protected void receivedLCDCommand(byte[] data) {
235
 
236
    }
237
 
238
    protected void receivedDebugCommand(byte[] data) {
239
 
240
    }
241
 
242
    protected void receivedContinuedSysex(byte[] data) {
243
        addMessage("Received 'continued' SysEx message");
244
    }
245
 
246
    protected void receivedErrorCode(byte[] data) {
247
        int errorCode = data[6] - 1;
248
        if (errorCode >= _errorCodes.length) {
249
            addMessage("Received error code " + Utils.byteToHex(data[6])
250
                    + " (unknown)");
251
        } else {
252
            addMessage("Received error code " + Utils.byteToHex(data[6]) + ": "
253
                    + _errorCodes[errorCode]);
254
        }
255
    }
256
 
257
    protected void receivedReturnValues(byte[] data) {
258
        addMessage("Received acknowledgement response");
259
    }
260
 
261
    protected void receivedUnknownMIOSType(byte[] data) {
262
        addMessage("Received MIOS SysEx message of unknown type '"
263
                + Utils.bytesToString(data) + "'");
264
    }
265
 
266
    protected void receivedUnknownSysex(byte[] data) {
267
        addMessage("Received unexpected MIOS SysEx message = "
268
                + Utils.bytesToString(data) + "  expected = "
269
                + Utils.bytesToString(axExpectedHeader));
270
    }
271
 
272
    protected void receivedSysexMessageLessThan8Bytes(byte[] data) {
273
        addMessage("Received SysEx message of less than 8 bytes");
274
    }
275
 
276
}