From 2408d77f1559221afb67ad9e21ec80a86adb86ec Mon Sep 17 00:00:00 2001 From: Jakob Ketterl Date: Mon, 13 May 2019 19:19:15 +0200 Subject: [PATCH] feature detection for digital voice; display modulator buttons only when available --- htdocs/index.html | 4 ++++ htdocs/openwebrx.js | 5 +++++ owrx/connection.py | 6 ++++++ owrx/feature.py | 47 +++++++++++++++++++++++++++++++++++++++------ 4 files changed, 56 insertions(+), 6 deletions(-) diff --git a/htdocs/index.html b/htdocs/index.html index a223eec..0fa04c4 100644 --- a/htdocs/index.html +++ b/htdocs/index.html @@ -91,12 +91,16 @@
CW
diff --git a/htdocs/openwebrx.js b/htdocs/openwebrx.js index f5b7da8..8610778 100644 --- a/htdocs/openwebrx.js +++ b/htdocs/openwebrx.js @@ -1233,6 +1233,11 @@ function on_ws_recv(evt) return '"; }).join(""); break; + case "features": + for (var feature in json.value) { + $('[data-feature="' + feature + '"')[json.value[feature] ? "show" : "hide"](); + } + break; default: console.warn('received message of unknown type: ' + json.type); } diff --git a/owrx/connection.py b/owrx/connection.py index 95ce84f..346f56d 100644 --- a/owrx/connection.py +++ b/owrx/connection.py @@ -1,5 +1,6 @@ from owrx.config import PropertyManager from owrx.source import DspManager, CpuUsageThread, SdrService, ClientRegistry +from owrx.feature import FeatureDetector import json import logging @@ -33,6 +34,9 @@ class OpenWebRxClient(object): profiles = [{"name": s.getName() + " " + p["name"], "id":sid + "|" + pid} for (sid, s) in SdrService.getSources().items() for (pid, p) in s.getProfiles().items()] self.write_profiles(profiles) + features = FeatureDetector().feature_availability() + self.write_features(features) + CpuUsageThread.getSharedInstance().add_client(self) def sendConfig(self, key, value): @@ -121,6 +125,8 @@ class OpenWebRxClient(object): self.protected_send({"type":"receiver_details","value":details}) def write_profiles(self, profiles): self.protected_send({"type":"profiles","value":profiles}) + def write_features(self, features): + self.protected_send({"type":"features","value":features}) class WebSocketMessageHandler(object): def __init__(self): diff --git a/owrx/feature.py b/owrx/feature.py index 83f9232..457588b 100644 --- a/owrx/feature.py +++ b/owrx/feature.py @@ -1,4 +1,7 @@ import os +import subprocess +from functools import reduce +from operator import and_ import logging logger = logging.getLogger(__name__) @@ -12,9 +15,13 @@ class FeatureDetector(object): "core": [ "csdr", "nmux" ], "rtl_sdr": [ "rtl_sdr" ], "sdrplay": [ "rx_tools" ], - "hackrf": [ "hackrf_transfer" ] + "hackrf": [ "hackrf_transfer" ], + "digital_voice": [ "digiham" ] } + def feature_availability(self): + return {name: self.is_available(name) for name in FeatureDetector.features} + def is_available(self, feature): return self.has_requirements(self.get_requirements(feature)) @@ -34,17 +41,20 @@ class FeatureDetector(object): logger.error("detection of requirement {0} not implement. please fix in code!".format(requirement)) return passed + def command_is_runnable(self, command): + return os.system("{0} 2>/dev/null >/dev/null".format(command)) != 32512 + def has_csdr(self): - return os.system("csdr 2> /dev/null") != 32512 + return self.command_is_runnable("csdr") def has_nmux(self): - return os.system("nmux --help 2> /dev/null") != 32512 + return self.command_is_runnable("nmux --help") def has_rtl_sdr(self): - return os.system("rtl_sdr --help 2> /dev/null") != 32512 + return self.command_is_runnable("rtl_sdr --help") def has_rx_tools(self): - return os.system("rx_sdr --help 2> /dev/null") != 32512 + return self.command_is_runnable("rx_sdr --help") """ To use a HackRF, compile the HackRF host tools from its "stdout" branch: @@ -62,4 +72,29 @@ class FeatureDetector(object): def has_hackrf_transfer(self): # TODO i don't have a hackrf, so somebody doublecheck this. # TODO also check if it has the stdout feature - return os.system("hackrf_transfer --help 2> /dev/null") != 32512 + return self.command_is_runnable("hackrf_transfer --help") + + def command_exists(self, command): + return os.system("which {0}".format(command)) == 0 + + def has_digiham(self): + # the digiham tools expect to be fed via stdin, they will block until their stdin is closed. + def check_with_stdin(command): + try: + process = subprocess.Popen(command, stdin=subprocess.PIPE) + process.communicate("") + return process.wait() == 0 + except FileNotFoundError: + return False + return reduce(and_, + map( + check_with_stdin, + ["rrc_filter", "ysf_decoder", "dmr_decoder", "mbe_synthesizer"] + ), + True) + + def has_dsd(self): + return self.command_is_runnable("dsd") + + def has_sox(self): + return self.command_is_runnable("sox") \ No newline at end of file