Icon change on non-immediate rx

Fixes #49
This commit is contained in:
Neale Pickett 2023-01-28 17:10:28 -07:00
parent 1d861b75e4
commit 72f2df5d6c
3 changed files with 95 additions and 14 deletions

50
static/scripts/icon.mjs Normal file
View File

@ -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,
}

35
static/scripts/noise.mjs Normal file
View File

@ -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
}
}

View File

@ -6,6 +6,7 @@ import * as Chart from "./chart.mjs"
import * as I18n from "./i18n.mjs" import * as I18n from "./i18n.mjs"
import * as time from "./time.mjs" import * as time from "./time.mjs"
import * as Music from "./music.mjs" import * as Music from "./music.mjs"
import * as Icon from "./icon.mjs"
const DefaultRepeater = "General" const DefaultRepeater = "General"
@ -45,6 +46,7 @@ class VailClient {
// Outputs // Outputs
this.outputs = new Outputs.Collection(globalAudioContext) this.outputs = new Outputs.Collection(globalAudioContext)
this.outputs.connect(globalAudioContext.destination) this.outputs.connect(globalAudioContext.destination)
this.icon = new Icon.Icon()
// Keyers // Keyers
this.straightKeyer = new Keyers.Keyers.straight(this) this.straightKeyer = new Keyers.Keyers.straight(this)
@ -165,21 +167,9 @@ class VailClient {
document.querySelector("#keyer-rate").dispatchEvent(new Event("input")) 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() { Buzz() {
this.outputs.Buzz(false) this.outputs.Buzz(false)
this.icon.Set("rx")
clearTimeout(this.activityTimeout)
this.activityTimeout = setTimeout(() => this.setIconType(), 2*time.Second)
this.setIconType("rx")
if (this.rxChart) this.rxChart.Set(1) if (this.rxChart) this.rxChart.Set(1)
} }
@ -192,7 +182,13 @@ class VailClient {
BuzzDuration(tx, when, duration) { BuzzDuration(tx, when, duration) {
this.outputs.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) { if (chart) {
chart.SetAt(1, when) chart.SetAt(1, when)
chart.SetAt(0, when+duration) chart.SetAt(0, when+duration)