mirror of
https://github.com/badaix/snapcast.git
synced 2025-05-31 01:46:16 +02:00
Return default page if doc_root is empty
This commit is contained in:
parent
279ea736c1
commit
8d54c502bc
5 changed files with 36 additions and 585 deletions
|
@ -94,5 +94,6 @@ target_link_libraries(snapserver ${SERVER_LIBRARIES})
|
|||
install(TARGETS snapserver COMPONENT server DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
install(FILES snapserver.1 COMPONENT server DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
|
||||
install(FILES etc/snapserver.conf COMPONENT server DESTINATION ${CMAKE_INSTALL_SYSCONFDIR})
|
||||
install(FILES etc/index.html COMPONENT server DESTINATION ${CMAKE_INSTALL_DATADIR}/snapserver)
|
||||
install(DIRECTORY etc/snapweb/ DESTINATION ${CMAKE_INSTALL_DATADIR}/snapserver/snapweb)
|
||||
#install(FILES ../debian/snapserver.service DESTINATION ${SYSTEMD_SERVICES_INSTALL_DIR})
|
||||
|
|
|
@ -125,6 +125,7 @@ install:
|
|||
install -g wheel -o root -m 555 $(BIN).1 $(TARGET_DIR)/local/man/man1/$(BIN).1
|
||||
install -g wheel -o root -m 555 etc/$(BIN).bsd $(TARGET_DIR)/local/etc/rc.d/$(BIN)
|
||||
install -g wheel -o root etc/$(BIN).conf /etc/$(BIN).conf
|
||||
install -g wheel -o root -m 644 etc/index.html -Dt /usr/share/snapserver/
|
||||
for file in etc/snapweb/*\.*; do install -g wheel -o root -m 644 $${file} -Dt "/usr/share/snapserver/snapweb/"; done
|
||||
for file in etc/snapweb/3rd-party/*\.*; do install -g wheel -o root -m 644 $${file} -Dt "/usr/share/snapserver/snapweb/3rd-party/"; done
|
||||
|
||||
|
@ -136,6 +137,7 @@ install:
|
|||
install -g wheel -o root $(BIN).1 $(TARGET_DIR)/local/share/man/man1/$(BIN).1
|
||||
install -g wheel -o root etc/$(BIN).plist /Library/LaunchAgents/de.badaix.snapcast.$(BIN).plist
|
||||
install -g wheel -o root etc/$(BIN).conf /etc/$(BIN).conf
|
||||
install -g wheel -o root -m 644 etc/index.html -Dt /usr/share/snapserver/
|
||||
for file in etc/snapweb/*\.*; do install -g wheel -o root -m 644 $${file} -Dt "/usr/share/snapserver/snapweb/"; done
|
||||
for file in etc/snapweb/3rd-party/*\.*; do install -g wheel -o root -m 644 $${file} -Dt "/usr/share/snapserver/snapweb/3rd-party/"; done
|
||||
launchctl load /Library/LaunchAgents/de.badaix.snapcast.$(BIN).plist
|
||||
|
@ -163,6 +165,7 @@ installfiles:
|
|||
install -s -D -g root -o root $(BIN) $(TARGET_DIR)/bin/$(BIN)
|
||||
install -D -g root -o root $(BIN).1 $(TARGET_DIR)/share/man/man1/$(BIN).1
|
||||
install -g root -o root etc/$(BIN).conf /etc/$(BIN).conf;
|
||||
install -g root -o root -m 644 etc/index.html -Dt /usr/share/snapserver/
|
||||
for file in etc/snapweb/*\.*; do install -g root -o root -m 644 $${file} -Dt "/usr/share/snapserver/snapweb/"; done
|
||||
for file in etc/snapweb/3rd-party/*\.*; do install -g root -o root -m 644 $${file} -Dt "/usr/share/snapserver/snapweb/3rd-party/"; done
|
||||
|
||||
|
|
|
@ -155,6 +155,17 @@ void ControlSessionHttp::handle_request(http::request<Body, http::basic_fields<A
|
|||
return res;
|
||||
};
|
||||
|
||||
// Returns a configuration help
|
||||
auto const unconfigured = [&req]() {
|
||||
http::response<http::string_body> res{http::status::ok, req.version()};
|
||||
res.set(http::field::server, HTTP_SERVER_NAME);
|
||||
res.set(http::field::content_type, "text/html");
|
||||
res.keep_alive(req.keep_alive());
|
||||
res.body() = "<html><head><title>Snapcast Default Page</title></head><body>TODO: description how to configure the doc_root</body></html>";
|
||||
res.prepare_payload();
|
||||
return res;
|
||||
};
|
||||
|
||||
// Returns a server error response
|
||||
auto const server_error = [&req](boost::beast::string_view what) {
|
||||
http::response<http::string_body> res{http::status::internal_server_error, req.version()};
|
||||
|
@ -190,14 +201,21 @@ void ControlSessionHttp::handle_request(http::request<Body, http::basic_fields<A
|
|||
if (req.target().empty() || req.target()[0] != '/' || req.target().find("..") != beast::string_view::npos)
|
||||
return send(bad_request("Illegal request-target"));
|
||||
|
||||
if (settings_.doc_root.empty())
|
||||
return send(not_found(req.target()));
|
||||
|
||||
// Build the path to the requested file
|
||||
std::string path = path_cat(settings_.doc_root, req.target());
|
||||
if (req.target().back() == '/')
|
||||
path.append("index.html");
|
||||
|
||||
if (settings_.doc_root.empty())
|
||||
{
|
||||
std::string default_page = "/usr/share/snapserver/index.html";
|
||||
struct stat buffer;
|
||||
if (stat(default_page.c_str(), &buffer) == 0)
|
||||
path = default_page;
|
||||
else
|
||||
return send(unconfigured());
|
||||
}
|
||||
|
||||
LOG(DEBUG, LOG_TAG) << "path: " << path << "\n";
|
||||
// Attempt to open the file
|
||||
beast::error_code ec;
|
||||
|
|
11
server/etc/index.html
Normal file
11
server/etc/index.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<title>Snapcast Default Page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
TODO: description how to configure the doc_root
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,582 +0,0 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<title>Snapcast Interface</title>
|
||||
Taken from <a href="https://github.com/derglaus/snapcast-websockets-ui">derglaus/snapcast-websockets-ui</a> for
|
||||
testing purposes
|
||||
<script>
|
||||
|
||||
var connection = new WebSocket('ws://' + window.location.hostname + ':1780/jsonrpc');
|
||||
|
||||
var server;
|
||||
|
||||
connection.onmessage = function (e) {
|
||||
var recv = e.data
|
||||
// console.log(recv);
|
||||
var answer = JSON.parse(recv);
|
||||
console.log(answer)
|
||||
if (answer.id == 1) {
|
||||
server = answer.result;
|
||||
} else if (Array.isArray(answer)) {
|
||||
for (let i = 0; i < answer.length; i++) {
|
||||
action(answer[i]);
|
||||
}
|
||||
} else {
|
||||
action(answer);
|
||||
|
||||
}
|
||||
|
||||
show()
|
||||
}
|
||||
|
||||
connection.onopen = function () {
|
||||
send('{"id":1,"jsonrpc":"2.0","method":"Server.GetStatus"}')
|
||||
}
|
||||
|
||||
connection.onerror = function () {
|
||||
alert("error");
|
||||
}
|
||||
|
||||
function action(answer) {
|
||||
switch (answer.method) {
|
||||
case 'Client.OnVolumeChanged':
|
||||
case 'Client.OnLatencyChanged':
|
||||
case 'Client.OnNameChanged':
|
||||
clientChange(answer.params);
|
||||
break;
|
||||
case 'Client.OnConnect':
|
||||
case 'Client.OnDisconnect':
|
||||
clientConnect(answer.params);
|
||||
break;
|
||||
case 'Group.OnMute':
|
||||
groupMute(answer.params);
|
||||
break;
|
||||
case 'Group.OnStremChanged':
|
||||
groupStream(answer.params);
|
||||
break;
|
||||
case 'Stream.OnUpdate':
|
||||
streamUpdate(answer.params);
|
||||
break;
|
||||
case 'Server.OnUpdate':
|
||||
server = answer.params;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function send(str) {
|
||||
var buf = new ArrayBuffer(str.length);
|
||||
var bufView = new Uint8Array(buf);
|
||||
for (var i = 0, strLen = str.length; i < strLen; i++) {
|
||||
bufView[i] = str.charCodeAt(i);
|
||||
}
|
||||
|
||||
// console.log(buf);
|
||||
var recv = String.fromCharCode.apply(null, new Uint8Array(buf));
|
||||
// console.log(recv);
|
||||
|
||||
connection.send(buf)
|
||||
|
||||
}
|
||||
|
||||
function clientChange(params) {
|
||||
// Update the client configuration with one from params
|
||||
for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
|
||||
for (let i_client = 0; i_client < server.server.groups[i_group].clients.length; i_client++) {
|
||||
if (server.server.groups[i_group].clients[i_client].id == params.id) {
|
||||
server.server.groups[i_group].clients[i_client].config = Object.assign(server.server.groups[i_group].clients[i_client].config, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clientConnect(params) {
|
||||
// Update all client info
|
||||
for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
|
||||
for (let i_client = 0; i_client < server.server.groups[i_group].clients.length; i_client++) {
|
||||
if (server.server.groups[i_group].clients[i_client].id == params.client.id) {
|
||||
server.server.groups[i_group].clients[i_client] = params.client;
|
||||
// console.log(server.server.groups[i_group].clients[i_client]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function groupMute(params) {
|
||||
// Set group mute boolean
|
||||
for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
|
||||
if (server.server.groups[i_group].id == params.id) {
|
||||
server.server.groups[i_group].muted = params.mute;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function groupStream(params) {
|
||||
// Set group stream id
|
||||
for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
|
||||
if (server.server.groups[i_group].id == params.id) {
|
||||
server.server.groups[i_group].stream_id = params.stream_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function streamUpdate(params) {
|
||||
// Update all stream inforamtion
|
||||
for (let i_stream = 0; i_stream < server.server.streams.length;) {
|
||||
if (server.server.streams[i_stream].id == params.id) {
|
||||
server.server.streams[i_stream] = params.stream;
|
||||
// console.log(server.server.streams[i_stream]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function show() {
|
||||
// Render the page
|
||||
var content = "";
|
||||
|
||||
for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
|
||||
// Set mute variables
|
||||
var classgroup;
|
||||
var unmuted;
|
||||
var mutetext;
|
||||
if (server.server.groups[i_group].muted == true) {
|
||||
classgroup = 'groupmuted';
|
||||
unmuted = 'false';
|
||||
mutetext = '🔇';
|
||||
} else {
|
||||
classgroup = 'group';
|
||||
unmuted = 'true';
|
||||
mutetext = '🔊';
|
||||
}
|
||||
|
||||
// Start group div
|
||||
content += "<div id='g_" + server.server.groups[i_group].id + "' class='" + classgroup + "'>";
|
||||
|
||||
// Create stream selection dropdown
|
||||
var streamselect = "<select id='stream_" + server.server.groups[i_group].id + "' onchange='setStream(\"" + server.server.groups[i_group].id + "\")' class='stream'>"
|
||||
for (let i_stream = 0; i_stream < server.server.streams.length; i_stream++) {
|
||||
var streamselected = "";
|
||||
if (server.server.groups[i_group].stream_id == server.server.streams[i_stream].id) {
|
||||
streamselected = 'selected'
|
||||
}
|
||||
streamselect += "<option value='" + server.server.streams[i_stream].id + "' " + streamselected + ">" + server.server.streams[i_stream].id + ": " + server.server.streams[i_stream].status + "</option>";
|
||||
}
|
||||
|
||||
streamselect += "</select>";
|
||||
content += streamselect;
|
||||
|
||||
// Group mute and refresh button
|
||||
content += " <a href=\"javascript:setMuteGroup('" + server.server.groups[i_group].id + "','" + unmuted + "');\" class='mutebuttongroup'>" + mutetext + "</a>";
|
||||
content += "<input type='button' value='Refresh' class='refreshbutton' onclick='javascript: location.reload()'>";
|
||||
content += "<br/>";
|
||||
|
||||
// Create clients in group
|
||||
for (let i_client = 0; i_client < server.server.groups[i_group].clients.length; i_client++) {
|
||||
var sv = server.server.groups[i_group].clients[i_client];
|
||||
|
||||
// Set name and connection state vars, start client div
|
||||
var name;
|
||||
var clas = 'client'
|
||||
if (sv.config.name != "") {
|
||||
name = sv.config.name;
|
||||
} else {
|
||||
name = sv.host.name;
|
||||
}
|
||||
if (sv.connected == false) {
|
||||
clas = 'disconnected';
|
||||
}
|
||||
content = content + "<div id='c_" + sv.id + "' class='" + clas + "'>";
|
||||
|
||||
// Client mute status vars
|
||||
var unmuted;
|
||||
var mutetextclient;
|
||||
var sliderclass;
|
||||
if (sv.config.volume.muted == true) {
|
||||
unmuted = 'false';
|
||||
sliderclass = 'slidermute';
|
||||
mutetext = '🔇';
|
||||
} else {
|
||||
sliderclass = 'slider'
|
||||
unmuted = 'true';
|
||||
mutetext = '🔊';
|
||||
}
|
||||
|
||||
// Client group selection vars
|
||||
var groupselect = "<select id='group_" + sv.id + "' onchange='setGroup(\"" + sv.id + "\")'>";
|
||||
for (let o_group = 0; o_group < server.server.groups.length; o_group++) {
|
||||
var groupselected = "";
|
||||
if (o_group == i_group) {
|
||||
groupselected = 'selected'
|
||||
}
|
||||
groupselect = groupselect + "<option value='" + server.server.groups[o_group].id + "' " + groupselected + ">Group " + o_group + " (" + server.server.groups[o_group].clients.length + " Clients)</option>";
|
||||
}
|
||||
|
||||
groupselect = groupselect + "<option value='new'>new</option>";
|
||||
groupselect = groupselect + "</select>"
|
||||
|
||||
// Populate client div
|
||||
content = content + " <a href=\"javascript:setVolume('" + sv.id + "','" + unmuted + "');\" class='mutebutton'>" + mutetext + "</a>";
|
||||
content = content + "<div class='sliders'><div class='sliderdiv'><input type='range' min=0 max=100 step=1 id='vol_" + sv.id + "' onchange='javascript:setVolume(\"" + sv.id + "\",\"" + sv.config.volume.muted + "\")' value=" + sv.config.volume.percent + " class='" + sliderclass + "' orient='vertical'></div>";
|
||||
content = content + "<div class='finebg'>++<br>+<br>0<br>-<br>--</div><div class='sliderdiv_fine'><input type='range' min=0 max=10 step=1 id='vol_fine_" + sv.id + "' onchange='javascript:setVolume(\"" + sv.id + "\",\"" + sv.config.volume.muted + "\")' value=5 class='" + sliderclass + "_fine' orient='vertical'></div></div>";
|
||||
content = content + " <a href=\"javascript:setName('" + sv.id + "');\" class='edit'>✎</a>";
|
||||
content = content + name;
|
||||
content = content + groupselect;
|
||||
content = content + "</div>";
|
||||
}
|
||||
|
||||
content = content + "</div>"
|
||||
}
|
||||
|
||||
// Pad then update page
|
||||
content = content + "<br><br>";
|
||||
document.getElementById('show').innerHTML = content;
|
||||
}
|
||||
|
||||
function setVolume(id, mute) {
|
||||
percent = document.getElementById('vol_' + id).value;
|
||||
percent_fine = document.getElementById('vol_fine_' + id).value;
|
||||
|
||||
// Take away 5 as it's the default of the fine slider. Only relevant if it
|
||||
// has changed
|
||||
percent = Number(percent) + Number(percent_fine) - 5;
|
||||
|
||||
if (percent < 0) {
|
||||
percent = 0
|
||||
}
|
||||
else if (percent > 100) {
|
||||
percent = 100
|
||||
}
|
||||
|
||||
// Request changes
|
||||
send('{"id":8,"jsonrpc":"2.0","method":"Client.SetVolume","params":{"id":"' + id + '","volume":{"muted":' + mute + ',"percent":' + percent + '}}}')
|
||||
|
||||
// Make updates to server info and refresh content
|
||||
for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
|
||||
for (let i_client = 0; i_client < server.server.groups[i_group].clients.length; i_client++) {
|
||||
var sv = server.server.groups[i_group].clients[i_client];
|
||||
if (sv.id == id) {
|
||||
if (mute == 'true') {
|
||||
sv.config.volume.muted = true;
|
||||
}
|
||||
if (mute == 'false') {
|
||||
sv.config.volume.muted = false;
|
||||
}
|
||||
sv.config.volume.percent = percent;
|
||||
}
|
||||
}
|
||||
}
|
||||
show()
|
||||
}
|
||||
|
||||
function setMuteGroup(id, what) {
|
||||
send('{"id":"MuteGroup_' + id + '","jsonrpc":"2.0","method":"Group.SetMute","params":{"id":"' + id + '","mute":' + what + '}}')
|
||||
|
||||
for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
|
||||
if (server.server.groups[i_group].id == id) {
|
||||
if (what == 'true') {
|
||||
server.server.groups[i_group].muted = true;
|
||||
}
|
||||
if (what == 'false') {
|
||||
server.server.groups[i_group].muted = false;
|
||||
}
|
||||
// console.log(server.server.groups[i_group]);
|
||||
}
|
||||
}
|
||||
show()
|
||||
}
|
||||
|
||||
function setStream(id) {
|
||||
send('{"id":4,"jsonrpc":"2.0","method":"Group.SetStream","params":{"id":"' + id + '","stream_id":"' + document.getElementById('stream_' + id).value + '"}}')
|
||||
|
||||
for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
|
||||
if (server.server.groups[i_group].id == id) {
|
||||
server.server.groups[i_group].stream_id = document.getElementById('stream_' + id).value;
|
||||
// console.log(server.server.groups[i_group]);
|
||||
}
|
||||
}
|
||||
show()
|
||||
}
|
||||
|
||||
function setGroup(id) {
|
||||
group = document.getElementById('group_' + id).value;
|
||||
|
||||
// Get client group id
|
||||
var current_group;
|
||||
groups:
|
||||
for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
|
||||
for (let i_client = 0; i_client < server.server.groups[i_group].clients.length; i_client++) {
|
||||
if (id == server.server.groups[i_group].clients[i_client].id) {
|
||||
current_group = server.server.groups[i_group].id;
|
||||
break groups;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get
|
||||
// List of target group's clients
|
||||
// OR
|
||||
// List of current group's other clients
|
||||
var send_clients = [];
|
||||
for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
|
||||
if (server.server.groups[i_group].id == group || (group == "new" && server.server.groups[i_group].id == current_group)) {
|
||||
for (let i_client = 0; i_client < server.server.groups[i_group].clients.length; i_client++) {
|
||||
if (group == "new" && server.server.groups[i_group].clients[i_client].id == id) { }
|
||||
else {
|
||||
send_clients[send_clients.length] = server.server.groups[i_group].clients[i_client].id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (group == "new") {
|
||||
group = current_group
|
||||
}
|
||||
else {
|
||||
send_clients[send_clients.length] = id;
|
||||
}
|
||||
|
||||
var send_clients_string = JSON.stringify(send_clients);
|
||||
send('{"id":1,"jsonrpc":"2.0","method":"Group.SetClients","params":{"clients":' + send_clients_string + ',"id":"' + group + '"}}')
|
||||
}
|
||||
|
||||
function setName(id) {
|
||||
// Get current name and lacency
|
||||
var current_name;
|
||||
var current_latency;
|
||||
groups:
|
||||
for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
|
||||
for (let i_client = 0; i_client < server.server.groups[i_group].clients.length; i_client++) {
|
||||
var sv = server.server.groups[i_group].clients[i_client];
|
||||
if (sv.id == id) {
|
||||
if (sv.config.name != "") {
|
||||
current_name = sv.config.name;
|
||||
} else {
|
||||
current_name = sv.host.name;
|
||||
}
|
||||
current_latency = sv.config.latency;
|
||||
break groups;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var newName = window.prompt("New Name", current_name);
|
||||
var newLatency = window.prompt("New Latency", current_latency);
|
||||
|
||||
// Don't change anything if user cancel's
|
||||
if (newName != null) {
|
||||
send('{"id":6,"jsonrpc":"2.0","method":"Client.SetName","params":{"id":"' + id + '","name":"' + newName + '"}}')
|
||||
} else {
|
||||
newName = current_name
|
||||
}
|
||||
if (newLatency != null) {
|
||||
send('{"id":7,"jsonrpc":"2.0","method":"Client.SetLatency","params":{"id":"' + id + '","latency":' + newLatency + '}}')
|
||||
} else {
|
||||
newLatency = current_latency
|
||||
}
|
||||
|
||||
for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
|
||||
for (let i_client = 0; i_client < server.server.groups[i_group].clients.length; i_client++) {
|
||||
var sv = server.server.groups[i_group].clients[i_client];
|
||||
if (sv.id == id) {
|
||||
sv.config.name = newName;
|
||||
sv.config.latency = newLatency;
|
||||
}
|
||||
}
|
||||
}
|
||||
show()
|
||||
}
|
||||
|
||||
</script>
|
||||
<style>
|
||||
body {
|
||||
background: #1f1f1f;
|
||||
color: rgb(255, 255, 255);
|
||||
font-family: 'Arial', sans-serif;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
/* width */
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
/* Track */
|
||||
::-webkit-scrollbar-track {
|
||||
background: #1f1f1f;
|
||||
}
|
||||
|
||||
/* Handle */
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #333;
|
||||
}
|
||||
|
||||
/* Handle on hover */
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #555;
|
||||
}
|
||||
|
||||
.group {
|
||||
float: none;
|
||||
clear: both;
|
||||
margin: 20px 15px 10px 15px;
|
||||
border: 2px solid #5f5f5f;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.groupmuted {
|
||||
float: none;
|
||||
clear: both;
|
||||
margin: 20px 15px 10px 15px;
|
||||
border: 2px solid #5f5f5f;
|
||||
overflow: auto;
|
||||
opacity: 0.27;
|
||||
}
|
||||
|
||||
.client {
|
||||
text-align: center;
|
||||
background: rgb(61, 61, 61);
|
||||
margin: 10px;
|
||||
width: 160px;
|
||||
height: 360px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.disconnected {
|
||||
text-align: center;
|
||||
background: rgb(61, 61, 61);
|
||||
margin: 10px;
|
||||
width: 160px;
|
||||
height: 360px;
|
||||
float: left;
|
||||
opacity: 0.27;
|
||||
}
|
||||
|
||||
.slider {
|
||||
writing-mode: bt-lr;
|
||||
/* IE */
|
||||
-webkit-appearance: slider-vertical;
|
||||
/* WebKit */
|
||||
height: 240px;
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
.slidermute {
|
||||
writing-mode: bt-lr;
|
||||
/* IE */
|
||||
-webkit-appearance: slider-vertical;
|
||||
/* WebKit */
|
||||
opacity: 0.27;
|
||||
height: 240px;
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
.slider_fine {
|
||||
writing-mode: bt-lr;
|
||||
/* IE */
|
||||
-webkit-appearance: slider-vertical;
|
||||
/* WebKit */
|
||||
height: 240px;
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
.slidermute_fine {
|
||||
writing-mode: bt-lr;
|
||||
/* IE */
|
||||
-webkit-appearance: slider-vertical;
|
||||
/* WebKit */
|
||||
height: 240px;
|
||||
width: 15px;
|
||||
opacity: 0.27;
|
||||
}
|
||||
|
||||
.sliders {
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
height: 250px;
|
||||
padding-top: 10px;
|
||||
clear: both;
|
||||
float: none;
|
||||
}
|
||||
|
||||
.sliderdiv {
|
||||
display: inline-block;
|
||||
padding-left: 40px;
|
||||
text-align: left;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.sliderdiv_fine {
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
width: 20px;
|
||||
position: relative;
|
||||
top: 0px;
|
||||
left: 13px;
|
||||
opacity: 0.01;
|
||||
}
|
||||
|
||||
.finebg {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
font-size: 35px;
|
||||
width: 40px;
|
||||
position: relative;
|
||||
top: -27px;
|
||||
left: 40px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
select {
|
||||
background-color: rgb(61, 61, 61);
|
||||
width: 150px;
|
||||
font-size: 20px;
|
||||
color: #e3e3e3;
|
||||
border: 1px solid #555555;
|
||||
-moz-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.stream {
|
||||
margin-left: 20px;
|
||||
width: 200px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.refreshbutton {
|
||||
background-color: rgb(61, 61, 61);
|
||||
font-size: 20px;
|
||||
color: #e3e3e3;
|
||||
border: 1px solid #555555;
|
||||
margin-left: 100px;
|
||||
}
|
||||
|
||||
.mutebutton {
|
||||
color: #e3e3e3;
|
||||
font-size: 30px;
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.mutebuttongroup {
|
||||
font-size: 30px;
|
||||
color: #e3e3e3;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.edit {
|
||||
color: #e3e3e3;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="show"></div>
|
||||
</body>
|
||||
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue