From 72f2df5d6ce0e6c3d0d2b18d787d8f2a3b5b3b82 Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Sat, 28 Jan 2023 17:10:28 -0700 Subject: [PATCH] Icon change on non-immediate rx Fixes #49 --- static/scripts/icon.mjs | 50 ++++++++++++++++++++++++++++++++++++++++ static/scripts/noise.mjs | 35 ++++++++++++++++++++++++++++ static/scripts/vail.mjs | 24 ++++++++----------- 3 files changed, 95 insertions(+), 14 deletions(-) create mode 100644 static/scripts/icon.mjs create mode 100644 static/scripts/noise.mjs diff --git a/static/scripts/icon.mjs b/static/scripts/icon.mjs new file mode 100644 index 0000000..635eebe --- /dev/null +++ b/static/scripts/icon.mjs @@ -0,0 +1,50 @@ +import * as time from "./time.mjs" + +const defaultIcon = "default" + +class Icon { + /** + * @param {Number} timeoutDuration Duration of timeout + */ + constructor(timeoutDuration = 2*time.Second) { + this.timeoutDuration = timeoutDuration + } + + /** + * Set the icon type + * + * @param {String} iconType Icon to set to + */ + Set(iconType=defaultIcon) { + if (iconType != defaultIcon) { + clearTimeout(this.cleanupTimer) + this.cleanupTimer = setTimeout(() => this.Set(), this.timeoutDuration) + } + + for (let e of document.querySelectorAll("link[rel=icon]")) { + if (! e.dataset[defaultIcon]) { + e.dataset[defaultIcon] = e.href + } + let url = e.dataset[iconType] + if (url) { + e.href = url + } else { + console.warn(`No data-${iconType} attribute`, e) + } + } + } + + /** + * Set icon at the provided time. + * + * @param {String} iconType Icon to set to + * @param {Number} when Time to set the value + */ + SetAt(iconType, when=null) { + setTimeout(() => this.Set(iconType), when - Date.now()) + } +} + +export { + Icon, +} \ No newline at end of file diff --git a/static/scripts/noise.mjs b/static/scripts/noise.mjs new file mode 100644 index 0000000..5b60fb1 --- /dev/null +++ b/static/scripts/noise.mjs @@ -0,0 +1,35 @@ + +/** + * Create a noise generator with a low pass filter + * + * @param {AudioContext} context Audio context + * @param {Number} lowpassFreq Low-pass filter frequency (Hz) + * @returns {GainNode} Gain object for noise + */ + function Noise(context, lowpassFreq = 100) { + let bufferSize = 17 * context.sampleRate + let noiseBuffer = context.createBuffer(1, bufferSize, context.sampleRate) + let output = noiseBuffer.getChannelData(0) + for (let i = 0; i < bufferSize; i++) { + output[i] = Math.random() * 2 - 1; + } + + let whiteNoise = context.createBufferSource(); + whiteNoise.buffer = noiseBuffer; + whiteNoise.loop = true; + whiteNoise.start(0); + + let filter = context.createBiquadFilter() + filter.type = "lowpass" + filter.frequency.value = lowpassFreq + + let gain = context.createGain() + gain.gain.value = 0.1 + + whiteNoise.connect(filter) + filter.connect(gain) + + return gain +} +} + diff --git a/static/scripts/vail.mjs b/static/scripts/vail.mjs index a534b69..b2c1bf9 100644 --- a/static/scripts/vail.mjs +++ b/static/scripts/vail.mjs @@ -6,6 +6,7 @@ import * as Chart from "./chart.mjs" import * as I18n from "./i18n.mjs" import * as time from "./time.mjs" import * as Music from "./music.mjs" +import * as Icon from "./icon.mjs" const DefaultRepeater = "General" @@ -45,6 +46,7 @@ class VailClient { // Outputs this.outputs = new Outputs.Collection(globalAudioContext) this.outputs.connect(globalAudioContext.destination) + this.icon = new Icon.Icon() // Keyers this.straightKeyer = new Keyers.Keyers.straight(this) @@ -165,21 +167,9 @@ class VailClient { document.querySelector("#keyer-rate").dispatchEvent(new Event("input")) } - setIconType(iconType="silent") { - for (let e of document.querySelectorAll("link[rel=icon]")) { - if (! e.dataset.silent) { - e.dataset.silent = e.href - } - e.href = e.dataset[iconType] - } - } - Buzz() { this.outputs.Buzz(false) - - clearTimeout(this.activityTimeout) - this.activityTimeout = setTimeout(() => this.setIconType(), 2*time.Second) - this.setIconType("rx") + this.icon.Set("rx") if (this.rxChart) this.rxChart.Set(1) } @@ -192,7 +182,13 @@ class VailClient { BuzzDuration(tx, when, duration) { this.outputs.BuzzDuration(tx, when, duration) - let chart = tx?this.txChart:this.rxChart + let chart + if (tx) { + chart = this.txChart + } else { + chart = this.rxChart + this.icon.SetAt("rx", when) + } if (chart) { chart.SetAt(1, when) chart.SetAt(0, when+duration)