- parametrized Dockerfile dependencies versions

- Dockerfile optimizations
- Dockerfile labels added
- Dockerfile readability improved
- use copy directive instead of wget
- use copy directive instead of echo
- pin noVNC and websockify versions
- docker-compose added
- parametrized timezone, screen resolution and password for alpine user
- formatted yaml, json, html files
- vnc.html renamed to index.html for autostart novnc client on port
- LICENSE file added
- entrypoint rewrited for sh with better readablility
pull/23/head
Vladimir nett00n Budylnikov 2 years ago
parent b6139933ec
commit 14a1826700

@ -1,15 +1,13 @@
---
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
- package-ecosystem: github-actions
directory: /
schedule:
interval: "daily"
- package-ecosystem: "docker"
directory: "/"
interval: daily
- package-ecosystem: docker
directory: /
schedule:
interval: "daily"
interval: daily
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem

@ -1,46 +1,38 @@
---
name: Docker
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * 1"
- cron: 0 0 * * 1
push:
branches:
- latest
- dev
jobs:
build:
name: build
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
steps:
- name: Check out the repo
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Setup Docker buildx
uses: docker/setup-buildx-action@v2
- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# - name: Log in to the Container registry
# uses: docker/login-action@v2
# with:
# registry: ghcr.io
# username: ${{ github.actor }}
# password: ${{ secrets.GIT_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4
@ -48,12 +40,11 @@ jobs:
images: |
${{ secrets.DOCKERHUB_USERNAME }}/alpine_xfce4_novnc
# ghcr.io/${{ github.repository }}
- name: Build and push Docker images
uses: docker/build-push-action@v3
with:
context: .
platforms: linux/amd64,linux/arm64,linux/arm/v7 #,linux/arm/v6, linux/386, linux/ppc64le,linux/s390x
platforms: linux/amd64,linux/arm64,linux/arm/v7 # ,linux/arm/v6, linux/386, linux/ppc64le,linux/s390x
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

1
.gitignore vendored

@ -0,0 +1 @@
.env

@ -1,23 +1,58 @@
FROM alpine:3.16
ARG ALPINE_VERSION=3.19
FROM alpine:${ALPINE_VERSION}
ARG NOVNC_VERSION=v1.4.0
ARG WEBSOCKIFY_VERSION=v0.11.0
ARG IMAGE_TAG=latest
ARG BUILD_DATE=01.01.1970
LABEL maintainer="Don <novaspirit@novaspirit.com>"
LABEL description="Simple and minimal Alpine Docker Image providing XFCE4 through html5 noVNC connection"
LABEL license="MIT"
LABEL org.opencontainers.image.version="${IMAGE_TAG}"
LABEL build-date="${BUILD_DATE}"
RUN apk add --no-cache sudo git xfce4 faenza-icon-theme bash python3 tigervnc xfce4-terminal firefox cmake wget \
pulseaudio xfce4-pulseaudio-plugin pavucontrol pulseaudio-alsa alsa-plugins-pulse alsa-lib-dev nodejs npm \
RUN apk add \
alsa-lib-dev \
alsa-plugins-pulse \
bash \
build-base \
&& adduser -h /home/alpine -s /bin/bash -S -D alpine && echo -e "alpine\nalpine" | passwd alpine \
cmake \
faenza-icon-theme \
firefox \
git \
nodejs \
npm \
pavucontrol \
pulseaudio \
pulseaudio-alsa \
python3 \
sudo \
tigervnc \
tzdata \
wget \
xfce4 \
xfce4-pulseaudio-plugin \
xfce4-terminal \
xrandr \
--no-cache
RUN adduser -h /home/alpine -s /bin/bash -S -D alpine \
&& echo 'alpine ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers \
&& git clone https://github.com/novnc/noVNC /opt/noVNC \
&& git clone https://github.com/novnc/websockify /opt/noVNC/utils/websockify \
&& wget https://raw.githubusercontent.com/novaspirit/Alpine_xfce4_noVNC/dev/script.js -O /opt/noVNC/script.js \
&& wget https://raw.githubusercontent.com/novaspirit/Alpine_xfce4_noVNC/dev/audify.js -O /opt/noVNC/audify.js \
&& wget https://raw.githubusercontent.com/novaspirit/Alpine_xfce4_noVNC/dev/vnc.html -O /opt/noVNC/vnc.html \
&& wget https://raw.githubusercontent.com/novaspirit/Alpine_xfce4_noVNC/dev/pcm-player.js -O /opt/noVNC/pcm-player.js
&& mkdir -p /opt/noVNC/
WORKDIR /opt
RUN git clone -b "${NOVNC_VERSION}" --single-branch https://github.com/novnc/noVNC.git /opt/noVNC \
&& rm -rf /opt/noVNC/.git/
RUN git clone -b "${WEBSOCKIFY_VERSION}" --single-branch https://github.com/novnc/websockify.git /opt/noVNC/utils/websockify \
&& rm -rf /opt/noVNC/utils/websockify/.git/
RUN npm install --prefix /opt/noVNC ws \
&& npm install --prefix /opt/noVNC audify
RUN npm install --prefix /opt/noVNC ws
RUN npm install --prefix /opt/noVNC audify
COPY script.js audify.js index.html pcm-player.js /opt/noVNC/
COPY entrypoint.sh /
USER alpine
WORKDIR /home/alpine
@ -27,18 +62,6 @@ RUN mkdir -p /home/alpine/.vnc \
&& echo -e "#!/bin/bash\nstartxfce4 &" > /home/alpine/.vnc/xstartup \
&& echo -e "alpine\nalpine\nn\n" | vncpasswd
USER root
RUN echo '\
#!/bin/bash \
/usr/bin/vncserver :99 2>&1 | sed "s/^/[Xtigervnc ] /" & \
sleep 1 & \
/usr/bin/pulseaudio 2>&1 | sed "s/^/[pulseaudio] /" & \
sleep 1 & \
/usr/bin/node /opt/noVNC/audify.js 2>&1 | sed "s/^/[audify ] /" & \
/opt/noVNC/utils/novnc_proxy --vnc localhost:5999 2>&1 | sed "s/^/[noVNC ] /"'\
>/entry.sh
USER alpine
ENTRYPOINT [ "/bin/bash", "/entry.sh" ]
ENTRYPOINT [ "/bin/bash", "/entrypoint.sh" ]

@ -0,0 +1,21 @@
# MIT License
Copyright (c) 2024 Don "novaspirit"
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -2,7 +2,7 @@
Simple and minimal Alpine Docker Image providing XFCE4 through html5 noVNC connection
Step by step tutorial on how this docker is created (https://www.youtube.com/watch?v=8IfTXJRAIJw)
Step by step tutorial on how this docker is created (<https://www.youtube.com/watch?v=8IfTXJRAIJw>)
<div align="center">
@ -10,7 +10,6 @@ Step by step tutorial on how this docker is created (https://www.youtube.com/wat
[![Youtube](https://img.shields.io/badge/YouTube-FF0000?style=flat-square&logo=youtube&logoColor=white)](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw)
[![Twitter URL](https://img.shields.io/twitter/follow/novaspirittech?style=flat-square&logo=twitter)](https://twitter.com/novaspirittech)
![GitHub repo size](https://img.shields.io/github/repo-size/novaspirit/Alpine_xfce4_noVNC?label=Repo%20Size&logo=github)
![Docker Build](https://github.com/novaspirit/Alpine_xfce4_noVNC/workflows/Docker/badge.svg)
![Docker Pulls](https://img.shields.io/docker/pulls/novaspirit/alpine_xfce4_novnc)
@ -20,7 +19,7 @@ Step by step tutorial on how this docker is created (https://www.youtube.com/wat
</div>
#### Updates
## Updates
v0.1.2 removed password requirement for noVNC
@ -28,25 +27,55 @@ v0.1.1 added firefox pulseaudio and audio support
v0.1.0 initial code
#### Build Image
## Build Image
```sh
```shell
git clone https://github.com/novaspirit/Alpine_xfce4_noVNC.git
docker build -t alpine-xfce4 Alpine_xfce4_noVNC/
```
#### Run Image
## Run Image
### Using plain Docker
```sh
```shell
docker run -it -p 6080:6080 -p 56780:56780 --name alpine-novnc alpine-xfce4
```
#### Connect With noVNC
Use modern browswer to connect to http://(docker ip):6080/vnc.html
### Using Docker Compose
the predefined password is `alpine`
#### LICENCE
```shell
docker-compose up -d
```
MIT
You can set environmental values in `.env` file
### Environment
- `ALPINE_PASSWORD` - change password for user `alpine`
- `PUBLIC_HTTP_PORT` - set port for access to novnc.
`16080:6080` would publish novnc on `16080` port.
`6080` would automatically map random port.
- `SCREEN_RESOLUTION` - You can preset screen resolution for noVNC. Default values for resolution:
- "1024x768"
- "1920x1200"
- "1920x1080"
- "1600x1200"
- "1680x1050"
- "1400x1050"
- "1360x768"
- "1280x1024"
- "1280x960"
- "1280x800"
- "1280x720"
- "800x600"
- "640x480"
- `TZ` - You can set TimeZone
## Connect With noVNC
Use modern browswer to connect to http://(docker ip):6080
## LICENCE
[MIT](./LICENSE.md)

@ -24,11 +24,11 @@ rtAudio.openStream({
deviceId: rtAudio.getDefaultOutputDevice(), // Output device id (Get all devices using `getDevices`)
nChannels: 2, // Number of channels
firstChannel: 0 // First channel index on device (default = 0).
}, {
}, {
deviceId: rtAudio.getDefaultInputDevice(), // Input device id (Get all devices using `getDevices`)
nChannels: 2, // Number of channels
firstChannel: 0 // First channel index on device (default = 0).
},
},
RtAudioFormat.RTAUDIO_SINT16, // PCM Format - Signed 16-bit integer
48000, // Sampling rate is 44.1kHz
480, // Frame size is 1920 (40ms)

@ -0,0 +1,19 @@
---
services:
app:
build:
context: .
args:
ALPINE_VERSION: "3.19"
NOVNC_VERSION: "v1.4.0"
WEBSOCKIFY_VERSION: "v0.11.0"
IMAGE_TAG: "latest"
BUILD_DATE: "01.01.1970"
ports:
- '${PUBLIC_HTTP_PORT:-6080:6080}'
restart: always
environment:
- TZ=${TZ:-Etc/UTC}
- SCREEN_RESOLUTION=${SCREEN_RESOLUTION:-1920x1080}
- ${ALPINE_PASSWORD:-alpine}
networks: {}

@ -0,0 +1,37 @@
#!/bin/sh
# Check if alpine password is set
if [ -n "${ALPINE_PASSWORD}" ]; then
# Set password for alpine user
echo -e "${ALPINE_PASSWORD}\n${ALPINE_PASSWORD}" | passwd alpine
fi
# Check if TZ variable is set and valid
if [ -n "${TZ}" ] && [ -f "/usr/share/zoneinfo/$(echo "$TZ" | cut -d'/' -f2)" ]; then
# Set Timezone
ln -sf "/usr/share/zoneinfo/$TZ" /etc/localtime
fi
# Start VNC server and prefix its output
/usr/bin/vncserver :99 2>&1 | sed "s/^/[Xtigervnc ] /" &
# Wait for a second before starting PulseAudio
sleep 1
# Start PulseAudio and prefix its output
/usr/bin/pulseaudio 2>&1 | sed "s/^/[pulseaudio] /" &
# Wait for a second before starting the Node.js script
sleep 1
# Start Node.js script and prefix its output
/usr/bin/node /opt/noVNC/audify.js 2>&1 | sed "s/^/[audify ] /" &
# Check if SCREEN_RESOLUTION is in the format [digits]x[digits]
if echo "$SCREEN_RESOLUTION" | grep -E '^[0-9]+x[0-9]+$' >/dev/null; then
# Set screen resolution if format is correct
xrandr -s "$SCREEN_RESOLUTION" -d :99
fi
# Start noVNC proxy and prefix its output
/opt/noVNC/utils/novnc_proxy --vnc localhost:5999 2>&1 | sed "s/^/[noVNC ] /"

@ -0,0 +1,370 @@
<!DOCTYPE html>
<html lang="en" class="noVNC_loading">
<head>
<!--
noVNC example: simple example using default UI
Copyright (C) 2019 The noVNC Authors
noVNC is licensed under the MPL 2.0 (see LICENSE.txt)
This file is licensed under the 2-Clause BSD license (see LICENSE.txt).
Connect parameters are provided in query string:
http://example.com/?host=HOST&port=PORT&encrypt=1
or the fragment:
http://example.com/#host=HOST&port=PORT&encrypt=1
-->
<title>noVNC</title>
<meta charset="utf-8">
<!-- Icons (see app/images/icons/Makefile for what the sizes are for) -->
<link rel="icon" sizes="16x16" type="image/png" href="app/images/icons/novnc-16x16.png">
<link rel="icon" sizes="24x24" type="image/png" href="app/images/icons/novnc-24x24.png">
<link rel="icon" sizes="32x32" type="image/png" href="app/images/icons/novnc-32x32.png">
<link rel="icon" sizes="48x48" type="image/png" href="app/images/icons/novnc-48x48.png">
<link rel="icon" sizes="60x60" type="image/png" href="app/images/icons/novnc-60x60.png">
<link rel="icon" sizes="64x64" type="image/png" href="app/images/icons/novnc-64x64.png">
<link rel="icon" sizes="72x72" type="image/png" href="app/images/icons/novnc-72x72.png">
<link rel="icon" sizes="76x76" type="image/png" href="app/images/icons/novnc-76x76.png">
<link rel="icon" sizes="96x96" type="image/png" href="app/images/icons/novnc-96x96.png">
<link rel="icon" sizes="120x120" type="image/png" href="app/images/icons/novnc-120x120.png">
<link rel="icon" sizes="144x144" type="image/png" href="app/images/icons/novnc-144x144.png">
<link rel="icon" sizes="152x152" type="image/png" href="app/images/icons/novnc-152x152.png">
<link rel="icon" sizes="192x192" type="image/png" href="app/images/icons/novnc-192x192.png">
<!-- Firefox currently mishandles SVG, see #1419039
<link rel="icon" sizes="any" type="image/svg+xml" href="app/images/icons/novnc-icon.svg">
-->
<!-- Repeated last so that legacy handling will pick this -->
<link rel="icon" sizes="16x16" type="image/png" href="app/images/icons/novnc-16x16.png">
<!-- Apple iOS Safari settings -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<!-- Home Screen Icons (favourites and bookmarks use the normal icons) -->
<link rel="apple-touch-icon" sizes="60x60" type="image/png" href="app/images/icons/novnc-60x60.png">
<link rel="apple-touch-icon" sizes="76x76" type="image/png" href="app/images/icons/novnc-76x76.png">
<link rel="apple-touch-icon" sizes="120x120" type="image/png" href="app/images/icons/novnc-120x120.png">
<link rel="apple-touch-icon" sizes="152x152" type="image/png" href="app/images/icons/novnc-152x152.png">
<!-- Stylesheets -->
<link rel="stylesheet" href="app/styles/base.css">
<link rel="stylesheet" href="app/styles/input.css">
<!-- Images that will later appear via CSS -->
<link rel="preload" as="image" href="app/images/info.svg">
<link rel="preload" as="image" href="app/images/error.svg">
<link rel="preload" as="image" href="app/images/warning.svg">
<script type="module" crossorigin="anonymous" src="app/error-handler.js"></script>
<script type="module" crossorigin="anonymous" src="app/ui.js"></script>
</head>
<body>
<div id="noVNC_fallback_error" class="noVNC_center">
<div>
<div>noVNC encountered an error:</div>
<br>
<div id="noVNC_fallback_errormsg"></div>
</div>
</div>
<!-- noVNC Control Bar -->
<div id="noVNC_control_bar_anchor" class="noVNC_vcenter">
<div id="noVNC_control_bar">
<div id="noVNC_control_bar_handle" title="Hide/Show the control bar">
<div></div>
</div>
<div class="noVNC_scroll">
<h1 class="noVNC_logo" translate="no"><span>no</span><br>VNC</h1>
<hr>
<!-- Drag/Pan the viewport -->
<input type="image" alt="Drag" src="app/images/drag.svg" id="noVNC_view_drag_button"
class="noVNC_button noVNC_hidden" title="Move/Drag Viewport">
<!--noVNC Touch Device only buttons-->
<div id="noVNC_mobile_buttons">
<input type="image" alt="Keyboard" src="app/images/keyboard.svg" id="noVNC_keyboard_button"
class="noVNC_button" title="Show Keyboard">
</div>
<!-- Extra manual keys -->
<input type="image" alt="Extra keys" src="app/images/toggleextrakeys.svg"
id="noVNC_toggle_extra_keys_button" class="noVNC_button" title="Show Extra Keys">
<div class="noVNC_vcenter">
<div id="noVNC_modifiers" class="noVNC_panel">
<input type="image" alt="Ctrl" src="app/images/ctrl.svg" id="noVNC_toggle_ctrl_button"
class="noVNC_button" title="Toggle Ctrl">
<input type="image" alt="Alt" src="app/images/alt.svg" id="noVNC_toggle_alt_button"
class="noVNC_button" title="Toggle Alt">
<input type="image" alt="Windows" src="app/images/windows.svg" id="noVNC_toggle_windows_button"
class="noVNC_button" title="Toggle Windows">
<input type="image" alt="Tab" src="app/images/tab.svg" id="noVNC_send_tab_button"
class="noVNC_button" title="Send Tab">
<input type="image" alt="Esc" src="app/images/esc.svg" id="noVNC_send_esc_button"
class="noVNC_button" title="Send Escape">
<input type="image" alt="Ctrl+Alt+Del" src="app/images/ctrlaltdel.svg"
id="noVNC_send_ctrl_alt_del_button" class="noVNC_button" title="Send Ctrl-Alt-Del">
</div>
</div>
<!-- Shutdown/Reboot -->
<input type="image" alt="Shutdown/Reboot" src="app/images/power.svg" id="noVNC_power_button"
class="noVNC_button" title="Shutdown/Reboot...">
<div class="noVNC_vcenter">
<div id="noVNC_power" class="noVNC_panel">
<div class="noVNC_heading">
<img alt="" src="app/images/power.svg"> Power
</div>
<input type="button" id="noVNC_shutdown_button" value="Shutdown">
<input type="button" id="noVNC_reboot_button" value="Reboot">
<input type="button" id="noVNC_reset_button" value="Reset">
</div>
</div>
<!-- Clipboard -->
<input type="image" alt="Clipboard" src="app/images/clipboard.svg" id="noVNC_clipboard_button"
class="noVNC_button" title="Clipboard">
<div class="noVNC_vcenter">
<div id="noVNC_clipboard" class="noVNC_panel">
<div class="noVNC_heading">
<img alt="" src="app/images/clipboard.svg"> Clipboard
</div>
<p class="noVNC_subheading">
Edit clipboard content in the textarea below.
</p>
<textarea id="noVNC_clipboard_text" rows=5></textarea>
</div>
</div>
<!-- Toggle fullscreen -->
<input type="image" alt="Full Screen" src="app/images/fullscreen.svg" id="noVNC_fullscreen_button"
class="noVNC_button noVNC_hidden" title="Full Screen">
<!-- Settings -->
<input type="image" alt="Settings" src="app/images/settings.svg" id="noVNC_settings_button"
class="noVNC_button" title="Settings">
<div class="noVNC_vcenter">
<div id="noVNC_settings" class="noVNC_panel">
<div class="noVNC_heading">
<img alt="" src="app/images/settings.svg"> Settings
</div>
<ul>
<li>
<label><input id="noVNC_setting_shared" type="checkbox"> Shared Mode</label>
</li>
<li>
<label><input id="noVNC_setting_view_only" type="checkbox"> View Only</label>
</li>
<li>
<hr>
</li>
<li>
<label><input id="noVNC_setting_view_clip" type="checkbox"> Clip to Window</label>
</li>
<li>
<label for="noVNC_setting_resize">Scaling Mode:</label>
<select id="noVNC_setting_resize" name="vncResize">
<option value="off">None</option>
<option value="scale">Local Scaling</option>
<option value="remote">Remote Resizing</option>
</select>
</li>
<li>
<hr>
</li>
<li>
<div class="noVNC_expander">Advanced</div>
<div>
<ul>
<li>
<label for="noVNC_setting_quality">Quality:</label>
<input id="noVNC_setting_quality" type="range" min="0" max="9" value="6">
</li>
<li>
<label for="noVNC_setting_compression">Compression level:</label>
<input id="noVNC_setting_compression" type="range" min="0" max="9"
value="2">
</li>
<li>
<hr>
</li>
<li>
<label for="noVNC_setting_repeaterID">Repeater ID:</label>
<input id="noVNC_setting_repeaterID" type="text" value="">
</li>
<li>
<div class="noVNC_expander">WebSocket</div>
<div>
<ul>
<li>
<label><input id="noVNC_setting_encrypt" type="checkbox">
Encrypt</label>
</li>
<li>
<label for="noVNC_setting_host">Host:</label>
<input id="noVNC_setting_host">
</li>
<li>
<label for="noVNC_setting_port">Port:</label>
<input id="noVNC_setting_port" type="number">
</li>
<li>
<label for="noVNC_setting_path">Path:</label>
<input id="noVNC_setting_path" type="text" value="websockify">
</li>
</ul>
</div>
</li>
<li>
<hr>
</li>
<li>
<label><input id="noVNC_setting_reconnect" type="checkbox"> Automatic
Reconnect</label>
</li>
<li>
<label for="noVNC_setting_reconnect_delay">Reconnect Delay (ms):</label>
<input id="noVNC_setting_reconnect_delay" type="number">
</li>
<li>
<hr>
</li>
<li>
<label><input id="noVNC_setting_show_dot" type="checkbox"> Show Dot when No
Cursor</label>
</li>
<li>
<hr>
</li>
<!-- Logging selection dropdown -->
<li>
<label>Logging:
<select id="noVNC_setting_logging" name="vncLogging">
</select>
</label>
</li>
</ul>
</div>
</li>
<li class="noVNC_version_separator">
<hr>
</li>
<li class="noVNC_version_wrapper">
<span>Version:</span>
<span class="noVNC_version"></span>
</li>
</ul>
</div>
</div>
<!-- Connection Controls -->
<input type="image" alt="Disconnect" src="app/images/disconnect.svg" id="noVNC_disconnect_button"
class="noVNC_button" title="Disconnect">
</div>
</div>
</div> <!-- End of noVNC_control_bar -->
<div id="noVNC_hint_anchor" class="noVNC_vcenter">
<div id="noVNC_control_bar_hint">
</div>
</div>
<!-- Status Dialog -->
<div id="noVNC_status"></div>
<!-- Connect button -->
<div class="noVNC_center">
<div id="noVNC_connect_dlg">
<div class="noVNC_logo" translate="no"><span>no</span>VNC</div>
<div id="noVNC_connect_button">
<div>
<img alt="" src="app/images/connect.svg"> Connect
</div>
</div>
</div>
</div>
<!-- Server Key Verification Dialog -->
<div class="noVNC_center noVNC_connect_layer">
<div id="noVNC_verify_server_dlg" class="noVNC_panel">
<form>
<div class="noVNC_heading">
Server identity
</div>
<div>
The server has provided the following identifying information:
</div>
<div id="noVNC_fingerprint_block">
<b>Fingerprint:</b>
<span id="noVNC_fingerprint"></span>
</div>
<div>
Please verify that the information is correct and press
"Approve". Otherwise press "Reject".
</div>
<div>
<input id="noVNC_approve_server_button" type="submit" value="Approve" class="noVNC_submit">
<input id="noVNC_reject_server_button" type="button" value="Reject" class="noVNC_submit">
</div>
</form>
</div>
</div>
<!-- Password Dialog -->
<div class="noVNC_center noVNC_connect_layer">
<div id="noVNC_credentials_dlg" class="noVNC_panel">
<form>
<div class="noVNC_heading">
Credentials
</div>
<div id="noVNC_username_block">
<label for="noVNC_username_input">Username:</label>
<input id="noVNC_username_input">
</div>
<div id="noVNC_password_block">
<label for="noVNC_password_input">Password:</label>
<input id="noVNC_password_input" type="password">
</div>
<div>
<input id="noVNC_credentials_button" type="submit" value="Send Credentials" class="noVNC_submit">
</div>
</form>
</div>
</div>
<!-- Transition Screens -->
<div id="noVNC_transition">
<div id="noVNC_transition_text"></div>
<div>
<input type="button" id="noVNC_cancel_reconnect_button" value="Cancel" class="noVNC_submit">
</div>
<div class="noVNC_spinner"></div>
</div>
<!-- This is where the RFB elements will attach -->
<div id="noVNC_container">
<!-- Note that Google Chrome on Android doesn't respect any of these,
html attributes which attempt to disable text suggestions on the
on-screen keyboard. Let's hope Chrome implements the ime-mode
style for example -->
<textarea id="noVNC_keyboardinput" autocapitalize="off" autocomplete="off" spellcheck="false"
tabindex="-1"></textarea>
</div>
<script type="text/javascript" src="pcm-player.js"></script>
<script type="text/javascript" src="script.js"></script>
<audio id="noVNC_bell">
<source src="app/sounds/bell.oga" type="audio/ogg">
<source src="app/sounds/bell.mp3" type="audio/mpeg">
</audio>
</body>
</html>

@ -2,7 +2,7 @@ function PCMPlayer(option) {
this.init(option);
}
PCMPlayer.prototype.init = function(option) {
PCMPlayer.prototype.init = function (option) {
var defaults = {
encoding: '16bitInt',
channels: 1,
@ -40,7 +40,7 @@ PCMPlayer.prototype.getTypedArray = function () {
return typedArrays[this.option.encoding] ? typedArrays[this.option.encoding] : typedArrays['16bitInt'];
};
PCMPlayer.prototype.createContext = function() {
PCMPlayer.prototype.createContext = function () {
this.audioCtx = new (window.AudioContext || window.webkitAudioContext)();
// context needs to be resumed on iOS and Safari (or it will stay in "suspended" state)
@ -53,11 +53,11 @@ PCMPlayer.prototype.createContext = function() {
this.startTime = this.audioCtx.currentTime;
};
PCMPlayer.prototype.isTypedArray = function(data) {
PCMPlayer.prototype.isTypedArray = function (data) {
return (data.byteLength && data.buffer && data.buffer.constructor == ArrayBuffer);
};
PCMPlayer.prototype.feed = function(data) {
PCMPlayer.prototype.feed = function (data) {
if (!this.isTypedArray(data)) return;
data = this.getFormatedValue(data);
var tmp = new Float32Array(this.samples.length + data.length);
@ -66,7 +66,7 @@ PCMPlayer.prototype.feed = function(data) {
this.samples = tmp;
};
PCMPlayer.prototype.getFormatedValue = function(data) {
PCMPlayer.prototype.getFormatedValue = function (data) {
var data = new this.typedArray(data.buffer),
float32 = new Float32Array(data.length),
i;
@ -77,11 +77,11 @@ PCMPlayer.prototype.getFormatedValue = function(data) {
return float32;
};
PCMPlayer.prototype.volume = function(volume) {
PCMPlayer.prototype.volume = function (volume) {
this.gainNode.gain.value = volume;
};
PCMPlayer.prototype.destroy = function() {
PCMPlayer.prototype.destroy = function () {
if (this.interval) {
clearInterval(this.interval);
}
@ -90,7 +90,7 @@ PCMPlayer.prototype.destroy = function() {
this.audioCtx = null;
};
PCMPlayer.prototype.flush = function() {
PCMPlayer.prototype.flush = function () {
if (!this.samples.length) return;
var bufferSource = this.audioCtx.createBufferSource(),
length = this.samples.length / this.option.channels,
@ -122,7 +122,7 @@ PCMPlayer.prototype.flush = function() {
if (this.startTime < this.audioCtx.currentTime) {
this.startTime = this.audioCtx.currentTime;
}
console.log('start vs current '+this.startTime+' vs '+this.audioCtx.currentTime+' duration: '+audioBuffer.duration);
console.log('start vs current ' + this.startTime + ' vs ' + this.audioCtx.currentTime + ' duration: ' + audioBuffer.duration);
bufferSource.buffer = audioBuffer;
bufferSource.connect(this.gainNode);
bufferSource.start(this.startTime);

@ -1,351 +0,0 @@
<!DOCTYPE html>
<html lang="en" class="noVNC_loading">
<head>
<!--
noVNC example: simple example using default UI
Copyright (C) 2019 The noVNC Authors
noVNC is licensed under the MPL 2.0 (see LICENSE.txt)
This file is licensed under the 2-Clause BSD license (see LICENSE.txt).
Connect parameters are provided in query string:
http://example.com/?host=HOST&port=PORT&encrypt=1
or the fragment:
http://example.com/#host=HOST&port=PORT&encrypt=1
-->
<title>noVNC</title>
<meta charset="utf-8">
<!-- Icons (see app/images/icons/Makefile for what the sizes are for) -->
<link rel="icon" sizes="16x16" type="image/png" href="app/images/icons/novnc-16x16.png">
<link rel="icon" sizes="24x24" type="image/png" href="app/images/icons/novnc-24x24.png">
<link rel="icon" sizes="32x32" type="image/png" href="app/images/icons/novnc-32x32.png">
<link rel="icon" sizes="48x48" type="image/png" href="app/images/icons/novnc-48x48.png">
<link rel="icon" sizes="60x60" type="image/png" href="app/images/icons/novnc-60x60.png">
<link rel="icon" sizes="64x64" type="image/png" href="app/images/icons/novnc-64x64.png">
<link rel="icon" sizes="72x72" type="image/png" href="app/images/icons/novnc-72x72.png">
<link rel="icon" sizes="76x76" type="image/png" href="app/images/icons/novnc-76x76.png">
<link rel="icon" sizes="96x96" type="image/png" href="app/images/icons/novnc-96x96.png">
<link rel="icon" sizes="120x120" type="image/png" href="app/images/icons/novnc-120x120.png">
<link rel="icon" sizes="144x144" type="image/png" href="app/images/icons/novnc-144x144.png">
<link rel="icon" sizes="152x152" type="image/png" href="app/images/icons/novnc-152x152.png">
<link rel="icon" sizes="192x192" type="image/png" href="app/images/icons/novnc-192x192.png">
<!-- Firefox currently mishandles SVG, see #1419039
<link rel="icon" sizes="any" type="image/svg+xml" href="app/images/icons/novnc-icon.svg">
-->
<!-- Repeated last so that legacy handling will pick this -->
<link rel="icon" sizes="16x16" type="image/png" href="app/images/icons/novnc-16x16.png">
<!-- Apple iOS Safari settings -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<!-- Home Screen Icons (favourites and bookmarks use the normal icons) -->
<link rel="apple-touch-icon" sizes="60x60" type="image/png" href="app/images/icons/novnc-60x60.png">
<link rel="apple-touch-icon" sizes="76x76" type="image/png" href="app/images/icons/novnc-76x76.png">
<link rel="apple-touch-icon" sizes="120x120" type="image/png" href="app/images/icons/novnc-120x120.png">
<link rel="apple-touch-icon" sizes="152x152" type="image/png" href="app/images/icons/novnc-152x152.png">
<!-- Stylesheets -->
<link rel="stylesheet" href="app/styles/base.css">
<link rel="stylesheet" href="app/styles/input.css">
<!-- Images that will later appear via CSS -->
<link rel="preload" as="image" href="app/images/info.svg">
<link rel="preload" as="image" href="app/images/error.svg">
<link rel="preload" as="image" href="app/images/warning.svg">
<script type="module" crossorigin="anonymous" src="app/error-handler.js"></script>
<script type="module" crossorigin="anonymous" src="app/ui.js"></script>
</head>
<body>
<div id="noVNC_fallback_error" class="noVNC_center">
<div>
<div>noVNC encountered an error:</div>
<br>
<div id="noVNC_fallback_errormsg"></div>
</div>
</div>
<!-- noVNC Control Bar -->
<div id="noVNC_control_bar_anchor" class="noVNC_vcenter">
<div id="noVNC_control_bar">
<div id="noVNC_control_bar_handle" title="Hide/Show the control bar"><div></div></div>
<div class="noVNC_scroll">
<h1 class="noVNC_logo" translate="no"><span>no</span><br>VNC</h1>
<hr>
<!-- Drag/Pan the viewport -->
<input type="image" alt="Drag" src="app/images/drag.svg"
id="noVNC_view_drag_button" class="noVNC_button noVNC_hidden"
title="Move/Drag Viewport">
<!--noVNC Touch Device only buttons-->
<div id="noVNC_mobile_buttons">
<input type="image" alt="Keyboard" src="app/images/keyboard.svg"
id="noVNC_keyboard_button" class="noVNC_button" title="Show Keyboard">
</div>
<!-- Extra manual keys -->
<input type="image" alt="Extra keys" src="app/images/toggleextrakeys.svg"
id="noVNC_toggle_extra_keys_button" class="noVNC_button"
title="Show Extra Keys">
<div class="noVNC_vcenter">
<div id="noVNC_modifiers" class="noVNC_panel">
<input type="image" alt="Ctrl" src="app/images/ctrl.svg"
id="noVNC_toggle_ctrl_button" class="noVNC_button"
title="Toggle Ctrl">
<input type="image" alt="Alt" src="app/images/alt.svg"
id="noVNC_toggle_alt_button" class="noVNC_button"
title="Toggle Alt">
<input type="image" alt="Windows" src="app/images/windows.svg"
id="noVNC_toggle_windows_button" class="noVNC_button"
title="Toggle Windows">
<input type="image" alt="Tab" src="app/images/tab.svg"
id="noVNC_send_tab_button" class="noVNC_button"
title="Send Tab">
<input type="image" alt="Esc" src="app/images/esc.svg"
id="noVNC_send_esc_button" class="noVNC_button"
title="Send Escape">
<input type="image" alt="Ctrl+Alt+Del" src="app/images/ctrlaltdel.svg"
id="noVNC_send_ctrl_alt_del_button" class="noVNC_button"
title="Send Ctrl-Alt-Del">
</div>
</div>
<!-- Shutdown/Reboot -->
<input type="image" alt="Shutdown/Reboot" src="app/images/power.svg"
id="noVNC_power_button" class="noVNC_button"
title="Shutdown/Reboot...">
<div class="noVNC_vcenter">
<div id="noVNC_power" class="noVNC_panel">
<div class="noVNC_heading">
<img alt="" src="app/images/power.svg"> Power
</div>
<input type="button" id="noVNC_shutdown_button" value="Shutdown">
<input type="button" id="noVNC_reboot_button" value="Reboot">
<input type="button" id="noVNC_reset_button" value="Reset">
</div>
</div>
<!-- Clipboard -->
<input type="image" alt="Clipboard" src="app/images/clipboard.svg"
id="noVNC_clipboard_button" class="noVNC_button"
title="Clipboard">
<div class="noVNC_vcenter">
<div id="noVNC_clipboard" class="noVNC_panel">
<div class="noVNC_heading">
<img alt="" src="app/images/clipboard.svg"> Clipboard
</div>
<p class="noVNC_subheading">
Edit clipboard content in the textarea below.
</p>
<textarea id="noVNC_clipboard_text" rows=5></textarea>
</div>
</div>
<!-- Toggle fullscreen -->
<input type="image" alt="Full Screen" src="app/images/fullscreen.svg"
id="noVNC_fullscreen_button" class="noVNC_button noVNC_hidden"
title="Full Screen">
<!-- Settings -->
<input type="image" alt="Settings" src="app/images/settings.svg"
id="noVNC_settings_button" class="noVNC_button"
title="Settings">
<div class="noVNC_vcenter">
<div id="noVNC_settings" class="noVNC_panel">
<div class="noVNC_heading">
<img alt="" src="app/images/settings.svg"> Settings
</div>
<ul>
<li>
<label><input id="noVNC_setting_shared" type="checkbox"> Shared Mode</label>
</li>
<li>
<label><input id="noVNC_setting_view_only" type="checkbox"> View Only</label>
</li>
<li><hr></li>
<li>
<label><input id="noVNC_setting_view_clip" type="checkbox"> Clip to Window</label>
</li>
<li>
<label for="noVNC_setting_resize">Scaling Mode:</label>
<select id="noVNC_setting_resize" name="vncResize">
<option value="off">None</option>
<option value="scale">Local Scaling</option>
<option value="remote">Remote Resizing</option>
</select>
</li>
<li><hr></li>
<li>
<div class="noVNC_expander">Advanced</div>
<div><ul>
<li>
<label for="noVNC_setting_quality">Quality:</label>
<input id="noVNC_setting_quality" type="range" min="0" max="9" value="6">
</li>
<li>
<label for="noVNC_setting_compression">Compression level:</label>
<input id="noVNC_setting_compression" type="range" min="0" max="9" value="2">
</li>
<li><hr></li>
<li>
<label for="noVNC_setting_repeaterID">Repeater ID:</label>
<input id="noVNC_setting_repeaterID" type="text" value="">
</li>
<li>
<div class="noVNC_expander">WebSocket</div>
<div><ul>
<li>
<label><input id="noVNC_setting_encrypt" type="checkbox"> Encrypt</label>
</li>
<li>
<label for="noVNC_setting_host">Host:</label>
<input id="noVNC_setting_host">
</li>
<li>
<label for="noVNC_setting_port">Port:</label>
<input id="noVNC_setting_port" type="number">
</li>
<li>
<label for="noVNC_setting_path">Path:</label>
<input id="noVNC_setting_path" type="text" value="websockify">
</li>
</ul></div>
</li>
<li><hr></li>
<li>
<label><input id="noVNC_setting_reconnect" type="checkbox"> Automatic Reconnect</label>
</li>
<li>
<label for="noVNC_setting_reconnect_delay">Reconnect Delay (ms):</label>
<input id="noVNC_setting_reconnect_delay" type="number">
</li>
<li><hr></li>
<li>
<label><input id="noVNC_setting_show_dot" type="checkbox"> Show Dot when No Cursor</label>
</li>
<li><hr></li>
<!-- Logging selection dropdown -->
<li>
<label>Logging:
<select id="noVNC_setting_logging" name="vncLogging">
</select>
</label>
</li>
</ul></div>
</li>
<li class="noVNC_version_separator"><hr></li>
<li class="noVNC_version_wrapper">
<span>Version:</span>
<span class="noVNC_version"></span>
</li>
</ul>
</div>
</div>
<!-- Connection Controls -->
<input type="image" alt="Disconnect" src="app/images/disconnect.svg"
id="noVNC_disconnect_button" class="noVNC_button"
title="Disconnect">
</div>
</div>
</div> <!-- End of noVNC_control_bar -->
<div id="noVNC_hint_anchor" class="noVNC_vcenter">
<div id="noVNC_control_bar_hint">
</div>
</div>
<!-- Status Dialog -->
<div id="noVNC_status"></div>
<!-- Connect button -->
<div class="noVNC_center">
<div id="noVNC_connect_dlg">
<div class="noVNC_logo" translate="no"><span>no</span>VNC</div>
<div id="noVNC_connect_button"><div>
<img alt="" src="app/images/connect.svg"> Connect
</div></div>
</div>
</div>
<!-- Server Key Verification Dialog -->
<div class="noVNC_center noVNC_connect_layer">
<div id="noVNC_verify_server_dlg" class="noVNC_panel"><form>
<div class="noVNC_heading">
Server identity
</div>
<div>
The server has provided the following identifying information:
</div>
<div id="noVNC_fingerprint_block">
<b>Fingerprint:</b>
<span id="noVNC_fingerprint"></span>
</div>
<div>
Please verify that the information is correct and press
"Approve". Otherwise press "Reject".
</div>
<div>
<input id="noVNC_approve_server_button" type="submit" value="Approve" class="noVNC_submit">
<input id="noVNC_reject_server_button" type="button" value="Reject" class="noVNC_submit">
</div>
</form></div>
</div>
<!-- Password Dialog -->
<div class="noVNC_center noVNC_connect_layer">
<div id="noVNC_credentials_dlg" class="noVNC_panel"><form>
<div class="noVNC_heading">
Credentials
</div>
<div id="noVNC_username_block">
<label for="noVNC_username_input">Username:</label>
<input id="noVNC_username_input">
</div>
<div id="noVNC_password_block">
<label for="noVNC_password_input">Password:</label>
<input id="noVNC_password_input" type="password">
</div>
<div>
<input id="noVNC_credentials_button" type="submit" value="Send Credentials" class="noVNC_submit">
</div>
</form></div>
</div>
<!-- Transition Screens -->
<div id="noVNC_transition">
<div id="noVNC_transition_text"></div>
<div>
<input type="button" id="noVNC_cancel_reconnect_button" value="Cancel" class="noVNC_submit">
</div>
<div class="noVNC_spinner"></div>
</div>
<!-- This is where the RFB elements will attach -->
<div id="noVNC_container">
<!-- Note that Google Chrome on Android doesn't respect any of these,
html attributes which attempt to disable text suggestions on the
on-screen keyboard. Let's hope Chrome implements the ime-mode
style for example -->
<textarea id="noVNC_keyboardinput" autocapitalize="off"
autocomplete="off" spellcheck="false" tabindex="-1"></textarea>
</div>
<script type="text/javascript" src="pcm-player.js"></script>
<script type="text/javascript" src="script.js"></script>
<audio id="noVNC_bell">
<source src="app/sounds/bell.oga" type="audio/ogg">
<source src="app/sounds/bell.mp3" type="audio/mpeg">
</audio>
</body>
</html>
Loading…
Cancel
Save