forked from server/soundboard
prod-changes
This commit is contained in:
parent
d24cef2b51
commit
217603823e
@ -33,7 +33,7 @@ def index(sound=None, text=None, video=None):
|
|||||||
pitch = request.form.get("pitch", default="")
|
pitch = request.form.get("pitch", default="")
|
||||||
pitch = pitch if pitch.strip() != "" else "50"
|
pitch = pitch if pitch.strip() != "" else "50"
|
||||||
|
|
||||||
subprocess.Popen(["espeak", "-v", voice, "-s", speed, "-p", pitch, text], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
subprocess.Popen(["espeak", "-v", voice, "-s", speed, "-p", pitch, text.encode('utf-8')], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||||
return redirect("/")
|
return redirect("/")
|
||||||
|
|
||||||
video = request.args.get("video")
|
video = request.args.get("video")
|
||||||
|
|||||||
2801
static/howler.js
Normal file
2801
static/howler.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -20,11 +20,11 @@ h1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
form {
|
form {
|
||||||
padding: 5px;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input, button {
|
||||||
background-color: #666;
|
background-color: #666;
|
||||||
border: 1px solid #999;
|
border: 1px solid #999;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
@ -34,6 +34,21 @@ input {
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background-color: #999;
|
||||||
|
border: 1px solid #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:active {
|
||||||
|
background-color: #999;
|
||||||
|
border: 1px solid #666;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
@ -65,12 +80,14 @@ section {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#reset {
|
div #reset {
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
|
display: inline;
|
||||||
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
#reset:hover {
|
div #reset:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,6 +113,29 @@ section {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sound a:hover {
|
.sound a:hover {
|
||||||
background-color: #ff4136;
|
cursor: pointer;
|
||||||
box-shadow: inset 5px 5px 5px rgba(0, 0, 0, 0.6);
|
}
|
||||||
|
|
||||||
|
.sound a:active {
|
||||||
|
background-color: #ff4136;
|
||||||
|
box-shadow: inset 5px 5px 5px rgba(0, 0, 0, 0.6);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sound-pressed {
|
||||||
|
background-color: #ff4136 !important;
|
||||||
|
box-shadow: inset 5px 5px 5px rgba(0, 0, 0, 0.6) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unselectable {
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#local-mode-button .local {
|
||||||
|
color: red;
|
||||||
}
|
}
|
||||||
|
|||||||
154
static/main.js
154
static/main.js
@ -1,3 +1,9 @@
|
|||||||
|
|
||||||
|
var localModeEnabled = false;
|
||||||
|
|
||||||
|
// References to howler objects
|
||||||
|
var howlerSounds = [];
|
||||||
|
|
||||||
function ready(fn) {
|
function ready(fn) {
|
||||||
if (document.attachEvent ? document.readyState === "complete" : document.readyState !== "loading") {
|
if (document.attachEvent ? document.readyState === "complete" : document.readyState !== "loading") {
|
||||||
fn();
|
fn();
|
||||||
@ -6,9 +12,11 @@ function ready(fn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ready(function() {
|
function sleep(ms) {
|
||||||
hideSections();
|
return new Promise(resolve => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||
|
|
||||||
|
ready(function() {
|
||||||
var sections = document.querySelectorAll("section");
|
var sections = document.querySelectorAll("section");
|
||||||
var nav = document.querySelectorAll("nav a");
|
var nav = document.querySelectorAll("nav a");
|
||||||
|
|
||||||
@ -28,9 +36,9 @@ ready(function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
var searchfield = document.querySelector("#search");
|
var searchfield = document.querySelector("#search");
|
||||||
|
searchfield.focus();
|
||||||
|
|
||||||
searchfield.addEventListener("keyup", function() {
|
searchfield.addEventListener("keyup", function() {
|
||||||
console.log("Search!");
|
|
||||||
|
|
||||||
var buttons = document.querySelectorAll(".sound");
|
var buttons = document.querySelectorAll(".sound");
|
||||||
|
|
||||||
@ -48,18 +56,77 @@ ready(function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
var reset = document.querySelector("#reset");
|
var reset = document.querySelector("#reset");
|
||||||
|
var sounds_nav = document.querySelector("#sounds-nav");
|
||||||
|
|
||||||
reset.addEventListener("click", function() {
|
reset.addEventListener("click", resetSearch, false);
|
||||||
var buttons = document.querySelectorAll(".sound");
|
sounds_nav.addEventListener("click", resetSearch, false);
|
||||||
|
|
||||||
buttons.forEach(function(item) {
|
addKeyListeners();
|
||||||
item.style.display = "inline-block";
|
|
||||||
});
|
|
||||||
|
|
||||||
searchfield.value = "";
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adds all necessary KeyListeners to document
|
||||||
|
*/
|
||||||
|
function addKeyListeners() {
|
||||||
|
// keyboard listener for global key strokes/inputs
|
||||||
|
document.onkeydown = function(evt) {
|
||||||
|
evt = evt || window.event;
|
||||||
|
if (evt.keyCode == 27) {
|
||||||
|
// esc key
|
||||||
|
resetSearch();
|
||||||
|
} else if ((evt.keyCode == 75 || evt.keyCode == 67) && evt.ctrlKey) {
|
||||||
|
// ctrl+k and ctrl+c key binding
|
||||||
|
killAllAudio();
|
||||||
|
} else if (evt.keyCode == 88 && evt.ctrlKey){
|
||||||
|
// ctrl+x key binding
|
||||||
|
toggleLocalMode();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// keyboard listener for playing sounds using enter key
|
||||||
|
var buttons = document.querySelectorAll(".sound");
|
||||||
|
|
||||||
|
buttons.forEach(function(item) {
|
||||||
|
item.firstChild.addEventListener('keypress', async function (e) {
|
||||||
|
var key = e.keyCode;
|
||||||
|
var source = e.target;
|
||||||
|
// keylistener for enter or ctrl+enter (which is k10 on chrome)
|
||||||
|
if (key === 13 || (key === 10 && e.ctrlKey)) {
|
||||||
|
if(e.ctrlKey){
|
||||||
|
killAllAudio();
|
||||||
|
await sleep(100);
|
||||||
|
}
|
||||||
|
source.classList.add("sound-pressed");
|
||||||
|
source.onclick();
|
||||||
|
await sleep(300);
|
||||||
|
source.classList.remove("sound-pressed");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function resetSearch() {
|
||||||
|
var searchfield = document.querySelector("#search");
|
||||||
|
var buttons = document.querySelectorAll(".sound");
|
||||||
|
|
||||||
|
buttons.forEach(function(item) {
|
||||||
|
item.style.display = "inline-block";
|
||||||
|
});
|
||||||
|
|
||||||
|
searchfield.value = "";
|
||||||
|
searchfield.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reads the stream url from input with id #streaming-url and forwards it to the server using AJAX.
|
||||||
|
*/
|
||||||
|
function playStream() {
|
||||||
|
var streamUrl = document.querySelector("#streaming-url").value;
|
||||||
|
ajaxRequest("/?video="+encodeURI(streamUrl));
|
||||||
|
}
|
||||||
|
|
||||||
function hideSections() {
|
function hideSections() {
|
||||||
var sections = document.querySelectorAll("section");
|
var sections = document.querySelectorAll("section");
|
||||||
|
|
||||||
@ -67,3 +134,68 @@ function hideSections() {
|
|||||||
item.style.display = "none";
|
item.style.display = "none";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ajaxRequest(url) {
|
||||||
|
var ajaxRequest;
|
||||||
|
try{
|
||||||
|
ajaxRequest = new XMLHttpRequest();
|
||||||
|
ajaxRequest.open("GET", url, true);
|
||||||
|
ajaxRequest.send(null);
|
||||||
|
}catch (e){
|
||||||
|
alert("Unfortunately we were unable to handle your request. Please try again later and contact the server administrator if the problem persists.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Switches between local and remote playback mode.
|
||||||
|
* Additionally changes the button text and its color so that the user has a visible feedback.
|
||||||
|
*/
|
||||||
|
function toggleLocalMode() {
|
||||||
|
toggleButton = document.getElementById("local-mode-button").children[0];
|
||||||
|
if(localModeEnabled){
|
||||||
|
localModeEnabled = false;
|
||||||
|
toggleButton.classList.remove("local");
|
||||||
|
toggleButton.innerHTML = "[S]";
|
||||||
|
toggleButton.title = "play sounds on server";
|
||||||
|
}else{
|
||||||
|
localModeEnabled = true;
|
||||||
|
toggleButton.classList.add("local");
|
||||||
|
toggleButton.innerHTML = "[L]";
|
||||||
|
toggleButton.title = "play sounds locally";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Either plays the given sound file locally by using howler.js or forwards the request to the remote server using AJAX.
|
||||||
|
*/
|
||||||
|
function playSound(filename) {
|
||||||
|
if(localModeEnabled){
|
||||||
|
// play local audio using howler.js
|
||||||
|
var sound = new Howl({
|
||||||
|
src: ['/sounds/'+filename]
|
||||||
|
});
|
||||||
|
sound.play();
|
||||||
|
howlerSounds.push(sound);
|
||||||
|
}else{
|
||||||
|
ajaxRequest("/play/"+filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function killAllHowlerAudio() {
|
||||||
|
for(i=0; i<howlerSounds.length; i++) {
|
||||||
|
howlerSounds[i].stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Kills all local or remote audio, depending on localModeEnabled
|
||||||
|
*/
|
||||||
|
function killAllAudio() {
|
||||||
|
if (localModeEnabled) {
|
||||||
|
killAllHowlerAudio();
|
||||||
|
} else {
|
||||||
|
ajaxRequest("/?killvideo=yes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -30,29 +30,32 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav>
|
<nav>
|
||||||
<a href="#sounds">Sounds</a>
|
<a href="#sounds" id="sounds-nav">Sounds</a>
|
||||||
<a href="#youtube">YouTube</a>
|
<a href="#streams">Streams</a>
|
||||||
<a href="#voice">Voice</a>
|
<a href="#voice">Voices</a>
|
||||||
</nav>
|
</nav>
|
||||||
<content>
|
<content>
|
||||||
<section id="sounds">
|
<section id="sounds" style="display:none;">
|
||||||
<div><input type="text" id="search" /><span id="reset">⨯</span></div>
|
<div>
|
||||||
|
<a onclick="toggleLocalMode();" id="local-mode-button"><button title="play sounds on server">[S]</button></a>
|
||||||
|
<input type="text" id="search" autofocus/>
|
||||||
|
<div id="reset">✕</div>
|
||||||
|
</div>
|
||||||
{% for sound in sounds %}
|
{% for sound in sounds %}
|
||||||
<div class="sound"><a href="{{ '/play/' + sound | urlencode }}">{{ sound.split('.', 1)[0] }}</a></div>
|
<div class="sound"><a tabindex="0" class="unselectable" onclick="playSound('{{ sound | urlencode }}');">{{ sound.split('.', 1)[0] }}</a></div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</section>
|
</section>
|
||||||
<section id="youtube">
|
<section id="streams" style="display:none;">
|
||||||
<form action="/" method="GET">
|
<div>
|
||||||
<label for="video">YouTube URL</label>
|
<form>
|
||||||
<input type="text" name="video" />
|
<label for="video">Stream URL</label>
|
||||||
<input type="submit" value="Play" />
|
<input id="streaming-url" type="text" name="video" placeholder="paste stream url here..." />
|
||||||
</form>
|
</form>
|
||||||
<form action="/" method="GET">
|
<button onclick="playStream();">Play!</button>
|
||||||
<input type="hidden" name="killvideo" value="yes" />
|
</div>
|
||||||
<input type="submit" name="submit" value="Terminate videos" />
|
<button name="submit" onclick="killAllAudio();">Terminate videos</button>
|
||||||
</form>
|
|
||||||
</section>
|
</section>
|
||||||
<section id="voice">
|
<section id="voice" style="display:none;">
|
||||||
<form action="/say/" method="POST">
|
<form action="/say/" method="POST">
|
||||||
<input type="text" name="text" />
|
<input type="text" name="text" />
|
||||||
<input type="text" name="voice" placeholder="DE" />
|
<input type="text" name="voice" placeholder="DE" />
|
||||||
@ -64,6 +67,7 @@
|
|||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
</content>
|
</content>
|
||||||
|
<script src="/static/howler.js"></script>
|
||||||
<script src="/static/main.js"></script>
|
<script src="/static/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user