Merge branch 'develop' into packet

This commit is contained in:
Jakob Ketterl
2019-08-11 11:53:29 +02:00
47 changed files with 3106 additions and 1055 deletions

12
htdocs/css/features.css Normal file
View File

@ -0,0 +1,12 @@
@import url("openwebrx-header.css");
@import url("openwebrx-globals.css");
/* expandable photo not implemented on features page */
#webrx-top-photo-clip {
max-height: 67px;
}
h1 {
text-align: center;
margin: 50px 0;
}

57
htdocs/css/map.css Normal file
View File

@ -0,0 +1,57 @@
@import url("openwebrx-header.css");
@import url("openwebrx-globals.css");
/* expandable photo not implemented on map page */
#webrx-top-photo-clip {
max-height: 67px;
}
body {
display: flex;
flex-direction: column;
}
#webrx-top-container {
flex: none;
}
.openwebrx-map {
flex: 1 1 auto;
}
h3 {
margin: 10px 0;
text-align: center;
}
ul {
margin-block-start: 5px;
margin-block-end: 5px;
padding-inline-start: 25px;
}
.openwebrx-map-legend {
background-color: #fff;
padding: 10px;
margin: 10px;
}
.openwebrx-map-legend ul {
list-style-type: none;
padding: 0;
}
.openwebrx-map-legend li.square .illustration {
display: inline-block;
width: 30px;
height: 20px;
margin-right: 10px;
border-width: 2px;
border-style: solid;
}
.openwebrx-map-legend select {
background-color: #FFF;
border-color: #DDD;
padding: 5px;
}

View File

@ -0,0 +1,8 @@
html, body
{
margin: 0;
padding: 0;
height: 100%;
font-family: "DejaVu Sans", Verdana, Geneva, sans-serif;
}

View File

@ -0,0 +1,203 @@
#webrx-top-container
{
position: relative;
z-index:1000;
}
#webrx-top-photo
{
width: 100%;
display: block;
}
#webrx-top-photo-clip
{
min-height: 67px;
max-height: 350px;
overflow: hidden;
position: relative;
}
.webrx-top-bar-parts
{
height:67px;
}
#webrx-top-bar
{
background: rgba(128, 128, 128, 0.15);
margin:0;
padding:0;
user-select: none;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
overflow: hidden;
position: absolute;
left: 0;
top: 0;
right: 0;
}
#webrx-top-logo
{
padding: 12px;
float: left;
}
#webrx-ha5kfu-top-logo
{
float: right;
padding: 15px;
}
#webrx-rx-avatar-background
{
cursor:pointer;
background-image: url(../gfx/openwebrx-avatar-background.png);
background-origin: content-box;
background-repeat: no-repeat;
float: left;
width: 54px;
height: 54px;
padding: 7px;
box-sizing: content-box;
}
#webrx-rx-avatar
{
cursor:pointer;
width: 46px;
height: 46px;
padding: 4px;
border-radius: 8px;
box-sizing: content-box;
}
#webrx-rx-texts {
float: left;
padding: 10px;
}
#webrx-rx-texts div {
padding: 3px;
}
#webrx-rx-title
{
white-space:nowrap;
overflow: hidden;
cursor:pointer;
font-family: "DejaVu Sans", Verdana, Geneva, sans-serif;
color: #909090;
font-size: 11pt;
font-weight: bold;
}
#webrx-rx-desc
{
white-space:nowrap;
overflow: hidden;
cursor:pointer;
font-size: 10pt;
color: #909090;
}
#webrx-rx-desc a
{
color: #909090;
}
#openwebrx-rx-details-arrow
{
cursor:pointer;
position: absolute;
left: 470px;
top: 51px;
}
#openwebrx-rx-details-arrow a
{
margin: 0;
padding: 0;
}
#openwebrx-rx-details-arrow-down
{
display:none;
}
#openwebrx-main-buttons ul
{
display: table;
margin:0;
}
#openwebrx-main-buttons ul li
{
display: table-cell;
padding-left: 5px;
padding-right: 5px;
cursor:pointer;
}
#openwebrx-main-buttons a {
color: inherit;
text-decoration: inherit;
}
#openwebrx-main-buttons li:hover
{
background-color: rgba(255, 255, 255, 0.3);
}
#openwebrx-main-buttons li:active
{
background-color: rgba(255, 255, 255, 0.55);
}
#openwebrx-main-buttons
{
float: right;
margin:0;
color: white;
text-shadow: 0px 0px 4px #000000;
text-align: center;
font-size: 9pt;
font-weight: bold;
}
#webrx-rx-photo-title
{
position: absolute;
left: 15px;
top: 78px;
color: White;
font-size: 16pt;
text-shadow: 1px 1px 4px #444;
opacity: 1;
}
#webrx-rx-photo-desc
{
position: absolute;
left: 15px;
top: 109px;
color: White;
font-size: 10pt;
font-weight: bold;
text-shadow: 0px 0px 6px #444;
opacity: 1;
line-height: 1.5em;
}
#webrx-rx-photo-desc a
{
color: #5ca8ff;
text-shadow: none;
}

View File

@ -18,13 +18,10 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@import url("openwebrx-header.css");
@import url("openwebrx-globals.css");
html, body
{
margin: 0;
padding: 0;
height: 100%;
font-family: "DejaVu Sans", Verdana, Geneva, sans-serif;
html, body {
overflow: hidden;
}
@ -147,182 +144,16 @@ input[type=range]:focus::-ms-fill-upper
background: #B6B6B6;
}
#webrx-top-container
{
position: relative;
z-index:1000;
}
.webrx-top-bar-parts
{
height:67px;
}
#webrx-top-bar
{
background: rgba(128, 128, 128, 0.15);
margin:0;
padding:0;
user-select: none;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
overflow: hidden;
position: absolute;
left: 0;
top: 0;
right: 0;
}
#webrx-top-logo
{
padding: 12px;
float: left;
}
#webrx-ha5kfu-top-logo
{
float: right;
padding: 15px;
}
#webrx-top-photo
{
width: 100%;
display: block;
}
#webrx-rx-avatar-background
{
cursor:pointer;
background-image: url(gfx/openwebrx-avatar-background.png);
background-origin: content-box;
background-repeat: no-repeat;
float: left;
width: 54px;
height: 54px;
padding: 7px;
}
#webrx-rx-avatar
{
cursor:pointer;
width: 46px;
height: 46px;
padding: 4px;
}
#webrx-top-photo-clip
{
min-height: 67px;
max-height: 350px;
overflow: hidden;
position: relative;
}
#webrx-page-container
{
min-height:100%;
position:relative;
}
#webrx-rx-photo-title
{
position: absolute;
left: 15px;
top: 78px;
color: White;
font-size: 16pt;
text-shadow: 1px 1px 4px #444;
opacity: 1;
}
#webrx-rx-photo-desc
{
position: absolute;
left: 15px;
top: 109px;
color: White;
font-size: 10pt;
font-weight: bold;
text-shadow: 0px 0px 6px #444;
opacity: 1;
line-height: 1.5em;
}
#webrx-rx-photo-desc a
{
color: #5ca8ff;
text-shadow: none;
}
#webrx-rx-texts {
float: left;
padding: 10px;
}
#webrx-rx-texts div {
padding: 3px;
}
#webrx-rx-title
{
white-space:nowrap;
overflow: hidden;
cursor:pointer;
font-family: "DejaVu Sans", Verdana, Geneva, sans-serif;
color: #909090;
font-size: 11pt;
font-weight: bold;
}
#webrx-rx-desc
{
white-space:nowrap;
overflow: hidden;
cursor:pointer;
font-size: 10pt;
color: #909090;
}
#webrx-rx-desc a
{
color: #909090;
}
#openwebrx-rx-details-arrow
{
cursor:pointer;
position: absolute;
left: 470px;
top: 51px;
}
#openwebrx-rx-details-arrow a
{
margin: 0;
padding: 0;
}
#openwebrx-rx-details-arrow-down
{
display:none;
}
/*canvas#waterfall-canvas
{
border-style: none;
border-width: 1px;
height: 150px;
width: 100%;
}*/
#openwebrx-scale-container
{
height: 47px;
background-image: url("gfx/openwebrx-scale-background.png");
background-image: url("../gfx/openwebrx-scale-background.png");
background-repeat: repeat-x;
overflow: hidden;
z-index:1000;
@ -331,14 +162,14 @@ input[type=range]:focus::-ms-fill-upper
#webrx-canvas-container
{
/*background-image:url('gfx/openwebrx-blank-background-1.jpg');*/
/*background-image:url('../gfx/openwebrx-blank-background-1.jpg');*/
position: relative;
height: 2000px;
overflow-y: scroll;
overflow-x: hidden;
/*background-color: #646464;*/
/*background-image: -webkit-linear-gradient(top, rgba(247,247,247,1) 0%, rgba(0,0,0,1) 100%);*/
background-image: url('gfx/openwebrx-background-cool-blue.png');
background-image: url('../gfx/openwebrx-background-cool-blue.png');
background-repeat: no-repeat;
background-color: #1e5f7f;
cursor: crosshair;
@ -428,15 +259,15 @@ input[type=range]:focus::-ms-fill-upper
/* removed non-free fonts like that: */
/*@font-face {
font-family: 'unibody_8_pro_regregular';
src: url('gfx/unibody8pro-regular-webfont.eot');
src: url('gfx/unibody8pro-regular-webfont.ttf');
src: url('../gfx/unibody8pro-regular-webfont.eot');
src: url('../gfx/unibody8pro-regular-webfont.ttf');
font-weight: normal;
font-style: normal;
}*/
@font-face {
font-family: 'expletus-sans-medium';
src: url('gfx/font-expletus-sans/ExpletusSans-Medium.ttf');
src: url('../gfx/font-expletus-sans/ExpletusSans-Medium.ttf');
font-weight: normal;
font-style: normal;
}
@ -533,6 +364,20 @@ input[type=range]:focus::-ms-fill-upper
text-align: center;
}
.openwebrx-dial-button svg {
width: 19px;
height: 19px;
vertical-align: bottom;
}
.openwebrx-dial-button #ph_dial {
fill: #888;
}
.openwebrx-dial-button.available #ph_dial {
fill: #FFF;
}
.openwebrx-square-button img
{
height: 27px;
@ -637,47 +482,6 @@ img.openwebrx-mirror-img
height: 20px;
}
#openwebrx-main-buttons img
{
}
#openwebrx-main-buttons ul
{
display: table;
margin:0;
}
#openwebrx-main-buttons ul li
{
display: table-cell;
padding-left: 5px;
padding-right: 5px;
cursor:pointer;
}
#openwebrx-main-buttons li:hover
{
background-color: rgba(255, 255, 255, 0.3);
}
#openwebrx-main-buttons li:active
{
background-color: rgba(255, 255, 255, 0.55);
}
#openwebrx-main-buttons
{
float: right;
margin:0;
color: white;
text-shadow: 0px 0px 4px #000000;
text-align: center;
font-size: 9pt;
font-weight: bold;
}
#openwebrx-panel-receiver
{
width:110px;
@ -812,7 +616,7 @@ img.openwebrx-mirror-img
#openwebrx-secondary-demod-listbox
{
width: 201px;
width: 174px;
height: 27px;
padding-left:3px;
}
@ -951,7 +755,7 @@ img.openwebrx-mirror-img
.openwebrx-meta-slot.muted:before {
display: block;
content: "";
background-image: url("gfx/openwebrx-mute.png");
background-image: url("../gfx/openwebrx-mute.png");
width:100%;
height:133px;
background-position: center;
@ -993,11 +797,11 @@ img.openwebrx-mirror-img
}
.openwebrx-meta-slot.active .openwebrx-meta-user-image {
background-image: url("gfx/openwebrx-directcall.png");
background-image: url("../gfx/openwebrx-directcall.png");
}
.openwebrx-meta-slot.active .openwebrx-meta-user-image.group {
background-image: url("gfx/openwebrx-groupcall.png");
background-image: url("../gfx/openwebrx-groupcall.png");
}
.openwebrx-dmr-timeslot-panel * {
@ -1005,7 +809,7 @@ img.openwebrx-mirror-img
}
.openwebrx-maps-pin {
background-image: url("gfx/google_maps_pin.svg");
background-image: url("../gfx/google_maps_pin.svg");
background-position: center;
background-repeat: no-repeat;
width: 15px;
@ -1013,3 +817,62 @@ img.openwebrx-mirror-img
background-size: contain;
display: inline-block;
}
#openwebrx-panel-wsjt-message {
height: 180px;
}
#openwebrx-panel-wsjt-message tbody {
display: block;
overflow: auto;
height: 150px;
width: 100%;
}
#openwebrx-panel-wsjt-message thead tr {
display: block;
}
#openwebrx-panel-wsjt-message th,
#openwebrx-panel-wsjt-message td {
width: 50px;
text-align: left;
padding: 1px 3px;
}
#openwebrx-panel-wsjt-message .message {
width: 380px;
}
#openwebrx-panel-wsjt-message .decimal {
text-align: right;
width: 35px;
}
#openwebrx-panel-wsjt-message .decimal.freq {
width: 70px;
}
#openwebrx-panel-digimodes[data-mode="ft8"] #openwebrx-digimode-content-container,
#openwebrx-panel-digimodes[data-mode="wspr"] #openwebrx-digimode-content-container,
#openwebrx-panel-digimodes[data-mode="jt65"] #openwebrx-digimode-content-container,
#openwebrx-panel-digimodes[data-mode="jt9"] #openwebrx-digimode-content-container,
#openwebrx-panel-digimodes[data-mode="ft4"] #openwebrx-digimode-content-container,
#openwebrx-panel-digimodes[data-mode="ft8"] #openwebrx-digimode-select-channel,
#openwebrx-panel-digimodes[data-mode="wspr"] #openwebrx-digimode-select-channel,
#openwebrx-panel-digimodes[data-mode="jt65"] #openwebrx-digimode-select-channel,
#openwebrx-panel-digimodes[data-mode="jt9"] #openwebrx-digimode-select-channel,
#openwebrx-panel-digimodes[data-mode="ft4"] #openwebrx-digimode-select-channel
{
display: none;
}
#openwebrx-panel-digimodes[data-mode="ft8"] #openwebrx-digimode-canvas-container,
#openwebrx-panel-digimodes[data-mode="wspr"] #openwebrx-digimode-canvas-container,
#openwebrx-panel-digimodes[data-mode="jt65"] #openwebrx-digimode-canvas-container,
#openwebrx-panel-digimodes[data-mode="jt9"] #openwebrx-digimode-canvas-container,
#openwebrx-panel-digimodes[data-mode="ft4"] #openwebrx-digimode-canvas-container
{
height: 200px;
margin: -10px;
}

21
htdocs/features.html Normal file
View File

@ -0,0 +1,21 @@
<HTML><HEAD>
<TITLE>OpenWebRX Feature report</TITLE>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="stylesheet" href="static/css/features.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/showdown/1.9.0/showdown.min.js"></script>
<script src="static/lib/jquery-3.2.1.min.js"></script>
<script src="static/features.js"></script>
</HEAD><BODY>
${header}
<div class="container">
<h1>OpenWebRX Feature Report</h1>
<table class="features table">
<tr>
<th>Feature</th>
<th>Requirement</th>
<th>Description</th>
<th>Available</th>
</tr>
</table>
</div>
</BODY></HTML>

24
htdocs/features.js Normal file
View File

@ -0,0 +1,24 @@
$(function(){
var converter = new showdown.Converter();
$.ajax('/api/features').done(function(data){
var $table = $('table.features');
$.each(data, function(name, details) {
var requirements = $.map(details.requirements, function(r, name){
return '<tr>' +
'<td></td>' +
'<td>' + name + '</td>' +
'<td>' + converter.makeHtml(r.description) + '</td>' +
'<td>' + (r.available ? 'YES' : 'NO') + '</td>' +
'</tr>';
});
$table.append(
'<tr>' +
'<td colspan=2>' + name + '</td>' +
'<td>' + converter.makeHtml(details.description) + '</td>' +
'<td>' + (details.available ? 'YES' : 'NO') + '</td>' +
'</tr>' +
requirements.join("")
);
})
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View File

@ -1,85 +0,0 @@
<html>
<!--
This file is part of OpenWebRX,
an open-source SDR receiver software with a web UI.
Copyright (c) 2013-2015 by Andras Retzler <randras@sdr.hu>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<head><title>OpenWebRX</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style>
html, body
{
font-family: "DejaVu Sans", Verdana, Geneva, sans-serif;
width: 100%;
text-align: center;
margin: 0;
padding: 0;
}
img.logo
{
margin-top: 120px;
}
div.frame
{
text-align: left;
margin:0px auto;
width: 800px;
}
div.panel
{
text-align: center;
background-color:#777777;
border-radius: 15px;
padding: 12px;
font-weight: bold;
color: White;
font-size: 13pt;
/*text-shadow: 1px 1px 4px #444;*/
font-family: sans;
}
div.alt
{
font-size: 10pt;
padding-top: 10px;
}
body div a
{
color: #5ca8ff;
text-shadow: none;
}
span.browser
{
}
</style>
</head>
<body>
<div class="frame">
<img class="logo" src="gfx/openwebrx-logo-big.png" style="height: 60px;"/>
<div class="panel">
Sorry, the receiver is inactive due to internal error.
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,30 @@
<div id="webrx-top-container">
<div id="webrx-top-photo-clip">
<img src="static/gfx/openwebrx-top-photo.jpg" id="webrx-top-photo"/>
<div id="webrx-top-bar" class="webrx-top-bar-parts">
<a href="https://sdr.hu/openwebrx" target="_blank"><img src="static/gfx/openwebrx-top-logo.png" id="webrx-top-logo" /></a>
<a href="http://ha5kfu.sch.bme.hu/" target="_blank"><img src="static/gfx/openwebrx-ha5kfu-top-logo.png" id="webrx-ha5kfu-top-logo" /></a>
<div id="webrx-rx-avatar-background">
<img id="webrx-rx-avatar" class="openwebrx-photo-trigger" src="static/gfx/openwebrx-avatar.png"/>
</div>
<div id="webrx-rx-texts">
<div id="webrx-rx-title" class="openwebrx-photo-trigger"></div>
<div id="webrx-rx-desc" class="openwebrx-photo-trigger"></div>
</div>
<div id="openwebrx-rx-details-arrow">
<a id="openwebrx-rx-details-arrow-up" class="openwebrx-photo-trigger"><img src="static/gfx/openwebrx-rx-details-arrow-up.png" /></a>
<a id="openwebrx-rx-details-arrow-down" class="openwebrx-photo-trigger"><img src="static/gfx/openwebrx-rx-details-arrow.png" /></a>
</div>
<section id="openwebrx-main-buttons">
<ul>
<li data-toggle-panel="openwebrx-panel-status"><img src="static/gfx/openwebrx-panel-status.png" /><br/>Status</li>
<li data-toggle-panel="openwebrx-panel-log"><img src="static/gfx/openwebrx-panel-log.png" /><br/>Log</li>
<li data-toggle-panel="openwebrx-panel-receiver"><img src="static/gfx/openwebrx-panel-receiver.png" /><br/>Receiver</li>
<li><a href="/map" target="_blank"><img src="static/gfx/openwebrx-panel-map.png" /><br/>Map</a></li>
</ul>
</section>
</div>
<div id="webrx-rx-photo-title"></div>
<div id="webrx-rx-photo-desc"></div>
</div>
</div>

View File

@ -25,43 +25,15 @@
<script src="static/sdr.js"></script>
<script src="static/mathbox-bundle.min.js"></script>
<script src="static/openwebrx.js"></script>
<script src="static/jquery-3.2.1.min.js"></script>
<script src="static/jquery.nanoscroller.js"></script>
<link rel="stylesheet" type="text/css" href="static/nanoscroller.css" />
<link rel="stylesheet" type="text/css" href="static/openwebrx.css" />
<script src="static/lib/jquery-3.2.1.min.js"></script>
<script src="static/lib/jquery.nanoscroller.js"></script>
<link rel="stylesheet" type="text/css" href="static/lib/nanoscroller.css" />
<link rel="stylesheet" type="text/css" href="static/css/openwebrx.css" />
<meta charset="utf-8">
</head>
<body onload="openwebrx_init();">
<div id="webrx-page-container">
<div id="webrx-top-container">
<div id="webrx-top-photo-clip">
<img src="static/gfx/openwebrx-top-photo.jpg" id="webrx-top-photo"/>
<div id="webrx-top-bar" class="webrx-top-bar-parts">
<a href="https://sdr.hu/openwebrx" target="_blank"><img src="static/gfx/openwebrx-top-logo.png" id="webrx-top-logo" /></a>
<a href="http://ha5kfu.sch.bme.hu/" target="_blank"><img src="static/gfx/openwebrx-ha5kfu-top-logo.png" id="webrx-ha5kfu-top-logo" /></a>
<div id="webrx-rx-avatar-background">
<img id="webrx-rx-avatar" src="static/gfx/openwebrx-avatar.png" onclick="toggle_rx_photo();"/>
</div>
<div id="webrx-rx-texts">
<div id="webrx-rx-title" onclick="toggle_rx_photo();"></div>
<div id="webrx-rx-desc" onclick="toggle_rx_photo();"></div>
</div>
<div id="openwebrx-rx-details-arrow">
<a id="openwebrx-rx-details-arrow-up" onclick="toggle_rx_photo();"><img src="static/gfx/openwebrx-rx-details-arrow-up.png" /></a>
<a id="openwebrx-rx-details-arrow-down" onclick="toggle_rx_photo();"><img src="static/gfx/openwebrx-rx-details-arrow.png" /></a>
</div>
<section id="openwebrx-main-buttons">
<ul>
<li onmouseup="toggle_panel('openwebrx-panel-status');"><img src="static/gfx/openwebrx-panel-status.png" /><br/>Status</li>
<li onmouseup="toggle_panel('openwebrx-panel-log');"><img src="static/gfx/openwebrx-panel-log.png" /><br/>Log</li>
<li onmouseup="toggle_panel('openwebrx-panel-receiver');"><img src="static/gfx/openwebrx-panel-receiver.png" /><br/>Receiver</li>
</ul>
</section>
</div>
<div id="webrx-rx-photo-title"></div>
<div id="webrx-rx-photo-desc"></div>
</div>
</div>
${header}
<div id="webrx-main-container">
<div id="openwebrx-scale-container">
<canvas id="openwebrx-scale-canvas" width="0" height="0"></canvas>
@ -111,7 +83,19 @@
<select id="openwebrx-secondary-demod-listbox" onchange="secondary_demod_listbox_changed();">
<option value="none"></option>
<option value="bpsk31">BPSK31</option>
<option value="ft8" data-feature="wsjt-x">FT8</option>
<option value="wspr" data-feature="wsjt-x">WSPR</option>
<option value="jt65" data-feature="wsjt-x">JT65</option>
<option value="jt9" data-feature="wsjt-x">JT9</option>
<option value="ft4" data-feature="wsjt-x">FT4</option>
</select>
<div id="openwebrx-secondary-demod-dial-button" class="openwebrx-button openwebrx-dial-button" onclick="dial_button_click();">
<svg version="1.1" id="Layer_1" x="0px" y="0px" width="246px" height="246px" viewBox="0 0 246 246" xmlns="http://www.w3.org/2000/svg">
<g id="ph_dial_1_" transform="matrix(1, 0, 0, 1, -45.398312, -50.931698)">
<path id="ph_dial" d="M238.875,190.125c3.853,7.148,34.267,4.219,50.242,2.145c0.891-5.977,1.508-12.043,1.508-18.27 c0-67.723-54.901-122.625-122.625-122.625c-67.723,0-122.625,54.902-122.625,122.625c0,67.723,54.902,122.625,122.625,122.625 c51.06,0,94.797-31.227,113.25-75.609c-13.969-9.668-41.625-18.891-41.625-18.891c-5.25,0-10.5-3-12.75-8.25 S233.625,180.375,238.875,190.125z M220.465,175.313c0,28.478-23.086,51.563-51.563,51.563c-28.478,0-51.563-23.086-51.563-51.563 c0-28.477,23.086-51.563,51.563-51.563C197.379,123.75,220.465,146.836,220.465,175.313z M185.25,64.125 c10.563,0,19.125,8.563,19.125,19.125s-8.563,19.125-19.125,19.125c-10.562,0-19.125-8.563-19.125-19.125 S174.688,64.125,185.25,64.125z M142.875,69C153.438,69,162,77.563,162,88.125s-8.563,19.125-19.125,19.125 c-10.562,0-19.125-8.563-19.125-19.125S132.313,69,142.875,69z M106.5,91.875c10.563,0,19.125,8.563,19.125,19.125 s-8.563,19.125-19.125,19.125c-10.562,0-19.125-8.562-19.125-19.125S95.938,91.875,106.5,91.875z M81.375,126.75 c10.563,0,19.125,8.563,19.125,19.125S91.938,165,81.375,165c-10.563,0-19.125-8.563-19.125-19.125S70.813,126.75,81.375,126.75z M58.125,188.625c0-10.559,8.563-19.125,19.125-19.125c10.563,0,19.125,8.566,19.125,19.125S87.813,207.75,77.25,207.75 C66.687,207.75,58.125,199.184,58.125,188.625z M75.75,229.875c0-10.559,8.563-19.125,19.125-19.125 c10.563,0,19.125,8.566,19.125,19.125S105.438,249,94.875,249C84.312,249,75.75,240.434,75.75,229.875z M126.375,276 c-10.563,0-19.125-8.566-19.125-19.125s8.563-19.125,19.125-19.125c10.563,0,19.125,8.566,19.125,19.125S136.938,276,126.375,276z M168,288c-10.563,0-19.125-8.566-19.125-19.125S157.438,249.75,168,249.75c10.563,0,19.125,8.566,19.125,19.125 S178.563,288,168,288z M210.375,276c-10.563,0-19.125-8.566-19.125-19.125s8.563-19.125,19.125-19.125 c10.563,0,19.125,8.566,19.125,19.125S220.938,276,210.375,276z M243.375,210.75c10.563,0,19.125,8.566,19.125,19.125 S253.938,249,243.375,249c-10.563,0-19.125-8.566-19.125-19.125S232.813,210.75,243.375,210.75z"/>
</g>
</svg>
</div>
</div>
<div class="openwebrx-panel-line">
<div title="Mute on/off" id="openwebrx-mute-off" class="openwebrx-button" onclick="toggleMute();"><img src="static/gfx/openwebrx-speaker.png" class="openwebrx-sliderbtn-img" id="openwebrx-mute-img"></div>
@ -160,7 +144,7 @@
<span style="font-size: 15pt; font-weight: bold;">Under construction</span>
<br />We're working on the code right now, so the application might fail.
</div>
<div class="openwebrx-panel" id="openwebrx-panel-digimodes" data-panel-name="digimodes" data-panel-pos="left" data-panel-order="2" data-panel-size="619,210">
<div class="openwebrx-panel" id="openwebrx-panel-digimodes" data-panel-name="digimodes" data-panel-pos="left" data-panel-order="3" data-panel-size="619,210">
<div id="openwebrx-digimode-canvas-container">
<div id="openwebrx-digimode-select-channel"></div>
</div>
@ -171,6 +155,16 @@
</div>
</div>
</div>
<table class="openwebrx-panel" id="openwebrx-panel-wsjt-message" data-panel-name="wsjt-message" data-panel-pos="left" data-panel-order="2" data-panel-size="619,200">
<thead><tr>
<th>UTC</th>
<th class="decimal">dB</th>
<th class="decimal">DT</th>
<th class="decimal freq">Freq</th>
<th class="message">Message</th>
</tr></thead>
<tbody></tbody>
</table>
<div class="openwebrx-panel openwebrx-meta-panel" id="openwebrx-panel-metadata-ysf" data-panel-name="metadata-ysf" data-panel-pos="left" data-panel-order="2" data-panel-size="145,220">
<div class="openwebrx-meta-frame">
<div class="openwebrx-meta-slot">

58
htdocs/lib/chroma.min.js vendored Normal file

File diff suppressed because one or more lines are too long

143
htdocs/lib/nite-overlay.js Normal file
View File

@ -0,0 +1,143 @@
/* Nite v1.7
* A tiny library to create a night overlay over the map
* Author: Rossen Georgiev @ https://github.com/rossengeorgiev
* Requires: GMaps API 3
*/
var nite = {
map: null,
date: null,
sun_position: null,
earth_radius_meters: 6371008,
marker_twilight_civil: null,
marker_twilight_nautical: null,
marker_twilight_astronomical: null,
marker_night: null,
init: function(map) {
if(typeof google === 'undefined'
|| typeof google.maps === 'undefined') throw "Nite Overlay: no google.maps detected";
this.map = map;
this.sun_position = this.calculatePositionOfSun();
this.marker_twilight_civil = new google.maps.Circle({
map: this.map,
center: this.getShadowPosition(),
radius: this.getShadowRadiusFromAngle(0.566666),
fillColor: "#000",
fillOpacity: 0.1,
strokeOpacity: 0,
clickable: false,
editable: false
});
this.marker_twilight_nautical = new google.maps.Circle({
map: this.map,
center: this.getShadowPosition(),
radius: this.getShadowRadiusFromAngle(6),
fillColor: "#000",
fillOpacity: 0.1,
strokeOpacity: 0,
clickable: false,
editable: false
});
this.marker_twilight_astronomical = new google.maps.Circle({
map: this.map,
center: this.getShadowPosition(),
radius: this.getShadowRadiusFromAngle(12),
fillColor: "#000",
fillOpacity: 0.1,
strokeOpacity: 0,
clickable: false,
editable: false
});
this.marker_night = new google.maps.Circle({
map: this.map,
center: this.getShadowPosition(),
radius: this.getShadowRadiusFromAngle(18),
fillColor: "#000",
fillOpacity: 0.1,
strokeOpacity: 0,
clickable: false,
editable: false
});
},
getShadowRadiusFromAngle: function(angle) {
var shadow_radius = this.earth_radius_meters * Math.PI * 0.5;
var twilight_dist = ((this.earth_radius_meters * 2 * Math.PI) / 360) * angle;
return shadow_radius - twilight_dist;
},
getSunPosition: function() {
return this.sun_position;
},
getShadowPosition: function() {
return (this.sun_position) ? new google.maps.LatLng(-this.sun_position.lat(), this.sun_position.lng() + 180) : null;
},
refresh: function() {
if(!this.isVisible()) return;
this.sun_position = this.calculatePositionOfSun(this.date);
var shadow_position = this.getShadowPosition();
this.marker_twilight_civil.setCenter(shadow_position);
this.marker_twilight_nautical.setCenter(shadow_position);
this.marker_twilight_astronomical.setCenter(shadow_position);
this.marker_night.setCenter(shadow_position);
},
jday: function(date) {
return (date.getTime() / 86400000.0) + 2440587.5;
},
calculatePositionOfSun: function(date) {
date = (date instanceof Date) ? date : new Date();
var rad = 0.017453292519943295;
// based on NOAA solar calculations
var ms_past_midnight = ((date.getUTCHours() * 60 + date.getUTCMinutes()) * 60 + date.getUTCSeconds()) * 1000 + date.getUTCMilliseconds();
var jc = (this.jday(date) - 2451545)/36525;
var mean_long_sun = (280.46646+jc*(36000.76983+jc*0.0003032)) % 360;
var mean_anom_sun = 357.52911+jc*(35999.05029-0.0001537*jc);
var sun_eq = Math.sin(rad*mean_anom_sun)*(1.914602-jc*(0.004817+0.000014*jc))+Math.sin(rad*2*mean_anom_sun)*(0.019993-0.000101*jc)+Math.sin(rad*3*mean_anom_sun)*0.000289;
var sun_true_long = mean_long_sun + sun_eq;
var sun_app_long = sun_true_long - 0.00569 - 0.00478*Math.sin(rad*125.04-1934.136*jc);
var mean_obliq_ecliptic = 23+(26+((21.448-jc*(46.815+jc*(0.00059-jc*0.001813))))/60)/60;
var obliq_corr = mean_obliq_ecliptic + 0.00256*Math.cos(rad*125.04-1934.136*jc);
var lat = Math.asin(Math.sin(rad*obliq_corr)*Math.sin(rad*sun_app_long)) / rad;
var eccent = 0.016708634-jc*(0.000042037+0.0000001267*jc);
var y = Math.tan(rad*(obliq_corr/2))*Math.tan(rad*(obliq_corr/2));
var rq_of_time = 4*((y*Math.sin(2*rad*mean_long_sun)-2*eccent*Math.sin(rad*mean_anom_sun)+4*eccent*y*Math.sin(rad*mean_anom_sun)*Math.cos(2*rad*mean_long_sun)-0.5*y*y*Math.sin(4*rad*mean_long_sun)-1.25*eccent*eccent*Math.sin(2*rad*mean_anom_sun))/rad);
var true_solar_time_in_deg = ((ms_past_midnight+rq_of_time*60000) % 86400000) / 240000;
var lng = -((true_solar_time_in_deg < 0) ? true_solar_time_in_deg + 180 : true_solar_time_in_deg - 180);
return new google.maps.LatLng(lat, lng);
},
setDate: function(date) {
this.date = date;
this.refresh();
},
setMap: function(map) {
this.map = map;
this.marker_twilight_civil.setMap(this.map);
this.marker_twilight_nautical.setMap(this.map);
this.marker_twilight_astronomical.setMap(this.map);
this.marker_night.setMap(this.map);
},
show: function() {
this.marker_twilight_civil.setVisible(true);
this.marker_twilight_nautical.setVisible(true);
this.marker_twilight_astronomical.setVisible(true);
this.marker_night.setVisible(true);
this.refresh();
},
hide: function() {
this.marker_twilight_civil.setVisible(false);
this.marker_twilight_nautical.setVisible(false);
this.marker_twilight_astronomical.setVisible(false);
this.marker_night.setVisible(false);
},
isVisible: function() {
return this.marker_night.getVisible();
}
}

24
htdocs/map.html Normal file
View File

@ -0,0 +1,24 @@
<!DOCTYPE HTML>
<html>
<head>
<title>OpenWebRX Map</title>
<script src="static/lib/jquery-3.2.1.min.js"></script>
<script src="static/lib/chroma.min.js"></script>
<script src="static/map.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<link rel="stylesheet" type="text/css" href="static/css/map.css" />
<meta charset="utf-8">
</head>
<body>
${header}
<div class="openwebrx-map"></div>
<div class="openwebrx-map-legend">
<h3>Colors</h3>
<select id="openwebrx-map-colormode">
<option value="byband" selected="selected">By Band</option>
<option value="bymode">By Mode</option>
</select>
<div class="content"></div>
</div>
</body>
</html>

340
htdocs/map.js Normal file
View File

@ -0,0 +1,340 @@
(function(){
var protocol = 'ws';
if (window.location.toString().startsWith('https://')) {
protocol = 'wss';
}
var query = window.location.search.replace(/^\?/, '').split('&').map(function(v){
var s = v.split('=');
var r = {};
r[s[0]] = s.slice(1).join('=');
return r;
}).reduce(function(a, b){
return a.assign(b);
});
var expectedCallsign;
if (query.callsign) expectedCallsign = query.callsign;
var expectedLocator;
if (query.locator) expectedLocator = query.locator;
var ws_url = protocol + "://" + (window.location.origin.split("://")[1]) + "/ws/";
if (!("WebSocket" in window)) return;
var map;
var markers = {};
var rectangles = {};
var updateQueue = [];
// reasonable default; will be overriden by server
var retention_time = 2 * 60 * 60 * 1000;
var strokeOpacity = 0.8;
var fillOpacity = 0.35;
var colorKeys = {};
var colorScale = chroma.scale(['red', 'blue', 'green']).mode('hsl');
var getColor = function(id){
if (!id) return "#000000";
if (!colorKeys[id]) {
var keys = Object.keys(colorKeys);
keys.push(id);
keys.sort();
var colors = colorScale.colors(keys.length);
colorKeys = {};
keys.forEach(function(key, index) {
colorKeys[key] = colors[index];
});
reColor();
updateLegend();
}
return colorKeys[id];
}
// when the color palette changes, update all grid squares with new color
var reColor = function() {
$.each(rectangles, function(_, r) {
var color = getColor(colorAccessor(r));
r.setOptions({
strokeColor: color,
fillColor: color
});
});
}
var colorMode = 'byband';
var colorAccessor = function(r) {
switch (colorMode) {
case 'byband':
return r.band;
case 'bymode':
return r.mode;
}
};
$(function(){
$('#openwebrx-map-colormode').on('change', function(){
colorMode = $(this).val();
colorKeys = {};
reColor();
updateLegend();
});
});
var updateLegend = function() {
var lis = $.map(colorKeys, function(value, key) {
return '<li class="square"><span class="illustration" style="background-color:' + chroma(value).alpha(fillOpacity) + ';border-color:' + chroma(value).alpha(strokeOpacity) + ';"></span>' + key + '</li>';
});
$(".openwebrx-map-legend .content").html('<ul>' + lis.join('') + '</ul>');
}
var processUpdates = function(updates) {
if (!map) {
updateQueue = updateQueue.concat(updates);
return;
}
updates.forEach(function(update){
switch (update.location.type) {
case 'latlon':
var pos = new google.maps.LatLng(update.location.lat, update.location.lon);
var marker;
if (markers[update.callsign]) {
marker = markers[update.callsign];
} else {
marker = new google.maps.Marker();
marker.addListener('click', function(){
showMarkerInfoWindow(update.callsign, pos);
});
markers[update.callsign] = marker;
}
marker.setOptions($.extend({
position: pos,
map: map,
title: update.callsign
}, getMarkerOpacityOptions(update.lastseen) ));
marker.lastseen = update.lastseen;
marker.mode = update.mode;
marker.band = update.band;
// TODO the trim should happen on the server side
if (expectedCallsign && expectedCallsign == update.callsign.trim()) {
map.panTo(pos);
showMarkerInfoWindow(update.callsign, pos);
delete(expectedCallsign);
}
break;
case 'locator':
var loc = update.location.locator;
var lat = (loc.charCodeAt(1) - 65 - 9) * 10 + Number(loc[3]);
var lon = (loc.charCodeAt(0) - 65 - 9) * 20 + Number(loc[2]) * 2;
var center = new google.maps.LatLng({lat: lat + .5, lng: lon + 1});
var rectangle;
// the accessor is designed to work on the rectangle... but it should work on the update object, too
var color = getColor(colorAccessor(update));
if (rectangles[update.callsign]) {
rectangle = rectangles[update.callsign];
} else {
rectangle = new google.maps.Rectangle();
rectangle.addListener('click', function(){
showLocatorInfoWindow(this.locator, this.center);
});
rectangles[update.callsign] = rectangle;
}
rectangle.setOptions($.extend({
strokeColor: color,
strokeWeight: 2,
fillColor: color,
map: map,
bounds:{
north: lat,
south: lat + 1,
west: lon,
east: lon + 2
}
}, getRectangleOpacityOptions(update.lastseen) ));
rectangle.lastseen = update.lastseen;
rectangle.locator = update.location.locator;
rectangle.mode = update.mode;
rectangle.band = update.band;
rectangle.center = center;
if (expectedLocator && expectedLocator == update.location.locator) {
map.panTo(center);
showLocatorInfoWindow(expectedLocator, center);
delete(expectedLocator);
}
break;
}
});
};
var clearMap = function(){
var reset = function(callsign, item) { item.setMap(); };
$.each(markers, reset);
$.each(rectangles, reset);
markers = {};
rectangles = {};
};
var reconnect_timeout = false;
var connect = function(){
var ws = new WebSocket(ws_url);
ws.onopen = function(){
ws.send("SERVER DE CLIENT client=map.js type=map");
reconnect_timeout = false
};
ws.onmessage = function(e){
if (typeof e.data != 'string') {
console.error("unsupported binary data on websocket; ignoring");
return
}
if (e.data.substr(0, 16) == "CLIENT DE SERVER") {
console.log("Server acknowledged WebSocket connection.");
return
}
try {
var json = JSON.parse(e.data);
switch (json.type) {
case "config":
var config = json.value;
if (!map) $.getScript("https://maps.googleapis.com/maps/api/js?key=" + config.google_maps_api_key).done(function(){
map = new google.maps.Map($('.openwebrx-map')[0], {
center: {
lat: config.receiver_gps[0],
lng: config.receiver_gps[1]
},
zoom: 5
});
processUpdates(updateQueue);
updateQueue = [];
$.getScript("/static/lib/nite-overlay.js").done(function(){
nite.init(map);
setInterval(function() { nite.refresh() }, 10000); // every 10s
});
map.controls[google.maps.ControlPosition.LEFT_BOTTOM].push($(".openwebrx-map-legend")[0]);
});
retention_time = config.map_position_retention_time * 1000;
break;
case "update":
processUpdates(json.value);
break;
}
} catch (e) {
// don't lose exception
console.error(e);
}
};
ws.onclose = function(){
clearMap();
if (reconnect_timeout) {
// max value: roundabout 8 and a half minutes
reconnect_timeout = Math.min(reconnect_timeout * 2, 512000);
} else {
// initial value: 1s
reconnect_timeout = 1000;
}
setTimeout(connect, reconnect_timeout);
};
window.onbeforeunload = function() { //http://stackoverflow.com/questions/4812686/closing-websocket-correctly-html5-javascript
ws.onclose = function () {};
ws.close();
};
/*
ws.onerror = function(){
console.info("websocket error");
};
*/
};
connect();
var infowindow;
var showLocatorInfoWindow = function(locator, pos) {
if (!infowindow) infowindow = new google.maps.InfoWindow();
var inLocator = $.map(rectangles, function(r, callsign) {
return {callsign: callsign, locator: r.locator, lastseen: r.lastseen, mode: r.mode, band: r.band}
}).filter(function(d) {
return d.locator == locator;
}).sort(function(a, b){
return b.lastseen - a.lastseen;
});
infowindow.setContent(
'<h3>Locator: ' + locator + '</h3>' +
'<div>Active Callsigns:</div>' +
'<ul>' +
inLocator.map(function(i){
var timestring = moment(i.lastseen).fromNow();
var message = i.callsign + ' (' + timestring + ' using ' + i.mode;
if (i.band) message += ' on ' + i.band;
message += ')';
return '<li>' + message + '</li>'
}).join("") +
'</ul>'
);
infowindow.setPosition(pos);
infowindow.open(map);
};
var showMarkerInfoWindow = function(callsign, pos) {
if (!infowindow) infowindow = new google.maps.InfoWindow();
var marker = markers[callsign];
var timestring = moment(marker.lastseen).fromNow();
infowindow.setContent(
'<h3>' + callsign + '</h3>' +
'<div>' + timestring + ' using ' + marker.mode + '</div>'
);
infowindow.open(map, marker);
}
var getScale = function(lastseen) {
var age = new Date().getTime() - lastseen;
var scale = 1;
if (age >= retention_time / 2) {
scale = (retention_time - age) / (retention_time / 2);
}
return Math.max(0, Math.min(1, scale));
};
var getRectangleOpacityOptions = function(lastseen) {
var scale = getScale(lastseen);
return {
strokeOpacity: strokeOpacity * scale,
fillOpacity: fillOpacity * scale
};
};
var getMarkerOpacityOptions = function(lastseen) {
var scale = getScale(lastseen);
return {
opacity: scale
};
};
// fade out / remove positions after time
setInterval(function(){
var now = new Date().getTime();
$.each(rectangles, function(callsign, m) {
var age = now - m.lastseen;
if (age > retention_time) {
delete rectangles[callsign];
m.setMap();
return;
}
m.setOptions(getRectangleOpacityOptions(m.lastseen));
});
$.each(markers, function(callsign, m) {
var age = now - m.lastseen;
if (age > retention_time) {
delete markers[callsign];
m.setMap();
return;
}
m.setOptions(getMarkerOpacityOptions(m.lastseen));
});
}, 1000);
})();

View File

@ -86,6 +86,7 @@ function init_rx_photo()
window.setTimeout(function() { animate(e("webrx-rx-photo-title"),"opacity","",1,0,1,500,30); },1000);
window.setTimeout(function() { animate(e("webrx-rx-photo-desc"),"opacity","",1,0,1,500,30); },1500);
window.setTimeout(function() { close_rx_photo() },2500);
$('#webrx-top-container .openwebrx-photo-trigger').click(toggle_rx_photo);
}
dont_toggle_rx_photo_flag=0;
@ -1250,6 +1251,13 @@ function on_ws_recv(evt)
case "metadata":
update_metadata(json.value);
break;
case "wsjt_message":
update_wsjt_panel(json.value);
break;
case "dial_frequencies":
dial_frequencies = json.value;
update_dial_button();
break;
default:
console.warn('received message of unknown type: ' + json.type);
}
@ -1315,6 +1323,29 @@ function on_ws_recv(evt)
}
}
var dial_frequencies = [];
function find_dial_frequencies() {
var sdm = $("#openwebrx-secondary-demod-listbox")[0].value;
return dial_frequencies.filter(function(d){
return d.mode == sdm;
});
}
function update_dial_button() {
var available = find_dial_frequencies();
$("#openwebrx-secondary-demod-dial-button")[available.length ? "addClass" : "removeClass"]("available");
}
function dial_button_click() {
var available = find_dial_frequencies();
if (!available.length) return;
var frequency = available[0].frequency;
console.info(frequency);
demodulator_set_offset_frequency(0, frequency - center_freq);
$("#webrx-actual-freq").html(format_frequency("{x} MHz", frequency, 1e6, 4));
}
function update_metadata(meta) {
if (meta.protocol) switch (meta.protocol) {
case 'DMR':
@ -1356,8 +1387,8 @@ function update_metadata(meta) {
if (meta.mode && meta.mode != "") {
mode = "Mode: " + meta.mode;
source = meta.source || "";
if (meta.lat && meta.lon) {
source = "<a class=\"openwebrx-maps-pin\" href=\"https://www.google.com/maps/search/?api=1&query=" + meta.lat + "," + meta.lon + "\" target=\"_blank\"></a>" + source;
if (meta.lat && meta.lon && meta.source) {
source = "<a class=\"openwebrx-maps-pin\" href=\"/map?callsign=" + meta.source + "\" target=\"_blank\"></a>" + source;
}
up = meta.up ? "Up: " + meta.up : "";
down = meta.down ? "Down: " + meta.down : "";
@ -1377,6 +1408,56 @@ function update_metadata(meta) {
}
function html_escape(input) {
return $('<div/>').text(input).html()
}
function update_wsjt_panel(msg) {
var $b = $('#openwebrx-panel-wsjt-message tbody');
var t = new Date(msg['timestamp']);
var pad = function(i) { return ('' + i).padStart(2, "0"); }
var linkedmsg = msg['msg'];
if (['FT8', 'JT65', 'JT9', 'FT4'].indexOf(msg['mode']) >= 0) {
var matches = linkedmsg.match(/(.*\s[A-Z0-9]+\s)([A-R]{2}[0-9]{2})$/);
if (matches && matches[2] != 'RR73') {
linkedmsg = html_escape(matches[1]) + '<a href="/map?locator=' + matches[2] + '" target="_blank">' + matches[2] + '</a>';
} else {
linkedmsg = html_escape(linkedmsg);
}
} else if (msg['mode'] == 'WSPR') {
var matches = linkedmsg.match(/([A-Z0-9]*\s)([A-R]{2}[0-9]{2})(\s[0-9]+)/);
if (matches) {
linkedmsg = html_escape(matches[1]) + '<a href="/map?locator=' + matches[2] + '" target="_blank">' + matches[2] + '</a>' + html_escape(matches[3]);
} else {
linkedmsg = html_escape(linkedmsg);
}
}
$b.append($(
'<tr data-timestamp="' + msg['timestamp'] + '">' +
'<td>' + pad(t.getUTCHours()) + pad(t.getUTCMinutes()) + pad(t.getUTCSeconds()) + '</td>' +
'<td class="decimal">' + msg['db'] + '</td>' +
'<td class="decimal">' + msg['dt'] + '</td>' +
'<td class="decimal freq">' + msg['freq'] + '</td>' +
'<td class="message">' + linkedmsg + '</td>' +
'</tr>'
));
$b.scrollTop($b[0].scrollHeight);
}
var wsjt_removal_interval;
// remove old wsjt messages in fixed intervals
function init_wsjt_removal_timer() {
if (wsjt_removal_interval) clearInterval(wsjt_removal_interval);
wsjt_removal_interval = setInterval(function(){
var $elements = $('#openwebrx-panel-wsjt-message tbody tr');
// limit to 1000 entries in the list since browsers get laggy at some point
var toRemove = $elements.length - 1000;
if (toRemove <= 0) return;
$elements.slice(0, toRemove).remove();
}, 15000);
}
function hide_digitalvoice_panels() {
$(".openwebrx-meta-panel").each(function(_, p){
toggle_panel(p.id, false);
@ -1436,8 +1517,9 @@ function waterfall_dequeue()
function on_ws_opened()
{
ws.send("SERVER DE CLIENT openwebrx.js");
ws.send("SERVER DE CLIENT client=openwebrx.js type=receiver");
divlog("WebSocket opened to "+ws_url);
reconnect_timeout = false;
}
var was_error=0;
@ -1818,6 +1900,8 @@ function audio_init()
}
var reconnect_timeout = false;
function on_ws_closed()
{
try
@ -1826,9 +1910,16 @@ function on_ws_closed()
}
catch (dont_care) {}
audio_initialized = 0;
divlog("WebSocket has closed unexpectedly. Attempting to reconnect in 5 seconds...", 1);
if (reconnect_timeout) {
// max value: roundabout 8 and a half minutes
reconnect_timeout = Math.min(reconnect_timeout * 2, 512000);
} else {
// initial value: 1s
reconnect_timeout = 1000;
}
divlog("WebSocket has closed unexpectedly. Attempting to reconnect in " + reconnect_timeout / 1000 + " seconds...", 1);
setTimeout(open_websocket, 5000);
setTimeout(open_websocket, reconnect_timeout);
}
function on_ws_error(event)
@ -2332,6 +2423,13 @@ function openwebrx_resize()
check_top_bar_congestion();
}
function init_header()
{
$('#openwebrx-main-buttons li[data-toggle-panel]').click(function() {
toggle_panel($(this).data('toggle-panel'));
});
}
function openwebrx_init()
{
if(ios||is_chrome) e("openwebrx-big-grey").style.display="table-cell";
@ -2344,6 +2442,7 @@ function openwebrx_init()
window.setTimeout(function(){window.setInterval(debug_audio,1000);},1000);
window.addEventListener("resize",openwebrx_resize);
check_top_bar_congestion();
init_header();
//Synchronise volume with slider
updateVolume();
@ -2351,7 +2450,9 @@ function openwebrx_init()
}
function digimodes_init() {
hide_digitalvoice_panels();
$(".openwebrx-meta-panel").each(function(_, p){
p.openwebrxHidden = true;
});
// initialze DMR timeslot muting
$('.openwebrx-dmr-timeslot-panel').click(function(e) {
@ -2638,12 +2739,19 @@ function demodulator_digital_replace(subtype)
{
case "bpsk31":
case "rtty":
case "ft8":
case "wspr":
case "jt65":
case "jt9":
case "ft4":
secondary_demod_start(subtype);
demodulator_analog_replace('usb', true);
demodulator_buttons_update();
break;
}
$('#openwebrx-panel-digimodes').attr('data-mode', subtype);
toggle_panel("openwebrx-panel-digimodes", true);
toggle_panel("openwebrx-panel-wsjt-message", ['ft8', 'wspr', 'jt65', 'jt9', 'ft4'].indexOf(subtype) >= 0);
}
function secondary_demod_create_canvas()
@ -2698,6 +2806,7 @@ function secondary_demod_swap_canvases()
function secondary_demod_init()
{
$("#openwebrx-panel-digimodes")[0].openwebrxHidden = true;
$("#openwebrx-panel-wsjt-message")[0].openwebrxHidden = true;
secondary_demod_canvas_container = $("#openwebrx-digimode-canvas-container")[0];
$(secondary_demod_canvas_container)
.mousemove(secondary_demod_canvas_container_mousemove)
@ -2705,6 +2814,7 @@ function secondary_demod_init()
.mousedown(secondary_demod_canvas_container_mousedown)
.mouseenter(secondary_demod_canvas_container_mousein)
.mouseleave(secondary_demod_canvas_container_mouseout);
init_wsjt_removal_timer();
}
function secondary_demod_start(subtype)
@ -2762,6 +2872,7 @@ function secondary_demod_close_window()
{
secondary_demod_stop();
toggle_panel("openwebrx-panel-digimodes", false);
toggle_panel("openwebrx-panel-wsjt-message", false);
}
secondary_demod_fft_offset_db=30; //need to calculate that later
@ -2802,19 +2913,23 @@ function secondary_demod_waterfall_dequeue()
secondary_demod_listbox_updating = false;
function secondary_demod_listbox_changed()
{
if(secondary_demod_listbox_updating) return;
switch ($("#openwebrx-secondary-demod-listbox")[0].value)
{
if (secondary_demod_listbox_updating) return;
var sdm = $("#openwebrx-secondary-demod-listbox")[0].value;
switch (sdm) {
case "none":
demodulator_analog_replace_last();
break;
case "bpsk31":
demodulator_digital_replace('bpsk31');
break;
case "rtty":
demodulator_digital_replace('rtty');
case "ft8":
case "wspr":
case "jt65":
case "jt9":
case "ft4":
demodulator_digital_replace(sdm);
break;
}
update_dial_button();
}
function secondary_demod_listbox_update()

View File

@ -1,94 +0,0 @@
<html>
<!--
This file is part of OpenWebRX,
an open-source SDR receiver software with a web UI.
Copyright (c) 2013-2015 by Andras Retzler <randras@sdr.hu>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<head><title>OpenWebRX</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style>
html, body
{
font-family: "DejaVu Sans", Verdana, Geneva, sans-serif;
width: 100%;
text-align: center;
margin: 0;
padding: 0;
}
img.logo
{
margin-top: 120px;
}
div.frame
{
text-align: left;
margin:0px auto;
width: 800px;
}
div.panel
{
text-align: center;
background-color:#777777;
border-radius: 15px;
padding: 12px;
font-weight: bold;
color: White;
font-size: 13pt;
/*text-shadow: 1px 1px 4px #444;*/
font-family: sans;
}
div.alt
{
font-size: 10pt;
padding-top: 10px;
}
body div a
{
color: #5ca8ff;
text-shadow: none;
}
span.browser
{
}
</style>
<script>
var irt = function (s,n) {return s.replace(/[a-zA-Z]/g,function(c){return String.fromCharCode((c>="a"?97:65)<=(c=c.charCodeAt(0)-n)?c:c+26);});}
var sendmail2 = function (s) { window.location.href="mailto:"+irt(s.replace("=",String.fromCharCode(0100)).replace("$","."),8); }
window.addEventListener("load",function(){rs=document.getElementById("reconnect-secs"); rt=document.getElementById("reconnect-text"); cnt=29;window.setInterval(function(){if(cnt<=-1) window.location.href=window.location.href.split("retry.")[0]; else if(cnt==0) {rt.innerHTML="Reconnecting..."; cnt--;} else rs.innerHTML=(cnt--).toString();},1000);},false);
</script>
</head>
<body>
<div class="frame">
<img class="logo" src="gfx/openwebrx-logo-big.png" style="height: 60px;"/>
<div class="panel">
There are no client slots left on this server.
<div class="alt">
Please wait until a client disconnects.<br /><span id="reconnect-text">We will try to reconnect in <span id="reconnect-secs">30</span> seconds...</span>
</div>
</div>
</div>
</body>
</html>

View File

@ -1,95 +0,0 @@
<html>
<!--
This file is part of OpenWebRX,
an open-source SDR receiver software with a web UI.
Copyright (c) 2013-2015 by Andras Retzler <randras@sdr.hu>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<head><title>OpenWebRX</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style>
html, body
{
font-family: "DejaVu Sans", Verdana, Geneva, sans-serif;
width: 100%;
text-align: center;
margin: 0;
padding: 0;
}
img.logo
{
margin-top: 120px;
}
div.frame
{
text-align: left;
margin:0px auto;
width: 800px;
}
div.panel
{
text-align: center;
background-color:#777777;
border-radius: 15px;
padding: 12px;
font-weight: bold;
color: White;
font-size: 13pt;
/*text-shadow: 1px 1px 4px #444;*/
font-family: sans;
}
div.alt
{
font-size: 10pt;
padding-top: 10px;
}
body div a
{
color: #5ca8ff;
text-shadow: none;
}
span.browser
{
}
</style>
<script>
var irt = function (s,n) {return s.replace(/[a-zA-Z]/g,function(c){return String.fromCharCode((c>="a"?97:65)<=(c=c.charCodeAt(0)-n)?c:c+26);});}
var sendmail2 = function (s) { window.location.href="mailto:"+irt(s.replace("=",String.fromCharCode(0100)).replace("$","."),8); }
</script>
</head>
<body>
<div class="frame">
<img class="logo" src="gfx/openwebrx-logo-big.png" style="height: 60px;"/>
<div class="panel">
Only the latest <span class="browser">Google Chrome</span> browser is supported at the moment.<br/>
Please <a href="http://chrome.google.com/">download and install Google Chrome.</a><br />
<div class="alt">
Alternatively, you may proceed to OpenWebRX, but it's not supposed to work as expected. <br />
<a href="/?unsupported">Click here</a> if you still want to try OpenWebRX.</a>
</div>
</div>
</div>
</body>
</html>