Added some features.
This commit is contained in:
parent
c9bf26f1ac
commit
4b3cc10924
20
README.md
20
README.md
@ -14,7 +14,7 @@ It has the following features:
|
||||
- it works in Google Chrome, Chromium (above version 37) and Mozilla Firefox (above version 28),
|
||||
- currently only supports RTL-SDR, but other SDR hardware may be easily added.
|
||||
|
||||
**News:**
|
||||
**News (2015-08-18)**
|
||||
- My BSc. thesis written on OpenWebRX is <a href="http://openwebrx.org/bsc-thesis.pdf">available here.</a>
|
||||
- Several bugs were fixed to improve reliability and stability.
|
||||
- OpenWebRX now supports compression of audio and waterfall stream, so the required network uplink bandwidth has been decreased from 2 Mbit/s to about 200 kbit/s per client! (Measured with the default settings. It is also dependent on `fft_size`.)
|
||||
@ -22,6 +22,13 @@ It has the following features:
|
||||
- Receivers can now be listed on <a href="http://sdr.hu/">sdr.hu</a>.
|
||||
- License for OpenWebRX is now Affero GPL v3.
|
||||
|
||||
**News (2015-09-01)**
|
||||
- The DDC in *csdr* has been hand-optimized for ARM NEON, so it runs 3× faster on the Raspberry Pi than before.
|
||||
- Also we use *ncat* instead of *rtl_mus*, and it is also 3× faster.
|
||||
- OpenWebRX now supports URLs like: http://localhost:8073/#freq=145555000,mod=usb
|
||||
|
||||
- When upgrading OpenWebRX, please make sure that you upgrade *csdr*, and install the new (optional) dependency *ncat*!
|
||||
|
||||
## Setup
|
||||
|
||||
OpenWebRX currently requires Linux and python 2.7 to run.
|
||||
@ -30,6 +37,7 @@ First you will need to install the dependencies:
|
||||
|
||||
- <a href="https://github.com/simonyiszk/csdr">libcsdr</a>
|
||||
- <a href="http://sdr.osmocom.org/trac/wiki/rtl-sdr">rtl-sdr</a>
|
||||
- ncat (on Debian/Ubuntu, it is in the *nmap* package). *(It is optional, but highly advised.)*
|
||||
|
||||
After cloning this repository and connecting an RTL-SDR dongle to your computer, you can run the server:
|
||||
|
||||
@ -57,14 +65,10 @@ However, if you hold down the shift key, you can drag the center line (BFO) or t
|
||||
|
||||
## Configuration tips
|
||||
|
||||
If you want to run OpenWebRX on a remote server instead of localhost, do not forget to set *server_hostname* in `config_webrx.py`, or you may get a WebSocket error.
|
||||
Now we have a %[Wiki](https://github.com/simonyiszk/openwebrx/wiki) with some how-tos. However, some quick tips:
|
||||
|
||||
If you want to run OpenWebRX on a remote server instead of localhost, do not forget to set *server_hostname* in `config_webrx.py`.
|
||||
|
||||
DSP CPU usage can be fine-tuned in `plugins/dsp/csdr/plugin.py`: you can set transition bandwidths higher (thus degrade filter performance by decreasing the length of the kernel, but also decrease CPU usage), and also set `fft_size` lower.
|
||||
|
||||
If you constantly get *audio overrun* errors, you may change `audio_buffer_maximal_length_sec` in `openwebrx.js` from the default 1.7 to 3.
|
||||
|
||||
If you want a chat-box to the top of the page, <a href="https://gist.github.com/ha7ilm/15c4c5e4c80cef9b3144">here is a snippet</a> for you to include in `config_webrx.py`.
|
||||
|
||||
## Todo
|
||||
|
||||
Currently, clients use up a lot of bandwidth. This will be improved later.
|
||||
|
@ -66,6 +66,7 @@ sdrhu_public_listing = False
|
||||
dsp_plugin="csdr"
|
||||
fft_fps=9
|
||||
fft_size=4096
|
||||
#samp_rate = 2048000
|
||||
samp_rate = 250000
|
||||
|
||||
center_freq = 145525000
|
||||
@ -103,7 +104,13 @@ format_conversion="csdr convert_u8_f"
|
||||
|
||||
shown_center_freq = center_freq #you can change this if you use an upconverter
|
||||
|
||||
client_audio_buffer_size = 4
|
||||
client_audio_buffer_size = 5
|
||||
#increasing client_audio_buffer_size will:
|
||||
# - also increase the latency
|
||||
# - decrease the chance of audio underruns
|
||||
|
||||
start_freq = center_freq
|
||||
start_mod = "nfm" #nfm, am, lsb, usb, cw
|
||||
|
||||
iq_server_port = 4951
|
||||
# (if ncat is not available on your system, rtl_mus will be used, thus you will have to set the same port as "my_listening_port" in config_rtl.py as well)
|
||||
|
@ -23,11 +23,13 @@
|
||||
<head>
|
||||
<title>OpenWebRX | Open Source SDR Web App for Everyone!</title>
|
||||
<script type="text/javascript">
|
||||
//Local variables
|
||||
client_id="%[CLIENT_ID]";
|
||||
ws_url="%[WS_URL]";
|
||||
rx_photo_height=%[RX_PHOTO_HEIGHT];
|
||||
//Global variables
|
||||
var client_id="%[CLIENT_ID]";
|
||||
var ws_url="%[WS_URL]";
|
||||
var rx_photo_height=%[RX_PHOTO_HEIGHT];
|
||||
var audio_buffering_fill_to=%[AUDIO_BUFSIZE];
|
||||
var starting_mod = "%[START_MOD]";
|
||||
var starting_offset_frequency = %[START_OFFSET_FREQ];
|
||||
</script>
|
||||
<script src="sdr.js"></script>
|
||||
<script src="openwebrx.js"></script>
|
||||
|
@ -959,6 +959,32 @@ function resize_waterfall_container(check_init)
|
||||
canvas_container.style.height=(window.innerHeight-e("webrx-top-container").clientHeight-e("openwebrx-scale-container").clientHeight).toString()+"px";
|
||||
}
|
||||
|
||||
|
||||
audio_server_output_rate=11025;
|
||||
audio_client_resampling_factor=4;
|
||||
|
||||
|
||||
function audio_calculate_resampling(targetRate)
|
||||
{ //both at the server and the client
|
||||
output_range_max = 12000;
|
||||
output_range_min = 8000;
|
||||
i = 1;
|
||||
while(true)
|
||||
{
|
||||
audio_server_output_rate = Math.floor(targetRate / i);
|
||||
if(audio_server_output_rate < output_range_min)
|
||||
{
|
||||
audio_client_resampling_factor = audio_server_output_rate = 0;
|
||||
divlog("Your audio card sampling rate ("+targetRate.toString()+") is not supported.<br />Please change your operating system default settings in order to fix this.",1);
|
||||
}
|
||||
if(audio_server_output_rate >= output_range_min && audio_server_output_rate <= output_range_max) break; //okay, we're done
|
||||
i++;
|
||||
}
|
||||
audio_client_resampling_factor=i;
|
||||
console.log("audio_calculate_resampling() :: "+audio_client_resampling_factor.toString()+", "+audio_server_output_rate.toString());
|
||||
}
|
||||
|
||||
|
||||
debug_ws_data_received=0;
|
||||
max_clients_num=0;
|
||||
|
||||
@ -974,6 +1000,7 @@ function on_ws_recv(evt)
|
||||
{
|
||||
var stringData=arrayBufferToString(evt.data);
|
||||
if(stringData.substring(0,16)=="CLIENT DE SERVER") divlog("Acknowledged WebSocket connection: "+stringData);
|
||||
|
||||
}
|
||||
if(firstChars=="AUD")
|
||||
{
|
||||
@ -1010,6 +1037,7 @@ function on_ws_recv(evt)
|
||||
{
|
||||
case "setup":
|
||||
waterfall_init();
|
||||
audio_preinit();
|
||||
break;
|
||||
case "bandwidth":
|
||||
bandwidth=parseInt(param[1]);
|
||||
@ -1122,7 +1150,7 @@ var audio_initialized=0;
|
||||
|
||||
var audio_received = Array();
|
||||
var audio_buffer_index = 0;
|
||||
var audio_resampler=new sdrjs.RationalResamplerFF(4,1);
|
||||
var audio_resampler;
|
||||
var audio_codec=new sdrjs.ImaAdpcm();
|
||||
var audio_compression="unknown";
|
||||
var audio_node;
|
||||
@ -1167,7 +1195,7 @@ function audio_prepare(data)
|
||||
audio_prepared_buffers.push(audio_rebuffer.take());
|
||||
audio_buffer_current_count_debug++;
|
||||
}
|
||||
if(audio_buffering && audio_prepared_buffers.length>audio_buffering_fill_to) audio_buffering=false;
|
||||
if(audio_buffering && audio_prepared_buffers.length>audio_buffering_fill_to) { console.log("buffers now: "+audio_prepared_buffers.length.toString()); audio_buffering=false; }
|
||||
}
|
||||
|
||||
|
||||
@ -1246,6 +1274,8 @@ var audio_buffer_progressbar_update_disabled=false;
|
||||
|
||||
var audio_buffer_total_average_level=0;
|
||||
var audio_buffer_total_average_level_length=0;
|
||||
var audio_overrun_cnt = 0;
|
||||
var audio_underrun_cnt = 0;
|
||||
|
||||
function audio_buffer_progressbar_update()
|
||||
{
|
||||
@ -1255,8 +1285,8 @@ function audio_buffer_progressbar_update()
|
||||
var overrun=audio_buffer_value>audio_buffer_maximal_length_sec;
|
||||
var underrun=audio_prepared_buffers.length==0;
|
||||
var text="buffer";
|
||||
if(overrun) text="overrun";
|
||||
if(underrun) text="underrun";
|
||||
if(overrun) { text="overrun"; console.log("audio overrun, "+(++audio_overrun_cnt).toString()); }
|
||||
if(underrun) { text="underrun"; console.log("audio underrun, "+(++audio_underrun_cnt).toString()); }
|
||||
if(overrun||underrun)
|
||||
{
|
||||
audio_buffer_progressbar_update_disabled=true;
|
||||
@ -1345,13 +1375,26 @@ function webrx_set_param(what, value)
|
||||
ws.send("SET "+what+"="+value.toString());
|
||||
}
|
||||
|
||||
function audio_init()
|
||||
function parsehash()
|
||||
{
|
||||
audio_debug_time_start=(new Date()).getTime();
|
||||
audio_debug_time_last_start=audio_debug_time_start;
|
||||
if(h=window.location.hash)
|
||||
{
|
||||
h.substring(1).split(",").forEach(function(x){
|
||||
harr=x.split("=");
|
||||
console.log(harr);
|
||||
if(harr[0]=="mod") starting_mod = harr[1];
|
||||
if(harr[0]=="freq") {
|
||||
console.log(parseInt(harr[1]));
|
||||
console.log(center_freq);
|
||||
starting_offset_frequency = parseInt(harr[1])-center_freq;
|
||||
}
|
||||
});
|
||||
|
||||
//https://github.com/0xfe/experiments/blob/master/www/tone/js/sinewave.js
|
||||
audio_initialized=1; // only tell on_ws_recv() not to call it again
|
||||
}
|
||||
}
|
||||
|
||||
function audio_preinit()
|
||||
{
|
||||
try
|
||||
{
|
||||
window.AudioContext = window.AudioContext||window.webkitAudioContext;
|
||||
@ -1362,6 +1405,28 @@ function audio_init()
|
||||
divlog('Your browser does not support Web Audio API, which is required for WebRX to run. Please upgrade to a HTML5 compatible browser.', 1);
|
||||
}
|
||||
|
||||
//we send our setup packet
|
||||
|
||||
parsehash();
|
||||
//needs audio_context.sampleRate to exist
|
||||
|
||||
audio_calculate_resampling(audio_context.sampleRate);
|
||||
audio_resampler = new sdrjs.RationalResamplerFF(audio_client_resampling_factor,1);
|
||||
ws.send("SET output_rate="+audio_server_output_rate.toString()+" action=start"); //now we'll get AUD packets as well
|
||||
|
||||
}
|
||||
|
||||
function audio_init()
|
||||
{
|
||||
if(audio_client_resampling_factor==0) return; //if failed to find a valid resampling factor...
|
||||
|
||||
audio_debug_time_start=(new Date()).getTime();
|
||||
audio_debug_time_last_start=audio_debug_time_start;
|
||||
|
||||
//https://github.com/0xfe/experiments/blob/master/www/tone/js/sinewave.js
|
||||
audio_initialized=1; // only tell on_ws_recv() not to call it again
|
||||
|
||||
|
||||
//on Chrome v36, createJavaScriptNode has been replaced by createScriptProcessor
|
||||
createjsnode_function = (audio_context.createJavaScriptNode == undefined)?audio_context.createScriptProcessor.bind(audio_context):audio_context.createJavaScriptNode.bind(audio_context);
|
||||
audio_node = createjsnode_function(audio_buffer_size, 0, 1);
|
||||
@ -1379,7 +1444,14 @@ function audio_init()
|
||||
audio_buffer = audio_context.createBuffer(xhr.response, false);
|
||||
audio_source.buffer = buffer;
|
||||
audio_source.noteOn(0);*/
|
||||
demodulator_analog_replace('nfm'); //needs audio_context.sampleRate to exist
|
||||
demodulator_analog_replace(starting_mod);
|
||||
if(starting_offset_frequency)
|
||||
{
|
||||
demodulators[0].offset_frequency = starting_offset_frequency;
|
||||
demodulators[0].set();
|
||||
mkscale();
|
||||
}
|
||||
|
||||
//hide log panel in a second (if user has not hidden it yet)
|
||||
window.setTimeout(function(){
|
||||
if(typeof e("openwebrx-panel-log").openwebrxHidden == "undefined" && !was_error)
|
||||
|
83
openwebrx.py
83
openwebrx.py
@ -47,7 +47,6 @@ import ctypes
|
||||
#import rtl_mus
|
||||
import rxws
|
||||
import uuid
|
||||
import config_webrx as cfg
|
||||
import signal
|
||||
import socket
|
||||
|
||||
@ -75,11 +74,17 @@ class MultiThreadHTTPServer(ThreadingMixIn, HTTPServer):
|
||||
pass
|
||||
|
||||
def handle_signal(signal, frame):
|
||||
global spectrum_dsp
|
||||
print "[openwebrx] Ctrl+C: aborting."
|
||||
cleanup_clients(True)
|
||||
spectrum_dsp.stop()
|
||||
os._exit(1) #not too graceful exit
|
||||
|
||||
rtl_thread=spectrum_dsp=server_fail=None
|
||||
|
||||
def main():
|
||||
global clients, clients_mutex, pypy, lock_try_time, avatar_ctime
|
||||
global clients, clients_mutex, pypy, lock_try_time, avatar_ctime, cfg
|
||||
global serverfail, rtl_thread
|
||||
print
|
||||
print "OpenWebRX - Open Source SDR Web App for Everyone! | for license see LICENSE file in the package"
|
||||
print "_________________________________________________________________________________________________"
|
||||
@ -87,6 +92,10 @@ def main():
|
||||
print "Author contact info: Andras Retzler, HA7ILM <randras@sdr.hu>"
|
||||
print
|
||||
|
||||
no_arguments=len(sys.argv)==1
|
||||
if no_arguments: print "[openwebrx] Configuration script not specified. I will use: \"config_webrx.py\""
|
||||
cfg=__import__("config_webrx" if no_arguments else sys.argv[1])
|
||||
|
||||
#Set signal handler
|
||||
signal.signal(signal.SIGINT, handle_signal) #http://stackoverflow.com/questions/1112343/how-do-i-capture-sigint-in-python
|
||||
|
||||
@ -108,13 +117,18 @@ def main():
|
||||
|
||||
#Start rtl thread
|
||||
if cfg.start_rtl_thread:
|
||||
rtl_thread=threading.Thread(target = lambda:subprocess.Popen(cfg.start_rtl_command, shell=True), args=())
|
||||
rtl_thread=threading.Thread(target = lambda:subprocess.Popen(cfg.start_rtl_command, shell=True), args=())
|
||||
rtl_thread.start()
|
||||
print "[openwebrx-main] Started rtl thread: "+cfg.start_rtl_command
|
||||
print "[openwebrx-main] Started rtl_thread: "+cfg.start_rtl_command
|
||||
|
||||
#Run rtl_mus.py in a different OS thread
|
||||
python_command="pypy" if pypy else "python2"
|
||||
rtl_mus_thread=threading.Thread(target = lambda:subprocess.Popen(python_command+" rtl_mus.py config_rtl", shell=True), args=())
|
||||
rtl_mus_cmd = python_command+" rtl_mus.py config_rtl"
|
||||
if os.system("ncat --version > /dev/null") != 32512:
|
||||
print "[openwebrx-main] ncat detected, using it instead of rtl_mus:"
|
||||
rtl_mus_cmd = "ncat localhost 8888 | ncat -4l %d -k --send-only --allow 127.0.0.1 " % cfg.iq_server_port
|
||||
print rtl_mus_cmd
|
||||
rtl_mus_thread=threading.Thread(target = lambda:subprocess.Popen(rtl_mus_cmd, shell=True), args=())
|
||||
rtl_mus_thread.start() # The new feature in GNU Radio 3.7: top_block() locks up ALL python threads until it gets the TCP connection.
|
||||
print "[openwebrx-main] Started rtl_mus."
|
||||
time.sleep(1) #wait until it really starts
|
||||
@ -208,9 +222,19 @@ def mutex_watchdog_thread_function():
|
||||
clients_mutex.release()
|
||||
time.sleep(0.5)
|
||||
|
||||
def check_server():
|
||||
global spectrum_dsp, server_fail, rtl_thread
|
||||
if server_fail: return server_fail
|
||||
#print spectrum_dsp.process.poll()
|
||||
if spectrum_dsp and spectrum_dsp.process.poll()!=None: server_fail = "spectrum_thread dsp subprocess failed"
|
||||
#if rtl_thread and not rtl_thread.is_alive(): server_fail = "rtl_thread failed"
|
||||
if server_fail: print "[openwebrx-check_server] >>>>>>> ERROR:", server_fail
|
||||
return server_fail
|
||||
|
||||
def spectrum_thread_function():
|
||||
global clients
|
||||
dsp=getattr(plugins.dsp,cfg.dsp_plugin).plugin.dsp_plugin()
|
||||
global clients, spectrum_dsp
|
||||
spectrum_dsp=dsp=getattr(plugins.dsp,cfg.dsp_plugin).plugin.dsp_plugin()
|
||||
dsp.nc_port=cfg.iq_server_port
|
||||
dsp.set_demodulator("fft")
|
||||
dsp.set_samp_rate(cfg.samp_rate)
|
||||
dsp.set_fft_size(cfg.fft_size)
|
||||
@ -220,6 +244,7 @@ def spectrum_thread_function():
|
||||
sleep_sec=0.87/cfg.fft_fps
|
||||
print "[openwebrx-spectrum] Spectrum thread initialized successfully."
|
||||
dsp.start()
|
||||
dsp.read(8) #dummy read to skip bufsize & preamble
|
||||
print "[openwebrx-spectrum] Spectrum thread started."
|
||||
bytes_to_read=int(dsp.get_fft_bytes_to_read())
|
||||
while True:
|
||||
@ -255,16 +280,17 @@ def get_client_by_id(client_id, use_mutex=True):
|
||||
def log_client(client, what):
|
||||
print "[openwebrx-httpd] client {0}#{1} :: {2}".format(client.ip,client.id,what)
|
||||
|
||||
def cleanup_clients():
|
||||
# if client doesn't open websocket for too long time, we drop it
|
||||
def cleanup_clients(end_all=False):
|
||||
# - if a client doesn't open websocket for too long time, we drop it
|
||||
# - or if end_all is true, we drop all clients
|
||||
global clients
|
||||
cma("cleanup_clients")
|
||||
correction=0
|
||||
for i in range(0,len(clients)):
|
||||
i-=correction
|
||||
#print "cleanup_clients:: len(clients)=", len(clients), "i=", i
|
||||
if (not clients[i].ws_started) and (time.time()-clients[i].gen_time)>45:
|
||||
print "[openwebrx] cleanup_clients :: client timeout to open WebSocket"
|
||||
if end_all or ((not clients[i].ws_started) and (time.time()-clients[i].gen_time)>45):
|
||||
if not end_all: print "[openwebrx] cleanup_clients :: client timeout to open WebSocket"
|
||||
close_client(i, False)
|
||||
correction+=1
|
||||
cmr()
|
||||
@ -363,13 +389,12 @@ class WebRXHandler(BaseHTTPRequestHandler):
|
||||
|
||||
# ========= Initialize DSP =========
|
||||
dsp=getattr(plugins.dsp,cfg.dsp_plugin).plugin.dsp_plugin()
|
||||
dsp.set_samp_rate(cfg.samp_rate)
|
||||
dsp.set_demodulator("nfm")
|
||||
dsp.set_offset_freq(0)
|
||||
dsp.set_bpf(-4000,4000)
|
||||
dsp_initialized=False
|
||||
dsp.set_audio_compression(cfg.audio_compression)
|
||||
dsp.set_format_conversion(cfg.format_conversion)
|
||||
dsp.start()
|
||||
dsp.set_offset_freq(0)
|
||||
dsp.set_bpf(-4000,4000)
|
||||
dsp.nc_port=cfg.iq_server_port
|
||||
myclient.dsp=dsp
|
||||
|
||||
while True:
|
||||
@ -378,8 +403,9 @@ class WebRXHandler(BaseHTTPRequestHandler):
|
||||
break
|
||||
|
||||
# ========= send audio =========
|
||||
temp_audio_data=dsp.read(256)
|
||||
rxws.send(self, temp_audio_data, "AUD ")
|
||||
if dsp_initialized:
|
||||
temp_audio_data=dsp.read(256)
|
||||
rxws.send(self, temp_audio_data, "AUD ")
|
||||
|
||||
# ========= send spectrum =========
|
||||
while not myclient.spectrum_queue.empty():
|
||||
@ -417,9 +443,17 @@ class WebRXHandler(BaseHTTPRequestHandler):
|
||||
dsp.set_offset_freq(int(param_value))
|
||||
elif param_name=="mod":
|
||||
if (dsp.get_demodulator()!=param_value):
|
||||
dsp.stop()
|
||||
if dsp_initialized: dsp.stop()
|
||||
dsp.set_demodulator(param_value)
|
||||
if dsp_initialized: dsp.start()
|
||||
elif param_name == "output_rate":
|
||||
if not dsp_initialized:
|
||||
dsp.set_output_rate(int(param_value))
|
||||
dsp.set_samp_rate(cfg.samp_rate)
|
||||
elif param_name=="action" and param_value=="start":
|
||||
if not dsp_initialized:
|
||||
dsp.start()
|
||||
dsp_initialized=True
|
||||
else:
|
||||
print "[openwebrx-httpd:ws] invalid parameter"
|
||||
if bpf_set:
|
||||
@ -464,6 +498,13 @@ class WebRXHandler(BaseHTTPRequestHandler):
|
||||
data=f.read()
|
||||
extension=self.path[(len(self.path)-4):len(self.path)]
|
||||
extension=extension[2:] if extension[1]=='.' else extension[1:]
|
||||
checkresult=check_server()
|
||||
if extension == "wrx" and checkresult:
|
||||
self.send_response(500)
|
||||
self.send_header('Content-type','text/html')
|
||||
self.end_headers()
|
||||
self.wfile.write("<html><body><h1>OpenWebRX Internal Server Error</h1>Please check the server log for details.</body></html>")
|
||||
return
|
||||
if extension == "wrx" and ((self.headers['user-agent'].count("Chrome")==0 and self.headers['user-agent'].count("Firefox")==0 and (not "Googlebot" in self.headers['user-agent'])) if 'user-agent' in self.headers.keys() else True) and (not request_param.count("unsupported")):
|
||||
self.send_302("upgrade.html")
|
||||
return
|
||||
@ -492,7 +533,9 @@ class WebRXHandler(BaseHTTPRequestHandler):
|
||||
("%[RX_ADMIN]",cfg.receiver_admin),
|
||||
("%[RX_ANT]",cfg.receiver_ant),
|
||||
("%[RX_DEVICE]",cfg.receiver_device),
|
||||
("%[AUDIO_BUFSIZE]",str(cfg.client_audio_buffer_size))
|
||||
("%[AUDIO_BUFSIZE]",str(cfg.client_audio_buffer_size)),
|
||||
("%[START_OFFSET_FREQ]",str(cfg.start_freq-cfg.center_freq)),
|
||||
("%[START_MOD]",cfg.start_mod)
|
||||
)
|
||||
for rule in replace_dictionary:
|
||||
while data.find(rule[0])!=-1:
|
||||
|
@ -44,13 +44,15 @@ class dsp_plugin:
|
||||
self.demodulator = "nfm"
|
||||
self.name = "csdr"
|
||||
self.format_conversion = "csdr convert_u8_f"
|
||||
self.base_bufsize = 512
|
||||
self.nc_port = 4951
|
||||
try:
|
||||
subprocess.Popen("nc",stdout=subprocess.PIPE,stderr=subprocess.PIPE).kill()
|
||||
except:
|
||||
print "[openwebrx-plugin:csdr] error: netcat not found, please install netcat!"
|
||||
|
||||
def chain(self,which):
|
||||
any_chain_base="nc -v localhost 4951 | "+self.format_conversion+(" | " if self.format_conversion!="" else "")+"csdr flowcontrol {flowcontrol} 10 | "
|
||||
any_chain_base="nc -v localhost {nc_port} | csdr setbuf {start_bufsize} | csdr through | "+self.format_conversion+(" | " if self.format_conversion!="" else "") ##"csdr flowcontrol {flowcontrol} auto 1.5 10 | "
|
||||
if which == "fft":
|
||||
fft_chain_base = "sleep 1; "+any_chain_base+"csdr fft_cc {fft_size} {fft_block_size} | csdr logpower_cf -70 | csdr fft_exchange_sides_ff {fft_size}"
|
||||
if self.fft_compression=="adpcm":
|
||||
@ -61,9 +63,9 @@ class dsp_plugin:
|
||||
chain_end = ""
|
||||
if self.audio_compression=="adpcm":
|
||||
chain_end = " | csdr encode_ima_adpcm_i16_u8"
|
||||
if which == "nfm": return chain_begin + "csdr fmdemod_quadri_cf | csdr limit_ff | csdr fractional_decimator_ff {last_decimation} | csdr deemphasis_nfm_ff 11025 | csdr fastagc_ff | csdr convert_f_i16"+chain_end
|
||||
if which == "nfm": return chain_begin + "csdr fmdemod_quadri_cf | csdr limit_ff | csdr fractional_decimator_ff {last_decimation} | csdr deemphasis_nfm_ff 11025 | csdr fastagc_ff 1024 | csdr convert_f_i16"+chain_end
|
||||
elif which == "am": return chain_begin + "csdr amdemod_cf | csdr fastdcblock_ff | csdr fractional_decimator_ff {last_decimation} | csdr agc_ff | csdr limit_ff | csdr convert_f_i16"+chain_end
|
||||
elif which == "ssb": return chain_begin + "csdr realpart_cf | csdr fractional_decimator_ff {last_decimation} | csdr agc_ff | csdr limit_ff | csdr convert_f_i16"+chain_end
|
||||
elif which == "ssb": return chain_begin + "csdr realpart_cf | csdr fractional_decimator_ff {last_decimation} | csdr agc_ff | csdr clipdetect_ff | csdr limit_ff | csdr convert_f_i16"+chain_end
|
||||
|
||||
def set_audio_compression(self,what):
|
||||
self.audio_compression = what
|
||||
@ -92,6 +94,10 @@ class dsp_plugin:
|
||||
def get_output_rate(self):
|
||||
return self.output_rate
|
||||
|
||||
def set_output_rate(self,output_rate):
|
||||
self.output_rate=output_rate
|
||||
self.set_samp_rate(self.samp_rate) #as it depends on output_rate
|
||||
|
||||
def set_demodulator(self,demodulator):
|
||||
#to change this, restart is required
|
||||
self.demodulator=demodulator
|
||||
@ -153,10 +159,16 @@ class dsp_plugin:
|
||||
self.mkfifo(self.shift_pipe)
|
||||
|
||||
#run the command
|
||||
command=command_base.format(bpf_pipe=self.bpf_pipe,shift_pipe=self.shift_pipe,decimation=self.decimation,last_decimation=self.last_decimation,fft_size=self.fft_size,fft_block_size=self.fft_block_size(),bpf_transition_bw=float(self.bpf_transition_bw)/self.if_samp_rate(),ddc_transition_bw=self.ddc_transition_bw(),flowcontrol=int(self.samp_rate*4*2*1.5))
|
||||
command=command_base.format( bpf_pipe=self.bpf_pipe, shift_pipe=self.shift_pipe, decimation=self.decimation, \
|
||||
last_decimation=self.last_decimation, fft_size=self.fft_size, fft_block_size=self.fft_block_size(), \
|
||||
bpf_transition_bw=float(self.bpf_transition_bw)/self.if_samp_rate(), ddc_transition_bw=self.ddc_transition_bw(), \
|
||||
flowcontrol=int(self.samp_rate*2), start_bufsize=self.base_bufsize*self.decimation, nc_port=self.nc_port)
|
||||
|
||||
print "[openwebrx-dsp-plugin:csdr] Command =",command
|
||||
#code.interact(local=locals())
|
||||
self.process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True, preexec_fn=os.setpgrp)
|
||||
my_env=os.environ.copy()
|
||||
my_env["CSDR_DYNAMIC_BUFSIZE_ON"]="1";
|
||||
self.process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True, preexec_fn=os.setpgrp, env=my_env)
|
||||
self.running = True
|
||||
|
||||
#open control pipes for csdr and send initialization data
|
||||
@ -179,14 +191,16 @@ class dsp_plugin:
|
||||
# os.killpg(self.process.pid, signal.SIGTERM)
|
||||
#
|
||||
# time.sleep(0.1)
|
||||
try:
|
||||
os.unlink(self.bpf_pipe)
|
||||
except:
|
||||
print "[openwebrx-dsp-plugin:csdr] stop() :: unlink failed: " + self.bpf_pipe
|
||||
try:
|
||||
os.unlink(self.shift_pipe)
|
||||
except:
|
||||
print "[openwebrx-dsp-plugin:csdr] stop() :: unlink failed: " + self.bpf_pipe
|
||||
if self.bpf_pipe:
|
||||
try:
|
||||
os.unlink(self.bpf_pipe)
|
||||
except:
|
||||
print "[openwebrx-dsp-plugin:csdr] stop() :: unlink failed: " + self.bpf_pipe
|
||||
if self.shift_pipe:
|
||||
try:
|
||||
os.unlink(self.shift_pipe)
|
||||
except:
|
||||
print "[openwebrx-dsp-plugin:csdr] stop() :: unlink failed: " + self.bpf_pipe
|
||||
self.running = False
|
||||
|
||||
def restart(self):
|
||||
|
Loading…
Reference in New Issue
Block a user