├── .dockerignore ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ └── feature_request.md ├── .gitignore ├── CHANGELOG.md ├── LICENSE.txt ├── README.md ├── attic ├── README.md └── docker │ ├── Dockerfiles │ ├── Dockerfile-airspy │ ├── Dockerfile-base │ ├── Dockerfile-bladerf │ ├── Dockerfile-fcdpp │ ├── Dockerfile-full │ ├── Dockerfile-hackrf │ ├── Dockerfile-hpsdr │ ├── Dockerfile-limesdr │ ├── Dockerfile-perseus │ ├── Dockerfile-plutosdr │ ├── Dockerfile-radioberry │ ├── Dockerfile-rtlsdr │ ├── Dockerfile-rtlsdr-soapy │ ├── Dockerfile-rtltcp │ ├── Dockerfile-runds │ ├── Dockerfile-sdrplay │ ├── Dockerfile-soapyremote │ ├── Dockerfile-soapysdr │ └── Dockerfile-uhd │ ├── deb_based │ ├── Dockerfile │ ├── Makefile │ ├── install-owrxp-extra.sh │ └── install-owrxp.sh │ ├── files │ ├── direwolf │ │ └── direwolf-hamlib.patch │ ├── dream │ │ └── dream.patch │ ├── js8call │ │ └── js8call-hamlib.patch │ ├── sdrplay │ │ ├── install-lib.aarch64.patch │ │ ├── install-lib.armv7l.patch │ │ └── install-lib.x86_64.patch │ ├── services │ │ ├── codecserver │ │ │ └── run │ │ └── sdrplay │ │ │ └── run │ └── wsjtx │ │ ├── wsjtx-hamlib.patch │ │ └── wsjtx.patch │ └── scripts │ ├── add-dependencies.sh │ ├── add-owrx-tools.sh │ ├── install-010-dependencies-rtlsdr.sh │ ├── install-020-dependencies-soapysdr.sh │ ├── install-030-dependencies-hackrf.sh │ ├── install-040-dependencies-sdrplay.sh │ ├── install-050-dependencies-airspy.sh │ ├── install-060-dependencies-rtlsdr-soapy.sh │ ├── install-070-dependencies-plutosdr.sh │ ├── install-080-dependencies-limesdr.sh │ ├── install-090-dependencies-soapyremote.sh │ ├── install-100-dependencies-perseus.sh │ ├── install-110-dependencies-fcdpp.sh │ ├── install-120-dependencies-radioberry.sh │ ├── install-130-dependencies-uhd.sh │ ├── install-140-dependencies-hpsdr.sh │ ├── install-150-dependencies-bladerf.sh │ ├── install-500-connectors.sh │ ├── install-510-dependencies-runds.sh │ └── run.sh ├── bands-r1.json ├── bands-r2.json ├── bands-r3.json ├── bands.json ├── bookmarks.d ├── aviation.json ├── cb.json ├── gmrs.json ├── maritime.json ├── misc.json ├── murs.json ├── pmr.json ├── weather.json └── wfax.json ├── bookmarks.json ├── bookmarks.txt ├── buildall.sh ├── config_webrx.py ├── csdr ├── __init__.py ├── chain │ ├── __init__.py │ ├── analog.py │ ├── clientaudio.py │ ├── dablin.py │ ├── demodulator.py │ ├── digiham.py │ ├── digimodes.py │ ├── drm.py │ ├── dummy.py │ ├── fft.py │ ├── freedv.py │ ├── hdradio.py │ ├── m17.py │ ├── selector.py │ └── toolbox.py └── module │ ├── __init__.py │ ├── drm.py │ ├── freedv.py │ ├── hdradio.py │ ├── m17.py │ ├── msk144.py │ ├── nrsc5.py │ └── toolbox.py ├── debian ├── changelog ├── compat ├── control ├── openwebrx.config ├── openwebrx.desktop ├── openwebrx.dirs ├── openwebrx.install ├── openwebrx.postinst ├── openwebrx.postrm ├── openwebrx.svg ├── openwebrx.templates ├── rules └── source │ ├── format │ └── options ├── docker.sh ├── htdocs ├── __init__.py ├── apple-touch-icon.png ├── clients.html ├── css │ ├── admin.css │ ├── bootstrap.min.css │ ├── files.css │ ├── keyboard.min.css │ ├── login.css │ ├── map.css │ ├── openwebrx-globals.css │ ├── openwebrx-header.css │ ├── openwebrx.css │ ├── shortcuts.css │ └── themes.css ├── favicon.ico ├── features.html ├── features.js ├── files.html ├── files.js ├── fonts │ ├── RobotoMono-Regular.ttf │ ├── RobotoMono-Regular.woff │ └── RobotoMono-Regular.woff2 ├── gfx │ ├── adsb-72.png │ ├── audio-file.png │ ├── favicon128.png │ ├── favicon32.png │ ├── favicon44.png │ ├── favicon64.png │ ├── favicon96.png │ ├── openwebrx-avatar.png │ ├── openwebrx-background-cool-blue.png │ ├── openwebrx-background-cool-blue.webp │ ├── openwebrx-directcall.svg │ ├── openwebrx-groupcall.svg │ ├── openwebrx-scale-background.png │ ├── openwebrx-top-photo.jpg │ ├── svg-defs.svg │ └── text-file.png ├── include │ └── header.include.html ├── index.html ├── lib │ ├── AprsMarker.js │ ├── AudioEngine.js │ ├── AudioProcessor.js │ ├── Bandplan.js │ ├── BookmarkBar.js │ ├── BookmarkDialog.js │ ├── BookmarkLocalStorage.js │ ├── Chat.js │ ├── Clock.js │ ├── Demodulator.js │ ├── DemodulatorPanel.js │ ├── FrequencyDisplay.js │ ├── GoogleMaps.js │ ├── Header.js │ ├── Js8Threads.js │ ├── Leaflet.js │ ├── Lookup.js │ ├── MapCalls.js │ ├── MapLocators.js │ ├── MapManager.js │ ├── MapMarkers.js │ ├── Measurement.js │ ├── MessagePanel.js │ ├── MetaPanel.js │ ├── Modes.js │ ├── ProgressBar.js │ ├── Scanner.js │ ├── Shortcuts.js │ ├── Spectrum.js │ ├── UI.js │ ├── Utils.js │ ├── Waterfall.js │ ├── bootstrap.bundle.min.js │ ├── chroma.min.js │ ├── jquery-3.2.1.min.js │ ├── jquery.nanoscroller.min.js │ ├── lame.min.js │ ├── location-picker.min.js │ ├── nanoscroller.css │ ├── nite-overlay.js │ └── settings │ │ ├── BookmarkTable.js │ │ ├── ClientList.js │ │ ├── ExponentialInput.js │ │ ├── GainInput.js │ │ ├── ImageUpload.js │ │ ├── LogMessages.js │ │ ├── MapInput.js │ │ ├── OptionalSection.js │ │ ├── Profiles.js │ │ ├── SchedulerInput.js │ │ ├── WaterfallDropdown.js │ │ └── WsjtDecodingDepthsInput.js ├── login.html ├── map-google.html ├── map-google.js ├── map-leaflet.html ├── map-leaflet.js ├── mstile-144x144.png ├── openwebrx.js ├── plugins.js ├── plugins │ └── receiver │ │ ├── example │ │ └── example.js │ │ ├── example_theme │ │ ├── example_theme.css │ │ └── example_theme.js │ │ ├── init.js.sample │ │ ├── sort_profiles │ │ └── sort_profiles.js │ │ └── utils │ │ └── utils.js ├── policy.html ├── pwchange.html ├── services.html ├── settings.html ├── settings.js └── settings │ ├── bookmarks.html │ └── general.html ├── inkscape files ├── favicon.svg ├── google_maps_pin.svg ├── openwebrx-bookmark.svg ├── openwebrx-directcall.svg ├── openwebrx-edit.svg ├── openwebrx-groupcall.svg ├── openwebrx-logo.svg ├── openwebrx-mute.svg ├── openwebrx-panel-log.svg ├── openwebrx-panel-map.svg ├── openwebrx-panel-receiver.svg ├── openwebrx-panel-settings.svg ├── openwebrx-panel-status.svg ├── openwebrx-play-button.svg ├── openwebrx-rx-details-arrow-down.svg ├── openwebrx-rx-details-arrow-up.svg ├── openwebrx-scanner-running.svg ├── openwebrx-speake-mutedr.svg ├── openwebrx-speaker.svg ├── openwebrx-spectrum.svg ├── openwebrx-squelch.svg ├── openwebrx-trashcan.svg ├── openwebrx-waterfall-auto.svg ├── openwebrx-waterfall-continuous.svg ├── openwebrx-waterfall-default.svg ├── openwebrx-zoom-in-total.svg ├── openwebrx-zoom-in.svg ├── openwebrx-zoom-out-total.svg └── openwebrx-zoom-out.svg ├── makebookmarks.pl ├── openwebrx.conf ├── openwebrx.py ├── owrx ├── __main__.py ├── admin │ ├── __init__.py │ └── commands.py ├── aircraft.py ├── aprs │ ├── __init__.py │ ├── direwolf.py │ └── kiss.py ├── audio │ ├── __init__.py │ ├── chopper.py │ ├── queue.py │ └── wav.py ├── bands.py ├── bookmarks.py ├── breadcrumb.py ├── client.py ├── color.py ├── command.py ├── config │ ├── __init__.py │ ├── classic.py │ ├── commands.py │ ├── core.py │ ├── defaults.py │ ├── dynamic.py │ ├── error.py │ └── migration.py ├── connection.py ├── controllers │ ├── __init__.py │ ├── admin.py │ ├── api.py │ ├── assets.py │ ├── clients.py │ ├── feature.py │ ├── file.py │ ├── imageupload.py │ ├── metrics.py │ ├── profile.py │ ├── receiverid.py │ ├── robots.py │ ├── services.py │ ├── session.py │ ├── settings │ │ ├── __init__.py │ │ ├── backgrounddecoding.py │ │ ├── bookmarks.py │ │ ├── decoding.py │ │ ├── general.py │ │ ├── reporting.py │ │ └── sdr.py │ ├── status.py │ ├── template.py │ └── websocket.py ├── cpu.py ├── details.py ├── dsame3 │ ├── defs.py │ └── dsame.py ├── dsp.py ├── fax.py ├── feature.py ├── fft.py ├── form │ ├── __init__.py │ ├── error.py │ ├── input │ │ ├── __init__.py │ │ ├── aprs.py │ │ ├── converter.py │ │ ├── device.py │ │ ├── gfx.py │ │ ├── location.py │ │ ├── receiverid.py │ │ ├── validator.py │ │ ├── wfm.py │ │ └── wsjt.py │ └── section.py ├── gps.py ├── http.py ├── icao.py ├── js8.py ├── jsons.py ├── locator.py ├── log │ └── __init__.py ├── lookup.py ├── map.py ├── marine.py ├── markers.py ├── meta.py ├── metrics.py ├── modes.py ├── pocsag.py ├── property │ ├── __init__.py │ ├── filter.py │ └── validators.py ├── receiverid.py ├── reporting │ ├── __init__.py │ ├── mqtt.py │ ├── pskreporter.py │ ├── reporter.py │ └── wsprnet.py ├── rigcontrol.py ├── sdr.py ├── service │ ├── __init__.py │ ├── chain.py │ └── schedule.py ├── soapy.py ├── socket.py ├── source │ ├── __init__.py │ ├── afedri.py │ ├── airspy.py │ ├── airspyhf.py │ ├── bladerf.py │ ├── connector.py │ ├── direct.py │ ├── fcdpp.py │ ├── fifi_sdr.py │ ├── hackrf.py │ ├── hpsdr.py │ ├── lime_sdr.py │ ├── mirics.py │ ├── perseussdr.py │ ├── pluto_sdr.py │ ├── radioberry.py │ ├── resampler.py │ ├── rtl_sdr.py │ ├── rtl_sdr_soapy.py │ ├── rtl_tcp.py │ ├── runds.py │ ├── sddc.py │ ├── sdrplay.py │ ├── soapy.py │ ├── soapy_remote.py │ └── uhd.py ├── sstv.py ├── storage.py ├── toolbox.py ├── users.py ├── version.py ├── waterfall.py ├── web │ ├── __init__.py │ ├── eibi.py │ ├── receivers.py │ └── repeaters.py ├── websocket.py └── wsjt.py ├── setup.py ├── systemd └── openwebrx.service └── test ├── __init__.py └── property ├── __init__.py ├── filter ├── __init__.py ├── test_by_lambda.py └── test_by_property_name.py ├── test_property_carousel.py ├── test_property_deletion.py ├── test_property_filter.py ├── test_property_layer.py ├── test_property_readonly.py ├── test_property_stack.py ├── test_property_validator.py └── validators ├── __init__.py ├── test_bool_validator.py ├── test_float_validator.py ├── test_integer_validator.py ├── test_lambda_validator.py ├── test_number_validator.py ├── test_or_validator.py ├── test_regex_validator.py ├── test_string_validator.py └── test_validator.py /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | .gitignore 3 | .idea 4 | **/*.pyc 5 | **/*.swp 6 | black-env 7 | debian -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior. 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Installation method** 20 | How did you install OpenWebRX? (Raspberry Pi SD card image, Debian / Ubuntu packages, Docker image, manually?) 21 | 22 | **Versions** 23 | What version of OpenWebRX are you running? (Check on startup, or see `owrx/version.py`. If a `-dev` version is used, ideally state the commit the issue is appearing on) 24 | 25 | **Log messages** 26 | Are there any relevant messages relating to the bug in the output / log of OpenWebRX? (On most installations, the log should be available using the command `sudo journalctl -u openwebrx`) 27 | 28 | **Additional context** 29 | Add any other context about the problem here. 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: General support request or other project-relasted question 4 | url: https://groups.io/g/openwebrx 5 | about: Request help on the community mailing list 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: feature 6 | assignees: '' 7 | 8 | --- 9 | 10 | Before posting a new feature request, please check if a similar idea has already been listed 11 | * on the issue tracker 12 | * on the [OpenWebRX github project](https://github.com/users/jketterl/projects/1). 13 | 14 | In the latter case, please only proceed if you have additional information about the feature, and please let us know that there's already a card there. 15 | 16 | **Feature description** 17 | Please describe in plain words what functionality you'd like to see in OpenWebRX, and why you think it's useful. 18 | 19 | **Target audience** 20 | Please let us know if you think that this feature is of particular interest for a particular group of users (e.g. hams, SWLs, DXers, ...) 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/*.pyc 2 | **/*.swp 3 | tags 4 | .idea 5 | packages 6 | -------------------------------------------------------------------------------- /attic/README.md: -------------------------------------------------------------------------------- 1 | Keeping old stuff around. 2 | If no one send a request to bring these stuff back, they will be removed. 3 | 4 | -------------------------------------------------------------------------------- /attic/docker/Dockerfiles/Dockerfile-airspy: -------------------------------------------------------------------------------- 1 | ARG ARCHTAG 2 | ARG PROJECT 3 | FROM ${PROJECT}-soapysdr-base:$ARCHTAG 4 | ARG MAKEFLAGS 5 | 6 | COPY docker/scripts/install-dependencies-airspy.sh / 7 | RUN /install-dependencies-airspy.sh &&\ 8 | rm /install-dependencies-airspy.sh 9 | 10 | ADD . /opt/openwebrx 11 | -------------------------------------------------------------------------------- /attic/docker/Dockerfiles/Dockerfile-base: -------------------------------------------------------------------------------- 1 | FROM debian:bullseye-slim 2 | ARG MAKEFLAGS 3 | 4 | COPY docker/files/js8call/js8call-hamlib.patch \ 5 | docker/files/wsjtx/wsjtx.patch \ 6 | docker/files/wsjtx/wsjtx-hamlib.patch \ 7 | docker/files/dream/dream.patch \ 8 | docker/files/direwolf/direwolf-hamlib.patch \ 9 | docker/scripts/add-dependencies.sh / 10 | RUN /add-dependencies.sh && \ 11 | rm /add-dependencies.sh && \ 12 | rm /*.patch 13 | COPY docker/scripts/add-owrx-tools.sh / 14 | RUN /add-owrx-tools.sh && \ 15 | rm /add-owrx-tools.sh 16 | 17 | COPY docker/files/services/codecserver /etc/services.d/codecserver 18 | 19 | ENTRYPOINT ["/init"] 20 | 21 | WORKDIR /opt/openwebrx 22 | 23 | VOLUME /etc/openwebrx 24 | VOLUME /var/lib/openwebrx 25 | 26 | ENV S6_CMD_ARG0="/opt/openwebrx/docker/scripts/run.sh" 27 | CMD [] 28 | 29 | EXPOSE 8073 30 | -------------------------------------------------------------------------------- /attic/docker/Dockerfiles/Dockerfile-bladerf: -------------------------------------------------------------------------------- 1 | ARG ARCHTAG 2 | ARG PROJECT 3 | FROM ${PROJECT}-soapysdr-base:$ARCHTAG 4 | ARG MAKEFLAGS 5 | 6 | COPY docker/scripts/install-dependencies-bladerf.sh / 7 | RUN /install-dependencies-bladerf.sh &&\ 8 | rm /install-dependencies-bladerf.sh 9 | 10 | COPY . /opt/openwebrx 11 | -------------------------------------------------------------------------------- /attic/docker/Dockerfiles/Dockerfile-fcdpp: -------------------------------------------------------------------------------- 1 | ARG ARCHTAG 2 | ARG PROJECT 3 | FROM ${PROJECT}-soapysdr-base:$ARCHTAG 4 | ARG MAKEFLAGS 5 | 6 | COPY docker/scripts/install-dependencies-fcdpp.sh / 7 | RUN /install-dependencies-fcdpp.sh &&\ 8 | rm /install-dependencies-fcdpp.sh 9 | 10 | COPY . /opt/openwebrx 11 | -------------------------------------------------------------------------------- /attic/docker/Dockerfiles/Dockerfile-full: -------------------------------------------------------------------------------- 1 | ARG ARCHTAG 2 | ARG PROJECT 3 | ARG LOCAL_REGISTRY 4 | FROM ${LOCAL_REGISTRY}${PROJECT}-base:$ARCHTAG 5 | ARG MAKEFLAGS 6 | 7 | COPY docker/scripts/install-*.sh \ 8 | docker/files/sdrplay/install-lib.*.patch / 9 | 10 | RUN export FULL_BUILD=1 && \ 11 | for x in $(ls -1 /install-*.sh | sort -n); do \ 12 | echo "installing $x" && \ 13 | $x || exit 1; \ 14 | done && \ 15 | for x in $(ls -1 /install-*.sh | sort -n); do \ 16 | echo "cleaning $x" && \ 17 | $x clean; \ 18 | done && \ 19 | apt-get clean && \ 20 | rm -rf /var/lib/apt/lists/* && \ 21 | rm /install-*.sh && \ 22 | rm /install-lib.*.patch 23 | 24 | COPY docker/files/services/sdrplay /etc/services.d/sdrplay 25 | 26 | COPY docker/scripts/run.sh / 27 | 28 | # this build-arg will reset the cache here, so we will have a fresh copy of the files 29 | ARG GIT_HASH=0 30 | RUN echo "$GIT_HASH" > /build-hash 31 | RUN date > /build-date 32 | RUN date +%s > /build-stamp 33 | 34 | ADD . /opt/openwebrx 35 | -------------------------------------------------------------------------------- /attic/docker/Dockerfiles/Dockerfile-hackrf: -------------------------------------------------------------------------------- 1 | ARG ARCHTAG 2 | ARG PROJECT 3 | FROM ${PROJECT}-soapysdr-base:$ARCHTAG 4 | ARG MAKEFLAGS 5 | 6 | COPY docker/scripts/install-dependencies-hackrf.sh / 7 | RUN /install-dependencies-hackrf.sh &&\ 8 | rm /install-dependencies-hackrf.sh 9 | 10 | COPY . /opt/openwebrx 11 | -------------------------------------------------------------------------------- /attic/docker/Dockerfiles/Dockerfile-hpsdr: -------------------------------------------------------------------------------- 1 | ARG ARCHTAG 2 | ARG PROJECT 3 | FROM ${PROJECT}-base:$ARCHTAG 4 | ARG MAKEFLAGS 5 | 6 | COPY docker/scripts/install-dependencies-hpsdr.sh / 7 | 8 | RUN /install-dependencies-hpsdr.sh &&\ 9 | rm /install-dependencies-hpsdr.sh 10 | 11 | COPY . /opt/openwebrx 12 | -------------------------------------------------------------------------------- /attic/docker/Dockerfiles/Dockerfile-limesdr: -------------------------------------------------------------------------------- 1 | ARG ARCHTAG 2 | ARG PROJECT 3 | FROM ${PROJECT}-soapysdr-base:$ARCHTAG 4 | ARG MAKEFLAGS 5 | 6 | COPY docker/scripts/install-dependencies-limesdr.sh / 7 | RUN /install-dependencies-limesdr.sh &&\ 8 | rm /install-dependencies-limesdr.sh 9 | 10 | COPY . /opt/openwebrx 11 | -------------------------------------------------------------------------------- /attic/docker/Dockerfiles/Dockerfile-perseus: -------------------------------------------------------------------------------- 1 | ARG ARCHTAG 2 | ARG PROJECT 3 | FROM ${PROJECT}-base:$ARCHTAG 4 | ARG MAKEFLAGS 5 | 6 | COPY docker/scripts/install-dependencies-perseus.sh / 7 | RUN /install-dependencies-perseus.sh &&\ 8 | rm /install-dependencies-perseus.sh 9 | 10 | COPY . /opt/openwebrx 11 | -------------------------------------------------------------------------------- /attic/docker/Dockerfiles/Dockerfile-plutosdr: -------------------------------------------------------------------------------- 1 | ARG ARCHTAG 2 | ARG PROJECT 3 | FROM ${PROJECT}-soapysdr-base:$ARCHTAG 4 | ARG MAKEFLAGS 5 | 6 | COPY docker/scripts/install-dependencies-plutosdr.sh / 7 | RUN /install-dependencies-plutosdr.sh &&\ 8 | rm /install-dependencies-plutosdr.sh 9 | 10 | COPY . /opt/openwebrx 11 | -------------------------------------------------------------------------------- /attic/docker/Dockerfiles/Dockerfile-radioberry: -------------------------------------------------------------------------------- 1 | ARG ARCHTAG 2 | ARG PROJECT 3 | FROM ${PROJECT}-soapysdr-base:$ARCHTAG 4 | ARG MAKEFLAGS 5 | 6 | COPY docker/scripts/install-dependencies-radioberry.sh / 7 | RUN /install-dependencies-radioberry.sh &&\ 8 | rm /install-dependencies-radioberry.sh 9 | 10 | COPY . /opt/openwebrx 11 | -------------------------------------------------------------------------------- /attic/docker/Dockerfiles/Dockerfile-rtlsdr: -------------------------------------------------------------------------------- 1 | ARG ARCHTAG 2 | ARG PROJECT 3 | FROM ${PROJECT}-base:$ARCHTAG 4 | ARG MAKEFLAGS 5 | 6 | COPY docker/scripts/install-dependencies-rtlsdr.sh \ 7 | docker/scripts/install-connectors.sh / 8 | 9 | RUN /install-dependencies-rtlsdr.sh &&\ 10 | rm /install-dependencies-rtlsdr.sh &&\ 11 | /install-connectors.sh &&\ 12 | rm /install-connectors.sh 13 | 14 | COPY . /opt/openwebrx 15 | -------------------------------------------------------------------------------- /attic/docker/Dockerfiles/Dockerfile-rtlsdr-soapy: -------------------------------------------------------------------------------- 1 | ARG ARCHTAG 2 | ARG PROJECT 3 | FROM ${PROJECT}-soapysdr-base:$ARCHTAG 4 | ARG MAKEFLAGS 5 | 6 | COPY docker/scripts/install-dependencies-rtlsdr-soapy.sh / 7 | RUN /install-dependencies-rtlsdr-soapy.sh &&\ 8 | rm /install-dependencies-rtlsdr-soapy.sh 9 | 10 | COPY . /opt/openwebrx 11 | -------------------------------------------------------------------------------- /attic/docker/Dockerfiles/Dockerfile-rtltcp: -------------------------------------------------------------------------------- 1 | ARG ARCHTAG 2 | ARG PROJECT 3 | FROM ${PROJECT}-base:$ARCHTAG 4 | ARG MAKEFLAGS 5 | 6 | COPY docker/scripts/install-connectors.sh / 7 | 8 | RUN /install-connectors.sh &&\ 9 | rm /install-connectors.sh 10 | 11 | COPY . /opt/openwebrx 12 | -------------------------------------------------------------------------------- /attic/docker/Dockerfiles/Dockerfile-runds: -------------------------------------------------------------------------------- 1 | ARG ARCHTAG 2 | ARG PROJECT 3 | FROM ${PROJECT}-base:$ARCHTAG 4 | ARG MAKEFLAGS 5 | 6 | COPY docker/scripts/install-connectors.sh \ 7 | docker/scripts/install-dependencies-runds.sh / 8 | 9 | RUN /install-connectors.sh &&\ 10 | rm /install-connectors.sh && \ 11 | /install-dependencies-runds.sh && \ 12 | rm /install-dependencies-runds.sh 13 | 14 | COPY . /opt/openwebrx 15 | -------------------------------------------------------------------------------- /attic/docker/Dockerfiles/Dockerfile-sdrplay: -------------------------------------------------------------------------------- 1 | ARG ARCHTAG 2 | ARG PROJECT 3 | FROM ${PROJECT}-soapysdr-base:$ARCHTAG 4 | ARG MAKEFLAGS 5 | 6 | COPY docker/scripts/install-dependencies-sdrplay.sh \ 7 | docker/files/sdrplay/install-lib.*.patch / 8 | RUN /install-dependencies-sdrplay.sh &&\ 9 | rm /install-dependencies-sdrplay.sh &&\ 10 | rm /install-lib.*.patch 11 | 12 | COPY docker/files/services/sdrplay /etc/services.d/sdrplay 13 | 14 | COPY . /opt/openwebrx 15 | -------------------------------------------------------------------------------- /attic/docker/Dockerfiles/Dockerfile-soapyremote: -------------------------------------------------------------------------------- 1 | ARG ARCHTAG 2 | ARG PROJECT 3 | FROM ${PROJECT}-soapysdr-base:$ARCHTAG 4 | ARG MAKEFLAGS 5 | 6 | COPY docker/scripts/install-dependencies-soapyremote.sh / 7 | RUN /install-dependencies-soapyremote.sh &&\ 8 | rm /install-dependencies-soapyremote.sh 9 | 10 | COPY . /opt/openwebrx 11 | -------------------------------------------------------------------------------- /attic/docker/Dockerfiles/Dockerfile-soapysdr: -------------------------------------------------------------------------------- 1 | ARG ARCHTAG 2 | ARG PROJECT 3 | FROM ${PROJECT}-base:$ARCHTAG 4 | ARG MAKEFLAGS 5 | 6 | COPY docker/scripts/install-dependencies-soapysdr.sh \ 7 | docker/scripts/install-connectors.sh / 8 | RUN /install-dependencies-soapysdr.sh &&\ 9 | rm /install-dependencies-soapysdr.sh &&\ 10 | /install-connectors.sh &&\ 11 | rm /install-connectors.sh 12 | -------------------------------------------------------------------------------- /attic/docker/Dockerfiles/Dockerfile-uhd: -------------------------------------------------------------------------------- 1 | ARG ARCHTAG 2 | ARG PROJECT 3 | FROM ${PROJECT}-soapysdr-base:$ARCHTAG 4 | ARG MAKEFLAGS 5 | 6 | COPY docker/scripts/install-dependencies-uhd.sh / 7 | RUN /install-dependencies-uhd.sh &&\ 8 | rm /install-dependencies-uhd.sh 9 | 10 | COPY . /opt/openwebrx 11 | -------------------------------------------------------------------------------- /attic/docker/deb_based/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:bullseye-slim 2 | ARG VERSION 3 | LABEL OpenWebRX+ with All Receivers and Demodulators 4 | ARG MAKEFLAGS 5 | 6 | ADD docker/files /files 7 | 8 | COPY docker/deb_based/install-owrxp.sh docker/scripts/run.sh / 9 | RUN /install-owrxp.sh 10 | COPY docker/deb_based/install-owrxp-extra.sh / 11 | RUN /install-owrxp-extra.sh 12 | 13 | ENV S6_CMD_ARG0="/run.sh" 14 | ENTRYPOINT ["/init"] 15 | 16 | WORKDIR / 17 | 18 | VOLUME /etc/openwebrx 19 | VOLUME /var/lib/openwebrx 20 | 21 | CMD [] 22 | 23 | EXPOSE 8073 24 | -------------------------------------------------------------------------------- /attic/docker/deb_based/Makefile: -------------------------------------------------------------------------------- 1 | DATE=$(shell date +%F) 2 | all: 3 | @docker build -t openwebrxplus-softmbe:$(DATE) -t openwebrxplus-softmbe . 4 | 5 | run: 6 | @docker run --rm -h openwebrxplus-softmbe --name openwebrxplus-softmbe --device /dev/bus/usb -p 8073:8073 -v openwebrxplus-settings:/var/lib/openwebrx openwebrxplus-softmbe 7 | 8 | admin: 9 | @docker exec -it openwebrxplus-softmbe /usr/bin/openwebrx admin adduser af 10 | 11 | push: 12 | @docker tag openwebrxplus-softmbe:$(DATE) slechev/openwebrxplus-softmbe:$(DATE) 13 | @docker tag openwebrxplus-softmbe:$(DATE) slechev/openwebrxplus-softmbe:latest 14 | @docker push slechev/openwebrxplus-softmbe:$(DATE) 15 | @docker push slechev/openwebrxplus-softmbe 16 | 17 | dev: 18 | @S6_CMD_ARG0=/bin/bash docker run -it --rm -p 8073:8073 --device /dev/bus/usb --name owrxp-build --entrypoint /bin/bash openwebrxplus-softmbe 19 | -------------------------------------------------------------------------------- /attic/docker/deb_based/install-owrxp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | export MAKEFLAGS="-j12" 4 | 5 | case `uname -m` in 6 | arm*) 7 | PLATFORM=armhf 8 | ;; 9 | aarch64*) 10 | PLATFORM=aarch64 11 | ;; 12 | x86_64*) 13 | PLATFORM=amd64 14 | ;; 15 | esac 16 | 17 | echo "+ Init..." 18 | apt update 19 | apt install -y --no-install-recommends wget gpg ca-certificates auto-apt-proxy udev 20 | 21 | echo "+ Install S6 services..." 22 | wget https://github.com/just-containers/s6-overlay/releases/download/v1.21.8.0/s6-overlay-${PLATFORM}.tar.gz 23 | tar xzf s6-overlay-${PLATFORM}.tar.gz -C / 24 | rm s6-overlay-${PLATFORM}.tar.gz 25 | cp -a /files/services/sdrplay /etc/services.d/ 26 | sed -ri 's/^python3 openwebrx.py/openwebrx/' /run.sh 27 | 28 | echo "+ Add repos and update..." 29 | wget -O - https://luarvique.github.io/ppa/openwebrx-plus.gpg | gpg --dearmor -o /etc/apt/trusted.gpg.d/openwebrx-plus.gpg 30 | echo "deb [signed-by=/etc/apt/trusted.gpg.d/openwebrx-plus.gpg] https://luarvique.github.io/ppa/debian ./" > /etc/apt/sources.list.d/openwebrx-plus.list 31 | wget -O - https://repo.openwebrx.de/debian/key.gpg.txt | gpg --dearmor -o /usr/share/keyrings/openwebrx.gpg 32 | echo "deb [signed-by=/usr/share/keyrings/openwebrx.gpg] https://repo.openwebrx.de/debian/ bullseye main" > /etc/apt/sources.list.d/openwebrx.list 33 | apt update 34 | 35 | echo "+ Install OpenWebRX, Soapy modules and some libs..." 36 | DEBIAN_FRONTEND=noninteractive apt install -y openwebrx soapysdr-module-all libsoapysdr-dev libpulse0 libfaad2 libopus0 soapysdr-module-sdrplay3 airspyhf alsa-utils libpopt0 libiio0 libad9361-0 libhidapi-hidraw0 libhidapi-libusb0 dump1090-fa-minimal libliquid2d csdr-eti python3-csdr-eti dablin 37 | -------------------------------------------------------------------------------- /attic/docker/files/direwolf/direwolf-hamlib.patch: -------------------------------------------------------------------------------- 1 | diff --git a/CMakeLists.txt b/CMakeLists.txt 2 | index 9e710f5..da90b43 100644 3 | --- a/CMakeLists.txt 4 | +++ b/CMakeLists.txt 5 | @@ -257,13 +257,8 @@ else() 6 | set(GPSD_LIBRARIES "") 7 | endif() 8 | 9 | -find_package(hamlib) 10 | -if(HAMLIB_FOUND) 11 | - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_HAMLIB") 12 | -else() 13 | - set(HAMLIB_INCLUDE_DIRS "") 14 | - set(HAMLIB_LIBRARIES "") 15 | -endif() 16 | +set(HAMLIB_INCLUDE_DIRS "") 17 | +set(HAMLIB_LIBRARIES "") 18 | 19 | if(LINUX) 20 | find_package(ALSA REQUIRED) 21 | -------------------------------------------------------------------------------- /attic/docker/files/sdrplay/install-lib.armv7l.patch: -------------------------------------------------------------------------------- 1 | diff -ur sdrplay-orig/install_lib.sh sdrplay/install_lib.sh 2 | --- sdrplay-orig/install_lib.sh 2020-05-24 14:13:04.561271707 +0000 3 | +++ sdrplay/install_lib.sh 2020-05-24 14:16:20.068329040 +0000 4 | @@ -4,19 +4,6 @@ 5 | MAJVERS="3" 6 | 7 | echo "Installing SDRplay RSP API library ${VERS}..." 8 | -read -p "Press RETURN to view the license agreement" ret 9 | - 10 | -more sdrplay_license.txt 11 | - 12 | -while true; do 13 | - echo "Press y and RETURN to accept the license agreement and continue with" 14 | - read -p "the installation, or press n and RETURN to exit the installer [y/n] " yn 15 | - case $yn in 16 | - [Yy]* ) break;; 17 | - [Nn]* ) exit;; 18 | - * ) echo "Please answer y or n";; 19 | - esac 20 | -done 21 | 22 | ARCH=`uname -m` 23 | 24 | @@ -141,16 +128,6 @@ 25 | echo "SDRplay API ${VERS} Installation Finished" 26 | echo " " 27 | 28 | -while true; do 29 | - echo "Would you like to add SDRplay USB IDs to the local database for easier 30 | -" 31 | - read -p "identification in applications such as lsusb? [y/n] " yn 32 | - case $yn in 33 | - [Yy]* ) break;; 34 | - [Nn]* ) exit;; 35 | - * ) echo "Please answer y or n";; 36 | - esac 37 | -done 38 | sudo cp scripts/sdrplay_usbids.sh ${INSTALLBINDIR}/. 39 | sudo chmod 755 ${INSTALLBINDIR}/sdrplay_usbids.sh 40 | sudo cp scripts/sdrplay_ids.txt ${INSTALLBINDIR}/. 41 | -------------------------------------------------------------------------------- /attic/docker/files/services/codecserver/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/execlineb -P 2 | /usr/local/bin/codecserver -------------------------------------------------------------------------------- /attic/docker/files/services/sdrplay/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/execlineb -P 2 | /usr/local/bin/sdrplay_apiService -------------------------------------------------------------------------------- /attic/docker/files/wsjtx/wsjtx-hamlib.patch: -------------------------------------------------------------------------------- 1 | --- CMakeLists.txt.orig 2021-09-28 14:33:14.329598412 +0200 2 | +++ CMakeLists.txt 2021-09-28 14:34:23.052345270 +0200 3 | @@ -106,24 +106,6 @@ 4 | 5 | 6 | # 7 | -# build and install hamlib locally so it can be referenced by the 8 | -# WSJT-X build 9 | -# 10 | -ExternalProject_Add (hamlib 11 | - GIT_REPOSITORY ${hamlib_repo} 12 | - GIT_TAG ${hamlib_TAG} 13 | - GIT_SHALLOW False 14 | - URL ${CMAKE_CURRENT_SOURCE_DIR}/src/${__hamlib_upstream}.tar.gz 15 | - URL_HASH MD5=${hamlib_md5sum} 16 | - #UPDATE_COMMAND ${CMAKE_COMMAND} -E env "[ -f ./bootstrap ] && ./bootstrap" 17 | - PATCH_COMMAND ${PATCH_EXECUTABLE} -p1 -N < ${CMAKE_CURRENT_SOURCE_DIR}/hamlib.patch 18 | - CONFIGURE_COMMAND /configure --prefix= --disable-shared --enable-static --without-cxx-binding ${EXTRA_FLAGS} # LIBUSB_LIBS=${USB_LIBRARY} 19 | - BUILD_COMMAND $(MAKE) all V=1 # $(MAKE) is ExternalProject_Add() magic to do recursive make 20 | - INSTALL_COMMAND $(MAKE) install-strip V=1 DESTDIR="" 21 | - STEP_TARGETS update install 22 | - ) 23 | - 24 | -# 25 | # custom target to make a hamlib source tarball 26 | # 27 | add_custom_target (hamlib_sources 28 | @@ -161,7 +143,6 @@ 29 | # build and optionally install WSJT-X using the hamlib package built 30 | # above 31 | # 32 | -ExternalProject_Get_Property (hamlib INSTALL_DIR) 33 | ExternalProject_Add (wsjtx 34 | GIT_REPOSITORY ${wsjtx_repo} 35 | GIT_TAG ${WSJTX_TAG} 36 | @@ -186,14 +167,8 @@ 37 | DEPENDEES build 38 | ) 39 | 40 | -set_target_properties (hamlib PROPERTIES EXCLUDE_FROM_ALL 1) 41 | set_target_properties (wsjtx PROPERTIES EXCLUDE_FROM_ALL 1) 42 | 43 | -add_dependencies (wsjtx-configure hamlib-install) 44 | -add_dependencies (wsjtx-build hamlib-install) 45 | -add_dependencies (wsjtx-install hamlib-install) 46 | -add_dependencies (wsjtx-package hamlib-install) 47 | - 48 | # export traditional targets 49 | add_custom_target (build ALL DEPENDS wsjtx-build) 50 | add_custom_target (install DEPENDS wsjtx-install) 51 | -------------------------------------------------------------------------------- /attic/docker/scripts/add-owrx-tools.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | function cmakebuild() { 5 | cd $1 6 | if [[ ! -z "${2:-}" ]]; then 7 | git checkout $2 8 | fi 9 | mkdir build 10 | cd build 11 | cmake ${CMAKE_ARGS:-} .. 12 | make 13 | make install 14 | cd ../.. 15 | rm -rf $1 16 | } 17 | 18 | cd /tmp 19 | 20 | STATIC_PACKAGES="libfftw3-bin libprotobuf23 libsamplerate0 libicu67 libudev1" 21 | BUILD_PACKAGES="git autoconf automake libtool libfftw3-dev pkg-config cmake make gcc g++ libprotobuf-dev protobuf-compiler libsamplerate-dev libicu-dev libpython3-dev libudev-dev" 22 | apt-get update 23 | apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES 24 | 25 | git clone https://github.com/jketterl/js8py.git 26 | pushd js8py 27 | # latest develop as of 2022-11-30 (structured callsign data) 28 | #git checkout f7e394b7892d26cbdcce5d43c0b4081a2a6a48f6 29 | git checkout 0.1.2 30 | python3 setup.py install 31 | popd 32 | rm -rf js8py 33 | 34 | git clone https://github.com/luarvique/csdr.git 35 | cmakebuild csdr master 36 | 37 | git clone https://github.com/luarvique/pycsdr.git 38 | cd pycsdr 39 | git checkout master 40 | ./setup.py install install_headers 41 | cd .. 42 | rm -rf pycsdr 43 | 44 | git clone https://github.com/jketterl/codecserver.git 45 | mkdir -p /usr/local/etc/codecserver 46 | cp codecserver/conf/codecserver.conf /usr/local/etc/codecserver 47 | cmakebuild codecserver 0.2.0 48 | 49 | git clone https://github.com/jketterl/digiham.git 50 | cmakebuild digiham 0.6.1 51 | 52 | git clone https://github.com/jketterl/pydigiham.git 53 | cd pydigiham 54 | git checkout 0.6.1 55 | ./setup.py install 56 | cd .. 57 | rm -rf pydigiham 58 | 59 | git clone https://github.com/luarvique/csdr-eti.git 60 | cmakebuild csdr-eti 61 | 62 | git clone https://github.com/luarvique/pycsdr-eti.git 63 | cd pycsdr-eti 64 | ./setup.py install install_headers 65 | cd .. 66 | rm -rf pycsdr-eti 67 | 68 | apt-get -y purge --autoremove $BUILD_PACKAGES 69 | apt-get clean 70 | rm -rf /var/lib/apt/lists/* 71 | -------------------------------------------------------------------------------- /attic/docker/scripts/install-010-dependencies-rtlsdr.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | function cmakebuild() { 5 | cd $1 6 | if [[ ! -z "${2:-}" ]]; then 7 | git checkout $2 8 | fi 9 | mkdir build 10 | cd build 11 | cmake .. 12 | make 13 | make install 14 | cd ../.. 15 | rm -rf $1 16 | } 17 | 18 | cd /tmp 19 | 20 | STATIC_PACKAGES="libusb-1.0.0" 21 | BUILD_PACKAGES="git libusb-1.0.0-dev cmake make gcc g++ pkg-config libtool" 22 | 23 | if [[ -z ${1:-} ]]; then 24 | apt-get update 25 | apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES 26 | 27 | git clone https://github.com/osmocom/rtl-sdr.git 28 | # release 2.0.1 from master as of 2024-02-04 29 | cmakebuild rtl-sdr 420086af84d7eaaf98ff948cd11fea2cae71734a 30 | 31 | git clone https://github.com/merbanan/rtl_433.git 32 | cd rtl_433 33 | mkdir build 34 | cd build 35 | cmake .. -DENABLE_SOAPYSDR=AUTO -DENABLE_RTLSDR=AUTO 36 | make 37 | make install 38 | cd ../../ 39 | rm -rf rtl_433 40 | fi 41 | 42 | if [[ -z ${FULL_BUILD:-} || ${1:-} == 'clean' ]]; then 43 | echo "Cleaning from $0" 44 | apt-get -y purge --autoremove $BUILD_PACKAGES 45 | if [[ -z ${FULL_BUILD:-} ]]; then 46 | apt-get clean 47 | rm -rf /var/lib/apt/lists/* 48 | fi 49 | fi 50 | -------------------------------------------------------------------------------- /attic/docker/scripts/install-020-dependencies-soapysdr.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | function cmakebuild() { 5 | cd $1 6 | if [[ ! -z "${2:-}" ]]; then 7 | git checkout $2 8 | fi 9 | mkdir build 10 | cd build 11 | cmake .. 12 | make 13 | make install 14 | cd ../.. 15 | rm -rf $1 16 | } 17 | 18 | cd /tmp 19 | 20 | STATIC_PACKAGES="libudev1" 21 | BUILD_PACKAGES="git cmake make patch wget sudo gcc g++ libtool" 22 | 23 | if [[ -z ${1:-} ]]; then 24 | apt-get update 25 | apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES 26 | 27 | git clone https://github.com/pothosware/SoapySDR 28 | # latest from master as of 2020-09-04 29 | cmakebuild SoapySDR 580b94f3dad46899f34ec0a060dbb4534e844e57 30 | 31 | git clone https://github.com/merbanan/rtl_433.git 32 | cd rtl_433 33 | mkdir build 34 | cd build 35 | cmake .. -DENABLE_SOAPYSDR=AUTO -DENABLE_RTLSDR=AUTO 36 | make 37 | make install 38 | cd ../../ 39 | rm -rf rtl_433 40 | fi 41 | 42 | if [[ -z ${FULL_BUILD:-} || ${1:-} == 'clean' ]]; then 43 | echo "Cleaning from $0" 44 | SUDO_FORCE_REMOVE=yes apt-get -y purge --autoremove $BUILD_PACKAGES 45 | if [[ -z ${FULL_BUILD:-} ]]; then 46 | apt-get clean 47 | rm -rf /var/lib/apt/lists/* 48 | fi 49 | fi 50 | -------------------------------------------------------------------------------- /attic/docker/scripts/install-030-dependencies-hackrf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | function cmakebuild() { 5 | cd $1 6 | if [[ ! -z "${2:-}" ]]; then 7 | git checkout $2 8 | fi 9 | mkdir build 10 | cd build 11 | cmake .. 12 | make 13 | make install 14 | cd ../.. 15 | rm -rf $1 16 | } 17 | 18 | cd /tmp 19 | 20 | STATIC_PACKAGES="libusb-1.0-0 libfftw3-3 udev" 21 | BUILD_PACKAGES="git cmake make patch wget sudo gcc g++ libusb-1.0-0-dev libfftw3-dev pkg-config" 22 | 23 | if [[ -z ${1:-} ]]; then 24 | apt-get update 25 | apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES 26 | 27 | git clone https://github.com/mossmann/hackrf.git 28 | cd hackrf 29 | # latest from master as of 2020-09-04 30 | git checkout 6e5cbda2945c3bab0e6e1510eae418eda60c358e 31 | cmakebuild host 32 | cd .. 33 | rm -rf hackrf 34 | 35 | git clone https://github.com/pothosware/SoapyHackRF.git 36 | # latest from master as of 2020-09-04 37 | cmakebuild SoapyHackRF 7d530872f96c1cbe0ed62617c32c48ce7e103e1d 38 | fi 39 | 40 | if [[ -z ${FULL_BUILD:-} || ${1:-} == 'clean' ]]; then 41 | echo "Cleaning from $0" 42 | SUDO_FORCE_REMOVE=yes apt-get -y purge --autoremove $BUILD_PACKAGES 43 | if [[ -z ${FULL_BUILD:-} ]]; then 44 | apt-get clean 45 | rm -rf /var/lib/apt/lists/* 46 | fi 47 | fi 48 | -------------------------------------------------------------------------------- /attic/docker/scripts/install-040-dependencies-sdrplay.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | function cmakebuild() { 5 | cd $1 6 | if [[ ! -z "${2:-}" ]]; then 7 | git checkout $2 8 | fi 9 | mkdir build 10 | cd build 11 | cmake .. 12 | make 13 | make install 14 | cd ../.. 15 | rm -rf $1 16 | } 17 | 18 | cd /tmp 19 | 20 | STATIC_PACKAGES="libusb-1.0.0 udev" 21 | BUILD_PACKAGES="git cmake make patch wget sudo gcc g++ libusb-1.0-0-dev" 22 | 23 | if [[ -z ${1:-} ]]; then 24 | apt-get update 25 | apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES 26 | 27 | ARCH=$(uname -m) 28 | 29 | case $ARCH in 30 | x86_64) 31 | #BINARY=SDRplay_RSP_API-Linux-3.07.1.run 32 | BINARY=SDRplay_RSP_API-Linux-3.14.0.run 33 | BRANCH=master 34 | ;; 35 | armv*) 36 | BINARY=SDRplay_RSP_API-ARM32-3.07.2.run 37 | BRANCH=0.8.7 38 | ;; 39 | aarch64) 40 | #BINARY=SDRplay_RSP_API-ARM64-3.07.1.run 41 | BINARY=SDRplay_RSP_API-Linux-3.14.0.run 42 | BRANCH=master 43 | ;; 44 | esac 45 | 46 | wget --no-http-keep-alive https://www.sdrplay.com/software/$BINARY 47 | sh $BINARY --noexec --target sdrplay 48 | patch --verbose -Np0 < /install-lib.$ARCH.patch 49 | 50 | cd sdrplay 51 | ./install_lib.sh 52 | cd .. 53 | rm -rf sdrplay 54 | rm $BINARY 55 | mkdir -p /usr/local/bin 56 | mv /opt/sdrplay_api/sdrplay_apiService /usr/local/bin/ || true 57 | 58 | #git clone https://github.com/pothosware/SoapySDRPlay3.git 59 | # latest from master as of 2021-06-19 (reliability fixes) 60 | #cmakebuild SoapySDRPlay3 a869f25364a1f0d5b16169ff908aa21a2ace475d 61 | git clone https://github.com/luarvique/SoapySDRPlay3 62 | cmakebuild SoapySDRPlay3 $BRANCH 63 | fi 64 | 65 | if [[ -z ${FULL_BUILD:-} || ${1:-} == 'clean' ]]; then 66 | echo "Cleaning from $0" 67 | SUDO_FORCE_REMOVE=yes apt-get -y purge --autoremove $BUILD_PACKAGES 68 | if [[ -z ${FULL_BUILD:-} ]]; then 69 | apt-get clean 70 | rm -rf /var/lib/apt/lists/* 71 | fi 72 | fi 73 | -------------------------------------------------------------------------------- /attic/docker/scripts/install-050-dependencies-airspy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | function cmakebuild() { 5 | cd $1 6 | if [[ ! -z "${2:-}" ]]; then 7 | git checkout $2 8 | fi 9 | mkdir build 10 | cd build 11 | cmake .. 12 | make 13 | make install 14 | cd ../.. 15 | rm -rf $1 16 | } 17 | 18 | cd /tmp 19 | 20 | STATIC_PACKAGES="libusb-1.0-0" 21 | BUILD_PACKAGES="git libusb-1.0-0-dev cmake make gcc g++ pkg-config" 22 | 23 | if [[ -z ${1:-} ]]; then 24 | apt-get update 25 | apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES 26 | 27 | git clone https://github.com/airspy/airspyone_host.git 28 | # latest from master as of 2020-09-04 29 | cmakebuild airspyone_host 652fd7f1a8f85687641e0bd91f739694d7258ecc 30 | 31 | git clone https://github.com/pothosware/SoapyAirspy.git 32 | cmakebuild SoapyAirspy 10d697b209e7f1acc8b2c8d24851d46170ef77e3 33 | 34 | git clone https://github.com/airspy/airspyhf.git 35 | # latest from master as of 2020-09-04 36 | cmakebuild airspyhf 8891387edddcd185e2949e9814e9ef35f46f0722 37 | 38 | git clone https://github.com/pothosware/SoapyAirspyHF.git 39 | # latest from master as of 2020-09-04 40 | cmakebuild SoapyAirspyHF 5488dac5b44f1432ce67b40b915f7e61d3bd4853 41 | fi 42 | 43 | if [[ -z ${FULL_BUILD:-} || ${1:-} == 'clean' ]]; then 44 | echo "Cleaning from $0" 45 | apt-get -y purge --autoremove $BUILD_PACKAGES 46 | if [[ -z ${FULL_BUILD:-} ]]; then 47 | apt-get clean 48 | rm -rf /var/lib/apt/lists/* 49 | fi 50 | fi 51 | -------------------------------------------------------------------------------- /attic/docker/scripts/install-060-dependencies-rtlsdr-soapy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | function cmakebuild() { 5 | cd $1 6 | if [[ ! -z "${2:-}" ]]; then 7 | git checkout $2 8 | fi 9 | mkdir build 10 | cd build 11 | cmake .. 12 | make 13 | make install 14 | cd ../.. 15 | rm -rf $1 16 | } 17 | 18 | cd /tmp 19 | 20 | STATIC_PACKAGES="libusb-1.0-0" 21 | BUILD_PACKAGES="git libusb-1.0-0-dev cmake make gcc g++ pkg-config" 22 | 23 | if [[ -z ${1:-} ]]; then 24 | apt-get update 25 | apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES 26 | 27 | git clone https://github.com/osmocom/rtl-sdr.git 28 | # release 2.0.1 from master as of 2024-02-04 29 | cmakebuild rtl-sdr 420086af84d7eaaf98ff948cd11fea2cae71734a 30 | 31 | git clone https://github.com/pothosware/SoapyRTLSDR.git 32 | cmakebuild SoapyRTLSDR soapy-rtl-sdr-0.3.1 33 | fi 34 | 35 | if [[ -z ${FULL_BUILD:-} || ${1:-} == 'clean' ]]; then 36 | echo "Cleaning from $0" 37 | apt-get -y purge --autoremove $BUILD_PACKAGES 38 | if [[ -z ${FULL_BUILD:-} ]]; then 39 | apt-get clean 40 | rm -rf /var/lib/apt/lists/* 41 | fi 42 | fi 43 | -------------------------------------------------------------------------------- /attic/docker/scripts/install-070-dependencies-plutosdr.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | function cmakebuild() { 5 | cd $1 6 | if [[ ! -z "${2:-}" ]]; then 7 | git checkout $2 8 | fi 9 | mkdir build 10 | cd build 11 | cmake .. ${3:-} 12 | make 13 | make install 14 | cd ../.. 15 | rm -rf $1 16 | } 17 | 18 | cd /tmp 19 | 20 | STATIC_PACKAGES="libusb-1.0-0 libxml2" 21 | BUILD_PACKAGES="git libusb-1.0-0-dev cmake make gcc g++ libxml2-dev flex bison pkg-config" 22 | 23 | if [[ -z ${1:-} ]]; then 24 | apt-get update 25 | apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES 26 | 27 | git clone https://github.com/analogdevicesinc/libiio.git 28 | cmakebuild libiio v0.21 -DCMAKE_INSTALL_PREFIX=/usr/local 29 | 30 | git clone https://github.com/analogdevicesinc/libad9361-iio.git 31 | cmakebuild libad9361-iio v0.2 32 | 33 | git clone https://github.com/pothosware/SoapyPlutoSDR.git 34 | # latest from master as of 2020-09-04 35 | cmakebuild SoapyPlutoSDR 93717b32ef052e0dfa717aa2c1a4eb27af16111f 36 | fi 37 | 38 | if [[ -z ${FULL_BUILD:-} || ${1:-} == 'clean' ]]; then 39 | echo "Cleaning from $0" 40 | apt-get -y purge --autoremove $BUILD_PACKAGES 41 | if [[ -z ${FULL_BUILD:-} ]]; then 42 | apt-get clean 43 | rm -rf /var/lib/apt/lists/* 44 | fi 45 | fi 46 | -------------------------------------------------------------------------------- /attic/docker/scripts/install-080-dependencies-limesdr.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | cd /tmp 5 | 6 | STATIC_PACKAGES="libusb-1.0-0 libatomic1" 7 | BUILD_PACKAGES="git libusb-1.0-0-dev cmake make gcc g++" 8 | 9 | if [[ -z ${1:-} ]]; then 10 | apt-get update 11 | apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES 12 | 13 | SIMD_FLAGS="" 14 | if [[ 'x86_64' == `uname -m` ]] ; then 15 | SIMD_FLAGS="-DDEFAULT_SIMD_FLAGS=SSE3" 16 | fi 17 | 18 | git clone https://github.com/myriadrf/LimeSuite.git 19 | cd LimeSuite 20 | # latest from master as of 2020-09-04 21 | git checkout 9526621f8b4c9e2a7f638b5ef50c45560dcad22a 22 | mkdir builddir 23 | cd builddir 24 | cmake .. -DENABLE_EXAMPLES=OFF -DENABLE_DESKTOP=OFF -DENABLE_LIME_UTIL=OFF -DENABLE_QUICKTEST=OFF -DENABLE_OCTAVE=OFF -DENABLE_GUI=OFF -DCMAKE_CXX_STANDARD_LIBRARIES="-latomic" ${SIMD_FLAGS} 25 | make 26 | make install 27 | cd ../.. 28 | rm -rf LimeSuite 29 | fi 30 | 31 | if [[ -z ${FULL_BUILD:-} || ${1:-} == 'clean' ]]; then 32 | echo "Cleaning from $0" 33 | apt-get -y purge --autoremove $BUILD_PACKAGES 34 | if [[ -z ${FULL_BUILD:-} ]]; then 35 | apt-get clean 36 | rm -rf /var/lib/apt/lists/* 37 | fi 38 | fi 39 | -------------------------------------------------------------------------------- /attic/docker/scripts/install-090-dependencies-soapyremote.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | function cmakebuild() { 5 | cd $1 6 | if [[ ! -z "${2:-}" ]]; then 7 | git checkout $2 8 | fi 9 | mkdir build 10 | cd build 11 | cmake .. 12 | make 13 | make install 14 | cd ../.. 15 | rm -rf $1 16 | } 17 | 18 | cd /tmp 19 | 20 | STATIC_PACKAGES="avahi-daemon libavahi-client3" 21 | BUILD_PACKAGES="git cmake make gcc g++ libavahi-client-dev" 22 | 23 | if [[ -z ${1:-} ]]; then 24 | apt-get update 25 | apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES 26 | 27 | git clone https://github.com/pothosware/SoapyRemote.git 28 | cmakebuild SoapyRemote soapy-remote-0.5.2 29 | fi 30 | 31 | if [[ -z ${FULL_BUILD:-} || ${1:-} == 'clean' ]]; then 32 | echo "Cleaning from $0" 33 | apt-get -y purge --autoremove $BUILD_PACKAGES 34 | if [[ -z ${FULL_BUILD:-} ]]; then 35 | apt-get clean 36 | rm -rf /var/lib/apt/lists/* 37 | fi 38 | fi 39 | -------------------------------------------------------------------------------- /attic/docker/scripts/install-100-dependencies-perseus.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euxo pipefail 3 | 4 | cd /tmp 5 | 6 | STATIC_PACKAGES="libusb-1.0-0 libudev1" 7 | BUILD_PACKAGES="git make gcc autoconf automake libtool libusb-1.0-0-dev xxd" 8 | 9 | export MARCH=native 10 | case `uname -m` in 11 | x86_64*) 12 | export MARCH=x86-64 13 | ;; 14 | esac 15 | 16 | 17 | 18 | if [[ -z ${1:-} ]]; then 19 | apt-get update 20 | apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES 21 | 22 | git clone https://github.com/Microtelecom/libperseus-sdr.git 23 | cd libperseus-sdr 24 | # latest from master as of 2020-09-04 25 | git checkout c2c95daeaa08bf0daed0e8ada970ab17cc264e1b 26 | sed -i 's/-march=native/-march='${MARCH}'/g' configure.ac 27 | ./bootstrap.sh 28 | ./configure 29 | make 30 | make install 31 | ldconfig /etc/ld.so.conf.d 32 | cd .. 33 | rm -rf libperseus-sdr 34 | fi 35 | 36 | if [[ -z ${FULL_BUILD:-} || ${1:-} == 'clean' ]]; then 37 | echo "Cleaning from $0" 38 | apt-get -y purge --autoremove $BUILD_PACKAGES 39 | if [[ -z ${FULL_BUILD:-} ]]; then 40 | apt-get clean 41 | rm -rf /var/lib/apt/lists/* 42 | fi 43 | fi 44 | -------------------------------------------------------------------------------- /attic/docker/scripts/install-110-dependencies-fcdpp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | function cmakebuild() { 5 | cd $1 6 | if [[ ! -z "${2:-}" ]]; then 7 | git checkout $2 8 | fi 9 | mkdir build 10 | cd build 11 | cmake .. 12 | make 13 | make install 14 | cd ../.. 15 | rm -rf $1 16 | } 17 | 18 | cd /tmp 19 | 20 | STATIC_PACKAGES="libhidapi-hidraw0 libhidapi-libusb0 libasound2" 21 | BUILD_PACKAGES="git cmake make gcc g++ libhidapi-dev libasound2-dev" 22 | 23 | if [[ -z ${1:-} ]]; then 24 | apt-get update 25 | apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES 26 | 27 | git clone https://github.com/pothosware/SoapyFCDPP.git 28 | cmakebuild SoapyFCDPP soapy-fcdpp-0.1.1 29 | fi 30 | 31 | if [[ -z ${FULL_BUILD:-} || ${1:-} == 'clean' ]]; then 32 | echo "Cleaning from $0" 33 | apt-get -y purge --autoremove $BUILD_PACKAGES 34 | if [[ -z ${FULL_BUILD:-} ]]; then 35 | apt-get clean 36 | rm -rf /var/lib/apt/lists/* 37 | fi 38 | fi 39 | -------------------------------------------------------------------------------- /attic/docker/scripts/install-120-dependencies-radioberry.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | function cmakebuild() { 5 | cd $1 6 | if [[ ! -z "${2:-}" ]]; then 7 | git checkout $2 8 | fi 9 | mkdir build 10 | cd build 11 | cmake .. 12 | make 13 | make install 14 | cd ../.. 15 | rm -rf $1 16 | } 17 | 18 | cd /tmp 19 | 20 | STATIC_PACKAGES="libusb-1.0-0 libfftw3-3 udev" 21 | BUILD_PACKAGES="git cmake make patch wget sudo gcc g++ libusb-1.0-0-dev libfftw3-dev pkg-config" 22 | 23 | if [[ -z ${1:-} ]]; then 24 | apt-get update 25 | apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES 26 | 27 | git clone https://github.com/pa3gsb/Radioberry-2.x 28 | cd Radioberry-2.x/SBC/rpi-4 29 | 30 | # latest from master as of 2020-09-04 31 | cmakebuild SoapyRadioberrySDR 8d17de6b4dc076e628900a82f05c7cf0b16cbe24 32 | cd ../../.. 33 | rm -rf Radioberry-2.x 34 | fi 35 | 36 | if [[ -z ${FULL_BUILD:-} || ${1:-} == 'clean' ]]; then 37 | echo "Cleaning from $0" 38 | SUDO_FORCE_REMOVE=yes apt-get -y purge --autoremove $BUILD_PACKAGES 39 | if [[ -z ${FULL_BUILD:-} ]]; then 40 | apt-get clean 41 | rm -rf /var/lib/apt/lists/* 42 | fi 43 | fi 44 | -------------------------------------------------------------------------------- /attic/docker/scripts/install-140-dependencies-hpsdr.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | BUILD_PACKAGES="git wget gcc libc6-dev" 5 | 6 | if [[ -z ${1:-} ]]; then 7 | apt-get update 8 | apt-get -y install --no-install-recommends $BUILD_PACKAGES 9 | 10 | pushd /tmp 11 | 12 | ARCH=$(uname -m) 13 | GOVERSION=1.15.5 14 | 15 | case ${ARCH} in 16 | x86_64) 17 | PACKAGE=go${GOVERSION}.linux-amd64.tar.gz 18 | ;; 19 | armv*) 20 | PACKAGE=go${GOVERSION}.linux-armv6l.tar.gz 21 | ;; 22 | aarch64) 23 | PACKAGE=go${GOVERSION}.linux-arm64.tar.gz 24 | ;; 25 | esac 26 | 27 | wget https://golang.org/dl/${PACKAGE} 28 | tar xfz $PACKAGE 29 | 30 | git clone https://github.com/jancona/hpsdrconnector.git 31 | pushd hpsdrconnector 32 | git checkout v0.6.1 33 | /tmp/go/bin/go build 34 | install -m 0755 hpsdrconnector /usr/local/bin 35 | popd 36 | 37 | rm -rf hpsdrconnector 38 | rm -rf go 39 | rm -rf ~/go ~/.cache 40 | rm $PACKAGE 41 | fi 42 | 43 | if [[ -z ${FULL_BUILD:-} || ${1:-} == 'clean' ]]; then 44 | echo "Cleaning from $0" 45 | apt-get -y purge --autoremove $BUILD_PACKAGES 46 | if [[ -z ${FULL_BUILD:-} ]]; then 47 | apt-get clean 48 | rm -rf /var/lib/apt/lists/* 49 | fi 50 | fi 51 | -------------------------------------------------------------------------------- /attic/docker/scripts/install-150-dependencies-bladerf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | function cmakebuild() { 5 | cd $1 6 | if [[ ! -z "${2:-}" ]]; then 7 | git checkout $2 8 | fi 9 | mkdir build 10 | cd build 11 | cmake .. 12 | make 13 | make install 14 | cd ../.. 15 | rm -rf $1 16 | } 17 | 18 | cd /tmp 19 | 20 | STATIC_PACKAGES="libusb-1.0-0" 21 | BUILD_PACKAGES="git cmake make gcc g++ libusb-1.0-0-dev" 22 | 23 | if [[ -z ${1:-} ]]; then 24 | apt-get update 25 | apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES 26 | 27 | git clone https://github.com/Nuand/bladeRF.git 28 | cmakebuild bladeRF 2021.10 29 | 30 | git clone https://github.com/pothosware/SoapyBladeRF.git 31 | # latest from master as of 2022-01-12 32 | cmakebuild SoapyBladeRF 70505a5cdf8c9deabc4af3eb3384aa82a7b6f021 33 | fi 34 | 35 | if [[ -z ${FULL_BUILD:-} || ${1:-} == 'clean' ]]; then 36 | echo "Cleaning from $0" 37 | apt-get -y purge --autoremove $BUILD_PACKAGES 38 | if [[ -z ${FULL_BUILD:-} ]]; then 39 | apt-get clean 40 | rm -rf /var/lib/apt/lists/* 41 | fi 42 | fi 43 | -------------------------------------------------------------------------------- /attic/docker/scripts/install-500-connectors.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euxo pipefail 3 | 4 | function cmakebuild() { 5 | cd $1 6 | if [[ ! -z "${2:-}" ]]; then 7 | git checkout $2 8 | fi 9 | mkdir build 10 | cd build 11 | cmake .. 12 | make 13 | make install 14 | cd ../.. 15 | rm -rf $1 16 | } 17 | 18 | cd /tmp 19 | 20 | BUILD_PACKAGES="git cmake make gcc g++ libsamplerate-dev libfftw3-dev" 21 | 22 | if [[ -z ${1:-} ]]; then 23 | apt-get update 24 | apt-get -y install --no-install-recommends $BUILD_PACKAGES 25 | 26 | git clone https://github.com/luarvique/owrx_connector.git 27 | cmakebuild owrx_connector master 28 | fi 29 | 30 | if [[ -z ${FULL_BUILD:-} || ${1:-} == 'clean' ]]; then 31 | echo "Cleaning from $0" 32 | apt-get -y purge --autoremove $BUILD_PACKAGES 33 | if [[ -z ${FULL_BUILD:-} ]]; then 34 | apt-get clean 35 | rm -rf /var/lib/apt/lists/* 36 | fi 37 | fi 38 | -------------------------------------------------------------------------------- /attic/docker/scripts/install-510-dependencies-runds.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | function cmakebuild() { 5 | cd $1 6 | if [[ ! -z "${2:-}" ]]; then 7 | git checkout $2 8 | fi 9 | mkdir build 10 | cd build 11 | cmake .. 12 | make 13 | make install 14 | cd ../.. 15 | rm -rf $1 16 | } 17 | 18 | cd /tmp 19 | 20 | STATIC_PACKAGES="" 21 | BUILD_PACKAGES="git cmake make gcc g++ pkg-config" 22 | 23 | if [[ -z ${1:-} ]]; then 24 | apt-get update 25 | apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES 26 | 27 | git clone https://github.com/jketterl/runds_connector.git 28 | # latest develop as of 2022-12-11 (std::endl implicit flushing) 29 | cmakebuild runds_connector 06ca993a3c81ddb0a2581b1474895da07752a9e1 30 | fi 31 | 32 | if [[ -z ${FULL_BUILD:-} || ${1:-} == 'clean' ]]; then 33 | echo "Cleaning from $0" 34 | apt-get -y purge --autoremove $BUILD_PACKAGES 35 | if [[ -z ${FULL_BUILD:-} ]]; then 36 | apt-get clean 37 | rm -rf /var/lib/apt/lists/* 38 | fi 39 | fi 40 | -------------------------------------------------------------------------------- /attic/docker/scripts/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | mkdir -p /etc/openwebrx/openwebrx.conf.d 5 | mkdir -p /var/lib/openwebrx 6 | mkdir -p /tmp/openwebrx/ 7 | if [[ ! -f /etc/openwebrx/openwebrx.conf.d/20-temporary-directory.conf ]] ; then 8 | cat << EOF > /etc/openwebrx/openwebrx.conf.d/20-temporary-directory.conf 9 | [core] 10 | temporary_directory = /tmp/openwebrx 11 | EOF 12 | fi 13 | if [[ ! -f /etc/openwebrx/bands.json ]] ; then 14 | cp bands.json /etc/openwebrx/ 15 | fi 16 | if [[ ! -f /etc/openwebrx/openwebrx.conf ]] ; then 17 | cp openwebrx.conf /etc/openwebrx/ 18 | fi 19 | if [[ ! -z "${OPENWEBRX_ADMIN_USER:-}" ]] && [[ ! -z "${OPENWEBRX_ADMIN_PASSWORD:-}" ]] ; then 20 | if ! python3 openwebrx.py admin --silent hasuser "${OPENWEBRX_ADMIN_USER}" ; then 21 | OWRX_PASSWORD="${OPENWEBRX_ADMIN_PASSWORD}" python3 openwebrx.py admin --noninteractive adduser "${OPENWEBRX_ADMIN_USER}" 22 | fi 23 | fi 24 | 25 | 26 | _term() { 27 | echo "Caught signal!" 28 | kill -TERM "$child" 2>/dev/null 29 | } 30 | 31 | trap _term SIGTERM SIGINT 32 | 33 | python3 openwebrx.py $@ & 34 | 35 | child=$! 36 | wait "$child" 37 | -------------------------------------------------------------------------------- /bookmarks.d/maritime.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name" : "NAVTEX", 4 | "frequency" : 489000, 5 | "modulation" : "sitorb" 6 | }, 7 | { 8 | "name" : "NAVTEX", 9 | "frequency" : 517000, 10 | "modulation" : "sitorb" 11 | }, 12 | { 13 | "name" : "NAVTEX", 14 | "frequency" : 4208500, 15 | "modulation" : "sitorb" 16 | }, 17 | { 18 | "name" : "MSI", 19 | "frequency" : 4209000, 20 | "modulation" : "sitorb" 21 | }, 22 | { 23 | "name" : "MSI", 24 | "frequency" : 6313000, 25 | "modulation" : "sitorb" 26 | }, 27 | { 28 | "name" : "MSI", 29 | "frequency" : 8415500, 30 | "modulation" : "sitorb" 31 | }, 32 | { 33 | "name" : "MSI", 34 | "frequency" : 12578000, 35 | "modulation" : "sitorb" 36 | }, 37 | { 38 | "name" : "MSI", 39 | "frequency" : 16805500, 40 | "modulation" : "sitorb" 41 | }, 42 | { 43 | "name" : "MSI", 44 | "frequency" : 19679500, 45 | "modulation" : "sitorb" 46 | }, 47 | { 48 | "name" : "MSI", 49 | "frequency" : 22375000, 50 | "modulation" : "sitorb" 51 | }, 52 | { 53 | "name" : "MSI", 54 | "frequency" : 26099500, 55 | "modulation" : "sitorb" 56 | }, 57 | { 58 | "name" : "DSC", 59 | "frequency" : 2186500, 60 | "modulation" : "dsc" 61 | }, 62 | { 63 | "name" : "DSC", 64 | "frequency" : 4206500, 65 | "modulation" : "dsc" 66 | }, 67 | { 68 | "name" : "DSC", 69 | "frequency" : 6311000, 70 | "modulation" : "dsc" 71 | }, 72 | { 73 | "name" : "DSC", 74 | "frequency" : 8413500, 75 | "modulation" : "dsc" 76 | }, 77 | { 78 | "name" : "DSC", 79 | "frequency" : 12576000, 80 | "modulation" : "dsc" 81 | }, 82 | { 83 | "name" : "DSC", 84 | "frequency" : 16803500, 85 | "modulation" : "dsc" 86 | }, 87 | { 88 | "name" : "DSC", 89 | "frequency" : 156524000, 90 | "modulation" : "dsc" 91 | } 92 | ] 93 | -------------------------------------------------------------------------------- /bookmarks.d/murs.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name" : "MURS1", 4 | "frequency" : 151820000, 5 | "modulation" : "nfm" 6 | }, 7 | { 8 | "name" : "MURS2", 9 | "frequency" : 151880000, 10 | "modulation" : "nfm" 11 | }, 12 | { 13 | "name" : "MURS3", 14 | "frequency" : 151940000, 15 | "modulation" : "nfm" 16 | }, 17 | { 18 | "name" : "MURS4", 19 | "frequency" : 154570000, 20 | "modulation" : "nfm" 21 | }, 22 | { 23 | "name" : "MURS5", 24 | "frequency" : 154600000, 25 | "modulation" : "nfm" 26 | } 27 | ] 28 | -------------------------------------------------------------------------------- /bookmarks.d/pmr.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name" : "PMR1", 4 | "frequency" : 446006250, 5 | "modulation" : "nfm" 6 | }, 7 | { 8 | "name" : "PMR2", 9 | "frequency" : 446018750, 10 | "modulation" : "nfm" 11 | }, 12 | { 13 | "name" : "PMR3", 14 | "frequency" : 446031250, 15 | "modulation" : "nfm" 16 | }, 17 | { 18 | "name" : "PMR4", 19 | "frequency" : 446043750, 20 | "modulation" : "nfm" 21 | }, 22 | { 23 | "name" : "PMR5", 24 | "frequency" : 446056250, 25 | "modulation" : "nfm" 26 | }, 27 | { 28 | "name" : "PMR6", 29 | "frequency" : 446068750, 30 | "modulation" : "nfm" 31 | }, 32 | { 33 | "name" : "PMR7", 34 | "frequency" : 446081250, 35 | "modulation" : "nfm" 36 | }, 37 | { 38 | "name" : "PMR8", 39 | "frequency" : 446093750, 40 | "modulation" : "nfm" 41 | }, 42 | { 43 | "name" : "PMR9", 44 | "frequency" : 446106250, 45 | "modulation" : "nfm" 46 | }, 47 | { 48 | "name" : "PMR10", 49 | "frequency" : 446118750, 50 | "modulation" : "nfm" 51 | }, 52 | { 53 | "name" : "PMR11", 54 | "frequency" : 446131250, 55 | "modulation" : "nfm" 56 | }, 57 | { 58 | "name" : "PMR12", 59 | "frequency" : 446143750, 60 | "modulation" : "nfm" 61 | }, 62 | { 63 | "name" : "PMR13", 64 | "frequency" : 446156250, 65 | "modulation" : "nfm" 66 | }, 67 | { 68 | "name" : "PMR14", 69 | "frequency" : 446168750, 70 | "modulation" : "nfm" 71 | }, 72 | { 73 | "name" : "PMR15", 74 | "frequency" : 446181250, 75 | "modulation" : "nfm" 76 | }, 77 | { 78 | "name" : "PMR16", 79 | "frequency" : 446193750, 80 | "modulation" : "nfm" 81 | } 82 | ] 83 | -------------------------------------------------------------------------------- /bookmarks.d/weather.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name" : "DDH47", 4 | "frequency" : 146300, 5 | "modulation" : "rtty450" 6 | }, 7 | { 8 | "name" : "DDH9", 9 | "frequency" : 11038000, 10 | "modulation" : "rtty450" 11 | }, 12 | { 13 | "name" : "DDH8", 14 | "frequency" : 14466300, 15 | "modulation" : "rtty450" 16 | }, 17 | { 18 | "name" : "DDK2", 19 | "frequency" : 4582000, 20 | "modulation" : "rtty450" 21 | }, 22 | { 23 | "name" : "DDH7", 24 | "frequency" : 7645000, 25 | "modulation" : "rtty450" 26 | }, 27 | { 28 | "name" : "DDK9", 29 | "frequency" : 10099800, 30 | "modulation" : "rtty450" 31 | }, 32 | { 33 | "name" : "NOAA-1", 34 | "frequency" : 162400000, 35 | "modulation" : "nfm" 36 | }, 37 | { 38 | "name" : "NOAA-2", 39 | "frequency" : 162425000, 40 | "modulation" : "nfm" 41 | }, 42 | { 43 | "name" : "NOAA-3", 44 | "frequency" : 162450000, 45 | "modulation" : "nfm" 46 | }, 47 | { 48 | "name" : "NOAA-4", 49 | "frequency" : 162475000, 50 | "modulation" : "nfm" 51 | }, 52 | { 53 | "name" : "NOAA-5", 54 | "frequency" : 162500000, 55 | "modulation" : "nfm" 56 | }, 57 | { 58 | "name" : "NOAA-6", 59 | "frequency" : 162525000, 60 | "modulation" : "nfm" 61 | }, 62 | { 63 | "name" : "NOAA-7", 64 | "frequency" : 162550000, 65 | "modulation" : "nfm" 66 | } 67 | ] 68 | -------------------------------------------------------------------------------- /bookmarks.json: -------------------------------------------------------------------------------- 1 | [ 2 | ] 3 | -------------------------------------------------------------------------------- /csdr/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xAF/openwebrxplus/5ef0b447d53f57a45a6cc1e4cbdd02cd5de66cc1/csdr/__init__.py -------------------------------------------------------------------------------- /csdr/chain/demodulator.py: -------------------------------------------------------------------------------- 1 | from csdr.chain import Chain 2 | from abc import ABC, ABCMeta, abstractmethod 3 | from pycsdr.modules import Writer 4 | 5 | 6 | class FixedAudioRateChain(ABC): 7 | @abstractmethod 8 | def getFixedAudioRate(self) -> int: 9 | pass 10 | 11 | 12 | class FixedIfSampleRateChain(ABC): 13 | @abstractmethod 14 | def getFixedIfSampleRate(self) -> int: 15 | pass 16 | 17 | 18 | class DialFrequencyReceiver(ABC): 19 | @abstractmethod 20 | def setDialFrequency(self, frequency: int) -> None: 21 | pass 22 | 23 | 24 | # marker interface 25 | class HdAudio: 26 | pass 27 | 28 | 29 | class MetaProvider(ABC): 30 | @abstractmethod 31 | def setMetaWriter(self, writer: Writer) -> None: 32 | pass 33 | 34 | 35 | class SlotFilterChain(ABC): 36 | @abstractmethod 37 | def setSlotFilter(self, filter: int) -> None: 38 | pass 39 | 40 | 41 | class SecondarySelectorChain(ABC): 42 | def getBandwidth(self) -> float: 43 | pass 44 | 45 | 46 | class DeemphasisTauChain(ABC): 47 | @abstractmethod 48 | def setDeemphasisTau(self, tau: float) -> None: 49 | pass 50 | 51 | 52 | class RdsChain(ABC): 53 | @abstractmethod 54 | def setRdsRbds(self, rdsRbds: bool) -> None: 55 | pass 56 | 57 | 58 | class AudioServiceSelector(ABC): 59 | @abstractmethod 60 | def setAudioServiceId(self, serviceId: int) -> None: 61 | pass 62 | 63 | 64 | class BaseDemodulatorChain(Chain): 65 | def supportsSquelch(self) -> bool: 66 | return True 67 | 68 | def setSampleRate(self, sampleRate: int) -> None: 69 | pass 70 | 71 | 72 | class SecondaryDemodulator(Chain): 73 | def supportsSquelch(self) -> bool: 74 | return True 75 | 76 | def setSampleRate(self, sampleRate: int) -> None: 77 | pass 78 | 79 | def isSecondaryFftShown(self): 80 | return True 81 | 82 | 83 | class ServiceDemodulator(SecondaryDemodulator, FixedAudioRateChain, metaclass=ABCMeta): 84 | pass 85 | 86 | 87 | class DemodulatorError(Exception): 88 | pass 89 | -------------------------------------------------------------------------------- /csdr/chain/drm.py: -------------------------------------------------------------------------------- 1 | from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain 2 | from pycsdr.modules import Convert, Downmix 3 | from pycsdr.types import Format 4 | from csdr.module.drm import DrmModule 5 | 6 | 7 | class Drm(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain): 8 | def __init__(self): 9 | workers = [ 10 | Convert(Format.COMPLEX_FLOAT, Format.COMPLEX_SHORT), 11 | DrmModule(), 12 | Downmix(Format.SHORT), 13 | ] 14 | super().__init__(workers) 15 | 16 | def supportsSquelch(self) -> bool: 17 | return False 18 | 19 | def getFixedIfSampleRate(self) -> int: 20 | return 48000 21 | 22 | def getFixedAudioRate(self) -> int: 23 | return 48000 24 | -------------------------------------------------------------------------------- /csdr/chain/dummy.py: -------------------------------------------------------------------------------- 1 | from pycsdr.types import Format 2 | from csdr.chain import Module 3 | 4 | 5 | class DummyDemodulator(Module): 6 | def __init__(self, outputFormat: Format): 7 | self.outputFormat = outputFormat 8 | super().__init__() 9 | 10 | def getInputFormat(self) -> Format: 11 | return Format.COMPLEX_FLOAT 12 | 13 | def getOutputFormat(self) -> Format: 14 | return self.outputFormat 15 | -------------------------------------------------------------------------------- /csdr/chain/freedv.py: -------------------------------------------------------------------------------- 1 | from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain 2 | from csdr.module.freedv import FreeDVModule 3 | from pycsdr.modules import RealPart, Agc, Convert 4 | from pycsdr.types import Format 5 | 6 | 7 | class FreeDV(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain): 8 | def __init__(self): 9 | agc = Agc(Format.SHORT) 10 | agc.setMaxGain(30) 11 | agc.setInitialGain(3) 12 | workers = [ 13 | RealPart(), 14 | Agc(Format.FLOAT), 15 | Convert(Format.FLOAT, Format.SHORT), 16 | FreeDVModule(), 17 | agc, 18 | ] 19 | super().__init__(workers) 20 | 21 | def getFixedIfSampleRate(self) -> int: 22 | return 8000 23 | 24 | def getFixedAudioRate(self) -> int: 25 | return 8000 26 | 27 | def supportsSquelch(self) -> bool: 28 | return False 29 | -------------------------------------------------------------------------------- /csdr/chain/hdradio.py: -------------------------------------------------------------------------------- 1 | from csdr.chain.demodulator import FixedIfSampleRateChain, BaseDemodulatorChain, FixedAudioRateChain, DialFrequencyReceiver, HdAudio, MetaProvider, AudioServiceSelector 2 | from csdr.module.hdradio import HdRadioModule 3 | from pycsdr.modules import Convert, Agc, Downmix, Writer, Buffer, Throttle 4 | from pycsdr.types import Format 5 | from typing import Optional 6 | 7 | import logging 8 | 9 | logger = logging.getLogger(__name__) 10 | logger.setLevel(logging.DEBUG) 11 | 12 | 13 | class HdRadio(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, MetaProvider, DialFrequencyReceiver, AudioServiceSelector): 14 | def __init__(self, program: int = 0): 15 | self.hdradio = HdRadioModule(program = program) 16 | workers = [ 17 | Agc(Format.COMPLEX_FLOAT), 18 | Convert(Format.COMPLEX_FLOAT, Format.COMPLEX_SHORT), 19 | self.hdradio, 20 | Throttle(Format.SHORT, 44100 * 2), 21 | Downmix(Format.SHORT), 22 | ] 23 | super().__init__(workers) 24 | 25 | def getFixedIfSampleRate(self) -> int: 26 | return self.hdradio.getFixedAudioRate() 27 | 28 | def getFixedAudioRate(self) -> int: 29 | return 44100 30 | 31 | def supportsSquelch(self) -> bool: 32 | return False 33 | 34 | # Set metadata consumer 35 | def setMetaWriter(self, writer: Writer) -> None: 36 | self.hdradio.setMetaWriter(writer) 37 | 38 | # Change program 39 | def setAudioServiceId(self, serviceId: int) -> None: 40 | self.hdradio.setProgram(serviceId) 41 | 42 | def setDialFrequency(self, frequency: int) -> None: 43 | self.hdradio.setFrequency(frequency) 44 | 45 | def _connect(self, w1, w2, buffer: Optional[Buffer] = None) -> None: 46 | if isinstance(w2, Throttle): 47 | # Audio data comes in in bursts, so we use a throttle 48 | # and 10x the default buffer size here 49 | buffer = Buffer(Format.SHORT, 2621440) 50 | return super()._connect(w1, w2, buffer) 51 | -------------------------------------------------------------------------------- /csdr/chain/m17.py: -------------------------------------------------------------------------------- 1 | from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, MetaProvider 2 | from csdr.module.m17 import M17Module 3 | from pycsdr.modules import FmDemod, Limit, Convert, Writer, DcBlock 4 | from pycsdr.types import Format 5 | 6 | 7 | class M17(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, MetaProvider): 8 | def __init__(self): 9 | self.module = M17Module() 10 | workers = [ 11 | FmDemod(), 12 | DcBlock(), 13 | Limit(), 14 | Convert(Format.FLOAT, Format.SHORT), 15 | self.module, 16 | ] 17 | super().__init__(workers) 18 | 19 | def getFixedIfSampleRate(self) -> int: 20 | return 48000 21 | 22 | def getFixedAudioRate(self) -> int: 23 | return 8000 24 | 25 | def supportsSquelch(self) -> bool: 26 | return False 27 | 28 | def setMetaWriter(self, writer: Writer) -> None: 29 | self.module.setMetaWriter(writer) 30 | -------------------------------------------------------------------------------- /csdr/module/drm.py: -------------------------------------------------------------------------------- 1 | from pycsdr.modules import ExecModule 2 | from pycsdr.types import Format 3 | 4 | 5 | class DrmModule(ExecModule): 6 | def __init__(self): 7 | super().__init__( 8 | Format.COMPLEX_SHORT, 9 | Format.SHORT, 10 | ["dream", "-c", "6", "--sigsrate", "48000", "--audsrate", "48000", "-I", "-", "-O", "-"] 11 | ) 12 | -------------------------------------------------------------------------------- /csdr/module/freedv.py: -------------------------------------------------------------------------------- 1 | from pycsdr.types import Format 2 | from pycsdr.modules import ExecModule 3 | 4 | 5 | class FreeDVModule(ExecModule): 6 | def __init__(self): 7 | super().__init__( 8 | Format.SHORT, 9 | Format.SHORT, 10 | ["freedv_rx", "1600", "-", "-"] 11 | ) 12 | -------------------------------------------------------------------------------- /csdr/module/m17.py: -------------------------------------------------------------------------------- 1 | from csdr.module import PopenModule 2 | from pycsdr.types import Format 3 | from pycsdr.modules import Writer 4 | from subprocess import Popen, PIPE 5 | from threading import Thread 6 | 7 | import re 8 | import pickle 9 | 10 | 11 | class M17Module(PopenModule): 12 | lsfRegex = re.compile("SRC: ([a-zA-Z0-9]+), DEST: ([a-zA-Z0-9]+)") 13 | 14 | def __init__(self): 15 | super().__init__() 16 | self.metawriter = None 17 | 18 | def getInputFormat(self) -> Format: 19 | return Format.SHORT 20 | 21 | def getOutputFormat(self) -> Format: 22 | return Format.SHORT 23 | 24 | def getCommand(self): 25 | return ["m17-demod", "-l"] 26 | 27 | def _getProcess(self): 28 | return Popen(self.getCommand(), stdin=PIPE, stdout=PIPE, stderr=PIPE) 29 | 30 | def start(self): 31 | super().start() 32 | Thread(target=self._readOutput).start() 33 | 34 | def _readOutput(self): 35 | while True: 36 | line = self.process.stderr.readline() 37 | if not line: 38 | break 39 | self.parseOutput(line.decode()) 40 | 41 | def parseOutput(self, line): 42 | if self.metawriter is None: 43 | return 44 | matches = self.lsfRegex.match(line) 45 | msg = {"protocol": "M17"} 46 | if matches: 47 | # fake sync 48 | msg["sync"] = "voice" 49 | msg["source"] = matches.group(1) 50 | msg["destination"] = matches.group(2) 51 | elif line.startswith("EOS"): 52 | pass 53 | else: 54 | return 55 | self.metawriter.write(pickle.dumps(msg)) 56 | 57 | def setMetaWriter(self, writer: Writer) -> None: 58 | self.metawriter = writer 59 | -------------------------------------------------------------------------------- /csdr/module/msk144.py: -------------------------------------------------------------------------------- 1 | from pycsdr.types import Format 2 | from pycsdr.modules import ExecModule 3 | from csdr.module import LineBasedModule 4 | from owrx.wsjt import WsjtParser, Msk144Profile 5 | import pickle 6 | 7 | import logging 8 | logger = logging.getLogger(__name__) 9 | 10 | 11 | class Msk144Module(ExecModule): 12 | def __init__(self): 13 | super().__init__( 14 | Format.SHORT, 15 | Format.CHAR, 16 | ["msk144decoder"] 17 | ) 18 | 19 | 20 | class ParserAdapter(LineBasedModule): 21 | def __init__(self): 22 | self.parser = WsjtParser() 23 | self.dialFrequency = 0 24 | self.profile = Msk144Profile() 25 | super().__init__() 26 | 27 | def process(self, line: bytes): 28 | # actual messages from msk144decoder should start with "*** " 29 | if line[0:4] == b"*** ": 30 | return self.parser.parse(self.profile, self.dialFrequency, line[4:]) 31 | 32 | def setDialFrequency(self, frequency: int) -> None: 33 | self.dialFrequency = frequency 34 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: openwebrx 2 | Maintainer: Marat Fayzullin 3 | Section: hamradio 4 | Priority: optional 5 | Rules-Requires-Root: no 6 | Standards-Version: 4.2.0 7 | Build-Depends: debhelper (>= 11), 8 | dh-python, 9 | python3-all (>= 3.5), 10 | python3-setuptools 11 | Homepage: https://www.openwebrx.de/ 12 | Vcs-Browser: https://github.com/luarvique/openwebrx 13 | Vcs-Git: https://github.com/luarvique/openwebrx.git 14 | 15 | Package: openwebrx 16 | Architecture: all 17 | Depends: adduser, 18 | python3 (>= 3.5), 19 | python3-pkg-resources, 20 | python3-distutils-extra, 21 | owrx-connector (>= 0.6.5), 22 | python3-csdr (>= 0.18.27), 23 | ${python3:Depends}, 24 | ${misc:Depends} 25 | Recommends: python3-digiham (>= 0.6), 26 | direwolf (>= 1.4), 27 | wsjtx, 28 | js8call, 29 | runds-connector (>= 0.2), 30 | hpsdrconnector, 31 | aprs-symbols, 32 | m17-demod, 33 | js8call, 34 | python3-js8py (>= 0.1), 35 | nmux (>= 0.18), 36 | codecserver (>= 0.1), 37 | msk144decoder, 38 | dump1090-fa-minimal, 39 | dumphfdl, 40 | dumpvdl2, 41 | acarsdec, 42 | rtl-433, 43 | extra-sdr-drivers, 44 | perseus-tools, 45 | dream-headless, 46 | codec2, 47 | redsea, 48 | python3-csdr-eti, 49 | python3-paho-mqtt, 50 | dablin, 51 | multimon-ng, 52 | imagemagick, 53 | nrsc5, 54 | libhamlib-utils, 55 | csdr-cwskimmer 56 | Description: multi-user web sdr 57 | Open source, multi-user SDR receiver with a web interface 58 | -------------------------------------------------------------------------------- /debian/openwebrx.config: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | . /usr/share/debconf/confmodule 3 | 4 | db_get openwebrx/admin_user_configured 5 | if [ "${1:-}" = "reconfigure" ] || [ "${RET}" != true ]; then 6 | db_settitle openwebrx/title 7 | db_input high openwebrx/admin_user_password || true 8 | db_go 9 | fi 10 | -------------------------------------------------------------------------------- /debian/openwebrx.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Version=1.0 3 | Name=OpenWebRX 4 | Type=Application 5 | Comment=Web-based software defined radio receiver 6 | Icon=openwebrx 7 | Exec=xdg-open http://localhost:8073/ 8 | Categories=Network;HamRadio 9 | -------------------------------------------------------------------------------- /debian/openwebrx.dirs: -------------------------------------------------------------------------------- 1 | /etc/openwebrx/openwebrx.conf.d 2 | /etc/openwebrx/bookmarks.d 3 | -------------------------------------------------------------------------------- /debian/openwebrx.install: -------------------------------------------------------------------------------- 1 | bands.json etc/openwebrx/ 2 | bands-r1.json etc/openwebrx/ 3 | bands-r2.json etc/openwebrx/ 4 | bands-r3.json etc/openwebrx/ 5 | bookmarks.json etc/openwebrx/ 6 | bookmarks.d etc/openwebrx/ 7 | openwebrx.conf etc/openwebrx/ 8 | systemd/openwebrx.service lib/systemd/system/ 9 | debian/openwebrx.svg usr/share/icons/hicolor/scalable/apps 10 | debian/openwebrx.desktop usr/share/applications 11 | -------------------------------------------------------------------------------- /debian/openwebrx.postinst: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | . /usr/share/debconf/confmodule 3 | 4 | set -euo pipefail 5 | 6 | OWRX_USER="openwebrx" 7 | OWRX_DATADIR="/var/lib/openwebrx" 8 | OWRX_USERS_FILE="${OWRX_DATADIR}/users.json" 9 | OWRX_SETTINGS_FILE="${OWRX_DATADIR}/settings.json" 10 | OWRX_BOOKMARKS_FILE="${OWRX_DATADIR}/bookmarks.json" 11 | 12 | case "$1" in 13 | configure|reconfigure) 14 | adduser --system --group --no-create-home --home /nonexistent --quiet "${OWRX_USER}" 15 | usermod -aG plugdev "${OWRX_USER}" 16 | 17 | # addgroup will error out if the group exists, but is not a system group. it doesn't matter for the intended purpose, but we need extra protection for this case. 18 | if [ ! $(getent group perseususb) ]; then 19 | addgroup --system --quiet perseususb 20 | fi 21 | usermod -aG perseususb "${OWRX_USER}" 22 | 23 | # create OpenWebRX data directory and set the correct permissions 24 | if [ ! -d "${OWRX_DATADIR}" ] && [ ! -L "${OWRX_DATADIR}" ]; then mkdir "${OWRX_DATADIR}"; fi 25 | chown "${OWRX_USER}": ${OWRX_DATADIR} 26 | 27 | # create empty config files now to avoid permission problems later 28 | if [ ! -e "${OWRX_USERS_FILE}" ]; then 29 | echo "[]" > "${OWRX_USERS_FILE}" 30 | chown "${OWRX_USER}": "${OWRX_USERS_FILE}" 31 | chmod 0600 "${OWRX_USERS_FILE}" 32 | fi 33 | 34 | if [ ! -e "${OWRX_SETTINGS_FILE}" ]; then 35 | echo "{}" > "${OWRX_SETTINGS_FILE}" 36 | chown "${OWRX_USER}": "${OWRX_SETTINGS_FILE}" 37 | fi 38 | 39 | if [ ! -e "${OWRX_BOOKMARKS_FILE}" ]; then 40 | touch "${OWRX_BOOKMARKS_FILE}" 41 | chown "${OWRX_USER}": "${OWRX_BOOKMARKS_FILE}" 42 | fi 43 | 44 | db_get openwebrx/admin_user_password 45 | if [ ! -z "${RET}" ]; then 46 | if ! openwebrx admin --silent hasuser admin; then 47 | # create initial openwebrx user 48 | OWRX_PASSWORD="${RET}" openwebrx admin --noninteractive adduser admin 49 | else 50 | # change existing user's password 51 | OWRX_PASSWORD="${RET}" openwebrx admin --noninteractive resetpassword admin 52 | fi 53 | fi 54 | # remove password from debconf database 55 | db_unregister openwebrx/admin_user_password 56 | # set a marker that admin is configured to avoid future questions 57 | db_set openwebrx/admin_user_configured true 58 | ;; 59 | *) 60 | echo "postinst called with unknown argument '$1'" 1>&2 61 | exit 1 62 | ;; 63 | esac 64 | 65 | #DEBHELPER# 66 | -------------------------------------------------------------------------------- /debian/openwebrx.postrm: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | if [ "$1" = purge ] && [ -e /usr/share/debconf/confmodule ]; then 4 | . /usr/share/debconf/confmodule 5 | db_purge 6 | fi 7 | 8 | #DEBHELPER# 9 | -------------------------------------------------------------------------------- /debian/openwebrx.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /debian/openwebrx.templates: -------------------------------------------------------------------------------- 1 | Template: openwebrx/admin_user_password 2 | Type: password 3 | Description: OpenWebRX "admin" user password: 4 | The system can create a user for the OpenWebRX web configuration interface for 5 | you. Using this user, you will be able to log into the "settings" area of 6 | OpenWebRX to configure your receiver conveniently through your browser. 7 | . 8 | The name of the created user will be "admin". 9 | . 10 | If you do not wish to create a web admin user right now, you can leave this 11 | empty for now. You can return to this prompt at a later time by running the 12 | command "sudo dpkg-reconfigure openwebrx". 13 | . 14 | You can also use the "openwebrx admin" command to create, delete or manage 15 | existing users. More information is available in by running the command 16 | "openwebrx admin --help". 17 | 18 | Template: openwebrx/admin_user_configured 19 | Type: boolean 20 | Default: false 21 | Description: OpenWebRX "admin" user previously configured? 22 | Marker used internally by the config scripts to remember if an admin user has 23 | been created. 24 | 25 | Template: openwebrx/title 26 | Type: title 27 | Description: Configuring OpenWebRX -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | export PYBUILD_NAME=openwebrx 3 | 4 | %: 5 | dh $@ --with python3 --buildsystem=pybuild --with systemd 6 | 7 | override_dh_strip_nondeterminism: 8 | dh_strip_nondeterminism -X.png 9 | 10 | override_dh_builddeb: 11 | dh_builddeb -- -Zxz 12 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (native) -------------------------------------------------------------------------------- /debian/source/options: -------------------------------------------------------------------------------- 1 | # Use xz instead of zstd 2 | compression = "xz" 3 | -------------------------------------------------------------------------------- /htdocs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xAF/openwebrxplus/5ef0b447d53f57a45a6cc1e4cbdd02cd5de66cc1/htdocs/__init__.py -------------------------------------------------------------------------------- /htdocs/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xAF/openwebrxplus/5ef0b447d53f57a45a6cc1e4cbdd02cd5de66cc1/htdocs/apple-touch-icon.png -------------------------------------------------------------------------------- /htdocs/clients.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | OpenWebRX+ Connected Clients 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | ${header} 13 |
14 |
15 |

Connected Clients

16 |
17 |
18 | 19 |
20 |
21 | 22 |
23 |
24 | ${clients} 25 |
26 |
27 | 28 | -------------------------------------------------------------------------------- /htdocs/css/files.css: -------------------------------------------------------------------------------- 1 | @import url("openwebrx-header.css"); 2 | @import url("openwebrx-globals.css"); 3 | 4 | html, body { 5 | height: unset; 6 | } 7 | 8 | body { 9 | margin-bottom: 5rem; 10 | } 11 | 12 | hr { 13 | background: #444; 14 | } 15 | 16 | h1 { 17 | margin: 1em 0; 18 | text-align: center; 19 | } 20 | 21 | table { 22 | border-collapse: separate; 23 | border-spacing: 15px; 24 | } 25 | 26 | td { 27 | text-align: center; 28 | border: 3px dotted; 29 | } 30 | 31 | img { 32 | width: 100%; 33 | } 34 | 35 | .file-title { 36 | text-align: center; 37 | font-size: 80%; 38 | } 39 | 40 | .file-tile { 41 | width: 32%; 42 | } 43 | 44 | .file-delete { 45 | position: relative; 46 | bottom : 5px; 47 | } 48 | -------------------------------------------------------------------------------- /htdocs/css/login.css: -------------------------------------------------------------------------------- 1 | @import url("openwebrx-header.css"); 2 | @import url("openwebrx-globals.css"); 3 | 4 | body { 5 | display: flex; 6 | flex-direction: column; 7 | } 8 | 9 | .login-container { 10 | flex: 1; 11 | position: relative; 12 | } 13 | 14 | .login { 15 | position: absolute; 16 | left: 50%; 17 | top: 50%; 18 | transform: translate(-50%, -50%); 19 | 20 | width: 500px; 21 | 22 | padding: 20px; 23 | border-radius: 10px; 24 | border: 1px solid #575757; 25 | box-shadow: 0 0 20px #000; 26 | } 27 | 28 | .login .btn { 29 | width: 100%; 30 | } 31 | 32 | .btn-login { 33 | height: 50px; 34 | } -------------------------------------------------------------------------------- /htdocs/css/map.css: -------------------------------------------------------------------------------- 1 | @import url("openwebrx-header.css"); 2 | @import url("openwebrx-globals.css"); 3 | 4 | body { 5 | display: flex; 6 | flex-direction: column; 7 | } 8 | 9 | .openwebrx-map { 10 | flex: 1 1 auto; 11 | } 12 | 13 | h3 { 14 | margin: 10px 0; 15 | text-align: center; 16 | } 17 | 18 | ul { 19 | margin-block-start: 5px; 20 | margin-block-end: 5px; 21 | padding-inline-start: 25px; 22 | } 23 | 24 | /* don't show the filter in it's initial position */ 25 | .openwebrx-map-legend { 26 | display: none; 27 | background-color: #fff; 28 | padding: 10px; 29 | margin: 10px; 30 | user-select: none; 31 | } 32 | 33 | /* show it as soon as google maps has moved it to its container */ 34 | .openwebrx-map .openwebrx-map-legend { 35 | display: block; 36 | } 37 | 38 | .openwebrx-map-legend ul { 39 | list-style-type: none; 40 | padding: 0; 41 | } 42 | 43 | .openwebrx-map-legend ul li { 44 | cursor: pointer; 45 | } 46 | 47 | .openwebrx-map-legend ul li.disabled { 48 | opacity: .3; 49 | filter: grayscale(70%); 50 | } 51 | 52 | .openwebrx-map-legend li.square .illustration { 53 | display: inline-block; 54 | width: 30px; 55 | height: 20px; 56 | margin-right: 10px; 57 | border-width: 2px; 58 | border-style: solid; 59 | } 60 | 61 | .openwebrx-map-legend li.square .feature { 62 | display: inline-block; 63 | width: 20px; 64 | height: 20px; 65 | margin-right: 10px; 66 | border-width: 0; 67 | border-style: none; 68 | font-size: 24px; 69 | text-align: center; 70 | } 71 | 72 | .openwebrx-map-legend select { 73 | background-color: #FFF; 74 | border-color: #DDD; 75 | padding: 5px; 76 | } 77 | 78 | .openwebrx-map-console { 79 | overflow: auto; 80 | margin: 5px auto; 81 | padding: 6px; 82 | border-radius: 8px; 83 | background-color: #000040; 84 | color: #80FF20; 85 | width: 92%; 86 | } 87 | 88 | .openwebrx-map-console hr { 89 | border: 1px dashed #80FF20; 90 | } 91 | 92 | .openwebrx-map-info td { 93 | padding-left: 5px; 94 | padding-right: 5px; 95 | text-align: center; 96 | white-space: nowrap; 97 | } 98 | -------------------------------------------------------------------------------- /htdocs/css/openwebrx-globals.css: -------------------------------------------------------------------------------- 1 | html, body 2 | { 3 | margin: 0; 4 | padding: 0; 5 | height: 100%; 6 | font-family: "DejaVu Sans", Verdana, Geneva, sans-serif; 7 | } 8 | -------------------------------------------------------------------------------- /htdocs/css/shortcuts.css: -------------------------------------------------------------------------------- 1 | /* import keyboard-css for keys in help */ 2 | @import url("keyboard.min.css"); 3 | 4 | #ks-overlay { 5 | position: fixed; 6 | top: 1vh; 7 | left: calc((100vw - 800px) / 2); 8 | max-height: 95vh; 9 | width: 800px; 10 | color: white; 11 | background-color: #000; 12 | opacity: 0.8; 13 | z-index: 10000; 14 | border: 3px solid white; 15 | border-radius: 20px; 16 | display: flex; 17 | align-items: center; 18 | flex-direction: column; 19 | padding: 0.5rem; 20 | } 21 | 22 | .ks-title { 23 | font-weight: bold; 24 | font-size: 1.5rem; 25 | margin-top: 0.8rem; 26 | } 27 | 28 | .ks-subtitle { 29 | font-size: 0.8rem; 30 | margin-top: 0.25rem; 31 | } 32 | 33 | .ks-separator { 34 | border-top: 1px dotted white; 35 | align-self: stretch; 36 | margin: 1rem; 37 | } 38 | 39 | .ks-content { 40 | padding: 0 0.75rem; 41 | font-size: 1rem; 42 | display: flex; 43 | flex-direction: row; 44 | flex-wrap: wrap; 45 | justify-content: space-between; 46 | align-items: center; 47 | overflow-y: auto; 48 | } 49 | 50 | .ks-item { 51 | width: 240px; 52 | padding: 0.25rem; 53 | border: 1px dashed #444; 54 | margin-bottom: 0.25rem; 55 | display: flex; 56 | justify-content: space-between; 57 | flex-wrap: nowrap; 58 | align-items: center; 59 | flex-direction: column; 60 | /* flex-direction: row; */ 61 | } 62 | 63 | .ks-item-txt { 64 | color: silver; 65 | } 66 | 67 | .ks-item-kbd { 68 | text-wrap: nowrap; 69 | color: silver; 70 | } 71 | 72 | a.kbc-button-xs, button.kbc-button-xs { 73 | padding: 0.02rem 0.25rem; 74 | } 75 | 76 | a.kbc-button-sm, button.kbc-button-sm { 77 | padding: 0 0.5rem; 78 | font-size: .85rem; 79 | } 80 | -------------------------------------------------------------------------------- /htdocs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xAF/openwebrxplus/5ef0b447d53f57a45a6cc1e4cbdd02cd5de66cc1/htdocs/favicon.ico -------------------------------------------------------------------------------- /htdocs/features.html: -------------------------------------------------------------------------------- 1 | 2 | OpenWebRX+ Feature Report 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ${header} 12 |
13 | ${breadcrumb} 14 |

OpenWebRX+ Feature Report

15 | 16 | 17 | 18 | 19 | 20 | 21 |
FeatureDescriptionAvailable
22 | ${breadcrumb} 23 |
24 | 25 | -------------------------------------------------------------------------------- /htdocs/features.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | var converter = new showdown.Converter({openLinksInNewWindow: true}); 3 | 4 | function yes_no(v) { 5 | return v? 6 | 'YES' : 7 | 'NO'; 8 | } 9 | 10 | $.ajax('api/features').done(function(data){ 11 | var $table = $('table.features'); 12 | $.each(data, function(name, details) { 13 | var requirements = $.map(details.requirements, function(r, name){ 14 | return '' + 15 | '' + name + '' + 16 | '' + converter.makeHtml(r.description) + '' + 17 | yes_no(r.available) + 18 | ''; 19 | }); 20 | $table.append( 21 | '' + 22 | '' + name + '' + 23 | yes_no(details.available) + 24 | '' + 25 | requirements.join("") 26 | ); 27 | }) 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /htdocs/files.html: -------------------------------------------------------------------------------- 1 | 2 | OpenWebRX+ Received Files 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ${header} 12 |
13 |

OpenWebRX+ Received Files

14 | 15 | ${rows} 16 |
17 |
18 | 19 | -------------------------------------------------------------------------------- /htdocs/files.js: -------------------------------------------------------------------------------- 1 | $.fn.fileTile = function() { 2 | this.each(function() { 3 | $(this).on('click', '.file-delete', function(e) { 4 | $.ajax("files/delete", { 5 | data: JSON.stringify({ name: this.value }), 6 | contentType: 'application/json', 7 | method: 'POST' 8 | }).done(function() { 9 | document.location.reload(); 10 | }); 11 | return false; 12 | }); 13 | }); 14 | }; 15 | 16 | $(function(){ 17 | $('.file-tile').fileTile(); 18 | }); 19 | -------------------------------------------------------------------------------- /htdocs/fonts/RobotoMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xAF/openwebrxplus/5ef0b447d53f57a45a6cc1e4cbdd02cd5de66cc1/htdocs/fonts/RobotoMono-Regular.ttf -------------------------------------------------------------------------------- /htdocs/fonts/RobotoMono-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xAF/openwebrxplus/5ef0b447d53f57a45a6cc1e4cbdd02cd5de66cc1/htdocs/fonts/RobotoMono-Regular.woff -------------------------------------------------------------------------------- /htdocs/fonts/RobotoMono-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xAF/openwebrxplus/5ef0b447d53f57a45a6cc1e4cbdd02cd5de66cc1/htdocs/fonts/RobotoMono-Regular.woff2 -------------------------------------------------------------------------------- /htdocs/gfx/adsb-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xAF/openwebrxplus/5ef0b447d53f57a45a6cc1e4cbdd02cd5de66cc1/htdocs/gfx/adsb-72.png -------------------------------------------------------------------------------- /htdocs/gfx/audio-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xAF/openwebrxplus/5ef0b447d53f57a45a6cc1e4cbdd02cd5de66cc1/htdocs/gfx/audio-file.png -------------------------------------------------------------------------------- /htdocs/gfx/favicon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xAF/openwebrxplus/5ef0b447d53f57a45a6cc1e4cbdd02cd5de66cc1/htdocs/gfx/favicon128.png -------------------------------------------------------------------------------- /htdocs/gfx/favicon32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xAF/openwebrxplus/5ef0b447d53f57a45a6cc1e4cbdd02cd5de66cc1/htdocs/gfx/favicon32.png -------------------------------------------------------------------------------- /htdocs/gfx/favicon44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xAF/openwebrxplus/5ef0b447d53f57a45a6cc1e4cbdd02cd5de66cc1/htdocs/gfx/favicon44.png -------------------------------------------------------------------------------- /htdocs/gfx/favicon64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xAF/openwebrxplus/5ef0b447d53f57a45a6cc1e4cbdd02cd5de66cc1/htdocs/gfx/favicon64.png -------------------------------------------------------------------------------- /htdocs/gfx/favicon96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xAF/openwebrxplus/5ef0b447d53f57a45a6cc1e4cbdd02cd5de66cc1/htdocs/gfx/favicon96.png -------------------------------------------------------------------------------- /htdocs/gfx/openwebrx-avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xAF/openwebrxplus/5ef0b447d53f57a45a6cc1e4cbdd02cd5de66cc1/htdocs/gfx/openwebrx-avatar.png -------------------------------------------------------------------------------- /htdocs/gfx/openwebrx-background-cool-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xAF/openwebrxplus/5ef0b447d53f57a45a6cc1e4cbdd02cd5de66cc1/htdocs/gfx/openwebrx-background-cool-blue.png -------------------------------------------------------------------------------- /htdocs/gfx/openwebrx-background-cool-blue.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xAF/openwebrxplus/5ef0b447d53f57a45a6cc1e4cbdd02cd5de66cc1/htdocs/gfx/openwebrx-background-cool-blue.webp -------------------------------------------------------------------------------- /htdocs/gfx/openwebrx-directcall.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /htdocs/gfx/openwebrx-scale-background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xAF/openwebrxplus/5ef0b447d53f57a45a6cc1e4cbdd02cd5de66cc1/htdocs/gfx/openwebrx-scale-background.png -------------------------------------------------------------------------------- /htdocs/gfx/openwebrx-top-photo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xAF/openwebrxplus/5ef0b447d53f57a45a6cc1e4cbdd02cd5de66cc1/htdocs/gfx/openwebrx-top-photo.jpg -------------------------------------------------------------------------------- /htdocs/gfx/text-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xAF/openwebrxplus/5ef0b447d53f57a45a6cc1e4cbdd02cd5de66cc1/htdocs/gfx/text-file.png -------------------------------------------------------------------------------- /htdocs/lib/BookmarkDialog.js: -------------------------------------------------------------------------------- 1 | $.fn.bookmarkDialog = function() { 2 | var $el = this; 3 | return { 4 | setModes: function(modes) { 5 | $el.find('#modulation').html(modes.filter(function(m) { 6 | return m.isAvailable(); 7 | }).map(function(m) { 8 | return ''; 9 | }).join('')); 10 | return this; 11 | }, 12 | setUnderlying: function(modes) { 13 | $el.find('#underlying').html('' + 14 | modes.filter(function(m) { 15 | return m.isAvailable() && !m.underlying && m.type === 'analog'; 16 | }).map(function(m) { 17 | return ''; 18 | }).join('')); 19 | return this; 20 | }, 21 | setValues: function(bookmark) { 22 | var $form = $el.find('form'); 23 | ['name', 'frequency', 'modulation', 'underlying', 'description', 'scannable'].forEach(function(key) { 24 | var $input = $form.find('#' + key); 25 | if ($input.is(':checkbox')) { 26 | $input.prop('checked', bookmark[key]); 27 | } else { 28 | $input.val(bookmark[key]); 29 | } 30 | }); 31 | $el.data('id', bookmark.id || false); 32 | return this; 33 | }, 34 | getValues: function() { 35 | var bookmark = {}; 36 | var valid = true; 37 | ['name', 'frequency', 'modulation', 'underlying', 'description', 'scannable'].forEach(function(key) { 38 | var $input = $el.find('#' + key); 39 | valid = valid && $input[0].checkValidity(); 40 | bookmark[key] = $input.is(':checkbox')? $input.is(':checked') : $input.val(); 41 | }); 42 | if (!valid) { 43 | $el.find("form :submit").click(); 44 | return; 45 | } 46 | bookmark.id = $el.data('id'); 47 | return bookmark; 48 | } 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /htdocs/lib/BookmarkLocalStorage.js: -------------------------------------------------------------------------------- 1 | BookmarkLocalStorage = function(){ 2 | }; 3 | 4 | BookmarkLocalStorage.prototype.getBookmarks = function(){ 5 | return JSON.parse(window.localStorage.getItem("bookmarks")) || []; 6 | }; 7 | 8 | BookmarkLocalStorage.prototype.setBookmarks = function(bookmarks){ 9 | window.localStorage.setItem("bookmarks", JSON.stringify(bookmarks)); 10 | }; 11 | 12 | BookmarkLocalStorage.prototype.deleteBookmark = function(data) { 13 | if (data.id) data = data.id; 14 | var bookmarks = this.getBookmarks(); 15 | bookmarks = bookmarks.filter(function(b) { return b.id !== data; }); 16 | this.setBookmarks(bookmarks); 17 | }; 18 | -------------------------------------------------------------------------------- /htdocs/lib/Chat.js: -------------------------------------------------------------------------------- 1 | // 2 | // Built-in Chat 3 | // 4 | 5 | function Chat() {} 6 | 7 | // We start with these values 8 | Chat.nickname = ''; 9 | 10 | // Load chat settings from local storage. 11 | Chat.loadSettings = function() { 12 | this.setNickname(LS.has('chatname')? LS.loadStr('chatname') : ''); 13 | }; 14 | 15 | // Set chat nickname. 16 | Chat.setNickname = function(nickname) { 17 | if (this.nickname !== nickname) { 18 | this.nickname = nickname; 19 | LS.save('chatname', nickname); 20 | $('#openwebrx-chat-name').val(nickname); 21 | } 22 | }; 23 | 24 | Chat.recvMessage = function(nickname, text, color = 'white') { 25 | // Show chat panel 26 | toggle_panel('openwebrx-panel-log', true); 27 | 28 | divlog( 29 | '[' 30 | + Utils.htmlEscape(nickname) + ']: ' 31 | + '' + Utils.htmlEscape(text) 32 | + '' 33 | ); 34 | }; 35 | 36 | Chat.sendMessage = function(text, nickname = '') { 37 | ws.send(JSON.stringify({ 38 | 'type': 'sendmessage', 'name': nickname, 'text': text 39 | })); 40 | }; 41 | 42 | // Collect nick and message from controls and send message. 43 | Chat.send = function() { 44 | this.setNickname($('#openwebrx-chat-name').val().trim()); 45 | 46 | var msg = $('#openwebrx-chat-message').val().trim(); 47 | if (msg.length > 0) this.sendMessage(msg, this.nickname); 48 | $('#openwebrx-chat-message').val(''); 49 | }; 50 | 51 | // Attach events to chat controls. 52 | Chat.keyPress = function(event) { 53 | if (event.key === 'Enter') { 54 | event.preventDefault(); 55 | this.send(); 56 | } 57 | }; 58 | -------------------------------------------------------------------------------- /htdocs/lib/Clock.js: -------------------------------------------------------------------------------- 1 | function Clock(el) { 2 | // Save HTML element to update 3 | this.el = el; 4 | // Update for the first time 5 | this.update(); 6 | } 7 | 8 | Clock.prototype.update = function() { 9 | const now = new Date(); 10 | const me = this; 11 | 12 | // Next update at the next minute change 13 | setTimeout(function() { me.update(); }, 1000 * (60 - now.getUTCSeconds())); 14 | 15 | // Display UTC clock 16 | if (this.el) { 17 | const hours = ("00" + now.getUTCHours()).slice(-2); 18 | const minutes = ("00" + now.getUTCMinutes()).slice(-2); 19 | this.el.html(`${hours}:${minutes} UTC`); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /htdocs/lib/Measurement.js: -------------------------------------------------------------------------------- 1 | function Measurement() { 2 | this.reporters = []; 3 | this.reset(); 4 | } 5 | 6 | Measurement.prototype.add = function(v) { 7 | this.value += v; 8 | }; 9 | 10 | Measurement.prototype.getValue = function() { 11 | return this.value; 12 | }; 13 | 14 | Measurement.prototype.getElapsed = function() { 15 | return new Date() - this.start; 16 | }; 17 | 18 | Measurement.prototype.getRate = function() { 19 | return this.getValue() / this.getElapsed(); 20 | }; 21 | 22 | Measurement.prototype.reset = function() { 23 | this.value = 0; 24 | this.start = new Date(); 25 | this.reporters.forEach(function(r){ r.reset(); }); 26 | }; 27 | 28 | Measurement.prototype.report = function(range, interval, callback) { 29 | var reporter = new Reporter(this, range, interval, callback); 30 | this.reporters.push(reporter); 31 | return reporter; 32 | }; 33 | 34 | function Reporter(measurement, range, interval, callback) { 35 | this.measurement = measurement; 36 | this.range = range; 37 | this.samples = []; 38 | this.callback = callback; 39 | this.interval = setInterval(this.report.bind(this), interval); 40 | } 41 | 42 | Reporter.prototype.sample = function(){ 43 | this.samples.push({ 44 | timestamp: new Date(), 45 | value: this.measurement.getValue() 46 | }); 47 | }; 48 | 49 | Reporter.prototype.report = function(){ 50 | this.sample(); 51 | var now = new Date(); 52 | var minDate = now.getTime() - this.range; 53 | this.samples = this.samples.filter(function(s) { 54 | return s.timestamp.getTime() > minDate; 55 | }); 56 | this.samples.sort(function(a, b) { 57 | return a.timestamp - b.timestamp; 58 | }); 59 | var oldest = this.samples[0]; 60 | var newest = this.samples[this.samples.length -1]; 61 | var elapsed = newest.timestamp - oldest.timestamp; 62 | if (elapsed <= 0) return; 63 | var accumulated = newest.value - oldest.value; 64 | // we want rate per second, but our time is in milliseconds... compensate by 1000 65 | this.callback(accumulated * 1000 / elapsed); 66 | }; 67 | 68 | Reporter.prototype.reset = function(){ 69 | this.samples = []; 70 | }; -------------------------------------------------------------------------------- /htdocs/lib/Modes.js: -------------------------------------------------------------------------------- 1 | var Modes = { 2 | modes: [], 3 | features: {}, 4 | panels: [], 5 | setModes:function(json){ 6 | this.modes = json.map(function(m){ return new Mode(m); }); 7 | this.updatePanels(); 8 | var bookmarkDialog = $('#openwebrx-dialog-bookmark').bookmarkDialog(); 9 | bookmarkDialog.setUnderlying(this.modes); 10 | bookmarkDialog.setModes(this.modes); 11 | }, 12 | getModes:function(){ 13 | return this.modes; 14 | }, 15 | setFeatures:function(features){ 16 | this.features = features; 17 | this.updatePanels(); 18 | }, 19 | findByModulation:function(modulation){ 20 | matches = this.modes.filter(function(m) { return m.modulation === modulation; }); 21 | if (matches.length) return matches[0] 22 | }, 23 | registerModePanel: function(el) { 24 | this.panels.push(el); 25 | }, 26 | initComplete: function() { 27 | return this.modes.length && Object.keys(this.features).length; 28 | }, 29 | updatePanels: function() { 30 | this.panels.forEach(function(p) { 31 | p.render(); 32 | p.startDemodulator(); 33 | }); 34 | } 35 | }; 36 | 37 | var Mode = function(json){ 38 | this.modulation = json.modulation; 39 | this.name = json.name; 40 | this.type = json.type; 41 | this.requirements = json.requirements; 42 | this.squelch = json.squelch; 43 | if (json.bandpass) { 44 | this.bandpass = json.bandpass; 45 | } 46 | if (json.ifRate) { 47 | this.ifRate = json.ifRate; 48 | } 49 | if (this.type === 'digimode') { 50 | this.underlying = json.underlying; 51 | this.secondaryFft = json.secondaryFft; 52 | } 53 | }; 54 | 55 | Mode.prototype.isAvailable = function(){ 56 | return this.requirements.map(function(r){ 57 | return Modes.features[r]; 58 | }).reduce(function(a, b){ 59 | return a && b; 60 | }, true); 61 | }; 62 | -------------------------------------------------------------------------------- /htdocs/lib/nanoscroller.css: -------------------------------------------------------------------------------- 1 | /** initial setup **/ 2 | .nano { 3 | position : relative; 4 | width : 100%; 5 | height : 100%; 6 | overflow : hidden; 7 | } 8 | .nano > .nano-content { 9 | position : absolute; 10 | overflow : scroll; 11 | overflow-x : hidden; 12 | top : 0; 13 | right : 0; 14 | bottom : 0; 15 | left : 0; 16 | } 17 | .nano > .nano-content:focus { 18 | outline: thin dotted; 19 | } 20 | .nano > .nano-content::-webkit-scrollbar { 21 | display: none; 22 | } 23 | .has-scrollbar > .nano-content::-webkit-scrollbar { 24 | display: block; 25 | } 26 | .nano > .nano-pane { 27 | background : rgba(0,0,0,.25); 28 | position : absolute; 29 | width : 8px; 30 | right : 0; 31 | top : 0; 32 | bottom : 0; 33 | visibility : hidden\9; /* Target only IE7 and IE8 with this hack */ 34 | opacity : .01; 35 | -webkit-transition : .2s; 36 | -moz-transition : .2s; 37 | -o-transition : .2s; 38 | transition : .2s; 39 | -moz-border-radius : 3px; 40 | -webkit-border-radius : 3px; 41 | border-radius : 3px; 42 | } 43 | .nano > .nano-pane > .nano-slider { 44 | background: #444; 45 | background: rgba(0,0,0,.5); 46 | position : relative; 47 | margin : 0 0px; 48 | -moz-border-radius : 4px; 49 | -webkit-border-radius : 4px; 50 | border-radius : 4px; 51 | } 52 | .nano:hover > .nano-pane, .nano-pane.active, .nano-pane.flashed { 53 | visibility : visible\9; /* Target only IE7 and IE8 with this hack */ 54 | opacity : 0.99; 55 | } 56 | -------------------------------------------------------------------------------- /htdocs/lib/settings/ClientList.js: -------------------------------------------------------------------------------- 1 | $.fn.clientList = function() { 2 | this.each(function() { 3 | $(this).on('click', '.client-ban', function(e) { 4 | var mins = $('#ban-minutes').val(); 5 | $.ajax("/ban", { 6 | data: JSON.stringify({ ip: this.value, mins: mins }), 7 | contentType: 'application/json', 8 | method: 'POST' 9 | }).done(function() { 10 | document.location.reload(); 11 | }); 12 | return false; 13 | }); 14 | 15 | $(this).on('click', '.client-unban', function(e) { 16 | $.ajax("/unban", { 17 | data: JSON.stringify({ ip: this.value }), 18 | contentType: 'application/json', 19 | method: 'POST' 20 | }).done(function() { 21 | document.location.reload(); 22 | }); 23 | return false; 24 | }); 25 | }); 26 | 27 | $('#broadcast-send').on('click', function(e) { 28 | var text = $('#broadcast-text').val(); 29 | if (text.length > 0) { 30 | $.ajax("/broadcast", { 31 | data: JSON.stringify({ text: text }), 32 | contentType: 'application/json', 33 | method: 'POST' 34 | }).done(function() { 35 | $('#broadcast-text').val(''); 36 | }); 37 | } 38 | return false; 39 | }); 40 | } 41 | -------------------------------------------------------------------------------- /htdocs/lib/settings/ExponentialInput.js: -------------------------------------------------------------------------------- 1 | $.fn.exponentialInput = function() { 2 | var prefixes = { 3 | 'K': 3, 4 | 'M': 6, 5 | 'G': 9, 6 | 'T': 12 7 | }; 8 | 9 | this.each(function(){ 10 | var $group = $(this); 11 | var currentExponent = 0; 12 | var $input = $group.find('input'); 13 | 14 | var setExponent = function() { 15 | var newExponent = parseInt($exponent.val()); 16 | var delta = currentExponent - newExponent; 17 | if (delta >= 0) { 18 | $input.val(parseFloat($input.val()) * 10 ** delta); 19 | } else { 20 | // should not be necessary to handle this separately, but floating point precision in javascript 21 | // does not handle this well otherwise 22 | $input.val(parseFloat($input.val()) / 10 ** -delta); 23 | } 24 | currentExponent = newExponent; 25 | }; 26 | 27 | $input.on('keydown', function(e) { 28 | var c = String.fromCharCode(e.which); 29 | if (c in prefixes) { 30 | currentExponent = prefixes[c]; 31 | $exponent.val(prefixes[c]); 32 | } 33 | }); 34 | 35 | var $exponent = $group.find('select.exponent'); 36 | $exponent.on('change', setExponent); 37 | 38 | // calculate initial exponent 39 | var value = parseFloat($input.val()); 40 | if (!Number.isNaN(value)) { 41 | $exponent.val(Math.floor(Math.log10(Math.abs(value)) / 3) * 3); 42 | setExponent(); 43 | } 44 | }) 45 | }; -------------------------------------------------------------------------------- /htdocs/lib/settings/GainInput.js: -------------------------------------------------------------------------------- 1 | $.fn.gainInput = function() { 2 | this.each(function() { 3 | var $container = $(this); 4 | 5 | var update = function(value){ 6 | $container.find('.option').hide(); 7 | $container.find('.option.' + value).show(); 8 | } 9 | 10 | var $select = $container.find('select'); 11 | $select.on('change', function(e) { 12 | var value = $(e.target).val(); 13 | update(value); 14 | }); 15 | update($select.val()); 16 | }); 17 | } -------------------------------------------------------------------------------- /htdocs/lib/settings/LogMessages.js: -------------------------------------------------------------------------------- 1 | $.fn.logMessages = function() { 2 | $.each(this, function(){ 3 | $(this).scrollTop(this.scrollHeight); 4 | }); 5 | }; -------------------------------------------------------------------------------- /htdocs/lib/settings/MapInput.js: -------------------------------------------------------------------------------- 1 | $.fn.mapInput = function() { 2 | this.each(function(el) { 3 | var $el = $(this); 4 | var field_id = $el.attr("for"); 5 | var $lat = $('#' + field_id + '-lat'); 6 | var $lon = $('#' + field_id + '-lon'); 7 | $.getScript('https://maps.googleapis.com/maps/api/js?key=' + $el.data('key')).done(function(){ 8 | $el.css('height', '200px'); 9 | var lp = new locationPicker($el.get(0), { 10 | lat: parseFloat($lat.val()), 11 | lng: parseFloat($lon.val()) 12 | }, { 13 | zoom: 7 14 | }); 15 | 16 | google.maps.event.addListener(lp.map, 'idle', function(event){ 17 | var pos = lp.getMarkerPosition(); 18 | $lat.val(pos.lat); 19 | $lon.val(pos.lng); 20 | }); 21 | }); 22 | }); 23 | }; -------------------------------------------------------------------------------- /htdocs/lib/settings/OptionalSection.js: -------------------------------------------------------------------------------- 1 | $.fn.optionalSection = function(){ 2 | this.each(function() { 3 | var $section = $(this); 4 | var $select = $section.find('.optional-select'); 5 | var $optionalInputs = $section.find('.optional-inputs'); 6 | $section.on('click', '.option-add-button', function(e){ 7 | var field = $select.val(); 8 | var group = $optionalInputs.find(".form-group[data-field='" + field + "']"); 9 | group.find('input, select').filter(function(){ 10 | // exclude template inputs 11 | return !$(this).parents('.template').length; 12 | }).prop('disabled', false); 13 | $section.find('hr').before(group); 14 | $select.find('option[value=\'' + field + '\']').remove(); 15 | 16 | return false; 17 | }); 18 | $section.on('click', '.option-remove-button', function(e) { 19 | var group = $(e.target).parents('.form-group') 20 | group.find('input, select').prop('disabled', true); 21 | $optionalInputs.append(group); 22 | var $label = group.find('label'); 23 | var $option = $(''); 24 | $select.append($option); 25 | 26 | return false; 27 | }) 28 | }); 29 | } -------------------------------------------------------------------------------- /htdocs/lib/settings/Profiles.js: -------------------------------------------------------------------------------- 1 | $.fn.profiles = function() { 2 | this.each(function() { 3 | $(this).on('click', '.move-down', function(e) { 4 | location.replace(document.URL.replace(/(\/sdr\/[^\/]+)\/profile\/([^\/]+)$/, '$1/moveprofiledown/$2')); 5 | return false; 6 | }); 7 | 8 | $(this).on('click', '.move-up', function(e) { 9 | location.replace(document.URL.replace(/(\/sdr\/[^\/]+)\/profile\/([^\/]+)$/, '$1/moveprofileup/$2')); 10 | return false; 11 | }); 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /htdocs/lib/settings/SchedulerInput.js: -------------------------------------------------------------------------------- 1 | $.fn.schedulerInput = function() { 2 | this.each(function() { 3 | var $container = $(this); 4 | var $template = $container.find('.template'); 5 | $template.find('input, select').prop('disabled', true); 6 | 7 | var update = function(value){ 8 | $container.find('.option').hide(); 9 | $container.find('.option.' + value).show(); 10 | } 11 | 12 | var $select = $container.find('select.mode'); 13 | $select.on('change', function(e) { 14 | var value = $(e.target).val(); 15 | update(value); 16 | }); 17 | update($select.val()); 18 | 19 | $container.find('.add-button').on('click', function() { 20 | var row = $template.clone(); 21 | row.removeClass('template').show(); 22 | row.find('input, select').prop('disabled', false); 23 | $template.before(row); 24 | 25 | return false; 26 | }); 27 | 28 | $container.on('click', '.remove-button', function(e) { 29 | var row = $(e.target).parents('.scheduler-static-time-inputs'); 30 | row.remove(); 31 | }); 32 | }); 33 | } -------------------------------------------------------------------------------- /htdocs/lib/settings/WaterfallDropdown.js: -------------------------------------------------------------------------------- 1 | $.fn.waterfallDropdown = function(){ 2 | this.each(function(){ 3 | var $select = $(this); 4 | var setVisibility = function() { 5 | var show = $select.val() === 'CUSTOM'; 6 | $('#waterfall_colors').parents('.form-group')[show ? 'show' : 'hide'](); 7 | } 8 | $select.on('change', setVisibility); 9 | setVisibility(); 10 | }) 11 | } -------------------------------------------------------------------------------- /htdocs/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | OpenWebRX+ Login 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | ${header} 14 | 29 | 30 | -------------------------------------------------------------------------------- /htdocs/map-google.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | OpenWebRX+ Map 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | ${header} 17 |
18 |
19 |
20 |

Colors

21 | 26 |
27 |

Features

28 |
    29 |
30 |
31 |

00:00 UTC

32 |
33 | 34 | 35 | -------------------------------------------------------------------------------- /htdocs/map-leaflet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | OpenWebRX+ Map 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | ${header} 17 |
18 |
19 |
20 |

Map

21 | 22 |
23 |

Colors

24 | 29 |
30 |

Features

31 |
    32 |
33 |
34 |

00:00 UTC

35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /htdocs/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xAF/openwebrxplus/5ef0b447d53f57a45a6cc1e4cbdd02cd5de66cc1/htdocs/mstile-144x144.png -------------------------------------------------------------------------------- /htdocs/plugins/receiver/example_theme/example_theme.css: -------------------------------------------------------------------------------- 1 | /* 2 | * colors for the new theme 3 | */ 4 | body.theme-eye-piercer { 5 | --theme-color1: #ff6262; 6 | --theme-color2: #ff626252; 7 | --theme-gradient-color1: #ff6262; 8 | --theme-gradient-color2: #ff0000; 9 | } 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /htdocs/plugins/receiver/example_theme/example_theme.js: -------------------------------------------------------------------------------- 1 | /* 2 | * example plugin, creating a new theme for OpenWebRx+ 3 | */ 4 | 5 | // Add new entry in the Theme selectbox 6 | $('#openwebrx-themes-listbox').append( 7 | $('