Skip to content

Commit

Permalink
update from main
Browse files Browse the repository at this point in the history
  • Loading branch information
codefrau committed Mar 25, 2024
1 parent 35762ef commit ea3b37a
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 39 deletions.
5 changes: 3 additions & 2 deletions run/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<script type="module" src="../squeak.js"></script>
<script>
function runSqueak(imageName) {
// Squeak.debugFiles = true;
sqText.style.display = "none";
sqCanvas.style.display = "block";
SqueakJS.runSqueak(imageName, sqCanvas,{
Expand Down Expand Up @@ -230,9 +231,9 @@ <h2>Run Squeak images from the internet</h2>
<li>Squeak 5.0 (2015) <a href="#url=https://freudenbergs.de/vanessa/squeakjs&zip=[Squeak5.0-15113.zip,SqueakV50.sources.zip]">link</a></li>
<li>SpeechPlugin Demo (2016) <a href="#zip=https://www.hpi.uni-potsdam.de/hirschfeld/artefacts/squeakjs/SpeechPluginDemo.zip">link</a></li>
<li>Squeak 6.0 64 bit (2022) <a href="#zip=https://files.squeak.org/6.0/Squeak6.0-22104-64bit/Squeak6.0-22104-64bit.zip">link</a></li>
<li>Cuis 6.2 (2023) <a href="#highdpi=true&url=https://cdn.jsdelivr.net/gh/Cuis-Smalltalk/Cuis6-2@6f984e8c/CuisImage&files=[32BitImages/Cuis6.2-32.image,32BitImages/Cuis6.2-32.changes,Cuis6.2.sources]">link</a></li>
<li>Cuis 6.2 (2023) <a href="#highdpi&url=https://cdn.jsdelivr.net/gh/Cuis-Smalltalk/Cuis6-2@6f984e8c/CuisImage&files=[32BitImages/Cuis6.2-32.image,32BitImages/Cuis6.2-32.changes,Cuis6.2.sources]">link</a></li>
<li>Squeak Trunk 6.1α (2024) <a href="#zip=https://files.squeak.org/6.1alpha/Squeak6.1alpha-22998-32bit/Squeak6.1alpha-22998-32bit.zip">link</a></li>
<li>Squeak Trunk 6.1α (hi-res: save image after first load for faster startup) <a href="#highdpi=true&zip=https://files.squeak.org/6.1alpha/Squeak6.1alpha-22998-32bit/Squeak6.1alpha-22998-32bit.zip">link</a></li>
<li>Squeak Trunk 6.1α (hi-res: save image after first load for faster startup) <a href="#highdpi&zip=https://files.squeak.org/6.1alpha/Squeak6.1alpha-22998-32bit/Squeak6.1alpha-22998-32bit.zip">link</a></li>
</ul>
On the first run these will be stored locally. Subsequent starts are much faster since there is no download.

Expand Down
78 changes: 41 additions & 37 deletions squeak.js
Original file line number Diff line number Diff line change
Expand Up @@ -38738,6 +38738,7 @@
vmProxy: null,
vm: null,
prims: null,
timeOffset: 0,
midi: null, // WebMIDI access or false if not supported
midiPromise: null,
ports: new Map(), // indexed by Squeak port number
Expand Down Expand Up @@ -38770,6 +38771,7 @@
this.midi = false;
});
}
if (performance.timeOrigin) this.timeOffset = performance.timeOrigin - this.vm.startupTime;
},
initMIDI(access) {
const allPorts = [...access.inputs.values(), ...access.outputs.values()];
Expand All @@ -38794,9 +38796,6 @@
console.log(`MIDIPlugin: port ${portNumber} ${dir} (${names.join(', ')})`);
}
},
clock() {
return performance.now() & Squeak.MaxSmallInt;
},
portChanged(port) {
// Squeak likes combined input/output ports so we create sqPorts with input+output here
let { name, manufacturer } = port;
Expand All @@ -38820,22 +38819,24 @@
input: null,
output: null,
runningStatus: 0,
receivedData: [],
receivedMessages: [],
};
this.ports.set(handle, sqPort);
}
// update port
sqPort[port.type] = port;
sqPort.dir |= port.type === 'input' ? 1 : 2; // 1=input, 2=output, 3=input+output
// dir: 1=input, 2=output, 3=input+output
if (port.state === "connected") {
sqPort[port.type] = port;
sqPort.dir |= port.type === 'input' ? 1 : 2;
} else {
sqPort[port.type] = null;
sqPort.dir &= port.type === 'input' ? ~1 : ~2;
}
return sqPort;
},
primitiveMIDIGetPortCount(argCount) {
// we rely on this primitive to be called first
// so the other primitives can be synchronous
const returnCount = () => {
const count = this.midi ? this.midi.outputs.size : 0;
return this.vm.popNandPush(argCount + 1, count);
};
const returnCount = () => this.vm.popNandPush(argCount + 1, this.ports.size);
if (this.midi === null) {
const unfreeze = this.vm.freeze();
this.midiPromise
Expand All @@ -38855,7 +38856,9 @@
const portNumber = this.prims.stackInteger(0);
const port = this.ports.get(portNumber);
if (!port) return false;
return this.prims.popNandPushIfOK(argCount + 1, this.prims.makeStString(port.name));
let name = port.name;
if (port.dir === 0) name += ' [disconnected]';
return this.prims.popNandPushIfOK(argCount + 1, this.prims.makeStString(name));
},
primitiveMIDIGetPortDirectionality(argCount) {
if (!this.midi) return false;
Expand All @@ -38866,7 +38869,8 @@
},
primitiveMIDIGetClock(argCount) {
if (!this.midi) return false;
return this.prims.popNandPushIfOK(argCount + 1, this.clock());
const clock = this.prims.millisecondClockValue();
return this.prims.popNandPushIfOK(argCount + 1, clock);
},
primitiveMIDIParameterGetOrSet(argCount) {
if (!this.midi) return false;
Expand Down Expand Up @@ -38902,7 +38906,11 @@
let port;
const checkPort = () => {
port = this.ports.get(portNumber);
if (!port) console.error('MIDIPlugin: invalid port ' + portNumber);
if (!port) console.error(`MIDIPlugin: invalid port ${portNumber}`);
else if (!port.dir) {
console.error(`MIDIPlugin: port ${portNumber} ${port.name} is disconnected`);
port = null;
}
};
const openPort = unfreeze => {
const promises = []; // wait for MIDI initialization first
Expand All @@ -38913,12 +38921,14 @@
if (port.output.connection === "closed") promises.push(port.output.open());
else console.warn(`MIDIPlugin: output port ${portNumber} is ${port.output.connection}`);
port.runningStatus = 0;
port.receivedData = [];
port.receivedMessages = [];
Promise.all(promises)
.then(() => {
if (port.input) port.input.onmidimessage = event => {
port.receivedData.push(event.data);
if (this.debug) console.log('MIDIPlugin: received', event.data);
const time = Math.round(event.timeStamp + this.timeOffset);
const bytes = new Uint8Array(event.data);
port.receivedMessages.push({time, bytes});
if (this.debug) console.log('MIDIPlugin: received', time, [...bytes]);
};
})
.catch(err => console.error('MIDIPlugin: ' + err))
Expand Down Expand Up @@ -38949,7 +38959,7 @@
if (port.input && port.input.connection === 'open') {
promises.push(port.input.close());
port.input.onmidimessage = null;
port.receivedData.length = 0;
port.receivedMessages.length = 0;
}
if (port.output && port.output.connection === 'open') {
promises.push(port.output.close());
Expand Down Expand Up @@ -38988,16 +38998,14 @@
data = newData;
}
try {
if (this.debug) console.log('MIDIPlugin: send', data, timestamp);
if (this.debug) console.log('MIDIPlugin: send', [...data], timestamp);
// send or schedule data
if (timestamp === 0) port.output.send(data);
else port.output.send(data, timestamp);
// find last status byte in data, but ignore real-time messages (0xF8-0xFF)
// system common messages (0xF0-0xF7) reset the running status
for (let i = data.length-3; i >= 0; i-=2) {
if (data[i] < 0x80) continue; // skip data bytes
if (data[i] >= 0xF8) i -= 1; // skip real-time message
else {
for (let i = data.length - 1; i >= 0; i--) {
if (data[i] >= 0x80 && data[i] <= 0xF7) {
port.runningStatus = data[i] < 0xF0 ? data[i] : 0;
break;
}
Expand All @@ -39015,21 +39023,17 @@
const port = this.ports.get(portNumber);
if (!port || !port.input || port.input.connection !== 'open') return false;
let received = 0;
let chunk = port.receivedData.shift();
while (chunk && received < data.length) {
const free = data.length - received;
if (chunk.length <= free) {
data.set(chunk, received);
received += chunk.length;
chunk = port.receivedData.shift();
} else {
data.set(chunk.subarray(0, free), received);
received += free;
port.receivedData.unshift(chunk.subarray(free));
chunk = null;
}
const event = port.receivedMessages.shift();
if (event) {
let { time, bytes } = event;
data[0] = (time >> 24) & 0xFF;
data[1] = (time >> 16) & 0xFF;
data[2] = (time >> 8) & 0xFF;
data[3] = time & 0xFF;
data.set(bytes, 4);
received = bytes.length + 4;
if (this.debug) console.log('MIDIPlugin: read', received, [...data.subarray(0, received)]);
}
if (this.debug) console.log('MIDIPlugin: read', received, data.subarray(0, received));
return this.prims.popNandPushIfOK(argCount + 1, received);
},
};
Expand Down

0 comments on commit ea3b37a

Please sign in to comment.