Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
166 commits
Select commit Hold shift + click to select a range
d70bcdf
vis, modespec: Handle VIS codes that use odd parity
sjlongland Dec 9, 2024
5b668ca
modespec, slowrx UI: Add Wraase SC-2 60
sjlongland Dec 9, 2024
868c64a
Makefile: Use $(shell ) so we can see exactly what's being injected.
sjlongland Jul 9, 2024
cc2561b
Makefile: Derive OBJECTS from the list of source files.
sjlongland Jul 9, 2024
c2e2a29
Makefile: Generate dependency files
sjlongland Jul 9, 2024
d090bcc
Makefile: Define the names of all output targets
sjlongland Jul 9, 2024
2015a29
Makefile: Add undeclared dependency
sjlongland Jul 9, 2024
9ced2e5
Makefile: Drop explicit `common.h` dependency
sjlongland Jul 9, 2024
8d7bf13
Makefile: Found another `.ui` file that `gui.c` pulls in
sjlongland Jul 9, 2024
61adb40
common.h: Move gui.c stuff into gui.h
sjlongland Jul 9, 2024
8bcefbb
common.h: Move video.c functions to video.h
sjlongland Jul 9, 2024
3bbef03
.gitignore: Ignore object and dependency files.
sjlongland Jul 9, 2024
99b227d
common.h: Move fsk.c functions to fsk.h
sjlongland Jul 9, 2024
aa3ee13
vis.c: Add missed `gui.h` include
sjlongland Jul 9, 2024
1de8f61
common.h: Move modespec.c definitions to modespec.h
sjlongland Jul 9, 2024
bc717f3
video.c: Add missed `gui.h` requirement
sjlongland Jul 9, 2024
c8da316
common.h: Move pcm.c stuff to pcm.h
sjlongland Jul 9, 2024
4a1ffe4
common.h: Move sync.c definitions to sync.h
sjlongland Jul 9, 2024
550dd5b
common: Move GTK event handlers to gui_events
sjlongland Jul 9, 2024
cfe514c
common.h: Move vis.c stuff to vis.h
sjlongland Jul 9, 2024
238d96e
common: Move GUI objects to the gui module
sjlongland Jul 9, 2024
e6fbe44
common: Move PcmData to pcm
sjlongland Jul 9, 2024
0254fd2
common: Move FFT logic to separate fft module
sjlongland Jul 9, 2024
29a1ebf
slowrx: Move listen thread code to listen module
sjlongland Jul 9, 2024
37982af
common: Move more GUI stuff into the gui module
sjlongland Jul 9, 2024
83b4d7c
common: Move config logic to config module.
sjlongland Jul 9, 2024
69db7f7
slowrx: Move fft initialisation to fft module
sjlongland Jul 9, 2024
00becaa
listen: Move start/stop listener thread logic
sjlongland Jul 9, 2024
3e632d1
common: Move config definitions to config.h
sjlongland Jul 9, 2024
8c1bde3
gui: Merge in gui_events
sjlongland Jul 9, 2024
bb36762
gui: Drop unused ShowWin parameter from setVU
sjlongland Jul 9, 2024
b28e69b
video: Drop unused variables
sjlongland Jul 9, 2024
a531fb6
video: Silence warning from compiler.
sjlongland Jul 9, 2024
a7b2bb8
pcm: Move PCM dropped samples warning to GUI
sjlongland Jul 9, 2024
4f4b832
pcm: Move device list population to the GUI
sjlongland Jul 9, 2024
3b71c6b
pcm: Move PCM error GUI logic to GUI module.
sjlongland Jul 9, 2024
7dd966e
pcm: Replace direct calls into GUI calls with function pointers.
sjlongland Jul 9, 2024
bd397f4
gui: Add routine for setting the status bar text.
sjlongland Jul 9, 2024
c1804ca
common: Define typedefs for these event definitions
sjlongland Jul 9, 2024
f13325d
listen, vis: Replace direct access to status bar with callbacks.
sjlongland Jul 9, 2024
b2d54a9
common: Move CurrentPic to new module
sjlongland Jul 9, 2024
b8fef15
pcm: Replace GTK+ import with specific GLIB imports
sjlongland Jul 9, 2024
0116704
common: Import the minimal headers needed
sjlongland Jul 9, 2024
933859a
config: Replace GTK+ include with GLIB
sjlongland Jul 9, 2024
42279e5
fsk: Replace GTK includes with GLIB
sjlongland Jul 9, 2024
155aa6f
modespec: Clean up includes
sjlongland Jul 9, 2024
51d268c
common.h: Move mode enumerations to modespec
sjlongland Jul 9, 2024
c910e15
sync: Replace GTK includes
sjlongland Jul 9, 2024
75027ff
listener: Replace direct calls into GUI with callback functions.
sjlongland Jul 9, 2024
ee26c08
gui: Make event handlers static
sjlongland Jul 9, 2024
84c429f
common: Drop references to GTK+ libs
sjlongland Jul 9, 2024
15acfd4
common: Drop unused thread1
sjlongland Jul 9, 2024
be865b2
Makefile: Separate out GUI from core functions
sjlongland Jul 9, 2024
12b3312
slowrx: Synchronise FSK-ID and Auto Slant Correct toggles.
sjlongland Jul 9, 2024
e4d0403
Makefile: Move fsk into common lib
sjlongland Jul 9, 2024
32004e8
pic, slowrx: Move thumbbuf to the GUI
sjlongland Jul 9, 2024
4b200f5
Makefile: move pic to the common lib
sjlongland Jul 9, 2024
bb1e55a
vis: Replace direct calls to GUI functions with callbacks
sjlongland Jul 9, 2024
659e2fa
Makefile: move vis to common lib
sjlongland Jul 9, 2024
0f3d530
vis: Replace magic number
sjlongland Jul 9, 2024
edba041
common: Define a call-back for VU updates.
sjlongland Jul 9, 2024
28ee797
vis: Remove unused GTK+ header
sjlongland Jul 9, 2024
79fe56d
video: Convert to callback API
sjlongland Jul 9, 2024
854f472
Makefile: Move final pieces to common lib
sjlongland Jul 9, 2024
942e6a0
vis: Use UpdateVUCallback for VU updates
sjlongland Jul 9, 2024
01c1392
video: tx is the column counter not x
sjlongland Jul 9, 2024
fdf5c1f
video: Use `gushort` for co-ordinates
sjlongland Jul 9, 2024
66be564
video: Hide `VideoImage` buffer
sjlongland Jul 9, 2024
e82b05b
pcm: Fix missing parameter
sjlongland Jul 9, 2024
09c11b3
config: Add required headers for GKeyFile type
sjlongland Jul 9, 2024
36754c2
fsk: Include complex.h for complex numbers
sjlongland Jul 9, 2024
bc5d5ee
vis: Include complex.h for native complex types
sjlongland Jul 9, 2024
7a20379
video: Include complex.h for native complex types
sjlongland Jul 9, 2024
4c50219
pcm: Add ALSA headers
sjlongland Jul 9, 2024
2b5b80a
common: Use standard data types
sjlongland Jul 9, 2024
986d1ed
fsk: Pass through buffer size to prevent overflow
sjlongland Jul 9, 2024
7081a4e
fsk: Replace glib types with stdint
sjlongland Jul 9, 2024
b341aae
fsk: Replace FFTLen variable with #defined constant
sjlongland Jul 9, 2024
8f555d8
.gitignore: Ignore archives
sjlongland Jul 9, 2024
097d82d
vis: Replace glib types, change FFTLen to constant
sjlongland Jul 9, 2024
283b77a
video: Drop glib types, replace unchanged variables with constants
sjlongland Jul 9, 2024
a90d477
sync: Replace glib types with stdint/stdbool
sjlongland Jul 9, 2024
fdbb07f
pic: Replace glib types and clean up
sjlongland Jul 9, 2024
a8ed69c
fsk: Use stdbool `true` and `false`
sjlongland Jul 9, 2024
b983e01
fsk: Missed one glib type
sjlongland Jul 9, 2024
0fee8b3
pcm: Use stdint and stdbool types
sjlongland Jul 9, 2024
1012734
pcm: Drop config.h
sjlongland Jul 9, 2024
e03a270
pcm: Bring in pthread.h for pthread_exit.
sjlongland Jul 9, 2024
4e90a4c
common: Use stdbool singletons
sjlongland Jul 9, 2024
43dd7b1
sync: Use stdbool singletons
sjlongland Jul 9, 2024
423ab2f
vis: Use stdbool singletons
sjlongland Jul 9, 2024
786bb34
video: Clean up glib types and singletons
sjlongland Jul 9, 2024
7ddc0db
modespec: Replace glib types with stdlib
sjlongland Jul 9, 2024
cf878dc
listen: Replace glib types and singletons
sjlongland Jul 9, 2024
7bb42a1
Makefile: Move config to the GUI
sjlongland Jul 9, 2024
4198007
Makefile: Drop direct inclusion of GLIB headers/libs
sjlongland Jul 9, 2024
d8d904e
slowrxd: Add shell for new daemon
sjlongland Jul 9, 2024
735ff12
slowrxd: Implement receive logging
sjlongland Jul 10, 2024
c8aae75
slowrxd: Rename log file after reception
sjlongland Jul 10, 2024
e83f788
slowrxd: Implement writing files using GD
sjlongland Jul 10, 2024
afbd2e0
Makefile: Compile slowrxd with libgd
sjlongland Jul 10, 2024
9bacc77
README.md: Document libgd dependency
sjlongland Jul 10, 2024
c8e1746
pcm: Make wanteddevname a constant
sjlongland Jul 10, 2024
cac3bf8
slowrxd: Add some command-line arguments
sjlongland Jul 10, 2024
a197f9c
slowrxd: Use inttypes.h PRId64 to format int64_t
sjlongland Jul 10, 2024
5e9538f
slowrxd: Add missed directory option
sjlongland Jul 10, 2024
e9ed3ec
slowrxd: Add some newlines to strings
sjlongland Jul 10, 2024
ae1dff1
slowrxd: Suppress FSK if none received
sjlongland Jul 10, 2024
c3c0ef2
slowrxd: Add latest path options, prepend directory if given
sjlongland Jul 10, 2024
ca722ba
slowrxd: Fix handling of line height
sjlongland Jul 10, 2024
13d4a68
slowrxd: Move .ndjson append step
sjlongland Jul 10, 2024
3676744
slowrxd: Use PATH_MAX for path length
sjlongland Jul 11, 2024
ff2e494
slowrxd: Use absolute paths
sjlongland Jul 11, 2024
aaee9e2
slowrxd: Strip full path from symlink target
sjlongland Jul 11, 2024
9023f1a
slowrxd: Add ability to execute script on receive
sjlongland Jul 11, 2024
84967c1
slowrxd: Fix skyrocketing CPU during receive
sjlongland Jul 11, 2024
594abdb
slowrxd: Limit the frequency of script executions during RX
sjlongland Jul 11, 2024
5ab8c0c
slowrxd: Use mutexes around logs to prevent records getting mixed
sjlongland Jul 11, 2024
22538b3
slowrxd: Fix forking logic
sjlongland Jul 11, 2024
a08af7e
pcm: Define constants for the return value
sjlongland Jul 11, 2024
3b52f42
slowrxd: Handle sub-optimal PCM init case
sjlongland Jul 11, 2024
098b84d
pcm: Don't hardcode sample rate to 44100
sjlongland Jul 11, 2024
a23f5fa
slowrxd: Allow changing the sample rate
sjlongland Jul 11, 2024
31ba25b
slowrxd: Document -x option
sjlongland Jul 11, 2024
d64871e
sync: Add missed pcm.h include
sjlongland Jul 11, 2024
22a3622
slowrxd: Add missed break
sjlongland Jul 11, 2024
cf4f21f
slowrxd: Remove redundant `int`
sjlongland Jul 11, 2024
9ed47f1
slowrxd: Remove stray commas
sjlongland Jul 11, 2024
4110b5c
slowrxd: Fix invalid parsing on sample rate
sjlongland Jul 11, 2024
7406e45
slowrxd: Fix detection of current directory
sjlongland Jul 11, 2024
f7c0bf9
vis: Derive number of frames from sample rate
sjlongland Jul 12, 2024
1bf7921
video: Derive 100ms of samples from sample rate
sjlongland Jul 12, 2024
99798f0
fsk: Derive sample counts from sample rate
sjlongland Jul 12, 2024
9e2c53b
fsk: Give up after 5 seconds
sjlongland Jul 12, 2024
d3a9ec1
common.h: Enlarge audio buffer to 5kB
sjlongland Jul 12, 2024
defc466
slowrxd: Clamp sample rate to 48kHz.
sjlongland Jul 12, 2024
d244fa1
slowrxd: Sanitise non-alphanumeric characters in FSK ID
sjlongland Jul 12, 2024
95d8fff
slowrxd: Add some missed \n's
sjlongland Jul 12, 2024
c6cc8be
fft: Declare a constant for the FFT size
sjlongland Jul 12, 2024
e554507
fft: Replace references to 1024 and 2048 magic numbers
sjlongland Jul 12, 2024
44f7a54
video: Make FFT interval a constant
sjlongland Jul 12, 2024
0acccb8
slowrxd: Allow some symlinks to be disabled
sjlongland Jul 12, 2024
fff9314
pcm: Add callback for reception of audio data
sjlongland Jul 12, 2024
bfce8b8
slowrxd: Add audio dump feature
sjlongland Jul 12, 2024
792f04e
slowrxd: Fix copy-paste error
sjlongland Jul 12, 2024
6f8fa1b
slowrxd: SIG_STRENGTH: Omit zero buckets
sjlongland Jul 13, 2024
5d0c6c5
slowrxd: Add missed -a and -A options, tweak option settings
sjlongland Jul 13, 2024
103ada6
pcm: Add channel selection
sjlongland Jul 13, 2024
de50e55
slowrxd: Fix malformed JSON output
sjlongland Jul 13, 2024
27d1145
slowrxd: Fix -h requiring argument
sjlongland Jul 13, 2024
bf8b9de
slowrxd: Indent command line arguments
sjlongland Jul 13, 2024
e365468
slowrxd: If filename given starts with /, assume absolute
sjlongland Jul 13, 2024
7a5a2c1
slowrxd: require in-progress image path be set.
sjlongland Jul 13, 2024
109f754
README.md: Document the daemon
sjlongland Jul 13, 2024
f5784fa
contrib sstv-cam: Add an example SSTV cam script
sjlongland Jul 13, 2024
49b53a3
contrib sstv-cam-script: Update the script
sjlongland Jul 14, 2024
5a64254
contrib sstv-cam-script: Fix broken W3C validator link
sjlongland Jul 14, 2024
1c3afc2
contrib sstv-cam-script: Fix W3C validation errors in output
sjlongland Jul 14, 2024
1227921
contrib sstv-cam-script: Document W3C icons
sjlongland Jul 14, 2024
5001b5e
contrib sstv-cam-script: Further bug fixes and tweaks.
sjlongland Jul 15, 2024
320eb1a
contrib sstv-cam-script: Add zoom features, dynamic location from GPS.
sjlongland Jul 18, 2024
b143303
slowrxd: Use `execv` not `execve`
sjlongland Jul 23, 2024
5f92e49
modespec: Correct video timings for Robot72 mode
sjlongland Nov 21, 2024
2255ce1
video: Calculate channel positions for Robot72
sjlongland Nov 21, 2024
50b438d
gui: Add combo boxes for rate and channel
sjlongland Nov 22, 2024
c94327a
slowrxd: Re-add `-p` option
sjlongland Dec 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
slowrx
slowrxd
rx
rx-lum

*.d
*.o
*.a
71 changes: 60 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,20 +1,69 @@
CC = gcc
CC ?= gcc
AR ?= ar
RANLIB ?= ranlib

CFLAGS = -Wall -Wextra -std=gnu99 -pedantic -g -DGDK_VERSION_MIN_REQUIRED=GDK_VERSION_3_4
GTKCFLAGS = `pkg-config --cflags gtk+-3.0`
GTKLIBS = `pkg-config --libs gtk+-3.0`
CFLAGS = -Wall -Wextra -std=gnu99 -pedantic -g

GTKCFLAGS = $(shell pkg-config --cflags gtk+-3.0)
GTKLIBS = $(shell pkg-config --libs gtk+-3.0)

GDCFLAGS = $(shell pkg-config --cflags gdlib)
GDLIBS = $(shell pkg-config --libs gdlib)

OFLAGS = -O3

OBJECTS = common.o modespec.o gui.o video.o vis.o sync.o pcm.o fsk.o slowrx.o
GUI_BIN = slowrx
DAEMON_BIN = slowrxd
COMMON_LIB = libslowrx.a

TARGETS ?= $(GUI_BIN) $(DAEMON_BIN)

COMMON_CFLAGS = $(CFLAGS) $(OFLAGS)
COMMON_LDFLAGS = -lfftw3 -lasound -lm -lpthread

LIB_SOURCES = common.c fft.c fsk.c listen.c modespec.c sync.c pic.c pcm.c vis.c video.c
LIB_OBJECTS = $(patsubst %.c,%.o,$(LIB_SOURCES))
LIB_DEPENDS = $(patsubst %.c,%.d,$(LIB_SOURCES))
LIB_CFLAGS = $(COMMON_CFLAGS)

GUI_SOURCES = config.c gui.c slowrx.c
GUI_OBJECTS = $(patsubst %.c,%.o,$(GUI_SOURCES))
GUI_DEPENDS = $(patsubst %.c,%.d,$(GUI_SOURCES))
GUI_CFLAGS = $(COMMON_CFLAGS) $(LIB_CFLAGS) $(GTKCFLAGS) -DGDK_VERSION_MIN_REQUIRED=GDK_VERSION_3_4
GUI_LDFLAGS = $(COMMON_LDFLAGS) -lgthread-2.0 $(GTKLIBS)

DAEMON_SOURCES = slowrxd.c
DAEMON_OBJECTS = $(patsubst %.c,%.o,$(DAEMON_SOURCES))
DAEMON_DEPENDS = $(patsubst %.c,%.d,$(DAEMON_SOURCES))
DAEMON_CFLAGS = $(COMMON_CFLAGS) $(LIB_CFLAGS) $(GDCFLAGS)
DAEMON_LDFLAGS = $(COMMON_LDFLAGS) $(GDLIBS)

all: slowrx
OBJECTS = $(GUI_OBJECTS) $(LIB_OBJECTS) $(DAEMON_OBJECTS)
DEPENDS = $(GUI_DEPENDS) $(LIB_DEPENDS) $(DAEMON_DEPENDS)

slowrx: $(OBJECTS)
$(CC) $(CFLAGS) -o $@ $(OBJECTS) $(GTKLIBS) -lfftw3 -lgthread-2.0 -lasound -lm -lpthread
all: $(TARGETS)

%.o: %.c common.h
$(CC) $(CFLAGS) $(GTKCFLAGS) $(OFLAGS) -c -o $@ $<
$(GUI_BIN): $(COMMON_LIB) $(GUI_OBJECTS)
$(CC) $(GUI_CFLAGS) -o $@ -Wl,--as-needed -Wl,--start-group $^ $(GUI_LDFLAGS) -Wl,--end-group

$(DAEMON_BIN): $(COMMON_LIB) $(DAEMON_OBJECTS)
$(CC) $(DAEMON_CFLAGS) -o $@ -Wl,--as-needed -Wl,--start-group $^ $(DAEMON_LDFLAGS) -Wl,--end-group

$(COMMON_LIB): $(LIB_OBJECTS)
$(AR) cr $@ $^
$(RANLIB) $@

%.o: %.c
$(CC) -MM -MF $(*F).d $(OBJ_CFLAGS) $<
$(CC) $(OBJ_CFLAGS) -c -o $@ $<

$(GUI_OBJECTS): OBJ_CFLAGS=$(GUI_CFLAGS)
$(LIB_OBJECTS): OBJ_CFLAGS=$(LIB_CFLAGS)
$(DAEMON_OBJECTS): OBJ_CFLAGS=$(DAEMON_CFLAGS)

clean:
rm -f slowrx $(OBJECTS)
rm -f $(TARGETS) $(COMMON_LIB) $(OBJECTS) $(DEPENDS)

-include $(DEPENDS)

gui.c: aboutdialog.ui slowrx.ui
250 changes: 248 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,269 @@ Features
Requirements
------------

### Common requirements

* Linux
* Alsa (`libasound2-dev`)
* Gtk+ 3.4 (`libgtk-3-dev`)
* FFTW 3 (`libfftw3-dev`)

And, obviously:

* shortwave radio with SSB
* computer with sound card
* computer with sound card capable of at least 6kHz sample rate (>24kHz
strongly recommended)
* means of getting sound from radio to sound card

### For the GUI:

* gtk+ 3.4 (`libgtk-3-dev`)

### For the daemon:

* libgd

Compiling
---------

`make`

### GUI only

```
make slowrx
```

### Daemon only

The daemon is experimental.

```
make slowrxd
```

Running
-------

### GUI

`./slowrx`

### Daemon

`./slowrxd [arguments]`

The daemon runs in the foreground, the intention is to run it beneath a daemon
service like `supervisord` or `systemd`. An example unit file for `systemd`
might be (see the
[`systemd-unit` manpage](https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html)
for correct syntax):

```
[Unit]
Description=slowrxd

[Service]
User=slowrxuser
ExecStart=/path/to/slowrxd [arguments]

[Install]
WantedBy=multi-user.target
```

#### Daemon arguments

These are listed with the `-h` argument:

```
$ ./slowrxd -h
Usage: ./slowrxd [-h] [-F] [-S] [-A inprogress.au]
[-I inprogress.png] [-L inprogress.ndjson] [-a latest.au]
[-c channel] [-d directory] [-i latest.png]
[-l latest.ndjson] [-p pcmdevice] [-r samplerate]
[-x script]

where:
-F : disable FSK ID detection
-S : disable slant correction
-h : display this help and exit
-d : set the directory where images are kept
-A : set the in-progress audio dump path (- to disable)
-I : set the in-progress image path (- to disable)
-L : set the in-progress receive log path (- to disable)
-a : set the latest audio dump path (- to disable)
-c : set the audio channel to use, left, right or mono
-i : set the latest image path (- to disable)
-l : set the latest receive log path (- to disable)
-r : set the ALSA PCM sample rate
-p : set the ALSA PCM capture device
-x : specify a script to run on receive events
```

##### Paths

`-d directory` sets the destination for files to `directory`, the path must
already exist. Default is the current working directory. All output files are
assumed to reside in the same directory (and **must** reside on the same
filesystem volume). As the image is received, it is periodically written to
the _in progress_ image path (see `-I`) as a PNG image.

Alongside this file are two other files (unless disabled):

* `inprogress.ndjson`: a [NDJSON](https://github.com/ndjson/ndjson-spec) log
file storing the events as the file was received.
* `inprogress.au`: a [Sun Audio](https://en.wikipedia.org/wiki/Au_file_format)
audio file containing the recording of the transmission.

`-A`, `-I` and `-L` set the path to the audio dump, image and receive log of
the transmission currently being received. Relative to the output directory
(see `-d`) unless they start with a `/`. `-A` and `-L` may be disabled by
specifying `-` as the path. `-I` may not be disabled.

`-a`, `-i` and `-l`: same as the upper-case counterparts, but these are for the
symbolic link to the _latest_ received image. Again, these are relative to the
output directory unless they start with a `/`. Pass `-` as the argument to
disable the corresponding symbolic link being generated.

(**NOTE** the code that figures out what the _target_ of the symlink is, is
especially dumb and does **NOT** handle the symlink residing in a different
place to the output file.)

When a SSTV image is fully received (after the FSK ID), the file names of the
three (or less) files currently named `inprogress` will be renamed to one of
the following forms:

* `YYYY-mm-ddTHH-MMZ-MODE-FSKID` if the FSK ID was decoded (non-alphanumeric
characters in the FSK ID are replaced with `-`).
* `YYYY-mm-ddTHH-MMZ-MODE` if no FSK ID was detected (or it was disabled).

The "latest" image symbolic links (`-a`, `-i` and `-l`) will then be re-created
to point to these new files.

##### PCM input options

`slowrxd` uses ALSA device names (see `arecord -L`). You can specify a
different PCM capture device with `-p name`. e.g. Pipewire users may want
`-p pipewire` or `-p pulse`.

The sample rate can be adjusted with `-r`. The default is 44100 Hz for
historical reasons, however some users may want to set this to 48000 if they
have hardware that requires it (some modern sound cards do not natively support
44.1kHz) or they are using a userspace subsystem like PulseAudio, PipeWire or
JACK running at this (or any other) sample rate.

Bare minimum sample rate required is 6kHz, and will work but deliver poor
results ([see this Mastodon thread](https://mastodon.longlandclan.id.au/@stuartl/112771433903628425)
for an example of how poor).

`-c` selects which channel is used. By default, the left channel is used, but
if your interface requires it, you may choose the right channel, or have both
summed together (mono). Only the first letter (`l`, `m` or `r`) is used, and
case does not matter.

##### SSTV decoder features

By default, FSK ID detection and slant correction are enabled, you can disable
these with `-F` and `-S` respectively.

##### Running scripts

The daemon can run a script on events. The path to the script must include the
relative or full path to the script if it is not in `${PATH}` and must be
executable by the process running `slowrxd`.

It will be called with 4 arguments:

* the event being triggered (see log file format)
* the path to the image file (either the in-progress or final image)
* the path to the log file for the image
* the path to the audio file for the image

This script **MUST** do its thing then return back to the process as soon as
possible, because it will block the SSTV receiver otherwise!

A recommended solution to this is to write a simple shell script that launches
the real workhorse as a forked process in the background using
[`nohup`](https://en.wikipedia.org/wiki/Nohup):

```bash
#!/bin/sh

nohup $( dirname $( realpath $0 ) )/real-upload.sh "$@" > upload.log 2>&1 &
```

This script can do whatever you want:

* upload the file to a web server for a SSTV cam
* notify another program
* post the image to social media

…etc…

#### The log file format

NDJSON was used since JSON itself is relatively easy to generate from C code,
and this allows for separate JSON "packets" to be logged one per line, to the
file and still maintain valid JSON at all times.

Each line of the NDJSON file is a JSON object storing a log record.

* `timestamp` (required): The timestamp of the event, in milliseconds since
the 1st January 1970 (UTC).
* `type` (required): The type of log record being emitted.
* `msg` (optional): Message text string, if applicable.

Each record type may have its own special parameters.

##### `RECEIVE_START` records

This indicates the start of a transmission. No special log records here.

##### `VIS_DETECT` records

This indicates the VIS header has been detected and decoded.

* `code`: Raw VIS code as an integer
* `mode`: Human+Machine-readable "short" descriptor of the mode. See the
`ShortName` fields in `modespec.c`.
* `desc`: Human-readable description of the mode. See the `Name` field in
`modespec.c`.

##### `SIG_STRENGTH` records

This is the FFT power calculation. Zero-valued FFT buckets before and after
the signal are omitted.

* `win`: The Hann window index being used
* `num`: the number of FFT buckets computed (usually 1024)
* `first`: the FFT bucket number of the first bucket storing non-zero data,
this will correspond to the first element of `fft`.
* `last`: the FFT bucket number of the last bucket storing non-zero data, this
will correspond to the last element of `fft`.
* `fft`: the FFT buckets between `first` and `last` (inclusive).

All omitted buckets may be assumed to contain zeroes (`0.000000`).

##### `IMAGE_REFRESHED` records

These do not actually appear in the log, but instead are used exclusively with
the receive script. This event tells the receive script that the image has
been re-drawn with new image data.

##### `FSK_DETECT` records

Indication that the actual SSTV image has been received in full (and no slant
correction yet applied).

##### `STATUS` records

These indicate the status bar text that would be seen in the GTK+ UI.

##### `FSK_RECEIVED` records

These are emitted if a FSK ID is successfully decoded.

* `id` is the FSK ID decoded.

##### `RECEIVE_END` records

Indicate that reception of this particular image has finished.
Loading