From 67f4f4dad92d79dc16c40ad7223bdb93bd25b88e Mon Sep 17 00:00:00 2001 From: Florrie Date: Tue, 4 Jun 2019 20:44:45 -0300 Subject: Volume slider in menubar --- players.js | 11 +++-- ui.js | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 3 deletions(-) diff --git a/players.js b/players.js index 2f7a574..0c296b3 100644 --- a/players.js +++ b/players.js @@ -141,12 +141,17 @@ module.exports.ControllableMPVPlayer = class extends module.exports.MPVPlayer { } volUp(amount) { - this.volume = Math.min(100, this.volume + amount) - this.sendCommand(`set volume ${this.volume}`) + this.setVolume(this.volume + amount) } volDown(amount) { - this.volume = Math.max(0, this.volume - amount) + this.setVolume(this.volume - amount) + } + + setVolume(value) { + this.volume = value + this.volume = Math.max(0, this.volume) + this.volume = Math.min(100, this.volume) this.sendCommand(`set volume ${this.volume}`) } diff --git a/ui.js b/ui.js index eb6b8f9..1bb74fc 100644 --- a/ui.js +++ b/ui.js @@ -235,6 +235,7 @@ class AppElement extends FocusElement { {divider: true}, this.playingTrack && {element: this.playingControl}, {element: this.loopingControl}, + {element: this.volumeSlider}, (next || previous) && {divider: true}, previous && {label: `Previous (${previous.name})`, action: () => this.playPreviousTrack(this.playingTrack)}, next && {label: `Next (${next.name})`, action: () => this.playNextTrack(this.playingTrack)}, @@ -263,6 +264,11 @@ class AppElement extends FocusElement { setValue: val => this.setLoop(val), getValue: () => this.player.isLooping }) + + this.volumeSlider = new SliderElement('Volume', { + setValue: val => this.setVolume(val), + getValue: () => this.player.volume + }) } selected() { @@ -720,6 +726,10 @@ class AppElement extends FocusElement { this.player.volDown(amount) } + setVolume(value) { + this.player.setVolume(value) + } + stopPlaying() { // We emit this so playTrack doesn't immediately start a new track. // We aren't *actually* about to play a new track. @@ -1822,6 +1832,132 @@ class InlineListPickerElement extends FocusElement { } } +class SliderElement extends FocusElement { + // Same general principle and usage as InlineListPickerElement, but for + // changing a numeric value. + + constructor(labelText, {setValue, getValue, maxValue = 100, percent = true}) { + super() + this.labelText = labelText + this.setValue = setValue + this.getValue = getValue + this.maxValue = maxValue + this.percent = percent + this.keyboardIdentifier = this.labelText + } + + fixLayout() { + const idealWidth = ansi.measureColumns( + this.labelText + + ' ' + this.getValueString(this.maxValue) + + ' ' + this.getNumString(this.maxValue) + + ' ' + ) + + this.w = Math.max(this.parent.contentW, idealWidth) + this.h = 1 + } + + drawTo(writable) { + if (this.isSelected) { + writable.write(ansi.invert()) + } + + let drawX = 0 + writable.write(ansi.moveCursor(this.absTop, this.absLeft)) + + writable.write(this.labelText + ' ') + drawX += ansi.measureColumns(this.labelText) + 1 + + writable.write(ansi.setAttributes([ansi.A_BRIGHT, ansi.C_BLUE])) + writable.write(' ') + drawX += 1 + + const valueString = this.getValueString(this.getValue()) + writable.write(valueString) + drawX += valueString.length + + const numString = this.getNumString(this.getValue()) + writable.write(' ' + numString + ' ') + drawX += numString.length + 2 + + writable.write(ansi.setForeground(ansi.C_RESET)) + writable.write(' '.repeat(Math.max(0, this.w - drawX))) + + writable.write(ansi.resetAttributes()) + } + + getValueString(value) { + const maxLength = 10 + + let length = Math.round(value / this.maxValue * maxLength) + + if (value < this.maxValue && length === maxLength) { + length-- + } + + if (value > 0 && length === 0) { + length++ + } + + return ( + '[' + + '-'.repeat(length) + + ' '.repeat(maxLength - length) + + ']' + ) + } + + getNumString(value) { + const maxValueString = Math.round(this.maxValue).toString() + const valueString = Math.round(value).toString() + const paddedString = valueString.padStart(maxValueString.length) + + return paddedString + (this.percent ? '%' : '') + } + + keyPressed(keyBuf) { + if (telc.isRight(keyBuf)) { + this.increment() + } else if (telc.isLeft(keyBuf)) { + this.decrement() + } else { + return true + } + return false + } + + clicked(button) { + if (button === 'left') { + if (this.isSelected) { + if (this.getValue() === this.maxValue) { + this.setValue(0) + } else { + this.increment() + } + } else { + this.root.select(this) + } + } else if (button === 'scroll-up') { + this.increment() + } else if (button === 'scroll-down') { + this.decrement() + } + } + + increment() { + this.setValue(this.getValue() + this.step) + } + + decrement() { + this.setValue(this.getValue() - this.step) + } + + get step() { + return this.maxValue / 10 + } +} + class ToggleControl extends FocusElement { constructor(labelText, {setValue, getValue}) { super() -- cgit 1.3.0-6-gf8a5