diff options
author | Max <ikj1234i@yahoo.com> | 2018-03-16 16:38:26 -0400 |
---|---|---|
committer | Max <ikj1234i@yahoo.com> | 2018-03-16 16:38:26 -0400 |
commit | e572cfe8022b2d2fd0d591bf90324c18c30090dc (patch) | |
tree | 8c09b2aa4a6b1cf0220d5879286fb474a2021cd6 | |
parent | 9d344f283b9a595b35c6b6e9a7e6b514838ed974 (diff) |
configuration additions
-rw-r--r-- | op25/gr-op25_repeater/www/www-static/index.html | 190 | ||||
-rw-r--r-- | op25/gr-op25_repeater/www/www-static/main.css | 91 | ||||
-rw-r--r-- | op25/gr-op25_repeater/www/www-static/main.js | 410 |
3 files changed, 671 insertions, 20 deletions
diff --git a/op25/gr-op25_repeater/www/www-static/index.html b/op25/gr-op25_repeater/www/www-static/index.html index b6c00bd..d1b882f 100644 --- a/op25/gr-op25_repeater/www/www-static/index.html +++ b/op25/gr-op25_repeater/www/www-static/index.html @@ -19,8 +19,10 @@ <ul class="nav-ul"> <li id="li1" class="nav-li"><input id="b1" class="nav-button" type="button" name="B1" value="Home" method="post" action="" onclick="javascript:f_select("status");"></li> <li id="li2" class="nav-li"><input id="b2" class="nav-button" type="button" name="B2" value="Plot" method="post" action="" onclick="javascript:f_select("plot");"></li> -<li id="li3" class="nav-li"><input id="b3" class="nav-button" type="button" name="B3" value="About" method="post" action="" onclick="javascript:f_select("about");"></li> -<li id="li4"><span class="copyr"> © 2017, 2018 Max H. Parke KA1RBI</span></li> +<li id="li3" class="nav-li"><input id="b3" class="nav-button" type="button" name="B3" value="Configuration" method="post" action="" onclick="javascript:f_select("settings");"></li> +<li id="li4" class="nav-li"><input id="b4" class="nav-button" type="button" name="B4" value="RX" method="post" action="" onclick="javascript:f_select("rx");"></li> +<li id="li5" class="nav-li"><input id="b5" class="nav-button" type="button" name="B5" value="About" method="post" action="" onclick="javascript:f_select("about");"></li> +<li id="li6"><span class="copyr"> © 2017, 2018 Max H. Parke KA1RBI</span></li> </ul> </div> <br> @@ -104,6 +106,190 @@ <img src="1x1.png" id="img3" style="display:none;" alt="plot"><br> </div> +<div id="div_settings" class="div_settings" style="display: none;"> +<img src="temp.png"><br> +<form method="post" action="#" id="form_settings"> +<div id="cfg_list_area"> +</div> +<input type="button" name="list" value="Refresh" onclick="javascript:f_list();"></input> - Reload selection list +<input type=checkbox id="include_tsv" name="include_tsv">Include old-style trunking TSV files +<br> +<input type="button" name="load" value="Edit" onclick="javascript:f_load();"></input> - Open configuration editor (any previous unsaved work will be lost)<br> +<input type="button" name="start" value="Start" onclick="javascript:f_start();"></input> - Run flowgraph using selected configuration<br> +<br> +<div id="answer_area"> +</div> +<div id="edit_settings" style="display: none"> +<hr><br> +<input type="button" name="save" value="Save" onclick="javascript:f_save();"></input> + - Store configuration. Name: +<input type="text" id="config_name" name="config_name" value=""> <br> +<div id="div_rx_opts"> +<table border=1 id="rxopt-table" style="display: none"> +<tr> +<th colspan=2 class="boxtitle-th"><span class="boxtitle">Backend Options [rx.py]</span></th> +<th colspan=2> +<input type="button" name="show" value="Show" onclick="javascript:show_advanced(this)">advanced options +</th> +</tr> +<tr> +<th>enable built-in udp audio player</th> +<th>voice codec</th> +<th>fine tuning</th> +<th>Wireshark host</th> +</tr> +<tr id="rxrow" class="rxrow"> +<td><input type=checkbox name="udp-player" ></input></td> +<td><input type=checkbox name="vocoder" ></input></td> +<td><input type=text name="fine-tune" value="0"></input></td> +<td><input type=text name="wireshark-host" value="127.0.0.1"></input></td> +</tr> +<tr id="advrow" class="advrow" style="display: none"> +<td colspan=5> +<table border=1> +<tr><th>Costas alpha</th><td><input type=text name="costas-alpha" value="0.04"></input></td></tr> +<tr><th>number of demods</th><td><input type=text name="logfile-workers" value="None"></input></td></tr> +<tr><th>spectrum decimation</th><td><input type=text name="decim-amt" value="1"></input></td></tr> +<tr><th>Gardner gain</th><td><input type=text name="gain-mu" value="0.025"></input></td></tr> +<tr><th>ifile seek</th><td><input type=text name="seek" value="0"></input></td></tr> +<tr><th>complex file input</th><td><input type=text name="ifile" value="None"></input></td></tr> +<tr><th>antenna</th><td><input type=text name="antenna" value=""></input></td></tr> +<tr><th>USRP offset / audio IF</th><td><input type=text name="calibration" value="0.0"></input></td></tr> +<tr><th>symbol dump file</th><td><input type=text name="raw-symbols" value="None"></input></td></tr> +<tr><th>audio output dev</th><td><input type=text name="audio-output" value="default"></input></td></tr> +<tr><th>input file</th><td><input type=text name="input" value="None"></input></td></tr> +<tr><th>Wireshark output</th><td><input type=checkbox name="wireshark" ></input></td></tr> +<tr><th>gain settings</th><td><input type=text name="gains" value="None"></input></td></tr> +<tr><th>USRP / audio gain</th><td><input type=text name="gain" value="None"></input></td></tr> +<tr><th>excess BW</th><td><input type=text name="excess-bw" value="0.2"></input></td></tr> +<tr><th>pcm inp device</th><td><input type=text name="audio-input" value=""></input></td></tr> +<tr><th>soundcard IF</th><td><input type=checkbox name="audio-if" ></input></td></tr> +<tr><th>tone detect algo</th><td><input type=checkbox name="tone-detect" ></input></td></tr> +<tr><th>voice codec</th><td><input type=checkbox name="vocoder" ></input></td></tr> +<tr><th>hamlib model</th><td><input type=text name="hamlib-model" value="None"></input></td></tr> +<tr><th>direct audio inp</th><td><input type=checkbox name="audio" ></input></td></tr> +<tr><th>startup pause</th><td><input type=checkbox name="pause" ></input></td></tr> +</table> +</td></tr> +</table> +</div> +<p> +<table id="devtable" border=1> +<tr><th colspan=8 class="boxtitle-th"><span class="boxtitle">Devices</span></th> +<th colspan=2> +<input type="button" name="new" value="Add New" onclick="javascript:f_command(this, "new");"></input> +</th> +</tr> +<tr> +<th>Active</th> +<th>Name</th> +<th>Device Args</th> +<th>Frequency (MHz)</th> +<th>Gains</th> +<th>Offset</th> +<th>PPM</th> +<th>Sample Rate</th> +<th> </th> +</tr> +<tr id="devrow" class="dynrow" style="display: none"> +<td><input type="checkbox" name="active" checked></input></td> +<td><input type="text" name="name" value="Device1"></td> +<td><input type="text" name="args" value="rtl:0"></td> +<td><input type="text" name="frequency" value="500.0"></td> +<td><input type="text" name="gains" value="lna:45"></td> +<td><input type="text" name="offset" value="0"></td> +<td><input type="text" name="ppm" value="0"></td> +<td><input type="text" name="rate" value="1000000"></td> +<td> +<input type="button" name="clone" value="CLONE" onclick="javascript:f_command(this, "clone");"></input> +<br> +<input type="button" name="delete" value="DELETE" onclick="javascript:f_command(this, "delete");"></input> +</td> +</tr> +</table> +<p> +<table id="chtable" border=1> +<tr><th colspan=7 class="boxtitle-th"><span class="boxtitle">Channel Details</span></th> +<th colspan=3> +<input type="button" name="new" value="Add New" onclick="javascript:f_command(this, "new");"></input> +</th> +</tr> +<tr> +<th>Active</th> +<th>Trunked</th> +<th>Name</th> +<th>Frequency (MHz)</th> +<th>Demod Type</th> +<th>Filter Type</th> +<th>Plot Type(s)</th> +<th>Destination</th> +<th>IF Rate</th> +<th> </th> +</tr> +<tr id="chrow" class="dynrow" style="display: none"> +<td><input type="checkbox" name="active" checked></input></td> +<td><input type="checkbox" name="trunked" onchange="javascript:f_trunked(this)"></input></td> +<td><input type="text" name="name" value="Channel1"></td> +<td><input type="text" name="frequency" value="500.0"></td> +<td><select name="demod_type"> +<option value="cqpsk">CQPSK</option> +<option value="c4fm">C4FM</option> +</select></td> +<td><select name="filter_type"> +<option value="rc">RC (P25)</option> +<option value="rrc">RRC (YSF/DMR)</option> +<option value="gmsk">GMSK</option> +</select></td> +<td><select name="plot" multiple size=1> +<option value="None" selected>None</option> +<option value="constellation">Constellation</option> +<option value="symbol">Symbol</option> +<option value="fft">FFT</option> +<option value="datascope">Datascope</option> +</select></td> +<td><input type="text" name="destination" value="udp://127.0.0.1:23456"></td> +<td><input type="text" name="if_rate" value="24000"></td> +<td> +<input type="button" name="clone" value="CLONE" onclick="javascript:f_command(this, "clone");"></input> +<br> +<input type="button" name="delete" value="DELETE" onclick="javascript:f_command(this, "delete");"></input> +</td> +</tr> +<tr id="trrow" class="dynrow" style="display: none"> +<td colspan=3> </td> +<td colspan=6> + <div> + <table border=1> + <tr> + <th colspan=2 class="boxtitle-th"><span class="boxtitle">Trunking Info</span></th> + <th>NAC</th> + <th>P2 TDMA</th> + <th>CC Freq's</th> + <th>White List</th> + <th>Black List</th> + <th>TGID Tags</th> + </tr> + <tr class="trunk-info"> + <td colspan=2> </td> + <td><input type="text" name="nac" value="None"></td> + <td><input type="checkbox" name="phase2_tdma"></td> + <td><input type="text" name="cclist" value="0"></td> + <td><input type="text" name="whitelist" value="None"></td> + <td><input type="text" name="blacklist" value="None"></td> + <td><input type="button" name="tgid-tags" value="Show"></input></td> + </tr> + </table> + </div> +</td> +<td> </td> +</tr> +</table> +</div> +</form> +</div> +<br> +<div id="div_rx" style="display: none"> +</div> </body> </html> diff --git a/op25/gr-op25_repeater/www/www-static/main.css b/op25/gr-op25_repeater/www/www-static/main.css index aee67a5..9aa3e5e 100644 --- a/op25/gr-op25_repeater/www/www-static/main.css +++ b/op25/gr-op25_repeater/www/www-static/main.css @@ -153,6 +153,11 @@ div.adjacent { font-size: 24px; } +.boxtitle { + font-weight: bold; + text-align: left; +} + /* the whole NAC string... NAC, freq tsbks, etc. */ .nac { @@ -251,3 +256,89 @@ div.adjacent { background-color: #699; background: linear-gradient(#588, #699); } + +#div_settings table { + border-color: black; +} + +#div_settings tr { + border-top: none; + border-bottom: solid; +} + +#div_settings th.boxtitle-th { + text-align: left; +} + +.div_settings th { + max-width: 75px; + border-style: none; + padding: 3px; + font-family: Arial, Helvetica, sans-serif; + font-size: 12px; + color: #000; + background: #eee; + text-align: right; + font-weight: normal; +} + +#div_settings td { + max-width: 75px; + border-style: none; + font-weight: bold; + text-align: right; +} + +#div_settings input[type=text] { + max-width: 75px; + border-top: none; + border-bottom-width: 1; + border-bottom: dotted; + border-right: none; + border-left: none; + text-align: right; +} + +#div_settings input[type=button] { + max-width: 75px; + padding: 10px; + color: blue; + border: 0; +} + +#div_settings select { + max-width: 100px; + padding: 0; + border: 0; +} + +#div_settings option { + max-width: 100px; + padding: 0; + border: 0; +} + +.boxtitle { + text-align: left; +} + +div#cfg_list_area select { + width: 250px; + max-width: 250px; +} + +#div_rx_opts td { + font-family: Arial, Helvetica, sans-serif; + font-size: 12px; + border-style: none; +} + +#div_rx_opts input[type=text] { + max-width: 75px; + border-top: none; + border-bottom-width: 1; + border-bottom: dotted; + border-right: none; + border-left: none; + text-align: right; +} diff --git a/op25/gr-op25_repeater/www/www-static/main.js b/op25/gr-op25_repeater/www/www-static/main.js index bf7d2ab..3319b2d 100644 --- a/op25/gr-op25_repeater/www/www-static/main.js +++ b/op25/gr-op25_repeater/www/www-static/main.js @@ -47,32 +47,155 @@ function find_parent(ele, tagname) { function f_command(ele, command) { var myrow = find_parent(ele, "TR"); + var mytbl = find_parent(ele, "TABLE"); + amend_d(myrow, mytbl, command); +} + +function edit_freq(freq, to_ui) { + var MHZ = 1000000.0; + if (to_ui) { + var f = (freq / MHZ) + ""; + if (f.indexOf(".") == -1) + f += ".0"; + return f; + } else { + var f = parseFloat(freq); + if (freq.indexOf(".")) + f *= MHZ; + return Math.round(f); + } +} + +function edit_d(d, to_ui) { + var new_d = {}; + var hexints = {"nac":1}; + var ints = {"if_rate":1, "ppm":1, "rate":1, "offset":1, "nac":1, "logfile-workers":1, "decim-amt":1, "seek":1, "hamlib-model":1 }; + var bools = {"active":1, "trunked":1, "rate":1, "offset":1, "phase2_tdma": 1, "phase2-tdma":1, "wireshark":1, "udp-player":1, "audio-if":1, "tone-detect":1, "vocoder":1, "audio":1, "pause":1 }; + var floats = {"costas-alpha":1, "gain-mu":1, "calibration":1, "fine-tune":1, "gain":1, "excess-bw":1, "offset":1} + var lists = {"blacklist":1, "whitelist":1, "cclist":1}; + var freqs = {"frequency":1, "cclist":1}; + + + for (var k in d) { + if (!to_ui) { + if (d[k] == "None") + new_d[k] = null; + else + new_d[k] = d[k]; + if (k == "plot" && !d[k].length) + new_d[k] = null; + if (k in ints) { + new_d[k] = parseInt(new_d[k]); + } else if (k in floats) { + new_d[k] = parseFloat(new_d[k]); + } else if (k in lists) { + var l = new_d[k].split(","); + if (k in freqs) { + var new_l = []; + for (var i in l) + new_l.push(edit_freq(l[i], to_ui)); + new_d[k] = new_l; + } else { + new_d[k] = l; + } + } else if (k in freqs) { + new_d[k] = edit_freq(new_d[k], to_ui); + } + } else { + if (k in hexints) { + new_d[k] = "0x" + d[k].toString(16); + } else if (k in ints) { + if (d[k] == null) + new_d[k] = ""; + else + new_d[k] = d[k].toString(10); + } else if (k in lists) { + if (k in freqs) { + var new_l = []; + for (var i in d[k]) { + new_l.push(edit_freq(d[k][i], to_ui)); + } + new_d[k] = new_l.join(","); + } else { + new_d[k] = d[k].join(","); + } + } else if (k in freqs) { + new_d[k] = edit_freq(d[k], to_ui); + } else { + new_d[k] = d[k]; + } + } + } + return new_d; +} + +function edit_l(cfg, to_ui) { + var new_d = {"devices": [], "channels": []}; + for (var device in cfg['devices']) + new_d["devices"].push(edit_d(cfg['devices'][device], to_ui)); + for (var channel in cfg['channels']) + new_d["channels"].push(edit_d(cfg['channels'][channel], to_ui)); + new_d["backend-rx"] = edit_d(cfg['backend-rx'], to_ui); + return new_d; +} + +function amend_d(myrow, mytbl, command) { + var trunk_row = null; + if (mytbl.id == "chtable") + trunk_row = find_next(myrow, "TR"); if (command == "delete") { var ok = confirm ("Confirm delete"); - if (ok) + if (ok) { myrow.parentNode.removeChild(myrow); + if (mytbl.id == "chtable") + trunk_row.parentNode.removeChild(trunk_row); + } } else if (command == "clone") { var newrow = myrow.cloneNode(true); - if (myrow.nextSibling) - myrow.parentNode.insertBefore(newrow, myrow.nextSibling); - else - myrow.parentNode.appendChild(newrow); + newrow.id = find_free_id("id_"); + if (mytbl.id == "chtable") { + var newrow2 = trunk_row.cloneNode(true); + newrow2.id = "tr_" + newrow.id.substring(3); + if (trunk_row.nextSibling) { + myrow.parentNode.insertBefore(newrow2, trunk_row.nextSibling); + myrow.parentNode.insertBefore(newrow, trunk_row.nextSibling); + } else { + myrow.parentNode.appendChild(newrow); + myrow.parentNode.appendChild(newrow2); + } + } else { + if (myrow.nextSibling) + myrow.parentNode.insertBefore(newrow, myrow.nextSibling); + else + myrow.parentNode.appendChild(newrow); + } } else if (command == "new") { - var mytbl = find_parent(ele, "TABLE"); var newrow = null; - if (mytbl.id == "chtable") + var parent = null; + if (mytbl.id == "chtable") { newrow = document.getElementById("chrow").cloneNode(true); - else if (mytbl.id == "devtable") + parent = document.getElementById("chrow").parentNode; + } else if (mytbl.id == "devtable") { newrow = document.getElementById("devrow").cloneNode(true); - else - return; - mytbl.appendChild(newrow); + parent = document.getElementById("devrow").parentNode; + } else { + return null; + } + newrow.style['display'] = ''; + newrow.id = find_free_id("id_"); + parent.appendChild(newrow); + if (mytbl.id == "chtable") { + var newrow2 = document.getElementById("trrow").cloneNode(true); + newrow2.id = "tr_" + newrow.id.substring(3); + parent.appendChild(newrow2); + } + return newrow.id; } } function nav_update(command) { - var names = ["b1", "b2", "b3"]; - var bmap = { "status": "b1", "plot": "b2", "about": "b3" }; + var names = ["b1", "b2", "b3", "b4", "b5"]; + var bmap = { "status": "b1", "plot": "b2", "settings": "b3", "rx": "b4", "about": "b5" }; var id = bmap[command]; for (var id1 in names) { b = document.getElementById(names[id1]); @@ -85,7 +208,7 @@ function nav_update(command) { } function f_select(command) { - var div_list = ["status", "plot", "about"]; + var div_list = ["status", "plot", "settings", "rx", "about"]; for (var i=0; i<div_list.length; i++) { var ele = document.getElementById("div_" + div_list[i]); if (command == div_list[i]) @@ -99,6 +222,8 @@ function f_select(command) { else ctl.style['display'] = "none"; nav_update(command); + if (command == "settings") + f_list(); } function is_digit(s) { @@ -152,14 +277,14 @@ function adjacent_data(d) { var html = "<div class=\"adjacent\">"; html += "<table border=1 borderwidth=0 cellpadding=0 cellspacing=0 width=100%>"; html += "<tr><th colspan=99 style=\"align: center\">Adjacent Sites</th></tr>"; - html += "<tr><th>Frequency</th><th>RFSS</th><th>Site</th><th>Uplink</th></tr>"; + html += "<tr><th>Frequency</th><th>Sys ID</th><th>RFSS</th><th>Site</th><th>Uplink</th></tr>"; var ct = 0; for (var freq in d) { var color = "#d0d0d0"; if ((ct & 1) == 0) color = "#c0c0c0"; ct += 1; - html += "<tr style=\"background-color: " + color + ";\"><td>" + freq / 1000000.0 + "</td><td>" + d[freq]["rfid"] + "</td><td>" + d[freq]["stid"] + "</td><td>" + (d[freq]["uplink"] / 1000000.0) + "</td></tr>"; + html += "<tr style=\"background-color: " + color + ";\"><td>" + freq / 1000000.0 + "</td><td>" + d[freq]['sysid'].toString(16) + "</td><td>" + d[freq]["rfid"] + "</td><td>" + d[freq]["stid"] + "</td><td>" + (d[freq]["uplink"] / 1000000.0) + "</td></tr>"; } html += "</table></div></div><br><br>"; @@ -174,6 +299,8 @@ function trunk_update(d) { var do_hex = {"syid":0, "sysid":0, "wacn": 0}; var do_float = {"rxchan":0, "txchan":0}; var html = ""; + var msg = JSON.stringify(d); + document.getElementById("answer_area").innerHTML = msg;msg; for (var nac in d) { if (!is_digit(nac.charAt(0))) continue; @@ -228,6 +355,58 @@ function trunk_update(d) { div_s1.innerHTML = html; } +function config_list(d) { + var html = ""; + html += "<select id=\"config_select\" name=\"cfg-list\" size=5>"; + for (var file in d["data"]) { + html += "<option value=\"" + d["data"][file] + "\">" + d["data"][file] + "</option>"; + } + html += "<option value=\"New Configuration\">New Configuration</option>"; + html += "</select>"; + document.getElementById("cfg_list_area").innerHTML = html; +} + +function config_data(d) { + var cfg = edit_l(d['data'], true); + open_editor(); + var chtable = document.getElementById("chtable"); + var devtable = document.getElementById("devtable"); + var chrow = document.getElementById("chrow"); + var devrow = document.getElementById("devrow"); + for (var device in cfg['devices']) + rollup_row("dev", document.getElementById(amend_d(devrow, devtable, "new")), cfg['devices'][device]); + for (var channel in cfg['channels']) + rollup_row("ch", document.getElementById(amend_d(chrow, chtable, "new")), cfg['channels'][channel]); + rollup_rx_rows(cfg['backend-rx']); +} + +function open_editor() { + document.getElementById("edit_settings").style["display"] = ""; + var rows = document.querySelectorAll(".dynrow"); + var ct = 0; + for (var r in rows) { + var row = rows[r]; + ct += 1; + if (row.id && (row.id.substring(0,3) == "id_" || row.id.substring(0,3) == "tr_")) { + row.parentNode.removeChild(row); + } + } + var oldtbl = document.getElementById("rt_1"); + if (oldtbl) + oldtbl.parentNode.removeChild(oldtbl); + var tbl = document.getElementById("rxopt-table"); + var newtbl = tbl.cloneNode(true); + newtbl.id = "rt_1"; + newtbl.style["display"] = ""; + var rxrow = newtbl.querySelector(".rxrow"); + var advrow = newtbl.querySelector(".advrow"); + rxrow.id = "rx_1"; + advrow.id = "rx_2"; + if (tbl.nextSibling) + tbl.parentNode.insertBefore(newtbl, tbl.nextSibling); + else + tbl.parentNode.appendChild(newtbl); +} function http_req_cb() { req_cb_count += 1; @@ -242,7 +421,7 @@ function http_req_cb() { } r200_count += 1; var dl = JSON.parse(http_req.responseText); - var dispatch = {'trunk_update': trunk_update, 'change_freq': change_freq, 'rx_update': rx_update} + var dispatch = {'trunk_update': trunk_update, 'change_freq': change_freq, 'rx_update': rx_update, 'config_data': config_data, 'config_list': config_list} for (var i=0; i<dl.length; i++) { var d = dl[i]; if (!("json_type" in d)) @@ -267,12 +446,17 @@ function do_update() { } function send_command(command, data) { + var d = {"command": command, "data": data}; + send(d); +} + +function send(d) { request_count += 1; if (send_queue.length >= SEND_QLIMIT) { send_qfull += 1; send_queue.unshift(); } - send_queue.push( {"command": command, "data": data} ); + send_queue.push( d ); send_process(); } @@ -312,3 +496,193 @@ function f_debug() { var div_debug = document.getElementById("div_debug"); div_debug.innerHTML = html; } + +function find_next(e, tag) { + var n = e.nextSibling; + for (var i=0; i<25; i++) { + if (n == null) + return null; + if (n.nodeName == tag) + return n; + n = n.nextSibling; + } + return null; +} + +function find_free_id(pfx) { + for (var seq = 1; seq < 5000; seq++) { + var test_id = pfx + seq; + var ele = document.getElementById(test_id); + if (!ele) + return test_id; + } + return null; +} + +function f_trunked(e) { + var row = find_parent(e, "TR"); + var trrow = document.getElementById("tr_" + row.id.substring(3)); + trrow['style']["display"] = (e.checked) ? "" : "none"; +} + +function read_write_sel(sel_node, def) { + var result = []; + var elist = sel_node.querySelectorAll("option"); + for (var e in elist) { + var ele = elist[e]; + if (def) { + var options = def[sel_node.name].split(","); + var opts = {}; + for (var o in options) + opts[options[o]] = 1; + if (ele.value in opts) + ele.selected = true; + else + ele.selected = false; + } else { + if (ele.selected) + result.push(ele.value); + } + } + if (!def) + return result.join(); +} + +function read_write(elist, def) { + var result = {}; + var s = "len: " + elist.length + "; "; + for (var e in elist) { + s += elist[e].tagName + "; "; + } + for (var e in elist) { + var ele = elist[e]; + if (ele.nodeName == 'INPUT') { + if (ele.type == 'text') + if (def) { + ele.value = def[ele.name]; + s += ele.name + "=" + ele.value + "; "; + } else + result[ele.name] = ele.value; + else if (ele.type == 'checkbox') + if (def) { + ele.checked = def[ele.name]; + s += "checkbox " + ele.name + "; "; + } + else + result[ele.name] = ele.checked; + } else if (ele.nodeName == 'SELECT') { + if (def) { + read_write_sel(ele, def); + s += "select " + ele.name + "; "; + } + else + result[ele.name] = read_write_sel(ele, def); + } + + } + if (!def) + return result; +} + +function rollup_row(which, row, def) { + var elements = Array.from(row.querySelectorAll("input,select")); + if (which == "ch") { + var trrow = document.getElementById("tr_" + row.id.substring(3)); + elements = elements.concat(Array.from(trrow.querySelectorAll("input,select"))); + } + else if (which == "rx") { + var advrow = document.getElementById("rx_2"); + elements = elements.concat(Array.from(advrow.querySelectorAll("input,select"))); + } + if (def && which == "ch") + trrow.style["display"] = (def["trunked"]) ? "" : "none"; + var result = read_write(elements, def); + if (!def) + return result; +} + +function rollup(which, def) { + var result = []; + var mytbl = document.getElementById(which + "table"); + var elements = mytbl.querySelectorAll(".dynrow"); + for (var e in elements) { + var row = elements[e]; + if (row.id != null && row.id.substring(0,3) == "id_") + result.push(rollup_row(which, row)); + } + if (!def) + return result; +} + +function rollup_rx_rows(def) { + return rollup_row("rx", document.getElementById("rx_1"), def); +} + +function f_save() { + var name = document.getElementById("config_name"); + if (!name.value) { + alert("Name is required"); + name.focus(); + return; + } + if (name.value == "New Configuration") { + alert ("'" + name.value + "' is a reserved name, please retry"); + name.value = ""; + name.focus(); + return; + } + var cfg = { "devices": rollup("dev", null), "channels": rollup("ch", null), "backend-rx": rollup_rx_rows(null) }; + cfg = edit_l(cfg, false); + var request = {"name": name.value, "value": cfg}; + send_command("config-save", request); + f_list(); +} + +function f_list() { + var inp = document.getElementById("include_tsv"); + send_command("config-list", (inp.checked) ? "tsv" : ""); +} + +function f_start() { + var sel = document.getElementById("config_select"); + if (!sel) return; + var val = read_write_sel(sel, null); + if ((!val) || val == "New Configuration") { + alert ("You must select a valid configuration to start"); + return; + } + if (val.indexOf("[TSV]") >= 0) { + alert ("TSV files not supported. First, invoke \"Edit\"; inspect the resulting configuration; then click \"Save\"."); + return; + } + send_command("rx-start", val); +} + +function f_load() { + var sel = document.getElementById("config_select"); + if (!sel) return; + var val = read_write_sel(sel, null); + if (!val) { + alert ("You must select a configuration to edit"); + return; + } + if (val == "New Configuration") { + open_editor(); + } else { + send_command('config-load', val); + var ele = document.getElementById("config_name"); + ele.value = val; + } +} + +function show_advanced(o) { + var tbl = find_parent(o, "TABLE"); + var row = tbl.querySelector(".advrow"); + if (o.value == "Show") { + o.value = "Hide"; + row.style["display"] = ""; + } else { + o.value = "Show"; + row.style["display"] = "none"; + } +} |