diff options
-rw-r--r-- | configs/kvmd/v1-hdmi.conf | 10 | ||||
-rw-r--r-- | configs/kvmd/v1-vga.conf | 10 | ||||
-rw-r--r-- | eslintrc.yaml | 2 | ||||
-rw-r--r-- | kvmd/apps/kvmd/__init__.py | 17 | ||||
-rw-r--r-- | kvmd/apps/kvmd/server.py | 43 | ||||
-rw-r--r-- | kvmd/apps/kvmd/streamer.py | 61 | ||||
-rw-r--r-- | testenv/kvmd.conf | 8 | ||||
-rw-r--r-- | web/js/main.js | 3 | ||||
-rw-r--r-- | web/js/session.js | 10 | ||||
-rw-r--r-- | web/js/stream.js | 236 |
10 files changed, 229 insertions, 171 deletions
diff --git a/configs/kvmd/v1-hdmi.conf b/configs/kvmd/v1-hdmi.conf index 7c663ce9..9c2e48a0 100644 --- a/configs/kvmd/v1-hdmi.conf +++ b/configs/kvmd/v1-hdmi.conf @@ -53,6 +53,10 @@ kvmd: quality: 20 desired_fps: 0 + host: 127.0.0.1 + port: 8082 + timeout: 2.0 + cmd: - "/usr/bin/ustreamer" - "--device=/dev/kvmd-streamer" @@ -63,10 +67,12 @@ kvmd: - "--quality={quality}" - "--desired-fps={desired_fps}" - "--dv-timings" - - "--host=127.0.0.1" - - "--port=8082" + - "--host={host}" + - "--port={port}" - "--drop-same-frames=30" + state_poll: 1.0 + logging: version: 1 disable_existing_loggers: false diff --git a/configs/kvmd/v1-vga.conf b/configs/kvmd/v1-vga.conf index fe2cafa0..3de3ac9f 100644 --- a/configs/kvmd/v1-vga.conf +++ b/configs/kvmd/v1-vga.conf @@ -53,6 +53,10 @@ kvmd: quality: 80 desired_fps: 0 + host: 127.0.0.1 + port: 8082 + timeout: 2.0 + cmd: - "/usr/bin/ustreamer" - "--device=/dev/kvmd-streamer" @@ -65,8 +69,10 @@ kvmd: - "--height=576" - "--fake-width=800" - "--fake-height=600" - - "--host=127.0.0.1" - - "--port=8082" + - "--host={host}" + - "--port={port}" + + state_poll: 1.0 logging: version: 1 diff --git a/eslintrc.yaml b/eslintrc.yaml index 4e8535b0..4ba71dda 100644 --- a/eslintrc.yaml +++ b/eslintrc.yaml @@ -5,7 +5,7 @@ globals: Mouse: true Msd: true Session: true - Stream: true + Streamer: true Ui: true ui: true tools: true diff --git a/kvmd/apps/kvmd/__init__.py b/kvmd/apps/kvmd/__init__.py index 01737b01..1959f05c 100644 --- a/kvmd/apps/kvmd/__init__.py +++ b/kvmd/apps/kvmd/__init__.py @@ -1,5 +1,7 @@ import asyncio +import aiohttp + from ...application import init from ...logging import get_logger from ...logging import Log @@ -18,6 +20,7 @@ def main() -> None: config = init() with gpio.bcm(): loop = asyncio.get_event_loop() + http_session = aiohttp.ClientSession(loop=loop) log = Log( services=list(config["log"]["services"]), @@ -34,6 +37,7 @@ def main() -> None: atx = Atx( power_led=int(config["atx"]["pinout"]["power_led"]), hdd_led=int(config["atx"]["pinout"]["hdd_led"]), + power_switch=int(config["atx"]["pinout"]["power_switch"]), reset_switch=int(config["atx"]["pinout"]["reset_switch"]), click_delay=float(config["atx"]["click_delay"]), @@ -43,10 +47,12 @@ def main() -> None: msd = MassStorageDevice( target=int(config["msd"]["pinout"]["target"]), reset=int(config["msd"]["pinout"]["reset"]), + device_path=str(config["msd"]["device"]), init_delay=float(config["msd"]["init_delay"]), reset_delay=float(config["msd"]["reset_delay"]), write_meta=bool(config["msd"]["write_meta"]), + loop=loop, ) @@ -56,10 +62,18 @@ def main() -> None: sync_delay=float(config["streamer"]["sync_delay"]), init_delay=float(config["streamer"]["init_delay"]), init_restart_after=float(config["streamer"]["init_restart_after"]), + quality=int(config["streamer"]["quality"]), desired_fps=int(config["streamer"]["desired_fps"]), + + host=str(config["streamer"]["host"]), + port=int(config["streamer"]["port"]), + timeout=float(config["streamer"]["timeout"]), + cmd=list(map(str, config["streamer"]["cmd"])), + loop=loop, + http_session=http_session, ) Server( @@ -68,10 +82,13 @@ def main() -> None: atx=atx, msd=msd, streamer=streamer, + heartbeat=float(config["server"]["heartbeat"]), atx_state_poll=float(config["atx"]["state_poll"]), + streamer_state_poll=float(config["streamer"]["state_poll"]), streamer_shutdown_delay=float(config["streamer"]["shutdown_delay"]), msd_chunk_size=int(config["msd"]["chunk_size"]), + loop=loop, ).run( host=str(config["server"]["host"]), diff --git a/kvmd/apps/kvmd/server.py b/kvmd/apps/kvmd/server.py index cd89c433..04ce140f 100644 --- a/kvmd/apps/kvmd/server.py +++ b/kvmd/apps/kvmd/server.py @@ -113,6 +113,7 @@ class Server: # pylint: disable=too-many-instance-attributes heartbeat: float, atx_state_poll: float, + streamer_state_poll: float, streamer_shutdown_delay: float, msd_chunk_size: int, @@ -126,8 +127,9 @@ class Server: # pylint: disable=too-many-instance-attributes self.__streamer = streamer self.__heartbeat = heartbeat - self.__streamer_shutdown_delay = streamer_shutdown_delay self.__atx_state_poll = atx_state_poll + self.__streamer_state_poll = streamer_state_poll + self.__streamer_shutdown_delay = streamer_shutdown_delay self.__msd_chunk_size = msd_chunk_size self.__loop = loop @@ -138,8 +140,7 @@ class Server: # pylint: disable=too-many-instance-attributes self.__system_tasks: List[asyncio.Task] = [] self.__reset_streamer = False - self.__streamer_quality = streamer.get_current_quality() - self.__streamer_desired_fps = streamer.get_current_desired_fps() + self.__streamer_params = streamer.get_params() def run(self, host: str, port: int) -> None: self.__hid.start() @@ -175,6 +176,7 @@ class Server: # pylint: disable=too-many-instance-attributes self.__loop.create_task(self.__stream_controller()), self.__loop.create_task(self.__poll_dead_sockets()), self.__loop.create_task(self.__poll_atx_state()), + self.__loop.create_task(self.__poll_streamer_state()), ]) aiohttp.web.run_app(app, host=host, port=port, print=self.__run_app_print) @@ -347,16 +349,17 @@ class Server: # pylint: disable=too-many-instance-attributes # ===== STREAMER async def __streamer_state_handler(self, _: aiohttp.web.Request) -> aiohttp.web.Response: - return _json(self.__streamer.get_state()) + return _json(await self.__streamer.get_state()) @_wrap_exceptions_for_web("Can't set stream params") async def __streamer_set_params_handler(self, request: aiohttp.web.Request) -> aiohttp.web.Response: - quality = request.query.get("quality") - if quality: - self.__streamer_quality = _valid_int("quality", quality, 1, 100) - desired_fps = request.query.get("desired_fps") - if desired_fps: - self.__streamer_desired_fps = _valid_int("desired_fps", desired_fps, 0, 30) + for (name, validator) in [ + ("quality", lambda arg: _valid_int("quality", arg, 1, 100)), + ("desired_fps", lambda arg: _valid_int("desired_fps", arg, 0, 30)), + ]: + value = request.query.get(name) + if value: + self.__streamer_params[name] = validator(value) return _json() async def __streamer_reset_handler(self, _: aiohttp.web.Request) -> aiohttp.web.Response: @@ -402,24 +405,17 @@ class Server: # pylint: disable=too-many-instance-attributes cur = len(self.__sockets) if prev == 0 and cur > 0: if not self.__streamer.is_running(): - await self.__streamer.start(self.__streamer_quality, self.__streamer_desired_fps) - await self.__broadcast_event("streamer_state", **self.__streamer.get_state()) + await self.__streamer.start(self.__streamer_params) elif prev > 0 and cur == 0: shutdown_at = time.time() + self.__streamer_shutdown_delay elif prev == 0 and cur == 0 and time.time() > shutdown_at: if self.__streamer.is_running(): await self.__streamer.stop() - await self.__broadcast_event("streamer_state", **self.__streamer.get_state()) - if ( - self.__reset_streamer - or self.__streamer_quality != self.__streamer.get_current_quality() - or self.__streamer_desired_fps != self.__streamer.get_current_desired_fps() - ): + if (self.__reset_streamer or self.__streamer_params != self.__streamer.get_params()): if self.__streamer.is_running(): await self.__streamer.stop() - await self.__streamer.start(self.__streamer_quality, self.__streamer_desired_fps, no_init_restart=True) - await self.__broadcast_event("streamer_state", **self.__streamer.get_state()) + await self.__streamer.start(self.__streamer_params, no_init_restart=True) self.__reset_streamer = False prev = cur @@ -440,6 +436,13 @@ class Server: # pylint: disable=too-many-instance-attributes await self.__broadcast_event("atx_state", **self.__atx.get_state()) await asyncio.sleep(self.__atx_state_poll) + @_system_task + async def __poll_streamer_state(self) -> None: + while True: + if self.__sockets: + await self.__broadcast_event("streamer_state", **(await self.__streamer.get_state())) + await asyncio.sleep(self.__streamer_state_poll) + async def __broadcast_event(self, event: str, **kwargs: Dict) -> None: await asyncio.gather(*[ ws.send_str(json.dumps({ diff --git a/kvmd/apps/kvmd/streamer.py b/kvmd/apps/kvmd/streamer.py index 983dee6e..da82ade1 100644 --- a/kvmd/apps/kvmd/streamer.py +++ b/kvmd/apps/kvmd/streamer.py @@ -6,6 +6,8 @@ from typing import List from typing import Dict from typing import Optional +import aiohttp + from ...logging import get_logger from ... import gpio @@ -13,17 +15,25 @@ from ... import gpio # ===== class Streamer: # pylint: disable=too-many-instance-attributes - def __init__( + def __init__( # pylint: disable=too-many-arguments self, cap_power: int, conv_power: int, sync_delay: float, init_delay: float, init_restart_after: float, + quality: int, desired_fps: int, + + host: str, + port: int, + timeout: float, + cmd: List[str], + loop: asyncio.AbstractEventLoop, + http_session: aiohttp.ClientSession, ) -> None: self.__cap_power = (gpio.set_output(cap_power) if cap_power > 0 else cap_power) @@ -31,23 +41,30 @@ class Streamer: # pylint: disable=too-many-instance-attributes self.__sync_delay = sync_delay self.__init_delay = init_delay self.__init_restart_after = init_restart_after - self.__quality = quality - self.__desired_fps = desired_fps + + self.__params = { + "quality": quality, + "desired_fps": desired_fps, + } + + self.__host = host + self.__port = port + self.__timeout = timeout + self.__cmd = cmd self.__loop = loop + self.__http_session = http_session self.__proc_task: Optional[asyncio.Task] = None - async def start(self, quality: int, desired_fps: int, no_init_restart: bool=False) -> None: + async def start(self, params: Dict, no_init_restart: bool=False) -> None: logger = get_logger() logger.info("Starting streamer ...") - assert 1 <= quality <= 100 - self.__quality = quality - - assert 0 <= desired_fps <= 30 - self.__desired_fps = desired_fps + self.__params = {key: params[key] for key in self.__params} # Only known params + assert 1 <= self.__params["quality"] <= 100 + assert 0 <= self.__params["desired_fps"] <= 30 await self.__inner_start() if self.__init_restart_after > 0.0 and not no_init_restart: @@ -63,17 +80,23 @@ class Streamer: # pylint: disable=too-many-instance-attributes def is_running(self) -> bool: return bool(self.__proc_task) - def get_current_quality(self) -> int: - return self.__quality + def get_params(self) -> Dict: + return dict(self.__params) - def get_current_desired_fps(self) -> int: - return self.__desired_fps - - def get_state(self) -> Dict: + async def get_state(self) -> Dict: + url = "http://%s:%d/state" % (self.__host, self.__port) + state = None + try: + async with self.__http_session.get(url, timeout=self.__timeout) as response: + response.raise_for_status() + state = (await response.json())["result"] + except aiohttp.ClientConnectorError: + pass + except Exception: + get_logger().exception("Invalid streamer response from /state") return { - "is_running": self.is_running(), - "quality": self.__quality, - "desired_fps": self.__desired_fps, + "params": self.get_params(), + "state": state, } def get_app(self) -> str: @@ -121,7 +144,7 @@ class Streamer: # pylint: disable=too-many-instance-attributes while True: # pylint: disable=too-many-nested-blocks proc: Optional[asyncio.subprocess.Process] = None # pylint: disable=no-member try: - cmd = [part.format(quality=self.__quality, desired_fps=self.__desired_fps) for part in self.__cmd] + cmd = [part.format(host=self.__host, port=self.__port, **self.__params) for part in self.__cmd] proc = await asyncio.create_subprocess_exec( *cmd, stdout=asyncio.subprocess.PIPE, diff --git a/testenv/kvmd.conf b/testenv/kvmd.conf index a0cc72a0..5c911066 100644 --- a/testenv/kvmd.conf +++ b/testenv/kvmd.conf @@ -52,6 +52,10 @@ kvmd: quality: 80 desired_fps: 0 + host: 127.0.0.1 + port: 8082 + timeout: 2.0 + cmd: - "/usr/bin/ustreamer" - "--device=/dev/kvmd-streamer" @@ -60,7 +64,9 @@ kvmd: - "--width=800" - "--height=600" - "--host=0.0.0.0" - - "--port=8082" + - "--port={port}" + + state_poll: 1.0 logging: version: 1 diff --git a/web/js/main.js b/web/js/main.js index 211e8525..e68b6ae9 100644 --- a/web/js/main.js +++ b/web/js/main.js @@ -10,7 +10,6 @@ function main() { $("bad-browser-modal").style.visibility = "visible"; } else { ui = new Ui(); - new Session(new Atx(), new Hid(), new Msd()); - new Stream(); + new Session(new Streamer(), new Atx(), new Hid(), new Msd()); } } diff --git a/web/js/session.js b/web/js/session.js index e6cbc21e..e93f0516 100644 --- a/web/js/session.js +++ b/web/js/session.js @@ -1,4 +1,4 @@ -function Session(atx, hid, msd) { +function Session(streamer, atx, hid, msd) { // var self = this; /********************************************************************************/ @@ -53,6 +53,7 @@ function Session(atx, hid, msd) { $("link-led").className = "led-green"; $("link-led").title = "Connected"; tools.debug("Session: socket opened:", event); + streamer.loadInitialState(); atx.loadInitialState(); msd.loadInitialState(); hid.setSocket(__ws); @@ -66,7 +67,9 @@ function Session(atx, hid, msd) { if (event.msg_type === "pong") { __missed_heartbeats = 0; } else if (event.msg_type === "event") { - if (event.msg.event === "atx_state") { + if (event.msg.event === "streamer_state") { + streamer.setState(event.msg.event_attrs); + } else if (event.msg.event === "atx_state") { atx.setState(event.msg.event_attrs); } else if (event.msg.event === "msd_state") { msd.setState(event.msg.event_attrs); @@ -90,8 +93,9 @@ function Session(atx, hid, msd) { clearInterval(__ping_timer); __ping_timer = null; } - hid.setSocket(null); + streamer.clearState(); atx.clearState(); + hid.setSocket(null); __ws = null; setTimeout(function() { $("link-led").className = "led-yellow"; diff --git a/web/js/stream.js b/web/js/stream.js index 2b431e89..324dd6cc 100644 --- a/web/js/stream.js +++ b/web/js/stream.js @@ -1,14 +1,14 @@ -function Stream() { - // var self = this; +function Streamer() { + var self = this; /********************************************************************************/ - var __prev_state = false; var __resolution = {width: 640, height: 480}; var __size_factor = 1; var __client_key = tools.makeId(); var __client_id = ""; var __client_fps = -1; + var __prev = false; var __init__ = function() { $("stream-led").title = "Stream inactive"; @@ -17,17 +17,13 @@ function Stream() { $("stream-quality-slider").max = 100; $("stream-quality-slider").step = 5; $("stream-quality-slider").value = 80; - tools.setOnUpSlider($("stream-quality-slider"), 1000, function(value) { - $("stream-quality-value").innerHTML = value + "%"; - }, __sendQuality); + tools.setOnUpSlider($("stream-quality-slider"), 1000, __updateQualityValue, (value) => __sendParam("quality", value)); $("stream-desired-fps-slider").min = 0; $("stream-desired-fps-slider").max = 30; $("stream-desired-fps-slider").step = 1; $("stream-desired-fps-slider").value = 0; - tools.setOnUpSlider($("stream-desired-fps-slider"), 1000, function(value) { - $("stream-desired-fps-value").innerHTML = (value == 0 ? "Unlimited" : value); - }, __sendSoftFps); + tools.setOnUpSlider($("stream-desired-fps-slider"), 1000, __updateDesiredFpsValue, (value) => __sendParam("desired_fps", value)); $("stream-size-slider").min = 20; $("stream-size-slider").max = 200; @@ -38,103 +34,122 @@ function Stream() { tools.setOnClick($("stream-screenshot-button"), __clickScreenshotButton); tools.setOnClick($("stream-reset-button"), __clickResetButton); - - __startPoller(); }; /********************************************************************************/ - // XXX: In current implementation we don't need this event because Stream() has own state poller - - var __startPoller = function() { - var http = tools.makeRequest("GET", "/streamer/state", function() { + self.loadInitialState = function() { + var http = tools.makeRequest("GET", "/kvmd/streamer", function() { if (http.readyState === 4) { - var response = (http.status === 200 ? JSON.parse(http.responseText) : null); - - if (http.status !== 200) { - if (__prev_state) { - tools.info("Stream: refreshing ..."); - $("stream-image").className = "stream-image-inactive"; - $("stream-box").classList.add("stream-box-inactive"); - $("stream-led").className = "led-gray"; - $("stream-led").title = "Stream inactive"; - $("stream-screenshot-button").disabled = true; - __setStreamerControlsDisabled(true); - __updateStreamHeader(false); - __client_key = tools.makeId(); - __client_id = ""; - __client_fps = -1; - __prev_state = false; - } - - } else if (http.status === 200) { - var source = response.result.source; - var stream = response.result.stream; - - if (!$("stream-desired-fps-slider").activated) { - $("stream-desired-fps-slider").disabled = false; - if ($("stream-desired-fps-slider").value !== source.desired_fps) { - $("stream-desired-fps-slider").value = source.desired_fps; - $("stream-desired-fps-value").innerHTML = (source.desired_fps == 0 ? "Unlimited" : source.desired_fps); - } - } - - if (!$("stream-quality-slider").activated) { - $("stream-quality-slider").disabled = false; - if ($("stream-quality-slider").value !== source.quality) { - $("stream-quality-slider").value = source.quality; - $("stream-quality-value").innerHTML = source.quality + "%"; - } - } - - if (__resolution.width !== source.resolution.width || __resolution.height !== source.resolution.height) { - __resolution = source.resolution; - if ($("stream-auto-resize-checkbox").checked) { - __adjustSizeFactor(); - } else { - __applySizeFactor(); - } - } - - var stream_client = tools.getCookie("stream_client"); - if (!__client_id && stream_client && stream_client.startsWith(__client_key + "/")) { - tools.info("Stream: found acceptable stream_client cookie:", stream_client); - __client_id = stream_client.slice(stream_client.indexOf("/") + 1); - } - - if (stream.clients_stat.hasOwnProperty(__client_id)) { - __client_fps = stream.clients_stat[__client_id].fps; - } else { - __client_fps = -1; - } - - __updateStreamHeader(true); - - if (!__prev_state) { - var path = "/streamer/stream?key=" + __client_key; - if (tools.browser.is_chrome || tools.browser.is_blink) { - // uStreamer fix for Blink https://bugs.chromium.org/p/chromium/issues/detail?id=527446 - tools.info("Stream: using advance_headers=1 to fix Blink MJPG bugs"); - path += "&advance_headers=1"; - } else if (tools.browser.is_safari || tools.browser.is_ios) { - // uStreamer fix for WebKit - tools.info("Stream: using dual_final_frames=1 to fix WebKit MJPG bugs"); - path += "&dual_final_frames=1"; - } - $("stream-image").src = path; - $("stream-image").className = "stream-image-active"; - $("stream-box").classList.remove("stream-box-inactive"); - $("stream-led").className = "led-green"; - $("stream-led").title = "Stream is active"; - $("stream-screenshot-button").disabled = false; - $("stream-reset-button").disabled = false; - __prev_state = true; - tools.info("Stream: acquired"); - } + if (http.status === 200) { + self.setState(JSON.parse(http.responseText).result); + } else { + self.clearState(); + setTimeout(self.loadInitialState, 1000); } } }); - setTimeout(__startPoller, 1000); + }; + + self.setState = function(state) { + if (state.state) { + var source = state.state.source; + var stream = state.state.stream; + + if (!__prev) { + $("stream-quality-slider").activated = false; + $("stream-desired-fps-slider").activated = false; + } + + if (!$("stream-quality-slider").activated) { + $("stream-quality-slider").disabled = false; + if ($("stream-quality-slider").value !== source.quality) { + $("stream-quality-slider").value = source.quality; + __updateQualityValue(source.quality); + } + } + + if (!$("stream-desired-fps-slider").activated) { + $("stream-desired-fps-slider").disabled = false; + if ($("stream-desired-fps-slider").value !== source.desired_fps) { + $("stream-desired-fps-slider").value = source.desired_fps; + __updateDesiredFpsValue(source.desired_fps); + } + } + + if (__resolution.width !== source.resolution.width || __resolution.height !== source.resolution.height) { + __resolution = source.resolution; + if ($("stream-auto-resize-checkbox").checked) { + __adjustSizeFactor(); + } else { + __applySizeFactor(); + } + } + + var stream_client = tools.getCookie("stream_client"); + if (!__client_id && stream_client && stream_client.startsWith(__client_key + "/")) { + tools.info("Stream: found acceptable stream_client cookie:", stream_client); + __client_id = stream_client.slice(stream_client.indexOf("/") + 1); + } + + if (stream.clients_stat.hasOwnProperty(__client_id)) { + __client_fps = stream.clients_stat[__client_id].fps; + } else { + __client_fps = -1; + } + + if (!__prev) { + var path = "/streamer/stream?key=" + __client_key; + if (tools.browser.is_chrome || tools.browser.is_blink) { + // uStreamer fix for Blink https://bugs.chromium.org/p/chromium/issues/detail?id=527446 + tools.info("Stream: using advance_headers=1 to fix Blink MJPG bugs"); + path += "&advance_headers=1"; + } else if (tools.browser.is_safari || tools.browser.is_ios) { + // uStreamer fix for WebKit + tools.info("Stream: using dual_final_frames=1 to fix WebKit MJPG bugs"); + path += "&dual_final_frames=1"; + } + $("stream-image").src = path; + $("stream-image").className = "stream-image-active"; + $("stream-box").classList.remove("stream-box-inactive"); + $("stream-led").className = "led-green"; + $("stream-led").title = "Stream is active"; + $("stream-screenshot-button").disabled = false; + $("stream-reset-button").disabled = false; + tools.info("Stream: acquired"); + __prev = true; + } + + __updateStreamHeader(true); + + } else { + self.clearState(); + } + }; + + self.clearState = function() { + tools.info("Stream: refreshing ..."); + $("stream-image").className = "stream-image-inactive"; + $("stream-box").classList.add("stream-box-inactive"); + $("stream-led").className = "led-gray"; + $("stream-led").title = "Stream inactive"; + $("stream-screenshot-button").disabled = true; + $("stream-reset-button").disabled = true; + $("stream-quality-slider").disabled = true; + $("stream-desired-fps-slider").disabled = true; + __client_key = tools.makeId(); + __client_id = ""; + __client_fps = -1; + __prev = false; + __updateStreamHeader(false); + }; + + var __updateQualityValue = function(value) { + $("stream-quality-value").innerHTML = value + "%"; + }; + + var __updateDesiredFpsValue = function(value) { + $("stream-desired-fps-value").innerHTML = (value == 0 ? "Unlimited" : value); }; var __updateStreamHeader = function(online) { @@ -158,7 +173,6 @@ function Stream() { }; var __clickResetButton = function() { - __setStreamerControlsDisabled(true); var http = tools.makeRequest("POST", "/kvmd/streamer/reset", function() { if (http.readyState === 4) { if (http.status !== 200) { @@ -168,36 +182,16 @@ function Stream() { }); }; - var __sendQuality = function(value) { - __setStreamerControlsDisabled(true); - var http = tools.makeRequest("POST", "/kvmd/streamer/set_params?quality=" + value, function() { + var __sendParam = function(name, value) { + var http = tools.makeRequest("POST", "/kvmd/streamer/set_params?" + name + "=" + value, function() { if (http.readyState === 4) { if (http.status !== 200) { ui.error("Can't configure stream:<br>", http.responseText); } - $("stream-quality-slider").activated = false; - } - }); - }; - - var __sendSoftFps = function(value) { - __setStreamerControlsDisabled(true); - var http = tools.makeRequest("POST", "/kvmd/streamer/set_params?desired_fps=" + value, function() { - if (http.readyState === 4) { - if (http.status !== 200) { - ui.error("Can't configure stream:<br>", http.responseText); - } - $("stream-desired-fps-slider").activated = false; } }); }; - var __setStreamerControlsDisabled = function(disabled) { - $("stream-reset-button").disabled = disabled; - $("stream-quality-slider").disabled = disabled; - $("stream-desired-fps-slider").disabled = disabled; - }; - var __resize = function(center=false) { var size = $("stream-size-slider").value; $("stream-size-value").innerHTML = size + "%"; |