├── .gitignore ├── .travis.yml ├── AUTHORS ├── COPYING ├── ChangeLog ├── INSTALL.md ├── LICENCE ├── Makefile.am ├── NEWS ├── README.md ├── TODO.md ├── bootstrap.sh ├── configure.ac ├── doc ├── README.md ├── STATS.md ├── TIMESTAMPS.rst ├── advanced.mux ├── dab_output_formats.txt ├── example.json ├── example.mux ├── remote_control.txt ├── retodrs.pl ├── servicelinking.mux ├── show_dabmux_stats.py ├── stats_dabmux_munin.py ├── stats_zmq2edi_munin.py └── zmq_remote.py ├── gui ├── README.md ├── muxconfig.py ├── muxrc.py ├── odr-dabmux-gui.py ├── rcparam.json ├── static │ ├── intercooler-1.0.1.min.js │ ├── jquery-1.10.2.min.js │ ├── script.js │ ├── stats.js │ └── style.css └── views │ ├── configeditor.tpl │ ├── index.tpl │ ├── rcparam.tpl │ ├── services.tpl │ └── stats.tpl ├── lib ├── ClockTAI.cpp ├── ClockTAI.h ├── Globals.cpp ├── Json.cpp ├── Json.h ├── Log.cpp ├── Log.h ├── ReedSolomon.cpp ├── ReedSolomon.h ├── RemoteControl.cpp ├── RemoteControl.h ├── Socket.cpp ├── Socket.h ├── ThreadsafeQueue.h ├── charset │ ├── README │ ├── charset.cpp │ ├── charset.h │ ├── utf8.h │ └── utf8 │ │ ├── checked.h │ │ ├── core.h │ │ ├── cpp11.h │ │ ├── cpp17.h │ │ ├── cpp20.h │ │ └── unchecked.h ├── crc.c ├── crc.h ├── edi │ ├── PFT.cpp │ ├── PFT.hpp │ ├── STIDecoder.cpp │ ├── STIDecoder.hpp │ ├── STIWriter.cpp │ ├── STIWriter.hpp │ ├── buffer_unpack.hpp │ ├── common.cpp │ └── common.hpp ├── edioutput │ ├── AFPacket.cpp │ ├── AFPacket.h │ ├── EDIConfig.h │ ├── PFT.cpp │ ├── PFT.h │ ├── TagItems.cpp │ ├── TagItems.h │ ├── TagPacket.cpp │ ├── TagPacket.h │ ├── Transport.cpp │ └── Transport.h ├── farsync │ ├── linux │ │ └── farsync.h │ └── windows │ │ ├── fscfg.h │ │ ├── sdci.h │ │ └── smcuser.h ├── fec │ ├── LICENSE │ ├── README.md │ ├── char.h │ ├── decode_rs.h │ ├── decode_rs_char.c │ ├── encode_rs.h │ ├── encode_rs_char.c │ ├── fec.h │ ├── init_rs.h │ ├── init_rs_char.c │ └── rs-common.h └── zmq.hpp ├── m4 ├── ax_boost_asio.m4 ├── ax_boost_base.m4 ├── ax_boost_system.m4 ├── ax_check_compile_flag.m4 ├── ax_cxx_compile_stdcxx.m4 ├── ax_pthread.m4 └── ax_zmq.m4 ├── man └── odr-dabmux.1 └── src ├── ConfigParser.cpp ├── ConfigParser.h ├── DabMultiplexer.cpp ├── DabMultiplexer.h ├── DabMux.cpp ├── DabMux.h ├── Dmb.cpp ├── Dmb.h ├── Eti.cpp ├── Eti.h ├── Interleaver.cpp ├── Interleaver.h ├── ManagementServer.cpp ├── ManagementServer.h ├── MuxElements.cpp ├── MuxElements.h ├── PcDebug.h ├── PrbsGenerator.cpp ├── PrbsGenerator.h ├── TestStatsServer.cpp ├── dabInputDmbFile.cpp ├── dabInputDmbFile.h ├── dabInputDmbUdp.cpp ├── dabInputDmbUdp.h ├── dabOutput ├── dabOutput.h ├── dabOutputFifo.cpp ├── dabOutputFile.cpp ├── dabOutputRaw.cpp ├── dabOutputSimul.cpp ├── dabOutputTcp.cpp ├── dabOutputUdp.cpp ├── dabOutputZMQ.cpp ├── metadata.cpp └── metadata.h ├── fig ├── FIG.cpp ├── FIG.h ├── FIG0.h ├── FIG0_0.cpp ├── FIG0_0.h ├── FIG0_1.cpp ├── FIG0_1.h ├── FIG0_10.cpp ├── FIG0_10.h ├── FIG0_13.cpp ├── FIG0_13.h ├── FIG0_14.cpp ├── FIG0_14.h ├── FIG0_17.cpp ├── FIG0_17.h ├── FIG0_18.cpp ├── FIG0_18.h ├── FIG0_19.cpp ├── FIG0_19.h ├── FIG0_2.cpp ├── FIG0_2.h ├── FIG0_21.cpp ├── FIG0_21.h ├── FIG0_24.cpp ├── FIG0_24.h ├── FIG0_3.cpp ├── FIG0_3.h ├── FIG0_5.cpp ├── FIG0_5.h ├── FIG0_6.cpp ├── FIG0_6.h ├── FIG0_7.cpp ├── FIG0_7.h ├── FIG0_8.cpp ├── FIG0_8.h ├── FIG0_9.cpp ├── FIG0_9.h ├── FIG0structs.h ├── FIG1.cpp ├── FIG1.h ├── FIG2.cpp ├── FIG2.h ├── FIGCarousel.cpp ├── FIGCarousel.h └── TransitionHandler.h ├── input ├── Edi.cpp ├── Edi.h ├── File.cpp ├── File.h ├── Prbs.cpp ├── Prbs.h ├── Udp.cpp ├── Udp.h ├── Zmq.cpp ├── Zmq.h └── inputs.h ├── mpeg.c ├── mpeg.h ├── test_statsserver.sh ├── utils.cpp ├── utils.h ├── zmq2farsync ├── README.md └── zmq2farsync.cpp └── zmqinput-keygen.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.Po 3 | 4 | .*.swp 5 | .directory 6 | 7 | odr-dabmux 8 | odr-zmq2farsync 9 | odr-zmq2edi 10 | zmqinput-keygen 11 | src/dabOutput/.deps/ 12 | src/dabOutput/.dirstamp 13 | 14 | aclocal.m4 15 | build-aux 16 | configure 17 | Makefile.in 18 | Makefile 19 | autom4te.cache 20 | config.h 21 | config.log 22 | config.status 23 | lib/Makefile 24 | src/Makefile 25 | stamp-h1 26 | config.h.in~ 27 | config.h.in 28 | .deps 29 | .dirstamp 30 | *.plist 31 | 32 | cscope.out 33 | ctags 34 | tags 35 | .clang_complete 36 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | dist: focal 3 | 4 | jobs: 5 | include: 6 | # Clang on OSX 7 | - env: MATRIX_EVAL="" CONF="" 8 | os: osx 9 | osx_image: xcode12.2 10 | compiler: clang 11 | 12 | # GCC builds on Linux 13 | - env: MATRIX_EVAL="CC=gcc-10 CXX=g++-10" CONF="--disable-output-edi" 14 | os: linux 15 | arch: amd64 16 | compiler: gcc 17 | addons: &linuxaddons 18 | apt: 19 | packages: &packages 20 | - libzmq3-dev 21 | - libzmq5 22 | - automake 23 | - libtool 24 | - libboost-all-dev 25 | - libcurl4-openssl-dev 26 | - g++-10 27 | 28 | - env: MATRIX_EVAL="CC=gcc-10 CXX=g++-10" CONF="--enable-output-raw" 29 | arch: amd64 30 | compiler: gcc 31 | addons: *linuxaddons 32 | 33 | - env: MATRIX_EVAL="CC=gcc-10 CXX=g++-10" CONF="" 34 | arch: amd64 35 | compiler: gcc 36 | addons: *linuxaddons 37 | 38 | - env: MATRIX_EVAL="CC=gcc-10 CXX=g++-10" CONF="" 39 | arch: arm64 40 | compiler: gcc 41 | addons: *linuxaddons 42 | 43 | before_install: 44 | - eval "${MATRIX_EVAL}" 45 | - | 46 | if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then 47 | brew update 48 | brew install automake || true 49 | brew install zeromq || true 50 | brew install boost || true 51 | brew install curl || true 52 | fi 53 | 54 | script: 55 | - | 56 | ./bootstrap.sh 57 | ./configure $CONF 58 | make 59 | 60 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Jean-Daniel Langlois <> for 2 | the Communications Research Centre, Ottawa, Canada, 2002: 3 | First version of DabMux.cpp (a.k.a. createETI.cpp) 4 | 5 | Pascal Charest for 6 | the Communications Research Centre, Ottawa, Canada, 2002-2009: 7 | Principal developer and maintainer of CRC-DABMUX 8 | 9 | Jean-Michel Bouffard for 10 | the Communications Research Centre, Ottawa, Canada, 2004: 11 | Minor changes for crc.c, DabMux.cpp 12 | 13 | Martin-Pierre Lussier for 14 | the Communications Research Centre, Ottawa, Canada, 2004, 2006: 15 | Minor changes for PcDebug.h, bridge.c, bridge.h, dabOutput.cpp 16 | 17 | FarSite Communications Ltd. 18 | All files included in lib/farsite/ 19 | 20 | Robin Alexander 21 | Improvements on the Web GUI 22 | 23 | Matthias P. Braendli for 24 | Opendigitalradio, since 2012: 25 | Configuration file 26 | Time encoding into necessary for SFN using ODR-DabMod and third-party modulators 27 | Service linking, announcements, frequency information 28 | EDI inputs and outputs 29 | Improved logging (syslog) and monitoring 30 | Remote Control 31 | ZeroMQ ETI output and contribution inputs 32 | STI/D UDP input 33 | 34 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | You have 3 ways to install odr-dabmux on your host: 2 | 3 | # Using your linux distribution packaging system 4 | `odr-dabmux` is available on the official repositories of several debian-based distributions, such as Debian 5 | (from Debian 12), Ubuntu (from 24.10), Opensuse and Arch. 6 | 7 | If you are using Debian 12 (Bookworm), you will need to 8 | [add the backports repository](https://backports.debian.org/Instructions/) 9 | 10 | **Notice**: this debian package does not include the Mux Web Management GUI 11 | 12 | # Using installation scripts 13 | If your linux distribution is debian-based, you can install odr-dabmux 14 | as well as the other main components of the mmbTools set with the 15 | [Opendigitalradio dab-scripts](https://github.com/opendigitalradio/dab-scripts.git) 16 | 17 | # Compiling manually 18 | Unlike the 2 previous options, this one allows you to compile odr-dabmux with the features you really need. 19 | 20 | ## Dependencies 21 | ### Debian Bullseye-based OS: 22 | ``` 23 | # Required packages 24 | ## C++11 compiler 25 | sudo apt-get install --yes build-essential automake libtool 26 | 27 | ## ZeroMQ 28 | sudo apt-get install --yes libzmq3-dev libzmq5 29 | 30 | ## Boost 1.48 or later 31 | sudo apt-get install --yes libboost-system-dev 32 | 33 | # optional packages 34 | ## cURL to download the TAI-UTC bulletin, needed for timestamps in EDI output 35 | sudo apt-get install --yes libcurl4-openssl-dev 36 | ``` 37 | 38 | ### Dependencies on other linux distributions 39 | For CentOS, in addition to the packages needed to install a compiler, install the packages: 40 | boost-devel libcurl-devel zeromq-devel 41 | 42 | Third-party RPM packages are maintained by RaBe, and are built by the 43 | [openSUSE Build Service](https://build.opensuse.org/project/show/home:radiorabe:dab). 44 | For questions regarding these packages, please get in touch with the maintainer of 45 | the [radio RaBe repository](https://github.com/radiorabe/). 46 | 47 | For openSUSE, mnhauke is maintaining packages, also built using 48 | [OBS](https://build.opensuse.org/project/show/home:mnhauke:ODR-mmbTools). 49 | 50 | ## Compilation 51 | The *master* branch in the repository always points to the 52 | latest release. If you are looking for a new feature or bug-fix 53 | that did not yet make its way into a release, you can clone the 54 | *next* branch from the repository. 55 | 56 | 1. Clone this repository: 57 | ``` 58 | # stable version: 59 | git clone https://github.com/Opendigitalradio/ODR-DabMux.git 60 | 61 | # or development version (at your own risk): 62 | git clone https://github.com/Opendigitalradio/ODR-DabMux.git -b next 63 | ``` 64 | 1. Configure the project 65 | ``` 66 | cd ODR-DabMux 67 | ./bootstrap 68 | ./configure 69 | ``` 70 | 1. Compile and install: 71 | ``` 72 | make 73 | sudo make install 74 | ``` 75 | 76 | Notes: 77 | - It is advised to run the bootstrap and configure steps again every time you pull updates from the repository. 78 | - The configure script can be launched with a variety of options. Run `./configure --help` to display a complete list 79 | 80 | # Develop on OSX and FreeBSD 81 | If you want to develop on OSX platform install the necessary build tools 82 | and dependencies with brew 83 | 84 | brew install boost zeromq automake curl 85 | 86 | On FreeBSD, pkg installs all dependencies to /usr/local, but the build 87 | tools will not search there by default. Set the following environment variables 88 | before calling ./configure 89 | 90 | LDFLAGS="-L/usr/local/lib" 91 | CFLAGS="-I/usr/local/include" 92 | CXXFLAGS="-I/usr/local/include" 93 | 94 | On both systems, RAW output is not available. Note that these systems 95 | are not tested regularly. 96 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | LICENSING 2 | ========= 3 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty 4 | the Queen in Right of Canada (Communications Research Center Canada) 5 | 6 | Copyright (C) 2020 7 | Matthias P. Braendli, http://www.opendigitalradio.org 8 | 9 | This file is part of ODR-DabMux. ODR-DabMux is a fork of CRC-DabMux, 10 | which was developed by the Communications Research Center Canada. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | 25 | 26 | KA9Q FEC routines 27 | ----------------- 28 | 29 | lib/fec/ contains code from KA9Q's fec library. Please see 30 | lib/fec/README.md and lib/fec/LICENSING 31 | 32 | Other parts 33 | ----------- 34 | 35 | lib/edi/PFT.{hpp,cpp} are APACHE 2.0 licensed. 36 | 37 | lib/charset contains a BSD-licensed UTF-8 library. 38 | 39 | lib/zmq.hpp is BSD-licensed. 40 | 41 | The farsync driver in lib/farsync is GPLv2+ licensed. 42 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Opendigitalradio/ODR-DabMux/354872579c8d4d9184555bdfc2888abaf0bd445c/NEWS -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Overview 2 | ======== 3 | 4 | ODR-DabMux is a *DAB (Digital Audio Broadcasting) multiplexer* compliant to 5 | ETSI EN 300 401. It is the continuation of the work started by the 6 | Communications Research Center Canada on CRC-DabMux, and is now pursued in the 7 | [Opendigitalradio project](http://opendigitalradio.org). 8 | 9 | ODR-DabMux is part of the ODR-mmbTools tool set. More information about the 10 | ODR-mmbTools is available in the *guide*, available on the 11 | [Opendigitalradio mmbTools page](http://www.opendigitalradio.org/mmbtools). 12 | 13 | Features of ODR-DabMux: 14 | 15 | - Standards-compliant DAB multiplexer 16 | - Configuration file, see doc/example.mux and doc/example.json 17 | - Timestamping support required for SFN 18 | - Logging to syslog 19 | - Monitoring using munin tool 20 | - Includes a Telnet and ZMQ Remote Control for setting/getting parameters 21 | - EDI input and output, both over UDP and TCP 22 | - Support for FarSync TE1 and TE1e cards (G.703) 23 | - Something that will (with your help?) one day become a nice GUI for 24 | configuration, see `gui/README.md` 25 | - Experimental STI-D(PI, X)/RTP input intended to be compatible 26 | with compliant encoders. 27 | - ZeroMQ and TCP ETI outputs that can be used with ODR-DabMod 28 | - ZeroMQ input that can be used with ODR-AudioEnc 29 | which supports CURVE authentication 30 | 31 | Additional tools: 32 | 33 | `odr-zmq2farsync`, a tool that can drive a FarSync card from a ZeroMQ ETI stream. 34 | 35 | The `src/` directory contains the source code of ODR-DabMux and the additional 36 | tools. 37 | 38 | The `doc/` directory contains the ODR-DabMux documentation, a few example 39 | configuration files, and the munin and xymon scripts for the statistics server. 40 | 41 | The `lib/` directory contains source code of libraries needed to build 42 | ODR-DabMux. 43 | 44 | Up to v4.5, this repository also contained 45 | `odr-zmq2edi`, a tool that can convert a ZeroMQ ETI stream to an EDI or ZMQ stream. 46 | This was superseded by `digris-zmq-converter` in the 47 | [digris-edi-zmq-bridge](https://github.com/digris/digris-edi-zmq-bridge) repository. 48 | 49 | Install 50 | ======= 51 | 52 | See `INSTALL.md` file for installation instructions. 53 | 54 | Licence 55 | ======= 56 | 57 | See the files `LICENCE` and `COPYING` 58 | 59 | Contributions and Contact 60 | ========================= 61 | 62 | Contributions to this tool are welcome, you can reach users and developers 63 | through the 64 | [ODR-mmbTools group](https://groups.io/g/odr-mmbtools) 65 | or any other channels mentioned on the ODR website. 66 | 67 | There is a list of ideas and thoughts about new possible features and improvements 68 | in the `TODO.md` file. 69 | 70 | Developed by: 71 | 72 | Matthias P. Braendli *matthias [at] mpb [dot] li* 73 | 74 | Pascal Charest *pascal [dot] charest [at] crc [dot] ca* 75 | 76 | Acknowledgements 77 | ================ 78 | 79 | David Lutton, Yoann Queret, Stefan Pöschel and Maik for bug-fix patches, 80 | Wim Nelis for the Xymon monitoring scripts, 81 | and many more for feedback and bug reports. 82 | 83 | - [http://opendigitalradio.org/](http://opendigitalradio.org/) 84 | 85 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | This TODO file lists ideas and features for future developments. They are 2 | more or less ordered according to their benefit, but that is subjective 3 | to some degree. 4 | 5 | Unless written, no activity has been started on the topics. 6 | 7 | 8 | Explicit Service Linking 9 | ------------------------ 10 | It is impossible to activate/deactive linkage sets. Commit 5c3c6d7 added 11 | some code to transmit a FIG0/6 CEI, but this was subsequently reverted 12 | because it was not tested enough. 13 | 14 | 15 | Inputs for packet data 16 | ---------------------- 17 | It is currently unclear what input formats and sources work for packet data, 18 | and which ones would make sense to add. 19 | 20 | Also, there is no documentation on the possibilites of packet data. 21 | 22 | 23 | Improvements for inputs 24 | ----------------------- 25 | Add statistics to UDP input, in a similar way that ZeroMQ offers statistics. 26 | This would mean we have to move the packet buffer from the operating system 27 | into our own buffer, so that we can actually get the statistics. 28 | 29 | 30 | Fix DMB input 31 | ------------- 32 | The code that does interleaving and reed-solomon encoding for DMB is not used 33 | anymore, and is untested. The relevant parts are `src/dabInputDmb*` and 34 | `src/Dmb.cpp` 35 | 36 | 37 | Communicate Leap Seconds 38 | ------------------------ 39 | Actually, we're supposed to say in FIG0/10 when there is a UTC leap second 40 | upcoming, but since that's not trivial to find out because the POSIX time 41 | concept is totally unaware of that, this is not done. We need to know for EDI 42 | TIST, and the ClockTAI class can get the information from the Internet, but it 43 | is not used in FIG0/10. 44 | 45 | 46 | Implement FIG0/20 Service List 47 | ------------------------------ 48 | See ETSI TS 103 176 49 | -------------------------------------------------------------------------------- /bootstrap.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | autoreconf --install && \ 4 | echo "You can call ./configure now" 5 | -------------------------------------------------------------------------------- /doc/README.md: -------------------------------------------------------------------------------- 1 | Description 2 | =========== 3 | ODR-DabMux is a software multiplexer that generates an ETI stream from audio 4 | and data streams. Because of its software based architecture, many typical DAB 5 | services can be generated and multiplexed on a single PC platform with live or 6 | pre-recorded sources. 7 | 8 | A DAB multiplex configuration is composed of one ensemble. An ensemble is the 9 | entity that receivers tune to and process. An ensemble contains several 10 | services. A service is the listener-selectable output. Each service contains 11 | one mandatory service component which is called primary component. An audio 12 | primary component define a program service while a data primary component 13 | define a data service. Service can contain additional components which are 14 | called secondary components. Maximum total number of components is 12 for 15 | program services and 11 for data services. A service component is a link to one 16 | subchannel (or Fast Information Data Channel). A subchannel is the physical 17 | space used within the common interleaved frame. 18 | 19 | __________________________________________________ 20 | ENSEMBLE | ODR-Ensemble | 21 | |__________________________________________________| 22 | | | | 23 | | | | 24 | _______V______ _______V______ _______V______ 25 | SERVICES | ODR-Service1 | | ODR-Service2 | | ODR-Service3 | 26 | |______________| |______________| |______________| 27 | | | | | |______ | 28 | | | | | | | 29 | __V__ __V__ __V__ __V__ __V__ __V__ 30 | SERVICE | SC1 | | SC2 | | SC3 | | SC4 | | SC5 | | SC6 | 31 | COMPONENTS |_____| |_____| |_____| |_____| |_____| |_____| 32 | | | _____| | | ____| 33 | | | | | | | 34 | __________ __V________V__V______________V________V___V_______ 35 | | MCI | SI | | SubCh1 | SubCh9 | ... | SubCh3 | SubCh60 | ... | 36 | |_____|____| |________|________|_______|________|_________|_____| 37 | Fast Information Ch. Main Service Channel 38 | COMMON INTERLEAVED FRAME 39 | 40 | Files in this folder 41 | ==================== 42 | The configuration is given in a file, this folder contains examples. 43 | 44 | A basic example is in the file *example.mux*, a more complete view of the 45 | settings is available in *advanced.mux* and configuration settings related to 46 | service linking are shown in *servicelinking.mux* 47 | 48 | An explanation on how to use the remote control is in *remote_control.txt*, and 49 | *zmq_remote.py* illustrates how to control ODR-DabMux using the ZMQ remote 50 | control interface. 51 | 52 | Two scripts are used for monitoring systems: *stats_dabmux_munin.py* for Munin, 53 | and *retodrs.pl* for Xymon. You can use *show_dabmux_stats.py* to print the 54 | statistics to console. The values are described in *STATS.md* 55 | 56 | *DabMux.1* is an old manpage that describes the command line options that 57 | existed in past versions. It is kept for archive. 58 | 59 | -------------------------------------------------------------------------------- /doc/STATS.md: -------------------------------------------------------------------------------- 1 | Stats available through Management Server 2 | ========================================= 3 | 4 | Interface 5 | --------- 6 | 7 | The management server makes statistics about the inputs and EDI/TCP outputs 8 | available through a ZMQ request/reply socket. 9 | 10 | The `show_dabmux_stats.py` illustrates how to access this information. 11 | 12 | Meaning of values for inputs 13 | ---------------------------- 14 | 15 | `max` and `min` indicate input buffer fullness in bytes. 16 | 17 | `under` and `over` count the number of buffer underruns and overruns. 18 | 19 | `audio L` and `audio R` show the maximum audio level in dBFS over the last 500ms. 20 | 21 | `peak L` and `audio R` show the max audio level in dBFS over the last 5 minutes. 22 | 23 | The audio levels are measured in the audio encoder and carried in the EDI 24 | `ODRa` TAG, or in the ZMQ metadata. Otherwise ODR-DabMux would have to decode 25 | all audio contributions to measure the audio level. 26 | 27 | `State` is either NoData, Unstable, Silence, Streaming. 28 | Unstable means that underruns or overruns have occurred in the previous 30 minutes. 29 | Silence means the stream is working, but audio levels are always below -50dBFS. 30 | 31 | `version` and `uptime` are fields directly coming from the contribution source, 32 | and are only supported for the EDI input. These are carried over EDI using custom 33 | TAG `ODRv` (see function `parse_odr_version_data` in `lib/edi/common.cpp`). 34 | 35 | -------------------------------------------------------------------------------- /doc/TIMESTAMPS.rst: -------------------------------------------------------------------------------- 1 | Some knowledge accumulated about timestamping 2 | ============================================= 3 | 4 | The meaning of the timestamps changed between v2.3.1 and v3.0.0, this document gives some guidance about the interaction between different settings. 5 | 6 | The following table tries to summarise the differences. 7 | 8 | +-----------------------------+----------------------------------------------+-------------------------------------+-----------------------------------------------+ 9 | | ODR-DabMux version | Meaning of timestamp inside EDI | ODR-ZMQ2EDI wait time w | Offset that should be set in the mod | 10 | +=============================+==============================================+=====================================+===============================================+ 11 | | Up to and including v2.3.1 | t_frame = t_mux (No offset in mux available) | positive, meaning delay after t_mux | Something larger than w + mod processing time | 12 | +-----------------------------+----------------------------------------------+-------------------------------------+-----------------------------------------------+ 13 | | Later than v2.3.1 | t_frame = t_tx = t_mux + tist_offset | negative, meaning delay before t_tx | Something larger than mod processing time | 14 | +-----------------------------+----------------------------------------------+-------------------------------------+-----------------------------------------------+ 15 | 16 | The edilib tool decodes both EDI timestamp and MNSC, and can be used to verify both are identical. 17 | 18 | Issues in ODR-DabMux v2.3.1 19 | --------------------------- 20 | 21 | Running ODR-DabMux against the absolute timestamp firmware has uncovered a few issues: 22 | 23 | * At startup, the UTCO was not properly applied to the EDI seconds. This offset was 5 seconds (TAI-UTC offset - 32s, see EDI spec); 24 | * odr-zmq2edi did not compensate for UTCO, hiding the above issue; 25 | * ODR-DabMux needs a configurable offset; 26 | * (minor) MNSC and EDI timestamps did not use the same internal representation, making it difficult to prove that they encode the same value; 27 | * (minor) odr-zmq2edi swapped endianness when regenerating EDI from ETI (minor because only ODR-DabMod considers MNSC, and usually isn't used with EDI); 28 | 29 | **Important** Do not combine odr-zmq2edi with odr-dabmux of a different version! 30 | 31 | Do not combine digris-zmq-converter with odr-dabmux older than v4! 32 | 33 | -------------------------------------------------------------------------------- /doc/dab_output_formats.txt: -------------------------------------------------------------------------------- 1 | ODR-DabMux supports three output formats for the ETI stream. 2 | 3 | The three formats are called 'framed', 'streamed' and 'raw'. 4 | 5 | The framed format is used for saving a finite ETI stream into a file. Each frame does 6 | not contain any padding, and the format can be described as follows: 7 | 8 | uint32_t nbFrames 9 | // for each frame 10 | uint16_t frameSize 11 | uint8_t data[ frameSize ] 12 | 13 | 14 | When streaming data, in which case the number of frames is not known in advance, 15 | the streamed format can be used. This format is identical to the first one except for the 16 | missing nbFrames. 17 | 18 | // for each frame 19 | uint16_t frameSize 20 | uint8_t data[ frameSize ] 21 | 22 | 23 | The raw format corresponds to ETI(NI), where each frame has a constant size of 6144 24 | Bytes. The padding in this case is necessary. 25 | 26 | // for each frame 27 | uint8_t data [6144] 28 | 29 | In order to select the format, the following syntax for the -O option or the 30 | output setting in the configuration file is: 31 | 32 | file://filename?type=format 33 | 34 | where format is one of framed, streamed or raw, e.g. 35 | 36 | file:///tmp/mux.eti?type=raw 37 | 38 | saves a raw ETI file to /tmp/mux.eti 39 | 40 | -------------------------------------------------------------------------------- /doc/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "_comment": "This is the same as example.mux, but in JSON format. JSON doesn't really support comments, so please refer to the example.mux and advanced.mux for documentation of the settings", 3 | "general": { 4 | "dabmode": 1, 5 | "nbframes": 0, 6 | "syslog": false, 7 | "tist": false, 8 | "tist_offset": 0, 9 | "managementport": 12720 10 | }, 11 | "remotecontrol": { 12 | "telnetport": 12721, 13 | "zmqendpoint": "tcp://lo:12722" 14 | }, 15 | "ensemble": { 16 | "id": "0x4fff", 17 | "ecc": "0xe1", 18 | "local-time-offset": "auto", 19 | "reconfig-counter": "hash", 20 | "label": "OpenDigitalRadio", 21 | "shortlabel": "ODR" 22 | }, 23 | "services": { 24 | "srv-fu": { 25 | "id": "0x4daa", 26 | "label": "Fünk" 27 | }, 28 | "srv-ri": { 29 | "id": "0x5dab", 30 | "ecc": "0xe0", 31 | "label": "Rick" 32 | } 33 | }, 34 | "subchannels": { 35 | "sub-fu": { 36 | "type": "audio", 37 | "bitrate": 128, 38 | "id": 10, 39 | "protection": 3, 40 | "inputfile": "funk.mp2" 41 | }, 42 | "sub-bla": { 43 | "type": "audio", 44 | "bitrate": 96, 45 | "id": 1, 46 | "protection": 1, 47 | 48 | "inputproto": "edi", 49 | "inputuri": "tcp://0.0.0.0:9001", 50 | "buffer-management": "prebuffering", 51 | "buffer": 40, 52 | "prebuffering": 20 53 | }, 54 | "sub-ri": { 55 | "type": "dabplus", 56 | "bitrate": 96, 57 | "id": 1, 58 | "protection": 3, 59 | 60 | "inputproto": "edi", 61 | "inputuri": "tcp://127.0.0.1:9000", 62 | "buffer-management": "timestamped", 63 | 64 | "buffer": 500, 65 | "tist-delay": 10 66 | } 67 | }, 68 | "components": { 69 | "comp-fu": { 70 | "service": "srv-fu", 71 | "subchannel": "sub-fu" 72 | }, 73 | "comp-ri": { 74 | "service": "srv-ri", 75 | "subchannel": "sub-ri", 76 | 77 | "user-applications": { 78 | "userapp": "slideshow" 79 | } 80 | } 81 | }, 82 | "outputs": { 83 | "throttle": "simul://", 84 | "stdout": "fifo:///dev/stdout?type=raw", 85 | "edi": { 86 | "destinations": { 87 | "example_tcp": { 88 | "protocol": "tcp", 89 | "listenport": 13000 90 | } 91 | } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /doc/zmq_remote.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This is an example program that illustrates 4 | # how to interact with the zeromq remote control 5 | # 6 | # LICENSE: see bottom of file 7 | 8 | import sys 9 | import zmq 10 | 11 | context = zmq.Context() 12 | 13 | sock = context.socket(zmq.REQ) 14 | 15 | poller = zmq.Poller() 16 | poller.register(sock, zmq.POLLIN) 17 | 18 | if len(sys.argv) < 2: 19 | print("Usage: program url cmd [args...]", file=sys.stderr) 20 | sys.exit(1) 21 | 22 | sock.connect(sys.argv[1]) 23 | 24 | message_parts = sys.argv[2:] 25 | 26 | # first do a ping test 27 | 28 | print("ping", file=sys.stderr) 29 | sock.send(b"ping") 30 | 31 | socks = dict(poller.poll(1000)) 32 | if socks: 33 | if socks.get(sock) == zmq.POLLIN: 34 | 35 | data = sock.recv_multipart() 36 | print("Received: {}".format(len(data)), file=sys.stderr) 37 | for i,part in enumerate(data): 38 | print(" {}".format(part), file=sys.stderr) 39 | 40 | for i, part in enumerate(message_parts): 41 | if i == len(message_parts) - 1: 42 | f = 0 43 | else: 44 | f = zmq.SNDMORE 45 | 46 | print("Send {}({}): '{}'".format(i, f, part), file=sys.stderr) 47 | 48 | sock.send(part.encode(), flags=f) 49 | 50 | data = sock.recv_multipart() 51 | 52 | print("Received: {}".format(len(data)), file=sys.stderr) 53 | for i, part in enumerate(data): 54 | if message_parts[0] == 'showjson': 55 | # This allows you to pipe the JSON into another tool 56 | print(part.decode()) 57 | else: 58 | print(" RX {}: {}".format(i, part.decode().replace('\n',' ')), file=sys.stderr) 59 | 60 | else: 61 | print("ZMQ error: timeout", file=sys.stderr) 62 | context.destroy(linger=5) 63 | 64 | # This is free and unencumbered software released into the public domain. 65 | # 66 | # Anyone is free to copy, modify, publish, use, compile, sell, or 67 | # distribute this software, either in source code form or as a compiled 68 | # binary, for any purpose, commercial or non-commercial, and by any 69 | # means. 70 | # 71 | # In jurisdictions that recognize copyright laws, the author or authors 72 | # of this software dedicate any and all copyright interest in the 73 | # software to the public domain. We make this dedication for the benefit 74 | # of the public at large and to the detriment of our heirs and 75 | # successors. We intend this dedication to be an overt act of 76 | # relinquishment in perpetuity of all present and future rights to this 77 | # software under copyright law. 78 | # 79 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 80 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 81 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 82 | # IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 83 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 84 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 85 | # OTHER DEALINGS IN THE SOFTWARE. 86 | # 87 | # For more information, please refer to 88 | 89 | 90 | -------------------------------------------------------------------------------- /gui/README.md: -------------------------------------------------------------------------------- 1 | The ODR-DabMux Web Management GUI 2 | ================================= 3 | 4 | The whole world has repeatedly been asking for a graphical administration 5 | console for the ODR-mmbTools. I give in now, and start working on this 6 | web-based GUI. 7 | 8 | In the current state, it can display part of the configuration of a running 9 | ODR-DabMux in your browser. It doesn't seem like much, but you *will* be 10 | impressed. 11 | 12 | Usage 13 | ----- 14 | 15 | Launch ODR-DabMux with your preferred multiplex, and enable the statistics and 16 | management server in the configuration file to port 12720, and the zeromq RC on 17 | tcp://lo:12722 18 | 19 | Start the gui/odr-dabmux-gui.py script on the same machine 20 | 21 | Connect to http://localhost:8000 22 | 23 | Admire the fabulously well-designed presentation of the configuration. In the 24 | remote control tab, you can interact with the ODR-DabMux RC to get an set 25 | parameters. 26 | 27 | Expect more features to come: Better design; integrated statistics, dynamically 28 | updated information, configuration upload and download, less ridiculous README, 29 | and much more. We can even start dreaming about live multiplex reconfiguration. 30 | 31 | 2016-10-07 mpb 32 | 33 | -------------------------------------------------------------------------------- /gui/muxrc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (C) 2019 5 | # Matthias P. Braendli, matthias.braendli@mpb.li 6 | # 7 | # http://www.opendigitalradio.org 8 | # 9 | # This file is part of ODR-DabMux. 10 | # 11 | # ODR-DabMux is free software: you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as 13 | # published by the Free Software Foundation, either version 3 of the 14 | # License, or (at your option) any later version. 15 | # 16 | # ODR-DabMux is distributed in the hope that it will be useful, 17 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | # GNU General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with ODR-DabMux. If not, see . 23 | import zmq 24 | import json 25 | 26 | class RCParameter(object): 27 | def __init__(self, param, value): 28 | self.param = param 29 | self.value = value 30 | 31 | class RCModule(object): 32 | """Container object for RC module""" 33 | def __init__(self, name): 34 | self.name = name 35 | self.parameters = [] 36 | 37 | class MuxRemoteControl(object): 38 | """Interact with ODR-DabMux using the ZMQ RC""" 39 | 40 | def __init__(self, mux_host, mux_port=12722): 41 | self._host = mux_host 42 | self._port = mux_port 43 | self._ctx = zmq.Context() 44 | 45 | self.module_list = [] 46 | 47 | def zRead(self, message_parts): 48 | sock = zmq.Socket(self._ctx, zmq.REQ) 49 | sock.setsockopt(zmq.LINGER, 0) 50 | sock.connect("tcp://{}:{}".format(self._host, self._port)) 51 | 52 | for i, part in enumerate(message_parts): 53 | if i == len(message_parts) - 1: 54 | f = 0 55 | else: 56 | f = zmq.SNDMORE 57 | 58 | print("Send {} {}".format(i, part)) 59 | sock.send(part.encode(), flags=f) 60 | 61 | print("Poll") 62 | 63 | # use poll for timeouts: 64 | poller = zmq.Poller() 65 | poller.register(sock, zmq.POLLIN) 66 | if poller.poll(5*1000): # 5s timeout in milliseconds 67 | recv = sock.recv_multipart() 68 | print("RX {}".format(recv)) 69 | sock.close() 70 | return recv 71 | else: 72 | raise IOError("Timeout processing ZMQ request") 73 | 74 | def load(self): 75 | """Load the list of RC modules""" 76 | module_jsons = self.zRead(['list']) 77 | 78 | self.module_list = [] 79 | 80 | for module_json in module_jsons: 81 | module = json.loads(module_json) 82 | name = module['name'] 83 | mod = RCModule(name) 84 | module_params = self.zRead(['show', name]) 85 | print("m_p", module_params) 86 | 87 | for param in module_params: 88 | p, v = param.split(b': ') 89 | mod.parameters.append(RCParameter(p, v)) 90 | 91 | self.module_list.append(mod) 92 | 93 | def get_modules(self): 94 | return self.module_list 95 | 96 | def get_param_value(self, module, param): 97 | value = self.zRead(['get', module, param]) 98 | if value[0] == b'fail': 99 | raise ValueError("Error getting param: {}".format(value[1])) 100 | else: 101 | return value[0] 102 | 103 | def set_param_value(self, module, param, value): 104 | ret = self.zRead(['set', module, param, value]) 105 | if ret[0] == b'fail': 106 | raise ValueError("Error getting param: {}".format(ret[1])) 107 | 108 | -------------------------------------------------------------------------------- /gui/rcparam.json: -------------------------------------------------------------------------------- 1 | { 2 | "labels": { 3 | "buffermanagement":"Buffer management", 4 | "ptysd":"Program-type mode", 5 | "pty":"Program type" 6 | }, 7 | "buffermanagement": [ 8 | {"value":"prebuffering", "desc":"prebuffering"}, 9 | {"value":"timestamped", "desc":"timestamped"} 10 | ], 11 | "ptysd": [ 12 | {"value":"dynamic", "desc":"dynamic"}, 13 | {"value":"static", "desc":"static"} 14 | ], 15 | "pty": [ 16 | {"value":"0", "desc":"None"}, 17 | {"value":"1", "desc":"News"}, 18 | {"value":"2", "desc":"Affairs"}, 19 | {"value":"3", "desc":"Info"}, 20 | {"value":"4", "desc":"Sport"}, 21 | {"value":"5", "desc":"Educate"}, 22 | {"value":"6", "desc":"Drama"}, 23 | {"value":"7", "desc":"Arts"}, 24 | {"value":"8", "desc":"Science"}, 25 | {"value":"9", "desc":"Talk"}, 26 | {"value":"10", "desc":"Pop"}, 27 | {"value":"11", "desc":"Rock"}, 28 | {"value":"12", "desc":"Easy"}, 29 | {"value":"13", "desc":"Light classics"}, 30 | {"value":"14", "desc":"Classics"}, 31 | {"value":"15", "desc":"Other music"}, 32 | {"value":"16", "desc":"Weather"}, 33 | {"value":"17", "desc":"Finance"}, 34 | {"value":"18", "desc":"Children"}, 35 | {"value":"19", "desc":"Factual"}, 36 | {"value":"20", "desc":"Religion"}, 37 | {"value":"21", "desc":"Phone in"}, 38 | {"value":"22", "desc":"Travel"}, 39 | {"value":"23", "desc":"Leisure"}, 40 | {"value":"24", "desc":"Jazz"}, 41 | {"value":"25", "desc":"Country"}, 42 | {"value":"26", "desc":"National music"}, 43 | {"value":"27", "desc":"Oldies"}, 44 | {"value":"28", "desc":"Folk"}, 45 | {"value":"29", "desc":"Document"} 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /gui/static/script.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | 3 | }); 4 | 5 | -------------------------------------------------------------------------------- /gui/static/stats.js: -------------------------------------------------------------------------------- 1 | var updatefunc = function(event) { 2 | $('#statdata p').remove(); 3 | $.getJSON('/stats.json', function(result) { 4 | $.each(result, function(name) { 5 | // TODO: use a hidden template inside the DOM instead 6 | // of building the HTML here 7 | $("

") 8 | .append(result[name]['inputstat']['num_underruns']) 9 | .appendTo('#statdata'); 10 | }); 11 | }); 12 | } 13 | 14 | // Handle clicks on the to change visiblity of panes 15 | setInterval(updatefunc, 1000); 16 | 17 | 18 | -------------------------------------------------------------------------------- /gui/static/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: "Lucida Sans Unicode","Lucida Grande",Sans-Serif; 3 | color: #3E3E3E; 4 | font-size: 12px; 5 | } 6 | 7 | p { 8 | padding: 5px; 9 | } 10 | 11 | div.cadre{ 12 | border: 1px solid #999; 13 | padding: 0 10px; 14 | margin: 5px; 15 | } 16 | 17 | #info{ 18 | width: 600px; 19 | border: 1px solid #999; 20 | padding: 0 10px; 21 | } 22 | #info p { 23 | width: inherit; 24 | background-color: inherit; 25 | } 26 | #info-nav{ 27 | margin: 0; 28 | padding: 3px 0; 29 | width: 100%; 30 | list-style: none; 31 | } 32 | #info-nav li{ 33 | display: inline; 34 | background: #ccc; 35 | border: 1px solid #888; 36 | border-bottom: 0; 37 | margin-right:2px; 38 | padding: 3px; 39 | } 40 | #info-nav li a:hover{ 41 | color:#d15600; 42 | } 43 | #info-nav li.current{ 44 | background: #fff; 45 | padding-bottom: 4px; 46 | } 47 | 48 | #celebs { 49 | clear: both; 50 | } 51 | 52 | table { 53 | border-collapse:collapse; 54 | font-size:12px; 55 | margin:0 20px 20px 20px; 56 | border-top:2px solid #015287; 57 | width:480px; 58 | } 59 | 60 | th { 61 | border-bottom: 2px solid #015287; 62 | color: #D15600; 63 | font-size: 14px; 64 | font-weight: normal; 65 | text-align: left; 66 | padding: 3px 8px; 67 | } 68 | 69 | td { 70 | padding: 6px; 71 | } 72 | 73 | 74 | -------------------------------------------------------------------------------- /gui/views/configeditor.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ODR-DabMux Configuration Editor 7 | 8 | 9 | 10 |

Configuration for {{version}}

11 | 12 |

Reload

13 | 14 | {% if message %} 15 |

{{message}}

16 | {% endif %} 17 | 18 |
19 |

20 | 21 |

22 | 23 |

24 | 25 |

26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /gui/views/rcparam.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ODR-DabMux Configuration 5 | 6 | 7 | 8 | 9 | 10 | 11 |

Remote-Control: module {{module}}

12 |
13 |
14 |

15 | {% if not list %} 16 | 17 | 18 | {% else %} 19 | 20 | 29 | {% endif %} 30 |

31 | 32 |

33 |

34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /gui/views/services.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ODR-DabMux Services 5 | 6 | 7 | 8 | 9 |

Services for {{version}}

10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | {% for s in services %} 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | {% endfor %} 29 |
ServiceIdLabelShort labelProgram typeLanguage
{{s.name}}{{s.id}}{{s.label}}{{s.shortlabel}}{{s.pty}}{{s.language}}
30 | 31 | -------------------------------------------------------------------------------- /gui/views/stats.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ODR-DabMux Statistics 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Subchannel stats for {{version}}

13 | 14 | Update 15 | 16 |
17 |

Subchannels

18 |
19 |
20 | 21 | -------------------------------------------------------------------------------- /lib/Globals.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 3 | Her Majesty the Queen in Right of Canada (Communications Research 4 | Center Canada) 5 | 6 | Copyright (C) 2019 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | 9 | http://www.opendigitalradio.org 10 | */ 11 | /* 12 | This file is part of the ODR-mmbTools. 13 | 14 | This program is free software: you can redistribute it and/or modify 15 | it under the terms of the GNU General Public License as 16 | published by the Free Software Foundation, either version 3 of the 17 | License, or (at your option) any later version. 18 | 19 | This program is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | GNU General Public License for more details. 23 | 24 | You should have received a copy of the GNU General Public License 25 | along with this program. If not, see . 26 | */ 27 | 28 | /* Ensure construction and destruction of static globals in the right order */ 29 | 30 | #include "Log.h" 31 | #include "RemoteControl.h" 32 | 33 | // the RC needs logging, and needs to be initialised later. 34 | Logger etiLog; 35 | #if ENABLE_REMOTECONTROL 36 | RemoteControllers rcs; 37 | #endif // ENABLE_REMOTECONTROL 38 | 39 | -------------------------------------------------------------------------------- /lib/Json.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 3 | Her Majesty the Queen in Right of Canada (Communications Research 4 | Center Canada) 5 | 6 | Copyright (C) 2025 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | 9 | http://www.opendigitalradio.org 10 | 11 | This module adds remote-control capability to some of the dabmux/dabmod modules. 12 | */ 13 | /* 14 | This program is free software: you can redistribute it and/or modify 15 | it under the terms of the GNU General Public License as published by 16 | the Free Software Foundation, either version 3 of the License, or 17 | (at your option) any later version. 18 | 19 | This program is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | GNU General Public License for more details. 23 | 24 | You should have received a copy of the GNU General Public License 25 | along with this program. If not, see . 26 | */ 27 | 28 | #pragma once 29 | 30 | #ifdef HAVE_CONFIG_H 31 | # include "config.h" 32 | #endif 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | namespace json { 43 | 44 | // STL containers are not required to support incomplete types, 45 | // hence the shared_ptr 46 | 47 | struct value_t { 48 | std::variant< 49 | std::shared_ptr>, 50 | std::vector, 51 | std::string, 52 | double, 53 | int64_t, 54 | uint64_t, 55 | int32_t, 56 | uint32_t, 57 | bool, 58 | std::nullopt_t> v; 59 | }; 60 | 61 | using map_t = std::unordered_map; 62 | 63 | std::string map_to_json(const map_t& values); 64 | std::string value_to_json(const value_t& value); 65 | } 66 | -------------------------------------------------------------------------------- /lib/ReedSolomon.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in Right 3 | of Canada (Communications Research Center Canada) 4 | 5 | Copyright (C) 2016 6 | Matthias P. Braendli, matthias.braendli@mpb.li 7 | 8 | http://www.opendigitalradio.org 9 | */ 10 | /* 11 | This file is part of ODR-DabMux. 12 | 13 | ODR-DabMux is free software: you can redistribute it and/or modify 14 | it under the terms of the GNU General Public License as 15 | published by the Free Software Foundation, either version 3 of the 16 | License, or (at your option) any later version. 17 | 18 | ODR-DabMux is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with ODR-DabMux. If not, see . 25 | */ 26 | 27 | #include "ReedSolomon.h" 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include // For memcpy 34 | 35 | extern "C" { 36 | #include "fec/fec.h" 37 | } 38 | #include 39 | 40 | #define SYMSIZE 8 41 | 42 | 43 | ReedSolomon::ReedSolomon(int N, int K, bool reverse, int gfpoly, int firstRoot, int primElem) 44 | { 45 | setReverse(reverse); 46 | 47 | m_N = N; 48 | m_K = K; 49 | 50 | const int symsize = SYMSIZE; 51 | const int nroots = N - K; // For EDI PFT, this must be 48 52 | const int pad = ((1 << symsize) - 1) - N; // is 255-N 53 | 54 | rsData = init_rs_char(symsize, gfpoly, firstRoot, primElem, nroots, pad); 55 | 56 | if (rsData == nullptr) { 57 | std::stringstream ss; 58 | ss << "Invalid Reed-Solomon parameters! " << 59 | "N=" << N << " ; K=" << K << " ; pad=" << pad; 60 | throw std::invalid_argument(ss.str()); 61 | } 62 | } 63 | 64 | 65 | ReedSolomon::~ReedSolomon() 66 | { 67 | if (rsData != nullptr) { 68 | free_rs_char(rsData); 69 | } 70 | } 71 | 72 | 73 | void ReedSolomon::setReverse(bool state) 74 | { 75 | reverse = state; 76 | } 77 | 78 | 79 | int ReedSolomon::encode(void* data, void* fec, size_t size) 80 | { 81 | uint8_t* input = reinterpret_cast(data); 82 | uint8_t* output = reinterpret_cast(fec); 83 | int ret = 0; 84 | 85 | if (reverse) { 86 | std::vector buffer(m_N); 87 | 88 | memcpy(&buffer[0], input, m_K); 89 | memcpy(&buffer[m_K], output, m_N - m_K); 90 | 91 | ret = decode_rs_char(rsData, &buffer[0], nullptr, 0); 92 | if ((ret != 0) && (ret != -1)) { 93 | memcpy(input, &buffer[0], m_K); 94 | memcpy(output, &buffer[m_K], m_N - m_K); 95 | } 96 | } 97 | else { 98 | encode_rs_char(rsData, input, output); 99 | } 100 | 101 | return ret; 102 | } 103 | 104 | 105 | int ReedSolomon::encode(void* data, size_t size) 106 | { 107 | uint8_t* input = reinterpret_cast(data); 108 | int ret = 0; 109 | 110 | if (reverse) { 111 | ret = decode_rs_char(rsData, input, nullptr, 0); 112 | } 113 | else { 114 | encode_rs_char(rsData, input, &input[m_K]); 115 | } 116 | 117 | return ret; 118 | } 119 | -------------------------------------------------------------------------------- /lib/ReedSolomon.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in Right 3 | of Canada (Communications Research Center Canada) 4 | 5 | Copyright (C) 2016 6 | Matthias P. Braendli, matthias.braendli@mpb.li 7 | 8 | http://www.opendigitalradio.org 9 | */ 10 | /* 11 | This file is part of ODR-DabMux. 12 | 13 | ODR-DabMux is free software: you can redistribute it and/or modify 14 | it under the terms of the GNU General Public License as 15 | published by the Free Software Foundation, either version 3 of the 16 | License, or (at your option) any later version. 17 | 18 | ODR-DabMux is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with ODR-DabMux. If not, see . 25 | */ 26 | 27 | #pragma once 28 | 29 | #ifdef HAVE_CONFIG_H 30 | # include 31 | #endif 32 | 33 | #include 34 | #include 35 | 36 | class ReedSolomon 37 | { 38 | public: 39 | ReedSolomon(int N, int K, 40 | bool reverse = false, 41 | int gfpoly = 0x11d, int firstRoot = 0, int primElem = 1); 42 | ReedSolomon(const ReedSolomon& other) = delete; 43 | ReedSolomon operator=(const ReedSolomon& other) = delete; 44 | ~ReedSolomon(); 45 | 46 | void setReverse(bool state); 47 | int encode(void* data, void* fec, size_t size); 48 | int encode(void* data, size_t size); 49 | 50 | private: 51 | int m_N; 52 | int m_K; 53 | 54 | void* rsData; 55 | bool reverse; 56 | }; 57 | 58 | -------------------------------------------------------------------------------- /lib/charset/README: -------------------------------------------------------------------------------- 1 | This UTF-8 to EBU charset (defined in ETSI TS 101 756v1.8.1) was copied from 2 | ODR-PadEnc, with utf8 library v4.0.5 from https://github.com/nemtrif/utfcpp/tree/master/source/utf8 3 | -------------------------------------------------------------------------------- /lib/charset/charset.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Matthias P. Braendli (http://opendigitalradio.org) 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | /*! 18 | \file charset.h 19 | \brief A converter for UTF-8 to EBU Latin charset according to 20 | ETSI TS 101 756 Annex C, used for DLS and Labels. 21 | 22 | \author Matthias P. Braendli 23 | \author Lindsay Cornell 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | #include 31 | #include "utf8.h" 32 | 33 | class CharsetConverter 34 | { 35 | public: 36 | CharsetConverter(); 37 | 38 | /*! Convert a UTF-8 encoded text line into an EBU Latin encoded byte 39 | * stream. If up_to_first_error is set, convert as much text as possible. 40 | * If false, raise an utf8::exception in case of conversion errors. 41 | */ 42 | std::string utf8_to_ebu(std::string line_utf8, bool up_to_first_error = true); 43 | 44 | /*! Convert a EBU Latin byte stream to a UTF-8 encoded string. 45 | * Invalid input characters are converted to ⁇ (unicode U+2047). 46 | */ 47 | std::string ebu_to_utf8(const std::string& str); 48 | 49 | private: 50 | // Representation of the table in 32-bit unicode 51 | std::vector m_conversion_table; 52 | }; 53 | -------------------------------------------------------------------------------- /lib/charset/utf8.h: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Nemanja Trifunovic 2 | 3 | /* 4 | Permission is hereby granted, free of charge, to any person or organization 5 | obtaining a copy of the software and accompanying documentation covered by 6 | this license (the "Software") to use, reproduce, display, distribute, 7 | execute, and transmit the Software, and to prepare derivative works of the 8 | Software, and to permit third-parties to whom the Software is furnished to 9 | do so, all subject to the following: 10 | 11 | The copyright notices in the Software and this entire statement, including 12 | the above license grant, this restriction and the following disclaimer, 13 | must be included in all copies of the Software, in whole or in part, and 14 | all derivative works of the Software, unless such copies or derivative 15 | works are solely in the form of machine-executable object code generated by 16 | a source language processor. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 21 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 22 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 23 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 | DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | 28 | #ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 29 | #define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 30 | 31 | /* 32 | To control the C++ language version used by the library, you can define UTF_CPP_CPLUSPLUS macro 33 | and set it to one of the values used by the __cplusplus predefined macro. 34 | 35 | For instance, 36 | #define UTF_CPP_CPLUSPLUS 199711L 37 | will cause the UTF-8 CPP library to use only types and language features available in the C++ 98 standard. 38 | Some library features will be disabled. 39 | 40 | If you leave UTF_CPP_CPLUSPLUS undefined, it will be internally assigned to __cplusplus. 41 | */ 42 | 43 | #include "utf8/checked.h" 44 | #include "utf8/unchecked.h" 45 | 46 | #endif // header guard 47 | -------------------------------------------------------------------------------- /lib/charset/utf8/cpp11.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Nemanja Trifunovic 2 | 3 | /* 4 | Permission is hereby granted, free of charge, to any person or organization 5 | obtaining a copy of the software and accompanying documentation covered by 6 | this license (the "Software") to use, reproduce, display, distribute, 7 | execute, and transmit the Software, and to prepare derivative works of the 8 | Software, and to permit third-parties to whom the Software is furnished to 9 | do so, all subject to the following: 10 | 11 | The copyright notices in the Software and this entire statement, including 12 | the above license grant, this restriction and the following disclaimer, 13 | must be included in all copies of the Software, in whole or in part, and 14 | all derivative works of the Software, unless such copies or derivative 15 | works are solely in the form of machine-executable object code generated by 16 | a source language processor. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 21 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 22 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 23 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 | DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | 28 | #ifndef UTF8_FOR_CPP_a184c22c_d012_11e8_a8d5_f2801f1b9fd1 29 | #define UTF8_FOR_CPP_a184c22c_d012_11e8_a8d5_f2801f1b9fd1 30 | 31 | #include "checked.h" 32 | 33 | namespace utf8 34 | { 35 | inline void append16(utfchar32_t cp, std::u16string& s) 36 | { 37 | append16(cp, std::back_inserter(s)); 38 | } 39 | 40 | inline std::string utf16to8(const std::u16string& s) 41 | { 42 | std::string result; 43 | utf16to8(s.begin(), s.end(), std::back_inserter(result)); 44 | return result; 45 | } 46 | 47 | inline std::u16string utf8to16(const std::string& s) 48 | { 49 | std::u16string result; 50 | utf8to16(s.begin(), s.end(), std::back_inserter(result)); 51 | return result; 52 | } 53 | 54 | inline std::string utf32to8(const std::u32string& s) 55 | { 56 | std::string result; 57 | utf32to8(s.begin(), s.end(), std::back_inserter(result)); 58 | return result; 59 | } 60 | 61 | inline std::u32string utf8to32(const std::string& s) 62 | { 63 | std::u32string result; 64 | utf8to32(s.begin(), s.end(), std::back_inserter(result)); 65 | return result; 66 | } 67 | } // namespace utf8 68 | 69 | #endif // header guard 70 | 71 | -------------------------------------------------------------------------------- /lib/charset/utf8/cpp17.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Nemanja Trifunovic 2 | 3 | /* 4 | Permission is hereby granted, free of charge, to any person or organization 5 | obtaining a copy of the software and accompanying documentation covered by 6 | this license (the "Software") to use, reproduce, display, distribute, 7 | execute, and transmit the Software, and to prepare derivative works of the 8 | Software, and to permit third-parties to whom the Software is furnished to 9 | do so, all subject to the following: 10 | 11 | The copyright notices in the Software and this entire statement, including 12 | the above license grant, this restriction and the following disclaimer, 13 | must be included in all copies of the Software, in whole or in part, and 14 | all derivative works of the Software, unless such copies or derivative 15 | works are solely in the form of machine-executable object code generated by 16 | a source language processor. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 21 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 22 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 23 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 | DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | 28 | #ifndef UTF8_FOR_CPP_7e906c01_03a3_4daf_b420_ea7ea952b3c9 29 | #define UTF8_FOR_CPP_7e906c01_03a3_4daf_b420_ea7ea952b3c9 30 | 31 | #include "cpp11.h" 32 | 33 | namespace utf8 34 | { 35 | inline std::string utf16to8(std::u16string_view s) 36 | { 37 | std::string result; 38 | utf16to8(s.begin(), s.end(), std::back_inserter(result)); 39 | return result; 40 | } 41 | 42 | inline std::u16string utf8to16(std::string_view s) 43 | { 44 | std::u16string result; 45 | utf8to16(s.begin(), s.end(), std::back_inserter(result)); 46 | return result; 47 | } 48 | 49 | inline std::string utf32to8(std::u32string_view s) 50 | { 51 | std::string result; 52 | utf32to8(s.begin(), s.end(), std::back_inserter(result)); 53 | return result; 54 | } 55 | 56 | inline std::u32string utf8to32(std::string_view s) 57 | { 58 | std::u32string result; 59 | utf8to32(s.begin(), s.end(), std::back_inserter(result)); 60 | return result; 61 | } 62 | 63 | inline std::size_t find_invalid(std::string_view s) 64 | { 65 | std::string_view::const_iterator invalid = find_invalid(s.begin(), s.end()); 66 | return (invalid == s.end()) ? std::string_view::npos : static_cast(invalid - s.begin()); 67 | } 68 | 69 | inline bool is_valid(std::string_view s) 70 | { 71 | return is_valid(s.begin(), s.end()); 72 | } 73 | 74 | inline std::string replace_invalid(std::string_view s, char32_t replacement) 75 | { 76 | std::string result; 77 | replace_invalid(s.begin(), s.end(), std::back_inserter(result), replacement); 78 | return result; 79 | } 80 | 81 | inline std::string replace_invalid(std::string_view s) 82 | { 83 | std::string result; 84 | replace_invalid(s.begin(), s.end(), std::back_inserter(result)); 85 | return result; 86 | } 87 | 88 | inline bool starts_with_bom(std::string_view s) 89 | { 90 | return starts_with_bom(s.begin(), s.end()); 91 | } 92 | 93 | } // namespace utf8 94 | 95 | #endif // header guard 96 | 97 | -------------------------------------------------------------------------------- /lib/crc.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the 3 | Queen in Right of Canada (Communications Research Center Canada) 4 | */ 5 | /* 6 | This file is part of ODR-DabMux. 7 | 8 | ODR-DabMux is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as 10 | published by the Free Software Foundation, either version 3 of the 11 | License, or (at your option) any later version. 12 | 13 | ODR-DabMux is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with ODR-DabMux. If not, see . 20 | */ 21 | 22 | #ifndef _CRC 23 | #define _CRC 24 | 25 | #ifdef HAVE_CONFIG_H 26 | # include "config.h" 27 | #endif 28 | 29 | #ifndef _WIN32 30 | #include 31 | #else 32 | #include // For types... 33 | typedef BYTE uint8_t; 34 | typedef WORD uint16_t; 35 | typedef DWORD32 uint32_t; 36 | #endif 37 | 38 | 39 | #ifdef __cplusplus 40 | extern "C" { // } 41 | #endif 42 | 43 | void init_crc8tab(uint8_t l_code, uint8_t l_init); 44 | uint8_t crc8(uint8_t l_crc, const void *lp_data, unsigned l_nb); 45 | extern uint8_t crc8tab[]; 46 | 47 | void init_crc16tab(uint16_t l_code, uint16_t l_init); 48 | uint16_t crc16(uint16_t l_crc, const void *lp_data, unsigned l_nb); 49 | extern uint16_t crc16tab[]; 50 | 51 | void init_crc32tab(uint32_t l_code, uint32_t l_init); 52 | uint32_t crc32(uint32_t l_crc, const void *lp_data, unsigned l_nb); 53 | extern uint32_t crc32tab[]; 54 | 55 | #ifdef __cplusplus 56 | } 57 | #endif 58 | 59 | #endif //_CRC 60 | -------------------------------------------------------------------------------- /lib/edi/STIWriter.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2019 3 | Matthias P. Braendli, matthias.braendli@mpb.li 4 | 5 | http://opendigitalradio.org 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License along 18 | with this program; if not, write to the Free Software Foundation, Inc., 19 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20 | */ 21 | #pragma once 22 | 23 | #include "common.hpp" 24 | #include "STIDecoder.hpp" 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | namespace EdiDecoder { 32 | 33 | struct sti_frame_t { 34 | std::vector frame; 35 | uint16_t dlfc; 36 | frame_timestamp_t timestamp; 37 | audio_level_data audio_levels; 38 | odr_version_data version_data; 39 | seq_info_t sequence_counters; 40 | }; 41 | 42 | class STIWriter : public STIDataCollector { 43 | public: 44 | // The callback gets called for every STI frame that gets assembled 45 | STIWriter(std::function&& frame_callback); 46 | 47 | // Tell the ETIWriter what EDI protocol we receive in *ptr. 48 | // This is not part of the ETI data, but is used as check 49 | virtual void update_protocol( 50 | const std::string& proto, 51 | uint16_t major, 52 | uint16_t minor) override; 53 | 54 | virtual void update_stat(uint8_t stat, uint16_t spid) override; 55 | 56 | virtual void update_edi_time( 57 | uint32_t utco, 58 | uint32_t seconds) override; 59 | 60 | virtual void update_rfad(std::array rfad) override; 61 | virtual void update_sti_management(const sti_management_data& data) override; 62 | virtual void add_payload(sti_payload_data&& payload) override; 63 | 64 | virtual void update_audio_levels(const audio_level_data& data) override; 65 | virtual void update_odr_version(const odr_version_data& data) override; 66 | 67 | virtual void assemble(seq_info_t seq) override; 68 | private: 69 | std::function m_frame_callback; 70 | 71 | bool m_proto_valid = false; 72 | 73 | bool m_management_data_valid = false; 74 | sti_management_data m_management_data; 75 | 76 | bool m_stat_valid = false; 77 | uint8_t m_stat = 0; 78 | uint16_t m_spid = 0; 79 | 80 | bool m_time_valid = false; 81 | uint32_t m_utco = 0; 82 | uint32_t m_seconds = 0; 83 | 84 | bool m_payload_valid = false; 85 | sti_payload_data m_payload; 86 | 87 | audio_level_data m_audio_levels; 88 | odr_version_data m_version_data; 89 | }; 90 | 91 | } 92 | 93 | -------------------------------------------------------------------------------- /lib/edi/buffer_unpack.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2016 3 | Matthias P. Braendli, matthias.braendli@mpb.li 4 | 5 | http://opendigitalradio.org 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License along 18 | with this program; if not, write to the Free Software Foundation, Inc., 19 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20 | */ 21 | 22 | #pragma once 23 | #include 24 | 25 | namespace EdiDecoder { 26 | 27 | template 28 | uint16_t read_16b(T buf) 29 | { 30 | uint16_t value = 0; 31 | value = (uint16_t)(buf[0]) << 8; 32 | value |= (uint16_t)(buf[1]); 33 | return value; 34 | } 35 | 36 | template 37 | uint32_t read_24b(T buf) 38 | { 39 | uint32_t value = 0; 40 | value = (uint32_t)(buf[0]) << 16; 41 | value |= (uint32_t)(buf[1]) << 8; 42 | value |= (uint32_t)(buf[2]); 43 | return value; 44 | } 45 | 46 | template 47 | uint32_t read_32b(T buf) 48 | { 49 | uint32_t value = 0; 50 | value = (uint32_t)(buf[0]) << 24; 51 | value |= (uint32_t)(buf[1]) << 16; 52 | value |= (uint32_t)(buf[2]) << 8; 53 | value |= (uint32_t)(buf[3]); 54 | return value; 55 | } 56 | 57 | inline uint32_t unpack1bit(uint8_t byte, int bitpos) 58 | { 59 | return (byte & 1 << (7-bitpos)) > (7-bitpos); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /lib/edioutput/AFPacket.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2021 3 | Matthias P. Braendli, matthias.braendli@mpb.li 4 | 5 | http://www.opendigitalradio.org 6 | 7 | EDI output. 8 | This implements an AF Packet as defined ETSI TS 102 821. 9 | Also see ETSI TS 102 693 10 | 11 | */ 12 | /* 13 | This file is part of the ODR-mmbTools. 14 | 15 | This program is free software: you can redistribute it and/or modify 16 | it under the terms of the GNU General Public License as 17 | published by the Free Software Foundation, either version 3 of the 18 | License, or (at your option) any later version. 19 | 20 | This program is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | GNU General Public License for more details. 24 | 25 | You should have received a copy of the GNU General Public License 26 | along with this program. If not, see . 27 | */ 28 | #include "crc.h" 29 | #include "AFPacket.h" 30 | #include "TagItems.h" 31 | #include "TagPacket.h" 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | namespace edi { 40 | 41 | // Header PT field. AF packet contains TAG payload 42 | const uint8_t AFHEADER_PT_TAG = 'T'; 43 | 44 | // AF Packet Major (3 bits) and Minor (4 bits) version 45 | const uint8_t AFHEADER_VERSION = 0x10; // MAJ=1, MIN=0 46 | 47 | AFPacket AFPacketiser::Assemble(TagPacket tag_packet) 48 | { 49 | std::vector payload = tag_packet.Assemble(); 50 | 51 | if (m_verbose) 52 | std::cerr << "Assemble AFPacket " << m_seq << std::endl; 53 | 54 | std::string pack_data("AF"); // SYNC 55 | std::vector packet(pack_data.begin(), pack_data.end()); 56 | 57 | uint32_t taglength = payload.size(); 58 | 59 | if (m_verbose) 60 | std::cerr << " AFPacket payload size " << payload.size() << std::endl; 61 | 62 | // write length into packet 63 | packet.push_back((taglength >> 24) & 0xFF); 64 | packet.push_back((taglength >> 16) & 0xFF); 65 | packet.push_back((taglength >> 8) & 0xFF); 66 | packet.push_back(taglength & 0xFF); 67 | 68 | // fill rest of header 69 | packet.push_back(m_seq >> 8); 70 | packet.push_back(m_seq & 0xFF); 71 | m_seq++; 72 | packet.push_back((m_have_crc ? 0x80 : 0) | AFHEADER_VERSION); // ar_cf: CRC=1 73 | packet.push_back(AFHEADER_PT_TAG); 74 | 75 | // insert payload, must have a length multiple of 8 bytes 76 | packet.insert(packet.end(), payload.begin(), payload.end()); 77 | 78 | // calculate CRC over AF Header and payload 79 | uint16_t crc = 0xffff; 80 | crc = crc16(crc, &(packet.front()), packet.size()); 81 | crc ^= 0xffff; 82 | 83 | if (m_verbose) 84 | fprintf(stderr, " AFPacket crc %x\n", crc); 85 | 86 | packet.push_back((crc >> 8) & 0xFF); 87 | packet.push_back(crc & 0xFF); 88 | 89 | if (m_verbose) 90 | std::cerr << " AFPacket length " << packet.size() << std::endl; 91 | 92 | return packet; 93 | } 94 | 95 | void AFPacketiser::OverrideSeq(uint16_t seq) 96 | { 97 | m_seq = seq; 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /lib/edioutput/AFPacket.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2021 3 | Matthias P. Braendli, matthias.braendli@mpb.li 4 | 5 | http://www.opendigitalradio.org 6 | 7 | EDI output. 8 | This implements an AF Packet as defined ETSI TS 102 821. 9 | Also see ETSI TS 102 693 10 | 11 | */ 12 | /* 13 | This file is part of the ODR-mmbTools. 14 | 15 | This program is free software: you can redistribute it and/or modify 16 | it under the terms of the GNU General Public License as 17 | published by the Free Software Foundation, either version 3 of the 18 | License, or (at your option) any later version. 19 | 20 | This program is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | GNU General Public License for more details. 24 | 25 | You should have received a copy of the GNU General Public License 26 | along with this program. If not, see . 27 | */ 28 | 29 | #pragma once 30 | 31 | #include 32 | #include 33 | #include "TagItems.h" 34 | #include "TagPacket.h" 35 | 36 | namespace edi { 37 | 38 | typedef std::vector AFPacket; 39 | 40 | // ETSI TS 102 821, 6.1 AF packet structure 41 | class AFPacketiser 42 | { 43 | public: 44 | AFPacketiser() : 45 | m_verbose(false) {}; 46 | AFPacketiser(bool verbose) : 47 | m_verbose(verbose) {}; 48 | 49 | AFPacket Assemble(TagPacket tag_packet); 50 | 51 | void OverrideSeq(uint16_t seq); 52 | 53 | private: 54 | static const bool m_have_crc = true; 55 | 56 | uint16_t m_seq = 0; //counter that overflows at 0xFFFF 57 | 58 | bool m_verbose; 59 | }; 60 | 61 | } 62 | 63 | -------------------------------------------------------------------------------- /lib/edioutput/EDIConfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2025 3 | Matthias P. Braendli, matthias.braendli@mpb.li 4 | 5 | http://www.opendigitalradio.org 6 | 7 | EDI output, 8 | UDP and TCP transports and their configuration 9 | 10 | */ 11 | /* 12 | This file is part of the ODR-mmbTools. 13 | 14 | This program is free software: you can redistribute it and/or modify 15 | it under the terms of the GNU General Public License as 16 | published by the Free Software Foundation, either version 3 of the 17 | License, or (at your option) any later version. 18 | 19 | This program is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | GNU General Public License for more details. 23 | 24 | You should have received a copy of the GNU General Public License 25 | along with this program. If not, see . 26 | */ 27 | 28 | #pragma once 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | namespace edi { 36 | 37 | /** Configuration for EDI output */ 38 | 39 | struct pft_settings_t { 40 | // protection and fragmentation settings 41 | bool verbose = false; 42 | bool enable_pft = false; 43 | unsigned chunk_len = 207; // RSk, data length of each chunk 44 | unsigned fec = 0; // number of fragments that can be recovered 45 | double fragment_spreading_factor = 0.95; 46 | // Spread transmission of fragments in time. 1.0 = 100% means spreading over the whole duration of a frame (24ms) 47 | // Above 100% means that the fragments are spread over several 24ms periods, interleaving the AF packets. 48 | }; 49 | 50 | struct destination_t { 51 | virtual ~destination_t() {}; 52 | 53 | pft_settings_t pft_settings = {}; 54 | }; 55 | 56 | 57 | // Can represent both unicast and multicast destinations 58 | struct udp_destination_t : public destination_t { 59 | std::string dest_addr; 60 | uint16_t dest_port = 0; 61 | std::string source_addr; 62 | uint16_t source_port = 0; 63 | uint8_t ttl = 10; 64 | }; 65 | 66 | // TCP server that can accept multiple connections 67 | struct tcp_server_t : public destination_t { 68 | unsigned int listen_port = 0; 69 | size_t max_frames_queued = 1024; 70 | 71 | // The TCP Server output can preroll a fixed number of previous buffers each time a new client connects. 72 | size_t tcp_server_preroll_buffers = 0; 73 | }; 74 | 75 | // TCP client that connects to one endpoint 76 | struct tcp_client_t : public destination_t { 77 | std::string dest_addr; 78 | unsigned int dest_port = 0; 79 | size_t max_frames_queued = 1024; 80 | }; 81 | 82 | struct configuration_t { 83 | bool verbose = false; 84 | unsigned int tagpacket_alignment = 0; 85 | std::vector > destinations; 86 | 87 | bool enabled() const { return destinations.size() > 0; } 88 | 89 | void print() const; 90 | }; 91 | 92 | } 93 | 94 | 95 | -------------------------------------------------------------------------------- /lib/edioutput/PFT.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2025 3 | Matthias P. Braendli, matthias.braendli@mpb.li 4 | 5 | http://www.opendigitalradio.org 6 | 7 | EDI output, 8 | Protection, Fragmentation and Transport. (PFT) 9 | 10 | Are supported: 11 | Reed-Solomon and Fragmentation 12 | 13 | This implements part of PFT as defined ETSI TS 102 821. 14 | 15 | */ 16 | /* 17 | This file is part of the ODR-mmbTools. 18 | 19 | This program is free software: you can redistribute it and/or modify 20 | it under the terms of the GNU General Public License as 21 | published by the Free Software Foundation, either version 3 of the 22 | License, or (at your option) any later version. 23 | 24 | This program is distributed in the hope that it will be useful, 25 | but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | GNU General Public License for more details. 28 | 29 | You should have received a copy of the GNU General Public License 30 | along with this program. If not, see . 31 | */ 32 | 33 | #pragma once 34 | 35 | #include 36 | #include 37 | #include "AFPacket.h" 38 | #include "EDIConfig.h" 39 | 40 | namespace edi { 41 | 42 | typedef std::vector RSBlock; 43 | typedef std::vector PFTFragment; 44 | 45 | class PFT 46 | { 47 | public: 48 | static constexpr int PARITYBYTES = 48; 49 | 50 | PFT(); 51 | PFT(const pft_settings_t& conf); 52 | 53 | bool is_enabled() const { return m_enabled and m_k > 0; } 54 | 55 | // return a list of PFT fragments with the correct 56 | // PFT headers 57 | std::vector Assemble(AFPacket af_packet); 58 | 59 | // Apply Reed-Solomon FEC to the AF Packet 60 | RSBlock Protect(AFPacket af_packet); 61 | 62 | // Cut a RSBlock into several fragments that can be transmitted 63 | std::vector> ProtectAndFragment(AFPacket af_packet); 64 | 65 | void OverridePSeq(uint16_t pseq); 66 | 67 | private: 68 | bool m_enabled = false; 69 | unsigned int m_k = 207; // length of RS data word 70 | unsigned int m_m = 3; // number of fragments that can be recovered if lost 71 | uint16_t m_pseq = 0; 72 | size_t m_num_chunks = 0; 73 | bool m_verbose = false; 74 | 75 | // Transport header is always deactivated 76 | const bool m_transport_header = false; 77 | const uint16_t m_addr_source = 0; 78 | const unsigned int m_dest_port = 0; 79 | }; 80 | 81 | } 82 | 83 | -------------------------------------------------------------------------------- /lib/edioutput/TagPacket.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2020 3 | Matthias P. Braendli, matthias.braendli@mpb.li 4 | 5 | http://www.opendigitalradio.org 6 | 7 | EDI output. 8 | This defines a TAG Packet. 9 | */ 10 | /* 11 | This file is part of the ODR-mmbTools. 12 | 13 | This program is free software: you can redistribute it and/or modify 14 | it under the terms of the GNU General Public License as 15 | published by the Free Software Foundation, either version 3 of the 16 | License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program. If not, see . 25 | */ 26 | 27 | #include "TagPacket.h" 28 | #include "TagItems.h" 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | namespace edi { 37 | 38 | TagPacket::TagPacket(unsigned int alignment) : m_alignment(alignment) 39 | { } 40 | 41 | std::vector TagPacket::Assemble() 42 | { 43 | if (raw_tagpacket.size() > 0 and tag_items.size() > 0) { 44 | throw std::logic_error("TagPacket: both raw and items used!"); 45 | } 46 | 47 | if (raw_tagpacket.size() > 0) { 48 | return raw_tagpacket; 49 | } 50 | 51 | std::vector packet; 52 | 53 | for (auto tag : tag_items) { 54 | std::vector tag_data = tag->Assemble(); 55 | packet.insert(packet.end(), tag_data.begin(), tag_data.end()); 56 | } 57 | 58 | if (m_alignment == 0) { /* no padding */ } 59 | else if (m_alignment == 8) { 60 | // Add padding inside TAG packet 61 | while (packet.size() % 8 > 0) { 62 | packet.push_back(0); // TS 102 821, 5.1, "padding shall be undefined" 63 | } 64 | } 65 | else if (m_alignment > 8) { 66 | TagStarDMY dmy(m_alignment - 8); 67 | auto dmy_data = dmy.Assemble(); 68 | packet.insert(packet.end(), dmy_data.begin(), dmy_data.end()); 69 | } 70 | else { 71 | std::cerr << "Invalid alignment requirement " << m_alignment << 72 | " defined in TagPacket" << std::endl; 73 | } 74 | 75 | return packet; 76 | } 77 | 78 | } 79 | 80 | -------------------------------------------------------------------------------- /lib/edioutput/TagPacket.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2020 3 | Matthias P. Braendli, matthias.braendli@mpb.li 4 | 5 | http://www.opendigitalradio.org 6 | 7 | EDI output. 8 | This defines a TAG Packet. 9 | */ 10 | /* 11 | This file is part of the ODR-mmbTools. 12 | 13 | This program is free software: you can redistribute it and/or modify 14 | it under the terms of the GNU General Public License as 15 | published by the Free Software Foundation, either version 3 of the 16 | License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program. If not, see . 25 | */ 26 | 27 | #pragma once 28 | 29 | #include "TagItems.h" 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | namespace edi { 36 | 37 | // A TagPacket is nothing else than a list of tag items, with an 38 | // Assemble function that puts the bytestream together and adds 39 | // padding such that the total length is a multiple of 8 Bytes. 40 | // 41 | // Alternatively, a raw tagpacket can be used instead of the 42 | // items list 43 | // 44 | // ETSI TS 102 821, 5.1 Tag Packet 45 | class TagPacket 46 | { 47 | public: 48 | TagPacket(unsigned int alignment); 49 | std::vector Assemble(); 50 | 51 | std::list tag_items; 52 | 53 | std::vector raw_tagpacket; 54 | 55 | private: 56 | unsigned int m_alignment; 57 | }; 58 | 59 | } 60 | 61 | -------------------------------------------------------------------------------- /lib/fec/README.md: -------------------------------------------------------------------------------- 1 | FEC routines from KA9Q's libfec 2 | =============================== 3 | 4 | This folder contains part of the libfec library by KA9Q. Only the 5 | char-sized Reed-Solomon encoder and decoder is here. 6 | 7 | The files have been copied from the libfec fork at 8 | https://github.com/Opendigitalradio/ka9q-fec 9 | 10 | Original code is at http://www.ka9q.net/code/fec/ 11 | 12 | All files in this folder are licenced under the LGPL v2.1, please see LICENCE 13 | -------------------------------------------------------------------------------- /lib/fec/char.h: -------------------------------------------------------------------------------- 1 | /* Stuff specific to the 8-bit symbol version of the general purpose RS codecs 2 | * 3 | * Copyright 2003, Phil Karn, KA9Q 4 | * May be used under the terms of the GNU Lesser General Public License (LGPL) 5 | */ 6 | typedef unsigned char data_t; 7 | 8 | #define MODNN(x) modnn(rs,x) 9 | 10 | #define MM (rs->mm) 11 | #define NN (rs->nn) 12 | #define ALPHA_TO (rs->alpha_to) 13 | #define INDEX_OF (rs->index_of) 14 | #define GENPOLY (rs->genpoly) 15 | #define NROOTS (rs->nroots) 16 | #define FCR (rs->fcr) 17 | #define PRIM (rs->prim) 18 | #define IPRIM (rs->iprim) 19 | #define PAD (rs->pad) 20 | #define A0 (NN) 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /lib/fec/decode_rs_char.c: -------------------------------------------------------------------------------- 1 | /* General purpose Reed-Solomon decoder for 8-bit symbols or less 2 | * Copyright 2003 Phil Karn, KA9Q 3 | * May be used under the terms of the GNU Lesser General Public License (LGPL) 4 | */ 5 | 6 | #ifdef DEBUG 7 | #include 8 | #endif 9 | 10 | #include 11 | 12 | #include "char.h" 13 | #include "rs-common.h" 14 | 15 | int decode_rs_char(void *p, data_t *data, int *eras_pos, int no_eras){ 16 | int retval; 17 | struct rs *rs = (struct rs *)p; 18 | 19 | #include "decode_rs.h" 20 | 21 | return retval; 22 | } 23 | -------------------------------------------------------------------------------- /lib/fec/encode_rs.h: -------------------------------------------------------------------------------- 1 | /* The guts of the Reed-Solomon encoder, meant to be #included 2 | * into a function body with the following typedefs, macros and variables supplied 3 | * according to the code parameters: 4 | 5 | * data_t - a typedef for the data symbol 6 | * data_t data[] - array of NN-NROOTS-PAD and type data_t to be encoded 7 | * data_t parity[] - an array of NROOTS and type data_t to be written with parity symbols 8 | * NROOTS - the number of roots in the RS code generator polynomial, 9 | * which is the same as the number of parity symbols in a block. 10 | Integer variable or literal. 11 | * 12 | * NN - the total number of symbols in a RS block. Integer variable or literal. 13 | * PAD - the number of pad symbols in a block. Integer variable or literal. 14 | * ALPHA_TO - The address of an array of NN elements to convert Galois field 15 | * elements in index (log) form to polynomial form. Read only. 16 | * INDEX_OF - The address of an array of NN elements to convert Galois field 17 | * elements in polynomial form to index (log) form. Read only. 18 | * MODNN - a function to reduce its argument modulo NN. May be inline or a macro. 19 | * GENPOLY - an array of NROOTS+1 elements containing the generator polynomial in index form 20 | 21 | * The memset() and memmove() functions are used. The appropriate header 22 | * file declaring these functions (usually ) must be included by the calling 23 | * program. 24 | 25 | * Copyright 2004, Phil Karn, KA9Q 26 | * May be used under the terms of the GNU Lesser General Public License (LGPL) 27 | */ 28 | 29 | 30 | #undef A0 31 | #define A0 (NN) /* Special reserved value encoding zero in index form */ 32 | 33 | { 34 | int i, j; 35 | data_t feedback; 36 | 37 | memset(parity,0,NROOTS*sizeof(data_t)); 38 | 39 | for(i=0;i 6 | 7 | #include "char.h" 8 | #include "rs-common.h" 9 | 10 | void encode_rs_char(void *p,data_t *data, data_t *parity){ 11 | struct rs *rs = (struct rs *)p; 12 | 13 | #include "encode_rs.h" 14 | 15 | } 16 | -------------------------------------------------------------------------------- /lib/fec/fec.h: -------------------------------------------------------------------------------- 1 | /* Main header for reduced libfec. 2 | * 3 | * The FEC code in this folder is 4 | * Copyright 2003 Phil Karn, KA9Q 5 | * May be used under the terms of the GNU Lesser General Public License (LGPL) 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | #include "char.h" 13 | #include "rs-common.h" 14 | 15 | /* Initialize a Reed-Solomon codec 16 | * symsize = symbol size, bits 17 | * gfpoly = Field generator polynomial coefficients 18 | * fcr = first root of RS code generator polynomial, index form 19 | * prim = primitive element to generate polynomial roots 20 | * nroots = RS code generator polynomial degree (number of roots) 21 | * pad = padding bytes at front of shortened block 22 | */ 23 | void *init_rs_char(int symsize,int gfpoly,int fcr,int prim,int nroots,int pad); 24 | 25 | int decode_rs_char(void *p, data_t *data, int *eras_pos, int no_eras); 26 | 27 | void encode_rs_char(void *p,data_t *data, data_t *parity); 28 | 29 | void free_rs_char(void *p); 30 | 31 | -------------------------------------------------------------------------------- /lib/fec/init_rs.h: -------------------------------------------------------------------------------- 1 | /* Common code for intializing a Reed-Solomon control block (char or int symbols) 2 | * Copyright 2004 Phil Karn, KA9Q 3 | * May be used under the terms of the GNU Lesser General Public License (LGPL) 4 | */ 5 | #undef NULL 6 | #define NULL ((void *)0) 7 | 8 | { 9 | int i, j, sr,root,iprim; 10 | 11 | rs = NULL; 12 | /* Check parameter ranges */ 13 | if(symsize < 0 || symsize > 8*sizeof(data_t)){ 14 | goto done; 15 | } 16 | 17 | if(fcr < 0 || fcr >= (1<= (1<= (1<= ((1<mm = symsize; 31 | rs->nn = (1<pad = pad; 33 | 34 | rs->alpha_to = (data_t *)malloc(sizeof(data_t)*(rs->nn+1)); 35 | if(rs->alpha_to == NULL){ 36 | free(rs); 37 | rs = NULL; 38 | goto done; 39 | } 40 | rs->index_of = (data_t *)malloc(sizeof(data_t)*(rs->nn+1)); 41 | if(rs->index_of == NULL){ 42 | free(rs->alpha_to); 43 | free(rs); 44 | rs = NULL; 45 | goto done; 46 | } 47 | 48 | /* Generate Galois field lookup tables */ 49 | rs->index_of[0] = A0; /* log(zero) = -inf */ 50 | rs->alpha_to[A0] = 0; /* alpha**-inf = 0 */ 51 | sr = 1; 52 | for(i=0;inn;i++){ 53 | rs->index_of[sr] = i; 54 | rs->alpha_to[i] = sr; 55 | sr <<= 1; 56 | if(sr & (1<nn; 59 | } 60 | if(sr != 1){ 61 | /* field generator polynomial is not primitive! */ 62 | free(rs->alpha_to); 63 | free(rs->index_of); 64 | free(rs); 65 | rs = NULL; 66 | goto done; 67 | } 68 | 69 | /* Form RS code generator polynomial from its roots */ 70 | rs->genpoly = (data_t *)malloc(sizeof(data_t)*(nroots+1)); 71 | if(rs->genpoly == NULL){ 72 | free(rs->alpha_to); 73 | free(rs->index_of); 74 | free(rs); 75 | rs = NULL; 76 | goto done; 77 | } 78 | rs->fcr = fcr; 79 | rs->prim = prim; 80 | rs->nroots = nroots; 81 | 82 | /* Find prim-th root of 1, used in decoding */ 83 | for(iprim=1;(iprim % prim) != 0;iprim += rs->nn) 84 | ; 85 | rs->iprim = iprim / prim; 86 | 87 | rs->genpoly[0] = 1; 88 | for (i = 0,root=fcr*prim; i < nroots; i++,root += prim) { 89 | rs->genpoly[i+1] = 1; 90 | 91 | /* Multiply rs->genpoly[] by @**(root + x) */ 92 | for (j = i; j > 0; j--){ 93 | if (rs->genpoly[j] != 0) 94 | rs->genpoly[j] = rs->genpoly[j-1] ^ rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[j]] + root)]; 95 | else 96 | rs->genpoly[j] = rs->genpoly[j-1]; 97 | } 98 | /* rs->genpoly[0] can never be zero */ 99 | rs->genpoly[0] = rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[0]] + root)]; 100 | } 101 | /* convert rs->genpoly[] to index form for quicker encoding */ 102 | for (i = 0; i <= nroots; i++) 103 | rs->genpoly[i] = rs->index_of[rs->genpoly[i]]; 104 | done:; 105 | 106 | } 107 | -------------------------------------------------------------------------------- /lib/fec/init_rs_char.c: -------------------------------------------------------------------------------- 1 | /* Initialize a RS codec 2 | * 3 | * Copyright 2002 Phil Karn, KA9Q 4 | * May be used under the terms of the GNU Lesser General Public License (LGPL) 5 | */ 6 | #include 7 | 8 | #include "char.h" 9 | #include "rs-common.h" 10 | 11 | void free_rs_char(void *p){ 12 | struct rs *rs = (struct rs *)p; 13 | 14 | free(rs->alpha_to); 15 | free(rs->index_of); 16 | free(rs->genpoly); 17 | free(rs); 18 | } 19 | 20 | /* Initialize a Reed-Solomon codec 21 | * symsize = symbol size, bits 22 | * gfpoly = Field generator polynomial coefficients 23 | * fcr = first root of RS code generator polynomial, index form 24 | * prim = primitive element to generate polynomial roots 25 | * nroots = RS code generator polynomial degree (number of roots) 26 | * pad = padding bytes at front of shortened block 27 | */ 28 | void *init_rs_char(int symsize,int gfpoly,int fcr,int prim, 29 | int nroots,int pad){ 30 | struct rs *rs; 31 | 32 | #include "init_rs.h" 33 | 34 | return rs; 35 | } 36 | -------------------------------------------------------------------------------- /lib/fec/rs-common.h: -------------------------------------------------------------------------------- 1 | /* Stuff common to all the general-purpose Reed-Solomon codecs 2 | * Copyright 2004 Phil Karn, KA9Q 3 | * May be used under the terms of the GNU Lesser General Public License (LGPL) 4 | */ 5 | 6 | /* Reed-Solomon codec control block */ 7 | struct rs { 8 | int mm; /* Bits per symbol */ 9 | int nn; /* Symbols per block (= (1<= rs->nn) { 22 | x -= rs->nn; 23 | x = (x >> rs->mm) + (x & rs->nn); 24 | } 25 | return x; 26 | } 27 | -------------------------------------------------------------------------------- /m4/ax_check_compile_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check whether the given FLAG works with the current language's compiler 12 | # or gives an error. (Warnings, however, are ignored) 13 | # 14 | # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 | # success/failure. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the current language's default 18 | # flags (e.g. CFLAGS) when the check is done. The check is thus made with 19 | # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to 20 | # force the compiler to issue an error when a bad flag is given. 21 | # 22 | # INPUT gives an alternative input source to AC_COMPILE_IFELSE. 23 | # 24 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 25 | # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. 26 | # 27 | # LICENSE 28 | # 29 | # Copyright (c) 2008 Guido U. Draheim 30 | # Copyright (c) 2011 Maarten Bosmans 31 | # 32 | # Copying and distribution of this file, with or without modification, are 33 | # permitted in any medium without royalty provided the copyright notice 34 | # and this notice are preserved. This file is offered as-is, without any 35 | # warranty. 36 | 37 | #serial 6 38 | 39 | AC_DEFUN([AX_CHECK_COMPILE_FLAG], 40 | [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF 41 | AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl 42 | AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ 43 | ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS 44 | _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" 45 | AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], 46 | [AS_VAR_SET(CACHEVAR,[yes])], 47 | [AS_VAR_SET(CACHEVAR,[no])]) 48 | _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) 49 | AS_VAR_IF(CACHEVAR,yes, 50 | [m4_default([$2], :)], 51 | [m4_default([$3], :)]) 52 | AS_VAR_POPDEF([CACHEVAR])dnl 53 | ])dnl AX_CHECK_COMPILE_FLAGS 54 | -------------------------------------------------------------------------------- /m4/ax_zmq.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_zmq.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_ZMQ([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Test for the ZMQ libraries of a particular version (or newer). The 12 | # default version tested for is 4.0.0. 13 | # 14 | # The macro tests for ZMQ libraries in the library/include path, and, when 15 | # provided, also in the path given by --with-zmq. 16 | # 17 | # This macro calls: 18 | # 19 | # AC_SUBST(ZMQ_CPPFLAGS) / AC_SUBST(ZMQ_LDFLAGS) / AC_SUBST(ZMQ_LIBS) 20 | # 21 | # And sets: 22 | # 23 | # HAVE_ZMQ 24 | # 25 | # LICENSE 26 | # 27 | # Copyright (c) 2016 Jeroen Meijer 28 | # 29 | # Copying and distribution of this file, with or without modification, are 30 | # permitted in any medium without royalty provided the copyright notice 31 | # and this notice are preserved. This file is offered as-is, without any 32 | # warranty. 33 | 34 | #serial 3 35 | 36 | AC_DEFUN([AX_ZMQ], [ 37 | AC_ARG_WITH([zmq], [AS_HELP_STRING([--with-zmq=],[ZMQ prefix directory])], [ 38 | ZMQ_LDFLAGS="-L${with_zmq}/lib" 39 | ZMQ_CPPFLAGS="-I${with_zmq}/include" 40 | ]) 41 | 42 | HAVE_ZMQ=0 43 | if test "$with_zmq" != "no"; then 44 | 45 | LD_FLAGS="$LDFLAGS $ZMQ_LDFLAGS" 46 | CPPFLAGS="$CPPFLAGS $ZMQ_CPPFLAGS" 47 | 48 | AC_LANG_PUSH([C]) 49 | AC_CHECK_HEADER(zmq.h, [zmq_h=yes], [zmq_h=no]) 50 | AC_LANG_POP([C]) 51 | 52 | if test "$zmq_h" = "yes"; then 53 | version=ifelse([$1], ,4.0.0,$1) 54 | AC_MSG_CHECKING([for ZMQ version >= $version]) 55 | version=$(echo $version | tr '.' ',') 56 | AC_EGREP_CPP([version_ok], [ 57 | #include 58 | #if defined(ZMQ_VERSION) && ZMQ_VERSION >= ZMQ_MAKE_VERSION($version) 59 | version_ok 60 | #endif 61 | ],[ 62 | AC_MSG_RESULT(yes) 63 | HAVE_ZMQ=1 64 | ZMQ_LIBS="-lzmq" 65 | AC_SUBST(ZMQ_LDFLAGS) 66 | AC_SUBST(ZMQ_CPPFLAGS) 67 | AC_SUBST(ZMQ_LIBS) 68 | ], AC_MSG_RESULT([no valid ZMQ version was found])) 69 | else 70 | AC_MSG_WARN([no valid ZMQ installation was found]) 71 | fi 72 | 73 | if test $HAVE_ZMQ = 1; then 74 | # execute ACTION-IF-FOUND (if present): 75 | ifelse([$2], , :, [$2]) 76 | else 77 | # execute ACTION-IF-NOT-FOUND (if present): 78 | ifelse([$3], , :, [$3]) 79 | fi 80 | else 81 | AC_MSG_NOTICE([not checking for ZMQ]) 82 | fi 83 | 84 | AC_DEFINE(HAVE_ZMQ,,[define if the ZMQ library is available]) 85 | ]) 86 | -------------------------------------------------------------------------------- /man/odr-dabmux.1: -------------------------------------------------------------------------------- 1 | .TH ODR-DABMUX "1" "May 2025" "odr-dabmux 5.2.0" "User Commands" 2 | .SH NAME 3 | \fBodr\-dabmux\fR \- A software DAB multiplexer 4 | .SH SYNOPSIS 5 | odr\-dabmux 6 | .PP 7 | This software requires a configuration file. See doc/example.config for an example format for the configuration file 8 | .SH DESCRIPTION 9 | odr\-dabmux implements a DAB multiplexer that combines all audio and data 10 | inputs into an ETI output. It can be used off-line (i.e. not real-time) to generate 11 | ETI data for later processing, or in a real-time streaming scenario (e.g. in a 12 | transmitter). 13 | .PP 14 | odr\-dabmux can read input audio or data from files (".mp2" for DAB, ".dabp" 15 | for DAB+), FIFOs (also called "named pipes"), or from a network connection. This 16 | network connection can use UDP (STI-D) or EDI. 17 | .PP 18 | The configuration of the multiplexer is given in a configuration file, whose 19 | format is defined in the example files in the doc/ folder inside the ODR-DabMux 20 | repository. 21 | .SH SEE ALSO 22 | odr\-audioenc(1), odr\-dabmod(1) 23 | 24 | A user guide for the mmbTools is available http://www.opendigitalradio.org/ 25 | -------------------------------------------------------------------------------- /src/ConfigParser.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2016 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | 9 | The Configuration parser sets up the ensemble according 10 | to the configuration given in a boost property tree, which 11 | is directly derived from a config file. 12 | 13 | The format of the configuration is given in doc/example.mux 14 | */ 15 | /* 16 | This file is part of ODR-DabMux. 17 | 18 | ODR-DabMux is free software: you can redistribute it and/or modify 19 | it under the terms of the GNU General Public License as 20 | published by the Free Software Foundation, either version 3 of the 21 | License, or (at your option) any later version. 22 | 23 | ODR-DabMux is distributed in the hope that it will be useful, 24 | but WITHOUT ANY WARRANTY; without even the implied warranty of 25 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 | GNU General Public License for more details. 27 | 28 | You should have received a copy of the GNU General Public License 29 | along with ODR-DabMux. If not, see . 30 | */ 31 | #pragma once 32 | 33 | #include "MuxElements.h" 34 | #include 35 | #include 36 | 37 | void parse_ptree(boost::property_tree::ptree& pt, 38 | std::shared_ptr ensemble); 39 | 40 | -------------------------------------------------------------------------------- /src/DabMux.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2014 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | 9 | This file declares several structures used in the multiplexer, 10 | and defines default values for some parameters. 11 | */ 12 | /* 13 | This file is part of ODR-DabMux. 14 | 15 | ODR-DabMux is free software: you can redistribute it and/or modify 16 | it under the terms of the GNU General Public License as 17 | published by the Free Software Foundation, either version 3 of the 18 | License, or (at your option) any later version. 19 | 20 | ODR-DabMux is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | GNU General Public License for more details. 24 | 25 | You should have received a copy of the GNU General Public License 26 | along with ODR-DabMux. If not, see . 27 | */ 28 | #pragma once 29 | 30 | #include 31 | #include 32 | #include 33 | #include "DabMultiplexer.h" 34 | #include "RemoteControl.h" 35 | #include "dabOutput/dabOutput.h" 36 | #include "input/inputs.h" 37 | #include "Eti.h" 38 | #include "MuxElements.h" 39 | 40 | #ifdef _WIN32 41 | # include 42 | #else 43 | # include 44 | #endif 45 | 46 | -------------------------------------------------------------------------------- /src/Dmb.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in Right 3 | of Canada (Communications Research Center Canada) 4 | */ 5 | /* 6 | This file is part of ODR-DabMux. 7 | 8 | ODR-DabMux is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as 10 | published by the Free Software Foundation, either version 3 of the 11 | License, or (at your option) any later version. 12 | 13 | ODR-DabMux is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with ODR-DabMux. If not, see . 20 | */ 21 | 22 | #ifndef _DMB 23 | #define _DMB 24 | 25 | #ifdef HAVE_CONFIG_H 26 | # include "config.h" 27 | #endif 28 | 29 | #include "Interleaver.h" 30 | #include "ReedSolomon.h" 31 | 32 | 33 | class DmbStats 34 | { 35 | public: 36 | DmbStats(); 37 | void reset(); 38 | 39 | unsigned dmbFrame; 40 | unsigned mpgFrame; 41 | unsigned synFrame; 42 | unsigned rcvBytes; 43 | unsigned nulBytes; 44 | unsigned sndBytes; 45 | unsigned errBytes; 46 | unsigned corBytes; 47 | }; 48 | 49 | 50 | class Dmb 51 | { 52 | public: 53 | Dmb(bool reverse = false); 54 | Dmb(const Dmb& clone); 55 | virtual ~Dmb(); 56 | 57 | void setReverse(bool state); 58 | int encode(void* dataIn, unsigned long sizeIn, void* dataOut, unsigned long sizeOut); 59 | void reset(); 60 | DmbStats getStats() { return stats; }; 61 | 62 | private: 63 | int sync(void* dataIn, unsigned long sizeIn); 64 | 65 | Interleaver interleaver; 66 | ReedSolomon encoder; 67 | unsigned char* buffer; 68 | unsigned bufferSize; 69 | unsigned bufferOffset; // Encoded data written to output 70 | unsigned bufferLength; // Encoded data 71 | unsigned inputOffset; 72 | unsigned outputOffset; 73 | // unsigned padding; // Padding data written 74 | 75 | bool reverse; 76 | 77 | DmbStats stats; 78 | }; 79 | 80 | 81 | #endif // _DMB 82 | -------------------------------------------------------------------------------- /src/Eti.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in Right 3 | of Canada (Communications Research Center Canada) 4 | 5 | Includes modifications 6 | 2012, Matthias P. Braendli, matthias.braendli@mpb.li 7 | */ 8 | /* 9 | This file is part of ODR-DabMux. 10 | 11 | ODR-DabMux is free software: you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation, either version 3 of the 14 | License, or (at your option) any later version. 15 | 16 | ODR-DabMux is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with ODR-DabMux. If not, see . 23 | */ 24 | 25 | #ifdef _WIN32 26 | # pragma warning ( disable : 4103 ) 27 | # include "Eti.h" 28 | # pragma warning ( default : 4103 ) 29 | #else 30 | # include "Eti.h" 31 | # include 32 | #endif 33 | 34 | 35 | //definitions des structures des champs du ETI(NI, G703) 36 | 37 | 38 | unsigned short eti_FC::getFrameLength() 39 | { 40 | return (unsigned short)((FL_high << 8) | FL_low); 41 | } 42 | 43 | 44 | void eti_FC::setFrameLength(uint16_t length) 45 | { 46 | FL_high = (length >> 8) & 0x07; 47 | FL_low = length & 0xff; 48 | } 49 | 50 | 51 | void eti_STC::setSTL(uint16_t length) 52 | { 53 | STL_high = length >> 8; 54 | STL_low = length & 0xff; 55 | } 56 | 57 | 58 | uint16_t eti_STC::getSTL() 59 | { 60 | return (uint16_t)((STL_high << 8) + STL_low); 61 | } 62 | 63 | 64 | void eti_STC::setStartAddress(uint16_t address) 65 | { 66 | startAddress_high = address >> 8; 67 | startAddress_low = address & 0xff; 68 | } 69 | 70 | 71 | uint16_t eti_STC::getStartAddress() 72 | { 73 | return (uint16_t)((startAddress_high << 8) + startAddress_low); 74 | } 75 | 76 | /* Helper functions for eti_MNSC_TIME_x which fill the time-relevant 77 | * fields for the MNSC 78 | */ 79 | void eti_MNSC_TIME_1::setFromTime(struct tm *time_tm) 80 | { 81 | second_unit = time_tm->tm_sec % 10; 82 | second_tens = time_tm->tm_sec / 10; 83 | 84 | minute_unit = time_tm->tm_min % 10; 85 | minute_tens = time_tm->tm_min / 10; 86 | } 87 | 88 | void eti_MNSC_TIME_2::setFromTime(struct tm *time_tm) 89 | { 90 | hour_unit = time_tm->tm_hour % 10; 91 | hour_tens = time_tm->tm_hour / 10; 92 | 93 | day_unit = time_tm->tm_mday % 10; 94 | day_tens = time_tm->tm_mday / 10; 95 | } 96 | 97 | void eti_MNSC_TIME_3::setFromTime(struct tm *time_tm) 98 | { 99 | month_unit = (time_tm->tm_mon + 1) % 10; 100 | month_tens = (time_tm->tm_mon + 1) / 10; 101 | 102 | // They didn't see the y2k bug coming, did they ? 103 | year_unit = (time_tm->tm_year - 100) % 10; 104 | year_tens = (time_tm->tm_year - 100) / 10; 105 | } 106 | -------------------------------------------------------------------------------- /src/Eti.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in Right 3 | of Canada (Communications Research Center Canada) 4 | 5 | Includes modifications 6 | 2012, Matthias P. Braendli, matthias.braendli@mpb.li 7 | */ 8 | /* 9 | This file is part of ODR-DabMux. 10 | 11 | ODR-DabMux is free software: you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as 13 | published by the Free Software Foundation, either version 3 of the 14 | License, or (at your option) any later version. 15 | 16 | ODR-DabMux is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with ODR-DabMux. If not, see . 23 | */ 24 | 25 | #ifndef ETI_ 26 | #define ETI_ 27 | 28 | #ifdef HAVE_CONFIG_H 29 | # include 30 | #endif 31 | 32 | #ifdef _WIN32 33 | # include // For types... 34 | typedef WORD uint16_t; 35 | typedef DWORD32 uint32_t; 36 | 37 | # define PACKED 38 | # pragma pack(push, 1) 39 | #else 40 | # include 41 | # include 42 | 43 | # define PACKED __attribute__ ((packed)) 44 | #endif 45 | 46 | 47 | //definitions des structures des champs du ETI(NI, G703) 48 | 49 | 50 | struct eti_SYNC { 51 | uint32_t ERR:8; 52 | uint32_t FSYNC:24; 53 | } PACKED; 54 | 55 | 56 | struct eti_FC { 57 | uint32_t FCT:8; 58 | uint32_t NST:7; 59 | uint32_t FICF:1; 60 | uint32_t FL_high:3; 61 | uint32_t MID:2; 62 | uint32_t FP:3; 63 | uint32_t FL_low:8; 64 | uint16_t getFrameLength(); 65 | void setFrameLength(uint16_t length); 66 | } PACKED; 67 | 68 | 69 | struct eti_STC { 70 | uint32_t startAddress_high:2; 71 | uint32_t SCID:6; 72 | uint32_t startAddress_low:8; 73 | uint32_t STL_high:2; 74 | uint32_t TPL:6; 75 | uint32_t STL_low:8; 76 | void setSTL(uint16_t length); 77 | uint16_t getSTL(); 78 | void setStartAddress(uint16_t address); 79 | uint16_t getStartAddress(); 80 | } PACKED; 81 | 82 | 83 | struct eti_EOH { 84 | uint16_t MNSC; 85 | uint16_t CRC; 86 | } PACKED; 87 | 88 | 89 | struct eti_EOF { 90 | uint16_t CRC; 91 | uint16_t RFU; 92 | } PACKED; 93 | 94 | 95 | struct eti_TIST { 96 | uint32_t TIST; 97 | } PACKED; 98 | 99 | 100 | struct eti_MNSC_TIME_0 { 101 | uint32_t type:4; 102 | uint32_t identifier:4; 103 | uint32_t rfa:8; 104 | } PACKED; 105 | 106 | struct eti_MNSC_TIME_1 { 107 | uint32_t second_unit:4; 108 | uint32_t second_tens:3; 109 | uint32_t accuracy:1; 110 | 111 | uint32_t minute_unit:4; 112 | uint32_t minute_tens:3; 113 | uint32_t sync_to_frame:1; 114 | void setFromTime(struct tm *time_tm); 115 | } PACKED; 116 | 117 | struct eti_MNSC_TIME_2 { 118 | uint32_t hour_unit:4; 119 | uint32_t hour_tens:4; 120 | 121 | uint32_t day_unit:4; 122 | uint32_t day_tens:4; 123 | void setFromTime(struct tm *time_tm); 124 | } PACKED; 125 | 126 | struct eti_MNSC_TIME_3 { 127 | uint32_t month_unit:4; 128 | uint32_t month_tens:4; 129 | 130 | uint32_t year_unit:4; 131 | uint32_t year_tens:4; 132 | void setFromTime(struct tm *time_tm); 133 | } PACKED; 134 | 135 | #endif // ETI_ 136 | -------------------------------------------------------------------------------- /src/Interleaver.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in Right 3 | of Canada (Communications Research Center Canada) 4 | */ 5 | /* 6 | This file is part of ODR-DabMux. 7 | 8 | ODR-DabMux is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as 10 | published by the Free Software Foundation, either version 3 of the 11 | License, or (at your option) any later version. 12 | 13 | ODR-DabMux is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with ODR-DabMux. If not, see . 20 | */ 21 | 22 | #ifndef _INTERLEAVER 23 | #define _INTERLEAVER 24 | 25 | #ifdef HAVE_CONFIG_H 26 | # include "config.h" 27 | #endif 28 | 29 | #include 30 | 31 | class Interleaver 32 | { 33 | public: 34 | Interleaver(unsigned short I, unsigned short M, bool reverse = false); 35 | 36 | void setReverse(bool state); 37 | void encode(void* data, unsigned long size); 38 | void encode(const void* inData, void* outData, unsigned long size); 39 | unsigned long sync(void* data, unsigned long size, char padding = 0); 40 | void reset(); 41 | void flush(char padding = 0); 42 | 43 | private: 44 | unsigned short I; 45 | unsigned short M; 46 | unsigned long N; 47 | unsigned long j; 48 | unsigned long index; 49 | unsigned long memSize; 50 | std::vector mem; 51 | bool reverse; 52 | }; 53 | 54 | 55 | #endif // _INTERLEAVER 56 | -------------------------------------------------------------------------------- /src/PcDebug.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the 3 | Queen in Right of Canada (Communications Research Center Canada) 4 | */ 5 | /* 6 | This file is part of ODR-DabMux. 7 | 8 | ODR-DabMux is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as 10 | published by the Free Software Foundation, either version 3 of the 11 | License, or (at your option) any later version. 12 | 13 | ODR-DabMux is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with ODR-DabMux. If not, see . 20 | */ 21 | 22 | #ifndef PC_DEBUG_ 23 | #define PC_DEBUG_ 24 | 25 | #ifdef HAVE_CONFIG_H 26 | # include "config.h" 27 | #endif 28 | 29 | #define STRINGIFY(x) XSTRINGIFY(x) 30 | #define XSTRINGIFY(x) #x 31 | 32 | #include 33 | 34 | #define LOG stderr 35 | 36 | #if !defined(_WIN32) || defined(__MINGW32__) 37 | # ifndef PDEBUG 38 | # ifdef DEBUG 39 | # define PDEBUG(fmt, args...) fprintf (LOG, fmt , ## args) 40 | # else 41 | # define PDEBUG(fmt, args...) 42 | # endif 43 | # endif 44 | # ifdef DEBUG 45 | # define PDEBUG_VERBOSE(level, verbosity, fmt, args...) if (level <= verbosity) { fprintf(LOG, fmt, ## args); fflush(LOG); } 46 | # define PDEBUG0_VERBOSE(level, verbosity, txt) if (level <= verbosity) { fprintf(LOG, txt); fflush(LOG); } 47 | # define PDEBUG1_VERBOSE(level, verbosity, txt, arg0) if (level <= verbosity) { fprintf(LOG, txt, arg0); fflush(LOG); } 48 | # define PDEBUG2_VERBOSE(level, verbosity, txt, arg0, arg1) if (level <= verbosity) { fprintf(LOG, txt, arg0, arg1); fflush(LOG); } 49 | # define PDEBUG3_VERBOSE(level, verbosity, txt, arg0, arg1, arg2) if (level <= verbosity) { fprintf(LOG, txt, arg0, arg1, arg2); fflush(LOG); } 50 | # define PDEBUG4_VERBOSE(level, verbosity, txt, arg0, arg1, arg2, arg3) if (level <= verbosity) { fprintf(LOG, txt, arg0, arg1, arg2, arg3); fflush(LOG); } 51 | # else 52 | # define PDEBUG_VERBOSE(level, verbosity, fmt, args...) 53 | # define PDEBUG0_VERBOSE(level, verbosity, txt) 54 | # define PDEBUG1_VERBOSE(level, verbosity, txt, arg0) 55 | # define PDEBUG2_VERBOSE(level, verbosity, txt, arg0, arg1) 56 | # define PDEBUG3_VERBOSE(level, verbosity, txt, arg0, arg1, arg2) 57 | # define PDEBUG4_VERBOSE(level, verbosity, txt, arg0, arg1, arg2, arg3) 58 | # endif // DEBUG 59 | #else // _WIN32 60 | # ifdef _DEBUG 61 | # define PDEBUG 62 | # define PDEBUG_VERBOSE 63 | # define PDEBUG0_VERBOSE(level, verbosity, txt) if (level <= verbosity) { fprintf(LOG, txt); fflush(LOG); } 64 | # define PDEBUG1_VERBOSE(level, verbosity, txt, arg0) if (level <= verbosity) { fprintf(LOG, txt, arg0); fflush(LOG); } 65 | # define PDEBUG2_VERBOSE(level, verbosity, txt, arg0, arg1) if (level <= verbosity) { fprintf(LOG, txt, arg0, arg1); fflush(LOG); } 66 | # define PDEBUG3_VERBOSE(level, verbosity, txt, arg0, arg1, arg2) if (level <= verbosity) { fprintf(LOG, txt, arg0, arg1, arg2); fflush(LOG); } 67 | # define PDEBUG4_VERBOSE(level, verbosity, txt, arg0, arg1, arg2, arg3) if (level <= verbosity) { fprintf(LOG, txt, arg0, arg1, arg2, arg3); fflush(LOG); } 68 | # else 69 | # define PDEBUG 70 | # define PDEBUG_VERBOSE 71 | # define PDEBUG0_VERBOSE(level, verbosity, txt) 72 | # define PDEBUG1_VERBOSE(level, verbosity, txt, arg0) 73 | # define PDEBUG2_VERBOSE(level, verbosity, txt, arg0, arg1) 74 | # define PDEBUG3_VERBOSE(level, verbosity, txt, arg0, arg1, arg2) 75 | # define PDEBUG4_VERBOSE(level, verbosity, txt, arg0, arg1, arg2, arg3) 76 | # endif 77 | #endif 78 | 79 | #endif // PC_DEBUG_ 80 | -------------------------------------------------------------------------------- /src/PrbsGenerator.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in Right 3 | of Canada (Communications Research Center Canada) 4 | */ 5 | /* 6 | This file is part of ODR-DabMux. 7 | 8 | ODR-DabMux is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as 10 | published by the Free Software Foundation, either version 3 of the 11 | License, or (at your option) any later version. 12 | 13 | ODR-DabMux is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with ODR-DabMux. If not, see . 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | 27 | #ifdef HAVE_CONFIG_H 28 | # include "config.h" 29 | #endif 30 | 31 | class PrbsGenerator { 32 | public: 33 | void setup(uint32_t polynomial); 34 | 35 | uint8_t step(void); 36 | 37 | void rewind(void); 38 | 39 | private: 40 | /* Generate a table of matrix products to update a 32-bit PRBS 41 | * generator. */ 42 | void gen_prbs_table(void); 43 | 44 | /* Update a 32-bit PRBS generator eight bits at a time. */ 45 | uint32_t update_prbs(void); 46 | 47 | /* Generate the weight table. */ 48 | void gen_weight_table(void); 49 | 50 | /* Count the number of errors in a block of received data. */ 51 | size_t error_count( 52 | uint8_t *rx_data, 53 | size_t rx_data_length); 54 | 55 | void gen_sequence( 56 | uint8_t *tx_data, 57 | size_t tx_data_length, 58 | uint32_t polynomial); 59 | 60 | // table of matrix products used to update a 32-bit PRBS generator 61 | uint32_t prbs_table [4] [256]; 62 | // table of weights for 8-bit bytes 63 | uint8_t weight[256]; 64 | // PRBS polynomial generator 65 | uint32_t polynomial; 66 | // PRBS generator polarity mask 67 | uint8_t polarity_mask; 68 | // PRBS accumulator 69 | uint32_t accum; 70 | }; 71 | 72 | -------------------------------------------------------------------------------- /src/TestStatsServer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "StatsServer.h" 3 | 4 | #define NUMOF(x) (sizeof(x) / sizeof(*x)) 5 | 6 | int main(int argc, char **argv) 7 | { 8 | int stats_example[] = {25, 24, 22, 21, 56, 56, 54, 53, 51, 45, 42, 39, 34, 30, 24, 15, 8, 4, 1, 0}; 9 | StatsServer serv(2720); 10 | 11 | serv.registerInput("foo"); 12 | serv.registerInput("bar"); 13 | 14 | while (true) { 15 | for (int i = 0; i < NUMOF(stats_example); i++) { 16 | usleep(400000); 17 | serv.notifyBuffer("foo", stats_example[i]); 18 | fprintf(stderr, "give %d\n", stats_example[i]); 19 | 20 | if (stats_example[i] == 0) { 21 | serv.notifyUnderrun("foo"); 22 | } 23 | 24 | if (stats_example[i] == 56) { 25 | serv.notifyOverrun("foo"); 26 | } 27 | } 28 | } 29 | 30 | return 0; 31 | } 32 | 33 | -------------------------------------------------------------------------------- /src/dabInputDmbFile.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications 3 | Research Center Canada) 4 | */ 5 | /* 6 | This file is part of ODR-DabMux. 7 | 8 | ODR-DabMux is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as 10 | published by the Free Software Foundation, either version 3 of the 11 | License, or (at your option) any later version. 12 | 13 | ODR-DabMux is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with ODR-DabMux. If not, see . 20 | */ 21 | 22 | #ifndef DAB_INPUT_DMB_FILE_H 23 | #define DAB_INPUT_DMB_FILE_H 24 | 25 | 26 | #ifdef HAVE_CONFIG_H 27 | # include "config.h" 28 | #endif 29 | #include "dabInput.h" 30 | 31 | 32 | #ifdef HAVE_FORMAT_DMB 33 | # ifdef HAVE_INPUT_FILE 34 | 35 | 36 | extern struct dabInputOperations dabInputDmbFileOperations; 37 | 38 | int dabInputDmbFileInit(void** args); 39 | int dabInputDmbFileOpen(void* args, const char* inputName); 40 | int dabInputDmbFileRead(dabInputOperations* ops, void* args, void* buffer, int size); 41 | int dabInputDmbFileClose(void* args); 42 | int dabInputDmbFileClean(void** args); 43 | 44 | 45 | # endif 46 | #endif 47 | 48 | 49 | #endif // DAB_INPUT_DMB_FILE_H 50 | -------------------------------------------------------------------------------- /src/dabInputDmbUdp.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications 3 | Research Center Canada) 4 | */ 5 | /* 6 | This file is part of ODR-DabMux. 7 | 8 | ODR-DabMux is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as 10 | published by the Free Software Foundation, either version 3 of the 11 | License, or (at your option) any later version. 12 | 13 | ODR-DabMux is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with ODR-DabMux. If not, see . 20 | */ 21 | 22 | #ifndef DAB_INPUT_DMB_UDP_H 23 | #define DAB_INPUT_DMB_UDP_H 24 | 25 | 26 | #ifdef HAVE_CONFIG_H 27 | # include "config.h" 28 | #endif 29 | #include "dabInput.h" 30 | 31 | 32 | #ifdef HAVE_FORMAT_DMB 33 | # ifdef HAVE_INPUT_UDP 34 | 35 | 36 | extern struct dabInputOperations dabInputDmbUdpOperations; 37 | 38 | int dabInputDmbUdpInit(void** args); 39 | int dabInputDmbUdpOpen(void* args, const char* inputName); 40 | int dabInputDmbUdpRead(dabInputOperations* ops, void* args, void* buffer, int size); 41 | int dabInputDmbUdpClose(void* args); 42 | int dabInputDmbUdpClean(void** args); 43 | 44 | 45 | # endif 46 | #endif 47 | 48 | 49 | #endif // DAB_INPUT_DMB_UDP_H 50 | -------------------------------------------------------------------------------- /src/dabOutput/dabOutputFifo.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in 3 | Right of Canada (Communications Research Center Canada) 4 | 5 | Copyright (C) 2016 6 | Matthias P. Braendli, matthias.braendli@mpb.li 7 | 8 | http://www.opendigitalradio.org 9 | 10 | Fifo output is very similar to file, except it doesn't seek 11 | */ 12 | /* 13 | This file is part of ODR-DabMux. 14 | 15 | ODR-DabMux is free software: you can redistribute it and/or modify 16 | it under the terms of the GNU General Public License as 17 | published by the Free Software Foundation, either version 3 of the 18 | License, or (at your option) any later version. 19 | 20 | ODR-DabMux is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | GNU General Public License for more details. 24 | 25 | You should have received a copy of the GNU General Public License 26 | along with ODR-DabMux. If not, see . 27 | */ 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "dabOutput.h" 37 | 38 | int DabOutputFifo::Open(const char* filename) 39 | { 40 | filename_ = SetEtiType(filename); 41 | 42 | // Create the fifo if it does not already exist 43 | struct stat s = {0}; 44 | int ret = stat(filename_.c_str(), &s); 45 | 46 | if (ret == -1) { 47 | if (errno == ENOENT) { 48 | ret = mkfifo(filename_.c_str(), 0666); 49 | if (ret == -1) { 50 | etiLog.level(error) << "Could not create fifo " << filename_ << " : " << 51 | strerror(errno); 52 | return -1; 53 | } 54 | } 55 | else { 56 | etiLog.level(error) << "Could not stat fifo " << filename_ << " : " << 57 | strerror(errno); 58 | return -1; 59 | } 60 | } 61 | 62 | this->file_ = open(filename_.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); 63 | if (this->file_ == -1) { 64 | perror(filename_.c_str()); 65 | return -1; 66 | } 67 | return 0; 68 | } 69 | 70 | 71 | int DabOutputFifo::Write(void* buffer, int size) 72 | { 73 | uint8_t padding[6144]; 74 | 75 | switch (this->type_) { 76 | case ETI_FILE_TYPE_FRAMED: 77 | if (this->nbFrames_ == 0) { 78 | uint32_t nbFrames = (uint32_t)-1; 79 | // Writing nb frames 80 | if (write(this->file_, &nbFrames, 4) == -1) 81 | goto FIFO_WRITE_ERROR; 82 | } 83 | case ETI_FILE_TYPE_STREAMED: 84 | // Writing frame length 85 | if (write(this->file_, &size, 2) == -1) 86 | goto FIFO_WRITE_ERROR; 87 | // Appending data 88 | if (write(this->file_, buffer, size) == -1) 89 | goto FIFO_WRITE_ERROR; 90 | break; 91 | case ETI_FILE_TYPE_RAW: 92 | // Appending data 93 | if (write(this->file_, buffer, size) == -1) 94 | goto FIFO_WRITE_ERROR; 95 | // Appending padding 96 | memset(padding, 0x55, 6144 - size); 97 | if (write(this->file_, padding, 6144 - size) == -1) 98 | goto FIFO_WRITE_ERROR; 99 | break; 100 | case ETI_FILE_TYPE_NONE: 101 | default: 102 | etiLog.log(error, "File type is not supported.\n"); 103 | return -1; 104 | } 105 | 106 | return size; 107 | 108 | FIFO_WRITE_ERROR: 109 | perror("Error while writing to fifo"); 110 | return -1; 111 | } 112 | -------------------------------------------------------------------------------- /src/dabOutput/dabOutputSimul.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in 3 | Right of Canada (Communications Research Center Canada) 4 | 5 | Copyright (C) 2018 6 | Matthias P. Braendli, matthias.braendli@mpb.li 7 | 8 | http://www.opendigitalradio.org 9 | 10 | SIMUL throttling output. It guarantees correct frame generation rate 11 | */ 12 | /* 13 | This file is part of ODR-DabMux. 14 | 15 | ODR-DabMux is free software: you can redistribute it and/or modify 16 | it under the terms of the GNU General Public License as 17 | published by the Free Software Foundation, either version 3 of the 18 | License, or (at your option) any later version. 19 | 20 | ODR-DabMux is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | GNU General Public License for more details. 24 | 25 | You should have received a copy of the GNU General Public License 26 | along with ODR-DabMux. If not, see . 27 | */ 28 | #include "dabOutput.h" 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | 37 | int DabOutputSimul::Open(const char* name) 38 | { 39 | startTime_ = std::chrono::steady_clock::now(); 40 | return 0; 41 | } 42 | 43 | int DabOutputSimul::Write(void* buffer, int size) 44 | { 45 | auto curTime = std::chrono::steady_clock::now(); 46 | 47 | const auto frameinterval = std::chrono::milliseconds(24); 48 | 49 | auto diff = curTime - startTime_; 50 | auto waiting = frameinterval - diff; 51 | 52 | if (diff < frameinterval) { 53 | std::this_thread::sleep_for(waiting); 54 | } 55 | 56 | startTime_ += frameinterval; 57 | 58 | return size; 59 | } 60 | 61 | -------------------------------------------------------------------------------- /src/dabOutput/dabOutputTcp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in 3 | Right of Canada (Communications Research Center Canada) 4 | 5 | Copyright (C) 2018 6 | Matthias P. Braendli, matthias.braendli@mpb.li 7 | 8 | http://www.opendigitalradio.org 9 | 10 | TCP output 11 | */ 12 | /* 13 | This file is part of ODR-DabMux. 14 | 15 | ODR-DabMux is free software: you can redistribute it and/or modify 16 | it under the terms of the GNU General Public License as 17 | published by the Free Software Foundation, either version 3 of the 18 | License, or (at your option) any later version. 19 | 20 | ODR-DabMux is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | GNU General Public License for more details. 24 | 25 | You should have received a copy of the GNU General Public License 26 | along with ODR-DabMux. If not, see . 27 | */ 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include "dabOutput.h" 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include "ThreadsafeQueue.h" 40 | 41 | using namespace std; 42 | 43 | using vec_u8 = std::vector; 44 | 45 | // In ETI one element would be an ETI frame of 6144 bytes. 46 | // 250 frames correspond to 6 seconds. This is mostly here 47 | // to ensure we do not accumulate data for faulty sockets, delay 48 | // management has to be done on the receiver end. 49 | const size_t MAX_QUEUED_ETI_FRAMES = 250; 50 | 51 | static bool parse_uri(const char *uri, long *port, string& addr) 52 | { 53 | char* const hostport = strdup(uri); // the uri is actually an tuple host:port 54 | 55 | char* address; 56 | address = strchr((char*)hostport, ':'); 57 | if (address == NULL) { 58 | etiLog.log(error, 59 | "\"%s\" is an invalid format for tcp address: " 60 | "should be [address]:port - > aborting\n", 61 | hostport); 62 | goto tcp_open_fail; 63 | } 64 | 65 | // terminate string hostport after the host, and advance address to the port number 66 | *(address++) = 0; 67 | 68 | *port = strtol(address, (char **)NULL, 10); 69 | if ((*port == LONG_MIN) || (*port == LONG_MAX)) { 70 | etiLog.log(error, 71 | "can't convert port number in tcp address %s\n", address); 72 | goto tcp_open_fail; 73 | } 74 | if (*port == 0) { 75 | etiLog.log(error, 76 | "can't use port number 0 in tcp address\n"); 77 | goto tcp_open_fail; 78 | } 79 | addr = hostport; 80 | free(hostport); 81 | return true; 82 | 83 | tcp_open_fail: 84 | free(hostport); 85 | return false; 86 | } 87 | 88 | int DabOutputTcp::Open(const char* name) 89 | { 90 | long port = 0; 91 | string address; 92 | bool success = parse_uri(name, &port, address); 93 | 94 | uri_ = name; 95 | 96 | if (success) { 97 | dispatcher_ = make_shared(MAX_QUEUED_ETI_FRAMES, 0); 98 | dispatcher_->start(port, address); 99 | } 100 | else { 101 | throw runtime_error(string("Could not parse TCP output address ") + name); 102 | } 103 | return 0; 104 | } 105 | 106 | 107 | int DabOutputTcp::Write(void* buffer, int size) 108 | { 109 | vec_u8 data(6144); 110 | uint8_t* buffer_u8 = (uint8_t*)buffer; 111 | 112 | std::copy(buffer_u8, buffer_u8 + size, data.begin()); 113 | 114 | // Pad to 6144 bytes 115 | std::fill(data.begin() + size, data.end(), 0x55); 116 | 117 | dispatcher_->write(data); 118 | return size; 119 | } 120 | 121 | 122 | int DabOutputTcp::Close() 123 | { 124 | return 0; 125 | } 126 | -------------------------------------------------------------------------------- /src/dabOutput/metadata.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in 3 | Right of Canada (Communications Research Center Canada) 4 | 5 | Copyright (C) 2017 6 | Matthias P. Braendli, matthias.braendli@mpb.li 7 | 8 | http://www.opendigitalradio.org 9 | 10 | The metadata support for the outputs. 11 | */ 12 | /* 13 | This file is part of ODR-DabMux. 14 | 15 | ODR-DabMux is free software: you can redistribute it and/or modify 16 | it under the terms of the GNU General Public License as 17 | published by the Free Software Foundation, either version 3 of the 18 | License, or (at your option) any later version. 19 | 20 | ODR-DabMux is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | GNU General Public License for more details. 24 | 25 | You should have received a copy of the GNU General Public License 26 | along with ODR-DabMux. If not, see . 27 | */ 28 | 29 | #include "dabOutput/metadata.h" 30 | #include 31 | #include 32 | 33 | #ifdef HAVE_CONFIG_H 34 | # include "config.h" 35 | #endif 36 | 37 | template 38 | size_t write_meta(output_metadata_id_e md, uint8_t *buf, const T value) 39 | { 40 | buf[0] = static_cast(md); 41 | 42 | const int16_t len_value = sizeof(T); 43 | 44 | const uint16_t data_length = htons(len_value); 45 | memcpy(buf + 1, &data_length, sizeof(data_length)); 46 | 47 | if (len_value == 1) { 48 | buf[3] = value; 49 | } 50 | else if (len_value == 2) { 51 | const uint16_t val = htons(value); 52 | memcpy(buf + 3, &val, sizeof(val)); 53 | } 54 | else if (len_value == 4) { 55 | const uint32_t val = htonl(value); 56 | memcpy(buf + 3, &val, sizeof(val)); 57 | } 58 | else { 59 | throw std::runtime_error("Unsupported metadata len " + 60 | std::to_string(len_value)); 61 | } 62 | 63 | return 3 + len_value; 64 | } 65 | 66 | size_t OutputMetadataSeparation::write(uint8_t *buf) 67 | { 68 | buf[0] = static_cast(getId()); 69 | 70 | // Length 0 71 | buf[1] = 0; 72 | buf[2] = 0; 73 | return 3; 74 | } 75 | 76 | size_t OutputMetadataUTCO::write(uint8_t *buf) 77 | { 78 | return write_meta(getId(), buf, utco); 79 | } 80 | 81 | size_t OutputMetadataEDITime::write(uint8_t *buf) 82 | { 83 | return write_meta(getId(), buf, seconds); 84 | } 85 | 86 | size_t OutputMetadataDLFC::write(uint8_t *buf) 87 | { 88 | return write_meta(getId(), buf, dlfc); 89 | } 90 | 91 | -------------------------------------------------------------------------------- /src/dabOutput/metadata.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in 3 | Right of Canada (Communications Research Center Canada) 4 | 5 | Copyright (C) 2017 6 | Matthias P. Braendli, matthias.braendli@mpb.li 7 | 8 | http://www.opendigitalradio.org 9 | 10 | The metadata support for the outputs. 11 | */ 12 | /* 13 | This file is part of ODR-DabMux. 14 | 15 | ODR-DabMux is free software: you can redistribute it and/or modify 16 | it under the terms of the GNU General Public License as 17 | published by the Free Software Foundation, either version 3 of the 18 | License, or (at your option) any later version. 19 | 20 | ODR-DabMux is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | GNU General Public License for more details. 24 | 25 | You should have received a copy of the GNU General Public License 26 | along with ODR-DabMux. If not, see . 27 | */ 28 | 29 | #pragma once 30 | #include "Log.h" 31 | 32 | /* Some outputs support additional metadata to be carried 33 | * next to the main ETI stream. This metadata always has the 34 | * following format: 35 | * Field: | id | len | value | 36 | * Length: 1 2 depending on id 37 | * 38 | * Multi-byte values are transmitted in network byte order. 39 | */ 40 | 41 | enum class output_metadata_id_e { 42 | // Contains no value, can be used to group fields 43 | separation_marker = 0, 44 | 45 | // TAI-UTC offset, value is int16_t. 46 | utc_offset = 1, 47 | 48 | /* EDI Time is the number of SI seconds since 2000-01-01 T 00:00:00 UTC. 49 | * value is an uint32_t */ 50 | edi_time = 2, 51 | 52 | /* The DLFC field from the EDI TAG deti. value is uint16_t */ 53 | dlfc = 3, 54 | }; 55 | 56 | struct OutputMetadata { 57 | virtual ~OutputMetadata() {}; 58 | 59 | virtual output_metadata_id_e getId(void) const = 0; 60 | virtual size_t getLength(void) const = 0; 61 | 62 | /* Write the value in the metadata format to the buffer. 63 | * Returns number of bytes written. The buffer buf needs 64 | * to be large enough to contain the value; 65 | */ 66 | virtual size_t write(uint8_t *buf) = 0; 67 | }; 68 | 69 | struct OutputMetadataSeparation : public OutputMetadata { 70 | explicit OutputMetadataSeparation() {} 71 | output_metadata_id_e getId(void) const { return output_metadata_id_e::separation_marker; } 72 | virtual size_t getLength(void) const { return 3; } 73 | virtual size_t write(uint8_t *buf); 74 | }; 75 | 76 | 77 | struct OutputMetadataUTCO : public OutputMetadata { 78 | explicit OutputMetadataUTCO(int16_t utco) : utco(utco) {} 79 | output_metadata_id_e getId(void) const { return output_metadata_id_e::utc_offset; } 80 | virtual size_t getLength(void) const { return 5; } 81 | virtual size_t write(uint8_t *buf); 82 | 83 | int16_t utco; 84 | }; 85 | 86 | struct OutputMetadataEDITime : public OutputMetadata { 87 | explicit OutputMetadataEDITime(uint32_t seconds) : seconds(seconds) {} 88 | output_metadata_id_e getId(void) const { return output_metadata_id_e::edi_time; } 89 | virtual size_t getLength(void) const { return 7; } 90 | virtual size_t write(uint8_t *buf); 91 | 92 | uint32_t seconds; 93 | 94 | }; 95 | 96 | struct OutputMetadataDLFC : public OutputMetadata { 97 | explicit OutputMetadataDLFC(uint16_t dlfc) : dlfc(dlfc) {} 98 | output_metadata_id_e getId(void) const { return output_metadata_id_e::dlfc; } 99 | virtual size_t getLength(void) const { return 5; } 100 | virtual size_t write(uint8_t *buf); 101 | 102 | uint16_t dlfc; 103 | 104 | }; 105 | 106 | -------------------------------------------------------------------------------- /src/fig/FIG.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2024 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | 9 | */ 10 | /* 11 | This file is part of ODR-DabMux. 12 | 13 | ODR-DabMux is free software: you can redistribute it and/or modify 14 | it under the terms of the GNU General Public License as 15 | published by the Free Software Foundation, either version 3 of the 16 | License, or (at your option) any later version. 17 | 18 | ODR-DabMux is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with ODR-DabMux. If not, see . 25 | */ 26 | 27 | #include "FIG.h" 28 | #include 29 | 30 | namespace FIC { 31 | 32 | int rate_increment_ms(FIG_rate rate) 33 | { 34 | switch (rate) { 35 | /* All these values are multiples of 24, so that it is easier to reason 36 | * about the behaviour when considering ETI frames of 24ms duration 37 | * 38 | * In large ensembles it's not always possible to respect the reptition rates, so 39 | * the values are a bit larger than what the spec says. 40 | * However, we observed that some receivers wouldn't always show labels (rate B), 41 | * and that's why we reduced B rate to slightly below 1s. 42 | * */ 43 | case FIG_rate::FIG0_0: return 96; // Is a special case 44 | case FIG_rate::A: return 240; 45 | case FIG_rate::A_B: return 480; 46 | case FIG_rate::B: return 960; 47 | case FIG_rate::C: return 24000; 48 | case FIG_rate::D: return 30000; 49 | case FIG_rate::E: return 120000; 50 | } 51 | throw std::logic_error("Invalid FIG_rate"); 52 | } 53 | 54 | } // namespace FIC 55 | 56 | -------------------------------------------------------------------------------- /src/fig/FIG0.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2020 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #pragma once 27 | 28 | #include "fig/FIG0structs.h" 29 | #include "fig/FIG0_0.h" 30 | #include "fig/FIG0_1.h" 31 | #include "fig/FIG0_2.h" 32 | #include "fig/FIG0_3.h" 33 | #include "fig/FIG0_5.h" 34 | #include "fig/FIG0_6.h" 35 | #include "fig/FIG0_7.h" 36 | #include "fig/FIG0_8.h" 37 | #include "fig/FIG0_9.h" 38 | #include "fig/FIG0_10.h" 39 | #include "fig/FIG0_13.h" 40 | #include "fig/FIG0_14.h" 41 | #include "fig/FIG0_17.h" 42 | #include "fig/FIG0_18.h" 43 | #include "fig/FIG0_19.h" 44 | #include "fig/FIG0_21.h" 45 | #include "fig/FIG0_24.h" 46 | 47 | -------------------------------------------------------------------------------- /src/fig/FIG0_0.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2016 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #include "fig/FIG0structs.h" 27 | #include "fig/FIG0_0.h" 28 | #include "utils.h" 29 | 30 | namespace FIC { 31 | 32 | struct FIGtype0_0 { 33 | uint8_t Length:5; 34 | uint8_t FIGtypeNumber:3; 35 | uint8_t Extension:5; 36 | uint8_t PD:1; 37 | uint8_t OE:1; 38 | uint8_t CN:1; 39 | 40 | uint16_t EId; 41 | uint8_t CIFcnt_hight:5; 42 | uint8_t Al:1; 43 | uint8_t Change:2; 44 | uint8_t CIFcnt_low:8; 45 | } PACKED; 46 | 47 | //=========== FIG 0/0 =========== 48 | 49 | FillStatus FIG0_0::fill(uint8_t *buf, size_t max_size) 50 | { 51 | FillStatus fs; 52 | 53 | if (max_size < 6) { 54 | fs.num_bytes_written = 0; 55 | return fs; 56 | } 57 | 58 | FIGtype0_0 *fig0_0; 59 | fig0_0 = (FIGtype0_0 *)buf; 60 | 61 | fig0_0->FIGtypeNumber = 0; 62 | fig0_0->Length = 5; 63 | fig0_0->CN = 0; 64 | fig0_0->OE = 0; 65 | fig0_0->PD = 0; 66 | fig0_0->Extension = 0; 67 | 68 | fig0_0->EId = htons(m_rti->ensemble->id); 69 | fig0_0->Change = 0; 70 | fig0_0->Al = m_rti->ensemble->alarm_flag; 71 | fig0_0->CIFcnt_hight = (m_rti->currentFrame / 250) % 20; 72 | fig0_0->CIFcnt_low = (m_rti->currentFrame % 250); 73 | 74 | fs.complete_fig_transmitted = true; 75 | fs.num_bytes_written = 6; 76 | return fs; 77 | } 78 | 79 | } 80 | 81 | -------------------------------------------------------------------------------- /src/fig/FIG0_0.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2016 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | 30 | namespace FIC { 31 | 32 | // FIG type 0/0, Multiplex Configuration Info (MCI), 33 | // Ensemble information 34 | class FIG0_0 : public IFIG 35 | { 36 | public: 37 | FIG0_0(FIGRuntimeInformation* rti) : 38 | m_rti(rti) {} 39 | virtual FillStatus fill(uint8_t *buf, size_t max_size); 40 | virtual FIG_rate repetition_rate() const { return FIG_rate::FIG0_0; } 41 | 42 | virtual int figtype() const { return 0; } 43 | virtual int figextension() const { return 0; } 44 | 45 | private: 46 | FIGRuntimeInformation *m_rti; 47 | }; 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/fig/FIG0_1.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2024 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include "fig/FIG.h" 30 | 31 | namespace FIC { 32 | 33 | // FIG type 0/1, MCI, Sub-Channel Organization, 34 | // one instance of the part for each subchannel 35 | class FIG0_1 : public IFIG 36 | { 37 | public: 38 | FIG0_1(FIGRuntimeInformation* rti); 39 | virtual FillStatus fill(uint8_t *buf, size_t max_size); 40 | virtual FIG_rate repetition_rate() const { return FIG_rate::A; } 41 | 42 | virtual int figtype() const { return 0; } 43 | virtual int figextension() const { return 1; } 44 | 45 | private: 46 | FIGRuntimeInformation *m_rti; 47 | bool m_initialised; 48 | vec_sp_subchannel subchannels; 49 | vec_sp_subchannel::iterator subchannelFIG0_1; 50 | 51 | uint8_t m_watermarkData[128]; 52 | size_t m_watermarkSize; 53 | size_t m_watermarkPos; 54 | }; 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/fig/FIG0_10.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2025 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #include "fig/FIG0_10.h" 27 | #include "utils.h" 28 | 29 | namespace FIC { 30 | 31 | struct FIGtype0_10_LongForm { 32 | uint8_t Length:5; 33 | uint8_t FIGtypeNumber:3; 34 | 35 | uint8_t Extension:5; 36 | uint8_t PD:1; 37 | uint8_t OE:1; 38 | uint8_t CN:1; 39 | 40 | uint8_t MJD_high:7; 41 | uint8_t RFU:1; 42 | 43 | uint8_t MJD_med; 44 | 45 | uint8_t Hours_high:3; 46 | uint8_t UTC:1; 47 | uint8_t ConfInd:1; 48 | uint8_t LSI:1; 49 | uint8_t MJD_low:2; 50 | 51 | uint8_t Minutes:6; 52 | uint8_t Hours_low:2; 53 | 54 | uint8_t Milliseconds_high:2; 55 | uint8_t Seconds:6; 56 | 57 | uint8_t Milliseconds_low; 58 | 59 | void setMJD(uint32_t date) { 60 | MJD_high = (date >> 10) & 0x7f; 61 | MJD_med = (date >> 2) & 0xff; 62 | MJD_low = date & 0x03; 63 | } 64 | void setHours(uint16_t hours) { 65 | Hours_high = (hours >> 2) & 0x07; 66 | Hours_low = hours & 0x03; 67 | } 68 | 69 | void setMilliseconds(uint16_t ms) { 70 | Milliseconds_high = (ms >> 8) & 0x03; 71 | Milliseconds_low = ms & 0xFF; 72 | } 73 | } PACKED; 74 | 75 | FIG0_10::FIG0_10(FIGRuntimeInformation *rti) : 76 | m_rti(rti) 77 | { 78 | } 79 | 80 | FillStatus FIG0_10::fill(uint8_t *buf, size_t max_size) 81 | { 82 | FillStatus fs; 83 | auto ensemble = m_rti->ensemble; 84 | size_t remaining = max_size; 85 | 86 | if (remaining < 8) { 87 | fs.num_bytes_written = 0; 88 | return fs; 89 | } 90 | 91 | // Time and country identifier 92 | auto fig0_10 = (FIGtype0_10_LongForm*)buf; 93 | 94 | fig0_10->FIGtypeNumber = 0; 95 | fig0_10->Length = 7; 96 | fig0_10->CN = 0; 97 | fig0_10->OE = 0; 98 | fig0_10->PD = 0; 99 | fig0_10->Extension = 10; 100 | buf += 2; 101 | remaining -= 2; 102 | 103 | struct tm timeData; 104 | const auto dab_time = m_rti->getTimeFunc(); 105 | time_t dab_time_seconds = dab_time.second; 106 | uint32_t dab_time_millis = dab_time.first; 107 | gmtime_r(&dab_time_seconds, &timeData); 108 | 109 | fig0_10->RFU = 0; 110 | fig0_10->setMJD(gregorian2mjd(timeData.tm_year + 1900, 111 | timeData.tm_mon + 1, 112 | timeData.tm_mday)); 113 | fig0_10->LSI = 0; 114 | fig0_10->ConfInd = 1; 115 | fig0_10->UTC = 1; 116 | fig0_10->setHours(timeData.tm_hour); 117 | fig0_10->Minutes = timeData.tm_min; 118 | fig0_10->Seconds = timeData.tm_sec; 119 | fig0_10->setMilliseconds(dab_time_millis); 120 | buf += 6; 121 | remaining -= 6; 122 | 123 | fs.num_bytes_written = max_size - remaining; 124 | fs.complete_fig_transmitted = true; 125 | return fs; 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /src/fig/FIG0_10.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2016 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include "fig/FIG.h" 30 | 31 | namespace FIC { 32 | 33 | // FIG type 0/10 34 | // The date and time feature is used to signal a location-independent timing 35 | // reference in UTC format. 36 | class FIG0_10 : public IFIG 37 | { 38 | public: 39 | FIG0_10(FIGRuntimeInformation* rti); 40 | virtual FillStatus fill(uint8_t *buf, size_t max_size); 41 | virtual FIG_rate repetition_rate() const { return FIG_rate::B; } 42 | 43 | virtual int figtype() const { return 0; } 44 | virtual int figextension() const { return 10; } 45 | 46 | private: 47 | FIGRuntimeInformation *m_rti; 48 | }; 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/fig/FIG0_13.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2020 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | #include "fig/FIG.h" 31 | 32 | namespace FIC { 33 | 34 | // FIG type 0/13 35 | // User Application Information 36 | class FIG0_13 : public IFIG 37 | { 38 | public: 39 | FIG0_13(FIGRuntimeInformation* rti); 40 | virtual FillStatus fill(uint8_t *buf, size_t max_size); 41 | virtual FIG_rate repetition_rate() const { return FIG_rate::B; } 42 | 43 | virtual int figtype() const { return 0; } 44 | virtual int figextension() const { return 13; } 45 | 46 | private: 47 | FIGRuntimeInformation *m_rti; 48 | bool m_initialised; 49 | bool m_transmit_programme; 50 | vec_sp_component::iterator componentFIG0_13; 51 | }; 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/fig/FIG0_14.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2020 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | 9 | Copyright (C) 2022 10 | Nick Piggott, nick@piggott.eu 11 | */ 12 | /* 13 | This file is part of ODR-DabMux. 14 | 15 | ODR-DabMux is free software: you can redistribute it and/or modify 16 | it under the terms of the GNU General Public License as 17 | published by the Free Software Foundation, either version 3 of the 18 | License, or (at your option) any later version. 19 | 20 | ODR-DabMux is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | GNU General Public License for more details. 24 | 25 | You should have received a copy of the GNU General Public License 26 | along with ODR-DabMux. If not, see . 27 | */ 28 | 29 | #pragma once 30 | 31 | #include 32 | #include 33 | 34 | namespace FIC { 35 | 36 | // FIG type 0/14 37 | // FEC sub-channel organization 38 | class FIG0_14 : public IFIG 39 | { 40 | public: 41 | FIG0_14(FIGRuntimeInformation* rti); 42 | virtual FillStatus fill(uint8_t *buf, size_t max_size); 43 | virtual FIG_rate repetition_rate() const { return FIG_rate::B; } 44 | 45 | virtual int figtype() const { return 0; } 46 | virtual int figextension() const { return 14; } 47 | 48 | private: 49 | FIGRuntimeInformation *m_rti; 50 | bool m_initialised; 51 | vec_sp_component::iterator componentFIG0_14; 52 | }; 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/fig/FIG0_17.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2016 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #include "fig/FIG0structs.h" 27 | #include "fig/FIG0_17.h" 28 | #include "utils.h" 29 | 30 | namespace FIC { 31 | 32 | struct FIGtype0_17 { 33 | uint16_t SId; 34 | 35 | uint8_t rfa2_high:4; 36 | uint8_t rfu1:2; 37 | uint8_t rfa1:1; 38 | uint8_t SD:1; // Static/Dynamic 39 | 40 | uint8_t IntCode:5; 41 | uint8_t rfu2:1; 42 | uint8_t rfa2_low:2; 43 | } PACKED; 44 | 45 | FIG0_17::FIG0_17(FIGRuntimeInformation *rti) : 46 | m_rti(rti), 47 | m_initialised(false) 48 | { 49 | } 50 | 51 | FillStatus FIG0_17::fill(uint8_t *buf, size_t max_size) 52 | { 53 | FillStatus fs; 54 | ssize_t remaining = max_size; 55 | 56 | if (not m_initialised) { 57 | serviceFIG0_17 = m_rti->ensemble->services.end(); 58 | m_initialised = true; 59 | } 60 | 61 | auto ensemble = m_rti->ensemble; 62 | 63 | FIGtype0* fig0 = NULL; 64 | 65 | for (; serviceFIG0_17 != ensemble->services.end(); 66 | ++serviceFIG0_17) { 67 | 68 | if ((*serviceFIG0_17)->pty_settings.pty == 0) { 69 | continue; 70 | } 71 | 72 | const int required_size = 4; 73 | 74 | 75 | if (fig0 == NULL) { 76 | if (remaining < 2 + required_size) { 77 | break; 78 | } 79 | fig0 = (FIGtype0*)buf; 80 | fig0->FIGtypeNumber = 0; 81 | fig0->Length = 1; 82 | fig0->CN = 0; 83 | fig0->OE = 0; 84 | fig0->PD = 0; 85 | fig0->Extension = 17; 86 | buf += 2; 87 | remaining -= 2; 88 | } 89 | else if (remaining < required_size) { 90 | break; 91 | } 92 | 93 | auto fig0_17 = (FIGtype0_17*)buf; 94 | fig0_17->SId = htons((*serviceFIG0_17)->id); 95 | fig0_17->SD = ((*serviceFIG0_17)->pty_settings.dynamic_no_static ? 1 : 0); 96 | fig0_17->rfa1 = 0; 97 | fig0_17->rfu1 = 0; 98 | fig0_17->rfa2_low = 0; 99 | fig0_17->rfa2_high = 0; 100 | fig0_17->rfu2 = 0; 101 | fig0_17->IntCode = (*serviceFIG0_17)->pty_settings.pty; 102 | 103 | fig0->Length += 4; 104 | buf += 4; 105 | remaining -= 4; 106 | } 107 | 108 | if (serviceFIG0_17 == ensemble->services.end()) { 109 | serviceFIG0_17 = ensemble->services.begin(); 110 | fs.complete_fig_transmitted = true; 111 | } 112 | 113 | fs.num_bytes_written = max_size - remaining; 114 | return fs; 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /src/fig/FIG0_17.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2016 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include "fig/FIG.h" 30 | 31 | namespace FIC { 32 | 33 | // FIG type 0/17 34 | // Programme Type (PTy) 35 | class FIG0_17 : public IFIG 36 | { 37 | public: 38 | FIG0_17(FIGRuntimeInformation* rti); 39 | virtual FillStatus fill(uint8_t *buf, size_t max_size); 40 | virtual FIG_rate repetition_rate() const { return FIG_rate::B; } 41 | 42 | virtual int figtype() const { return 0; } 43 | virtual int figextension() const { return 17; } 44 | 45 | private: 46 | FIGRuntimeInformation *m_rti; 47 | bool m_initialised; 48 | vec_sp_service::iterator serviceFIG0_17; 49 | }; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/fig/FIG0_18.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2016 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #include "fig/FIG0structs.h" 27 | #include "fig/FIG0_18.h" 28 | #include "utils.h" 29 | 30 | namespace FIC { 31 | 32 | struct FIGtype0_18 { 33 | uint16_t SId; 34 | uint16_t ASu; 35 | uint8_t NumClusters:5; 36 | uint8_t Rfa:3; 37 | /* Followed by uint8_t Cluster IDs */ 38 | } PACKED; 39 | 40 | FIG0_18::FIG0_18(FIGRuntimeInformation *rti) : 41 | m_rti(rti), 42 | m_initialised(false) 43 | { 44 | } 45 | 46 | FillStatus FIG0_18::fill(uint8_t *buf, size_t max_size) 47 | { 48 | FillStatus fs; 49 | ssize_t remaining = max_size; 50 | 51 | if (not m_initialised) { 52 | service = m_rti->ensemble->services.end(); 53 | m_initialised = true; 54 | } 55 | 56 | auto ensemble = m_rti->ensemble; 57 | 58 | FIGtype0* fig0 = NULL; 59 | 60 | for (; service != ensemble->services.end(); 61 | ++service) { 62 | 63 | if ( (*service)->ASu == 0 ) { 64 | continue; 65 | } 66 | 67 | const ssize_t numclusters = (*service)->clusters.size(); 68 | 69 | const int required_size = 5 + numclusters; 70 | 71 | 72 | if (fig0 == NULL) { 73 | if (remaining < 2 + required_size) { 74 | break; 75 | } 76 | 77 | fig0 = (FIGtype0*)buf; 78 | fig0->FIGtypeNumber = 0; 79 | fig0->Length = 1; 80 | fig0->CN = 0; 81 | fig0->OE = 0; 82 | fig0->PD = 0; 83 | fig0->Extension = 18; 84 | buf += 2; 85 | remaining -= 2; 86 | } 87 | else if (remaining < required_size) { 88 | break; 89 | } 90 | 91 | auto programme = (FIGtype0_18*)buf; 92 | programme->SId = htons((*service)->id); 93 | programme->ASu = htons((*service)->ASu); 94 | programme->Rfa = 0; 95 | programme->NumClusters = numclusters; 96 | buf += 5; 97 | 98 | for (uint8_t cluster : (*service)->clusters) { 99 | *(buf++) = cluster; 100 | } 101 | 102 | fig0->Length += 5 + numclusters; 103 | remaining -= 5 + numclusters; 104 | } 105 | 106 | if (service == ensemble->services.end()) { 107 | service = ensemble->services.begin(); 108 | fs.complete_fig_transmitted = true; 109 | } 110 | 111 | fs.num_bytes_written = max_size - remaining; 112 | return fs; 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/fig/FIG0_18.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2016 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | 31 | namespace FIC { 32 | 33 | // FIG type 0/18 34 | class FIG0_18 : public IFIG 35 | { 36 | public: 37 | FIG0_18(FIGRuntimeInformation* rti); 38 | virtual FillStatus fill(uint8_t *buf, size_t max_size); 39 | virtual FIG_rate repetition_rate() const { return FIG_rate::B; } 40 | 41 | virtual int figtype() const { return 0; } 42 | virtual int figextension() const { return 18; } 43 | 44 | private: 45 | FIGRuntimeInformation *m_rti; 46 | bool m_initialised; 47 | vec_sp_service::iterator service; 48 | }; 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/fig/FIG0_19.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2016 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | #include "fig/TransitionHandler.h" 31 | 32 | namespace FIC { 33 | 34 | // FIG type 0/19 35 | class FIG0_19 : public IFIG 36 | { 37 | public: 38 | FIG0_19(FIGRuntimeInformation* rti); 39 | virtual FillStatus fill(uint8_t *buf, size_t max_size); 40 | virtual FIG_rate repetition_rate() const; 41 | 42 | virtual int figtype() const { return 0; } 43 | virtual int figextension() const { return 19; } 44 | 45 | private: 46 | FIGRuntimeInformation *m_rti; 47 | 48 | TransitionHandler m_transition; 49 | }; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/fig/FIG0_2.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2016 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | #include "fig/FIG.h" 31 | 32 | namespace FIC { 33 | // FIG type 0/2, MCI, Service Organization, one instance of 34 | // FIGtype0_2_Service for each subchannel 35 | class FIG0_2 : public IFIG 36 | { 37 | public: 38 | FIG0_2(FIGRuntimeInformation* rti); 39 | virtual FillStatus fill(uint8_t *buf, size_t max_size); 40 | virtual FIG_rate repetition_rate() const { return FIG_rate::A; } 41 | 42 | virtual int figtype() const { return 0; } 43 | virtual int figextension() const { return 2; } 44 | 45 | private: 46 | FIGRuntimeInformation *m_rti; 47 | bool m_initialised; 48 | bool m_inserting_audio_not_data; 49 | vec_sp_service m_audio_services; 50 | vec_sp_service m_data_services; 51 | vec_sp_service::iterator serviceFIG0_2; 52 | }; 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/fig/FIG0_21.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2018 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | namespace FIC { 33 | 34 | // FIG type 0/21 35 | // Frequency Information 36 | class FIG0_21 : public IFIG 37 | { 38 | public: 39 | FIG0_21(FIGRuntimeInformation* rti); 40 | virtual FillStatus fill(uint8_t *buf, size_t max_size); 41 | virtual FIG_rate repetition_rate() const { return FIG_rate::E; } 42 | 43 | virtual int figtype() const { return 0; } 44 | virtual int figextension() const { return 21; } 45 | 46 | private: 47 | FIGRuntimeInformation *m_rti; 48 | 49 | bool m_initialised = false; 50 | bool m_last_oe = false; 51 | 52 | std::vector::iterator freqInfoFIG0_21; 53 | size_t fi_frequency_index = 0; 54 | }; 55 | 56 | } 57 | 58 | -------------------------------------------------------------------------------- /src/fig/FIG0_24.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2018 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | #include "FIG.h" 31 | 32 | namespace FIC { 33 | /* The OE Services feature is used to identify the services currently carried 34 | * in other DAB ensembles. 35 | */ 36 | class FIG0_24 : public IFIG 37 | { 38 | public: 39 | FIG0_24(FIGRuntimeInformation* rti); 40 | virtual FillStatus fill(uint8_t *buf, size_t max_size); 41 | virtual FIG_rate repetition_rate() const { return FIG_rate::E; } 42 | 43 | virtual int figtype() const { return 0; } 44 | virtual int figextension() const { return 24; } 45 | 46 | private: 47 | FIGRuntimeInformation *m_rti; 48 | bool m_initialised; 49 | bool m_inserting_audio_not_data; 50 | std::vector::iterator serviceFIG0_24; 51 | }; 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/fig/FIG0_3.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2016 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | 31 | namespace FIC { 32 | 33 | // FIG type 0/3 34 | // The Extension 3 of FIG type 0 (FIG 0/3) gives additional information about 35 | // the service component description in packet mode. 36 | class FIG0_3 : public IFIG 37 | { 38 | public: 39 | FIG0_3(FIGRuntimeInformation* rti); 40 | virtual FillStatus fill(uint8_t *buf, size_t max_size); 41 | virtual FIG_rate repetition_rate() const { return FIG_rate::A; } 42 | 43 | virtual int figtype() const { return 0; } 44 | virtual int figextension() const { return 3; } 45 | 46 | private: 47 | FIGRuntimeInformation *m_rti; 48 | bool m_initialised; 49 | vec_sp_component::iterator componentFIG0_3; 50 | }; 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/fig/FIG0_5.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2016 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #include "fig/FIG0structs.h" 27 | #include "fig/FIG0_5.h" 28 | #include "utils.h" 29 | 30 | namespace FIC { 31 | 32 | struct FIGtype0_5_short { 33 | uint8_t SubChId:6; 34 | uint8_t rfu:1; 35 | uint8_t LS:1; 36 | 37 | uint8_t language; 38 | } PACKED; 39 | 40 | FIG0_5::FIG0_5(FIGRuntimeInformation *rti) : 41 | m_rti(rti), 42 | m_initialised(false) 43 | { 44 | } 45 | 46 | FillStatus FIG0_5::fill(uint8_t *buf, size_t max_size) 47 | { 48 | FillStatus fs; 49 | ssize_t remaining = max_size; 50 | auto ensemble = m_rti->ensemble; 51 | 52 | if (not m_initialised) { 53 | componentFIG0_5 = m_rti->ensemble->components.end(); 54 | m_initialised = true; 55 | } 56 | 57 | FIGtype0* fig0 = NULL; 58 | 59 | for (; componentFIG0_5 != ensemble->components.end(); 60 | ++componentFIG0_5) { 61 | 62 | auto service = getService(*componentFIG0_5, 63 | ensemble->services); 64 | auto subchannel = getSubchannel(ensemble->subchannels, 65 | (*componentFIG0_5)->subchId); 66 | 67 | if (subchannel == ensemble->subchannels.end()) { 68 | etiLog.log(error, 69 | "FIG0/5: Subchannel %i does not exist " 70 | "for component of service %i", 71 | (*componentFIG0_5)->subchId, 72 | (*componentFIG0_5)->serviceId); 73 | continue; 74 | } 75 | 76 | if ( (*service)->language == 0) { 77 | continue; 78 | } 79 | 80 | const int required_size = 2; 81 | 82 | if (fig0 == NULL) { 83 | if (remaining < 2 + required_size) { 84 | break; 85 | } 86 | fig0 = (FIGtype0*)buf; 87 | fig0->FIGtypeNumber = 0; 88 | fig0->Length = 1; 89 | fig0->CN = 0; 90 | fig0->OE = 0; 91 | fig0->PD = 0; 92 | fig0->Extension = 5; 93 | 94 | buf += 2; 95 | remaining -= 2; 96 | } 97 | else if (remaining < required_size) { 98 | break; 99 | } 100 | 101 | FIGtype0_5_short *fig0_5 = (FIGtype0_5_short*)buf; 102 | 103 | fig0_5->LS = 0; 104 | fig0_5->rfu = 0; 105 | fig0_5->SubChId = (*subchannel)->id; 106 | fig0_5->language = (*service)->language; 107 | 108 | fig0->Length += 2; 109 | buf += 2; 110 | remaining -= 2; 111 | } 112 | 113 | if (componentFIG0_5 == ensemble->components.end()) { 114 | componentFIG0_5 = ensemble->components.begin(); 115 | fs.complete_fig_transmitted = true; 116 | } 117 | 118 | fs.num_bytes_written = max_size - remaining; 119 | return fs; 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/fig/FIG0_5.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2016 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | 31 | namespace FIC { 32 | 33 | // FIG type 0/5 34 | // The service component language feature is used to signal a language 35 | // associated with a service component; the spoken language of an audio 36 | // component or the language of the content of a data component. This 37 | // information can be used for user selection or display. The feature is 38 | // encoded in Extension 5 of FIG type 0 (FIG 0/5). 39 | class FIG0_5 : public IFIG 40 | { 41 | public: 42 | FIG0_5(FIGRuntimeInformation* rti); 43 | virtual FillStatus fill(uint8_t *buf, size_t max_size); 44 | virtual FIG_rate repetition_rate() const { return FIG_rate::B; } 45 | 46 | virtual int figtype() const { return 0; } 47 | virtual int figextension() const { return 5; } 48 | 49 | private: 50 | FIGRuntimeInformation *m_rti; 51 | bool m_initialised; 52 | vec_sp_component::iterator componentFIG0_5; 53 | }; 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/fig/FIG0_6.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2016 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | namespace FIC { 33 | 34 | /* TODO 35 | * This FIG code is unable to transmit the CEI to announce 36 | * activation/deactivation of linkage sets. 37 | * The TransitionHandler.h would be useful for that purpose 38 | */ 39 | 40 | // FIG type 0/6 41 | // Service Linking 42 | // 43 | // This feature shall use the SIV signalling (see clause 5.2.2.1). The database 44 | // shall be divided by use of a database key. Changes to the database shall be 45 | // signalled using the CEI. The first service in the list of services in each 46 | // part of the database, as divided by the database key, shall be a service 47 | // carried in the ensemble. This service is called the key service. 48 | // 49 | // The database key comprises the OE and P/D flags and the S/H, ILS, and LSN 50 | // fields. 51 | class FIG0_6 : public IFIG 52 | { 53 | public: 54 | FIG0_6(FIGRuntimeInformation* rti); 55 | virtual FillStatus fill(uint8_t *buf, size_t max_size); 56 | virtual FIG_rate repetition_rate() const { return FIG_rate::E; } 57 | 58 | virtual int figtype() const { return 0; } 59 | virtual int figextension() const { return 6; } 60 | 61 | private: 62 | FIGRuntimeInformation *m_rti; 63 | bool m_initialised; 64 | 65 | /* Update the linkageSubsets */ 66 | void update(); 67 | 68 | /* A LinkageSet can contain links of different types 69 | * (DAB, FM, DRM, AMSS), but the FIG needs to send 70 | * different FIGs for each of those, because the IdLQ flag 71 | * is common to a list. 72 | * 73 | * We reorganise all LinkageSets into subsets that have 74 | * the same type. 75 | */ 76 | std::vector linkageSubsets; 77 | std::vector::iterator linkageSetFIG0_6; 78 | }; 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/fig/FIG0_7.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2020 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | Mathias Kuntze, mathias@kuntze.email 9 | */ 10 | /* 11 | This file is part of ODR-DabMux. 12 | 13 | ODR-DabMux is free software: you can redistribute it and/or modify 14 | it under the terms of the GNU General Public License as 15 | published by the Free Software Foundation, either version 3 of the 16 | License, or (at your option) any later version. 17 | 18 | ODR-DabMux is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with ODR-DabMux. If not, see . 25 | */ 26 | 27 | #include "fig/FIG0structs.h" 28 | #include "fig/FIG0_7.h" 29 | #include "utils.h" 30 | 31 | namespace FIC { 32 | 33 | struct FIGtype0_7 { 34 | uint8_t Length:5; 35 | uint8_t FIGtypeNumber:3; 36 | uint8_t Extension:5; 37 | uint8_t PD:1; 38 | uint8_t OE:1; 39 | uint8_t CN:1; 40 | 41 | uint8_t ReconfigCounter_high:2; 42 | uint8_t ServiceCount:6; 43 | uint8_t ReconfigCounter_low:8; 44 | } PACKED; 45 | 46 | //=========== FIG 0/7 =========== 47 | 48 | FillStatus FIG0_7::fill(uint8_t *buf, size_t max_size) 49 | { 50 | FillStatus fs; 51 | 52 | if (max_size < 4) { 53 | fs.complete_fig_transmitted = false; 54 | fs.num_bytes_written = 0; 55 | return fs; 56 | } 57 | 58 | auto ensemble = m_rti->ensemble; 59 | 60 | if (ensemble->reconfig_counter < 0) { 61 | // FIG 0/7 is disabled 62 | fs.complete_fig_transmitted = true; 63 | fs.num_bytes_written = 0; 64 | return fs; 65 | } 66 | 67 | FIGtype0_7 *fig0_7; 68 | fig0_7 = (FIGtype0_7 *)buf; 69 | 70 | fig0_7->FIGtypeNumber = 0; 71 | fig0_7->Length = 3; 72 | fig0_7->CN = 0; 73 | fig0_7->OE = 0; 74 | fig0_7->PD = 0; 75 | fig0_7->Extension = 7; 76 | 77 | fig0_7->ServiceCount = ensemble->services.size(); 78 | fig0_7->ReconfigCounter_high = (ensemble->reconfig_counter % 1024) / 256; 79 | fig0_7->ReconfigCounter_low = (ensemble->reconfig_counter % 1024) % 256; 80 | 81 | fs.complete_fig_transmitted = true; 82 | fs.num_bytes_written = 4; 83 | return fs; 84 | } 85 | 86 | } 87 | 88 | -------------------------------------------------------------------------------- /src/fig/FIG0_7.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2020 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | Mathias Kuntze, mathias@kuntze.email 9 | */ 10 | /* 11 | This file is part of ODR-DabMux. 12 | 13 | ODR-DabMux is free software: you can redistribute it and/or modify 14 | it under the terms of the GNU General Public License as 15 | published by the Free Software Foundation, either version 3 of the 16 | License, or (at your option) any later version. 17 | 18 | ODR-DabMux is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with ODR-DabMux. If not, see . 25 | */ 26 | 27 | #pragma once 28 | 29 | #include 30 | #include 31 | 32 | namespace FIC { 33 | 34 | // FIG type 0/7, Configuration Info (MCI), 35 | // Service Number information 36 | class FIG0_7 : public IFIG 37 | { 38 | public: 39 | FIG0_7(FIGRuntimeInformation* rti) : 40 | m_rti(rti) {} 41 | virtual FillStatus fill(uint8_t *buf, size_t max_size); 42 | virtual FIG_rate repetition_rate() const { return FIG_rate::FIG0_0; } 43 | 44 | virtual int figtype() const { return 0; } 45 | virtual int figextension() const { return 7; } 46 | 47 | private: 48 | FIGRuntimeInformation *m_rti; 49 | }; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/fig/FIG0_8.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2016 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | #include "fig/FIG.h" 31 | 32 | namespace FIC { 33 | 34 | // FIG type 0/8 35 | // The Extension 8 of FIG type 0 (FIG 0/8) provides information to link 36 | // together the service component description that is valid within the ensemble 37 | // to a service component description that is valid in other ensembles 38 | class FIG0_8 : public IFIG 39 | { 40 | public: 41 | FIG0_8(FIGRuntimeInformation* rti); 42 | virtual FillStatus fill(uint8_t *buf, size_t max_size); 43 | virtual FIG_rate repetition_rate() const { return FIG_rate::B; } 44 | 45 | virtual int figtype() const { return 0; } 46 | virtual int figextension() const { return 8; } 47 | 48 | private: 49 | FIGRuntimeInformation *m_rti; 50 | bool m_initialised; 51 | bool m_transmit_programme; 52 | vec_sp_component::iterator componentFIG0_8; 53 | }; 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/fig/FIG0_9.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2021 Matthias P. Braendli 7 | http://www.opendigitalradio.org 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | #include "fig/FIG.h" 31 | 32 | namespace FIC { 33 | 34 | // FIG type 0/9 35 | // The Country, LTO and International table feature defines the local time 36 | // offset, the International Table and the Extended Country Code (ECC) for 37 | // the ensemble. Also, the ECC for services with differing ECC. 38 | class FIG0_9 : public IFIG 39 | { 40 | public: 41 | FIG0_9(FIGRuntimeInformation* rti); 42 | virtual FillStatus fill(uint8_t *buf, size_t max_size); 43 | virtual FIG_rate repetition_rate() const { return FIG_rate::B; } 44 | 45 | virtual int figtype() const { return 0; } 46 | virtual int figextension() const { return 9; } 47 | 48 | private: 49 | FIGRuntimeInformation *m_rti; 50 | 51 | struct FIG0_9_Extended_Field { 52 | uint8_t ecc; 53 | std::list sids; 54 | 55 | size_t required_bytes() const { 56 | return 2 + 2 * sids.size(); 57 | } 58 | }; 59 | std::list m_extended_fields; 60 | 61 | }; 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/fig/FIG0structs.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2020 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #pragma once 27 | #include 28 | #include "fig/FIG.h" 29 | 30 | constexpr uint16_t FIG0_13_APPTYPE_SLIDESHOW = 0x2; 31 | constexpr uint16_t FIG0_13_APPTYPE_WEBSITE = 0x3; 32 | constexpr uint16_t FIG0_13_APPTYPE_TPEG = 0x4; 33 | constexpr uint16_t FIG0_13_APPTYPE_DGPS = 0x5; 34 | constexpr uint16_t FIG0_13_APPTYPE_TMC = 0x6; 35 | constexpr uint16_t FIG0_13_APPTYPE_SPI = 0x7; 36 | constexpr uint16_t FIG0_13_APPTYPE_DABJAVA = 0x8; 37 | constexpr uint16_t FIG0_13_APPTYPE_JOURNALINE = 0x44a; 38 | 39 | 40 | struct FIGtype0 { 41 | uint8_t Length:5; 42 | uint8_t FIGtypeNumber:3; 43 | uint8_t Extension:5; 44 | uint8_t PD:1; 45 | uint8_t OE:1; 46 | uint8_t CN:1; 47 | } PACKED; 48 | 49 | -------------------------------------------------------------------------------- /src/input/File.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications 3 | Research Center Canada) 4 | 5 | Copyright (C) 2022 Matthias P. Braendli 6 | http://www.opendigitalradio.org 7 | 8 | */ 9 | /* 10 | This file is part of ODR-DabMux. 11 | 12 | ODR-DabMux is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as 14 | published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | ODR-DabMux is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with ODR-DabMux. If not, see . 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include "input/inputs.h" 33 | #include "ManagementServer.h" 34 | 35 | namespace Inputs { 36 | 37 | class FileBase : public InputBase { 38 | public: 39 | virtual void open(const std::string& name); 40 | virtual size_t readFrame(uint8_t *buffer, size_t size) = 0; 41 | virtual size_t readFrame(uint8_t *buffer, size_t size, std::time_t seconds, int utco, uint32_t tsta); 42 | virtual int setBitrate(int bitrate); 43 | virtual void close(); 44 | 45 | virtual void setNonblocking(bool nonblock); 46 | virtual void setLoadEntireFile(bool load_entire_file); 47 | 48 | protected: 49 | /* Rewind the file 50 | * Returns -1 on failure, 0 on success 51 | */ 52 | virtual ssize_t rewind(); 53 | /* Read len bytes from the file into buf, and return 54 | * the number of bytes read, or -1 in case of error. 55 | */ 56 | virtual ssize_t readFromFile(uint8_t* buf, size_t len); 57 | 58 | virtual ssize_t load_entire_file(); 59 | 60 | // We use unix open() instead of fopen() because 61 | // of non-blocking I/O 62 | int m_fd = -1; 63 | 64 | std::string m_filename; 65 | bool m_nonblock = false; 66 | bool m_load_entire_file = false; 67 | std::vector m_nonblock_buffer; 68 | 69 | size_t m_file_contents_offset = 0; 70 | std::vector m_file_contents; 71 | bool m_file_open_alert_shown = false; 72 | }; 73 | 74 | class MPEGFile : public FileBase { 75 | public: 76 | virtual size_t readFrame(uint8_t *buffer, size_t size); 77 | virtual int setBitrate(int bitrate); 78 | 79 | private: 80 | bool m_parity = false; 81 | }; 82 | 83 | class RawFile : public FileBase { 84 | public: 85 | virtual size_t readFrame(uint8_t *buffer, size_t size); 86 | }; 87 | 88 | class PacketFile : public FileBase { 89 | public: 90 | PacketFile(bool enhancedPacketMode); 91 | virtual size_t readFrame(uint8_t *buffer, size_t size); 92 | 93 | protected: 94 | std::array m_packetData; 95 | size_t m_packetLength = 0; 96 | 97 | /* Enhanced packet mode enables FEC for MSC packet mode 98 | * as described in EN 300 401 Clause 5.3.5 99 | */ 100 | bool m_enhancedPacketEnabled = false; 101 | std::array,12> m_enhancedPacketData; 102 | size_t m_enhancedPacketWaiting = 0; 103 | size_t m_enhancedPacketLength = 0; 104 | }; 105 | 106 | }; 107 | -------------------------------------------------------------------------------- /src/input/Prbs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications 3 | Research Center Canada) 4 | 5 | Copyright (C) 2016 6 | Matthias P. Braendli, matthias.braendli@mpb.li 7 | 8 | http://www.opendigitalradio.org 9 | 10 | Pseudo-Random Bit Sequence generator for test purposes. 11 | */ 12 | /* 13 | This file is part of ODR-DabMux. 14 | 15 | ODR-DabMux is free software: you can redistribute it and/or modify 16 | it under the terms of the GNU General Public License as 17 | published by the Free Software Foundation, either version 3 of the 18 | License, or (at your option) any later version. 19 | 20 | ODR-DabMux is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | GNU General Public License for more details. 24 | 25 | You should have received a copy of the GNU General Public License 26 | along with ODR-DabMux. If not, see . 27 | */ 28 | 29 | #include "input/Prbs.h" 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include "utils.h" 38 | 39 | using namespace std; 40 | 41 | namespace Inputs { 42 | 43 | // ETS 300 799 Clause G.2.1 44 | // Preferred polynomial is G(x) = x^20 + x^17 + 1 45 | const uint32_t PRBS_DEFAULT_POLY = (1 << 20) | (1 << 17) | (1 << 0); 46 | 47 | void Prbs::open(const string& name) 48 | { 49 | if (name.substr(0, 7) != "prbs://") { 50 | throw logic_error("Invalid PRBS name"); 51 | } 52 | 53 | const string& url_polynomial = name.substr(7); 54 | 55 | if (url_polynomial.empty()) { 56 | m_prbs.setup(PRBS_DEFAULT_POLY); 57 | } 58 | else { 59 | if (url_polynomial[0] != ':') { 60 | throw invalid_argument( 61 | "Invalid PRBS address format. " 62 | "Must be prbs://:polynomial."); 63 | } 64 | 65 | const string poly_str = url_polynomial.substr(1); 66 | 67 | long polynomial = hexparse(poly_str); 68 | 69 | if (polynomial == 0) { 70 | throw invalid_argument("No polynomial given for PRBS input"); 71 | } 72 | 73 | m_prbs.setup(polynomial); 74 | } 75 | rewind(); 76 | } 77 | 78 | size_t Prbs::readFrame(uint8_t *buffer, size_t size) 79 | { 80 | for (size_t i = 0; i < size; ++i) { 81 | buffer[i] = m_prbs.step(); 82 | } 83 | 84 | return size; 85 | } 86 | 87 | size_t Prbs::readFrame(uint8_t *buffer, size_t size, std::time_t seconds, int utco, uint32_t tsta) 88 | { 89 | memset(buffer, 0, size); 90 | return 0; 91 | } 92 | 93 | int Prbs::setBitrate(int bitrate) 94 | { 95 | if (bitrate <= 0) { 96 | throw invalid_argument("Invalid bitrate " + to_string(bitrate)); 97 | } 98 | return bitrate; 99 | } 100 | 101 | void Prbs::close() 102 | { 103 | } 104 | 105 | int Prbs::rewind() 106 | { 107 | m_prbs.rewind(); 108 | return 0; 109 | } 110 | 111 | }; 112 | -------------------------------------------------------------------------------- /src/input/Prbs.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications 3 | Research Center Canada) 4 | 5 | Copyright (C) 2016 6 | Matthias P. Braendli, matthias.braendli@mpb.li 7 | 8 | http://www.opendigitalradio.org 9 | 10 | Pseudo-Random Bit Sequence generator for test purposes. 11 | */ 12 | /* 13 | This file is part of ODR-DabMux. 14 | 15 | ODR-DabMux is free software: you can redistribute it and/or modify 16 | it under the terms of the GNU General Public License as 17 | published by the Free Software Foundation, either version 3 of the 18 | License, or (at your option) any later version. 19 | 20 | ODR-DabMux is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | GNU General Public License for more details. 24 | 25 | You should have received a copy of the GNU General Public License 26 | along with ODR-DabMux. If not, see . 27 | */ 28 | 29 | #pragma once 30 | 31 | #include 32 | 33 | #include "input/inputs.h" 34 | #include "PrbsGenerator.h" 35 | 36 | namespace Inputs { 37 | 38 | class Prbs : public InputBase { 39 | public: 40 | virtual void open(const std::string& name); 41 | virtual size_t readFrame(uint8_t *buffer, size_t size); 42 | virtual size_t readFrame(uint8_t *buffer, size_t size, std::time_t seconds, int utco, uint32_t tsta); 43 | virtual int setBitrate(int bitrate); 44 | virtual void close(); 45 | 46 | private: 47 | virtual int rewind(); 48 | 49 | PrbsGenerator m_prbs; 50 | }; 51 | 52 | }; 53 | 54 | -------------------------------------------------------------------------------- /src/input/Udp.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications 3 | Research Center Canada) 4 | 5 | Copyright (C) 2017 6 | Matthias P. Braendli, matthias.braendli@mpb.li 7 | 8 | http://www.opendigitalradio.org 9 | */ 10 | /* 11 | This file is part of ODR-DabMux. 12 | 13 | ODR-DabMux is free software: you can redistribute it and/or modify 14 | it under the terms of the GNU General Public License as 15 | published by the Free Software Foundation, either version 3 of the 16 | License, or (at your option) any later version. 17 | 18 | ODR-DabMux is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with ODR-DabMux. If not, see . 25 | */ 26 | 27 | #pragma once 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "input/inputs.h" 34 | #include "Socket.h" 35 | 36 | namespace Inputs { 37 | 38 | /* A Udp input that takes incoming datagrams, concatenates them 39 | * together and gives them back. 40 | */ 41 | class Udp : public InputBase { 42 | public: 43 | virtual void open(const std::string& name); 44 | virtual size_t readFrame(uint8_t *buffer, size_t size); 45 | virtual size_t readFrame(uint8_t *buffer, size_t size, std::time_t seconds, int utco, uint32_t tsta); 46 | virtual int setBitrate(int bitrate); 47 | virtual void close(); 48 | 49 | protected: 50 | Socket::UDPSocket m_sock; 51 | std::string m_name; 52 | 53 | void openUdpSocket(const std::string& endpoint); 54 | 55 | private: 56 | // The content of the UDP packets gets written into the 57 | // buffer, and the UDP packet boundaries disappear there. 58 | std::vector m_buffer; 59 | }; 60 | 61 | /* An input for STI-D(LI) carried in STI(PI, X) inside RTP inside UDP. 62 | * Reorders incoming datagrams which must contain an RTP header and valid 63 | * STI-D data. 64 | * 65 | * This is intended to be compatible with encoders from AVT. 66 | */ 67 | class Sti_d_Rtp : public Udp { 68 | using vec_u8 = std::vector; 69 | 70 | public: 71 | virtual void open(const std::string& name); 72 | virtual size_t readFrame(uint8_t *buffer, size_t size); 73 | 74 | private: 75 | void receive_packet(void); 76 | std::deque m_queue; 77 | }; 78 | 79 | }; 80 | 81 | -------------------------------------------------------------------------------- /src/input/inputs.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in 3 | Right of Canada (Communications Research Center Canada) 4 | 5 | Copyright (C) 2019 6 | Matthias P. Braendli, matthias.braendli@mpb.li 7 | 8 | http://www.opendigitalradio.org 9 | */ 10 | /* 11 | This file is part of ODR-DabMux. 12 | 13 | ODR-DabMux is free software: you can redistribute it and/or modify 14 | it under the terms of the GNU General Public License as 15 | published by the Free Software Foundation, either version 3 of the 16 | License, or (at your option) any later version. 17 | 18 | ODR-DabMux is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with ODR-DabMux. If not, see . 25 | */ 26 | 27 | #pragma once 28 | 29 | #ifdef HAVE_CONFIG_H 30 | # include "config.h" 31 | #endif 32 | #include "Log.h" 33 | #include "RemoteControl.h" 34 | #include 35 | 36 | namespace Inputs { 37 | 38 | enum class BufferManagement { 39 | // Use a buffer in the input that doesn't consider timestamps 40 | Prebuffering, 41 | 42 | // Buffer incoming data until a given timestamp is reached 43 | Timestamped, 44 | }; 45 | 46 | 47 | /* New input object base */ 48 | class InputBase { 49 | public: 50 | /* Throws runtime_error or invalid_argument on failure */ 51 | virtual void open(const std::string& name) = 0; 52 | 53 | /* read a frame from the input. Buffer management is either not necessary 54 | * (e.g. File input) or done with pre-buffering (network-based inputs). 55 | * 56 | * This ignores timestamps. All inputs support this. 57 | * 58 | * Returns number of data bytes written to the buffer. May clear the buffer 59 | * if no data bytes available, in which case it will return 0. 60 | * 61 | * Returns negative on error. 62 | */ 63 | virtual size_t readFrame(uint8_t *buffer, size_t size) = 0; 64 | 65 | /* read a frame from the input, taking into account timestamp. The timestamp of the data 66 | * returned is not more recent than the timestamp specified in seconds and tsta. 67 | * 68 | * seconds is in UNIX epoch, utco is the TAI-UTC offset, tsta is in the format used by ETI. 69 | * 70 | * Returns number of data bytes written to the buffer. May clear the buffer 71 | * if no data bytes available, in which case it will return 0. 72 | * 73 | * Returns negative on error. 74 | * 75 | * Calling this function on inputs that do not support timestamps returns 0. This allows 76 | * changing the buffer management at runtime without risking an crash due to an exception. 77 | */ 78 | virtual size_t readFrame(uint8_t *buffer, size_t size, std::time_t seconds, int utco, uint32_t tsta) = 0; 79 | 80 | /* Returns the effectively used bitrate, or throws invalid_argument on invalid bitrate */ 81 | virtual int setBitrate(int bitrate) = 0; 82 | virtual void close() = 0; 83 | 84 | virtual ~InputBase() {} 85 | 86 | void setTistDelay(const std::chrono::milliseconds& ms) { m_tist_delay = ms; } 87 | void setBufferManagement(BufferManagement bm) { m_bufferManagement = bm; } 88 | BufferManagement getBufferManagement() const { return m_bufferManagement; } 89 | 90 | protected: 91 | InputBase() {} 92 | 93 | std::atomic m_bufferManagement = ATOMIC_VAR_INIT(BufferManagement::Prebuffering); 94 | std::chrono::milliseconds m_tist_delay; 95 | }; 96 | 97 | }; 98 | 99 | -------------------------------------------------------------------------------- /src/mpeg.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty 3 | the Queen in Right of Canada (Communications Research Center Canada) 4 | */ 5 | /* 6 | This file is part of ODR-DabMux. 7 | 8 | ODR-DabMux is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as 10 | published by the Free Software Foundation, either version 3 of the 11 | License, or (at your option) any later version. 12 | 13 | ODR-DabMux is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with ODR-DabMux. If not, see . 20 | */ 21 | 22 | #ifndef _MPEG 23 | #define _MPEG 24 | 25 | #ifdef HAVE_CONFIG_H 26 | # include "config.h" 27 | #endif 28 | 29 | #ifdef _WIN32 30 | # include 31 | # include 32 | # include 33 | 34 | # define ssize_t SSIZE_T 35 | #else 36 | # include 37 | #endif 38 | 39 | #ifdef __cplusplus 40 | extern "C" { 41 | #endif 42 | 43 | typedef struct { 44 | unsigned long sync1:8; 45 | 46 | unsigned long protection:1; 47 | unsigned long layer:2; 48 | unsigned long id:2; 49 | unsigned long sync2:3; 50 | 51 | unsigned long priv:1; 52 | unsigned long padding:1; 53 | unsigned long samplingrate:2; 54 | unsigned long bitrate:4; 55 | 56 | unsigned long emphasis:2; 57 | unsigned long original:1; 58 | unsigned long copyright:1; 59 | unsigned long mode:2; 60 | unsigned long channel:2; 61 | } mpegHeader; 62 | 63 | 64 | extern short getMpegBitrate(void* data); 65 | extern int getMpegFrequency(void* data); 66 | int getMpegFrameLength(mpegHeader* header); 67 | ssize_t readData(int file, void* data, size_t size, unsigned int tries); 68 | 69 | #define MPEG_BUFFER_OVERFLOW -2 70 | #define MPEG_FILE_EMPTY -3 71 | #define MPEG_FILE_ERROR -4 72 | #define MPEG_SYNC_NOT_FOUND -5 73 | #define MPEG_INVALID_FRAME -6 74 | #define MPEG_BUFFER_UNDERFLOW -7 75 | int readMpegHeader(int file, void* data, int size); 76 | int readMpegFrame(int file, void* data, int size); 77 | 78 | #define MPEG_FREQUENCY -2 79 | #define MPEG_PADDING -3 80 | #define MPEG_COPYRIGHT -4 81 | #define MPEG_ORIGINAL -5 82 | #define MPEG_EMPHASIS -6 83 | int checkDabMpegFrame(void* data); 84 | 85 | #ifdef __cplusplus 86 | } 87 | #endif 88 | 89 | #endif // _MPEG 90 | -------------------------------------------------------------------------------- /src/test_statsserver.sh: -------------------------------------------------------------------------------- 1 | clang++ -Wall --include=../config.h StatsServer.cpp TestStatsServer.cpp Log.cpp -lboost_system -lboost_thread -o test && ./test 2 | -------------------------------------------------------------------------------- /src/utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 3 | 2011, 2012 Her Majesty the Queen in Right of Canada (Communications 4 | Research Center Canada) 5 | 6 | Copyright (C) 2025 7 | Matthias P. Braendli, matthias.braendli@mpb.li 8 | 9 | This file contains a set of utility functions that are used to show 10 | useful information to the user, and handles time and date for the 11 | the signalling. 12 | */ 13 | /* 14 | This file is part of ODR-DabMux. 15 | 16 | ODR-DabMux is free software: you can redistribute it and/or modify 17 | it under the terms of the GNU General Public License as 18 | published by the Free Software Foundation, either version 3 of the 19 | License, or (at your option) any later version. 20 | 21 | ODR-DabMux is distributed in the hope that it will be useful, 22 | but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | GNU General Public License for more details. 25 | 26 | You should have received a copy of the GNU General Public License 27 | along with ODR-DabMux. If not, see . 28 | */ 29 | #pragma once 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "MuxElements.h" 36 | 37 | /* Convert a date and time into the modified Julian date 38 | * used in FIG 0/10 39 | * 40 | * Year is four digit format. 41 | * Months are Jan=1, Feb=2, etc. 42 | * First day of the month is 1, as usual. 43 | * 44 | * Returns corresponding MJD 45 | */ 46 | uint32_t gregorian2mjd(int year, int month, int day); 47 | 48 | /* Shows the introductory header on program start */ 49 | void header_message(); 50 | 51 | /* The usage information refers to the command-line 52 | * ensemble definition, and explains how to create 53 | * an ensemble without using a configuration file 54 | */ 55 | void printUsage(char *name, FILE* out = stderr); 56 | 57 | /* This usage information explains how to run the program 58 | * with a configuration file 59 | */ 60 | void printUsageConfigfile(char *name, FILE* out = stderr); 61 | 62 | /* The following four utility functions display a 63 | * description of all outputs, services, components 64 | * resp. subchannels*/ 65 | void printOutputs(const std::vector >& outputs); 66 | 67 | /* Print information about the whole ensemble */ 68 | void printEnsemble(const std::shared_ptr& ensemble); 69 | 70 | void printSubchannels(const vec_sp_subchannel& subchannels); 71 | 72 | unsigned long hexparse(const std::string& input); 73 | 74 | bool stringEndsWith(std::string const &fullString, std::string const &ending); 75 | -------------------------------------------------------------------------------- /src/zmq2farsync/README.md: -------------------------------------------------------------------------------- 1 | Drive a Farsync card from a ZMQ ETI stream 2 | ========================================== 3 | 4 | This *zmq2farsync* tool can receive a ZMQ ETI stream from 5 | ODR-DabMux and drive a Farsync card with it. 6 | -------------------------------------------------------------------------------- /src/zmqinput-keygen.c: -------------------------------------------------------------------------------- 1 | /* Create a key file for the ZMQinput 2 | * and save to file. 3 | * 4 | * Copyright (c) 2014 Matthias P. Braendli 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | 35 | int main(int argc, char** argv) 36 | { 37 | if (argc == 1) { 38 | fprintf(stderr, "Generate a random key for dabInputZMQ and save it to two files.\n\n"); 39 | fprintf(stderr, "Usage: %s \n", argv[0]); 40 | return 1; 41 | } 42 | 43 | const char* keyname = argv[1]; 44 | 45 | if (strlen(keyname) > 2048) { 46 | fprintf(stderr, "name too long\n"); 47 | return 1; 48 | } 49 | 50 | char pubkeyfile[strlen(keyname) + 10]; 51 | char seckeyfile[strlen(keyname) + 10]; 52 | 53 | sprintf(pubkeyfile, "%s.pub", keyname); 54 | sprintf(seckeyfile, "%s.sec", keyname); 55 | 56 | char public_key [41]; 57 | char secret_key [41]; 58 | int rc = zmq_curve_keypair(public_key, secret_key); 59 | if (rc != 0) { 60 | fprintf(stderr, "key generation failed\n"); 61 | return 1; 62 | } 63 | 64 | int fdpub = creat(pubkeyfile, S_IRUSR | S_IWUSR); 65 | if (fdpub < 0) { 66 | perror("File creation failed"); 67 | return 1; 68 | } 69 | 70 | int fdsec = creat(seckeyfile, S_IRUSR | S_IWUSR); 71 | if (fdsec < 0) { 72 | perror("File creation failed"); 73 | return 1; 74 | } 75 | 76 | int r = write(fdpub, public_key, 41); 77 | 78 | int ret = 0; 79 | 80 | if (r < 0) { 81 | perror("write failed"); 82 | ret = 1; 83 | } 84 | else if (r != 41) { 85 | fprintf(stderr, "Not enough key data written to file\n"); 86 | ret = 1; 87 | } 88 | 89 | close(fdpub); 90 | 91 | if (ret == 0) { 92 | r = write(fdsec, secret_key, 41); 93 | 94 | if (r < 0) { 95 | perror("write failed"); 96 | ret = 1; 97 | } 98 | else if (r != 41) { 99 | fprintf(stderr, "Not enough key data written to file\n"); 100 | ret = 1; 101 | } 102 | } 103 | 104 | close(fdsec); 105 | 106 | return ret; 107 | } 108 | 109 | --------------------------------------------------------------------------------