I may have created my own dead simple static site generation
74
build.py
Normal file
|
@ -0,0 +1,74 @@
|
|||
import os
|
||||
import shutil
|
||||
from dataclasses import dataclass
|
||||
import markdown
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
|
||||
|
||||
@dataclass
|
||||
class Section:
|
||||
name: str
|
||||
type: str
|
||||
content: str = ""
|
||||
|
||||
def render(self) -> str:
|
||||
"""Render the section content based on its type."""
|
||||
if self.type.lower() == "html":
|
||||
return self.content
|
||||
elif self.type.lower() == "markdown":
|
||||
return markdown.markdown(
|
||||
self.content,
|
||||
extensions=[
|
||||
"pymdownx.blocks.html",
|
||||
"markdown.extensions.def_list",
|
||||
"sane_lists",
|
||||
"pymdownx.blocks.tab",
|
||||
],
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"Unsupported content type: {self.type}")
|
||||
|
||||
@classmethod
|
||||
def open(cls, filename: str) -> dict[str, "Section"]:
|
||||
"""Open a file and return its contents."""
|
||||
env = {}
|
||||
with open(filename, "r") as file:
|
||||
content = file.readlines()
|
||||
key = None
|
||||
for line in content:
|
||||
if line.startswith("!!section:"):
|
||||
keyline = line[10:].strip().split(",")
|
||||
key = keyline[0].strip()
|
||||
content_type = keyline[1].strip() if len(keyline) > 1 else "HTML"
|
||||
|
||||
env[key] = cls(name=key, type=content_type, content="")
|
||||
elif key is not None and env[key] is not None:
|
||||
env[key].content += line
|
||||
return env
|
||||
|
||||
|
||||
def main() -> None:
|
||||
env = Environment(loader=FileSystemLoader("."))
|
||||
|
||||
template = env.get_template("site.template.html")
|
||||
|
||||
sites = os.listdir("sites")
|
||||
for site in sites:
|
||||
sitename, _ = os.path.splitext(site)
|
||||
print(f"Found site: {sitename}")
|
||||
site_config = {k: v.render() for k, v in Section.open(f"sites/{site}").items()}
|
||||
rendered_html = template.render(site_config)
|
||||
os.makedirs("dist", exist_ok=True)
|
||||
with open(f"dist/{sitename}.html", "w") as f:
|
||||
f.write(rendered_html)
|
||||
|
||||
static_folders = ["css", "js", "images"]
|
||||
for folder in static_folders:
|
||||
src_folder = os.path.join(folder)
|
||||
dst_folder = os.path.join("dist", folder)
|
||||
shutil.rmtree(dst_folder, ignore_errors=True)
|
||||
shutil.copytree(src_folder, dst_folder)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -7,7 +7,7 @@
|
|||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.textleft .work-feature-block-image {
|
||||
.showcase-image img {
|
||||
display: block;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
|
@ -50,7 +50,7 @@
|
|||
justify-content: space-between;
|
||||
}
|
||||
body {
|
||||
background: url("../images/background_small.jpg") center center no-repeat;
|
||||
background: url("../images/background_smaller.jpg") center center no-repeat;
|
||||
background-size: cover;
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
|
132
dist/css/app.css
vendored
Normal file
|
@ -0,0 +1,132 @@
|
|||
.hero-section-text {
|
||||
display: block;
|
||||
color: #0a0a0a;
|
||||
text-shadow: 1px 1px 2px #fefefe;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.showcase-image img {
|
||||
display: block;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
max-height: 500px;
|
||||
/* width: 100%; */
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.textleft .text {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.grid-container h1 {
|
||||
border-bottom: 1px solid #0a0a0a;
|
||||
}
|
||||
|
||||
.textright .work-feature-block-image {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-height: 500px;
|
||||
/* width: 100%; */
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.hero-full-screen {
|
||||
padding-top: 100px;
|
||||
margin-bottom: 100px;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-flex-direction: column;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-webkit-align-items: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
-webkit-justify-content: space-between;
|
||||
-ms-flex-pack: justify;
|
||||
justify-content: space-between;
|
||||
}
|
||||
body {
|
||||
background: url("../images/background_smaller.jpg") center center no-repeat;
|
||||
background-size: cover;
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
.hero-full-screen .middle-content-section {
|
||||
/* text-align: center; */
|
||||
color: #fefefe;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.hero-full-screen .middle-content-section {
|
||||
width: 100%;
|
||||
}
|
||||
.overview-image {
|
||||
display: none;
|
||||
}
|
||||
#main-content-section .grid-container {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.top-content-section {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.hero-full-screen .bottom-content-section {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.hero-full-screen .bottom-content-section svg {
|
||||
height: 3.75rem;
|
||||
width: 3.75rem;
|
||||
fill: #fefefe;
|
||||
}
|
||||
|
||||
.top-bar {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.top-bar .menu {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.top-bar .menu-text {
|
||||
color: #fefefe;
|
||||
}
|
||||
|
||||
.top-bar img {
|
||||
height: 2.5rem;
|
||||
width: 2.5rem;
|
||||
}
|
||||
|
||||
.top-bar .menu li {
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-align-items: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.top-bar .menu a {
|
||||
color: #fefefe;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#main-content-section .grid-container {
|
||||
margin: auto;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
border-radius: 10px;
|
||||
padding: 20px;
|
||||
/* max-width: 50%; */
|
||||
}
|
||||
#main-content-section .grid-container .grid-x {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
7753
dist/css/foundation.css
vendored
Normal file
1
dist/css/foundation.min.css
vendored
Normal file
114
dist/faq.html
vendored
Normal file
|
@ -0,0 +1,114 @@
|
|||
|
||||
<!doctype html>
|
||||
<html class="no-js" lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Syng.Rocks</title>
|
||||
<link rel="stylesheet" href="css/foundation.css">
|
||||
<link rel="stylesheet" href="css/app.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="top-content-section">
|
||||
<div class="top-bar">
|
||||
<div class="top-bar-left">
|
||||
<ul class="menu">
|
||||
<li class="menu-text"><img src="images/rocks.syng.Syng.png" alt="Syng.Rocks! Logo" height=30></li>
|
||||
|
||||
<li><a href="index.html">Home</a></li>
|
||||
|
||||
<li><a href="install.html">Installation</a></li>
|
||||
|
||||
<li><a href="faq.html">FAQ</a></li>
|
||||
|
||||
<li><a href="privacy.html">Privacy Policy</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="main-content-section" style="padding-top: 100px;">
|
||||
<div class="grid-container">
|
||||
<h1>FAQ</h1>
|
||||
<dl>
|
||||
<dt>Is using Syng.Rocks! free?</dt>
|
||||
<dd>
|
||||
<p>Yes, Syng.Rocks! is free software and licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). You can use it for free without any limitations.</p>
|
||||
</dd>
|
||||
<dt>Can you add a specific song?</dt>
|
||||
<dd>
|
||||
<p>Syng.Rocks! does not host any songs itself. The client fetches songs from YouTube or any of your configured sources.</p>
|
||||
</dd>
|
||||
<dt>What are sources?</dt>
|
||||
<dd>
|
||||
<p>Since Syng.Rocks! does not host any songs itself, songs played by the playback client, need to come from external sources. Currently, the following sources can be added:</p>
|
||||
<ul>
|
||||
<li>YouTube</li>
|
||||
<li>Any S3 compatible server</li>
|
||||
<li>A local directory</li>
|
||||
</ul>
|
||||
<p>The sources are accessed from the playback client directly, the server is unaware of the contents of the sources and just uses a list of filenames to search for songs.</p>
|
||||
</dd>
|
||||
<dt>What file format can Syng.Rocks! play?</dt>
|
||||
<dd>
|
||||
<p>Syng.Rocks! uses <a href="https://mpv.io">MPV</a> to play the karaoke songs, so it supports most video formats including <code>cdg+mp3</code>.</p>
|
||||
</dd>
|
||||
<dt>What do you mean by <em>Playback Client</em>, <em>Web Client</em> and <em>Server</em>?</dt>
|
||||
<dd>
|
||||
<p>The <em>Playback Client</em> is the application that plays the songs and displays the lyrics. It is a desktop application.
|
||||
The <em>Web Client</em> is the web application that allows you to manage the queue and search for songs. It is used by the guests to add songs to the queue.
|
||||
The <em>Server</em> is the backend that manages the queue and handles connection between web clients and playback clients.</p>
|
||||
<p>If you only want to host a karaoke event, you only need the playback client.
|
||||
The server is optional, as you can use the public server at <a href="https://syng.rocks">syng.rocks</a>.</p>
|
||||
</dd>
|
||||
<dt>Can I use Syng.Rocks! without internet?</dt>
|
||||
<dd>
|
||||
<p>Yes and no. The playback client needs to connect to a server instance. While you can host the server yourself in your intranet, the experience can be limited, as some source (such as YouTube) need the playback client to reach YouTube. You can however use local and s3 sources, that are reachable from the playback client.</p>
|
||||
</dd>
|
||||
<dt>Can I use Syng.Rocks! without a server?</dt>
|
||||
<dd>
|
||||
<p>You do need some kind of server to manage the queue, but you can use the public server at <a href="https://syng.rocks">syng.rocks</a> to host your karaoke events. No need to roll up your own server.</p>
|
||||
</dd>
|
||||
<dt>Can I host my own server?</dt>
|
||||
<dd>
|
||||
<p>Yes, you can host your own server. The server is available as a Docker image on GitHub, or you can install it using the Python Package Index (PyPI) package <code>syng[server]</code>.
|
||||
For more information, see the <a href="install.html">installation instructions</a>.</p>
|
||||
</dd>
|
||||
<dt><a id="waiting-room"></a>What is the waiting room?</dt>
|
||||
<dd>
|
||||
<p>The waiting room is a feature that allows you to limit the amount of songs a guest can have in the queue.
|
||||
If the waiting room is enabled, guests can only add songs to the queue if they have no songs in the queue. All additional songs are placed in a waiting room and automatically leave the queue once no songs of the guest are left in the queue.</p>
|
||||
</dd>
|
||||
<dt>What data do you store?</dt>
|
||||
<dd>
|
||||
<p>Syng.Rocks! does not store any personal data. The server only stores the current state of the queue.
|
||||
If you use the public server at <a href="https://syng.rocks">syng.rocks</a>, the server will also store your IP address for a limited time to prevent abuse.
|
||||
For more information, see the <a href="privacy.html">privacy policy</a>.</p>
|
||||
</dd>
|
||||
<dt>I cannot connect to <a href="https://syng.rocks">syng.rocks</a>.</dt>
|
||||
<dd>
|
||||
<p>Sometimes the server is down for maintenance. Check the official <a href="https://floss.social/@syng">Mastodon account</a> for announcements. Also check, if your client is up-to-date. The server is only compatible with the latest release.</p>
|
||||
</dd>
|
||||
<dt>What is the restricted mode of the server?</dt>
|
||||
<dd>
|
||||
<p>When the server is in restricted mode, <em>server side search</em> is only available to authenticated rooms. For other rooms, a search request is forwarded to the playback client and results are then sent back to the web client.</p>
|
||||
</dd>
|
||||
<dt>Something does not work, or I have questions not covered here</dt>
|
||||
<dd>
|
||||
<p>Feel free to open an issue on the official issue tracker on <a href="https://github.com/christofsteel/syng/issues">GitHub</a> or reach out to us at our official Mastodon account: <a href="https://floss.social/@syng">@syng@floss.social</a> account or join our official matrix room: <a href="https://matrix.to/#/#syng:matrix.org">#syng:matrix.org</a>.</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="js/vendor/jquery.js"></script>
|
||||
<script src="js/vendor/what-input.js"></script>
|
||||
<script src="js/vendor/foundation.js"></script>
|
||||
<script src="js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
BIN
dist/images/background.jpg
vendored
Normal file
After Width: | Height: | Size: 1.2 MiB |
BIN
dist/images/background_small.jpg
vendored
Normal file
After Width: | Height: | Size: 348 KiB |
BIN
dist/images/background_smaller.jpg
vendored
Normal file
After Width: | Height: | Size: 165 KiB |
BIN
dist/images/overview.png
vendored
Normal file
After Width: | Height: | Size: 276 KiB |
BIN
dist/images/overview.xcf
vendored
Normal file
BIN
dist/images/rocks.syng.Syng.png
vendored
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
dist/images/sources.png
vendored
Normal file
After Width: | Height: | Size: 183 KiB |
742
dist/images/sources.svg
vendored
Normal file
|
@ -0,0 +1,742 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="210.547mm"
|
||||
height="87.391151mm"
|
||||
viewBox="0 0 210.547 87.391151"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xml:space="preserve"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
sodipodi:docname="sources.svg"
|
||||
inkscape:export-filename="sources.png"
|
||||
inkscape:export-xdpi="266.60046"
|
||||
inkscape:export-ydpi="266.60046"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:i="&ns_ai;"
|
||||
xmlns:ns="&#38;ns_ai;"><sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="0.54440085"
|
||||
inkscape:cx="451.87291"
|
||||
inkscape:cy="-17.450377"
|
||||
inkscape:window-width="1440"
|
||||
inkscape:window-height="888"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" /><defs
|
||||
id="defs1"><clipPath
|
||||
id="_clipPath_iJhCLJIxvnBD6H216wD2nheMtI7NQsNe"><rect
|
||||
width="48"
|
||||
height="48"
|
||||
id="rect1"
|
||||
x="0"
|
||||
y="0" /></clipPath><clipPath
|
||||
id="_clipPath_iJhCLJIxvnBD6H216wD2nheMtI7NQsNe-3"><rect
|
||||
width="48"
|
||||
height="48"
|
||||
id="rect1-5"
|
||||
x="0"
|
||||
y="0" /></clipPath><filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
inkscape:label="Blur"
|
||||
id="filter44"
|
||||
x="-0.039903544"
|
||||
y="-0.020766242"
|
||||
width="1.0798071"
|
||||
height="1.0415325"><feGaussianBlur
|
||||
stdDeviation="2 2"
|
||||
result="fbSourceGraphic"
|
||||
id="feGaussianBlur44" /><feColorMatrix
|
||||
result="fbSourceGraphicAlpha"
|
||||
in="fbSourceGraphic"
|
||||
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
|
||||
id="feColorMatrix78" /><feGaussianBlur
|
||||
id="feGaussianBlur78"
|
||||
stdDeviation="3 3"
|
||||
result="blur"
|
||||
in="fbSourceGraphic" /></filter><filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
inkscape:label="Blur"
|
||||
id="filter45"
|
||||
x="-0.20689655"
|
||||
y="-0.3"
|
||||
width="1.4137931"
|
||||
height="1.6"><feGaussianBlur
|
||||
stdDeviation="2 2"
|
||||
result="blur"
|
||||
id="feGaussianBlur45" /></filter><filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
inkscape:label="Blur"
|
||||
id="filter46"
|
||||
x="-0.025940825"
|
||||
y="-0.019008118"
|
||||
width="1.0518816"
|
||||
height="1.0380162"><feGaussianBlur
|
||||
stdDeviation="2 2"
|
||||
result="fbSourceGraphic"
|
||||
id="feGaussianBlur46" /><feColorMatrix
|
||||
result="fbSourceGraphicAlpha"
|
||||
in="fbSourceGraphic"
|
||||
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
|
||||
id="feColorMatrix77" /><feGaussianBlur
|
||||
id="feGaussianBlur77"
|
||||
stdDeviation="3 3"
|
||||
result="blur"
|
||||
in="fbSourceGraphic" /></filter></defs><g
|
||||
clip-path="url(#_clipPath_iJhCLJIxvnBD6H216wD2nheMtI7NQsNe-3)"
|
||||
inkscape:label="Design.svg"
|
||||
transform="matrix(2.9374705,0,0,3.4117573,-19.762837,-35.044531)"
|
||||
id="g2-9"
|
||||
style="fill:#000000;filter:url(#filter45)"><rect
|
||||
x="19.393"
|
||||
y="19.603001"
|
||||
width="9.8009996"
|
||||
height="9.0889997"
|
||||
fill="#ffffff"
|
||||
id="rect2-1"
|
||||
style="fill:#000000" /><path
|
||||
d="m 35.2,18.5 c 0,-0.1 0,-0.2 -0.1,-0.3 0,0 0,-0.1 0,-0.1 C 34.8,17.2 34,16.6 33,16.6 h 0.2 c 0,0 -3.9,-0.6 -9.2,-0.6 -5.2,0 -9.2,0.6 -9.2,0.6 H 15 c -1,0 -1.8,0.6 -2.1,1.5 0,0 0,0.1 0,0.1 0,0.1 0,0.2 -0.1,0.3 -0.1,1 -0.4,3.1 -0.4,5.5 0,2.4 0.3,4.5 0.4,5.5 0,0.1 0,0.2 0.1,0.3 0,0 0,0.1 0,0.1 0.3,0.9 1.1,1.5 2.1,1.5 h -0.2 c 0,0 3.9,0.6 9.2,0.6 5.2,0 9.2,-0.6 9.2,-0.6 H 33 c 1,0 1.8,-0.6 2.1,-1.5 0,0 0,-0.1 0,-0.1 0,-0.1 0,-0.2 0.1,-0.3 0.1,-1 0.4,-3.1 0.4,-5.5 0,-2.4 -0.2,-4.5 -0.4,-5.5 z m -7.8,6 -4.7,3.4 C 22.6,28 22.5,28 22.4,28 c -0.1,0 -0.2,0 -0.3,-0.1 -0.2,-0.1 -0.3,-0.3 -0.3,-0.5 v -6.8 c 0,-0.2 0.1,-0.4 0.3,-0.5 0.2,-0.1 0.4,-0.1 0.6,0 l 4.7,3.4 c 0.1,0.1 0.2,0.3 0.2,0.5 0.1,0.2 0,0.4 -0.2,0.5 z"
|
||||
fill="#ca3737"
|
||||
id="path2-2"
|
||||
style="fill:#000000" /></g><switch
|
||||
id="switch3-7"
|
||||
transform="matrix(0.14520157,0,0,0.14520157,146.27311,-11.962151)"
|
||||
style="fill:#000000;filter:url(#filter44)">
|
||||
<foreignObject
|
||||
requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/"
|
||||
x="0"
|
||||
y="0"
|
||||
width="1"
|
||||
height="1">
|
||||
|
||||
</foreignObject>
|
||||
<g
|
||||
ns:extraneous="self"
|
||||
id="g3-0"
|
||||
style="fill:#000000">
|
||||
<g
|
||||
id="g2-3-9"
|
||||
style="fill:#000000">
|
||||
<path
|
||||
fill="#f15a29"
|
||||
d="m 319.096,122.504 c 0,0 56.734,91.377 75.696,123.853 0.306,0.529 0.176,1.228 -0.28,1.684 -0.575,0.57 -1.441,0.637 -2.011,0.062 L 294.745,145.864 Z"
|
||||
id="path1-3"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
d="m 151.967,455.475 c 16.593,-35.104 38.975,-66.865 66.674,-94.564 10.535,-10.53 21.656,-20.288 33.321,-29.253 v 72.348 z m -57.734,66.818 157.729,-80.297 v 183.557 l 35.544,46.691 V 423.713 l 21.589,-11.105 c 9.945,-4.996 19.272,-11.644 27.569,-19.946 41.115,-41.11 41.768,-107.467 1.824,-149.293 l -81.484,-84.894 c -3.249,-3.472 -4.954,-8.017 -4.804,-12.795 0.15,-4.809 2.161,-9.276 5.659,-12.572 7.214,-6.783 18.708,-6.327 25.491,0.881 l 11.396,11.878 24.351,-23.361 C 290.326,85.189 255.123,89.874 234.732,108.54 c -10.053,9.463 -15.826,22.278 -16.262,36.083 -0.435,13.826 4.545,26.978 14.013,37.037 l 0.109,0.119 81.909,85.324 c 26.937,28.668 26.398,73.758 -1.622,101.772 -4.369,4.369 -9.157,8.069 -14.23,11.105 l -11.142,5.731 V 269.746 c -34.078,17.562 -65.155,40.125 -92.553,67.529 -34.124,34.119 -60.916,73.861 -79.634,118.117 -9.184,21.708 -16.221,44.064 -21.087,66.901"
|
||||
id="path2-6-6"
|
||||
style="fill:#000000" />
|
||||
</g>
|
||||
</g>
|
||||
</switch><g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-4.2133262,-15.880973)"><g
|
||||
clip-path="url(#_clipPath_iJhCLJIxvnBD6H216wD2nheMtI7NQsNe)"
|
||||
inkscape:label="Design.svg"
|
||||
transform="matrix(2.9374705,0,0,3.4117573,-17.394632,-23.446126)"
|
||||
id="g2"><rect
|
||||
x="19.393"
|
||||
y="19.603001"
|
||||
width="9.8009996"
|
||||
height="9.0889997"
|
||||
fill="#ffffff"
|
||||
id="rect2" /><path
|
||||
d="m 35.2,18.5 c 0,-0.1 0,-0.2 -0.1,-0.3 0,0 0,-0.1 0,-0.1 C 34.8,17.2 34,16.6 33,16.6 h 0.2 c 0,0 -3.9,-0.6 -9.2,-0.6 -5.2,0 -9.2,0.6 -9.2,0.6 H 15 c -1,0 -1.8,0.6 -2.1,1.5 0,0 0,0.1 0,0.1 0,0.1 0,0.2 -0.1,0.3 -0.1,1 -0.4,3.1 -0.4,5.5 0,2.4 0.3,4.5 0.4,5.5 0,0.1 0,0.2 0.1,0.3 0,0 0,0.1 0,0.1 0.3,0.9 1.1,1.5 2.1,1.5 h -0.2 c 0,0 3.9,0.6 9.2,0.6 5.2,0 9.2,-0.6 9.2,-0.6 H 33 c 1,0 1.8,-0.6 2.1,-1.5 0,0 0,-0.1 0,-0.1 0,-0.1 0,-0.2 0.1,-0.3 0.1,-1 0.4,-3.1 0.4,-5.5 0,-2.4 -0.2,-4.5 -0.4,-5.5 z m -7.8,6 -4.7,3.4 C 22.6,28 22.5,28 22.4,28 c -0.1,0 -0.2,0 -0.3,-0.1 -0.2,-0.1 -0.3,-0.3 -0.3,-0.5 v -6.8 c 0,-0.2 0.1,-0.4 0.3,-0.5 0.2,-0.1 0.4,-0.1 0.6,0 l 4.7,3.4 c 0.1,0.1 0.2,0.3 0.2,0.5 0.1,0.2 0,0.4 -0.2,0.5 z"
|
||||
fill="#ca3737"
|
||||
id="path2" /></g><switch
|
||||
id="switch3"
|
||||
transform="matrix(0.14520157,0,0,0.14520157,149.58394,2.7783219)">
|
||||
<foreignObject
|
||||
requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/"
|
||||
x="0"
|
||||
y="0"
|
||||
width="1"
|
||||
height="1">
|
||||
|
||||
</foreignObject>
|
||||
<g
|
||||
i:extraneous="self"
|
||||
id="g3">
|
||||
<g
|
||||
id="g2-3">
|
||||
<path
|
||||
fill="#f15a29"
|
||||
d="m 319.096,122.504 c 0,0 56.734,91.377 75.696,123.853 0.306,0.529 0.176,1.228 -0.28,1.684 -0.575,0.57 -1.441,0.637 -2.011,0.062 L 294.745,145.864 Z"
|
||||
id="path1" />
|
||||
<path
|
||||
d="m 151.967,455.475 c 16.593,-35.104 38.975,-66.865 66.674,-94.564 10.535,-10.53 21.656,-20.288 33.321,-29.253 v 72.348 z m -57.734,66.818 157.729,-80.297 v 183.557 l 35.544,46.691 V 423.713 l 21.589,-11.105 c 9.945,-4.996 19.272,-11.644 27.569,-19.946 41.115,-41.11 41.768,-107.467 1.824,-149.293 l -81.484,-84.894 c -3.249,-3.472 -4.954,-8.017 -4.804,-12.795 0.15,-4.809 2.161,-9.276 5.659,-12.572 7.214,-6.783 18.708,-6.327 25.491,0.881 l 11.396,11.878 24.351,-23.361 C 290.326,85.189 255.123,89.874 234.732,108.54 c -10.053,9.463 -15.826,22.278 -16.262,36.083 -0.435,13.826 4.545,26.978 14.013,37.037 l 0.109,0.119 81.909,85.324 c 26.937,28.668 26.398,73.758 -1.622,101.772 -4.369,4.369 -9.157,8.069 -14.23,11.105 l -11.142,5.731 V 269.746 c -34.078,17.562 -65.155,40.125 -92.553,67.529 -34.124,34.119 -60.916,73.861 -79.634,118.117 -9.184,21.708 -16.221,44.064 -21.087,66.901"
|
||||
id="path2-6" />
|
||||
</g>
|
||||
</g>
|
||||
</switch></g><g
|
||||
inkscape:label="hdd.svg"
|
||||
id="layer1-1-0"
|
||||
transform="matrix(0.11642098,0,0,0.11642098,64.699557,-2.316239)"
|
||||
style="fill:#000000;filter:url(#filter46)">
|
||||
<rect
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="rect11036-6"
|
||||
width="462.5799"
|
||||
height="631.18384"
|
||||
x="260.13293"
|
||||
y="79.689705"
|
||||
ry="10"
|
||||
rx="10" />
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
d="m 336.50948,472.01841 v 35.6662 l -39.2688,33.8649 v 65.9284 l 35.8463,35.8464 v 26.8397 h 285.5098 l 60.3443,-60.3444 v -66.4688 l -36.8371,-36.8372 v -34.4952 z"
|
||||
id="path11038-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccccc" />
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
d="m 518.83658,541.83781 v 27.7658 h -28.5315 v 83.5567 h 112.3426 l 37.8298,-37.8299 v -48.0193 l 17.7686,-17.7686 -23.8824,-23.8824 -16.9405,16.1777 z"
|
||||
id="path11042-6"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccc" />
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
d="m 311.29088,535.78531 v 67.3695 l 56.0212,56.0211 h 68.2702 v -40.1696 h -64.8476 l -19.8146,-19.8144 v -63.4066 z"
|
||||
id="path11045-1"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccc" />
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#333c45;stroke-width:4.70599;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path11047-8"
|
||||
transform="matrix(3.187429,0,0,3.187429,19262.69,14995.327)"
|
||||
cx="-5889.75"
|
||||
cy="-4606.25"
|
||||
r="67.25" />
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#333c45;stroke-width:12.2273;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path11049-7"
|
||||
transform="matrix(0.81784386,0,0,0.81784386,5306.4261,4080.4251)"
|
||||
cx="-5889.75"
|
||||
cy="-4606.25"
|
||||
r="67.25" />
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path11051-9"
|
||||
transform="matrix(4.8829271,0,0,4.8829271,29486.67,22593.13)"
|
||||
cx="-5960"
|
||||
cy="-4506.6875"
|
||||
r="7.5625" />
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
d="m 554.46978,419.78001 -144.6591,194.3395 -52.2033,-52.2035 z"
|
||||
id="path11053-2"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:transform-center-x="-67.882251"
|
||||
inkscape:transform-center-y="-69.296465" />
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#333c45;stroke-width:1.15912;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path11055-0"
|
||||
transform="matrix(3.4509084,0,0,3.4509084,20951.838,16139.469)"
|
||||
cx="-5960"
|
||||
cy="-4506.6875"
|
||||
r="7.5625" />
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
d="m 552.20808,548.71451 v 44.3257 h -52.9869 v 51.7136 h 99.0959 l 33.3717,-33.3719 v -18.851 h -25.9841 v -43.8164 z"
|
||||
id="path11057-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccc" />
|
||||
<rect
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="rect11059-3"
|
||||
width="29.361576"
|
||||
height="29.901972"
|
||||
x="564.27551"
|
||||
y="555.67114" />
|
||||
<circle
|
||||
transform="matrix(2.8821179,0,0,2.8821179,17559.96,13576.481)"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path11062-7"
|
||||
cx="-5917.644"
|
||||
cy="-4508.8921"
|
||||
r="2.1655145" />
|
||||
<circle
|
||||
id="path11065-5"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(2.8821179,0,0,2.8821179,17691.848,13542.296)"
|
||||
cx="-5917.644"
|
||||
cy="-4508.8921"
|
||||
r="2.1655145" />
|
||||
<g
|
||||
transform="matrix(-1,0,0,1,-4012.4724,6304.2598)"
|
||||
id="g11089-9"
|
||||
style="fill:#000000">
|
||||
<g
|
||||
style="fill:#000000;fill-opacity:1"
|
||||
id="g11091-2"
|
||||
transform="matrix(2.8821179,0,0,2.8821179,12565.448,7645.2124)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m -4302.875,-6966.4375 c -8.7807,0 -15.9063,7.1255 -15.9062,15.9063 0,8.7807 7.1255,15.9062 15.9062,15.9062 h 30.2812 v -31.8125 z"
|
||||
transform="matrix(-0.34696707,0,0,0.34696707,-7485.2033,-2258.3505)"
|
||||
id="rect11093-2" />
|
||||
</g>
|
||||
<circle
|
||||
transform="matrix(3.9132938,0,0,3.9132938,18734.2,12451.798)"
|
||||
id="path11097-8"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
cx="-5989.9604"
|
||||
cy="-4667.6646"
|
||||
r="2.2894223" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:#000000;stroke:#fab82e;stroke-width:4.84193;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 534.91288,592.01131 c 0,0 -52.2205,-83.9328 -114.2875,11.3002"
|
||||
id="path11102-9"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<circle
|
||||
transform="matrix(2.8821179,0,0,2.8821179,17544.878,13273.391)"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path11105-7"
|
||||
cx="-5917.644"
|
||||
cy="-4508.8921"
|
||||
r="2.1655145" />
|
||||
<circle
|
||||
id="path11107-3"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(2.8821179,0,0,2.8821179,17543.166,13343.54)"
|
||||
cx="-5917.644"
|
||||
cy="-4508.8921"
|
||||
r="2.1655145" />
|
||||
<circle
|
||||
inkscape:transform-center-x="-34.999423"
|
||||
inkscape:transform-center-y="-0.00011176152"
|
||||
id="path11110-6"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0,2.8821179,-2.8821179,0,-12470.629,17368.58)"
|
||||
cx="-5917.644"
|
||||
cy="-4508.8921"
|
||||
r="2.1655145" />
|
||||
<circle
|
||||
inkscape:transform-center-x="34.99928"
|
||||
inkscape:transform-center-y="-0.00046723847"
|
||||
id="path11114-1"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0,-2.8821179,2.8821179,0,13449.69,-16742.117)"
|
||||
cx="-5917.644"
|
||||
cy="-4508.8921"
|
||||
r="2.1655145" />
|
||||
<circle
|
||||
id="path11118-2"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(2.8821179,0,0,2.8821179,17544.878,13273.391)"
|
||||
cx="-5917.644"
|
||||
cy="-4508.8921"
|
||||
r="2.1655145" />
|
||||
<g
|
||||
id="g11120-9"
|
||||
transform="matrix(0,1,1,0,6516.7671,4810.6757)"
|
||||
style="fill:#000000">
|
||||
<g
|
||||
transform="matrix(2.0379651,-2.0379651,2.0379651,2.0379651,17022.519,-8513.1716)"
|
||||
id="g11123-3"
|
||||
style="fill:#000000;fill-opacity:1">
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m -4298.6562,-7356.7812 c -8.7807,0 -15.9063,7.1255 -15.9063,15.9062 0,8.7704 7.1085,15.8895 15.875,15.9062 6.164,0 12.3339,0 18.5,0 l 8.8125,-8.8124 c 1.9587,-1.9587 2.9688,-4.5377 2.9688,-7.0938 0,-2.5562 -1.0101,-5.1038 -2.9688,-7.0625 l -8.8125,-8.8125 z"
|
||||
transform="matrix(-0.34696707,0,0,0.34696707,-7483.7515,-2122.9129)"
|
||||
id="path11126-1"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="csccssscc" />
|
||||
</g>
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path11134-9"
|
||||
transform="matrix(2.7671166,-2.7671166,2.7671166,2.7671166,24783.255,-9476.3687)"
|
||||
cx="-5989.9604"
|
||||
cy="-4667.6646"
|
||||
r="2.2894223" />
|
||||
</g>
|
||||
<g
|
||||
id="g11160-4"
|
||||
transform="translate(4995.3295,6304.2598)"
|
||||
style="fill:#000000">
|
||||
<g
|
||||
transform="matrix(2.8821179,0,0,2.8821179,12565.448,7645.2124)"
|
||||
id="g11163-7"
|
||||
style="fill:#000000;fill-opacity:1">
|
||||
<path
|
||||
id="path11165-8"
|
||||
transform="matrix(-0.34696707,0,0,0.34696707,-7485.2033,-2258.3505)"
|
||||
d="m -4302.875,-6966.4375 c -8.7807,0 -15.9063,7.1255 -15.9062,15.9063 0,8.7807 7.1255,15.9062 15.9062,15.9062 h 30.2812 v -31.8125 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path11167-4"
|
||||
transform="matrix(3.9132938,0,0,3.9132938,18734.2,12451.798)"
|
||||
cx="-5989.9604"
|
||||
cy="-4667.6646"
|
||||
r="2.2894223" />
|
||||
</g>
|
||||
<g
|
||||
transform="rotate(90,-5172.2358,-361.68515)"
|
||||
id="g11171-5"
|
||||
style="fill:#000000">
|
||||
<g
|
||||
style="fill:#000000;fill-opacity:1"
|
||||
id="g11173-0"
|
||||
transform="matrix(2.0379651,-2.0379651,2.0379651,2.0379651,17022.519,-8513.1716)">
|
||||
<path
|
||||
sodipodi:nodetypes="csccssscc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path11175-3"
|
||||
transform="matrix(-0.34696707,0,0,0.34696707,-7483.7515,-2122.9129)"
|
||||
d="m -4298.6562,-7356.7812 c -8.7807,0 -15.9063,7.1255 -15.9063,15.9062 0,8.7704 7.1085,15.8895 15.875,15.9062 6.164,0 12.3339,0 18.5,0 l 8.8125,-8.8124 c 1.9587,-1.9587 2.9688,-4.5377 2.9688,-7.0938 0,-2.5562 -1.0101,-5.1038 -2.9688,-7.0625 l -8.8125,-8.8125 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
|
||||
</g>
|
||||
<circle
|
||||
transform="matrix(2.7671166,-2.7671166,2.7671166,2.7671166,24783.255,-9476.3687)"
|
||||
id="path11177-6"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
cx="-5989.9604"
|
||||
cy="-4667.6646"
|
||||
r="2.2894223" />
|
||||
</g>
|
||||
<g
|
||||
transform="rotate(-90,1248.3275,-5268.4396)"
|
||||
id="g11179-1"
|
||||
style="fill:#000000">
|
||||
<g
|
||||
style="fill:#000000;fill-opacity:1"
|
||||
id="g11181-0"
|
||||
transform="matrix(2.0379651,-2.0379651,2.0379651,2.0379651,17022.519,-8513.1716)">
|
||||
<path
|
||||
sodipodi:nodetypes="csccssscc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path11183-6"
|
||||
transform="matrix(-0.34696707,0,0,0.34696707,-7483.7515,-2122.9129)"
|
||||
d="m -4298.6562,-7356.7812 c -8.7807,0 -15.9063,7.1255 -15.9063,15.9062 0,8.7704 7.1085,15.8895 15.875,15.9062 6.164,0 12.3339,0 18.5,0 l 8.8125,-8.8124 c 1.9587,-1.9587 2.9688,-4.5377 2.9688,-7.0938 0,-2.5562 -1.0101,-5.1038 -2.9688,-7.0625 l -8.8125,-8.8125 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
|
||||
</g>
|
||||
<circle
|
||||
transform="matrix(2.7671166,-2.7671166,2.7671166,2.7671166,24783.255,-9476.3687)"
|
||||
id="path11185-3"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
cx="-5989.9604"
|
||||
cy="-4667.6646"
|
||||
r="2.2894223" />
|
||||
</g>
|
||||
<g
|
||||
id="g11187-2"
|
||||
transform="matrix(0,-1,-1,0,-5533.921,-4020.1121)"
|
||||
style="fill:#000000">
|
||||
<g
|
||||
transform="matrix(2.0379651,-2.0379651,2.0379651,2.0379651,17022.519,-8513.1716)"
|
||||
id="g11189-0"
|
||||
style="fill:#000000;fill-opacity:1">
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m -4298.6562,-7356.7812 c -8.7807,0 -15.9063,7.1255 -15.9063,15.9062 0,8.7704 7.1085,15.8895 15.875,15.9062 6.164,0 12.3339,0 18.5,0 l 8.8125,-8.8124 c 1.9587,-1.9587 2.9688,-4.5377 2.9688,-7.0938 0,-2.5562 -1.0101,-5.1038 -2.9688,-7.0625 l -8.8125,-8.8125 z"
|
||||
transform="matrix(-0.34696707,0,0,0.34696707,-7483.7515,-2122.9129)"
|
||||
id="path11191-6"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="csccssscc" />
|
||||
</g>
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path11193-1"
|
||||
transform="matrix(2.7671166,-2.7671166,2.7671166,2.7671166,24783.255,-9476.3687)"
|
||||
cx="-5989.9604"
|
||||
cy="-4667.6646"
|
||||
r="2.2894223" />
|
||||
</g>
|
||||
</g><g
|
||||
inkscape:label="hdd.svg"
|
||||
id="layer1-1"
|
||||
transform="matrix(0.11642098,0,0,0.11642098,63.797057,-3.456739)">
|
||||
<rect
|
||||
style="fill:#414d5b;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="rect11036"
|
||||
width="462.5799"
|
||||
height="631.18384"
|
||||
x="260.13293"
|
||||
y="79.689705"
|
||||
ry="10"
|
||||
rx="10" />
|
||||
<path
|
||||
style="fill:#333c45;fill-opacity:1;stroke:none"
|
||||
d="m 336.50948,472.01841 v 35.6662 l -39.2688,33.8649 v 65.9284 l 35.8463,35.8464 v 26.8397 h 285.5098 l 60.3443,-60.3444 v -66.4688 l -36.8371,-36.8372 v -34.4952 z"
|
||||
id="path11038"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccccc" />
|
||||
<path
|
||||
style="fill:#eaeaea;fill-opacity:1;stroke:none"
|
||||
d="m 518.83658,541.83781 v 27.7658 h -28.5315 v 83.5567 h 112.3426 l 37.8298,-37.8299 v -48.0193 l 17.7686,-17.7686 -23.8824,-23.8824 -16.9405,16.1777 z"
|
||||
id="path11042"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccc" />
|
||||
<path
|
||||
style="fill:#eaeaea;fill-opacity:1;stroke:none"
|
||||
d="m 311.29088,535.78531 v 67.3695 l 56.0212,56.0211 h 68.2702 v -40.1696 h -64.8476 l -19.8146,-19.8144 v -63.4066 z"
|
||||
id="path11045"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccc" />
|
||||
<circle
|
||||
style="fill:#eaeaea;fill-opacity:1;fill-rule:nonzero;stroke:#333c45;stroke-width:4.70599;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path11047"
|
||||
transform="matrix(3.187429,0,0,3.187429,19262.69,14995.327)"
|
||||
cx="-5889.75"
|
||||
cy="-4606.25"
|
||||
r="67.25" />
|
||||
<circle
|
||||
style="fill:#eaeaea;fill-opacity:1;fill-rule:nonzero;stroke:#333c45;stroke-width:12.2273;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path11049"
|
||||
transform="matrix(0.81784386,0,0,0.81784386,5306.4261,4080.4251)"
|
||||
cx="-5889.75"
|
||||
cy="-4606.25"
|
||||
r="67.25" />
|
||||
<circle
|
||||
style="fill:#f9794c;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path11051"
|
||||
transform="matrix(4.8829271,0,0,4.8829271,29486.67,22593.13)"
|
||||
cx="-5960"
|
||||
cy="-4506.6875"
|
||||
r="7.5625" />
|
||||
<path
|
||||
style="fill:#f9794c;fill-opacity:1;stroke:none"
|
||||
d="m 554.46978,419.78001 -144.6591,194.3395 -52.2033,-52.2035 z"
|
||||
id="path11053"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:transform-center-x="-67.882251"
|
||||
inkscape:transform-center-y="-69.296465" />
|
||||
<circle
|
||||
style="fill:#eaeaea;fill-opacity:1;fill-rule:nonzero;stroke:#333c45;stroke-width:1.15912;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path11055"
|
||||
transform="matrix(3.4509084,0,0,3.4509084,20951.838,16139.469)"
|
||||
cx="-5960"
|
||||
cy="-4506.6875"
|
||||
r="7.5625" />
|
||||
<path
|
||||
style="fill:#f9cd54;fill-opacity:1;stroke:none"
|
||||
d="m 552.20808,548.71451 v 44.3257 h -52.9869 v 51.7136 h 99.0959 l 33.3717,-33.3719 v -18.851 h -25.9841 v -43.8164 z"
|
||||
id="path11057"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccc" />
|
||||
<rect
|
||||
style="fill:#3e3e40;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="rect11059"
|
||||
width="29.361576"
|
||||
height="29.901972"
|
||||
x="564.27551"
|
||||
y="555.67114" />
|
||||
<circle
|
||||
transform="matrix(2.8821179,0,0,2.8821179,17559.96,13576.481)"
|
||||
style="fill:#76a8d4;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path11062"
|
||||
cx="-5917.644"
|
||||
cy="-4508.8921"
|
||||
r="2.1655145" />
|
||||
<circle
|
||||
id="path11065"
|
||||
style="fill:#76a8d4;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(2.8821179,0,0,2.8821179,17691.848,13542.296)"
|
||||
cx="-5917.644"
|
||||
cy="-4508.8921"
|
||||
r="2.1655145" />
|
||||
<g
|
||||
transform="matrix(-1,0,0,1,-4012.4724,6304.2598)"
|
||||
id="g11089">
|
||||
<g
|
||||
style="fill:#eaeaea;fill-opacity:1"
|
||||
id="g11091"
|
||||
transform="matrix(2.8821179,0,0,2.8821179,12565.448,7645.2124)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#eaeaea;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m -4302.875,-6966.4375 c -8.7807,0 -15.9063,7.1255 -15.9062,15.9063 0,8.7807 7.1255,15.9062 15.9062,15.9062 h 30.2812 v -31.8125 z"
|
||||
transform="matrix(-0.34696707,0,0,0.34696707,-7485.2033,-2258.3505)"
|
||||
id="rect11093" />
|
||||
</g>
|
||||
<circle
|
||||
transform="matrix(3.9132938,0,0,3.9132938,18734.2,12451.798)"
|
||||
id="path11097"
|
||||
style="fill:#353c46;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
cx="-5989.9604"
|
||||
cy="-4667.6646"
|
||||
r="2.2894223" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#fab82e;stroke-width:4.84193;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 534.91288,592.01131 c 0,0 -52.2205,-83.9328 -114.2875,11.3002"
|
||||
id="path11102"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<circle
|
||||
transform="matrix(2.8821179,0,0,2.8821179,17544.878,13273.391)"
|
||||
style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path11105"
|
||||
cx="-5917.644"
|
||||
cy="-4508.8921"
|
||||
r="2.1655145" />
|
||||
<circle
|
||||
id="path11107"
|
||||
style="fill:#76a8d4;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(2.8821179,0,0,2.8821179,17543.166,13343.54)"
|
||||
cx="-5917.644"
|
||||
cy="-4508.8921"
|
||||
r="2.1655145" />
|
||||
<circle
|
||||
inkscape:transform-center-x="-34.999423"
|
||||
inkscape:transform-center-y="-0.00011176152"
|
||||
id="path11110"
|
||||
style="fill:#76a8d4;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0,2.8821179,-2.8821179,0,-12470.629,17368.58)"
|
||||
cx="-5917.644"
|
||||
cy="-4508.8921"
|
||||
r="2.1655145" />
|
||||
<circle
|
||||
inkscape:transform-center-x="34.99928"
|
||||
inkscape:transform-center-y="-0.00046723847"
|
||||
id="path11114"
|
||||
style="fill:#76a8d4;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0,-2.8821179,2.8821179,0,13449.69,-16742.117)"
|
||||
cx="-5917.644"
|
||||
cy="-4508.8921"
|
||||
r="2.1655145" />
|
||||
<circle
|
||||
id="path11118"
|
||||
style="fill:#76a8d4;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(2.8821179,0,0,2.8821179,17544.878,13273.391)"
|
||||
cx="-5917.644"
|
||||
cy="-4508.8921"
|
||||
r="2.1655145" />
|
||||
<g
|
||||
id="g11120"
|
||||
transform="matrix(0,1,1,0,6516.7671,4810.6757)">
|
||||
<g
|
||||
transform="matrix(2.0379651,-2.0379651,2.0379651,2.0379651,17022.519,-8513.1716)"
|
||||
id="g11123"
|
||||
style="fill:#eaeaea;fill-opacity:1">
|
||||
<path
|
||||
style="fill:#eaeaea;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m -4298.6562,-7356.7812 c -8.7807,0 -15.9063,7.1255 -15.9063,15.9062 0,8.7704 7.1085,15.8895 15.875,15.9062 6.164,0 12.3339,0 18.5,0 l 8.8125,-8.8124 c 1.9587,-1.9587 2.9688,-4.5377 2.9688,-7.0938 0,-2.5562 -1.0101,-5.1038 -2.9688,-7.0625 l -8.8125,-8.8125 z"
|
||||
transform="matrix(-0.34696707,0,0,0.34696707,-7483.7515,-2122.9129)"
|
||||
id="path11126"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="csccssscc" />
|
||||
</g>
|
||||
<circle
|
||||
style="fill:#353c46;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path11134"
|
||||
transform="matrix(2.7671166,-2.7671166,2.7671166,2.7671166,24783.255,-9476.3687)"
|
||||
cx="-5989.9604"
|
||||
cy="-4667.6646"
|
||||
r="2.2894223" />
|
||||
</g>
|
||||
<g
|
||||
id="g11160"
|
||||
transform="translate(4995.3295,6304.2598)">
|
||||
<g
|
||||
transform="matrix(2.8821179,0,0,2.8821179,12565.448,7645.2124)"
|
||||
id="g11163"
|
||||
style="fill:#eaeaea;fill-opacity:1">
|
||||
<path
|
||||
id="path11165"
|
||||
transform="matrix(-0.34696707,0,0,0.34696707,-7485.2033,-2258.3505)"
|
||||
d="m -4302.875,-6966.4375 c -8.7807,0 -15.9063,7.1255 -15.9062,15.9063 0,8.7807 7.1255,15.9062 15.9062,15.9062 h 30.2812 v -31.8125 z"
|
||||
style="fill:#eaeaea;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<circle
|
||||
style="fill:#353c46;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path11167"
|
||||
transform="matrix(3.9132938,0,0,3.9132938,18734.2,12451.798)"
|
||||
cx="-5989.9604"
|
||||
cy="-4667.6646"
|
||||
r="2.2894223" />
|
||||
</g>
|
||||
<g
|
||||
transform="rotate(90,-5172.2358,-361.68515)"
|
||||
id="g11171">
|
||||
<g
|
||||
style="fill:#eaeaea;fill-opacity:1"
|
||||
id="g11173"
|
||||
transform="matrix(2.0379651,-2.0379651,2.0379651,2.0379651,17022.519,-8513.1716)">
|
||||
<path
|
||||
sodipodi:nodetypes="csccssscc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path11175"
|
||||
transform="matrix(-0.34696707,0,0,0.34696707,-7483.7515,-2122.9129)"
|
||||
d="m -4298.6562,-7356.7812 c -8.7807,0 -15.9063,7.1255 -15.9063,15.9062 0,8.7704 7.1085,15.8895 15.875,15.9062 6.164,0 12.3339,0 18.5,0 l 8.8125,-8.8124 c 1.9587,-1.9587 2.9688,-4.5377 2.9688,-7.0938 0,-2.5562 -1.0101,-5.1038 -2.9688,-7.0625 l -8.8125,-8.8125 z"
|
||||
style="fill:#eaeaea;fill-opacity:1;fill-rule:nonzero;stroke:none" />
|
||||
</g>
|
||||
<circle
|
||||
transform="matrix(2.7671166,-2.7671166,2.7671166,2.7671166,24783.255,-9476.3687)"
|
||||
id="path11177"
|
||||
style="fill:#353c46;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
cx="-5989.9604"
|
||||
cy="-4667.6646"
|
||||
r="2.2894223" />
|
||||
</g>
|
||||
<g
|
||||
transform="rotate(-90,1248.3275,-5268.4396)"
|
||||
id="g11179">
|
||||
<g
|
||||
style="fill:#eaeaea;fill-opacity:1"
|
||||
id="g11181"
|
||||
transform="matrix(2.0379651,-2.0379651,2.0379651,2.0379651,17022.519,-8513.1716)">
|
||||
<path
|
||||
sodipodi:nodetypes="csccssscc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path11183"
|
||||
transform="matrix(-0.34696707,0,0,0.34696707,-7483.7515,-2122.9129)"
|
||||
d="m -4298.6562,-7356.7812 c -8.7807,0 -15.9063,7.1255 -15.9063,15.9062 0,8.7704 7.1085,15.8895 15.875,15.9062 6.164,0 12.3339,0 18.5,0 l 8.8125,-8.8124 c 1.9587,-1.9587 2.9688,-4.5377 2.9688,-7.0938 0,-2.5562 -1.0101,-5.1038 -2.9688,-7.0625 l -8.8125,-8.8125 z"
|
||||
style="fill:#eaeaea;fill-opacity:1;fill-rule:nonzero;stroke:none" />
|
||||
</g>
|
||||
<circle
|
||||
transform="matrix(2.7671166,-2.7671166,2.7671166,2.7671166,24783.255,-9476.3687)"
|
||||
id="path11185"
|
||||
style="fill:#353c46;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
cx="-5989.9604"
|
||||
cy="-4667.6646"
|
||||
r="2.2894223" />
|
||||
</g>
|
||||
<g
|
||||
id="g11187"
|
||||
transform="matrix(0,-1,-1,0,-5533.921,-4020.1121)">
|
||||
<g
|
||||
transform="matrix(2.0379651,-2.0379651,2.0379651,2.0379651,17022.519,-8513.1716)"
|
||||
id="g11189"
|
||||
style="fill:#eaeaea;fill-opacity:1">
|
||||
<path
|
||||
style="fill:#eaeaea;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m -4298.6562,-7356.7812 c -8.7807,0 -15.9063,7.1255 -15.9063,15.9062 0,8.7704 7.1085,15.8895 15.875,15.9062 6.164,0 12.3339,0 18.5,0 l 8.8125,-8.8124 c 1.9587,-1.9587 2.9688,-4.5377 2.9688,-7.0938 0,-2.5562 -1.0101,-5.1038 -2.9688,-7.0625 l -8.8125,-8.8125 z"
|
||||
transform="matrix(-0.34696707,0,0,0.34696707,-7483.7515,-2122.9129)"
|
||||
id="path11191"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="csccssscc" />
|
||||
</g>
|
||||
<circle
|
||||
style="fill:#353c46;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path11193"
|
||||
transform="matrix(2.7671166,-2.7671166,2.7671166,2.7671166,24783.255,-9476.3687)"
|
||||
cx="-5989.9604"
|
||||
cy="-4667.6646"
|
||||
r="2.2894223" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 30 KiB |
BIN
dist/images/syng.png
vendored
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
dist/images/syng_advanced.png
vendored
Normal file
After Width: | Height: | Size: 69 KiB |
BIN
dist/images/syng_mobile_search.png
vendored
Normal file
After Width: | Height: | Size: 242 KiB |
BIN
dist/images/syng_player_empty.png
vendored
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
dist/images/syng_player_next_up.png
vendored
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
dist/images/syng_player_song.png
vendored
Normal file
After Width: | Height: | Size: 109 KiB |
BIN
dist/images/syng_web.png
vendored
Normal file
After Width: | Height: | Size: 67 KiB |
BIN
dist/images/syng_web2.png
vendored
Normal file
After Width: | Height: | Size: 550 KiB |
BIN
dist/images/web-shadows.png
vendored
Normal file
After Width: | Height: | Size: 615 KiB |
101
dist/index.html
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
|
||||
<!doctype html>
|
||||
<html class="no-js" lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Syng.Rocks</title>
|
||||
<link rel="stylesheet" href="css/foundation.css">
|
||||
<link rel="stylesheet" href="css/app.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="top-content-section">
|
||||
<div class="top-bar">
|
||||
<div class="top-bar-left">
|
||||
<ul class="menu">
|
||||
<li class="menu-text"><img src="images/rocks.syng.Syng.png" alt="Syng.Rocks! Logo" height=30></li>
|
||||
|
||||
<li><a href="index.html">Home</a></li>
|
||||
|
||||
<li><a href="install.html">Installation</a></li>
|
||||
|
||||
<li><a href="faq.html">FAQ</a></li>
|
||||
|
||||
<li><a href="privacy.html">Privacy Policy</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hero-full-screen">
|
||||
<div class="middle-content-section grid-container">
|
||||
<div class="grid-x align-middle">
|
||||
<div class="cell large-6">
|
||||
<p><img alt="Syng.Rocks! Overview" src="images/overview.png" /></p>
|
||||
</div>
|
||||
<div class="cell large-6">
|
||||
<div class="hero-section-text">
|
||||
<h1>Syng.Rocks!</h1>
|
||||
<h5>Easily host karaoke events</h5>
|
||||
<p>Syng.Rocks! is a karaoke app that allows you to host karaoke events without much hassle. Whether you have a big collection of karaoke songs, or just want to stream karaoke songs from YouTube, whether you want to sing with a couple of friends or with a crowd of over 100 people, Syng.Rocks! has you covered in a privacy-friendly manner. No need to register, no need to log in, Syng.Rocks! will never collect any personal data from you. You can even host your own server if you want to.</p>
|
||||
<p><a href="https://flathub.org/apps/rocks.syng.Syng" target="_blank" class="button">Linux/Flatpak</a>
|
||||
<a href="https://github.com/christofsteel/syng/releases" target="_blank" class="button">Windows</a>
|
||||
<a href="https://syng.rocks" target="_blank" class="button hollow">Web Client</a>
|
||||
<a href="https://github.com/christofsteel/syng" target="_blank" class="button hollow">Source Code</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="main-content-section">
|
||||
<div class="grid-container">
|
||||
<div class="grid-x grid-padding textleft align-right">
|
||||
<div class="cell medium-5 text-right">
|
||||
<h2>Start Singing</h2>
|
||||
<p>If you only want to have a small YouTube based karaoke event, you can just download the app, share the generated QR Code and start singing. No registration, no login and no configuration required. </p>
|
||||
</div>
|
||||
<div class="cell medium-5 showcase-image">
|
||||
<p><img alt="Syng.Rocks! Client" src="images/syng.png" /></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid-x grid-padding textright">
|
||||
<div class="cell medium-8 showcase-image">
|
||||
<p><img alt="Syng.Rocks! Web Client" src="images/web-shadows.png" /></p>
|
||||
</div>
|
||||
<div class="cell medium-4">
|
||||
<h2>Web client</h2>
|
||||
<p>Let your guests join your karaoke event using the web client. They can use their browser on their own devices to search for songs and queue them up.
|
||||
The web client also contains an admin mode, that allows for manual moderation of the song queue.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid-x grid-padding textleft align-right">
|
||||
<div class="cell medium-4 text-right">
|
||||
<h2>Configure to your needs</h2>
|
||||
<p>Syng.Rocks! allows for a lot of configuration options. You can set up your own song database, you can set up a <a href="faq.html#waiting-room">waiting room</a>, a set time the event ends and much more.</p>
|
||||
</div>
|
||||
<div class="cell medium-8 showcase-image">
|
||||
<p><img alt="Syng.Rocks! Web Client" src="images/syng_advanced.png" /></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid-x grid-padding textright">
|
||||
<div class="cell medium-7 showcase-image">
|
||||
<p><img alt="Syng.Rocks! Web Client" src="images/sources.svg" /></p>
|
||||
</div>
|
||||
<div class="cell medium-5">
|
||||
<h2>Multiple Sources</h2>
|
||||
<p>Syng.Rocks! supports multiple sources for karaoke songs. The default source is YouTube, but you can configure a remote S3 compatible server or simply a folder on your system. The client connects directly to the sources, no login data is ever shared with the server.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="js/vendor/jquery.js"></script>
|
||||
<script src="js/vendor/what-input.js"></script>
|
||||
<script src="js/vendor/foundation.js"></script>
|
||||
<script src="js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
72
dist/install.html
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
|
||||
<!doctype html>
|
||||
<html class="no-js" lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Syng.Rocks</title>
|
||||
<link rel="stylesheet" href="css/foundation.css">
|
||||
<link rel="stylesheet" href="css/app.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="top-content-section">
|
||||
<div class="top-bar">
|
||||
<div class="top-bar-left">
|
||||
<ul class="menu">
|
||||
<li class="menu-text"><img src="images/rocks.syng.Syng.png" alt="Syng.Rocks! Logo" height=30></li>
|
||||
|
||||
<li><a href="index.html">Home</a></li>
|
||||
|
||||
<li><a href="install.html">Installation</a></li>
|
||||
|
||||
<li><a href="faq.html">FAQ</a></li>
|
||||
|
||||
<li><a href="privacy.html">Privacy Policy</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="main-content-section" style="padding-top: 100px;">
|
||||
<div class="grid-container">
|
||||
<h1>Installation</h1>
|
||||
<h2>Client</h2>
|
||||
<p>Depending on your platform, you can install Syng.Rocks! in different ways.</p>
|
||||
<dl>
|
||||
<dt>Linux</dt>
|
||||
<dd>
|
||||
<p>Syng.Rocks! is available as a Flatpak on <a href="https://flathub.org/apps/rocks.syng.Syng">Flathub</a>. You can install it using the command line with:</p>
|
||||
<p><code>flatpak install rocks.syng.Syng</code></p>
|
||||
<p>There also exists an Arch Linux package in the <a href="https://aur.archlinux.org/packages/syng-client">AUR</a>.</p>
|
||||
</dd>
|
||||
<dt>Windows</dt>
|
||||
<dd>
|
||||
<p>Windows binaries are available on <a href="https://github.com/christofsteel/syng/releases">Github</a>. This is a portable version and does not require installation.</p>
|
||||
</dd>
|
||||
<dt>Generic</dt>
|
||||
<dd>
|
||||
<p>Syng.Rocks! is available in the Python Package Index (PyPI) as <code>syng</code>. You can install the client using pip:</p>
|
||||
<p><code>pip install syng[client]</code></p>
|
||||
</dd>
|
||||
</dl>
|
||||
<h2>Server</h2>
|
||||
<p>The server is available as a Docker image hosted on Github. You can run it with:</p>
|
||||
<pre><code>docker run ghcr.io/christofsteel/syng
|
||||
</code></pre>
|
||||
<p>Alternatively, you can run the server using the Python Package Index (PyPI) package <code>syng</code>:</p>
|
||||
<pre><code>pip install syng[server]
|
||||
</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="js/vendor/jquery.js"></script>
|
||||
<script src="js/vendor/what-input.js"></script>
|
||||
<script src="js/vendor/foundation.js"></script>
|
||||
<script src="js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
1
dist/js/app.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
$(document).foundation()
|
460
dist/js/vendor/foundation.js
vendored
Normal file
1
dist/js/vendor/foundation.min.js
vendored
Normal file
10716
dist/js/vendor/jquery.js
vendored
Normal file
517
dist/js/vendor/what-input.js
vendored
Normal file
|
@ -0,0 +1,517 @@
|
|||
/**
|
||||
* what-input - A global utility for tracking the current input method (mouse, keyboard or touch).
|
||||
* @version v5.2.12
|
||||
* @link https://github.com/ten1seven/what-input
|
||||
* @license MIT
|
||||
*/
|
||||
(function webpackUniversalModuleDefinition(root, factory) {
|
||||
if(typeof exports === 'object' && typeof module === 'object')
|
||||
module.exports = factory();
|
||||
else if(typeof define === 'function' && define.amd)
|
||||
define("whatInput", [], factory);
|
||||
else if(typeof exports === 'object')
|
||||
exports["whatInput"] = factory();
|
||||
else
|
||||
root["whatInput"] = factory();
|
||||
})(this, function() {
|
||||
return /******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId])
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ exports: {},
|
||||
/******/ id: moduleId,
|
||||
/******/ loaded: false
|
||||
/******/ };
|
||||
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.loaded = true;
|
||||
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
|
||||
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = function () {
|
||||
/*
|
||||
* bail out if there is no document or window
|
||||
* (i.e. in a node/non-DOM environment)
|
||||
*
|
||||
* Return a stubbed API instead
|
||||
*/
|
||||
if (typeof document === 'undefined' || typeof window === 'undefined') {
|
||||
return {
|
||||
// always return "initial" because no interaction will ever be detected
|
||||
ask: function ask() {
|
||||
return 'initial';
|
||||
},
|
||||
|
||||
// always return null
|
||||
element: function element() {
|
||||
return null;
|
||||
},
|
||||
|
||||
// no-op
|
||||
ignoreKeys: function ignoreKeys() {},
|
||||
|
||||
// no-op
|
||||
specificKeys: function specificKeys() {},
|
||||
|
||||
// no-op
|
||||
registerOnChange: function registerOnChange() {},
|
||||
|
||||
// no-op
|
||||
unRegisterOnChange: function unRegisterOnChange() {}
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* variables
|
||||
*/
|
||||
|
||||
// cache document.documentElement
|
||||
var docElem = document.documentElement;
|
||||
|
||||
// currently focused dom element
|
||||
var currentElement = null;
|
||||
|
||||
// last used input type
|
||||
var currentInput = 'initial';
|
||||
|
||||
// last used input intent
|
||||
var currentIntent = currentInput;
|
||||
|
||||
// UNIX timestamp of current event
|
||||
var currentTimestamp = Date.now();
|
||||
|
||||
// check for a `data-whatpersist` attribute on either the `html` or `body` elements, defaults to `true`
|
||||
var shouldPersist = false;
|
||||
|
||||
// form input types
|
||||
var formInputs = ['button', 'input', 'select', 'textarea'];
|
||||
|
||||
// empty array for holding callback functions
|
||||
var functionList = [];
|
||||
|
||||
// list of modifier keys commonly used with the mouse and
|
||||
// can be safely ignored to prevent false keyboard detection
|
||||
var ignoreMap = [16, // shift
|
||||
17, // control
|
||||
18, // alt
|
||||
91, // Windows key / left Apple cmd
|
||||
93 // Windows menu / right Apple cmd
|
||||
];
|
||||
|
||||
var specificMap = [];
|
||||
|
||||
// mapping of events to input types
|
||||
var inputMap = {
|
||||
keydown: 'keyboard',
|
||||
keyup: 'keyboard',
|
||||
mousedown: 'mouse',
|
||||
mousemove: 'mouse',
|
||||
MSPointerDown: 'pointer',
|
||||
MSPointerMove: 'pointer',
|
||||
pointerdown: 'pointer',
|
||||
pointermove: 'pointer',
|
||||
touchstart: 'touch',
|
||||
touchend: 'touch'
|
||||
|
||||
// boolean: true if the page is being scrolled
|
||||
};var isScrolling = false;
|
||||
|
||||
// store current mouse position
|
||||
var mousePos = {
|
||||
x: null,
|
||||
y: null
|
||||
|
||||
// map of IE 10 pointer events
|
||||
};var pointerMap = {
|
||||
2: 'touch',
|
||||
3: 'touch', // treat pen like touch
|
||||
4: 'mouse'
|
||||
|
||||
// check support for passive event listeners
|
||||
};var supportsPassive = false;
|
||||
|
||||
try {
|
||||
var opts = Object.defineProperty({}, 'passive', {
|
||||
get: function get() {
|
||||
supportsPassive = true;
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('test', null, opts);
|
||||
} catch (e) {}
|
||||
// fail silently
|
||||
|
||||
|
||||
/*
|
||||
* set up
|
||||
*/
|
||||
|
||||
var setUp = function setUp() {
|
||||
// add correct mouse wheel event mapping to `inputMap`
|
||||
inputMap[detectWheel()] = 'mouse';
|
||||
|
||||
addListeners();
|
||||
};
|
||||
|
||||
/*
|
||||
* events
|
||||
*/
|
||||
|
||||
var addListeners = function addListeners() {
|
||||
// `pointermove`, `MSPointerMove`, `mousemove` and mouse wheel event binding
|
||||
// can only demonstrate potential, but not actual, interaction
|
||||
// and are treated separately
|
||||
var options = supportsPassive ? { passive: true, capture: true } : true;
|
||||
|
||||
document.addEventListener('DOMContentLoaded', setPersist, true);
|
||||
|
||||
// pointer events (mouse, pen, touch)
|
||||
if (window.PointerEvent) {
|
||||
window.addEventListener('pointerdown', setInput, true);
|
||||
window.addEventListener('pointermove', setIntent, true);
|
||||
} else if (window.MSPointerEvent) {
|
||||
window.addEventListener('MSPointerDown', setInput, true);
|
||||
window.addEventListener('MSPointerMove', setIntent, true);
|
||||
} else {
|
||||
// mouse events
|
||||
window.addEventListener('mousedown', setInput, true);
|
||||
window.addEventListener('mousemove', setIntent, true);
|
||||
|
||||
// touch events
|
||||
if ('ontouchstart' in window) {
|
||||
window.addEventListener('touchstart', setInput, options);
|
||||
window.addEventListener('touchend', setInput, true);
|
||||
}
|
||||
}
|
||||
|
||||
// mouse wheel
|
||||
window.addEventListener(detectWheel(), setIntent, options);
|
||||
|
||||
// keyboard events
|
||||
window.addEventListener('keydown', setInput, true);
|
||||
window.addEventListener('keyup', setInput, true);
|
||||
|
||||
// focus events
|
||||
window.addEventListener('focusin', setElement, true);
|
||||
window.addEventListener('focusout', clearElement, true);
|
||||
};
|
||||
|
||||
// checks if input persistence should happen and
|
||||
// get saved state from session storage if true (defaults to `false`)
|
||||
var setPersist = function setPersist() {
|
||||
shouldPersist = !(docElem.getAttribute('data-whatpersist') === 'false' || document.body.getAttribute('data-whatpersist') === 'false');
|
||||
|
||||
if (shouldPersist) {
|
||||
// check for session variables and use if available
|
||||
try {
|
||||
if (window.sessionStorage.getItem('what-input')) {
|
||||
currentInput = window.sessionStorage.getItem('what-input');
|
||||
}
|
||||
|
||||
if (window.sessionStorage.getItem('what-intent')) {
|
||||
currentIntent = window.sessionStorage.getItem('what-intent');
|
||||
}
|
||||
} catch (e) {
|
||||
// fail silently
|
||||
}
|
||||
}
|
||||
|
||||
// always run these so at least `initial` state is set
|
||||
doUpdate('input');
|
||||
doUpdate('intent');
|
||||
};
|
||||
|
||||
// checks conditions before updating new input
|
||||
var setInput = function setInput(event) {
|
||||
var eventKey = event.which;
|
||||
var value = inputMap[event.type];
|
||||
|
||||
if (value === 'pointer') {
|
||||
value = pointerType(event);
|
||||
}
|
||||
|
||||
var ignoreMatch = !specificMap.length && ignoreMap.indexOf(eventKey) === -1;
|
||||
|
||||
var specificMatch = specificMap.length && specificMap.indexOf(eventKey) !== -1;
|
||||
|
||||
var shouldUpdate = value === 'keyboard' && eventKey && (ignoreMatch || specificMatch) || value === 'mouse' || value === 'touch';
|
||||
|
||||
// prevent touch detection from being overridden by event execution order
|
||||
if (validateTouch(value)) {
|
||||
shouldUpdate = false;
|
||||
}
|
||||
|
||||
if (shouldUpdate && currentInput !== value) {
|
||||
currentInput = value;
|
||||
|
||||
persistInput('input', currentInput);
|
||||
doUpdate('input');
|
||||
}
|
||||
|
||||
if (shouldUpdate && currentIntent !== value) {
|
||||
// preserve intent for keyboard interaction with form fields
|
||||
var activeElem = document.activeElement;
|
||||
var notFormInput = activeElem && activeElem.nodeName && (formInputs.indexOf(activeElem.nodeName.toLowerCase()) === -1 || activeElem.nodeName.toLowerCase() === 'button' && !checkClosest(activeElem, 'form'));
|
||||
|
||||
if (notFormInput) {
|
||||
currentIntent = value;
|
||||
|
||||
persistInput('intent', currentIntent);
|
||||
doUpdate('intent');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// updates the doc and `inputTypes` array with new input
|
||||
var doUpdate = function doUpdate(which) {
|
||||
docElem.setAttribute('data-what' + which, which === 'input' ? currentInput : currentIntent);
|
||||
|
||||
fireFunctions(which);
|
||||
};
|
||||
|
||||
// updates input intent for `mousemove` and `pointermove`
|
||||
var setIntent = function setIntent(event) {
|
||||
var value = inputMap[event.type];
|
||||
|
||||
if (value === 'pointer') {
|
||||
value = pointerType(event);
|
||||
}
|
||||
|
||||
// test to see if `mousemove` happened relative to the screen to detect scrolling versus mousemove
|
||||
detectScrolling(event);
|
||||
|
||||
// only execute if scrolling isn't happening
|
||||
if ((!isScrolling && !validateTouch(value) || isScrolling && event.type === 'wheel' || event.type === 'mousewheel' || event.type === 'DOMMouseScroll') && currentIntent !== value) {
|
||||
currentIntent = value;
|
||||
|
||||
persistInput('intent', currentIntent);
|
||||
doUpdate('intent');
|
||||
}
|
||||
};
|
||||
|
||||
var setElement = function setElement(event) {
|
||||
if (!event.target.nodeName) {
|
||||
// If nodeName is undefined, clear the element
|
||||
// This can happen if click inside an <svg> element.
|
||||
clearElement();
|
||||
return;
|
||||
}
|
||||
|
||||
currentElement = event.target.nodeName.toLowerCase();
|
||||
docElem.setAttribute('data-whatelement', currentElement);
|
||||
|
||||
if (event.target.classList && event.target.classList.length) {
|
||||
docElem.setAttribute('data-whatclasses', event.target.classList.toString().replace(' ', ','));
|
||||
}
|
||||
};
|
||||
|
||||
var clearElement = function clearElement() {
|
||||
currentElement = null;
|
||||
|
||||
docElem.removeAttribute('data-whatelement');
|
||||
docElem.removeAttribute('data-whatclasses');
|
||||
};
|
||||
|
||||
var persistInput = function persistInput(which, value) {
|
||||
if (shouldPersist) {
|
||||
try {
|
||||
window.sessionStorage.setItem('what-' + which, value);
|
||||
} catch (e) {
|
||||
// fail silently
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* utilities
|
||||
*/
|
||||
|
||||
var pointerType = function pointerType(event) {
|
||||
if (typeof event.pointerType === 'number') {
|
||||
return pointerMap[event.pointerType];
|
||||
} else {
|
||||
// treat pen like touch
|
||||
return event.pointerType === 'pen' ? 'touch' : event.pointerType;
|
||||
}
|
||||
};
|
||||
|
||||
// prevent touch detection from being overridden by event execution order
|
||||
var validateTouch = function validateTouch(value) {
|
||||
var timestamp = Date.now();
|
||||
|
||||
var touchIsValid = value === 'mouse' && currentInput === 'touch' && timestamp - currentTimestamp < 200;
|
||||
|
||||
currentTimestamp = timestamp;
|
||||
|
||||
return touchIsValid;
|
||||
};
|
||||
|
||||
// detect version of mouse wheel event to use
|
||||
// via https://developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event
|
||||
var detectWheel = function detectWheel() {
|
||||
var wheelType = null;
|
||||
|
||||
// Modern browsers support "wheel"
|
||||
if ('onwheel' in document.createElement('div')) {
|
||||
wheelType = 'wheel';
|
||||
} else {
|
||||
// Webkit and IE support at least "mousewheel"
|
||||
// or assume that remaining browsers are older Firefox
|
||||
wheelType = document.onmousewheel !== undefined ? 'mousewheel' : 'DOMMouseScroll';
|
||||
}
|
||||
|
||||
return wheelType;
|
||||
};
|
||||
|
||||
// runs callback functions
|
||||
var fireFunctions = function fireFunctions(type) {
|
||||
for (var i = 0, len = functionList.length; i < len; i++) {
|
||||
if (functionList[i].type === type) {
|
||||
functionList[i].fn.call(undefined, type === 'input' ? currentInput : currentIntent);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// finds matching element in an object
|
||||
var objPos = function objPos(match) {
|
||||
for (var i = 0, len = functionList.length; i < len; i++) {
|
||||
if (functionList[i].fn === match) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var detectScrolling = function detectScrolling(event) {
|
||||
if (mousePos.x !== event.screenX || mousePos.y !== event.screenY) {
|
||||
isScrolling = false;
|
||||
|
||||
mousePos.x = event.screenX;
|
||||
mousePos.y = event.screenY;
|
||||
} else {
|
||||
isScrolling = true;
|
||||
}
|
||||
};
|
||||
|
||||
// manual version of `closest()`
|
||||
var checkClosest = function checkClosest(elem, tag) {
|
||||
var ElementPrototype = window.Element.prototype;
|
||||
|
||||
if (!ElementPrototype.matches) {
|
||||
ElementPrototype.matches = ElementPrototype.msMatchesSelector || ElementPrototype.webkitMatchesSelector;
|
||||
}
|
||||
|
||||
if (!ElementPrototype.closest) {
|
||||
do {
|
||||
if (elem.matches(tag)) {
|
||||
return elem;
|
||||
}
|
||||
|
||||
elem = elem.parentElement || elem.parentNode;
|
||||
} while (elem !== null && elem.nodeType === 1);
|
||||
|
||||
return null;
|
||||
} else {
|
||||
return elem.closest(tag);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* init
|
||||
*/
|
||||
|
||||
// don't start script unless browser cuts the mustard
|
||||
// (also passes if polyfills are used)
|
||||
if ('addEventListener' in window && Array.prototype.indexOf) {
|
||||
setUp();
|
||||
}
|
||||
|
||||
/*
|
||||
* api
|
||||
*/
|
||||
|
||||
return {
|
||||
// returns string: the current input type
|
||||
// opt: 'intent'|'input'
|
||||
// 'input' (default): returns the same value as the `data-whatinput` attribute
|
||||
// 'intent': includes `data-whatintent` value if it's different than `data-whatinput`
|
||||
ask: function ask(opt) {
|
||||
return opt === 'intent' ? currentIntent : currentInput;
|
||||
},
|
||||
|
||||
// returns string: the currently focused element or null
|
||||
element: function element() {
|
||||
return currentElement;
|
||||
},
|
||||
|
||||
// overwrites ignored keys with provided array
|
||||
ignoreKeys: function ignoreKeys(arr) {
|
||||
ignoreMap = arr;
|
||||
},
|
||||
|
||||
// overwrites specific char keys to update on
|
||||
specificKeys: function specificKeys(arr) {
|
||||
specificMap = arr;
|
||||
},
|
||||
|
||||
// attach functions to input and intent "events"
|
||||
// funct: function to fire on change
|
||||
// eventType: 'input'|'intent'
|
||||
registerOnChange: function registerOnChange(fn, eventType) {
|
||||
functionList.push({
|
||||
fn: fn,
|
||||
type: eventType || 'input'
|
||||
});
|
||||
},
|
||||
|
||||
unRegisterOnChange: function unRegisterOnChange(fn) {
|
||||
var position = objPos(fn);
|
||||
|
||||
if (position || position === 0) {
|
||||
functionList.splice(position, 1);
|
||||
}
|
||||
},
|
||||
|
||||
clearStorage: function clearStorage() {
|
||||
window.sessionStorage.clear();
|
||||
}
|
||||
};
|
||||
}();
|
||||
|
||||
/***/ })
|
||||
/******/ ])
|
||||
});
|
||||
;
|
66
dist/privacy.html
vendored
Normal file
|
@ -0,0 +1,66 @@
|
|||
|
||||
<!doctype html>
|
||||
<html class="no-js" lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Syng.Rocks</title>
|
||||
<link rel="stylesheet" href="css/foundation.css">
|
||||
<link rel="stylesheet" href="css/app.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="top-content-section">
|
||||
<div class="top-bar">
|
||||
<div class="top-bar-left">
|
||||
<ul class="menu">
|
||||
<li class="menu-text"><img src="images/rocks.syng.Syng.png" alt="Syng.Rocks! Logo" height=30></li>
|
||||
|
||||
<li><a href="index.html">Home</a></li>
|
||||
|
||||
<li><a href="install.html">Installation</a></li>
|
||||
|
||||
<li><a href="faq.html">FAQ</a></li>
|
||||
|
||||
<li><a href="privacy.html">Privacy Policy</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="main-content-section" style="padding-top: 100px;">
|
||||
<div class="grid-container">
|
||||
<h1>Privacy Policy</h1>
|
||||
<p>Syng.Rocks! respects your privacy. We do not collect any personal data, apart from what is necessary for the application to function and for anti-abuse reasons. </p>
|
||||
<p>The only data shared from using the web client is the following</p>
|
||||
<ul>
|
||||
<li>The chosen username</li>
|
||||
<li>The name of the room you connect to</li>
|
||||
<li>Search queries</li>
|
||||
<li>Enqueued songs</li>
|
||||
<li>The IP address of your device</li>
|
||||
</ul>
|
||||
<p>This data may be collected in log files and used for maintenance and anti-abuse reasons. We will never sell your data.</p>
|
||||
<p>The data shared from using the playback client is the following</p>
|
||||
<ul>
|
||||
<li>The chosen room name</li>
|
||||
<li>The admin password</li>
|
||||
<li>The configuration of the room</li>
|
||||
<li>The configuration of the sources, excluding any authentication data</li>
|
||||
<li>A list of file names present in the sources to handle search request</li>
|
||||
</ul>
|
||||
<p>This data will be deleted from the server, once a karaoke session is removed from the server, which is two hours after the last client disconnects.</p>
|
||||
<p>Syng.Rocks! does not use any cookies, but stores the chosen username and room name in the local storage of your browser. The local storage is cleared, if you press the <code>Log out</code> button.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="js/vendor/jquery.js"></script>
|
||||
<script src="js/vendor/what-input.js"></script>
|
||||
<script src="js/vendor/foundation.js"></script>
|
||||
<script src="js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
110
faq.html
|
@ -1,110 +0,0 @@
|
|||
<!doctype html>
|
||||
<html class="no-js" lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Syng.Rocks</title>
|
||||
<link rel="stylesheet" href="css/foundation.css">
|
||||
<link rel="stylesheet" href="css/app.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="top-content-section">
|
||||
<div class="top-bar">
|
||||
<div class="top-bar-left">
|
||||
<ul class="menu">
|
||||
<li class="menu-text"><img src="images/rocks.syng.Syng.png" alt="Syng.Rocks! Logo" height=30></li>
|
||||
<li><a href="index.html">Home</a></li>
|
||||
<li><a href="install.html">Installation</a></li>
|
||||
<li><a href="faq.html">FAQ</a></li>
|
||||
<li><a href="#">Server</a></li>
|
||||
<li><a href="#privacy">Privacy Policy</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="main-content-section" style="padding-top: 100px;">
|
||||
<div class="grid-container">
|
||||
<h1>FAQ</h1>
|
||||
<dl>
|
||||
<dt>Does Syng.Rocks! cost money?</dt>
|
||||
<dd>
|
||||
No, Syng.Rocks! is free software and licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). You can use it for free without any limitations.
|
||||
</dd>
|
||||
<dt>Can you add song XYZ?</dt>
|
||||
<dd>
|
||||
Syng.Rocks! does not host any songs itself.
|
||||
The client fetches songs from YouTube or any of your configured sources.
|
||||
</dd>
|
||||
<dt>What are sources?</dt>
|
||||
<dd>
|
||||
Since Syng.Rocks! does not host any songs itself, songs played by the playback client, need to come from external sources. Currently the following sources can be added:
|
||||
<ul>
|
||||
<li>YouTube</li>
|
||||
<li>A S3 compatible server</li>
|
||||
<li>A local directory</li>
|
||||
</ul>
|
||||
The sources are accessed from the playback client directly, the server is mostly unaware of the sources. It currently is sent a list of files to utilize the search feature.
|
||||
</dd>
|
||||
<dt>What file format can Syng.Rocks! play?</dt>
|
||||
<dd>
|
||||
Syng.Rocks! uses <a href="https://mpv.io" target="_blank">MPV</a> to play the karaoke songs, so it supports most video formats including <code>cdg+mp3</code>.
|
||||
</dd>
|
||||
<dt>What do you mean by <emph>Playback Client</emph>,<emph>Web Client</emph> and <emph>Server</emph>?</dt>
|
||||
<dd>
|
||||
<p></p>The <emph>Playback Client</emph> is the application that plays the songs and displays the lyrics. It is a desktop application.
|
||||
The <emph>Web Client</emph> is the web application that allows you to manage the queue and search for songs. It is used by the guests to add songs to the queue.
|
||||
The <emph>Server</emph> is the backend that manages the queue and handles connection between web clients and playback clients.</p>
|
||||
<p>
|
||||
If you only want to host a karaoke event, you only need the playback client.
|
||||
The server is optional, as you can use the public server at <a href="https://syng.rocks" target="_blank">syng.rocks</a>.
|
||||
</p>
|
||||
</dd>
|
||||
<dt>Can I use Syng.Rocks! without internet?</dt>
|
||||
<dd>
|
||||
Yes and no. The playback client needs to connect to a server instance. While you can host the server yourself in your intranet, the featureset will be limited, as some source (such as YouTube) need the playback client to reach YouTube. You can however use local and s3 sources, that are reachable from the playback client.
|
||||
</dd>
|
||||
<dt>Can I use Syng.Rocks! without a server?</dt>
|
||||
<dd>
|
||||
You can use the public server at <a href="https://syng.rocks" target="_blank">syng.rocks</a> to host your karaoke events. No need to roll up your own server.
|
||||
</dd>
|
||||
<dt>Can I host my own server?</dt>
|
||||
<dd>
|
||||
Yes, you can host your own server. The server is available as a Docker image on GitHub, or you can install it using the Python Package Index (PyPI) package <code>syng[server]</code>.
|
||||
For more information, see the <a href="install.html">installation instructions</a>.
|
||||
</dd>
|
||||
<dt><a id="waiting-room"></a>What is the waiting room?</dt>
|
||||
<dd>
|
||||
The waiting room is a feature that allows you to limit the amount of songs a guest can have in the queue.
|
||||
If the waiting room is enabled, guests can only add songs to the queue if they have no songs in the queue. All additional songs are placed in a waiting room and automatically leave the queue once no songs of the guest are left in the queue.
|
||||
</dd>
|
||||
<dt>What data do you store?</dt>
|
||||
<dd>
|
||||
Syng.Rocks! does not store any personal data. The server only stores the current state of the queue.
|
||||
If you use the public server at <a href="https://syng.rocks" target="_blank">syng.rocks</a>, the server will also store your IP address for a limited time to prevent abuse.
|
||||
For more information, see the <a href="#privacy">privacy policy</a>.
|
||||
</dd>
|
||||
<dt>I cannot connect to <a href="https://syng.rocks" target="_blank">https://syng.rocks</a>.</dt>
|
||||
<dd>
|
||||
Sometimes the server is down for maintenance. Check the official <a href="https://floss.social/@syng" target="_blank">Mastodon account</a> for announcements. Also check, if your client is up to date. The server is only compatible with the latest release.
|
||||
</dd>
|
||||
<dt>What is the restricted mode of the server?</dt>
|
||||
<dd>
|
||||
When the server is in restricted mode, <i>server side search</i> is only available to authenticated rooms. For other rooms, a search request is forwarded to the playback client and results are then send back to the web client.
|
||||
</dd>
|
||||
<dt>Something does not work, or I have questions not covered here</dt>
|
||||
<dd>
|
||||
Feel free to open an issue on the official issue tracker on <a href="https://github.com/christofsteel/syng/issues" target="_blank">GitHub</a> or reach out to us at our official Mastodon account: <a href="https://floss.social/@syng" target="_blank">@syng@floss.social</a> account or join our official matrix room: <a href="https://matrix.to/#/#syng:matrix.org" target="_blank">#syng:matrix.org</a>.
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="js/vendor/jquery.js"></script>
|
||||
<script src="js/vendor/what-input.js"></script>
|
||||
<script src="js/vendor/foundation.js"></script>
|
||||
<script src="js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
BIN
images/background_smaller.jpg
Normal file
After Width: | Height: | Size: 165 KiB |
BIN
images/syng.png
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 29 KiB |
110
index.html
|
@ -1,110 +0,0 @@
|
|||
<!doctype html>
|
||||
<html class="no-js" lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Syng.Rocks</title>
|
||||
<link rel="stylesheet" href="css/foundation.css">
|
||||
<link rel="stylesheet" href="css/app.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="top-content-section">
|
||||
<div class="top-bar">
|
||||
<div class="top-bar-left">
|
||||
<ul class="menu">
|
||||
<li class="menu-text"><img src="images/rocks.syng.Syng.png" alt="Syng.Rocks! Logo" height=30></li>
|
||||
<li><a href="index.html">Home</a></li>
|
||||
<li><a href="install.html">Installation</a></li>
|
||||
<li><a href="faq.html">FAQ</a></li>
|
||||
<li><a href="#">Server</a></li>
|
||||
<li><a href="#privacy">Privacy Policy</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hero-full-screen">
|
||||
<div class="middle-content-section grid-container">
|
||||
<div class="grid-x align-middle">
|
||||
<div class="cell large-6">
|
||||
<img src="images/overview.png" alt="Syng.Rocks Overview" class="work-feature-block-image overview-image"/>
|
||||
</div>
|
||||
<div class="cell large-6">
|
||||
<div class="hero-section-text">
|
||||
<h1>Syng.Rocks!</h1>
|
||||
<h5>Easily host karaoke events</h5>
|
||||
<p>
|
||||
Syng.Rocks! is a karaoke app that allows you to host karaoke events without much hassle.
|
||||
Whether you have a big collection of karaoke songs, or just want to stream karaoke songs from YouTube, whether you want to sing with a couple of friends or with a crowd of over 100 people, Syng.Rocks! has you covered in a privacy friendly manner. No need to register, no need to log in, Syng.Rocks! will never collect any personal data from you. You can even host your own server if you want to.
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://flathub.org/apps/rocks.syng.Syng" target="_blank" class="button">Linux/Flatpak</a>
|
||||
<a href="https://github.com/christofsteel/syng/releases" target="_blank" class="button">Windows</a>
|
||||
<a href="https://syng.rocks" target="_blank" class="button hollow">Web Client</a>
|
||||
<a href="https://github.com/christofsteel/syng" target="_blank" class="button hollow">Source Code</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="main-content-section">
|
||||
<div class="grid-container">
|
||||
<div class="grid-x grid-padding-x textleft align-right">
|
||||
<div class="cell medium-5 text-right">
|
||||
<h2>Get started</h2>
|
||||
<p>
|
||||
If you only want to have a small YouTube based karaoke event, you can just download the app, share the generated QR Code and start singing. No registration, no login and no configuration required.
|
||||
</p>
|
||||
</div>
|
||||
<div class="cell medium-5">
|
||||
<img src="images/syng.png" alt="Syng.Rocks Client" class="work-feature-block-image"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid-x grid-padding-x textright">
|
||||
<div class="cell medium-8">
|
||||
<img src="images/web-shadows.png" alt="Syng.Rocks Web Client" class="work-feature-block-image"/>
|
||||
</div>
|
||||
<div class="cell medium-4">
|
||||
<h2>Web client</h2>
|
||||
<p>
|
||||
Let your guests join your karaoke event using the web client. They can use their browser on their own devices to search for songs and queue them up.
|
||||
The web client also contains an admin mode, that allows for manual moderation of the song queue.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid-x grid-padding-x textleft">
|
||||
<div class="cell medium-4">
|
||||
<h2>Configure to your needs</h2>
|
||||
<p>
|
||||
Syng allows for a lot of configuration options. You can set up your own song database, you can set up a <a href="faq.html#waiting-room">waiting room</a>, a set time the event ends and much more.
|
||||
</p>
|
||||
</div>
|
||||
<div class="cell medium-8">
|
||||
<img src="./images/syng_advanced.png" alt="Syng.Rocks Client" class="work-feature-block-image"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid-x grid-padding-x textright">
|
||||
<div class="cell medium-7">
|
||||
<img src="images/sources.svg" style="max-height:250px" alt="Syng.Rocks Web Client" class="work-feature-block-image"/>
|
||||
</div>
|
||||
<div class="cell medium-5">
|
||||
<h2>Multiple Sources</h2>
|
||||
<p>
|
||||
Syng.Rocks! supports multiple sources for karaoke songs. The default source is YouTube, but you can configure a remote S3 compatible server or simply a folder on your system. The client connects directly to the sources, no login data is ever shared with the server.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="js/vendor/jquery.js"></script>
|
||||
<script src="js/vendor/what-input.js"></script>
|
||||
<script src="js/vendor/foundation.js"></script>
|
||||
<script src="js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
67
install.html
|
@ -1,67 +0,0 @@
|
|||
<!doctype html>
|
||||
<html class="no-js" lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Syng.Rocks</title>
|
||||
<link rel="stylesheet" href="css/foundation.css">
|
||||
<link rel="stylesheet" href="css/app.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="top-content-section">
|
||||
<div class="top-bar">
|
||||
<div class="top-bar-left">
|
||||
<ul class="menu">
|
||||
<li class="menu-text"><img src="images/rocks.syng.Syng.png" alt="Syng.Rocks! Logo" height=30></li>
|
||||
<li><a href="index.html">Home</a></li>
|
||||
<li><a href="install.html">Installation</a></li>
|
||||
<li><a href="#">FAQ</a></li>
|
||||
<li><a href="#">Server</a></li>
|
||||
<li><a href="#privacy">Privacy Policy</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="main-content-section" style="padding-top: 100px;">
|
||||
<div class="grid-container">
|
||||
<h1>Installation</h1>
|
||||
<h2>Client</h2>
|
||||
<p>
|
||||
Depending on your platform, you can install Syng.Rocks! in different ways.
|
||||
<dl>
|
||||
<dt>Linux</dt>
|
||||
<dd>
|
||||
Syng.Rocks! is available as a Flatpak on <a href="https://flathub.org/apps/rocks.syng.Syng" target="_blank">Flathub</a>. You can install it using the command line with:
|
||||
<pre>flatpak install rocks.syng.Syng</pre>
|
||||
There also exists an Arch Linux package in the <a href="https://aur.archlinux.org/packages/syng-client" target="_blank">AUR</a>.
|
||||
</dd>
|
||||
<dt>Windows</dt>
|
||||
<dd>
|
||||
Windows binaries are available on <a href="https://github.com/christofsteel/syng/releases">GitHub</a>. This is a portable version and does not require installation.
|
||||
</dd>
|
||||
<dt>Generic</dt>
|
||||
<dd>
|
||||
The Syng.Rocks! client is available in the Python Package Index (PyPI) as <code>syng</code>. You can install it using pip:
|
||||
<pre>pip install syng[client]</pre>
|
||||
</dd>
|
||||
</dl>
|
||||
</p>
|
||||
<h2>Server</h2>
|
||||
<p>
|
||||
The server is available as a Docker image hosted on GitHub. You can install it with
|
||||
<pre>docker run ghcr.io/christofsteel/syng</pre>
|
||||
Alternatively, you can also run the server using the Python Package Index (PyPI) package <code>syng</code>:
|
||||
<pre>pip install syng[server]</pre>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="js/vendor/jquery.js"></script>
|
||||
<script src="js/vendor/what-input.js"></script>
|
||||
<script src="js/vendor/foundation.js"></script>
|
||||
<script src="js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
41
site.template.html
Normal file
|
@ -0,0 +1,41 @@
|
|||
{% set nav = {
|
||||
"Home": "index.html",
|
||||
"Installation": "install.html",
|
||||
"FAQ": "faq.html",
|
||||
"Privacy Policy": "privacy.html",
|
||||
} %}
|
||||
<!doctype html>
|
||||
<html class="no-js" lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Syng.Rocks</title>
|
||||
<link rel="stylesheet" href="css/foundation.css">
|
||||
<link rel="stylesheet" href="css/app.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="top-content-section">
|
||||
<div class="top-bar">
|
||||
<div class="top-bar-left">
|
||||
<ul class="menu">
|
||||
<li class="menu-text"><img src="images/rocks.syng.Syng.png" alt="Syng.Rocks! Logo" height=30></li>
|
||||
{% for name, url in nav.items() %}
|
||||
<li><a href="{{ url }}">{{ name }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ header }}
|
||||
{{ content }}
|
||||
|
||||
|
||||
<script src="js/vendor/jquery.js"></script>
|
||||
<script src="js/vendor/what-input.js"></script>
|
||||
<script src="js/vendor/foundation.js"></script>
|
||||
<script src="js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
73
sites/faq.md
Normal file
|
@ -0,0 +1,73 @@
|
|||
!!section:content,markdown
|
||||
/// html | div#main-content-section[style='padding-top: 100px;']
|
||||
/// html | div.grid-container
|
||||
# FAQ
|
||||
|
||||
Is using Syng.Rocks! free?
|
||||
|
||||
: Yes, Syng.Rocks! is free software and licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). You can use it for free without any limitations.
|
||||
|
||||
Can you add a specific song?
|
||||
|
||||
: Syng.Rocks! does not host any songs itself. The client fetches songs from YouTube or any of your configured sources.
|
||||
|
||||
What are sources?
|
||||
|
||||
: Since Syng.Rocks! does not host any songs itself, songs played by the playback client, need to come from external sources. Currently, the following sources can be added:
|
||||
|
||||
* YouTube
|
||||
* Any S3 compatible server
|
||||
* A local directory
|
||||
|
||||
The sources are accessed from the playback client directly, the server is unaware of the contents of the sources and just uses a list of filenames to search for songs.
|
||||
|
||||
What file format can Syng.Rocks! play?
|
||||
|
||||
: Syng.Rocks! uses [MPV](https://mpv.io) to play the karaoke songs, so it supports most video formats including `cdg+mp3`.
|
||||
|
||||
What do you mean by *Playback Client*, *Web Client* and *Server*?
|
||||
|
||||
: The *Playback Client* is the application that plays the songs and displays the lyrics. It is a desktop application.
|
||||
The *Web Client* is the web application that allows you to manage the queue and search for songs. It is used by the guests to add songs to the queue.
|
||||
The *Server* is the backend that manages the queue and handles connection between web clients and playback clients.
|
||||
|
||||
If you only want to host a karaoke event, you only need the playback client.
|
||||
The server is optional, as you can use the public server at [syng.rocks](https://syng.rocks).
|
||||
|
||||
Can I use Syng.Rocks! without internet?
|
||||
|
||||
: Yes and no. The playback client needs to connect to a server instance. While you can host the server yourself in your intranet, the experience can be limited, as some source (such as YouTube) need the playback client to reach YouTube. You can however use local and s3 sources, that are reachable from the playback client.
|
||||
|
||||
Can I use Syng.Rocks! without a server?
|
||||
|
||||
: You do need some kind of server to manage the queue, but you can use the public server at [syng.rocks](https://syng.rocks) to host your karaoke events. No need to roll up your own server.
|
||||
|
||||
Can I host my own server?
|
||||
|
||||
: Yes, you can host your own server. The server is available as a Docker image on GitHub, or you can install it using the Python Package Index (PyPI) package `syng[server]`.
|
||||
For more information, see the [installation instructions](install.html).
|
||||
|
||||
<a id="waiting-room"></a>What is the waiting room?
|
||||
|
||||
: The waiting room is a feature that allows you to limit the amount of songs a guest can have in the queue.
|
||||
If the waiting room is enabled, guests can only add songs to the queue if they have no songs in the queue. All additional songs are placed in a waiting room and automatically leave the queue once no songs of the guest are left in the queue.
|
||||
|
||||
What data do you store?
|
||||
|
||||
: Syng.Rocks! does not store any personal data. The server only stores the current state of the queue.
|
||||
If you use the public server at [syng.rocks](https://syng.rocks), the server will also store your IP address for a limited time to prevent abuse.
|
||||
For more information, see the [privacy policy](privacy.html).
|
||||
|
||||
I cannot connect to [syng.rocks](https://syng.rocks).
|
||||
|
||||
: Sometimes the server is down for maintenance. Check the official [Mastodon account](https://floss.social/@syng) for announcements. Also check, if your client is up-to-date. The server is only compatible with the latest release.
|
||||
|
||||
What is the restricted mode of the server?
|
||||
|
||||
: When the server is in restricted mode, *server side search* is only available to authenticated rooms. For other rooms, a search request is forwarded to the playback client and results are then sent back to the web client.
|
||||
|
||||
Something does not work, or I have questions not covered here
|
||||
|
||||
: Feel free to open an issue on the official issue tracker on [GitHub](https://github.com/christofsteel/syng/issues) or reach out to us at our official Mastodon account: [@syng@floss.social](https://floss.social/@syng) account or join our official matrix room: [#syng:matrix.org](https://matrix.to/#/#syng:matrix.org).
|
||||
///
|
||||
///
|
66
sites/index.md
Normal file
|
@ -0,0 +1,66 @@
|
|||
!!section:header,markdown
|
||||
/// html | div.hero-full-screen
|
||||
/// html | div.middle-content-section.grid-container
|
||||
/// html | div.grid-x.align-middle
|
||||
/// html | div.cell.large-6
|
||||

|
||||
///
|
||||
/// html | div.cell.large-6
|
||||
/// html | div.hero-section-text
|
||||
# Syng.Rocks!
|
||||
##### Easily host karaoke events
|
||||
|
||||
Syng.Rocks! is a karaoke app that allows you to host karaoke events without much hassle. Whether you have a big collection of karaoke songs, or just want to stream karaoke songs from YouTube, whether you want to sing with a couple of friends or with a crowd of over 100 people, Syng.Rocks! has you covered in a privacy-friendly manner. No need to register, no need to log in, Syng.Rocks! will never collect any personal data from you. You can even host your own server if you want to.
|
||||
|
||||
<a href="https://flathub.org/apps/rocks.syng.Syng" target="_blank" class="button">Linux/Flatpak</a>
|
||||
<a href="https://github.com/christofsteel/syng/releases" target="_blank" class="button">Windows</a>
|
||||
<a href="https://syng.rocks" target="_blank" class="button hollow">Web Client</a>
|
||||
<a href="https://github.com/christofsteel/syng" target="_blank" class="button hollow">Source Code</a>
|
||||
!!section:content,markdown
|
||||
/// html | div#main-content-section
|
||||
/// html | div.grid-container
|
||||
/// html | div.grid-x.grid-padding.textleft.align-right
|
||||
/// html | div.cell.medium-5.text-right
|
||||
## Start Singing
|
||||
|
||||
If you only want to have a small YouTube based karaoke event, you can just download the app, share the generated QR Code and start singing. No registration, no login and no configuration required.
|
||||
///
|
||||
/// html | div.cell.medium-5.showcase-image
|
||||

|
||||
///
|
||||
///
|
||||
/// html | div.grid-x.grid-padding.textright
|
||||
/// html | div.cell.medium-8.showcase-image
|
||||

|
||||
///
|
||||
/// html | div.cell.medium-4
|
||||
## Web client
|
||||
|
||||
Let your guests join your karaoke event using the web client. They can use their browser on their own devices to search for songs and queue them up.
|
||||
The web client also contains an admin mode, that allows for manual moderation of the song queue.
|
||||
///
|
||||
///
|
||||
/// html | div.grid-x.grid-padding.textleft.align-right
|
||||
/// html | div.cell.medium-4.text-right
|
||||
## Configure to your needs
|
||||
|
||||
Syng.Rocks! allows for a lot of configuration options. You can set up your own song database, you can set up a [waiting room](faq.html#waiting-room), a set time the event ends and much more.
|
||||
///
|
||||
/// html | div.cell.medium-8.showcase-image
|
||||

|
||||
///
|
||||
///
|
||||
/// html | div.grid-x.grid-padding.textright
|
||||
/// html | div.cell.medium-7.showcase-image
|
||||

|
||||
///
|
||||
/// html | div.cell.medium-5
|
||||
## Multiple Sources
|
||||
|
||||
Syng.Rocks! supports multiple sources for karaoke songs. The default source is YouTube, but you can configure a remote S3 compatible server or simply a folder on your system. The client connects directly to the sources, no login data is ever shared with the server.
|
||||
///
|
||||
///
|
||||
|
||||
|
||||
|
||||
|
41
sites/install.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
!!section:content,markdown
|
||||
/// html | div#main-content-section[style='padding-top: 100px;']
|
||||
/// html | div.grid-container
|
||||
# Installation
|
||||
## Client
|
||||
|
||||
Depending on your platform, you can install Syng.Rocks! in different ways.
|
||||
|
||||
Linux
|
||||
|
||||
: Syng.Rocks! is available as a Flatpak on [Flathub](https://flathub.org/apps/rocks.syng.Syng). You can install it using the command line with:
|
||||
|
||||
```
|
||||
flatpak install rocks.syng.Syng
|
||||
```
|
||||
|
||||
There also exists an Arch Linux package in the [AUR](https://aur.archlinux.org/packages/syng-client).
|
||||
|
||||
Windows
|
||||
|
||||
: Windows binaries are available on [Github](https://github.com/christofsteel/syng/releases). This is a portable version and does not require installation.
|
||||
|
||||
Generic
|
||||
|
||||
: Syng.Rocks! is available in the Python Package Index (PyPI) as `syng`. You can install the client using pip:
|
||||
|
||||
```
|
||||
pip install syng[client]
|
||||
```
|
||||
|
||||
## Server
|
||||
|
||||
The server is available as a Docker image hosted on Github. You can run it with:
|
||||
|
||||
docker run ghcr.io/christofsteel/syng
|
||||
|
||||
Alternatively, you can run the server using the Python Package Index (PyPI) package `syng`:
|
||||
|
||||
pip install syng[server]
|
||||
///
|
||||
///
|
28
sites/privacy.md
Normal file
|
@ -0,0 +1,28 @@
|
|||
!!section:content,markdown
|
||||
/// html | div#main-content-section[style='padding-top: 100px;']
|
||||
/// html | div.grid-container
|
||||
# Privacy Policy
|
||||
|
||||
Syng.Rocks! respects your privacy. We do not collect any personal data, apart from what is necessary for the application to function and for anti-abuse reasons.
|
||||
|
||||
The only data shared from using the web client is the following
|
||||
|
||||
- The chosen username
|
||||
- The name of the room you connect to
|
||||
- Search queries
|
||||
- Enqueued songs
|
||||
- The IP address of your device
|
||||
|
||||
This data may be collected in log files and used for maintenance and anti-abuse reasons. We will never sell your data.
|
||||
|
||||
The data shared from using the playback client is the following
|
||||
|
||||
- The chosen room name
|
||||
- The admin password
|
||||
- The configuration of the room
|
||||
- The configuration of the sources, excluding any authentication data
|
||||
- A list of file names present in the sources to handle search request
|
||||
|
||||
This data will be deleted from the server, once a karaoke session is removed from the server, which is two hours after the last client disconnects.
|
||||
|
||||
Syng.Rocks! does not use any cookies, but stores the chosen username and room name in the local storage of your browser. The local storage is cleared, if you press the `Log out` button.
|