diff --git a/src/GameManager.js b/src/GameManager.js
index 0d59ca8..e34645b 100644
--- a/src/GameManager.js
+++ b/src/GameManager.js
@@ -17,7 +17,8 @@ class EJS_GameManager {
toggleShader: this.Module.cwrap('shader_enable', 'null', ['number']),
getDiskCount: this.Module.cwrap('get_disk_count', 'number', []),
getCurrentDisk: this.Module.cwrap('get_current_disk', 'number', []),
- setCurrentDisk: this.Module.cwrap('set_current_disk', 'null', ['number'])
+ setCurrentDisk: this.Module.cwrap('set_current_disk', 'null', ['number']),
+ setVolume: this.Module.cwrap('set_volume', 'null', ['number'])
}
this.mkdir("/home");
this.mkdir("/home/web_user");
@@ -134,6 +135,9 @@ class EJS_GameManager {
setCurrentDisk(disk) {
this.functions.setCurrentDisk(disk);
}
+ setVolume(volume) {
+ this.functions.setVolume(volume);
+ }
}
window.EJS_GameManager = EJS_GameManager;
diff --git a/src/css/main.css b/src/css/main.css
index a4333f6..1e5d620 100644
--- a/src/css/main.css
+++ b/src/css/main.css
@@ -951,3 +951,135 @@
right: .025rem;
border: 0;
}
+
+.ejs_volume_parent {
+ padding-right: 15px;
+ max-width: 110px;
+ align-items: center;
+ display: flex;
+ flex: 1;
+ position: relative;
+}
+.ejs_volume_parent::-webkit-media-controls{
+ display: none;
+}
+.ejs_volume_parent input[type='range']{
+ -webkit-appearance:none;
+ border:0;
+ border-radius:28px;
+ color:rgba(var(--ejs-primary-color), 1);
+ display:block;
+ margin:0;
+ padding:0;
+ transition:box-shadow 0.3s ease;
+ width:100%
+}
+.ejs_volume_parent input[type='range']::-webkit-slider-runnable-track{
+ background-color:rgba(255,255,255,0.25)
+ box-shadow:0 0 0 5px rgba(var(--ejs-primary-color), 0.5);
+ outline:0
+ background:transparent;
+ border:0;
+ border-radius:3px;
+ height:6px;
+ transition:box-shadow 0.3s ease;
+ user-select:none;
+ background-image:linear-gradient(to right, currentColor var(--value, 0%), transparent var(--value, 0%))
+}
+.ejs_volume_parent input[type='range']::-webkit-slider-thumb{
+ background:#fff;
+ border:0;
+ border-radius:100%;
+ box-shadow:0 1px 1px rgba(0,0,0,0.15),0 0 0 1px rgba(47,52,61,0.2);
+ height:14px;
+ position:relative;
+ transition:all 0.2s ease;
+ width:14px;
+ -webkit-appearance:none;
+ margin-top:-4px
+}
+.ejs_volume_parent input[type='range']::-moz-range-track{
+ background-color:rgba(255,255,255,0.25)
+ box-shadow:0 0 0 5px rgba(var(--ejs-primary-color), 0.5);
+ outline:0
+ background:transparent;
+ border:0;
+ border-radius:3px;
+ height:6px;
+ transition:box-shadow 0.3s ease;
+ user-select:none
+}
+.ejs_volume_parent input[type='range']::-moz-range-thumb{
+ background:#fff;
+ border:0;
+ border-radius:100%;
+ box-shadow:0 1px 1px rgba(0,0,0,0.15),0 0 0 1px rgba(47,52,61,0.2);
+ height:14px;
+ position:relative;
+ transition:all 0.2s ease;
+ width:14px
+}
+.ejs_volume_parent input[type='range']::-moz-range-progress{
+ background:currentColor;
+ border-radius:3px;
+ height:6px
+}
+.ejs_volume_parent input[type='range']::-ms-track{
+ background-color:rgba(255,255,255,0.25)
+ box-shadow:0 0 0 5px rgba(var(--ejs-primary-color), 0.5);
+ outline:0
+ background:transparent;
+ border:0;
+ border-radius:3px;
+ height:6px;
+ transition:box-shadow 0.3s ease;
+ user-select:none;
+ color:transparent
+}
+.ejs_volume_parent input[type='range']::-ms-fill-upper{
+ background:transparent;
+ border:0;
+ border-radius:3px;
+ height:6px;
+ transition:box-shadow 0.3s ease;
+ user-select:none
+}
+.ejs_volume_parent input[type='range']::-ms-fill-lower{
+ background:transparent;
+ border:0;
+ border-radius:3px;
+ height:6px;
+ transition:box-shadow 0.3s ease;
+ user-select:none;
+ background:currentColor
+}
+.ejs_volume_parent input[type='range']::-ms-thumb{
+ background:#fff;
+ border:0;
+ border-radius:100%;
+ box-shadow:0 1px 1px rgba(0,0,0,0.15),0 0 0 1px rgba(47,52,61,0.2);
+ height:14px;
+ position:relative;
+ transition:all 0.2s ease;
+ width:14px;
+ margin-top:0
+}
+.ejs_volume_parent input[type='range']::-ms-tooltip{
+ display:none
+}
+.ejs_volume_parent input[type='range']:focus{
+ outline:0
+}
+.ejs_volume_parent input[type='range']::-moz-focus-outer{
+ border:0
+}
+
+.ejs_volume_parent input[type='range']:active::-webkit-slider-thumb {
+ box-shadow:0 1px 1px rgba(0,0,0,0.15),0 0 0 1px rgba(47,52,61,0.2),0 0 0 3px rgba(255,255,255,0.5)
+}
+.ejs_volume_parent input[type='range']:active::-moz-range-thumb {
+ box-shadow:0 1px 1px rgba(0,0,0,0.15),0 0 0 1px rgba(47,52,61,0.2),0 0 0 3px rgba(255,255,255,0.5)
+}
+.ejs_volume_parent input[type='range']:active::-ms-thumb {
+ box-shadow:0 1px 1px rgba(0,0,0,0.15),0 0 0 1px rgba(47,52,61,0.2),0 0 0 3px rgba(255,255,255,0.5)
+}
diff --git a/src/emulator.js b/src/emulator.js
index 0ab4e34..7f402ee 100644
--- a/src/emulator.js
+++ b/src/emulator.js
@@ -154,6 +154,8 @@ class EmulatorJS {
this.debug = (window.EJS_DEBUG_XX === true);
this.cheats = [];
this.started = false;
+ this.volume = 0.5;
+ this.muted = false;
this.paused = true;
this.listeners = [];
this.config = config;
@@ -636,6 +638,7 @@ class EmulatorJS {
this.handleResize();
this.updateCheatUI();
this.updateGamepadLabels();
+ this.setVolume(this.volume);
this.elements.parent.focus();
this.callEvent("start");
}
@@ -925,6 +928,60 @@ class EmulatorJS {
spacer.style = "flex:1;";
this.elements.menu.appendChild(spacer);
+ const volumeSettings = this.createElement("div");
+ volumeSettings.classList.add("ejs_volume_parent");
+ const muteButton = addButton("Mute", '', () => {
+ muteButton.style.display = "none";
+ unmuteButton.style.display = "";
+ this.muted = true;
+ this.setVolume(0);
+ }, volumeSettings);
+ const unmuteButton = addButton("Unmute", '', () => {
+ muteButton.style.display = "";
+ unmuteButton.style.display = "none";
+ this.muted = false;
+ this.setVolume(this.volume);
+ }, volumeSettings);
+ unmuteButton.style.display = "none";
+
+ const volumeSlider = this.createElement("input");
+ volumeSlider.setAttribute("data-range", "volume");
+ volumeSlider.setAttribute("type", "range");
+ volumeSlider.setAttribute("min", 0);
+ volumeSlider.setAttribute("max", 1);
+ volumeSlider.setAttribute("step", 0.01);
+ volumeSlider.setAttribute("autocomplete", "off");
+ volumeSlider.setAttribute("role", "slider");
+ volumeSlider.setAttribute("aria-label", "Volume");
+ volumeSlider.setAttribute("aria-valuemin", 0);
+ volumeSlider.setAttribute("aria-valuemax", 100);
+
+ this.setVolume = (volume) => {
+ volumeSlider.setAttribute("value", volume);
+ volumeSlider.setAttribute("aria-valuenow", volume*100);
+ volumeSlider.setAttribute("aria-valuetext", (volume*100).toFixed(1) + "%");
+ volumeSlider.setAttribute("style", "--value: "+volume*100+"%;margin-left: 5px;position: relative;z-index: 2;");
+ if (this.gameManager) this.gameManager.setVolume(volume);
+ }
+ this.setVolume(this.volume);
+
+ this.addEventListener(volumeSlider, "change mousemove touchmove mousedown touchstart mouseup", (e) => {
+ setTimeout(() => {
+ this.volume = parseFloat(volumeSlider.value);
+ this.setVolume(this.volume);
+ unmuteButton.style.display = (this.volume === 0) ? "" : "none";
+ muteButton.style.display = (this.volume === 0) ? "none" : "";
+ }, 5);
+ })
+
+ volumeSettings.appendChild(volumeSlider);
+
+
+
+ //this.volume this.muted
+
+ this.elements.menu.appendChild(volumeSettings);
+
this.settingParent = this.createElement("div");
this.settingsMenuOpen = false;
const settingButton = addButton("Settings", '', () => {