Subversion Repositories svn.mios

Rev

Rev 846 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
628 adamjking 1
/*
2
 * @(#)SysexSendReceive.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.midi;
22
 
23
import java.io.File;
846 tk 24
import java.io.FileOutputStream;
25
import java.io.OutputStream;
628 adamjking 26
import java.util.LinkedList;
27
import java.util.Observable;
28
 
845 tk 29
import javax.sound.midi.InvalidMidiDataException;
628 adamjking 30
import javax.sound.midi.MidiMessage;
31
import javax.sound.midi.Receiver;
32
import javax.sound.midi.SysexMessage;
33
 
34
public class SysexSendReceive extends Observable implements Receiver {
35
 
845 tk 36
    public final static Object WORKER = new Object();
37
 
850 adamjking 38
    public final static Object SEND_SYSEX_FILE = new Object();
39
 
40
    public final static Object RECEIVE_SYSEX_FILE = new Object();
41
 
42
    public final static Object SEND_DELAY_TIME = new Object();
43
 
44
    public final static Object RECEIVED_BYTES = new Object();
45
 
628 adamjking 46
    protected Receiver receiver;
47
 
846 tk 48
    protected File sendFile;
49
    protected long sendFileLastModified;
628 adamjking 50
 
846 tk 51
    protected File receiveFile;
628 adamjking 52
 
53
    protected SysexFile sysexFile;
54
 
55
    protected int sendBufferSize;
56
 
845 tk 57
    protected int sendDelayTime;
58
 
628 adamjking 59
    protected LinkedList receivedBytes;
60
 
846 tk 61
    protected boolean sendDone = true;
62
    protected boolean sendCancelled = true;
845 tk 63
 
846 tk 64
    protected boolean receiveStopped = true;
845 tk 65
 
628 adamjking 66
    public SysexSendReceive(Receiver receiver) {
67
        super();
68
        this.receiver = receiver;
850 adamjking 69
        sendBufferSize = 100000; // TK: shouldn't be changed by user since Java
70
                                    // doesn't allow to split SysEx streams
71
                                    // properly
845 tk 72
        sendDelayTime = 750; // delay between F0
628 adamjking 73
        receivedBytes = new LinkedList();
74
    }
75
 
846 tk 76
    public File getSendFile() {
77
        return sendFile;
628 adamjking 78
    }
79
 
846 tk 80
    public boolean sendFileChanged() {
81
        return sendFile.lastModified() != sendFileLastModified;
628 adamjking 82
    }
83
 
846 tk 84
    public void setSendFile(File file) {
850 adamjking 85
 
846 tk 86
        this.sendFile = file;
850 adamjking 87
 
846 tk 88
        sendFileLastModified = sendFile.lastModified();
628 adamjking 89
 
90
        readSysexFile();
91
 
92
        setChanged();
850 adamjking 93
        notifyObservers(SEND_SYSEX_FILE);
628 adamjking 94
        clearChanged();
95
    }
96
 
97
    public void readSysexFile() {
98
        sysexFile = new SysexFile();
846 tk 99
        if (!sysexFile.read(sendFile.getPath())) {
628 adamjking 100
            // TODO
101
        }
102
    }
103
 
846 tk 104
    public File getReceiveFile() {
105
        return receiveFile;
106
    }
107
 
108
    public void setReceiveFile(File file) {
850 adamjking 109
 
846 tk 110
        this.receiveFile = file;
111
 
112
        setChanged();
850 adamjking 113
        notifyObservers(RECEIVE_SYSEX_FILE);
846 tk 114
        clearChanged();
115
    }
116
 
628 adamjking 117
    public SysexFile getSysexFile() {
118
        return sysexFile;
119
    }
120
 
121
    public int getSendBufferSize() {
122
        return sendBufferSize;
123
    }
124
 
845 tk 125
    public int getSendDelayTime() {
126
        return sendDelayTime;
628 adamjking 127
    }
128
 
845 tk 129
    public void setSendDelayTime(int sendDelayTime) {
850 adamjking 130
 
845 tk 131
        this.sendDelayTime = sendDelayTime;
850 adamjking 132
 
133
        setChanged();
134
        notifyObservers(SEND_DELAY_TIME);
135
        clearChanged();
845 tk 136
    }
137
 
628 adamjking 138
    public LinkedList getReceivedBytes() {
139
        return receivedBytes;
140
    }
850 adamjking 141
 
846 tk 142
    public void clearReceivedBytes() {
143
        receivedBytes.clear();
144
    }
628 adamjking 145
 
846 tk 146
    public boolean writeSysexFile(File file, byte[] data, int dataLen) {
147
        // could also be located in SysexFile.java?
845 tk 148
 
846 tk 149
        try {
150
            OutputStream os = new FileOutputStream(file);
151
            os.write(data, 0, dataLen);
152
            os.close();
850 adamjking 153
        } catch (Exception e) {
846 tk 154
            return false;
155
        }
156
 
157
        return true;
845 tk 158
    }
159
 
846 tk 160
    public boolean isSendDone() {
161
        return sendDone;
845 tk 162
    }
163
 
846 tk 164
    public boolean isSendCancelled() {
165
        return sendCancelled;
166
    }
167
 
168
    public void sendCancel() {
845 tk 169
        synchronized (this) {
846 tk 170
            sendCancelled = true;
850 adamjking 171
            // addMessage("Process stopped by user");
845 tk 172
            notify(); // TK: finally the reason why threads where not informed
173
            // about a cancel request and mixed the upload blocks!
628 adamjking 174
        }
175
    }
176
 
846 tk 177
    public boolean isReceiveStopped() {
178
        return receiveStopped;
179
    }
845 tk 180
 
850 adamjking 181
    public void setReceiveStopped(boolean receiveStopped) {
846 tk 182
        this.receiveStopped = receiveStopped;
183
    }
184
 
628 adamjking 185
    public void close() {
186
 
187
    }
188
 
808 adamjking 189
    public void setReceiver(Receiver receiver) {
190
        this.receiver = receiver;
191
    }
192
 
845 tk 193
    public void send(MidiMessage message, long timestamp) {
846 tk 194
        if (!isReceiveStopped()) {
845 tk 195
            if (message instanceof SysexMessage) {
196
                receivedBytes.add(((SysexMessage) message).getData());
197
 
198
                setChanged();
850 adamjking 199
                notifyObservers(RECEIVED_BYTES);
845 tk 200
                clearChanged();
201
            }
202
        }
203
    }
204
 
850 adamjking 205
    // ///////////////////////////////////////////////////////////////////////////////
845 tk 206
    // SysEx File Sender Functions
850 adamjking 207
    // ///////////////////////////////////////////////////////////////////////////////
845 tk 208
 
209
    public void startSend(byte[] sysexData, int sysexDataLen) {
210
        int offset = 0;
211
 
846 tk 212
        sendCancelled = false;
213
        sendDone = false;
845 tk 214
 
215
        synchronized (this) {
216
 
850 adamjking 217
            while (!sendCancelled && !sendDone && offset < sysexDataLen) {
845 tk 218
                int sendLen = 1;
219
                int i;
220
 
221
                // update GUI
222
                setChanged();
223
                notifyObservers(WORKER);
224
                clearChanged();
225
 
850 adamjking 226
                for (i = 1; i < sendBufferSize && (i + offset) < sysexDataLen
227
                        && sysexData[i + offset] != (byte) 0xf0; ++i) {
845 tk 228
                    ++sendLen;
229
                }
230
 
850 adamjking 231
                if (sendLen == 0) {
846 tk 232
                    sendDone = true;
845 tk 233
                    break;
234
                }
235
 
236
                byte[] axSysExData = new byte[sendLen];
237
                System.arraycopy(sysexData, offset, axSysExData, 0, sendLen);
238
 
239
                try {
240
                    SysexMessage sysExMessage = new SysexMessage();
241
                    sysExMessage.setMessage(axSysExData, axSysExData.length);
242
                    receiver.send(sysExMessage, -1);
243
                } catch (InvalidMidiDataException ex) {
846 tk 244
                    sendCancelled = true;
845 tk 245
                    System.out.println("Error: " + ex.getMessage());
246
                    break;
247
                }
248
 
249
                offset += sendLen;
250
 
850 adamjking 251
                if (offset < sysexDataLen) {
845 tk 252
                    try {
253
                        wait(sendDelayTime);
254
                    } catch (InterruptedException e) {
846 tk 255
                        sendCancelled = true;
845 tk 256
                        System.out.println("Error: SysEx task interrupted");
257
                        break;
258
                    }
259
                } else {
846 tk 260
                    sendDone = true;
845 tk 261
                }
262
            }
263
        }
264
 
265
        // update GUI
266
        setChanged();
267
        notifyObservers(WORKER);
268
        clearChanged();
269
    }
628 adamjking 270
}