Added support within the UI to change a clients playback latency
This commit is contained in:
parent
259a317440
commit
cbad10f717
8 changed files with 286 additions and 0 deletions
84
shared/css/static/modal-latency.scss
Normal file
84
shared/css/static/modal-latency.scss
Normal file
|
@ -0,0 +1,84 @@
|
|||
@import "mixin";
|
||||
@import "properties";
|
||||
|
||||
.modal-body.modal-latency {
|
||||
@include user-select(none);
|
||||
@include transform(all $button_hover_animation_time ease-in-out);
|
||||
|
||||
.info {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: stretch;
|
||||
|
||||
.htmltag-client {
|
||||
color: #999!important;
|
||||
margin-left: .25em;
|
||||
}
|
||||
|
||||
div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: stretch;
|
||||
}
|
||||
|
||||
.value {
|
||||
margin-left: .25em;
|
||||
}
|
||||
}
|
||||
|
||||
.container-min, .container-max {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: stretch;
|
||||
|
||||
height: 2em;
|
||||
|
||||
.container-value {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
|
||||
margin-right: 1em;
|
||||
width: 9em;
|
||||
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
align-self: center;
|
||||
|
||||
.value {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.container-max {
|
||||
padding-top: 1em;
|
||||
}
|
||||
|
||||
.container-slider {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: stretch;
|
||||
|
||||
margin-top: 2em;
|
||||
|
||||
.spacer {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
button:not(:last-of-type) {
|
||||
margin-right: 1em;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -256,6 +256,10 @@
|
|||
.modal-body.modal-green {
|
||||
border-left: 2px solid #00d400;
|
||||
}
|
||||
.modal-body.modal-red {
|
||||
border: none;
|
||||
border-left: 2px solid #d50000;
|
||||
}
|
||||
|
||||
.modal-body.modal-body-input {
|
||||
color: #999999;
|
||||
|
|
|
@ -2586,6 +2586,48 @@
|
|||
</div>
|
||||
</script>
|
||||
|
||||
<script class="jsrender-template" id="tmpl_change_latency" type="text/html">
|
||||
<div> <!-- for the renderer -->
|
||||
<div class="info">
|
||||
<div>{{tr "Change latency for client "/}} <node key="client"></node></div>
|
||||
</div>
|
||||
<div class="container-min">
|
||||
<div class="container-value">
|
||||
{{tr "Min buffer: "/}}
|
||||
<a class="value">20ms</a>
|
||||
</div>
|
||||
<div class="container-slider">
|
||||
<div class="filler" style="width: 30%"></div>
|
||||
<div class="thumb container-tooltip" style="left: 30%">
|
||||
<div class="tooltip">
|
||||
<a>86%</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-max">
|
||||
<div class="container-value">
|
||||
{{tr "Max buffer: "/}}
|
||||
<a class="value">20ms</a>
|
||||
</div>
|
||||
<div class="container-slider">
|
||||
<div class="filler" style="width: 30%"></div>
|
||||
<div class="thumb container-tooltip" style="left: 30%">
|
||||
<div class="tooltip">
|
||||
<a>86%</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button class="btn btn-blue button-reset">{{tr "Reset" /}}</button>
|
||||
<div class="spacer"></div>
|
||||
<button class="btn btn-danger button-cancel">{{tr "Cancel" /}}</button>
|
||||
<button class="btn btn-success button-close">{{tr "Close" /}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- Permission overview -->
|
||||
<script class="jsrender-template" id="tmpl_server_permissions" type="text/html">
|
||||
<div class="container">
|
||||
|
|
|
@ -55,6 +55,11 @@ namespace connection {
|
|||
STOPPED
|
||||
}
|
||||
|
||||
export type LatencySettings = {
|
||||
min_buffer: number; /* milliseconds */
|
||||
max_buffer: number; /* milliseconds */
|
||||
}
|
||||
|
||||
export interface VoiceClient {
|
||||
client_id: number;
|
||||
|
||||
|
@ -69,6 +74,11 @@ namespace connection {
|
|||
set_volume(volume: number) : void;
|
||||
|
||||
abort_replay();
|
||||
|
||||
support_latency_settings() : boolean;
|
||||
|
||||
reset_latency_settings();
|
||||
latency_settings(settings?: LatencySettings) : LatencySettings;
|
||||
}
|
||||
|
||||
export abstract class AbstractVoiceConnection {
|
||||
|
|
|
@ -625,6 +625,17 @@ class ClientEntry {
|
|||
//TODO: Update in info
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Change playback latency"),
|
||||
callback: () => {
|
||||
Modals.spawnChangeLatency(this, this._audio_handle.latency_settings(), () => {
|
||||
this._audio_handle.reset_latency_settings();
|
||||
return this._audio_handle.latency_settings();
|
||||
}, settings => this._audio_handle.latency_settings(settings));
|
||||
},
|
||||
visible: this._audio_handle && this._audio_handle.support_latency_settings()
|
||||
}, {
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
icon_class: "client-input_muted_local",
|
||||
|
@ -1413,6 +1424,17 @@ class MusicClientEntry extends ClientEntry {
|
|||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Change playback latency"),
|
||||
callback: () => {
|
||||
Modals.spawnChangeLatency(this, this._audio_handle.latency_settings(), () => {
|
||||
this._audio_handle.reset_latency_settings();
|
||||
return this._audio_handle.latency_settings();
|
||||
}, settings => this._audio_handle.latency_settings(settings));
|
||||
},
|
||||
visible: this._audio_handle && this._audio_handle.support_latency_settings()
|
||||
},
|
||||
contextmenu.Entry.HR(),
|
||||
{
|
||||
name: tr("Delete bot"),
|
||||
|
|
110
shared/js/ui/modal/ModalChangeLatency.ts
Normal file
110
shared/js/ui/modal/ModalChangeLatency.ts
Normal file
|
@ -0,0 +1,110 @@
|
|||
/// <reference path="../../ui/elements/modal.ts" />
|
||||
/// <reference path="../../ConnectionHandler.ts" />
|
||||
/// <reference path="../../proto.ts" />
|
||||
|
||||
namespace Modals {
|
||||
let modal: Modal;
|
||||
export function spawnChangeLatency(client: ClientEntry, current: connection.voice.LatencySettings, reset: () => connection.voice.LatencySettings, apply: (settings: connection.voice.LatencySettings) => any) {
|
||||
if(modal) modal.close();
|
||||
|
||||
const begin = Object.assign({}, current);
|
||||
current = Object.assign({}, current);
|
||||
|
||||
modal = createModal({
|
||||
header: tr("Change playback latency"),
|
||||
body: function () {
|
||||
let tag = $("#tmpl_change_latency").renderTag({
|
||||
client: htmltags.generate_client_object({
|
||||
add_braces: false,
|
||||
client_name: client.clientNickName(),
|
||||
client_unique_id: client.properties.client_unique_identifier,
|
||||
client_id: client.clientId()
|
||||
})
|
||||
});
|
||||
|
||||
const update_value = () => {
|
||||
const valid = current.min_buffer < current.max_buffer;
|
||||
|
||||
modal.htmlTag.find(".modal-body").toggleClass("modal-red", !valid);
|
||||
modal.htmlTag.find(".modal-body").toggleClass("modal-green", valid);
|
||||
|
||||
if(!valid)
|
||||
return;
|
||||
|
||||
apply(current);
|
||||
};
|
||||
|
||||
let slider_min: Slider, slider_max: Slider;
|
||||
{
|
||||
const container = tag.find(".container-min");
|
||||
const tag_value = container.find(".value");
|
||||
|
||||
const slider_tag = container.find(".container-slider");
|
||||
slider_min = sliderfy(slider_tag, {
|
||||
initial_value: current.min_buffer,
|
||||
step: 20,
|
||||
max_value: 1000,
|
||||
min_value: 0,
|
||||
|
||||
unit: 'ms'
|
||||
});
|
||||
slider_tag.on('change', event => {
|
||||
current.min_buffer = parseInt(slider_tag.attr("value"));
|
||||
tag_value.text(current.min_buffer + "ms");
|
||||
update_value();
|
||||
});
|
||||
|
||||
tag_value.text(current.min_buffer + "ms");
|
||||
}
|
||||
|
||||
{
|
||||
const container = tag.find(".container-max");
|
||||
const tag_value = container.find(".value");
|
||||
|
||||
const slider_tag = container.find(".container-slider");
|
||||
slider_max = sliderfy(slider_tag, {
|
||||
initial_value: current.max_buffer,
|
||||
step: 20,
|
||||
max_value: 1020,
|
||||
min_value: 20,
|
||||
|
||||
unit: 'ms'
|
||||
});
|
||||
|
||||
slider_tag.on('change', event => {
|
||||
current.max_buffer = parseInt(slider_tag.attr("value"));
|
||||
tag_value.text(current.max_buffer + "ms");
|
||||
update_value();
|
||||
});
|
||||
|
||||
tag_value.text(current.max_buffer + "ms");
|
||||
}
|
||||
setTimeout(update_value, 0);
|
||||
|
||||
tag.find(".button-close").on('click', event => {
|
||||
modal.close();
|
||||
});
|
||||
|
||||
tag.find(".button-cancel").on('click', event => {
|
||||
apply(begin);
|
||||
modal.close();
|
||||
});
|
||||
|
||||
tag.find(".button-reset").on('click', event => {
|
||||
current = Object.assign({}, reset());
|
||||
slider_max.value(current.max_buffer);
|
||||
slider_min.value(current.min_buffer);
|
||||
});
|
||||
|
||||
return tag.children();
|
||||
},
|
||||
footer: null,
|
||||
|
||||
width: 600
|
||||
});
|
||||
|
||||
modal.close_listener.push(() => modal = undefined);
|
||||
modal.open();
|
||||
modal.htmlTag.find(".modal-body").addClass("modal-latency");
|
||||
}
|
||||
}
|
|
@ -185,6 +185,7 @@ const loader_javascript = {
|
|||
"js/ui/modal/ModalCreateChannel.js",
|
||||
"js/ui/modal/ModalServerEdit.js",
|
||||
"js/ui/modal/ModalChangeVolume.js",
|
||||
"js/ui/modal/ModalChangeLatency.js",
|
||||
"js/ui/modal/ModalBanClient.js",
|
||||
"js/ui/modal/ModalIconSelect.js",
|
||||
"js/ui/modal/ModalInvite.js",
|
||||
|
@ -343,6 +344,7 @@ const loader_style = {
|
|||
"css/static/modal-channel.css",
|
||||
"css/static/modal-query.css",
|
||||
"css/static/modal-volume.css",
|
||||
"css/static/modal-latency.css",
|
||||
"css/static/modal-invite.css",
|
||||
"css/static/modal-playlist.css",
|
||||
"css/static/modal-banlist.css",
|
||||
|
|
|
@ -211,6 +211,18 @@ namespace audio {
|
|||
abort_replay() {
|
||||
this.stopAudio(true);
|
||||
}
|
||||
|
||||
latency_settings(settings?: connection.voice.LatencySettings): connection.voice.LatencySettings {
|
||||
throw "not supported";
|
||||
}
|
||||
|
||||
reset_latency_settings() {
|
||||
throw "not supported";
|
||||
}
|
||||
|
||||
support_latency_settings(): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue